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  * Copyright 2012 Milan Jurik. All rights reserved.
23  */
24 
25 /*
26  * This file implements the export operation for this tool.
27  * The basic flow of the process is to find the soft token,
28  * log into it, find the PKCS#11 objects in the soft token
29  * to be exported matching keys with their certificates, export
30  * them to the PKCS#12 file encrypting them with a file password
31  * if desired, and log out.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include "common.h"
40 
41 #include <kmfapi.h>
42 
43 static KMF_RETURN
44 pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist,
45 	int numattr, KMF_X509_DER_CERT *cert)
46 {
47 	KMF_RETURN rv = KMF_OK;
48 	uint32_t numcerts = 0;
49 
50 	numcerts = 0;
51 	(void) memset(cert, 0, sizeof (KMF_X509_DER_CERT));
52 
53 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
54 	    &numcerts, sizeof (uint32_t));
55 	numattr++;
56 
57 	rv = kmf_find_cert(kmfhandle, numattr, attrlist);
58 	if (rv != KMF_OK) {
59 		return (rv);
60 	}
61 	if (numcerts == 0) {
62 		cryptoerror(LOG_STDERR,
63 		    gettext("No matching certificates found."));
64 		return (KMF_ERR_CERT_NOT_FOUND);
65 
66 	} else if (numcerts == 1) {
67 		kmf_set_attr_at_index(attrlist, numattr,
68 		    KMF_X509_DER_CERT_ATTR, cert,
69 		    sizeof (KMF_X509_DER_CERT));
70 		numattr++;
71 		rv = kmf_find_cert(kmfhandle, numattr, attrlist);
72 
73 	} else if (numcerts > 1) {
74 		cryptoerror(LOG_STDERR,
75 		    gettext("%d certificates found, refine the "
76 		    "search parameters to eliminate ambiguity\n"),
77 		    numcerts);
78 		return (KMF_ERR_BAD_PARAMETER);
79 	}
80 	return (rv);
81 }
82 
83 static KMF_RETURN
84 pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
85 	char *issuer, char *subject, KMF_BIGINT *serial,
86 	char *infile, char *filename)
87 {
88 	KMF_RETURN rv = KMF_OK;
89 	KMF_X509_DER_CERT kmfcert;
90 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
91 	int numattr = 0;
92 	KMF_ATTRIBUTE attrlist[16];
93 
94 	/* If searching for public objects or certificates, find certs now */
95 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
96 		kmf_set_attr_at_index(attrlist, numattr,
97 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
98 		    sizeof (kstype));
99 		numattr++;
100 
101 		if (issuer != NULL) {
102 			kmf_set_attr_at_index(attrlist, numattr,
103 			    KMF_ISSUER_NAME_ATTR, issuer,
104 			    strlen(issuer));
105 			numattr++;
106 		}
107 
108 		if (subject != NULL) {
109 			kmf_set_attr_at_index(attrlist, numattr,
110 			    KMF_SUBJECT_NAME_ATTR, subject,
111 			    strlen(subject));
112 			numattr++;
113 		}
114 
115 		if (serial != NULL) {
116 			kmf_set_attr_at_index(attrlist, numattr,
117 			    KMF_BIGINT_ATTR, serial,
118 			    sizeof (KMF_BIGINT));
119 			numattr++;
120 		}
121 
122 		if (infile != NULL) {
123 			kmf_set_attr_at_index(attrlist, numattr,
124 			    KMF_CERT_FILENAME_ATTR, infile,
125 			    strlen(infile));
126 			numattr++;
127 		}
128 
129 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
130 		    &kmfcert);
131 		if (rv == KMF_OK) {
132 			kstype = KMF_KEYSTORE_OPENSSL;
133 			numattr = 0;
134 
135 			kmf_set_attr_at_index(attrlist, numattr,
136 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
137 			numattr++;
138 
139 			kmf_set_attr_at_index(attrlist, numattr,
140 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
141 			    sizeof (KMF_DATA));
142 			numattr++;
143 
144 			kmf_set_attr_at_index(attrlist, numattr,
145 			    KMF_CERT_FILENAME_ATTR, filename,
146 			    strlen(filename));
147 			numattr++;
148 
149 			rv = kmf_store_cert(kmfhandle, numattr,
150 			    attrlist);
151 
152 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
153 		}
154 	}
155 	return (rv);
156 }
157 
158 static KMF_RETURN
159 pk_export_pk12_nss(KMF_HANDLE_T kmfhandle,
160 	char *token_spec, char *dir, char *prefix,
161 	char *certlabel, char *issuer, char *subject,
162 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred,
163 	char *filename)
164 {
165 	KMF_RETURN rv = KMF_OK;
166 	KMF_KEYSTORE_TYPE kstype;
167 	KMF_CREDENTIAL p12cred = { NULL, 0};
168 	KMF_ATTRIBUTE attrlist[16];
169 	int numattr = 0;
170 
171 	rv = configure_nss(kmfhandle, dir, prefix);
172 	if (rv != KMF_OK)
173 		return (rv);
174 
175 	if (token_spec == NULL)
176 		token_spec = DEFAULT_NSS_TOKEN;
177 
178 	kstype = KMF_KEYSTORE_NSS;
179 	kmf_set_attr_at_index(attrlist, numattr,
180 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
181 	numattr++;
182 
183 	if (certlabel != NULL) {
184 		kmf_set_attr_at_index(attrlist, numattr,
185 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
186 		numattr++;
187 	}
188 
189 	if (issuer != NULL) {
190 		kmf_set_attr_at_index(attrlist, numattr,
191 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
192 		numattr++;
193 	}
194 
195 	if (subject != NULL) {
196 		kmf_set_attr_at_index(attrlist, numattr,
197 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
198 		numattr++;
199 	}
200 
201 	if (serial != NULL) {
202 		kmf_set_attr_at_index(attrlist, numattr,
203 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
204 		numattr++;
205 	}
206 
207 	if (tokencred != NULL) {
208 		kmf_set_attr_at_index(attrlist, numattr,
209 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
210 		numattr++;
211 	}
212 
213 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
214 	    token_spec, strlen(token_spec));
215 	numattr++;
216 
217 	(void) get_pk12_password(&p12cred);
218 	kmf_set_attr_at_index(attrlist, numattr,
219 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
220 	numattr++;
221 
222 	kmf_set_attr_at_index(attrlist, numattr,
223 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
224 	numattr++;
225 
226 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
227 
228 	if (p12cred.cred)
229 		free(p12cred.cred);
230 
231 	return (rv);
232 }
233 
234 static KMF_RETURN
235 pk_export_pk12_files(KMF_HANDLE_T kmfhandle,
236 	char *certfile, char *keyfile,
237 	char *outfile)
238 {
239 	KMF_RETURN rv;
240 	KMF_KEYSTORE_TYPE kstype;
241 	KMF_CREDENTIAL p12cred = { NULL, 0};
242 	KMF_ATTRIBUTE attrlist[16];
243 	int numattr = 0;
244 
245 	kstype = KMF_KEYSTORE_OPENSSL;
246 	kmf_set_attr_at_index(attrlist, numattr,
247 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
248 	numattr++;
249 
250 	if (certfile != NULL) {
251 		kmf_set_attr_at_index(attrlist, numattr,
252 		    KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile));
253 		numattr++;
254 	}
255 
256 	if (keyfile != NULL) {
257 		kmf_set_attr_at_index(attrlist, numattr,
258 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
259 		numattr++;
260 	}
261 
262 	(void) get_pk12_password(&p12cred);
263 	kmf_set_attr_at_index(attrlist, numattr,
264 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
265 	numattr++;
266 
267 	kmf_set_attr_at_index(attrlist, numattr,
268 	    KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile));
269 	numattr++;
270 
271 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
272 
273 	if (p12cred.cred)
274 		free(p12cred.cred);
275 
276 	return (rv);
277 }
278 
279 static KMF_RETURN
280 pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
281 	int oclass, char *certlabel, char *issuer, char *subject,
282 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir,
283 	char *prefix, char *filename)
284 {
285 	KMF_RETURN rv = KMF_OK;
286 	KMF_X509_DER_CERT kmfcert;
287 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
288 	KMF_ATTRIBUTE attrlist[16];
289 	int numattr = 0;
290 
291 	rv = configure_nss(kmfhandle, dir, prefix);
292 	if (rv != KMF_OK)
293 		return (rv);
294 
295 	/* If searching for public objects or certificates, find certs now */
296 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
297 		kmf_set_attr_at_index(attrlist, numattr,
298 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
299 		    sizeof (kstype));
300 		numattr++;
301 
302 		if (certlabel != NULL) {
303 			kmf_set_attr_at_index(attrlist, numattr,
304 			    KMF_CERT_LABEL_ATTR, certlabel,
305 			    strlen(certlabel));
306 			numattr++;
307 		}
308 
309 		if (issuer != NULL) {
310 			kmf_set_attr_at_index(attrlist, numattr,
311 			    KMF_ISSUER_NAME_ATTR, issuer,
312 			    strlen(issuer));
313 			numattr++;
314 		}
315 
316 		if (subject != NULL) {
317 			kmf_set_attr_at_index(attrlist, numattr,
318 			    KMF_SUBJECT_NAME_ATTR, subject,
319 			    strlen(subject));
320 			numattr++;
321 		}
322 
323 		if (serial != NULL) {
324 			kmf_set_attr_at_index(attrlist, numattr,
325 			    KMF_BIGINT_ATTR, serial,
326 			    sizeof (KMF_BIGINT));
327 			numattr++;
328 		}
329 
330 		if (token_spec != NULL) {
331 			kmf_set_attr_at_index(attrlist, numattr,
332 			    KMF_TOKEN_LABEL_ATTR, token_spec,
333 			    strlen(token_spec));
334 			numattr++;
335 		}
336 
337 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
338 		    &kmfcert);
339 		if (rv == KMF_OK) {
340 			kstype = KMF_KEYSTORE_OPENSSL;
341 			numattr = 0;
342 
343 			kmf_set_attr_at_index(attrlist, numattr,
344 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
345 			numattr++;
346 
347 			kmf_set_attr_at_index(attrlist, numattr,
348 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
349 			    sizeof (KMF_DATA));
350 			numattr++;
351 
352 			kmf_set_attr_at_index(attrlist, numattr,
353 			    KMF_CERT_FILENAME_ATTR, filename,
354 			    strlen(filename));
355 			numattr++;
356 
357 			kmf_set_attr_at_index(attrlist, numattr,
358 			    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
359 			numattr++;
360 
361 			rv = kmf_store_cert(kmfhandle, numattr, attrlist);
362 
363 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
364 		}
365 	}
366 	return (rv);
367 }
368 
369 static KMF_RETURN
370 pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec,
371 	char *certlabel, char *issuer, char *subject,
372 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename)
373 {
374 	KMF_RETURN rv = KMF_OK;
375 	KMF_KEYSTORE_TYPE kstype;
376 	KMF_CREDENTIAL p12cred = { NULL, 0};
377 	KMF_ATTRIBUTE attrlist[16];
378 	int numattr = 0;
379 
380 	rv = select_token(kmfhandle, token_spec, TRUE);
381 	if (rv != KMF_OK) {
382 		return (rv);
383 	}
384 
385 	kstype = KMF_KEYSTORE_PK11TOKEN;
386 	kmf_set_attr_at_index(attrlist, numattr,
387 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
388 	numattr++;
389 
390 	if (certlabel != NULL) {
391 		kmf_set_attr_at_index(attrlist, numattr,
392 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
393 		numattr++;
394 	}
395 
396 	if (issuer != NULL) {
397 		kmf_set_attr_at_index(attrlist, numattr,
398 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
399 		numattr++;
400 	}
401 
402 	if (subject != NULL) {
403 		kmf_set_attr_at_index(attrlist, numattr,
404 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
405 		numattr++;
406 	}
407 
408 	if (serial != NULL) {
409 		kmf_set_attr_at_index(attrlist, numattr,
410 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
411 		numattr++;
412 	}
413 
414 	if (tokencred != NULL) {
415 		kmf_set_attr_at_index(attrlist, numattr,
416 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
417 		numattr++;
418 	}
419 
420 	(void) get_pk12_password(&p12cred);
421 	kmf_set_attr_at_index(attrlist, numattr,
422 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
423 	numattr++;
424 
425 	kmf_set_attr_at_index(attrlist, numattr,
426 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
427 	numattr++;
428 
429 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
430 
431 	if (p12cred.cred)
432 		free(p12cred.cred);
433 
434 	return (rv);
435 }
436 
437 static KMF_RETURN
438 pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token,
439 	KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format,
440 	char *label, char *filename, int oclass)
441 {
442 	KMF_RETURN rv = KMF_OK;
443 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
444 	KMF_KEY_CLASS kclass = KMF_KEYCLASS_NONE;
445 	int numattr = 0;
446 	uint32_t numkeys = 1;
447 	KMF_ATTRIBUTE attrlist[16];
448 	KMF_KEY_HANDLE key;
449 	boolean_t is_token = B_TRUE;
450 
451 	if (EMPTYSTRING(label)) {
452 		cryptoerror(LOG_STDERR, gettext("A label "
453 		    "must be specified to export a key."));
454 		return (KMF_ERR_BAD_PARAMETER);
455 	}
456 
457 	rv = select_token(kmfhandle, token, TRUE);
458 	if (rv != KMF_OK) {
459 		return (rv);
460 	}
461 
462 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
463 	    &kstype, sizeof (kstype));
464 	numattr++;
465 
466 	if (cred != NULL) {
467 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
468 		    cred, sizeof (KMF_CREDENTIAL));
469 		numattr++;
470 	}
471 
472 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
473 	    label, strlen(label));
474 	numattr++;
475 
476 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
477 	    &numkeys, sizeof (numkeys));
478 	numattr++;
479 
480 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
481 	    &key, sizeof (key));
482 	numattr++;
483 
484 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
485 	    &is_token, sizeof (is_token));
486 	numattr++;
487 
488 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
489 	    &format, sizeof (format));
490 	numattr++;
491 
492 	/* Check to see if we are exporting private or public only */
493 	if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ)
494 		kclass = KMF_ASYM_PRI;
495 	else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ)
496 		kclass = KMF_ASYM_PUB;
497 	else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ)
498 		kclass = KMF_SYMMETRIC;
499 	else /* only 1 key at a time can be exported here, so default to pri */
500 		kclass = KMF_ASYM_PRI;
501 
502 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
503 	    &kclass, sizeof (kclass));
504 	numattr++;
505 
506 	rv = kmf_find_key(kmfhandle, numattr, attrlist);
507 	/*
508 	 * If nothing found but caller wanted ALL keys, try symmetric
509 	 * this time.
510 	 */
511 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
512 		kclass = KMF_SYMMETRIC;
513 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
514 	}
515 	/*
516 	 * If nothing found but caller wanted ALL keys, try asymmetric
517 	 * public this time.
518 	 */
519 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
520 		kclass = KMF_ASYM_PUB;
521 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
522 	}
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 	KMF_CREDENTIAL *cred, 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 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
604 	    &kstype, sizeof (kstype));
605 	numattr++;
606 
607 	if (cred != NULL) {
608 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
609 		    cred, sizeof (KMF_CREDENTIAL));
610 		numattr++;
611 	}
612 	if (certlabel != NULL) {
613 		kmf_set_attr_at_index(attrlist, numattr,
614 		    KMF_CERT_LABEL_ATTR, certlabel,
615 		    strlen(certlabel));
616 		numattr++;
617 	}
618 
619 	if (issuer != NULL) {
620 		kmf_set_attr_at_index(attrlist, numattr,
621 		    KMF_ISSUER_NAME_ATTR, issuer,
622 		    strlen(issuer));
623 		numattr++;
624 	}
625 
626 	if (subject != NULL) {
627 		kmf_set_attr_at_index(attrlist, numattr,
628 		    KMF_SUBJECT_NAME_ATTR, subject,
629 		    strlen(subject));
630 		numattr++;
631 	}
632 
633 	if (serial != NULL) {
634 		kmf_set_attr_at_index(attrlist, numattr,
635 		    KMF_BIGINT_ATTR, serial,
636 		    sizeof (KMF_BIGINT));
637 		numattr++;
638 	}
639 
640 	rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert);
641 
642 	if (rv == KMF_OK) {
643 		kstype = KMF_KEYSTORE_OPENSSL;
644 		numattr = 0;
645 
646 		kmf_set_attr_at_index(attrlist, numattr,
647 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
648 		numattr++;
649 
650 		kmf_set_attr_at_index(attrlist, numattr,
651 		    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
652 		    sizeof (KMF_DATA));
653 		numattr++;
654 
655 		kmf_set_attr_at_index(attrlist, numattr,
656 		    KMF_CERT_FILENAME_ATTR, filename, strlen(filename));
657 		numattr++;
658 
659 		kmf_set_attr_at_index(attrlist, numattr,
660 		    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
661 		numattr++;
662 
663 		rv = kmf_store_cert(kmfhandle, numattr, attrlist);
664 
665 		kmf_free_kmf_cert(kmfhandle, &kmfcert);
666 	}
667 	return (rv);
668 }
669 
670 /*
671  * Export objects from one keystore to a file.
672  */
673 int
674 pk_export(int argc, char *argv[])
675 {
676 	int		opt;
677 	extern int	optind_av;
678 	extern char	*optarg_av;
679 	char		*token_spec = NULL;
680 	char		*filename = NULL;
681 	char		*dir = NULL;
682 	char		*prefix = NULL;
683 	char		*certlabel = NULL;
684 	char		*subject = NULL;
685 	char		*issuer = NULL;
686 	char		*infile = NULL;
687 	char		*keyfile = NULL;
688 	char		*certfile = NULL;
689 	char		*serstr = NULL;
690 	KMF_KEYSTORE_TYPE	kstype = 0;
691 	KMF_ENCODE_FORMAT	kfmt = KMF_FORMAT_PKCS12;
692 	KMF_RETURN		rv = KMF_OK;
693 	int		oclass = PK_CERT_OBJ;
694 	KMF_BIGINT	serial = { NULL, 0 };
695 	KMF_HANDLE_T	kmfhandle = NULL;
696 	KMF_CREDENTIAL	tokencred = {NULL, 0};
697 
698 	/* Parse command line options.  Do NOT i18n/l10n. */
699 	while ((opt = getopt_av(argc, argv,
700 	    "k:(keystore)y:(objtype)T:(token)"
701 	    "d:(dir)p:(prefix)"
702 	    "l:(label)n:(nickname)s:(subject)"
703 	    "i:(issuer)S:(serial)"
704 	    "K:(keyfile)c:(certfile)"
705 	    "F:(outformat)"
706 	    "I:(infile)o:(outfile)")) != EOF) {
707 		if (EMPTYSTRING(optarg_av))
708 			return (PK_ERR_USAGE);
709 		switch (opt) {
710 		case 'k':
711 			kstype = KS2Int(optarg_av);
712 			if (kstype == 0)
713 				return (PK_ERR_USAGE);
714 			break;
715 		case 'y':
716 			oclass = OT2Int(optarg_av);
717 			if (oclass == -1)
718 				return (PK_ERR_USAGE);
719 			break;
720 		case 'T':	/* token specifier */
721 			if (token_spec)
722 				return (PK_ERR_USAGE);
723 			token_spec = optarg_av;
724 			break;
725 		case 'd':
726 			if (dir)
727 				return (PK_ERR_USAGE);
728 			dir = optarg_av;
729 			break;
730 		case 'p':
731 			if (prefix)
732 				return (PK_ERR_USAGE);
733 			prefix = optarg_av;
734 			break;
735 		case 'n':
736 		case 'l':
737 			if (certlabel)
738 				return (PK_ERR_USAGE);
739 			certlabel = optarg_av;
740 			break;
741 		case 's':
742 			if (subject)
743 				return (PK_ERR_USAGE);
744 			subject = optarg_av;
745 			break;
746 		case 'i':
747 			if (issuer)
748 				return (PK_ERR_USAGE);
749 			issuer = optarg_av;
750 			break;
751 		case 'S':
752 			serstr = optarg_av;
753 			break;
754 		case 'F':
755 			kfmt = Str2Format(optarg_av);
756 			if (kfmt == KMF_FORMAT_UNDEF)
757 				return (PK_ERR_USAGE);
758 			break;
759 		case 'I':	/* output file name */
760 			if (infile)
761 				return (PK_ERR_USAGE);
762 			infile = optarg_av;
763 			break;
764 		case 'o':	/* output file name */
765 			if (filename)
766 				return (PK_ERR_USAGE);
767 			filename = optarg_av;
768 			break;
769 		case 'c':	/* input cert file name */
770 			if (certfile)
771 				return (PK_ERR_USAGE);
772 			certfile = optarg_av;
773 			break;
774 		case 'K':	/* input key file name */
775 			if (keyfile)
776 				return (PK_ERR_USAGE);
777 			keyfile = optarg_av;
778 			break;
779 		default:
780 			return (PK_ERR_USAGE);
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