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 contains the functions that are shared among 30 * the various services this tool will ultimately provide. 31 * The functions in this file return PKCS#11 CK_RV errors. 32 * Only one session and one login per token is supported 33 * at this time. 34 */ 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <ctype.h> 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 #include <fcntl.h> 43 #include <tzfile.h> 44 #include <cryptoutil.h> 45 #include <security/cryptoki.h> 46 #include <kmfapi.h> 47 48 #include "common.h" 49 50 /* Local status variables. */ 51 static boolean_t initialized = B_FALSE; 52 static boolean_t session_opened = B_FALSE; 53 static boolean_t logged_in = B_FALSE; 54 55 /* Supporting structures and global variables for getopt_av(). */ 56 typedef struct av_opts_s { 57 int shortnm; /* short name character */ 58 char *longnm; /* long name string, NOT terminated */ 59 int longnm_len; /* length of long name string */ 60 boolean_t has_arg; /* takes optional argument */ 61 } av_opts; 62 static av_opts *opts_av = NULL; 63 static const char *_save_optstr = NULL; 64 static int _save_numopts = 0; 65 66 int optind_av = 1; 67 char *optarg_av = NULL; 68 69 static void close_sess(CK_SESSION_HANDLE); 70 static void logout_token(CK_SESSION_HANDLE); 71 72 /* 73 * Perform PKCS#11 setup here. Currently only C_Initialize is required, 74 * along with setting/resetting state variables. 75 */ 76 CK_RV 77 init_pk11(void) 78 { 79 CK_RV rv = CKR_OK; 80 81 /* If C_Initialize() already called, nothing to do here. */ 82 if (initialized == B_TRUE) 83 return (CKR_OK); 84 85 /* Reset state variables because C_Initialize() not yet done. */ 86 session_opened = B_FALSE; 87 logged_in = B_FALSE; 88 89 /* Initialize PKCS#11 library. */ 90 if ((rv = C_Initialize(NULL_PTR)) != CKR_OK && 91 rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 92 return (rv); 93 } 94 95 initialized = B_TRUE; 96 return (CKR_OK); 97 } 98 99 /* 100 * Finalize PKCS#11 library and reset state variables. Open sessions, 101 * if any, are closed, and thereby any logins are logged out also. 102 */ 103 void 104 final_pk11(CK_SESSION_HANDLE sess) 105 { 106 107 /* If the library wasn't initialized, nothing to do here. */ 108 if (!initialized) 109 return; 110 111 /* Make sure the sesion is closed first. */ 112 close_sess(sess); 113 114 (void) C_Finalize(NULL); 115 initialized = B_FALSE; 116 } 117 118 /* 119 * Close PKCS#11 session and reset state variables. Any logins are 120 * logged out. 121 */ 122 static void 123 close_sess(CK_SESSION_HANDLE sess) 124 { 125 126 if (sess == NULL) { 127 return; 128 } 129 130 /* If session is already closed, nothing to do here. */ 131 if (!session_opened) 132 return; 133 134 /* Make sure user is logged out of token. */ 135 logout_token(sess); 136 137 (void) C_CloseSession(sess); 138 session_opened = B_FALSE; 139 } 140 141 /* 142 * Log user out of token and reset status variable. 143 */ 144 static void 145 logout_token(CK_SESSION_HANDLE sess) 146 { 147 148 if (sess == NULL) { 149 return; 150 } 151 152 /* If already logged out, nothing to do here. */ 153 if (!logged_in) 154 return; 155 156 (void) C_Logout(sess); 157 logged_in = B_FALSE; 158 } 159 160 /* 161 * Gets PIN from user. Caller needs to free the returned PIN when done. 162 * If two prompts are given, the PIN is confirmed with second prompt. 163 * Note that getphassphrase() may return data in static memory area. 164 */ 165 CK_RV 166 get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen) 167 { 168 char *save_phrase, *phrase1, *phrase2; 169 170 171 #ifdef DEBUG 172 if (getenv("TOKENPIN") != NULL) { 173 *pin = (CK_UTF8CHAR_PTR)strdup(getenv("TOKENPIN")); 174 *pinlen = strlen((char *)(*pin)); 175 return (CKR_OK); 176 } 177 #endif /* DEBUG */ 178 179 /* Prompt user for a PIN. */ 180 if (prompt1 == NULL) { 181 return (CKR_ARGUMENTS_BAD); 182 } 183 if ((phrase1 = getpassphrase(prompt1)) == NULL) { 184 return (CKR_FUNCTION_FAILED); 185 } 186 187 /* Duplicate 1st PIN in separate chunk of memory. */ 188 if ((save_phrase = strdup(phrase1)) == NULL) 189 return (CKR_HOST_MEMORY); 190 191 /* If second prompt given, PIN confirmation is requested. */ 192 if (prompt2 != NULL) { 193 if ((phrase2 = getpassphrase(prompt2)) == NULL) { 194 free(save_phrase); 195 return (CKR_FUNCTION_FAILED); 196 } 197 if (strcmp(save_phrase, phrase2) != 0) { 198 free(save_phrase); 199 return (CKR_PIN_INCORRECT); 200 } 201 } 202 203 *pin = (CK_UTF8CHAR_PTR)save_phrase; 204 *pinlen = strlen(save_phrase); 205 return (CKR_OK); 206 } 207 208 /* 209 * Gets yes/no response from user. If either no prompt is supplied, a 210 * default prompt is used. If not message for invalid input is supplied, 211 * a default will not be provided. If the user provides no response, 212 * the input default B_TRUE == yes, B_FALSE == no is returned. 213 * Otherwise, B_TRUE is returned for yes, and B_FALSE for no. 214 */ 215 boolean_t 216 yesno(char *prompt, char *invalid, boolean_t dflt) 217 { 218 char *response, buf[1024]; 219 char *yes = gettext("yes"); 220 char *no = gettext("no"); 221 222 223 #ifdef DEBUG 224 /* If debugging or testing, return TRUE and avoid prompting */ 225 if (getenv("TOKENPIN") != NULL) { 226 return (B_TRUE); 227 } 228 #endif /* DEBUG */ 229 230 if (prompt == NULL) 231 prompt = gettext("Enter (y)es or (n)o? "); 232 233 for (;;) { 234 /* Prompt user. */ 235 (void) printf("%s", prompt); 236 (void) fflush(stdout); 237 238 /* Get the response. */ 239 if ((response = fgets(buf, sizeof (buf), stdin)) == NULL) 240 break; /* go to default response */ 241 242 /* Skip any leading white space. */ 243 while (isspace(*response)) 244 response++; 245 if (*response == '\0') 246 break; /* go to default response */ 247 248 /* Is it valid input? Return appropriately. */ 249 if (strncasecmp(response, yes, 1) == 0) 250 return (B_TRUE); 251 if (strncasecmp(response, no, 1) == 0) 252 return (B_FALSE); 253 254 /* Indicate invalid input, and try again. */ 255 if (invalid != NULL) 256 (void) printf("%s", invalid); 257 } 258 return (dflt); 259 } 260 261 /* 262 * Gets the list of slots which have tokens in them. Keeps adjusting 263 * the size of the slot list buffer until the call is successful or an 264 * irrecoverable error occurs. 265 */ 266 CK_RV 267 get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count) 268 { 269 CK_ULONG tmp_count = 0; 270 CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR; 271 int rv = CKR_OK; 272 273 if (!initialized) 274 if ((rv = init_pk11()) != CKR_OK) 275 return (rv); 276 277 /* 278 * Get the slot count first because we don't know how many 279 * slots there are and how many of those slots even have tokens. 280 * Don't specify an arbitrary buffer size for the slot list; 281 * it may be too small (see section 11.5 of PKCS#11 spec). 282 * Also select only those slots that have tokens in them, 283 * because this tool has no need to know about empty slots. 284 */ 285 if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK) 286 return (rv); 287 288 if (tmp_count == 0) { 289 *slot_list = NULL_PTR; 290 *slot_count = 0; 291 return (CKR_OK); 292 } 293 294 /* Allocate initial space for the slot list. */ 295 if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count * 296 sizeof (CK_SLOT_ID))) == NULL) 297 return (CKR_HOST_MEMORY); 298 299 /* Then get the slot list itself. */ 300 for (;;) { 301 if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) { 302 *slot_list = tmp_list; 303 *slot_count = tmp_count; 304 break; 305 } 306 307 if (rv != CKR_BUFFER_TOO_SMALL) { 308 free(tmp_list); 309 break; 310 } 311 312 /* If the number of slots grew, try again. */ 313 if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list, 314 tmp_count * sizeof (CK_SLOT_ID))) == NULL) { 315 free(tmp_list); 316 rv = CKR_HOST_MEMORY; 317 break; 318 } 319 tmp_list = tmp2_list; 320 } 321 322 return (rv); 323 } 324 325 /* 326 * Breaks out the getopt-style option string into a structure that can be 327 * traversed later for calls to getopt_av(). Option string is NOT altered, 328 * but the struct fields point to locations within option string. 329 */ 330 static int 331 populate_opts(char *optstring) 332 { 333 int i; 334 av_opts *temp; 335 char *marker; 336 337 if (optstring == NULL || *optstring == '\0') 338 return (0); 339 340 /* 341 * This tries to imitate getopt(3c) Each option must conform to: 342 * <short name char> [ ':' ] [ '(' <long name string> ')' ] 343 * If long name is missing, the short name is used for long name. 344 */ 345 for (i = 0; *optstring != '\0'; i++) { 346 if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) : 347 realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) { 348 if (opts_av != NULL) 349 free(opts_av); 350 opts_av = NULL; 351 return (0); 352 } else { 353 opts_av = (av_opts *)temp; 354 } 355 356 (void) memset(&opts_av[i], 0, sizeof (av_opts)); 357 marker = optstring; /* may need optstring later */ 358 359 opts_av[i].shortnm = *marker++; /* set short name */ 360 361 if (*marker == ':') { /* check for opt arg */ 362 marker++; 363 opts_av[i].has_arg = B_TRUE; 364 } 365 366 if (*marker == '(') { /* check and set long name */ 367 marker++; 368 opts_av[i].longnm = marker; 369 opts_av[i].longnm_len = strcspn(marker, ")"); 370 optstring = marker + opts_av[i].longnm_len + 1; 371 } else { 372 /* use short name option character */ 373 opts_av[i].longnm = optstring; 374 opts_av[i].longnm_len = 1; 375 optstring = marker; 376 } 377 } 378 379 return (i); 380 } 381 382 /* 383 * getopt_av() is very similar to getopt(3c) in that the takes an option 384 * string, compares command line arguments for matches, and returns a single 385 * letter option when a match is found. However, getopt_av() differs from 386 * getopt(3c) by requiring that only longname options and values be found 387 * on the command line and all leading dashes are omitted. In other words, 388 * it tries to enforce only longname "option=value" arguments on the command 389 * line. Boolean options are not allowed either. 390 */ 391 int 392 getopt_av(int argc, char * const *argv, const char *optstring) 393 { 394 int i; 395 int len; 396 char *cur_option; 397 398 if (optind_av >= argc) 399 return (EOF); 400 401 /* First time or when optstring changes from previous one */ 402 if (_save_optstr != optstring) { 403 if (opts_av != NULL) 404 free(opts_av); 405 opts_av = NULL; 406 _save_optstr = optstring; 407 _save_numopts = populate_opts((char *)optstring); 408 } 409 410 for (i = 0; i < _save_numopts; i++) { 411 cur_option = argv[optind_av]; 412 413 if (strcmp(cur_option, "--") == 0) { 414 optind_av++; 415 break; 416 } 417 418 if (cur_option[0] == '-' && strlen(cur_option) == 2) { 419 len = 1; 420 cur_option++; /* remove "-" */ 421 } else { 422 len = strcspn(cur_option, "="); 423 } 424 425 if (len == opts_av[i].longnm_len && strncmp(cur_option, 426 opts_av[i].longnm, opts_av[i].longnm_len) == 0) { 427 /* matched */ 428 if (!opts_av[i].has_arg) { 429 optind_av++; 430 return (opts_av[i].shortnm); 431 } 432 433 /* needs optarg */ 434 if (cur_option[len] == '=') { 435 optarg_av = &(cur_option[len+1]); 436 optind_av++; 437 return (opts_av[i].shortnm); 438 } 439 440 optarg_av = NULL; 441 optind_av++; 442 return ((int)'?'); 443 } 444 } 445 446 return (EOF); 447 } 448 449 KMF_KEYSTORE_TYPE 450 KS2Int(char *keystore_str) 451 { 452 if (keystore_str == NULL) 453 return (0); 454 if (!strcasecmp(keystore_str, "pkcs11")) 455 return (KMF_KEYSTORE_PK11TOKEN); 456 else if (!strcasecmp(keystore_str, "nss")) 457 return (KMF_KEYSTORE_NSS); 458 else if (!strcasecmp(keystore_str, "file")) 459 return (KMF_KEYSTORE_OPENSSL); 460 else 461 return (0); 462 } 463 464 465 int 466 Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg) 467 { 468 if (algm == NULL) { 469 *sigAlg = KMF_ALGID_MD5WithRSA; 470 *ktype = KMF_RSA; 471 } else if (strcasecmp(algm, "DSA") == 0) { 472 *sigAlg = KMF_ALGID_SHA1WithDSA; 473 *ktype = KMF_DSA; 474 } else if (strcasecmp(algm, "RSA") == 0) { 475 *sigAlg = KMF_ALGID_MD5WithRSA; 476 *ktype = KMF_RSA; 477 } else { 478 return (-1); 479 } 480 return (0); 481 } 482 483 int 484 Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype) 485 { 486 if (algm == NULL) 487 *ktype = KMF_AES; 488 else if (strcasecmp(algm, "aes") == 0) 489 *ktype = KMF_AES; 490 else if (strcasecmp(algm, "arcfour") == 0) 491 *ktype = KMF_RC4; 492 else if (strcasecmp(algm, "des") == 0) 493 *ktype = KMF_DES; 494 else if (strcasecmp(algm, "3des") == 0) 495 *ktype = KMF_DES3; 496 else 497 return (-1); 498 499 return (0); 500 } 501 502 int 503 Str2Lifetime(char *ltimestr, uint32_t *ltime) 504 { 505 int num; 506 char timetok[6]; 507 508 if (ltimestr == NULL || !strlen(ltimestr)) { 509 /* default to 1 year lifetime */ 510 *ltime = SECSPERDAY * DAYSPERNYEAR; 511 return (0); 512 } 513 514 (void) memset(timetok, 0, sizeof (timetok)); 515 if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2) 516 return (-1); 517 518 if (!strcasecmp(timetok, "day") || 519 !strcasecmp(timetok, "days")) { 520 *ltime = num * SECSPERDAY; 521 } else if (!strcasecmp(timetok, "hour") || 522 !strcasecmp(timetok, "hours")) { 523 *ltime = num * SECSPERHOUR; 524 } else if (!strcasecmp(timetok, "year") || 525 !strcasecmp(timetok, "years")) { 526 *ltime = num * SECSPERDAY * DAYSPERNYEAR; 527 } else { 528 *ltime = 0; 529 return (-1); 530 } 531 532 return (0); 533 } 534 535 int 536 OT2Int(char *objclass) 537 { 538 char *c = NULL; 539 int retval = 0; 540 541 if (objclass == NULL) 542 return (-1); 543 544 c = strchr(objclass, ':'); 545 if (c != NULL) { 546 if (!strcasecmp(c, ":private")) 547 retval = PK_PRIVATE_OBJ; 548 else if (!strcasecmp(c, ":public")) 549 retval = PK_PUBLIC_OBJ; 550 else if (!strcasecmp(c, ":both")) 551 retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ; 552 else /* unrecognized option */ 553 return (-1); 554 555 *c = '\0'; 556 } 557 558 if (!strcasecmp(objclass, "public")) { 559 if (retval) 560 return (-1); 561 return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | 562 PK_PUBKEY_OBJ); 563 } else if (!strcasecmp(objclass, "private")) { 564 if (retval) 565 return (-1); 566 return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ); 567 } else if (!strcasecmp(objclass, "both")) { 568 if (retval) 569 return (-1); 570 return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ); 571 } else if (!strcasecmp(objclass, "cert")) { 572 return (retval | PK_CERT_OBJ); 573 } else if (!strcasecmp(objclass, "key")) { 574 if (retval == 0) /* return all keys */ 575 return (retval | PK_KEY_OBJ); 576 else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ)) 577 /* return all keys */ 578 return (retval | PK_KEY_OBJ); 579 else if (retval & PK_PUBLIC_OBJ) 580 /* Only return public keys */ 581 return (retval | PK_PUBKEY_OBJ); 582 else if (retval & PK_PRIVATE_OBJ) 583 /* Only return private keys */ 584 return (retval | PK_PRIKEY_OBJ); 585 } else if (!strcasecmp(objclass, "crl")) { 586 if (retval) 587 return (-1); 588 return (retval | PK_CRL_OBJ); 589 } 590 591 if (retval == 0) /* No matches found */ 592 retval = -1; 593 return (retval); 594 } 595 596 KMF_ENCODE_FORMAT 597 Str2Format(char *formstr) 598 { 599 if (formstr == NULL || !strcasecmp(formstr, "der")) 600 return (KMF_FORMAT_ASN1); 601 if (!strcasecmp(formstr, "pem")) 602 return (KMF_FORMAT_PEM); 603 if (!strcasecmp(formstr, "pkcs12")) 604 return (KMF_FORMAT_PKCS12); 605 606 return (KMF_FORMAT_UNDEF); 607 } 608 609 610 KMF_RETURN 611 select_token(void *kmfhandle, char *token, 612 int readonly) 613 { 614 KMF_RETURN rv = KMF_OK; 615 KMF_CONFIG_PARAMS config; 616 617 if (token == NULL) 618 return (KMF_ERR_BAD_PARAMETER); 619 620 (void) memset(&config, 0, sizeof (config)); 621 config.kstype = KMF_KEYSTORE_PK11TOKEN; 622 config.pkcs11config.label = token; 623 config.pkcs11config.readonly = readonly; 624 625 rv = KMF_ConfigureKeystore(kmfhandle, &config); 626 if (rv == KMF_ERR_TOKEN_SELECTED) 627 rv = KMF_OK; 628 return (rv); 629 } 630 631 632 KMF_RETURN 633 configure_nss(void *kmfhandle, char *dir, char *prefix) 634 { 635 KMF_RETURN rv = KMF_OK; 636 KMF_CONFIG_PARAMS config; 637 638 (void) memset(&config, 0, sizeof (config)); 639 config.kstype = KMF_KEYSTORE_NSS; 640 config.nssconfig.configdir = dir; 641 config.nssconfig.certPrefix = prefix; 642 config.nssconfig.keyPrefix = prefix; 643 config.nssconfig.secModName = NULL; 644 645 rv = KMF_ConfigureKeystore(kmfhandle, &config); 646 if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED) 647 rv = KMF_OK; 648 649 return (rv); 650 } 651 652 653 KMF_RETURN 654 get_pk12_password(KMF_CREDENTIAL *cred) 655 { 656 KMF_RETURN rv = KMF_OK; 657 char prompt[1024]; 658 659 /* 660 * Get the password to use for the PK12 encryption. 661 */ 662 (void) strlcpy(prompt, 663 gettext("Enter password to use for " 664 "accessing the PKCS12 file: "), 665 sizeof (prompt)); 666 667 if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 668 (ulong_t *)&cred->credlen) != CKR_OK) { 669 cred->cred = NULL; 670 cred->credlen = 0; 671 } 672 673 return (rv); 674 } 675 676 677 #define COUNTRY_PROMPT "Country Name (2 letter code) [US]:" 678 #define STATE_PROMPT "State or Province Name (full name) [Some-State]:" 679 #define LOCALITY_PROMPT "Locality Name (eg, city) []:" 680 #define ORG_PROMPT "Organization Name (eg, company) []:" 681 #define UNIT_PROMPT "Organizational Unit Name (eg, section) []:" 682 #define NAME_PROMPT "Common Name (eg, YOUR name) []:" 683 #define EMAIL_PROMPT "Email Address []:" 684 685 #define COUNTRY_DEFAULT "US" 686 #define STATE_DEFAULT "Some-State" 687 #define INVALID_INPUT "Invalid input; please re-enter ..." 688 689 #define SUBNAMESIZ 1024 690 #define RDN_MIN 1 691 #define RDN_MAX 64 692 #define COUNTRYNAME_MIN 2 693 #define COUNTRYNAME_MAX 2 694 695 static char * 696 get_input_string(char *prompt, char *default_str, int min_len, int max_len) 697 { 698 char buf[1024]; 699 char *response = NULL; 700 char *ret = NULL; 701 int len; 702 703 for (;;) { 704 (void) printf("\t%s", prompt); 705 (void) fflush(stdout); 706 707 response = fgets(buf, sizeof (buf), stdin); 708 if (response == NULL) { 709 if (default_str != NULL) { 710 ret = strdup(default_str); 711 } 712 break; 713 } 714 715 /* Skip any leading white space. */ 716 while (isspace(*response)) 717 response++; 718 if (*response == '\0') { 719 if (default_str != NULL) { 720 ret = strdup(default_str); 721 } 722 break; 723 } 724 725 len = strlen(response); 726 response[len-1] = '\0'; /* get rid of "LF" */ 727 len--; 728 if (len >= min_len && len <= max_len) { 729 ret = strdup(response); 730 break; 731 } 732 733 (void) printf("%s\n", INVALID_INPUT); 734 735 } 736 737 return (ret); 738 } 739 740 int 741 get_subname(char **result) 742 { 743 char *country = NULL; 744 char *state = NULL; 745 char *locality = NULL; 746 char *org = NULL; 747 char *unit = NULL; 748 char *name = NULL; 749 char *email = NULL; 750 char *subname = NULL; 751 752 (void) printf("Entering following fields for subject (a DN) ...\n"); 753 country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT, 754 COUNTRYNAME_MIN, COUNTRYNAME_MAX); 755 if (country == NULL) 756 return (-1); 757 758 state = get_input_string(STATE_PROMPT, STATE_DEFAULT, 759 RDN_MIN, RDN_MAX); 760 if (state == NULL) { 761 goto out; 762 } 763 764 locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX); 765 org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX); 766 unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX); 767 name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX); 768 email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX); 769 770 /* Now create a subject name from the input strings */ 771 if ((subname = malloc(SUBNAMESIZ)) == NULL) 772 goto out; 773 774 (void) memset(subname, 0, SUBNAMESIZ); 775 (void) strlcpy(subname, "C=", SUBNAMESIZ); 776 (void) strlcat(subname, country, SUBNAMESIZ); 777 (void) strlcat(subname, ", ", SUBNAMESIZ); 778 (void) strlcat(subname, "ST=", SUBNAMESIZ); 779 (void) strlcat(subname, state, SUBNAMESIZ); 780 781 if (locality) { 782 (void) strlcat(subname, ", ", SUBNAMESIZ); 783 (void) strlcat(subname, "L=", SUBNAMESIZ); 784 (void) strlcat(subname, locality, SUBNAMESIZ); 785 } 786 787 if (org) { 788 (void) strlcat(subname, ", ", SUBNAMESIZ); 789 (void) strlcat(subname, "O=", SUBNAMESIZ); 790 (void) strlcat(subname, org, SUBNAMESIZ); 791 } 792 793 if (unit) { 794 (void) strlcat(subname, ", ", SUBNAMESIZ); 795 (void) strlcat(subname, "OU=", SUBNAMESIZ); 796 (void) strlcat(subname, unit, SUBNAMESIZ); 797 } 798 799 if (name) { 800 (void) strlcat(subname, ", ", SUBNAMESIZ); 801 (void) strlcat(subname, "CN=", SUBNAMESIZ); 802 (void) strlcat(subname, name, SUBNAMESIZ); 803 } 804 805 if (email) { 806 (void) strlcat(subname, ", ", SUBNAMESIZ); 807 (void) strlcat(subname, "E=", SUBNAMESIZ); 808 (void) strlcat(subname, email, SUBNAMESIZ); 809 } 810 811 out: 812 if (country) 813 free(country); 814 if (state) 815 free(state); 816 if (locality) 817 free(locality); 818 if (org) 819 free(org); 820 if (unit) 821 free(unit); 822 if (name) 823 free(name); 824 if (email) 825 free(email); 826 827 if (subname == NULL) 828 return (-1); 829 else { 830 *result = subname; 831 return (0); 832 } 833 } 834 835 /* 836 * Parse a string of KeyUsage values and convert 837 * them to the correct KU Bits. 838 * The field may be marked "critical" by prepending 839 * "critical:" to the list. 840 * EX: critical:digitialSignature,keyEncipherment 841 */ 842 KMF_RETURN 843 verify_keyusage(char *kustr, uint16_t *kubits, int *critical) 844 { 845 KMF_RETURN ret = KMF_OK; 846 uint16_t kuval; 847 char *k; 848 849 *kubits = 0; 850 if (kustr == NULL || !strlen(kustr)) 851 return (KMF_ERR_BAD_PARAMETER); 852 853 /* Check to see if this is critical */ 854 if (!strncasecmp(kustr, "critical:", strlen("critical:"))) { 855 *critical = TRUE; 856 kustr += strlen("critical:"); 857 } else { 858 *critical = FALSE; 859 } 860 861 k = strtok(kustr, ","); 862 while (k != NULL) { 863 kuval = KMF_StringToKeyUsage(k); 864 if (kuval == 0) { 865 *kubits = 0; 866 return (KMF_ERR_BAD_PARAMETER); 867 } 868 *kubits |= kuval; 869 k = strtok(NULL, ","); 870 } 871 872 return (ret); 873 } 874 875 /* 876 * Verify the alternate subject label is real or invalid. 877 * 878 * The field may be marked "critical" by prepending 879 * "critical:" to the list. 880 * EX: "critical:IP=1.2.3.4" 881 */ 882 KMF_RETURN 883 verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical) 884 { 885 char *p; 886 KMF_RETURN rv = KMF_OK; 887 888 /* Check to see if this is critical */ 889 if (!strncasecmp(arg, "critical:", strlen("critical:"))) { 890 *critical = TRUE; 891 arg += strlen("critical:"); 892 } else { 893 *critical = FALSE; 894 } 895 896 /* Make sure there is an "=" sign */ 897 p = strchr(arg, '='); 898 if (p == NULL) 899 return (KMF_ERR_BAD_PARAMETER); 900 901 p[0] = '\0'; 902 903 if (strcmp(arg, "IP") == 0) 904 *type = GENNAME_IPADDRESS; 905 else if (strcmp(arg, "DNS") == 0) 906 *type = GENNAME_DNSNAME; 907 else if (strcmp(arg, "EMAIL") == 0) 908 *type = GENNAME_RFC822NAME; 909 else if (strcmp(arg, "URI") == 0) 910 *type = GENNAME_URI; 911 else if (strcmp(arg, "DN") == 0) 912 *type = GENNAME_DIRECTORYNAME; 913 else if (strcmp(arg, "RID") == 0) 914 *type = GENNAME_REGISTEREDID; 915 else 916 rv = KMF_ERR_BAD_PARAMETER; 917 918 p[0] = '='; 919 920 return (rv); 921 } 922 923 int 924 get_token_password(KMF_KEYSTORE_TYPE kstype, 925 char *token_spec, KMF_CREDENTIAL *cred) 926 { 927 char prompt[1024]; 928 char *p = NULL; 929 930 if (kstype == KMF_KEYSTORE_PK11TOKEN) { 931 p = strchr(token_spec, ':'); 932 if (p != NULL) 933 *p = 0; 934 } 935 /* 936 * Login to the token first. 937 */ 938 (void) snprintf(prompt, sizeof (prompt), 939 gettext(DEFAULT_TOKEN_PROMPT), 940 token_spec); 941 942 if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 943 (ulong_t *)&cred->credlen) != CKR_OK) { 944 cred->cred = NULL; 945 cred->credlen = 0; 946 } 947 948 if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL) 949 *p = ':'; 950 return (KMF_OK); 951 } 952 953 KMF_RETURN 954 verify_file(char *filename) 955 { 956 KMF_RETURN ret = KMF_OK; 957 int fd; 958 959 /* 960 * Attempt to open with the EXCL flag so that if 961 * it already exists, the open will fail. It will 962 * also fail if the file cannot be created due to 963 * permissions on the parent directory, or if the 964 * parent directory itself does not exist. 965 */ 966 fd = open(filename, O_CREAT | O_EXCL, 0600); 967 if (fd == -1) 968 return (KMF_ERR_OPEN_FILE); 969 970 /* If we were able to create it, delete it. */ 971 (void) close(fd); 972 (void) unlink(filename); 973 974 return (ret); 975 } 976 977 void 978 display_error(void *handle, KMF_RETURN errcode, char *prefix) 979 { 980 KMF_RETURN rv1, rv2; 981 char *plugin_errmsg = NULL; 982 char *kmf_errmsg = NULL; 983 984 rv1 = KMF_GetPluginErrorString(handle, &plugin_errmsg); 985 rv2 = KMF_GetKMFErrorString(errcode, &kmf_errmsg); 986 987 cryptoerror(LOG_STDERR, "%s:", prefix); 988 if (rv1 == KMF_OK && plugin_errmsg) { 989 cryptoerror(LOG_STDERR, 990 gettext("keystore error: %s"), 991 plugin_errmsg); 992 KMF_FreeString(plugin_errmsg); 993 } 994 995 if (rv2 == KMF_OK && kmf_errmsg) { 996 cryptoerror(LOG_STDERR, 997 gettext("libkmf error: %s"), 998 kmf_errmsg); 999 KMF_FreeString(kmf_errmsg); 1000 } 1001 1002 if (rv1 != KMF_OK && rv2 != KMF_OK) 1003 cryptoerror(LOG_STDERR, gettext("<unknown error>\n")); 1004 1005 } 1006