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 2006 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 import operation for this tool. 30 * The basic flow of the process is to decrypt the PKCS#12 31 * input file if it has a password, parse the elements in 32 * the file, find the soft token, log into it, import the 33 * PKCS#11 objects into the soft token, and log out. 34 */ 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <ctype.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include "common.h" 45 46 #include <kmfapi.h> 47 48 static KMF_RETURN 49 pk_import_pk12_files(KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *cred, 50 char *outfile, char *certfile, char *keyfile, 51 char *dir, char *keydir, KMF_ENCODE_FORMAT outformat) 52 { 53 KMF_RETURN rv = KMF_OK; 54 KMF_DATA *certs = NULL; 55 KMF_RAW_KEY_DATA *keys = NULL; 56 int ncerts = 0; 57 int nkeys = 0; 58 int i; 59 60 rv = KMF_ImportPK12(kmfhandle, outfile, cred, 61 &certs, &ncerts, &keys, &nkeys); 62 63 if (rv == KMF_OK) { 64 (void) printf(gettext("Found %d certificate(s) and %d " 65 "key(s) in %s\n"), ncerts, nkeys, outfile); 66 } 67 68 if (rv == KMF_OK && ncerts > 0) { 69 KMF_STORECERT_PARAMS params; 70 char newcertfile[MAXPATHLEN]; 71 72 (void) memset(¶ms, 0, sizeof (KMF_STORECERT_PARAMS)); 73 params.kstype = KMF_KEYSTORE_OPENSSL; 74 params.sslparms.dirpath = dir; 75 params.sslparms.format = outformat; 76 77 for (i = 0; rv == KMF_OK && i < ncerts; i++) { 78 /* 79 * If storing more than 1 cert, gotta change 80 * the name so we don't overwrite the previous one. 81 * Just append a _# to the name. 82 */ 83 if (i > 0) { 84 (void) snprintf(newcertfile, 85 sizeof (newcertfile), 86 "%s_%d", certfile, i); 87 params.sslparms.certfile = newcertfile; 88 } else { 89 params.sslparms.certfile = certfile; 90 } 91 rv = KMF_StoreCert(kmfhandle, ¶ms, &certs[i]); 92 } 93 } 94 if (rv == KMF_OK && nkeys > 0) { 95 KMF_STOREKEY_PARAMS skparms; 96 char newkeyfile[MAXPATHLEN]; 97 98 (void) memset(&skparms, 0, sizeof (skparms)); 99 100 /* The order of certificates and keys should match */ 101 for (i = 0; rv == KMF_OK && i < nkeys; i++) { 102 skparms.kstype = KMF_KEYSTORE_OPENSSL; 103 skparms.sslparms.dirpath = keydir; 104 skparms.sslparms.format = outformat; 105 skparms.cred = *cred; 106 skparms.certificate = &certs[i]; 107 108 if (i > 0) { 109 (void) snprintf(newkeyfile, 110 sizeof (newkeyfile), 111 "%s_%d", keyfile, i); 112 skparms.sslparms.keyfile = newkeyfile; 113 } else { 114 skparms.sslparms.keyfile = keyfile; 115 } 116 117 rv = KMF_StorePrivateKey(kmfhandle, &skparms, 118 &keys[i]); 119 } 120 } 121 /* 122 * Cleanup memory. 123 */ 124 if (certs) { 125 for (i = 0; i < ncerts; i++) 126 KMF_FreeData(&certs[i]); 127 free(certs); 128 } 129 if (keys) { 130 for (i = 0; i < nkeys; i++) 131 KMF_FreeRawKey(&keys[i]); 132 free(keys); 133 } 134 135 136 return (rv); 137 } 138 139 140 static KMF_RETURN 141 pk_import_pk12_nss( 142 KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *kmfcred, 143 KMF_CREDENTIAL *tokencred, 144 char *token_spec, char *dir, char *prefix, 145 char *nickname, char *trustflags, char *filename) 146 { 147 KMF_RETURN rv = KMF_OK; 148 KMF_DATA *certs = NULL; 149 KMF_RAW_KEY_DATA *keys = NULL; 150 int ncerts = 0; 151 int nkeys = 0; 152 int i; 153 154 rv = configure_nss(kmfhandle, dir, prefix); 155 if (rv != KMF_OK) 156 return (rv); 157 158 rv = KMF_ImportPK12(kmfhandle, filename, kmfcred, 159 &certs, &ncerts, &keys, &nkeys); 160 161 if (rv == KMF_OK) 162 (void) printf(gettext("Found %d certificate(s) and %d " 163 "key(s) in %s\n"), ncerts, nkeys, filename); 164 165 if (rv == KMF_OK) { 166 KMF_STORECERT_PARAMS params; 167 168 (void) memset(¶ms, 0, sizeof (KMF_STORECERT_PARAMS)); 169 params.kstype = KMF_KEYSTORE_NSS; 170 params.nssparms.slotlabel = token_spec; 171 params.nssparms.trustflag = trustflags; 172 173 for (i = 0; rv == KMF_OK && i < ncerts; i++) { 174 if (i == 0) 175 params.certLabel = nickname; 176 else 177 params.certLabel = NULL; 178 179 rv = KMF_StoreCert(kmfhandle, ¶ms, &certs[i]); 180 } 181 if (rv != KMF_OK) { 182 display_error(kmfhandle, rv, 183 gettext("Error storing certificate " 184 "in PKCS11 token")); 185 } 186 } 187 188 if (rv == KMF_OK) { 189 KMF_STOREKEY_PARAMS skparms; 190 191 /* The order of certificates and keys should match */ 192 for (i = 0; i < nkeys; i++) { 193 (void) memset(&skparms, 0, 194 sizeof (KMF_STOREKEY_PARAMS)); 195 skparms.kstype = KMF_KEYSTORE_NSS; 196 skparms.cred = *tokencred; 197 skparms.label = nickname; 198 skparms.certificate = &certs[i]; 199 skparms.nssparms.slotlabel = token_spec; 200 201 rv = KMF_StorePrivateKey(kmfhandle, &skparms, &keys[i]); 202 } 203 } 204 205 /* 206 * Cleanup memory. 207 */ 208 if (certs) { 209 for (i = 0; i < ncerts; i++) 210 KMF_FreeData(&certs[i]); 211 free(certs); 212 } 213 if (keys) { 214 for (i = 0; i < nkeys; i++) 215 KMF_FreeRawKey(&keys[i]); 216 free(keys); 217 } 218 219 return (rv); 220 } 221 222 static KMF_RETURN 223 pk_import_cert( 224 KMF_HANDLE_T kmfhandle, 225 KMF_KEYSTORE_TYPE kstype, 226 char *label, char *token_spec, char *filename, 227 char *dir, char *prefix, char *trustflags) 228 { 229 KMF_RETURN rv = KMF_OK; 230 KMF_IMPORTCERT_PARAMS params; 231 232 if (kstype == KMF_KEYSTORE_PK11TOKEN) { 233 rv = select_token(kmfhandle, token_spec, FALSE); 234 235 if (rv != KMF_OK) { 236 return (rv); 237 } 238 } 239 240 (void) memset(¶ms, 0, sizeof (params)); 241 params.kstype = kstype; 242 params.certfile = filename; 243 params.certLabel = label; 244 245 if (kstype == KMF_KEYSTORE_NSS) { 246 rv = configure_nss(kmfhandle, dir, prefix); 247 if (rv != KMF_OK) 248 return (rv); 249 params.nssparms.trustflag = trustflags; 250 params.nssparms.slotlabel = token_spec; 251 } 252 253 rv = KMF_ImportCert(kmfhandle, ¶ms); 254 255 return (rv); 256 } 257 258 static KMF_RETURN 259 pk_import_file_crl(void *kmfhandle, 260 char *infile, 261 char *outfile, 262 char *outdir, 263 KMF_ENCODE_FORMAT outfmt) 264 { 265 KMF_IMPORTCRL_PARAMS icrl_params; 266 KMF_OPENSSL_PARAMS sslparams; 267 268 sslparams.crlfile = infile; 269 sslparams.dirpath = outdir; 270 sslparams.outcrlfile = outfile; 271 sslparams.format = outfmt; 272 sslparams.crl_check = B_FALSE; 273 274 icrl_params.kstype = KMF_KEYSTORE_OPENSSL; 275 icrl_params.sslparms = sslparams; 276 277 return (KMF_ImportCRL(kmfhandle, &icrl_params)); 278 279 } 280 281 static KMF_RETURN 282 pk_import_nss_crl(void *kmfhandle, 283 boolean_t verify_crl_flag, 284 char *infile, 285 char *outdir, 286 char *prefix) 287 { 288 KMF_IMPORTCRL_PARAMS icrl_params; 289 KMF_RETURN rv; 290 291 rv = configure_nss(kmfhandle, outdir, prefix); 292 if (rv != KMF_OK) 293 return (rv); 294 295 icrl_params.kstype = KMF_KEYSTORE_NSS; 296 icrl_params.nssparms.slotlabel = NULL; 297 icrl_params.nssparms.crlfile = infile; 298 icrl_params.nssparms.crl_check = verify_crl_flag; 299 300 return (KMF_ImportCRL(kmfhandle, &icrl_params)); 301 302 } 303 304 static KMF_RETURN 305 pk_import_pk12_pk11( 306 KMF_HANDLE_T kmfhandle, 307 KMF_CREDENTIAL *p12cred, 308 KMF_CREDENTIAL *tokencred, 309 char *label, char *token_spec, 310 char *filename) 311 { 312 KMF_RETURN rv = KMF_OK; 313 KMF_DATA *certs = NULL; 314 KMF_RAW_KEY_DATA *keys = NULL; 315 int ncerts = 0; 316 int nkeys = 0; 317 int i; 318 319 rv = select_token(kmfhandle, token_spec, FALSE); 320 321 if (rv != KMF_OK) { 322 return (rv); 323 } 324 325 rv = KMF_ImportPK12(kmfhandle, filename, p12cred, 326 &certs, &ncerts, &keys, &nkeys); 327 328 if (rv == KMF_OK) { 329 KMF_STOREKEY_PARAMS skparms; 330 331 /* The order of certificates and keys should match */ 332 for (i = 0; i < nkeys; i++) { 333 (void) memset(&skparms, 0, 334 sizeof (KMF_STOREKEY_PARAMS)); 335 skparms.kstype = KMF_KEYSTORE_PK11TOKEN; 336 skparms.certificate = &certs[i]; 337 if (tokencred != NULL) 338 skparms.cred = *tokencred; 339 if (i == 0) 340 skparms.label = label; 341 else 342 skparms.label = NULL; 343 344 rv = KMF_StorePrivateKey(kmfhandle, &skparms, 345 &keys[i]); 346 } 347 } 348 349 if (rv == KMF_OK) { 350 KMF_STORECERT_PARAMS params; 351 352 (void) printf(gettext("Found %d certificate(s) and %d " 353 "key(s) in %s\n"), ncerts, nkeys, filename); 354 (void) memset(¶ms, 0, sizeof (KMF_STORECERT_PARAMS)); 355 356 params.kstype = KMF_KEYSTORE_PK11TOKEN; 357 358 for (i = 0; rv == KMF_OK && i < ncerts; i++) { 359 if (i == 0) 360 params.certLabel = label; 361 else 362 params.certLabel = NULL; 363 364 rv = KMF_StoreCert(kmfhandle, ¶ms, &certs[i]); 365 } 366 } 367 368 /* 369 * Cleanup memory. 370 */ 371 if (certs) { 372 for (i = 0; i < ncerts; i++) 373 KMF_FreeData(&certs[i]); 374 free(certs); 375 } 376 if (keys) { 377 for (i = 0; i < nkeys; i++) 378 KMF_FreeRawKey(&keys[i]); 379 free(keys); 380 } 381 382 return (rv); 383 } 384 385 /* 386 * Import objects from into KMF repositories. 387 */ 388 int 389 pk_import(int argc, char *argv[]) 390 { 391 int opt; 392 extern int optind_av; 393 extern char *optarg_av; 394 char *token_spec = NULL; 395 char *filename = NULL; 396 char *keyfile = NULL; 397 char *certfile = NULL; 398 char *crlfile = NULL; 399 char *certlabel = NULL; 400 char *dir = NULL; 401 char *keydir = NULL; 402 char *prefix = NULL; 403 char *trustflags = NULL; 404 char *verify_crl = NULL; 405 boolean_t verify_crl_flag = B_FALSE; 406 int oclass = 0; 407 KMF_KEYSTORE_TYPE kstype = 0; 408 KMF_ENCODE_FORMAT kfmt = 0; 409 KMF_ENCODE_FORMAT okfmt = KMF_FORMAT_ASN1; 410 KMF_RETURN rv = KMF_OK; 411 KMF_CREDENTIAL pk12cred = { NULL, 0 }; 412 KMF_CREDENTIAL tokencred = { NULL, 0 }; 413 KMF_HANDLE_T kmfhandle = NULL; 414 415 /* Parse command line options. Do NOT i18n/l10n. */ 416 while ((opt = getopt_av(argc, argv, 417 "T:(token)i:(infile)" 418 "k:(keystore)y:(objtype)" 419 "d:(dir)p:(prefix)" 420 "n:(certlabel)N:(label)" 421 "K:(outkey)c:(outcert)" 422 "v:(verifycrl)l:(outcrl)" 423 "t:(trust)D:(keydir)F:(outformat)")) != EOF) { 424 if (EMPTYSTRING(optarg_av)) 425 return (PK_ERR_USAGE); 426 switch (opt) { 427 case 'T': /* token specifier */ 428 if (token_spec) 429 return (PK_ERR_USAGE); 430 token_spec = optarg_av; 431 break; 432 case 'c': /* output cert file name */ 433 if (certfile) 434 return (PK_ERR_USAGE); 435 certfile = optarg_av; 436 break; 437 case 'l': /* output CRL file name */ 438 if (crlfile) 439 return (PK_ERR_USAGE); 440 crlfile = optarg_av; 441 break; 442 case 'K': /* output key file name */ 443 if (keyfile) 444 return (PK_ERR_USAGE); 445 keyfile = optarg_av; 446 break; 447 case 'i': /* input file name */ 448 if (filename) 449 return (PK_ERR_USAGE); 450 filename = optarg_av; 451 break; 452 case 'k': 453 kstype = KS2Int(optarg_av); 454 if (kstype == 0) 455 return (PK_ERR_USAGE); 456 break; 457 case 'y': 458 oclass = OT2Int(optarg_av); 459 if (oclass == -1) 460 return (PK_ERR_USAGE); 461 break; 462 case 'd': 463 dir = optarg_av; 464 break; 465 case 'D': 466 keydir = optarg_av; 467 break; 468 case 'p': 469 if (prefix) 470 return (PK_ERR_USAGE); 471 prefix = optarg_av; 472 break; 473 case 'n': 474 case 'N': 475 if (certlabel) 476 return (PK_ERR_USAGE); 477 certlabel = optarg_av; 478 break; 479 case 'F': 480 okfmt = Str2Format(optarg_av); 481 if (okfmt == KMF_FORMAT_UNDEF) 482 return (PK_ERR_USAGE); 483 break; 484 case 't': 485 if (trustflags) 486 return (PK_ERR_USAGE); 487 trustflags = optarg_av; 488 break; 489 case 'v': 490 verify_crl = optarg_av; 491 if (tolower(verify_crl[0]) == 'y') 492 verify_crl_flag = B_TRUE; 493 else if (tolower(verify_crl[0]) == 'n') 494 verify_crl_flag = B_FALSE; 495 else 496 return (PK_ERR_USAGE); 497 break; 498 default: 499 return (PK_ERR_USAGE); 500 break; 501 } 502 } 503 504 /* Assume keystore = PKCS#11 if not specified */ 505 if (kstype == 0) 506 kstype = KMF_KEYSTORE_PK11TOKEN; 507 508 /* Filename arg is required. */ 509 if (EMPTYSTRING(filename)) { 510 cryptoerror(LOG_STDERR, gettext("The 'infile' parameter" 511 "is required for the import operation.\n")); 512 return (PK_ERR_USAGE); 513 } 514 515 /* No additional args allowed. */ 516 argc -= optind_av; 517 argv += optind_av; 518 if (argc) 519 return (PK_ERR_USAGE); 520 521 /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */ 522 if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) && 523 kstype != KMF_KEYSTORE_PK11TOKEN) { 524 525 (void) fprintf(stderr, gettext("The objtype parameter " 526 "is only relevant if keystore=pkcs11\n")); 527 return (PK_ERR_USAGE); 528 } 529 530 /* 531 * You must specify a certlabel (cert label) when importing 532 * into NSS or PKCS#11. 533 */ 534 if (kstype == KMF_KEYSTORE_NSS && 535 (oclass != PK_CRL_OBJ) && EMPTYSTRING(certlabel)) { 536 cryptoerror(LOG_STDERR, gettext("The 'label' argument " 537 "is required for this operation\n")); 538 return (PK_ERR_USAGE); 539 } 540 541 /* 542 * PKCS11 only imports PKCS#12 files or PEM/DER Cert files. 543 */ 544 if (kstype == KMF_KEYSTORE_PK11TOKEN) { 545 /* we do not import private keys except in PKCS12 bundles */ 546 if (oclass & (PK_PRIVATE_OBJ | PK_PRIKEY_OBJ)) { 547 cryptoerror(LOG_STDERR, gettext( 548 "The PKCS11 keystore only imports PKCS12 " 549 "files or raw certificate data files " 550 " or CRL file.\n")); 551 return (PK_ERR_USAGE); 552 } 553 } 554 555 if ((rv = KMF_GetFileFormat(filename, &kfmt)) != KMF_OK) { 556 cryptoerror(LOG_STDERR, 557 gettext("File format not recognized.")); 558 return (rv); 559 } 560 if (oclass == 0 && (kfmt == KMF_FORMAT_ASN1 || 561 kfmt == KMF_FORMAT_PEM)) 562 oclass = PK_CERT_OBJ; 563 564 if (kstype == KMF_KEYSTORE_NSS) { 565 if (oclass == PK_CRL_OBJ && 566 (kfmt != KMF_FORMAT_ASN1 && kfmt != KMF_FORMAT_PEM)) { 567 cryptoerror(LOG_STDERR, gettext( 568 "CRL data can only be imported as DER or " 569 "PEM format")); 570 return (PK_ERR_USAGE); 571 } 572 573 if (oclass == PK_CERT_OBJ && 574 (kfmt != KMF_FORMAT_ASN1 && kfmt != KMF_FORMAT_PEM)) { 575 cryptoerror(LOG_STDERR, gettext( 576 "Certificates can only be imported as DER or " 577 "PEM format")); 578 return (PK_ERR_USAGE); 579 } 580 581 /* we do not import private keys except in PKCS12 bundles */ 582 if (oclass & (PK_PRIVATE_OBJ | PK_PRIKEY_OBJ)) { 583 cryptoerror(LOG_STDERR, gettext( 584 "Private key data can only be imported as part " 585 "of a PKCS12 file.\n")); 586 return (PK_ERR_USAGE); 587 } 588 } 589 590 if (kstype == KMF_KEYSTORE_OPENSSL && oclass != PK_CRL_OBJ) { 591 if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) { 592 cryptoerror(LOG_STDERR, gettext( 593 "The 'outkey' and 'outcert' parameters " 594 "are required for the import operation " 595 "when the 'file' keystore is used.\n")); 596 return (PK_ERR_USAGE); 597 } 598 } 599 600 if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) 601 token_spec = PK_DEFAULT_PK11TOKEN; 602 else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) 603 token_spec = DEFAULT_NSS_TOKEN; 604 605 if (kfmt == KMF_FORMAT_PKCS12) { 606 (void) get_pk12_password(&pk12cred); 607 608 if (kstype == KMF_KEYSTORE_PK11TOKEN || 609 kstype == KMF_KEYSTORE_NSS) 610 (void) get_token_password(kstype, token_spec, 611 &tokencred); 612 } 613 614 if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 615 cryptoerror(LOG_STDERR, gettext("Error initializing " 616 "KMF: 0x%02x\n"), rv); 617 goto end; 618 } 619 620 switch (kstype) { 621 case KMF_KEYSTORE_PK11TOKEN: 622 if (kfmt == KMF_FORMAT_PKCS12) 623 rv = pk_import_pk12_pk11( 624 kmfhandle, 625 &pk12cred, 626 &tokencred, 627 certlabel, 628 token_spec, 629 filename); 630 else if (oclass == PK_CERT_OBJ) 631 rv = pk_import_cert( 632 kmfhandle, 633 kstype, 634 certlabel, 635 token_spec, 636 filename, 637 NULL, NULL, NULL); 638 else if (oclass == PK_CRL_OBJ) 639 rv = pk_import_file_crl( 640 kmfhandle, 641 filename, 642 crlfile, 643 dir, 644 okfmt); 645 break; 646 case KMF_KEYSTORE_NSS: 647 if (dir == NULL) 648 dir = PK_DEFAULT_DIRECTORY; 649 if (kfmt == KMF_FORMAT_PKCS12) 650 rv = pk_import_pk12_nss( 651 kmfhandle, &pk12cred, 652 &tokencred, 653 token_spec, dir, prefix, 654 certlabel, trustflags, filename); 655 else if (oclass == PK_CERT_OBJ) { 656 rv = pk_import_cert( 657 kmfhandle, kstype, 658 certlabel, token_spec, 659 filename, dir, prefix, trustflags); 660 } else if (oclass == PK_CRL_OBJ) { 661 rv = pk_import_nss_crl( 662 kmfhandle, 663 verify_crl_flag, 664 filename, 665 dir, 666 prefix); 667 } 668 break; 669 case KMF_KEYSTORE_OPENSSL: 670 if (kfmt == KMF_FORMAT_PKCS12) 671 rv = pk_import_pk12_files( 672 kmfhandle, &pk12cred, 673 filename, certfile, keyfile, 674 dir, keydir, okfmt); 675 else if (oclass == PK_CRL_OBJ) { 676 rv = pk_import_file_crl( 677 kmfhandle, 678 filename, 679 crlfile, 680 dir, 681 okfmt); 682 } else 683 /* 684 * It doesn't make sense to import anything 685 * else for the files plugin. 686 */ 687 return (PK_ERR_USAGE); 688 break; 689 default: 690 rv = PK_ERR_USAGE; 691 break; 692 } 693 694 end: 695 if (rv != KMF_OK) 696 display_error(kmfhandle, rv, 697 gettext("Error importing objects")); 698 699 if (tokencred.cred != NULL) 700 free(tokencred.cred); 701 702 if (pk12cred.cred != NULL) 703 free(pk12cred.cred); 704 705 (void) KMF_Finalize(kmfhandle); 706 707 if (rv != KMF_OK) 708 return (PK_ERR_USAGE); 709 710 return (0); 711 } 712