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 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 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 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 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 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 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 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 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 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