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