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