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