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