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 #include <stdio.h> 29 #include <string.h> 30 #include <ctype.h> 31 #include <malloc.h> 32 #include <libgen.h> 33 #include <errno.h> 34 #include <cryptoutil.h> 35 #include <security/cryptoki.h> 36 #include "common.h" 37 38 #include <kmfapi.h> 39 40 #define SET_VALUE(f, s) \ 41 kmfrv = f; \ 42 if (kmfrv != KMF_OK) { \ 43 cryptoerror(LOG_STDERR, \ 44 gettext("Failed to %s: 0x%02\n"), \ 45 s, kmfrv); \ 46 goto cleanup; \ 47 } 48 49 static KMF_RETURN 50 gencsr_pkcs11(KMF_HANDLE_T kmfhandle, 51 char *token, char *subject, char *altname, 52 KMF_GENERALNAMECHOICES alttype, int altcrit, 53 char *certlabel, KMF_KEY_ALG keyAlg, 54 int keylen, 55 uint16_t kubits, int kucrit, 56 KMF_ENCODE_FORMAT fmt, char *csrfile, 57 KMF_CREDENTIAL *tokencred) 58 { 59 KMF_RETURN kmfrv = KMF_OK; 60 KMF_CREATEKEYPAIR_PARAMS kp_params; 61 KMF_DELETEKEY_PARAMS dk_params; 62 KMF_KEY_HANDLE pubk, prik; 63 KMF_X509_NAME csrSubject; 64 KMF_CSR_DATA csr; 65 KMF_ALGORITHM_INDEX sigAlg; 66 KMF_DATA signedCsr = {NULL, 0}; 67 68 (void) memset(&csr, 0, sizeof (csr)); 69 (void) memset(&csrSubject, 0, sizeof (csrSubject)); 70 (void) memset(&kp_params, 0, sizeof (kp_params)); 71 72 if (keyAlg == KMF_DSA) 73 sigAlg = KMF_ALGID_SHA1WithDSA; 74 else 75 sigAlg = KMF_ALGID_MD5WithRSA; 76 77 78 /* If the subject name cannot be parsed, flag it now and exit */ 79 if ((kmfrv = KMF_DNParser(subject, &csrSubject)) != KMF_OK) { 80 return (kmfrv); 81 } 82 83 kp_params.kstype = KMF_KEYSTORE_PK11TOKEN; 84 kp_params.keylabel = certlabel; 85 kp_params.keylength = keylen; /* bits */ 86 kp_params.keytype = keyAlg; 87 kp_params.cred.cred = tokencred->cred; 88 kp_params.cred.credlen = tokencred->credlen; 89 90 /* Select a PKCS11 token */ 91 kmfrv = select_token(kmfhandle, token, FALSE); 92 if (kmfrv != KMF_OK) { 93 return (kmfrv); 94 } 95 96 kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk); 97 if (kmfrv != KMF_OK) { 98 return (kmfrv); 99 } 100 101 SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr), "keypair"); 102 103 SET_VALUE(KMF_SetCSRVersion(&csr, 2), "version number"); 104 105 SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject), 106 "subject name"); 107 108 SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg), 109 "SignatureAlgorithm"); 110 111 if (altname != NULL) { 112 SET_VALUE(KMF_SetCSRSubjectAltName(&csr, altname, altcrit, 113 alttype), "SetCSRSubjectAltName"); 114 } 115 116 if (kubits != 0) { 117 SET_VALUE(KMF_SetCSRKeyUsage(&csr, kucrit, kubits), 118 "SetCSRKeyUsage"); 119 } 120 121 if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) == 122 KMF_OK) { 123 kmfrv = KMF_CreateCSRFile(&signedCsr, fmt, csrfile); 124 } 125 126 cleanup: 127 (void) KMF_FreeData(&signedCsr); 128 (void) KMF_FreeKMFKey(kmfhandle, &prik); 129 /* delete the key */ 130 (void) memset(&dk_params, 0, sizeof (dk_params)); 131 dk_params.kstype = KMF_KEYSTORE_PK11TOKEN; 132 (void) KMF_DeleteKeyFromKeystore(kmfhandle, &dk_params, &pubk); 133 (void) KMF_FreeSignedCSR(&csr); 134 135 return (kmfrv); 136 } 137 138 static KMF_RETURN 139 gencsr_file(KMF_HANDLE_T kmfhandle, 140 KMF_KEY_ALG keyAlg, 141 int keylen, KMF_ENCODE_FORMAT fmt, 142 char *subject, char *altname, KMF_GENERALNAMECHOICES alttype, 143 int altcrit, uint16_t kubits, int kucrit, 144 char *dir, char *outcsr, char *outkey) 145 { 146 KMF_RETURN kmfrv; 147 KMF_CREATEKEYPAIR_PARAMS kp_params; 148 KMF_KEY_HANDLE pubk, prik; 149 KMF_X509_NAME csrSubject; 150 KMF_CSR_DATA csr; 151 KMF_ALGORITHM_INDEX sigAlg; 152 KMF_DATA signedCsr = {NULL, 0}; 153 char *fullcsrpath = NULL; 154 char *fullkeypath = NULL; 155 156 (void) memset(&csr, 0, sizeof (csr)); 157 (void) memset(&csrSubject, 0, sizeof (csrSubject)); 158 (void) memset(&kp_params, 0, sizeof (kp_params)); 159 160 if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) { 161 cryptoerror(LOG_STDERR, 162 gettext("No output file was specified for " 163 "the csr or key\n")); 164 return (KMF_ERR_BAD_PARAMETER); 165 } 166 if (dir != NULL) { 167 fullcsrpath = get_fullpath(dir, outcsr); 168 if (fullcsrpath == NULL) { 169 cryptoerror(LOG_STDERR, 170 gettext("Cannot create file %s in " 171 "directory %s\n"), dir, outcsr); 172 return (PK_ERR_USAGE); 173 } 174 } else { 175 fullcsrpath = strdup(outcsr); 176 } 177 if (verify_file(fullcsrpath)) { 178 cryptoerror(LOG_STDERR, 179 gettext("Cannot write the indicated output " 180 "certificate file (%s).\n"), fullcsrpath); 181 free(fullcsrpath); 182 return (PK_ERR_USAGE); 183 } 184 if (dir != NULL) { 185 fullkeypath = get_fullpath(dir, outkey); 186 if (fullkeypath == NULL) { 187 cryptoerror(LOG_STDERR, 188 gettext("Cannot create file %s in " 189 "directory %s\n"), dir, outkey); 190 free(fullcsrpath); 191 return (PK_ERR_USAGE); 192 } 193 } else { 194 fullkeypath = strdup(outkey); 195 } 196 if (verify_file(fullcsrpath)) { 197 cryptoerror(LOG_STDERR, 198 gettext("Cannot write the indicated output " 199 "key file (%s).\n"), fullkeypath); 200 free(fullcsrpath); 201 return (PK_ERR_USAGE); 202 } 203 204 if (keyAlg == KMF_DSA) 205 sigAlg = KMF_ALGID_SHA1WithDSA; 206 else 207 sigAlg = KMF_ALGID_MD5WithRSA; 208 209 /* If the subject name cannot be parsed, flag it now and exit */ 210 if ((kmfrv = KMF_DNParser(subject, &csrSubject)) != KMF_OK) { 211 return (kmfrv); 212 } 213 214 kp_params.kstype = KMF_KEYSTORE_OPENSSL; 215 kp_params.keylength = keylen; /* bits */ 216 kp_params.keytype = keyAlg; 217 218 kp_params.sslparms.keyfile = fullkeypath; 219 kp_params.sslparms.format = fmt; 220 221 kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk); 222 if (kmfrv != KMF_OK) { 223 goto cleanup; 224 } 225 SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr), 226 "SetCSRPubKey"); 227 228 SET_VALUE(KMF_SetCSRVersion(&csr, 2), "SetCSRVersion"); 229 230 SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject), 231 "SetCSRSubjectName"); 232 233 SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg), 234 "SetCSRSignatureAlgorithm"); 235 236 if (altname != NULL) { 237 SET_VALUE(KMF_SetCSRSubjectAltName(&csr, altname, altcrit, 238 alttype), "SetCSRSubjectAltName"); 239 } 240 if (kubits != NULL) { 241 SET_VALUE(KMF_SetCSRKeyUsage(&csr, kucrit, kubits), 242 "SetCSRKeyUsage"); 243 } 244 if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) == 245 KMF_OK) { 246 kmfrv = KMF_CreateCSRFile(&signedCsr, fmt, fullcsrpath); 247 } 248 249 cleanup: 250 if (fullkeypath) 251 free(fullkeypath); 252 if (fullcsrpath) 253 free(fullcsrpath); 254 255 KMF_FreeData(&signedCsr); 256 KMF_FreeKMFKey(kmfhandle, &prik); 257 KMF_FreeSignedCSR(&csr); 258 259 return (kmfrv); 260 } 261 262 static KMF_RETURN 263 gencsr_nss(KMF_HANDLE_T kmfhandle, 264 char *token, char *subject, char *altname, 265 KMF_GENERALNAMECHOICES alttype, int altcrit, 266 char *nickname, char *dir, char *prefix, 267 KMF_KEY_ALG keyAlg, int keylen, 268 uint16_t kubits, int kucrit, 269 KMF_ENCODE_FORMAT fmt, char *csrfile, 270 KMF_CREDENTIAL *tokencred) 271 { 272 KMF_RETURN kmfrv; 273 KMF_CREATEKEYPAIR_PARAMS kp_params; 274 KMF_KEY_HANDLE pubk, prik; 275 KMF_X509_NAME csrSubject; 276 KMF_CSR_DATA csr; 277 KMF_ALGORITHM_INDEX sigAlg; 278 KMF_DATA signedCsr = {NULL, 0}; 279 KMF_DELETEKEY_PARAMS dk_params; 280 281 if (token == NULL) 282 token = DEFAULT_NSS_TOKEN; 283 284 if (keyAlg == KMF_DSA) 285 sigAlg = KMF_ALGID_SHA1WithDSA; 286 else 287 sigAlg = KMF_ALGID_MD5WithRSA; 288 289 kmfrv = configure_nss(kmfhandle, dir, prefix); 290 if (kmfrv != KMF_OK) 291 return (kmfrv); 292 293 (void) memset(&csr, 0, sizeof (csr)); 294 (void) memset(&csrSubject, 0, sizeof (csrSubject)); 295 296 /* If the subject name cannot be parsed, flag it now and exit */ 297 if ((kmfrv = KMF_DNParser(subject, &csrSubject)) != KMF_OK) { 298 return (kmfrv); 299 } 300 301 (void) memset(&kp_params, 0, sizeof (kp_params)); 302 303 kp_params.kstype = KMF_KEYSTORE_NSS; 304 kp_params.keylabel = nickname; 305 kp_params.keylength = keylen; /* bits */ 306 kp_params.keytype = keyAlg; 307 kp_params.cred.cred = tokencred->cred; 308 kp_params.cred.credlen = tokencred->credlen; 309 kp_params.nssparms.slotlabel = token; 310 311 kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk); 312 if (kmfrv != KMF_OK) { 313 goto cleanup; 314 } 315 316 SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr), "SetCSRPubKey"); 317 SET_VALUE(KMF_SetCSRVersion(&csr, 2), "SetCSRVersion"); 318 SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject), 319 "SetCSRSubjectName"); 320 SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg), 321 "SetCSRSignatureAlgorithm"); 322 323 if (altname != NULL) { 324 SET_VALUE(KMF_SetCSRSubjectAltName(&csr, altname, altcrit, 325 alttype), "SetCSRSubjectAltName"); 326 } 327 if (kubits != NULL) { 328 SET_VALUE(KMF_SetCSRKeyUsage(&csr, kucrit, kubits), 329 "SetCSRKeyUsage"); 330 } 331 if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) == 332 KMF_OK) { 333 kmfrv = KMF_CreateCSRFile(&signedCsr, fmt, csrfile); 334 } 335 336 cleanup: 337 (void) KMF_FreeData(&signedCsr); 338 (void) KMF_FreeKMFKey(kmfhandle, &prik); 339 /* delete the key */ 340 (void) memset(&dk_params, 0, sizeof (dk_params)); 341 dk_params.kstype = KMF_KEYSTORE_NSS; 342 dk_params.cred.cred = tokencred->cred; 343 dk_params.cred.credlen = tokencred->credlen; 344 dk_params.nssparms.slotlabel = token; 345 (void) KMF_DeleteKeyFromKeystore(kmfhandle, &dk_params, &pubk); 346 (void) KMF_FreeSignedCSR(&csr); 347 348 return (kmfrv); 349 } 350 351 int 352 pk_gencsr(int argc, char *argv[]) 353 { 354 KMF_RETURN rv; 355 int opt; 356 extern int optind_av; 357 extern char *optarg_av; 358 KMF_KEYSTORE_TYPE kstype = 0; 359 char *subject = NULL; 360 char *tokenname = NULL; 361 char *dir = NULL; 362 char *prefix = NULL; 363 int keylen = PK_DEFAULT_KEYLENGTH; 364 char *certlabel = NULL; 365 char *outcsr = NULL; 366 char *outkey = NULL; 367 char *format = NULL; 368 char *altname = NULL; 369 char *kustr = NULL; 370 uint16_t kubits = 0; 371 char *keytype = PK_DEFAULT_KEYTYPE; 372 KMF_HANDLE_T kmfhandle = NULL; 373 KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1; 374 KMF_KEY_ALG keyAlg = KMF_RSA; 375 KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA; 376 boolean_t interactive = B_FALSE; 377 char *subname = NULL; 378 KMF_CREDENTIAL tokencred = {NULL, 0}; 379 KMF_GENERALNAMECHOICES alttype = 0; 380 int altcrit = 0, kucrit = 0; 381 382 while ((opt = getopt_av(argc, argv, 383 "ik:(keystore)s:(subject)n:(nickname)A:(altname)" 384 "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)" 385 "y:(keylen)l:(label)c:(outcsr)" 386 "K:(outkey)F:(format)")) != EOF) { 387 388 if (opt != 'i' && EMPTYSTRING(optarg_av)) 389 return (PK_ERR_USAGE); 390 391 switch (opt) { 392 case 'A': 393 altname = optarg_av; 394 break; 395 case 'i': 396 if (interactive || subject) 397 return (PK_ERR_USAGE); 398 else 399 interactive = B_TRUE; 400 break; 401 case 'k': 402 kstype = KS2Int(optarg_av); 403 if (kstype == 0) 404 return (PK_ERR_USAGE); 405 break; 406 case 's': 407 if (interactive || subject) 408 return (PK_ERR_USAGE); 409 else 410 subject = optarg_av; 411 break; 412 case 'l': 413 case 'n': 414 if (certlabel) 415 return (PK_ERR_USAGE); 416 certlabel = optarg_av; 417 break; 418 case 'T': 419 if (tokenname) 420 return (PK_ERR_USAGE); 421 tokenname = optarg_av; 422 break; 423 case 'd': 424 dir = optarg_av; 425 break; 426 case 'p': 427 if (prefix) 428 return (PK_ERR_USAGE); 429 prefix = optarg_av; 430 break; 431 case 't': 432 keytype = optarg_av; 433 break; 434 case 'u': 435 kustr = optarg_av; 436 break; 437 case 'y': 438 if (sscanf(optarg_av, "%d", 439 &keylen) != 1) { 440 cryptoerror(LOG_STDERR, 441 gettext("Unrecognized " 442 "key length (%s)\n"), 443 optarg_av); 444 return (PK_ERR_USAGE); 445 } 446 break; 447 case 'c': 448 if (outcsr) 449 return (PK_ERR_USAGE); 450 outcsr = optarg_av; 451 break; 452 case 'K': 453 if (outkey) 454 return (PK_ERR_USAGE); 455 outkey = optarg_av; 456 break; 457 case 'F': 458 if (format) 459 return (PK_ERR_USAGE); 460 format = optarg_av; 461 break; 462 default: 463 cryptoerror(LOG_STDERR, gettext( 464 "unrecognized gencsr option '%s'\n"), 465 argv[optind_av]); 466 return (PK_ERR_USAGE); 467 } 468 } 469 /* No additional args allowed. */ 470 argc -= optind_av; 471 argv += optind_av; 472 if (argc) { 473 return (PK_ERR_USAGE); 474 } 475 476 if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 477 cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); 478 return (PK_ERR_USAGE); 479 } 480 481 /* Assume keystore = PKCS#11 if not specified. */ 482 if (kstype == 0) 483 kstype = KMF_KEYSTORE_PK11TOKEN; 484 485 if (EMPTYSTRING(outcsr)) { 486 (void) printf(gettext("A filename must be specified to hold" 487 "the final certificate request data.\n")); 488 return (PK_ERR_USAGE); 489 } else { 490 /* 491 * verify that the outcsr file does not already exist 492 * and that it can be created. 493 */ 494 rv = verify_file(outcsr); 495 if (rv != KMF_OK) { 496 cryptoerror(LOG_STDERR, gettext("output file (%s) " 497 "cannot be created.\n"), outcsr); 498 return (PK_ERR_USAGE); 499 } 500 } 501 502 if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) && 503 EMPTYSTRING(certlabel)) { 504 cryptoerror(LOG_STDERR, gettext("A label must be specified " 505 "to create a certificate request.\n")); 506 return (PK_ERR_USAGE); 507 } else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outkey)) { 508 cryptoerror(LOG_STDERR, gettext("A key filename must be " 509 "specified to create a certificate request.\n")); 510 return (PK_ERR_USAGE); 511 } 512 513 if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) { 514 cryptoerror(LOG_STDERR, 515 gettext("Error parsing format string (%s).\n"), 516 format); 517 return (PK_ERR_USAGE); 518 } 519 if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) { 520 cryptoerror(LOG_STDERR, 521 gettext("CSR must be DER or PEM format.\n")); 522 return (PK_ERR_USAGE); 523 } 524 525 /* 526 * Check the subject name. 527 * If interactive is true, get it now interactively. 528 */ 529 if (interactive) { 530 if (get_subname(&subname) != KMF_OK) { 531 cryptoerror(LOG_STDERR, gettext("Failed to get the " 532 "subject name interactively.\n")); 533 return (PK_ERR_USAGE); 534 } 535 } else { 536 if (EMPTYSTRING(subject)) { 537 cryptoerror(LOG_STDERR, gettext("A subject name or " 538 "-i must be specified to create a certificate " 539 "request.\n")); 540 return (PK_ERR_USAGE); 541 } else { 542 subname = strdup(subject); 543 if (subname == NULL) { 544 cryptoerror(LOG_STDERR, 545 gettext("Out of memory.\n")); 546 return (PK_ERR_SYSTEM); 547 } 548 } 549 } 550 if (altname != NULL) { 551 rv = verify_altname(altname, &alttype, &altcrit); 552 if (rv != KMF_OK) { 553 cryptoerror(LOG_STDERR, gettext("Subject AltName " 554 "must be specified as a name=value pair. " 555 "See the man page for details.")); 556 goto end; 557 } else { 558 /* advance the altname past the '=' sign */ 559 char *p = strchr(altname, '='); 560 if (p != NULL) 561 altname = p + 1; 562 } 563 } 564 565 if (kustr != NULL) { 566 rv = verify_keyusage(kustr, &kubits, &kucrit); 567 if (rv != KMF_OK) { 568 cryptoerror(LOG_STDERR, gettext("KeyUsage " 569 "must be specified as a comma-separated list. " 570 "See the man page for details.")); 571 goto end; 572 } 573 } 574 if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) { 575 cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"), 576 keytype); 577 goto end; 578 } 579 580 if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) { 581 if (tokenname == NULL || !strlen(tokenname)) { 582 if (kstype == KMF_KEYSTORE_NSS) { 583 tokenname = "internal"; 584 } else { 585 tokenname = PK_DEFAULT_PK11TOKEN; 586 } 587 } 588 589 (void) get_token_password(kstype, tokenname, &tokencred); 590 } 591 592 if (kstype == KMF_KEYSTORE_NSS) { 593 if (dir == NULL) 594 dir = PK_DEFAULT_DIRECTORY; 595 596 rv = gencsr_nss(kmfhandle, 597 tokenname, subname, altname, alttype, altcrit, 598 certlabel, dir, prefix, 599 keyAlg, keylen, kubits, kucrit, 600 fmt, outcsr, &tokencred); 601 602 } else if (kstype == KMF_KEYSTORE_PK11TOKEN) { 603 rv = gencsr_pkcs11(kmfhandle, 604 tokenname, subname, altname, alttype, altcrit, 605 certlabel, keyAlg, keylen, 606 kubits, kucrit, fmt, outcsr, &tokencred); 607 608 } else if (kstype == KMF_KEYSTORE_OPENSSL) { 609 rv = gencsr_file(kmfhandle, 610 keyAlg, keylen, fmt, subname, altname, 611 alttype, altcrit, kubits, kucrit, 612 dir, outcsr, outkey); 613 } 614 615 end: 616 if (rv != KMF_OK) 617 display_error(kmfhandle, rv, 618 gettext("Error creating CSR or keypair")); 619 620 if (subname) 621 free(subname); 622 623 if (tokencred.cred != NULL) 624 free(tokencred.cred); 625 626 (void) KMF_Finalize(kmfhandle); 627 if (rv != KMF_OK) 628 return (PK_ERR_USAGE); 629 630 return (0); 631 } 632