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