1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  *
21  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
22  */
23 
24 /*
25  * This file implements the export operation for this tool.
26  * The basic flow of the process is to find the soft token,
27  * log into it, find the PKCS#11 objects in the soft token
28  * to be exported matching keys with their certificates, export
29  * them to the PKCS#12 file encrypting them with a file password
30  * if desired, and log out.
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include "common.h"
39 
40 #include <kmfapi.h>
41 
42 static KMF_RETURN
43 pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist,
44 	int numattr, KMF_X509_DER_CERT *cert)
45 {
46 	KMF_RETURN rv = KMF_OK;
47 	uint32_t numcerts = 0;
48 
49 	numcerts = 0;
50 	(void) memset(cert, 0, sizeof (KMF_X509_DER_CERT));
51 
52 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
53 	    &numcerts, sizeof (uint32_t));
54 	numattr++;
55 
56 	rv = kmf_find_cert(kmfhandle, numattr, attrlist);
57 	if (rv != KMF_OK) {
58 		return (rv);
59 	}
60 	if (numcerts == 0) {
61 		cryptoerror(LOG_STDERR,
62 		    gettext("No matching certificates found."));
63 		return (KMF_ERR_CERT_NOT_FOUND);
64 
65 	} else if (numcerts == 1) {
66 		kmf_set_attr_at_index(attrlist, numattr,
67 		    KMF_X509_DER_CERT_ATTR, cert,
68 		    sizeof (KMF_X509_DER_CERT));
69 		numattr++;
70 		rv = kmf_find_cert(kmfhandle, numattr, attrlist);
71 
72 	} else if (numcerts > 1) {
73 		cryptoerror(LOG_STDERR,
74 		    gettext("%d certificates found, refine the "
75 		    "search parameters to eliminate ambiguity\n"),
76 		    numcerts);
77 		return (KMF_ERR_BAD_PARAMETER);
78 	}
79 	return (rv);
80 }
81 
82 static KMF_RETURN
83 pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
84 	char *issuer, char *subject, KMF_BIGINT *serial,
85 	char *infile, char *filename)
86 {
87 	KMF_RETURN rv = KMF_OK;
88 	KMF_X509_DER_CERT kmfcert;
89 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
90 	int numattr = 0;
91 	KMF_ATTRIBUTE attrlist[16];
92 
93 	/* If searching for public objects or certificates, find certs now */
94 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
95 		kmf_set_attr_at_index(attrlist, numattr,
96 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
97 		    sizeof (kstype));
98 		numattr++;
99 
100 		if (issuer != NULL) {
101 			kmf_set_attr_at_index(attrlist, numattr,
102 			    KMF_ISSUER_NAME_ATTR, issuer,
103 			    strlen(issuer));
104 			numattr++;
105 		}
106 
107 		if (subject != NULL) {
108 			kmf_set_attr_at_index(attrlist, numattr,
109 			    KMF_SUBJECT_NAME_ATTR, subject,
110 			    strlen(subject));
111 			numattr++;
112 		}
113 
114 		if (serial != NULL) {
115 			kmf_set_attr_at_index(attrlist, numattr,
116 			    KMF_BIGINT_ATTR, serial,
117 			    sizeof (KMF_BIGINT));
118 			numattr++;
119 		}
120 
121 		if (infile != NULL) {
122 			kmf_set_attr_at_index(attrlist, numattr,
123 			    KMF_CERT_FILENAME_ATTR, infile,
124 			    strlen(infile));
125 			numattr++;
126 		}
127 
128 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
129 		    &kmfcert);
130 		if (rv == KMF_OK) {
131 			kstype = KMF_KEYSTORE_OPENSSL;
132 			numattr = 0;
133 
134 			kmf_set_attr_at_index(attrlist, numattr,
135 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
136 			numattr++;
137 
138 			kmf_set_attr_at_index(attrlist, numattr,
139 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
140 			    sizeof (KMF_DATA));
141 			numattr++;
142 
143 			kmf_set_attr_at_index(attrlist, numattr,
144 			    KMF_CERT_FILENAME_ATTR, filename,
145 			    strlen(filename));
146 			numattr++;
147 
148 			rv = kmf_store_cert(kmfhandle, numattr,
149 			    attrlist);
150 
151 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
152 		}
153 	}
154 	return (rv);
155 }
156 
157 static KMF_RETURN
158 pk_export_pk12_nss(KMF_HANDLE_T kmfhandle,
159 	char *token_spec, char *dir, char *prefix,
160 	char *certlabel, char *issuer, char *subject,
161 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred,
162 	char *filename)
163 {
164 	KMF_RETURN rv = KMF_OK;
165 	KMF_KEYSTORE_TYPE kstype;
166 	KMF_CREDENTIAL p12cred = { NULL, 0};
167 	KMF_ATTRIBUTE attrlist[16];
168 	int numattr = 0;
169 
170 	rv = configure_nss(kmfhandle, dir, prefix);
171 	if (rv != KMF_OK)
172 		return (rv);
173 
174 	if (token_spec == NULL)
175 		token_spec = DEFAULT_NSS_TOKEN;
176 
177 	kstype = KMF_KEYSTORE_NSS;
178 	kmf_set_attr_at_index(attrlist, numattr,
179 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
180 	numattr++;
181 
182 	if (certlabel != NULL) {
183 		kmf_set_attr_at_index(attrlist, numattr,
184 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
185 		numattr++;
186 	}
187 
188 	if (issuer != NULL) {
189 		kmf_set_attr_at_index(attrlist, numattr,
190 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
191 		numattr++;
192 	}
193 
194 	if (subject != NULL) {
195 		kmf_set_attr_at_index(attrlist, numattr,
196 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
197 		numattr++;
198 	}
199 
200 	if (serial != NULL) {
201 		kmf_set_attr_at_index(attrlist, numattr,
202 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
203 		numattr++;
204 	}
205 
206 	if (tokencred != NULL) {
207 		kmf_set_attr_at_index(attrlist, numattr,
208 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
209 		numattr++;
210 	}
211 
212 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
213 	    token_spec, strlen(token_spec));
214 	numattr++;
215 
216 	(void) get_pk12_password(&p12cred);
217 	kmf_set_attr_at_index(attrlist, numattr,
218 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
219 	numattr++;
220 
221 	kmf_set_attr_at_index(attrlist, numattr,
222 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
223 	numattr++;
224 
225 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
226 
227 	if (p12cred.cred)
228 		free(p12cred.cred);
229 
230 	return (rv);
231 }
232 
233 static KMF_RETURN
234 pk_export_pk12_files(KMF_HANDLE_T kmfhandle,
235 	char *certfile, char *keyfile,
236 	char *outfile)
237 {
238 	KMF_RETURN rv;
239 	KMF_KEYSTORE_TYPE kstype;
240 	KMF_CREDENTIAL p12cred = { NULL, 0};
241 	KMF_ATTRIBUTE attrlist[16];
242 	int numattr = 0;
243 
244 	kstype = KMF_KEYSTORE_OPENSSL;
245 	kmf_set_attr_at_index(attrlist, numattr,
246 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
247 	numattr++;
248 
249 	if (certfile != NULL) {
250 		kmf_set_attr_at_index(attrlist, numattr,
251 		    KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile));
252 		numattr++;
253 	}
254 
255 	if (keyfile != NULL) {
256 		kmf_set_attr_at_index(attrlist, numattr,
257 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
258 		numattr++;
259 	}
260 
261 	(void) get_pk12_password(&p12cred);
262 	kmf_set_attr_at_index(attrlist, numattr,
263 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
264 	numattr++;
265 
266 	kmf_set_attr_at_index(attrlist, numattr,
267 	    KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile));
268 	numattr++;
269 
270 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
271 
272 	if (p12cred.cred)
273 		free(p12cred.cred);
274 
275 	return (rv);
276 }
277 
278 static KMF_RETURN
279 pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
280 	int oclass, char *certlabel, char *issuer, char *subject,
281 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir,
282 	char *prefix, char *filename)
283 {
284 	KMF_RETURN rv = KMF_OK;
285 	KMF_X509_DER_CERT kmfcert;
286 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
287 	KMF_ATTRIBUTE attrlist[16];
288 	int numattr = 0;
289 
290 	rv = configure_nss(kmfhandle, dir, prefix);
291 	if (rv != KMF_OK)
292 		return (rv);
293 
294 	/* If searching for public objects or certificates, find certs now */
295 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
296 		kmf_set_attr_at_index(attrlist, numattr,
297 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
298 		    sizeof (kstype));
299 		numattr++;
300 
301 		if (certlabel != NULL) {
302 			kmf_set_attr_at_index(attrlist, numattr,
303 			    KMF_CERT_LABEL_ATTR, certlabel,
304 			    strlen(certlabel));
305 			numattr++;
306 		}
307 
308 		if (issuer != NULL) {
309 			kmf_set_attr_at_index(attrlist, numattr,
310 			    KMF_ISSUER_NAME_ATTR, issuer,
311 			    strlen(issuer));
312 			numattr++;
313 		}
314 
315 		if (subject != NULL) {
316 			kmf_set_attr_at_index(attrlist, numattr,
317 			    KMF_SUBJECT_NAME_ATTR, subject,
318 			    strlen(subject));
319 			numattr++;
320 		}
321 
322 		if (serial != NULL) {
323 			kmf_set_attr_at_index(attrlist, numattr,
324 			    KMF_BIGINT_ATTR, serial,
325 			    sizeof (KMF_BIGINT));
326 			numattr++;
327 		}
328 
329 		if (token_spec != NULL) {
330 			kmf_set_attr_at_index(attrlist, numattr,
331 			    KMF_TOKEN_LABEL_ATTR, token_spec,
332 			    strlen(token_spec));
333 			numattr++;
334 		}
335 
336 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
337 		    &kmfcert);
338 		if (rv == KMF_OK) {
339 			kstype = KMF_KEYSTORE_OPENSSL;
340 			numattr = 0;
341 
342 			kmf_set_attr_at_index(attrlist, numattr,
343 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
344 			numattr++;
345 
346 			kmf_set_attr_at_index(attrlist, numattr,
347 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
348 			    sizeof (KMF_DATA));
349 			numattr++;
350 
351 			kmf_set_attr_at_index(attrlist, numattr,
352 			    KMF_CERT_FILENAME_ATTR, filename,
353 			    strlen(filename));
354 			numattr++;
355 
356 			kmf_set_attr_at_index(attrlist, numattr,
357 			    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
358 			numattr++;
359 
360 			rv = kmf_store_cert(kmfhandle, numattr, attrlist);
361 
362 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
363 		}
364 	}
365 	return (rv);
366 }
367 
368 static KMF_RETURN
369 pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec,
370 	char *certlabel, char *issuer, char *subject,
371 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename)
372 {
373 	KMF_RETURN rv = KMF_OK;
374 	KMF_KEYSTORE_TYPE kstype;
375 	KMF_CREDENTIAL p12cred = { NULL, 0};
376 	KMF_ATTRIBUTE attrlist[16];
377 	int numattr = 0;
378 
379 	rv = select_token(kmfhandle, token_spec, TRUE);
380 	if (rv != KMF_OK) {
381 		return (rv);
382 	}
383 
384 	kstype = KMF_KEYSTORE_PK11TOKEN;
385 	kmf_set_attr_at_index(attrlist, numattr,
386 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
387 	numattr++;
388 
389 	if (certlabel != NULL) {
390 		kmf_set_attr_at_index(attrlist, numattr,
391 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
392 		numattr++;
393 	}
394 
395 	if (issuer != NULL) {
396 		kmf_set_attr_at_index(attrlist, numattr,
397 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
398 		numattr++;
399 	}
400 
401 	if (subject != NULL) {
402 		kmf_set_attr_at_index(attrlist, numattr,
403 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
404 		numattr++;
405 	}
406 
407 	if (serial != NULL) {
408 		kmf_set_attr_at_index(attrlist, numattr,
409 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
410 		numattr++;
411 	}
412 
413 	if (tokencred != NULL) {
414 		kmf_set_attr_at_index(attrlist, numattr,
415 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
416 		numattr++;
417 	}
418 
419 	(void) get_pk12_password(&p12cred);
420 	kmf_set_attr_at_index(attrlist, numattr,
421 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
422 	numattr++;
423 
424 	kmf_set_attr_at_index(attrlist, numattr,
425 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
426 	numattr++;
427 
428 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
429 
430 	if (p12cred.cred)
431 		free(p12cred.cred);
432 
433 	return (rv);
434 }
435 
436 static KMF_RETURN
437 pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token,
438 	KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format,
439 	char *label, char *filename, int oclass)
440 {
441 	KMF_RETURN rv = KMF_OK;
442 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
443 	KMF_KEY_CLASS kclass = KMF_KEYCLASS_NONE;
444 	int numattr = 0;
445 	uint32_t numkeys = 1;
446 	KMF_ATTRIBUTE attrlist[16];
447 	KMF_KEY_HANDLE key;
448 	boolean_t is_token = B_TRUE;
449 
450 	if (EMPTYSTRING(label)) {
451 		cryptoerror(LOG_STDERR, gettext("A label "
452 		    "must be specified to export a key."));
453 		return (KMF_ERR_BAD_PARAMETER);
454 	}
455 
456 	rv = select_token(kmfhandle, token, TRUE);
457 	if (rv != KMF_OK) {
458 		return (rv);
459 	}
460 
461 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
462 	    &kstype, sizeof (kstype));
463 	numattr++;
464 
465 	if (cred != NULL) {
466 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
467 		    cred, sizeof (KMF_CREDENTIAL));
468 		numattr++;
469 	}
470 
471 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
472 	    label, strlen(label));
473 	numattr++;
474 
475 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
476 	    &numkeys, sizeof (numkeys));
477 	numattr++;
478 
479 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
480 	    &key, sizeof (key));
481 	numattr++;
482 
483 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
484 	    &is_token, sizeof (is_token));
485 	numattr++;
486 
487 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
488 	    &format, sizeof (format));
489 	numattr++;
490 
491 	/* Check to see if we are exporting private or public only */
492 	if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ)
493 		kclass = KMF_ASYM_PRI;
494 	else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ)
495 		kclass = KMF_ASYM_PUB;
496 	else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ)
497 		kclass = KMF_SYMMETRIC;
498 	else /* only 1 key at a time can be exported here, so default to pri */
499 		kclass = KMF_ASYM_PRI;
500 
501 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
502 	    &kclass, sizeof (kclass));
503 	numattr++;
504 
505 	rv = kmf_find_key(kmfhandle, numattr, attrlist);
506 	/*
507 	 * If nothing found but caller wanted ALL keys, try symmetric
508 	 * this time.
509 	 */
510 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
511 		kclass = KMF_SYMMETRIC;
512 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
513 	}
514 	/*
515 	 * If nothing found but caller wanted ALL keys, try asymmetric
516 	 * public this time.
517 	 */
518 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
519 		kclass = KMF_ASYM_PUB;
520 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
521 	}
522 	if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) {
523 		KMF_RAW_SYM_KEY rkey;
524 
525 		(void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY));
526 		rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey);
527 		if (rv == KMF_OK) {
528 			int fd, n, total = 0;
529 
530 			fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600);
531 			if (fd == -1) {
532 				rv = KMF_ERR_OPEN_FILE;
533 				goto done;
534 			}
535 			do {
536 				n = write(fd, rkey.keydata.val + total,
537 				    rkey.keydata.len - total);
538 				if (n < 0) {
539 					if (errno == EINTR)
540 						continue;
541 					(void) close(fd);
542 					rv = KMF_ERR_WRITE_FILE;
543 					goto done;
544 				}
545 				total += n;
546 
547 			} while (total < rkey.keydata.len);
548 			(void) close(fd);
549 		}
550 done:
551 		kmf_free_bigint(&rkey.keydata);
552 		kmf_free_kmf_key(kmfhandle, &key);
553 	} else if (rv == KMF_OK) {
554 		KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL;
555 		(void) printf(gettext("Found %d asymmetric keys\n"), numkeys);
556 
557 		numattr = 0;
558 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
559 		    &sslks, sizeof (sslks));
560 		numattr++;
561 
562 		kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR,
563 		    key.keyp, sizeof (KMF_RAW_KEY_DATA));
564 		numattr++;
565 
566 		kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
567 		    &format, sizeof (format));
568 		numattr++;
569 
570 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
571 		    filename, strlen(filename));
572 		numattr++;
573 
574 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
575 		    &key.keyclass, sizeof (KMF_KEY_CLASS));
576 		numattr++;
577 
578 		rv = kmf_store_key(kmfhandle, numattr, attrlist);
579 		kmf_free_kmf_key(kmfhandle, &key);
580 	}
581 
582 	return (rv);
583 }
584 
585 static KMF_RETURN
586 pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
587 	KMF_CREDENTIAL *cred, char *certlabel, char *issuer, char *subject,
588 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt,
589 	char *filename)
590 {
591 	KMF_RETURN rv = KMF_OK;
592 	KMF_X509_DER_CERT kmfcert;
593 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
594 	int numattr = 0;
595 	KMF_ATTRIBUTE attrlist[16];
596 
597 	rv = select_token(kmfhandle, token_spec, TRUE);
598 
599 	if (rv != KMF_OK)
600 		return (rv);
601 
602 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
603 	    &kstype, sizeof (kstype));
604 	numattr++;
605 
606 	if (cred != NULL) {
607 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
608 		    cred, sizeof (KMF_CREDENTIAL));
609 		numattr++;
610 	}
611 	if (certlabel != NULL) {
612 		kmf_set_attr_at_index(attrlist, numattr,
613 		    KMF_CERT_LABEL_ATTR, certlabel,
614 		    strlen(certlabel));
615 		numattr++;
616 	}
617 
618 	if (issuer != NULL) {
619 		kmf_set_attr_at_index(attrlist, numattr,
620 		    KMF_ISSUER_NAME_ATTR, issuer,
621 		    strlen(issuer));
622 		numattr++;
623 	}
624 
625 	if (subject != NULL) {
626 		kmf_set_attr_at_index(attrlist, numattr,
627 		    KMF_SUBJECT_NAME_ATTR, subject,
628 		    strlen(subject));
629 		numattr++;
630 	}
631 
632 	if (serial != NULL) {
633 		kmf_set_attr_at_index(attrlist, numattr,
634 		    KMF_BIGINT_ATTR, serial,
635 		    sizeof (KMF_BIGINT));
636 		numattr++;
637 	}
638 
639 	rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert);
640 
641 	if (rv == KMF_OK) {
642 		kstype = KMF_KEYSTORE_OPENSSL;
643 		numattr = 0;
644 
645 		kmf_set_attr_at_index(attrlist, numattr,
646 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
647 		numattr++;
648 
649 		kmf_set_attr_at_index(attrlist, numattr,
650 		    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
651 		    sizeof (KMF_DATA));
652 		numattr++;
653 
654 		kmf_set_attr_at_index(attrlist, numattr,
655 		    KMF_CERT_FILENAME_ATTR, filename, strlen(filename));
656 		numattr++;
657 
658 		kmf_set_attr_at_index(attrlist, numattr,
659 		    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
660 		numattr++;
661 
662 		rv = kmf_store_cert(kmfhandle, numattr, attrlist);
663 
664 		kmf_free_kmf_cert(kmfhandle, &kmfcert);
665 	}
666 	return (rv);
667 }
668 
669 /*
670  * Export objects from one keystore to a file.
671  */
672 int
673 pk_export(int argc, char *argv[])
674 {
675 	int		opt;
676 	extern int	optind_av;
677 	extern char	*optarg_av;
678 	char		*token_spec = NULL;
679 	char		*filename = NULL;
680 	char		*dir = NULL;
681 	char		*prefix = NULL;
682 	char		*certlabel = NULL;
683 	char		*subject = NULL;
684 	char		*issuer = NULL;
685 	char		*infile = NULL;
686 	char		*keyfile = NULL;
687 	char		*certfile = NULL;
688 	char		*serstr = NULL;
689 	KMF_KEYSTORE_TYPE	kstype = 0;
690 	KMF_ENCODE_FORMAT	kfmt = KMF_FORMAT_PKCS12;
691 	KMF_RETURN		rv = KMF_OK;
692 	int		oclass = PK_CERT_OBJ;
693 	KMF_BIGINT	serial = { NULL, 0 };
694 	KMF_HANDLE_T	kmfhandle = NULL;
695 	KMF_CREDENTIAL	tokencred = {NULL, 0};
696 
697 	/* Parse command line options.  Do NOT i18n/l10n. */
698 	while ((opt = getopt_av(argc, argv,
699 	    "k:(keystore)y:(objtype)T:(token)"
700 	    "d:(dir)p:(prefix)"
701 	    "l:(label)n:(nickname)s:(subject)"
702 	    "i:(issuer)S:(serial)"
703 	    "K:(keyfile)c:(certfile)"
704 	    "F:(outformat)"
705 	    "I:(infile)o:(outfile)")) != EOF) {
706 		if (EMPTYSTRING(optarg_av))
707 			return (PK_ERR_USAGE);
708 		switch (opt) {
709 		case 'k':
710 			kstype = KS2Int(optarg_av);
711 			if (kstype == 0)
712 				return (PK_ERR_USAGE);
713 			break;
714 		case 'y':
715 			oclass = OT2Int(optarg_av);
716 			if (oclass == -1)
717 				return (PK_ERR_USAGE);
718 			break;
719 		case 'T':	/* token specifier */
720 			if (token_spec)
721 				return (PK_ERR_USAGE);
722 			token_spec = optarg_av;
723 			break;
724 		case 'd':
725 			if (dir)
726 				return (PK_ERR_USAGE);
727 			dir = optarg_av;
728 			break;
729 		case 'p':
730 			if (prefix)
731 				return (PK_ERR_USAGE);
732 			prefix = optarg_av;
733 			break;
734 		case 'n':
735 		case 'l':
736 			if (certlabel)
737 				return (PK_ERR_USAGE);
738 			certlabel = optarg_av;
739 			break;
740 		case 's':
741 			if (subject)
742 				return (PK_ERR_USAGE);
743 			subject = optarg_av;
744 			break;
745 		case 'i':
746 			if (issuer)
747 				return (PK_ERR_USAGE);
748 			issuer = optarg_av;
749 			break;
750 		case 'S':
751 			serstr = optarg_av;
752 			break;
753 		case 'F':
754 			kfmt = Str2Format(optarg_av);
755 			if (kfmt == KMF_FORMAT_UNDEF)
756 				return (PK_ERR_USAGE);
757 			break;
758 		case 'I':	/* output file name */
759 			if (infile)
760 				return (PK_ERR_USAGE);
761 			infile = optarg_av;
762 			break;
763 		case 'o':	/* output file name */
764 			if (filename)
765 				return (PK_ERR_USAGE);
766 			filename = optarg_av;
767 			break;
768 		case 'c':	/* input cert file name */
769 			if (certfile)
770 				return (PK_ERR_USAGE);
771 			certfile = optarg_av;
772 			break;
773 		case 'K':	/* input key file name */
774 			if (keyfile)
775 				return (PK_ERR_USAGE);
776 			keyfile = optarg_av;
777 			break;
778 		default:
779 			return (PK_ERR_USAGE);
780 			break;
781 		}
782 	}
783 
784 	/* Assume keystore = PKCS#11 if not specified */
785 	if (kstype == 0)
786 		kstype = KMF_KEYSTORE_PK11TOKEN;
787 
788 	/* Filename arg is required. */
789 	if (EMPTYSTRING(filename)) {
790 		cryptoerror(LOG_STDERR, gettext("You must specify "
791 		    "an 'outfile' parameter when exporting.\n"));
792 		return (PK_ERR_USAGE);
793 	}
794 
795 	/* No additional args allowed. */
796 	argc -= optind_av;
797 	argv += optind_av;
798 	if (argc)
799 		return (PK_ERR_USAGE);
800 
801 	DIR_OPTION_CHECK(kstype, dir);
802 
803 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
804 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
805 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
806 
807 		(void) fprintf(stderr, gettext("The objtype parameter "
808 		    "is only relevant if keystore=pkcs11\n"));
809 		return (PK_ERR_USAGE);
810 	}
811 
812 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
813 		token_spec = PK_DEFAULT_PK11TOKEN;
814 	else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
815 		token_spec = DEFAULT_NSS_TOKEN;
816 
817 	if (kstype == KMF_KEYSTORE_OPENSSL) {
818 		if (kfmt != KMF_FORMAT_PKCS12) {
819 			cryptoerror(LOG_STDERR, gettext("PKCS12 "
820 			    "is the only export format "
821 			    "supported for the 'file' "
822 			    "keystore.\n"));
823 			return (PK_ERR_USAGE);
824 		}
825 		if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
826 			cryptoerror(LOG_STDERR, gettext("A cert file"
827 			    "and a key file must be specified "
828 			    "when exporting to PKCS12 from the "
829 			    "'file' keystore.\n"));
830 			return (PK_ERR_USAGE);
831 		}
832 	}
833 
834 	/* Check if the file exists */
835 	if (verify_file(filename) != KMF_OK) {
836 		cryptoerror(LOG_STDERR,
837 		    gettext("Warning: file \"%s\" exists, "
838 		    "will be overwritten."), filename);
839 		if (yesno(gettext("Continue with export? "),
840 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
841 			return (0);
842 		} else {
843 			/* remove the file */
844 			(void) unlink(filename);
845 		}
846 	}
847 
848 	if (serstr != NULL) {
849 		uchar_t *bytes = NULL;
850 		size_t bytelen;
851 
852 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
853 		if (rv != KMF_OK || bytes == NULL) {
854 			(void) fprintf(stderr, gettext("serial number "
855 			    "must be specified as a hex number "
856 			    "(ex: 0x0102030405ffeeddee)\n"));
857 			return (PK_ERR_USAGE);
858 		}
859 		serial.val = bytes;
860 		serial.len = bytelen;
861 	}
862 
863 	/*
864 	 * We need a password in the following situations:
865 	 * 1.  When accessing PKCS11 token
866 	 * 2.  If NSS keystore, when making a PKCS12 file or when
867 	 * accessing any private object or key.
868 	 */
869 	if (kstype == KMF_KEYSTORE_PK11TOKEN ||
870 	    ((kstype == KMF_KEYSTORE_NSS) &&
871 	    ((oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ)) ||
872 	    (kfmt == KMF_FORMAT_PKCS12)))) {
873 			(void) get_token_password(kstype, token_spec,
874 			    &tokencred);
875 	}
876 
877 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
878 		cryptoerror(LOG_STDERR, gettext("Error initializing "
879 		    "KMF: 0x%02x\n"), rv);
880 		return (rv);
881 	}
882 
883 	switch (kstype) {
884 		case KMF_KEYSTORE_PK11TOKEN:
885 			if (kfmt == KMF_FORMAT_PKCS12)
886 				rv = pk_export_pk12_pk11(kmfhandle,
887 				    token_spec, certlabel,
888 				    issuer, subject,
889 				    &serial, &tokencred,
890 				    filename);
891 			else if ((oclass & PK_KEY_OBJ) ||
892 			    kfmt == KMF_FORMAT_RAWKEY)
893 				rv = pk_export_pk11_keys(kmfhandle,
894 				    token_spec, &tokencred, kfmt,
895 				    certlabel, filename, oclass);
896 			else
897 				rv = pk_export_pk11_objects(kmfhandle,
898 				    token_spec, &tokencred, certlabel,
899 				    issuer, subject, &serial, kfmt,
900 				    filename);
901 			break;
902 		case KMF_KEYSTORE_NSS:
903 			if (dir == NULL)
904 				dir = PK_DEFAULT_DIRECTORY;
905 			if (kfmt == KMF_FORMAT_PKCS12)
906 				rv = pk_export_pk12_nss(kmfhandle,
907 				    token_spec, dir, prefix,
908 				    certlabel, issuer,
909 				    subject, &serial,
910 				    &tokencred, filename);
911 			else
912 				rv = pk_export_nss_objects(kmfhandle,
913 				    token_spec,
914 				    oclass, certlabel, issuer, subject,
915 				    &serial, kfmt, dir, prefix, filename);
916 			break;
917 		case KMF_KEYSTORE_OPENSSL:
918 			if (kfmt == KMF_FORMAT_PKCS12)
919 				rv = pk_export_pk12_files(kmfhandle,
920 				    certfile, keyfile, filename);
921 			else
922 				rv = pk_export_file_objects(kmfhandle, oclass,
923 				    issuer, subject, &serial,
924 				    infile, filename);
925 			break;
926 		default:
927 			rv = PK_ERR_USAGE;
928 			break;
929 	}
930 
931 	if (rv != KMF_OK) {
932 		display_error(kmfhandle, rv,
933 		    gettext("Error exporting objects"));
934 	}
935 
936 	if (serial.val != NULL)
937 		free(serial.val);
938 
939 	(void) kmf_finalize(kmfhandle);
940 
941 	return (rv);
942 }
943