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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * This file implements the export operation for this tool. 30 * The basic flow of the process is to find the soft token, 31 * log into it, find the PKCS#11 objects in the soft token 32 * to be exported matching keys with their certificates, export 33 * them to the PKCS#12 file encrypting them with a file password 34 * if desired, and log out. 35 */ 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include "common.h" 43 44 #include <kmfapi.h> 45 46 static KMF_RETURN 47 pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist, 48 int numattr, KMF_X509_DER_CERT *cert) 49 { 50 KMF_RETURN rv = KMF_OK; 51 uint32_t numcerts = 0; 52 53 numcerts = 0; 54 (void) memset(cert, 0, sizeof (KMF_X509_DER_CERT)); 55 56 kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 57 &numcerts, sizeof (uint32_t)); 58 numattr++; 59 60 rv = kmf_find_cert(kmfhandle, numattr, attrlist); 61 if (rv != KMF_OK) { 62 return (rv); 63 } 64 if (numcerts == 0) { 65 cryptoerror(LOG_STDERR, 66 gettext("No matching certificates found.")); 67 return (KMF_ERR_CERT_NOT_FOUND); 68 69 } else if (numcerts == 1) { 70 kmf_set_attr_at_index(attrlist, numattr, 71 KMF_X509_DER_CERT_ATTR, cert, 72 sizeof (KMF_X509_DER_CERT)); 73 numattr++; 74 rv = kmf_find_cert(kmfhandle, numattr, attrlist); 75 76 } else if (numcerts > 1) { 77 cryptoerror(LOG_STDERR, 78 gettext("%d certificates found, refine the " 79 "search parameters to eliminate ambiguity\n"), 80 numcerts); 81 return (KMF_ERR_BAD_PARAMETER); 82 } 83 return (rv); 84 } 85 86 static KMF_RETURN 87 pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass, 88 char *issuer, char *subject, KMF_BIGINT *serial, 89 char *infile, char *filename) 90 { 91 KMF_RETURN rv = KMF_OK; 92 KMF_X509_DER_CERT kmfcert; 93 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 94 int numattr = 0; 95 KMF_ATTRIBUTE attrlist[16]; 96 97 /* If searching for public objects or certificates, find certs now */ 98 if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) { 99 kmf_set_attr_at_index(attrlist, numattr, 100 KMF_KEYSTORE_TYPE_ATTR, &kstype, 101 sizeof (kstype)); 102 numattr++; 103 104 if (issuer != NULL) { 105 kmf_set_attr_at_index(attrlist, numattr, 106 KMF_ISSUER_NAME_ATTR, issuer, 107 strlen(issuer)); 108 numattr++; 109 } 110 111 if (subject != NULL) { 112 kmf_set_attr_at_index(attrlist, numattr, 113 KMF_SUBJECT_NAME_ATTR, subject, 114 strlen(subject)); 115 numattr++; 116 } 117 118 if (serial != NULL) { 119 kmf_set_attr_at_index(attrlist, numattr, 120 KMF_BIGINT_ATTR, serial, 121 sizeof (KMF_BIGINT)); 122 numattr++; 123 } 124 125 if (infile != NULL) { 126 kmf_set_attr_at_index(attrlist, numattr, 127 KMF_CERT_FILENAME_ATTR, infile, 128 strlen(infile)); 129 numattr++; 130 } 131 132 rv = pk_find_export_cert(kmfhandle, attrlist, numattr, 133 &kmfcert); 134 if (rv == KMF_OK) { 135 kstype = KMF_KEYSTORE_OPENSSL; 136 numattr = 0; 137 138 kmf_set_attr_at_index(attrlist, numattr, 139 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 140 numattr++; 141 142 kmf_set_attr_at_index(attrlist, numattr, 143 KMF_CERT_DATA_ATTR, &kmfcert.certificate, 144 sizeof (KMF_DATA)); 145 numattr++; 146 147 kmf_set_attr_at_index(attrlist, numattr, 148 KMF_CERT_FILENAME_ATTR, filename, 149 strlen(filename)); 150 numattr++; 151 152 rv = kmf_store_cert(kmfhandle, numattr, 153 attrlist); 154 155 kmf_free_kmf_cert(kmfhandle, &kmfcert); 156 } 157 } 158 return (rv); 159 } 160 161 static KMF_RETURN 162 pk_export_pk12_nss(KMF_HANDLE_T kmfhandle, 163 char *token_spec, char *dir, char *prefix, 164 char *certlabel, char *issuer, char *subject, 165 KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, 166 char *filename) 167 { 168 KMF_RETURN rv = KMF_OK; 169 KMF_KEYSTORE_TYPE kstype; 170 KMF_CREDENTIAL p12cred = { NULL, 0}; 171 KMF_ATTRIBUTE attrlist[16]; 172 int numattr = 0; 173 174 rv = configure_nss(kmfhandle, dir, prefix); 175 if (rv != KMF_OK) 176 return (rv); 177 178 if (token_spec == NULL) 179 token_spec = DEFAULT_NSS_TOKEN; 180 181 kstype = KMF_KEYSTORE_NSS; 182 kmf_set_attr_at_index(attrlist, numattr, 183 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 184 numattr++; 185 186 if (certlabel != NULL) { 187 kmf_set_attr_at_index(attrlist, numattr, 188 KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); 189 numattr++; 190 } 191 192 if (issuer != NULL) { 193 kmf_set_attr_at_index(attrlist, numattr, 194 KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer)); 195 numattr++; 196 } 197 198 if (subject != NULL) { 199 kmf_set_attr_at_index(attrlist, numattr, 200 KMF_SUBJECT_NAME_ATTR, subject, strlen(subject)); 201 numattr++; 202 } 203 204 if (serial != NULL) { 205 kmf_set_attr_at_index(attrlist, numattr, 206 KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT)); 207 numattr++; 208 } 209 210 if (tokencred != NULL) { 211 kmf_set_attr_at_index(attrlist, numattr, 212 KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); 213 numattr++; 214 } 215 216 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 217 token_spec, strlen(token_spec)); 218 numattr++; 219 220 (void) get_pk12_password(&p12cred); 221 kmf_set_attr_at_index(attrlist, numattr, 222 KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 223 numattr++; 224 225 kmf_set_attr_at_index(attrlist, numattr, 226 KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename)); 227 numattr++; 228 229 rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 230 231 if (p12cred.cred) 232 free(p12cred.cred); 233 234 return (rv); 235 } 236 237 static KMF_RETURN 238 pk_export_pk12_files(KMF_HANDLE_T kmfhandle, 239 char *certfile, char *keyfile, 240 char *outfile) 241 { 242 KMF_RETURN rv; 243 KMF_KEYSTORE_TYPE kstype; 244 KMF_CREDENTIAL p12cred = { NULL, 0}; 245 KMF_ATTRIBUTE attrlist[16]; 246 int numattr = 0; 247 248 kstype = KMF_KEYSTORE_OPENSSL; 249 kmf_set_attr_at_index(attrlist, numattr, 250 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 251 numattr++; 252 253 if (certfile != NULL) { 254 kmf_set_attr_at_index(attrlist, numattr, 255 KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile)); 256 numattr++; 257 } 258 259 if (keyfile != NULL) { 260 kmf_set_attr_at_index(attrlist, numattr, 261 KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile)); 262 numattr++; 263 } 264 265 (void) get_pk12_password(&p12cred); 266 kmf_set_attr_at_index(attrlist, numattr, 267 KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 268 numattr++; 269 270 kmf_set_attr_at_index(attrlist, numattr, 271 KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile)); 272 numattr++; 273 274 rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 275 276 if (p12cred.cred) 277 free(p12cred.cred); 278 279 return (rv); 280 } 281 282 static KMF_RETURN 283 pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 284 int oclass, char *certlabel, char *issuer, char *subject, 285 KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir, 286 char *prefix, char *filename) 287 { 288 KMF_RETURN rv = KMF_OK; 289 KMF_X509_DER_CERT kmfcert; 290 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 291 KMF_ATTRIBUTE attrlist[16]; 292 int numattr = 0; 293 294 rv = configure_nss(kmfhandle, dir, prefix); 295 if (rv != KMF_OK) 296 return (rv); 297 298 /* If searching for public objects or certificates, find certs now */ 299 if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) { 300 kmf_set_attr_at_index(attrlist, numattr, 301 KMF_KEYSTORE_TYPE_ATTR, &kstype, 302 sizeof (kstype)); 303 numattr++; 304 305 if (certlabel != NULL) { 306 kmf_set_attr_at_index(attrlist, numattr, 307 KMF_CERT_LABEL_ATTR, certlabel, 308 strlen(certlabel)); 309 numattr++; 310 } 311 312 if (issuer != NULL) { 313 kmf_set_attr_at_index(attrlist, numattr, 314 KMF_ISSUER_NAME_ATTR, issuer, 315 strlen(issuer)); 316 numattr++; 317 } 318 319 if (subject != NULL) { 320 kmf_set_attr_at_index(attrlist, numattr, 321 KMF_SUBJECT_NAME_ATTR, subject, 322 strlen(subject)); 323 numattr++; 324 } 325 326 if (serial != NULL) { 327 kmf_set_attr_at_index(attrlist, numattr, 328 KMF_BIGINT_ATTR, serial, 329 sizeof (KMF_BIGINT)); 330 numattr++; 331 } 332 333 if (token_spec != NULL) { 334 kmf_set_attr_at_index(attrlist, numattr, 335 KMF_TOKEN_LABEL_ATTR, token_spec, 336 strlen(token_spec)); 337 numattr++; 338 } 339 340 rv = pk_find_export_cert(kmfhandle, attrlist, numattr, 341 &kmfcert); 342 if (rv == KMF_OK) { 343 kstype = KMF_KEYSTORE_OPENSSL; 344 numattr = 0; 345 346 kmf_set_attr_at_index(attrlist, numattr, 347 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 348 numattr++; 349 350 kmf_set_attr_at_index(attrlist, numattr, 351 KMF_CERT_DATA_ATTR, &kmfcert.certificate, 352 sizeof (KMF_DATA)); 353 numattr++; 354 355 kmf_set_attr_at_index(attrlist, numattr, 356 KMF_CERT_FILENAME_ATTR, filename, 357 strlen(filename)); 358 numattr++; 359 360 kmf_set_attr_at_index(attrlist, numattr, 361 KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 362 numattr++; 363 364 rv = kmf_store_cert(kmfhandle, numattr, attrlist); 365 366 kmf_free_kmf_cert(kmfhandle, &kmfcert); 367 } 368 } 369 return (rv); 370 } 371 372 static KMF_RETURN 373 pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec, 374 char *certlabel, char *issuer, char *subject, 375 KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename) 376 { 377 KMF_RETURN rv = KMF_OK; 378 KMF_KEYSTORE_TYPE kstype; 379 KMF_CREDENTIAL p12cred = { NULL, 0}; 380 KMF_ATTRIBUTE attrlist[16]; 381 int numattr = 0; 382 383 rv = select_token(kmfhandle, token_spec, TRUE); 384 if (rv != KMF_OK) { 385 return (rv); 386 } 387 388 kstype = KMF_KEYSTORE_PK11TOKEN; 389 kmf_set_attr_at_index(attrlist, numattr, 390 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 391 numattr++; 392 393 if (certlabel != NULL) { 394 kmf_set_attr_at_index(attrlist, numattr, 395 KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); 396 numattr++; 397 } 398 399 if (issuer != NULL) { 400 kmf_set_attr_at_index(attrlist, numattr, 401 KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer)); 402 numattr++; 403 } 404 405 if (subject != NULL) { 406 kmf_set_attr_at_index(attrlist, numattr, 407 KMF_SUBJECT_NAME_ATTR, subject, strlen(subject)); 408 numattr++; 409 } 410 411 if (serial != NULL) { 412 kmf_set_attr_at_index(attrlist, numattr, 413 KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT)); 414 numattr++; 415 } 416 417 if (tokencred != NULL) { 418 kmf_set_attr_at_index(attrlist, numattr, 419 KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); 420 numattr++; 421 } 422 423 (void) get_pk12_password(&p12cred); 424 kmf_set_attr_at_index(attrlist, numattr, 425 KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 426 numattr++; 427 428 kmf_set_attr_at_index(attrlist, numattr, 429 KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename)); 430 numattr++; 431 432 rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 433 434 if (p12cred.cred) 435 free(p12cred.cred); 436 437 return (rv); 438 } 439 440 static KMF_RETURN 441 pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token, 442 KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format, 443 char *label, char *filename, int oclass) 444 { 445 KMF_RETURN rv = KMF_OK; 446 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 447 KMF_KEY_CLASS kclass = KMF_KEYCLASS_NONE; 448 int numattr = 0; 449 uint32_t numkeys = 1; 450 KMF_ATTRIBUTE attrlist[16]; 451 KMF_KEY_HANDLE key; 452 boolean_t is_token = B_TRUE; 453 454 if (EMPTYSTRING(label)) { 455 cryptoerror(LOG_STDERR, gettext("A label " 456 "must be specified to export a key.")); 457 return (KMF_ERR_BAD_PARAMETER); 458 } 459 460 rv = select_token(kmfhandle, token, TRUE); 461 if (rv != KMF_OK) { 462 return (rv); 463 } 464 465 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 466 &kstype, sizeof (kstype)); 467 numattr++; 468 469 if (cred != NULL) { 470 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 471 cred, sizeof (KMF_CREDENTIAL)); 472 numattr++; 473 } 474 475 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 476 label, strlen(label)); 477 numattr++; 478 479 kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 480 &numkeys, sizeof (numkeys)); 481 numattr++; 482 483 kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR, 484 &key, sizeof (key)); 485 numattr++; 486 487 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR, 488 &is_token, sizeof (is_token)); 489 numattr++; 490 491 kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 492 &format, sizeof (format)); 493 numattr++; 494 495 /* Check to see if we are exporting private or public only */ 496 if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ) 497 kclass = KMF_ASYM_PRI; 498 else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ) 499 kclass = KMF_ASYM_PUB; 500 else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ) 501 kclass = KMF_SYMMETRIC; 502 else /* only 1 key at a time can be exported here, so default to pri */ 503 kclass = KMF_ASYM_PRI; 504 505 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 506 &kclass, sizeof (kclass)); 507 numattr++; 508 509 rv = kmf_find_key(kmfhandle, numattr, attrlist); 510 /* 511 * If nothing found but caller wanted ALL keys, try symmetric 512 * this time. 513 */ 514 if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) { 515 kclass = KMF_SYMMETRIC; 516 rv = kmf_find_key(kmfhandle, numattr, attrlist); 517 } 518 /* 519 * If nothing found but caller wanted ALL keys, try asymmetric 520 * public this time. 521 */ 522 if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) { 523 kclass = KMF_ASYM_PUB; 524 rv = kmf_find_key(kmfhandle, numattr, attrlist); 525 } 526 if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) { 527 KMF_RAW_SYM_KEY rkey; 528 529 (void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 530 rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey); 531 if (rv == KMF_OK) { 532 int fd, n, total = 0; 533 534 fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600); 535 if (fd == -1) { 536 rv = KMF_ERR_OPEN_FILE; 537 goto done; 538 } 539 do { 540 n = write(fd, rkey.keydata.val + total, 541 rkey.keydata.len - total); 542 if (n < 0) { 543 if (errno == EINTR) 544 continue; 545 (void) close(fd); 546 rv = KMF_ERR_WRITE_FILE; 547 goto done; 548 } 549 total += n; 550 551 } while (total < rkey.keydata.len); 552 (void) close(fd); 553 } 554 done: 555 kmf_free_bigint(&rkey.keydata); 556 kmf_free_kmf_key(kmfhandle, &key); 557 } else if (rv == KMF_OK) { 558 KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL; 559 (void) printf(gettext("Found %d asymmetric keys\n"), numkeys); 560 561 numattr = 0; 562 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 563 &sslks, sizeof (sslks)); 564 numattr++; 565 566 kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR, 567 key.keyp, sizeof (KMF_RAW_KEY_DATA)); 568 numattr++; 569 570 kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 571 &format, sizeof (format)); 572 numattr++; 573 574 kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR, 575 filename, strlen(filename)); 576 numattr++; 577 578 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 579 &key.keyclass, sizeof (KMF_KEY_CLASS)); 580 numattr++; 581 582 rv = kmf_store_key(kmfhandle, numattr, attrlist); 583 kmf_free_kmf_key(kmfhandle, &key); 584 } 585 586 return (rv); 587 } 588 589 static KMF_RETURN 590 pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 591 char *certlabel, char *issuer, char *subject, 592 KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, 593 char *filename) 594 { 595 KMF_RETURN rv = KMF_OK; 596 KMF_X509_DER_CERT kmfcert; 597 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 598 int numattr = 0; 599 KMF_ATTRIBUTE attrlist[16]; 600 601 rv = select_token(kmfhandle, token_spec, TRUE); 602 603 if (rv != KMF_OK) { 604 return (rv); 605 } 606 607 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 608 &kstype, sizeof (kstype)); 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 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 and might be overwritten. */ 835 if (access(filename, F_OK) == 0) { 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 } else { 847 rv = verify_file(filename); 848 if (rv != KMF_OK) { 849 cryptoerror(LOG_STDERR, gettext("The file (%s) " 850 "cannot be created.\n"), filename); 851 return (PK_ERR_USAGE); 852 } 853 } 854 855 if (serstr != NULL) { 856 uchar_t *bytes = NULL; 857 size_t bytelen; 858 859 rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen); 860 if (rv != KMF_OK || bytes == NULL) { 861 (void) fprintf(stderr, gettext("serial number " 862 "must be specified as a hex number " 863 "(ex: 0x0102030405ffeeddee)\n")); 864 return (PK_ERR_USAGE); 865 } 866 serial.val = bytes; 867 serial.len = bytelen; 868 } 869 870 if ((kstype == KMF_KEYSTORE_PK11TOKEN || 871 kstype == KMF_KEYSTORE_NSS) && 872 (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) || 873 kfmt == KMF_FORMAT_PKCS12)) { 874 (void) get_token_password(kstype, token_spec, 875 &tokencred); 876 } 877 878 if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 879 cryptoerror(LOG_STDERR, gettext("Error initializing " 880 "KMF: 0x%02x\n"), rv); 881 return (rv); 882 } 883 884 switch (kstype) { 885 case KMF_KEYSTORE_PK11TOKEN: 886 if (kfmt == KMF_FORMAT_PKCS12) 887 rv = pk_export_pk12_pk11(kmfhandle, 888 token_spec, certlabel, 889 issuer, subject, 890 &serial, &tokencred, 891 filename); 892 else if ((oclass & PK_KEY_OBJ) || 893 kfmt == KMF_FORMAT_RAWKEY) 894 rv = pk_export_pk11_keys(kmfhandle, 895 token_spec, &tokencred, kfmt, 896 certlabel, filename, oclass); 897 else 898 rv = pk_export_pk11_objects(kmfhandle, 899 token_spec, certlabel, 900 issuer, subject, &serial, kfmt, 901 filename); 902 break; 903 case KMF_KEYSTORE_NSS: 904 if (dir == NULL) 905 dir = PK_DEFAULT_DIRECTORY; 906 if (kfmt == KMF_FORMAT_PKCS12) 907 rv = pk_export_pk12_nss(kmfhandle, 908 token_spec, dir, prefix, 909 certlabel, issuer, 910 subject, &serial, 911 &tokencred, filename); 912 else 913 rv = pk_export_nss_objects(kmfhandle, 914 token_spec, 915 oclass, certlabel, issuer, subject, 916 &serial, kfmt, dir, prefix, filename); 917 break; 918 case KMF_KEYSTORE_OPENSSL: 919 if (kfmt == KMF_FORMAT_PKCS12) 920 rv = pk_export_pk12_files(kmfhandle, 921 certfile, keyfile, filename); 922 else 923 rv = pk_export_file_objects(kmfhandle, oclass, 924 issuer, subject, &serial, 925 infile, filename); 926 break; 927 default: 928 rv = PK_ERR_USAGE; 929 break; 930 } 931 932 if (rv != KMF_OK) { 933 display_error(kmfhandle, rv, 934 gettext("Error exporting objects")); 935 } 936 937 if (serial.val != NULL) 938 free(serial.val); 939 940 (void) kmf_finalize(kmfhandle); 941 942 return (rv); 943 } 944