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 2008 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 *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 (infile != NULL) {
126 			kmf_set_attr_at_index(attrlist, numattr,
127 			    KMF_CERT_FILENAME_ATTR, infile,
128 			    strlen(infile));
129 			numattr++;
130 		}
131 
132 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
133 		    &kmfcert);
134 		if (rv == KMF_OK) {
135 			kstype = KMF_KEYSTORE_OPENSSL;
136 			numattr = 0;
137 
138 			kmf_set_attr_at_index(attrlist, numattr,
139 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
140 			numattr++;
141 
142 			kmf_set_attr_at_index(attrlist, numattr,
143 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
144 			    sizeof (KMF_DATA));
145 			numattr++;
146 
147 			kmf_set_attr_at_index(attrlist, numattr,
148 			    KMF_CERT_FILENAME_ATTR, filename,
149 			    strlen(filename));
150 			numattr++;
151 
152 			rv = kmf_store_cert(kmfhandle, numattr,
153 			    attrlist);
154 
155 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
156 		}
157 	}
158 	return (rv);
159 }
160 
161 static KMF_RETURN
162 pk_export_pk12_nss(KMF_HANDLE_T kmfhandle,
163 	char *token_spec, char *dir, char *prefix,
164 	char *certlabel, char *issuer, char *subject,
165 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred,
166 	char *filename)
167 {
168 	KMF_RETURN rv = KMF_OK;
169 	KMF_KEYSTORE_TYPE kstype;
170 	KMF_CREDENTIAL p12cred = { NULL, 0};
171 	KMF_ATTRIBUTE attrlist[16];
172 	int numattr = 0;
173 
174 	rv = configure_nss(kmfhandle, dir, prefix);
175 	if (rv != KMF_OK)
176 		return (rv);
177 
178 	if (token_spec == NULL)
179 		token_spec = DEFAULT_NSS_TOKEN;
180 
181 	kstype = KMF_KEYSTORE_NSS;
182 	kmf_set_attr_at_index(attrlist, numattr,
183 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
184 	numattr++;
185 
186 	if (certlabel != NULL) {
187 		kmf_set_attr_at_index(attrlist, numattr,
188 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
189 		numattr++;
190 	}
191 
192 	if (issuer != NULL) {
193 		kmf_set_attr_at_index(attrlist, numattr,
194 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
195 		numattr++;
196 	}
197 
198 	if (subject != NULL) {
199 		kmf_set_attr_at_index(attrlist, numattr,
200 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
201 		numattr++;
202 	}
203 
204 	if (serial != NULL) {
205 		kmf_set_attr_at_index(attrlist, numattr,
206 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
207 		numattr++;
208 	}
209 
210 	if (tokencred != NULL) {
211 		kmf_set_attr_at_index(attrlist, numattr,
212 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
213 		numattr++;
214 	}
215 
216 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
217 	    token_spec, strlen(token_spec));
218 	numattr++;
219 
220 	(void) get_pk12_password(&p12cred);
221 	kmf_set_attr_at_index(attrlist, numattr,
222 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
223 	numattr++;
224 
225 	kmf_set_attr_at_index(attrlist, numattr,
226 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
227 	numattr++;
228 
229 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
230 
231 	if (p12cred.cred)
232 		free(p12cred.cred);
233 
234 	return (rv);
235 }
236 
237 static KMF_RETURN
238 pk_export_pk12_files(KMF_HANDLE_T kmfhandle,
239 	char *certfile, char *keyfile,
240 	char *outfile)
241 {
242 	KMF_RETURN rv;
243 	KMF_KEYSTORE_TYPE kstype;
244 	KMF_CREDENTIAL p12cred = { NULL, 0};
245 	KMF_ATTRIBUTE attrlist[16];
246 	int numattr = 0;
247 
248 	kstype = KMF_KEYSTORE_OPENSSL;
249 	kmf_set_attr_at_index(attrlist, numattr,
250 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
251 	numattr++;
252 
253 	if (certfile != NULL) {
254 		kmf_set_attr_at_index(attrlist, numattr,
255 		    KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile));
256 		numattr++;
257 	}
258 
259 	if (keyfile != NULL) {
260 		kmf_set_attr_at_index(attrlist, numattr,
261 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
262 		numattr++;
263 	}
264 
265 	(void) get_pk12_password(&p12cred);
266 	kmf_set_attr_at_index(attrlist, numattr,
267 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
268 	numattr++;
269 
270 	kmf_set_attr_at_index(attrlist, numattr,
271 	    KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile));
272 	numattr++;
273 
274 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
275 
276 	if (p12cred.cred)
277 		free(p12cred.cred);
278 
279 	return (rv);
280 }
281 
282 static KMF_RETURN
283 pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
284 	int oclass, char *certlabel, char *issuer, char *subject,
285 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir,
286 	char *prefix, char *filename)
287 {
288 	KMF_RETURN rv = KMF_OK;
289 	KMF_X509_DER_CERT kmfcert;
290 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
291 	KMF_ATTRIBUTE attrlist[16];
292 	int numattr = 0;
293 
294 	rv = configure_nss(kmfhandle, dir, prefix);
295 	if (rv != KMF_OK)
296 		return (rv);
297 
298 	/* If searching for public objects or certificates, find certs now */
299 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
300 		kmf_set_attr_at_index(attrlist, numattr,
301 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
302 		    sizeof (kstype));
303 		numattr++;
304 
305 		if (certlabel != NULL) {
306 			kmf_set_attr_at_index(attrlist, numattr,
307 			    KMF_CERT_LABEL_ATTR, certlabel,
308 			    strlen(certlabel));
309 			numattr++;
310 		}
311 
312 		if (issuer != NULL) {
313 			kmf_set_attr_at_index(attrlist, numattr,
314 			    KMF_ISSUER_NAME_ATTR, issuer,
315 			    strlen(issuer));
316 			numattr++;
317 		}
318 
319 		if (subject != NULL) {
320 			kmf_set_attr_at_index(attrlist, numattr,
321 			    KMF_SUBJECT_NAME_ATTR, subject,
322 			    strlen(subject));
323 			numattr++;
324 		}
325 
326 		if (serial != NULL) {
327 			kmf_set_attr_at_index(attrlist, numattr,
328 			    KMF_BIGINT_ATTR, serial,
329 			    sizeof (KMF_BIGINT));
330 			numattr++;
331 		}
332 
333 		if (token_spec != NULL) {
334 			kmf_set_attr_at_index(attrlist, numattr,
335 			    KMF_TOKEN_LABEL_ATTR, token_spec,
336 			    strlen(token_spec));
337 			numattr++;
338 		}
339 
340 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
341 		    &kmfcert);
342 		if (rv == KMF_OK) {
343 			kstype = KMF_KEYSTORE_OPENSSL;
344 			numattr = 0;
345 
346 			kmf_set_attr_at_index(attrlist, numattr,
347 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
348 			numattr++;
349 
350 			kmf_set_attr_at_index(attrlist, numattr,
351 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
352 			    sizeof (KMF_DATA));
353 			numattr++;
354 
355 			kmf_set_attr_at_index(attrlist, numattr,
356 			    KMF_CERT_FILENAME_ATTR, filename,
357 			    strlen(filename));
358 			numattr++;
359 
360 			kmf_set_attr_at_index(attrlist, numattr,
361 			    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
362 			numattr++;
363 
364 			rv = kmf_store_cert(kmfhandle, numattr, attrlist);
365 
366 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
367 		}
368 	}
369 	return (rv);
370 }
371 
372 static KMF_RETURN
373 pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec,
374 	char *certlabel, char *issuer, char *subject,
375 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename)
376 {
377 	KMF_RETURN rv = KMF_OK;
378 	KMF_KEYSTORE_TYPE kstype;
379 	KMF_CREDENTIAL p12cred = { NULL, 0};
380 	KMF_ATTRIBUTE attrlist[16];
381 	int numattr = 0;
382 
383 	rv = select_token(kmfhandle, token_spec, TRUE);
384 	if (rv != KMF_OK) {
385 		return (rv);
386 	}
387 
388 	kstype = KMF_KEYSTORE_PK11TOKEN;
389 	kmf_set_attr_at_index(attrlist, numattr,
390 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
391 	numattr++;
392 
393 	if (certlabel != NULL) {
394 		kmf_set_attr_at_index(attrlist, numattr,
395 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
396 		numattr++;
397 	}
398 
399 	if (issuer != NULL) {
400 		kmf_set_attr_at_index(attrlist, numattr,
401 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
402 		numattr++;
403 	}
404 
405 	if (subject != NULL) {
406 		kmf_set_attr_at_index(attrlist, numattr,
407 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
408 		numattr++;
409 	}
410 
411 	if (serial != NULL) {
412 		kmf_set_attr_at_index(attrlist, numattr,
413 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
414 		numattr++;
415 	}
416 
417 	if (tokencred != NULL) {
418 		kmf_set_attr_at_index(attrlist, numattr,
419 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
420 		numattr++;
421 	}
422 
423 	(void) get_pk12_password(&p12cred);
424 	kmf_set_attr_at_index(attrlist, numattr,
425 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
426 	numattr++;
427 
428 	kmf_set_attr_at_index(attrlist, numattr,
429 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
430 	numattr++;
431 
432 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
433 
434 	if (p12cred.cred)
435 		free(p12cred.cred);
436 
437 	return (rv);
438 }
439 
440 static KMF_RETURN
441 pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token,
442 	KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format,
443 	char *label, char *filename, int oclass)
444 {
445 	KMF_RETURN rv = KMF_OK;
446 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
447 	KMF_KEY_CLASS kclass = KMF_KEYCLASS_NONE;
448 	int numattr = 0;
449 	uint32_t numkeys = 1;
450 	KMF_ATTRIBUTE attrlist[16];
451 	KMF_KEY_HANDLE key;
452 	boolean_t is_token = B_TRUE;
453 
454 	if (EMPTYSTRING(label)) {
455 		cryptoerror(LOG_STDERR, gettext("A label "
456 		    "must be specified to export a key."));
457 		return (KMF_ERR_BAD_PARAMETER);
458 	}
459 
460 	rv = select_token(kmfhandle, token, TRUE);
461 	if (rv != KMF_OK) {
462 		return (rv);
463 	}
464 
465 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
466 	    &kstype, sizeof (kstype));
467 	numattr++;
468 
469 	if (cred != NULL) {
470 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
471 		    cred, sizeof (KMF_CREDENTIAL));
472 		numattr++;
473 	}
474 
475 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
476 	    label, strlen(label));
477 	numattr++;
478 
479 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
480 	    &numkeys, sizeof (numkeys));
481 	numattr++;
482 
483 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
484 	    &key, sizeof (key));
485 	numattr++;
486 
487 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
488 	    &is_token, sizeof (is_token));
489 	numattr++;
490 
491 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
492 	    &format, sizeof (format));
493 	numattr++;
494 
495 	/* Check to see if we are exporting private or public only */
496 	if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ)
497 		kclass = KMF_ASYM_PRI;
498 	else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ)
499 		kclass = KMF_ASYM_PUB;
500 	else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ)
501 		kclass = KMF_SYMMETRIC;
502 	else /* only 1 key at a time can be exported here, so default to pri */
503 		kclass = KMF_ASYM_PRI;
504 
505 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
506 	    &kclass, sizeof (kclass));
507 	numattr++;
508 
509 	rv = kmf_find_key(kmfhandle, numattr, attrlist);
510 	/*
511 	 * If nothing found but caller wanted ALL keys, try symmetric
512 	 * this time.
513 	 */
514 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
515 		kclass = KMF_SYMMETRIC;
516 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
517 	}
518 	/*
519 	 * If nothing found but caller wanted ALL keys, try asymmetric
520 	 * public this time.
521 	 */
522 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
523 		kclass = KMF_ASYM_PUB;
524 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
525 	}
526 	if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) {
527 		KMF_RAW_SYM_KEY rkey;
528 
529 		(void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY));
530 		rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey);
531 		if (rv == KMF_OK) {
532 			int fd, n, total = 0;
533 
534 			fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600);
535 			if (fd == -1) {
536 				rv = KMF_ERR_OPEN_FILE;
537 				goto done;
538 			}
539 			do {
540 				n = write(fd, rkey.keydata.val + total,
541 				    rkey.keydata.len - total);
542 				if (n < 0) {
543 					if (errno == EINTR)
544 						continue;
545 					(void) close(fd);
546 					rv = KMF_ERR_WRITE_FILE;
547 					goto done;
548 				}
549 				total += n;
550 
551 			} while (total < rkey.keydata.len);
552 			(void) close(fd);
553 		}
554 done:
555 		kmf_free_bigint(&rkey.keydata);
556 		kmf_free_kmf_key(kmfhandle, &key);
557 	} else if (rv == KMF_OK) {
558 		KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL;
559 		(void) printf(gettext("Found %d asymmetric keys\n"), numkeys);
560 
561 		numattr = 0;
562 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
563 		    &sslks, sizeof (sslks));
564 		numattr++;
565 
566 		kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR,
567 		    key.keyp, sizeof (KMF_RAW_KEY_DATA));
568 		numattr++;
569 
570 		kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
571 		    &format, sizeof (format));
572 		numattr++;
573 
574 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
575 		    filename, strlen(filename));
576 		numattr++;
577 
578 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
579 		    &key.keyclass, sizeof (KMF_KEY_CLASS));
580 		numattr++;
581 
582 		rv = kmf_store_key(kmfhandle, numattr, attrlist);
583 		kmf_free_kmf_key(kmfhandle, &key);
584 	}
585 
586 	return (rv);
587 }
588 
589 static KMF_RETURN
590 pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
591 	char *certlabel, char *issuer, char *subject,
592 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt,
593 	char *filename)
594 {
595 	KMF_RETURN rv = KMF_OK;
596 	KMF_X509_DER_CERT kmfcert;
597 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
598 	int numattr = 0;
599 	KMF_ATTRIBUTE attrlist[16];
600 
601 	rv = select_token(kmfhandle, token_spec, TRUE);
602 
603 	if (rv != KMF_OK) {
604 		return (rv);
605 	}
606 
607 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
608 	    &kstype, sizeof (kstype));
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 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
802 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
803 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
804 
805 		(void) fprintf(stderr, gettext("The objtype parameter "
806 		    "is only relevant if keystore=pkcs11\n"));
807 		return (PK_ERR_USAGE);
808 	}
809 
810 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
811 		token_spec = PK_DEFAULT_PK11TOKEN;
812 	else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
813 		token_spec = DEFAULT_NSS_TOKEN;
814 
815 	if (kstype == KMF_KEYSTORE_OPENSSL) {
816 		if (kfmt != KMF_FORMAT_PKCS12) {
817 			cryptoerror(LOG_STDERR, gettext("PKCS12 "
818 			    "is the only export format "
819 			    "supported for the 'file' "
820 			    "keystore.\n"));
821 			return (PK_ERR_USAGE);
822 		}
823 		if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
824 			cryptoerror(LOG_STDERR, gettext("A cert file"
825 			    "and a key file must be specified "
826 			    "when exporting to PKCS12 from the "
827 			    "'file' keystore.\n"));
828 			return (PK_ERR_USAGE);
829 		}
830 	}
831 
832 	/* Check if the file exists and might be overwritten. */
833 	if (access(filename, F_OK) == 0) {
834 		cryptoerror(LOG_STDERR,
835 		    gettext("Warning: file \"%s\" exists, "
836 		    "will be overwritten."), filename);
837 		if (yesno(gettext("Continue with export? "),
838 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
839 			return (0);
840 		} else {
841 			/* remove the file */
842 			(void) unlink(filename);
843 		}
844 	} else {
845 		rv = verify_file(filename);
846 		if (rv != KMF_OK) {
847 			cryptoerror(LOG_STDERR, gettext("The file (%s) "
848 			    "cannot be created.\n"), filename);
849 			return (PK_ERR_USAGE);
850 		}
851 	}
852 
853 	if (serstr != NULL) {
854 		uchar_t *bytes = NULL;
855 		size_t bytelen;
856 
857 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
858 		if (rv != KMF_OK || bytes == NULL) {
859 			(void) fprintf(stderr, gettext("serial number "
860 			    "must be specified as a hex number "
861 			    "(ex: 0x0102030405ffeeddee)\n"));
862 			return (PK_ERR_USAGE);
863 		}
864 		serial.val = bytes;
865 		serial.len = bytelen;
866 	}
867 
868 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
869 	    kstype == KMF_KEYSTORE_NSS) &&
870 	    (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) ||
871 	    kfmt == KMF_FORMAT_PKCS12)) {
872 			(void) get_token_password(kstype, token_spec,
873 			    &tokencred);
874 	}
875 
876 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
877 		cryptoerror(LOG_STDERR, gettext("Error initializing "
878 		    "KMF: 0x%02x\n"), rv);
879 		return (rv);
880 	}
881 
882 	switch (kstype) {
883 		case KMF_KEYSTORE_PK11TOKEN:
884 			if (kfmt == KMF_FORMAT_PKCS12)
885 				rv = pk_export_pk12_pk11(kmfhandle,
886 				    token_spec, certlabel,
887 				    issuer, subject,
888 				    &serial, &tokencred,
889 				    filename);
890 			else if ((oclass & PK_KEY_OBJ) ||
891 			    kfmt == KMF_FORMAT_RAWKEY)
892 				rv = pk_export_pk11_keys(kmfhandle,
893 				    token_spec, &tokencred, kfmt,
894 				    certlabel, filename, oclass);
895 			else
896 				rv = pk_export_pk11_objects(kmfhandle,
897 				    token_spec, certlabel,
898 				    issuer, subject, &serial, kfmt,
899 				    filename);
900 			break;
901 		case KMF_KEYSTORE_NSS:
902 			if (dir == NULL)
903 				dir = PK_DEFAULT_DIRECTORY;
904 			if (kfmt == KMF_FORMAT_PKCS12)
905 				rv = pk_export_pk12_nss(kmfhandle,
906 				    token_spec, dir, prefix,
907 				    certlabel, issuer,
908 				    subject, &serial,
909 				    &tokencred, filename);
910 			else
911 				rv = pk_export_nss_objects(kmfhandle,
912 				    token_spec,
913 				    oclass, certlabel, issuer, subject,
914 				    &serial, kfmt, dir, prefix, filename);
915 			break;
916 		case KMF_KEYSTORE_OPENSSL:
917 			if (kfmt == KMF_FORMAT_PKCS12)
918 				rv = pk_export_pk12_files(kmfhandle,
919 				    certfile, keyfile, filename);
920 			else
921 				rv = pk_export_file_objects(kmfhandle, oclass,
922 				    issuer, subject, &serial,
923 				    infile, filename);
924 			break;
925 		default:
926 			rv = PK_ERR_USAGE;
927 			break;
928 	}
929 
930 	if (rv != KMF_OK) {
931 		display_error(kmfhandle, rv,
932 		    gettext("Error exporting objects"));
933 	}
934 
935 	if (serial.val != NULL)
936 		free(serial.val);
937 
938 	(void) kmf_finalize(kmfhandle);
939 
940 	return (rv);
941 }
942