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