xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/export.c (revision 6a074c93c5dee390d8ca2377f42e55418f0a9eb3)
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)
457 {
458 	KMF_RETURN rv = KMF_OK;
459 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
460 	int numattr = 0;
461 	uint32_t numkeys = 1;
462 	KMF_ATTRIBUTE attrlist[16];
463 	KMF_KEY_HANDLE key;
464 	boolean_t is_token = B_TRUE;
465 
466 	if (EMPTYSTRING(label)) {
467 		cryptoerror(LOG_STDERR, gettext("A label "
468 		    "must be specified to export a key."));
469 		return (KMF_ERR_BAD_PARAMETER);
470 	}
471 
472 	rv = select_token(kmfhandle, token, TRUE);
473 	if (rv != KMF_OK) {
474 		return (rv);
475 	}
476 
477 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
478 	    &kstype, sizeof (kstype));
479 	numattr++;
480 
481 	if (cred != NULL) {
482 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
483 		    cred, sizeof (KMF_CREDENTIAL));
484 		numattr++;
485 	}
486 
487 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
488 	    label, strlen(label));
489 	numattr++;
490 
491 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
492 	    &numkeys, sizeof (numkeys));
493 	numattr++;
494 
495 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
496 	    &key, sizeof (key));
497 	numattr++;
498 
499 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
500 	    &is_token, sizeof (is_token));
501 	numattr++;
502 
503 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
504 	    &format, sizeof (format));
505 	numattr++;
506 
507 	rv = kmf_find_key(kmfhandle, numattr, attrlist);
508 	if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) {
509 		KMF_RAW_SYM_KEY rkey;
510 
511 		(void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY));
512 		rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey);
513 		if (rv == KMF_OK) {
514 			int fd, n, total = 0;
515 
516 			fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600);
517 			if (fd == -1) {
518 				rv = KMF_ERR_OPEN_FILE;
519 				goto done;
520 			}
521 			do {
522 				n = write(fd, rkey.keydata.val + total,
523 				    rkey.keydata.len - total);
524 				if (n < 0) {
525 					if (errno == EINTR)
526 						continue;
527 					(void) close(fd);
528 					rv = KMF_ERR_WRITE_FILE;
529 					goto done;
530 				}
531 				total += n;
532 
533 			} while (total < rkey.keydata.len);
534 			(void) close(fd);
535 		}
536 done:
537 		kmf_free_bigint(&rkey.keydata);
538 		kmf_free_kmf_key(kmfhandle, &key);
539 	} else if (rv == KMF_OK) {
540 		KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL;
541 		(void) printf(gettext("Found %d asymmetric keys\n"), numkeys);
542 
543 		numattr = 0;
544 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
545 		    &sslks, sizeof (sslks));
546 		numattr++;
547 
548 		kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR,
549 		    key.keyp, sizeof (KMF_RAW_KEY_DATA));
550 		numattr++;
551 
552 		kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
553 		    &format, sizeof (format));
554 		numattr++;
555 
556 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
557 		    filename, strlen(filename));
558 		numattr++;
559 
560 		rv = kmf_store_key(kmfhandle, numattr, attrlist);
561 		kmf_free_kmf_key(kmfhandle, &key);
562 	}
563 
564 	return (rv);
565 }
566 
567 static KMF_RETURN
568 pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
569 	char *certlabel, char *issuer, char *subject,
570 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt,
571 	char *filename)
572 {
573 	KMF_RETURN rv = KMF_OK;
574 	KMF_X509_DER_CERT kmfcert;
575 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
576 	int numattr = 0;
577 	KMF_ATTRIBUTE attrlist[16];
578 
579 	rv = select_token(kmfhandle, token_spec, TRUE);
580 
581 	if (rv != KMF_OK) {
582 		return (rv);
583 	}
584 
585 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
586 	    &kstype, sizeof (kstype));
587 	numattr++;
588 
589 	if (certlabel != NULL) {
590 		kmf_set_attr_at_index(attrlist, numattr,
591 		    KMF_CERT_LABEL_ATTR, certlabel,
592 		    strlen(certlabel));
593 		numattr++;
594 	}
595 
596 	if (issuer != NULL) {
597 		kmf_set_attr_at_index(attrlist, numattr,
598 		    KMF_ISSUER_NAME_ATTR, issuer,
599 		    strlen(issuer));
600 		numattr++;
601 	}
602 
603 	if (subject != NULL) {
604 		kmf_set_attr_at_index(attrlist, numattr,
605 		    KMF_SUBJECT_NAME_ATTR, subject,
606 		    strlen(subject));
607 		numattr++;
608 	}
609 
610 	if (serial != NULL) {
611 		kmf_set_attr_at_index(attrlist, numattr,
612 		    KMF_BIGINT_ATTR, serial,
613 		    sizeof (KMF_BIGINT));
614 		numattr++;
615 	}
616 
617 	rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert);
618 
619 	if (rv == KMF_OK) {
620 		kstype = KMF_KEYSTORE_OPENSSL;
621 		numattr = 0;
622 
623 		kmf_set_attr_at_index(attrlist, numattr,
624 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
625 		numattr++;
626 
627 		kmf_set_attr_at_index(attrlist, numattr,
628 		    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
629 		    sizeof (KMF_DATA));
630 		numattr++;
631 
632 		kmf_set_attr_at_index(attrlist, numattr,
633 		    KMF_CERT_FILENAME_ATTR, filename, strlen(filename));
634 		numattr++;
635 
636 		kmf_set_attr_at_index(attrlist, numattr,
637 		    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
638 		numattr++;
639 
640 		rv = kmf_store_cert(kmfhandle, numattr, attrlist);
641 
642 		kmf_free_kmf_cert(kmfhandle, &kmfcert);
643 	}
644 	return (rv);
645 }
646 
647 /*
648  * Export objects from one keystore to a file.
649  */
650 int
651 pk_export(int argc, char *argv[])
652 {
653 	int		opt;
654 	extern int	optind_av;
655 	extern char	*optarg_av;
656 	char		*token_spec = NULL;
657 	char		*filename = NULL;
658 	char		*dir = NULL;
659 	char		*prefix = NULL;
660 	char		*certlabel = NULL;
661 	char		*subject = NULL;
662 	char		*issuer = NULL;
663 	char		*infile = NULL;
664 	char		*keyfile = NULL;
665 	char		*certfile = NULL;
666 	char		*serstr = NULL;
667 	KMF_KEYSTORE_TYPE	kstype = 0;
668 	KMF_ENCODE_FORMAT	kfmt = KMF_FORMAT_PKCS12;
669 	KMF_RETURN		rv = KMF_OK;
670 	int		oclass = PK_CERT_OBJ;
671 	KMF_BIGINT	serial = { NULL, 0 };
672 	KMF_HANDLE_T	kmfhandle = NULL;
673 	KMF_CREDENTIAL	tokencred = {NULL, 0};
674 
675 	/* Parse command line options.  Do NOT i18n/l10n. */
676 	while ((opt = getopt_av(argc, argv,
677 	    "k:(keystore)y:(objtype)T:(token)"
678 	    "d:(dir)p:(prefix)"
679 	    "l:(label)n:(nickname)s:(subject)"
680 	    "i:(issuer)S:(serial)"
681 	    "K:(keyfile)c:(certfile)"
682 	    "F:(outformat)"
683 	    "I:(infile)o:(outfile)")) != EOF) {
684 		if (EMPTYSTRING(optarg_av))
685 			return (PK_ERR_USAGE);
686 		switch (opt) {
687 		case 'k':
688 			kstype = KS2Int(optarg_av);
689 			if (kstype == 0)
690 				return (PK_ERR_USAGE);
691 			break;
692 		case 'y':
693 			oclass = OT2Int(optarg_av);
694 			if (oclass == -1)
695 				return (PK_ERR_USAGE);
696 			break;
697 		case 'T':	/* token specifier */
698 			if (token_spec)
699 				return (PK_ERR_USAGE);
700 			token_spec = optarg_av;
701 			break;
702 		case 'd':
703 			if (dir)
704 				return (PK_ERR_USAGE);
705 			dir = optarg_av;
706 			break;
707 		case 'p':
708 			if (prefix)
709 				return (PK_ERR_USAGE);
710 			prefix = optarg_av;
711 			break;
712 		case 'n':
713 		case 'l':
714 			if (certlabel)
715 				return (PK_ERR_USAGE);
716 			certlabel = optarg_av;
717 			break;
718 		case 's':
719 			if (subject)
720 				return (PK_ERR_USAGE);
721 			subject = optarg_av;
722 			break;
723 		case 'i':
724 			if (issuer)
725 				return (PK_ERR_USAGE);
726 			issuer = optarg_av;
727 			break;
728 		case 'S':
729 			serstr = optarg_av;
730 			break;
731 		case 'F':
732 			kfmt = Str2Format(optarg_av);
733 			if (kfmt == KMF_FORMAT_UNDEF)
734 				return (PK_ERR_USAGE);
735 			break;
736 		case 'I':	/* output file name */
737 			if (infile)
738 				return (PK_ERR_USAGE);
739 			infile = optarg_av;
740 			break;
741 		case 'o':	/* output file name */
742 			if (filename)
743 				return (PK_ERR_USAGE);
744 			filename = optarg_av;
745 			break;
746 		case 'c':	/* input cert file name */
747 			if (certfile)
748 				return (PK_ERR_USAGE);
749 			certfile = optarg_av;
750 			break;
751 		case 'K':	/* input key file name */
752 			if (keyfile)
753 				return (PK_ERR_USAGE);
754 			keyfile = optarg_av;
755 			break;
756 		default:
757 			return (PK_ERR_USAGE);
758 			break;
759 		}
760 	}
761 
762 	/* Assume keystore = PKCS#11 if not specified */
763 	if (kstype == 0)
764 		kstype = KMF_KEYSTORE_PK11TOKEN;
765 
766 	/* Filename arg is required. */
767 	if (EMPTYSTRING(filename)) {
768 		cryptoerror(LOG_STDERR, gettext("You must specify "
769 		    "an 'outfile' parameter when exporting.\n"));
770 		return (PK_ERR_USAGE);
771 	}
772 
773 	/* No additional args allowed. */
774 	argc -= optind_av;
775 	argv += optind_av;
776 	if (argc)
777 		return (PK_ERR_USAGE);
778 
779 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
780 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
781 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
782 
783 		(void) fprintf(stderr, gettext("The objtype parameter "
784 		    "is only relevant if keystore=pkcs11\n"));
785 		return (PK_ERR_USAGE);
786 	}
787 
788 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
789 		token_spec = PK_DEFAULT_PK11TOKEN;
790 	else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
791 		token_spec = DEFAULT_NSS_TOKEN;
792 
793 	if (kstype == KMF_KEYSTORE_OPENSSL) {
794 		if (kfmt != KMF_FORMAT_PKCS12) {
795 			cryptoerror(LOG_STDERR, gettext("PKCS12 "
796 			    "is the only export format "
797 			    "supported for the 'file' "
798 			    "keystore.\n"));
799 			return (PK_ERR_USAGE);
800 		}
801 		if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
802 			cryptoerror(LOG_STDERR, gettext("A cert file"
803 			    "and a key file must be specified "
804 			    "when exporting to PKCS12 from the "
805 			    "'file' keystore.\n"));
806 			return (PK_ERR_USAGE);
807 		}
808 	}
809 
810 	/* Check if the file exists and might be overwritten. */
811 	if (access(filename, F_OK) == 0) {
812 		cryptoerror(LOG_STDERR,
813 		    gettext("Warning: file \"%s\" exists, "
814 		    "will be overwritten."), filename);
815 		if (yesno(gettext("Continue with export? "),
816 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
817 			return (0);
818 		}
819 	} else {
820 		rv = verify_file(filename);
821 		if (rv != KMF_OK) {
822 			cryptoerror(LOG_STDERR, gettext("The file (%s) "
823 			    "cannot be created.\n"), filename);
824 			return (PK_ERR_USAGE);
825 		}
826 	}
827 
828 	if (serstr != NULL) {
829 		uchar_t *bytes = NULL;
830 		size_t bytelen;
831 
832 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
833 		if (rv != KMF_OK || bytes == NULL) {
834 			(void) fprintf(stderr, gettext("serial number "
835 			    "must be specified as a hex number "
836 			    "(ex: 0x0102030405ffeeddee)\n"));
837 			return (PK_ERR_USAGE);
838 		}
839 		serial.val = bytes;
840 		serial.len = bytelen;
841 	}
842 
843 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
844 	    kstype == KMF_KEYSTORE_NSS) &&
845 	    (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) ||
846 	    kfmt == KMF_FORMAT_PKCS12)) {
847 			(void) get_token_password(kstype, token_spec,
848 			    &tokencred);
849 	}
850 
851 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
852 		cryptoerror(LOG_STDERR, gettext("Error initializing "
853 		    "KMF: 0x%02x\n"), rv);
854 		return (rv);
855 	}
856 
857 	switch (kstype) {
858 		case KMF_KEYSTORE_PK11TOKEN:
859 			if (kfmt == KMF_FORMAT_PKCS12)
860 				rv = pk_export_pk12_pk11(kmfhandle,
861 				    token_spec, certlabel,
862 				    issuer, subject,
863 				    &serial, &tokencred,
864 				    filename);
865 			else if ((oclass & PK_KEY_OBJ) ||
866 			    kfmt == KMF_FORMAT_RAWKEY)
867 				rv = pk_export_pk11_keys(kmfhandle,
868 				    token_spec, &tokencred, kfmt,
869 				    certlabel, filename);
870 			else
871 				rv = pk_export_pk11_objects(kmfhandle,
872 				    token_spec, certlabel,
873 				    issuer, subject, &serial, kfmt,
874 				    filename);
875 			break;
876 		case KMF_KEYSTORE_NSS:
877 			if (dir == NULL)
878 				dir = PK_DEFAULT_DIRECTORY;
879 			if (kfmt == KMF_FORMAT_PKCS12)
880 				rv = pk_export_pk12_nss(kmfhandle,
881 				    token_spec, dir, prefix,
882 				    certlabel, issuer,
883 				    subject, &serial,
884 				    &tokencred, filename);
885 			else
886 				rv = pk_export_nss_objects(kmfhandle,
887 				    token_spec,
888 				    oclass, certlabel, issuer, subject,
889 				    &serial, kfmt, dir, prefix, filename);
890 			break;
891 		case KMF_KEYSTORE_OPENSSL:
892 			if (kfmt == KMF_FORMAT_PKCS12)
893 				rv = pk_export_pk12_files(kmfhandle,
894 				    certfile, keyfile, dir,
895 				    filename);
896 			else
897 				rv = pk_export_file_objects(kmfhandle, oclass,
898 				    issuer, subject, &serial,
899 				    dir, infile, filename);
900 			break;
901 		default:
902 			rv = PK_ERR_USAGE;
903 			break;
904 	}
905 
906 	if (rv != KMF_OK) {
907 		display_error(kmfhandle, rv,
908 		    gettext("Error exporting objects"));
909 	}
910 
911 	if (serial.val != NULL)
912 		free(serial.val);
913 
914 	(void) kmf_finalize(kmfhandle);
915 
916 	return (rv);
917 }
918