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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file contains the functions that are shared among 31 * the various services this tool will ultimately provide. 32 * The functions in this file return PKCS#11 CK_RV errors. 33 * Only one session and one login per token is supported 34 * at this time. 35 */ 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <ctype.h> 41 #include <cryptoutil.h> 42 #include <security/cryptoki.h> 43 #include "common.h" 44 #include "biginteger.h" 45 46 /* True and false for attribute templates. */ 47 CK_BBOOL pk_true = B_TRUE; 48 CK_BBOOL pk_false = B_FALSE; 49 50 /* Local status variables. */ 51 static boolean_t initialized = B_FALSE; 52 static boolean_t session_opened = B_FALSE; 53 static boolean_t session_writable = B_FALSE; 54 static boolean_t logged_in = B_FALSE; 55 56 /* Supporting structures and global variables for getopt_av(). */ 57 typedef struct av_opts_s { 58 int shortnm; /* short name character */ 59 char *longnm; /* long name string, NOT terminated */ 60 int longnm_len; /* length of long name string */ 61 boolean_t has_arg; /* takes optional argument */ 62 } av_opts; 63 static av_opts *opts_av = NULL; 64 static const char *_save_optstr = NULL; 65 static int _save_numopts = 0; 66 67 int optind_av = 1; 68 char *optarg_av = NULL; 69 70 /* 71 * Perform PKCS#11 setup here. Currently only C_Initialize is required, 72 * along with setting/resetting state variables. 73 */ 74 CK_RV 75 init_pk11(void) 76 { 77 CK_RV rv = CKR_OK; 78 79 cryptodebug("inside init_pk11"); 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 session_writable = B_FALSE; 88 logged_in = B_FALSE; 89 90 /* Initialize PKCS#11 library. */ 91 cryptodebug("calling C_Initialize()"); 92 if ((rv = C_Initialize(NULL_PTR)) != CKR_OK && 93 rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 94 return (rv); 95 } 96 97 initialized = B_TRUE; 98 return (CKR_OK); 99 } 100 101 /* 102 * Finalize PKCS#11 library and reset state variables. Open sessions, 103 * if any, are closed, and thereby any logins are logged out also. 104 */ 105 void 106 final_pk11(CK_SESSION_HANDLE sess) 107 { 108 cryptodebug("inside final_pk11"); 109 110 /* If the library wasn't initialized, nothing to do here. */ 111 if (!initialized) 112 return; 113 114 /* Make sure the sesion is closed first. */ 115 close_sess(sess); 116 117 cryptodebug("calling C_Finalize()"); 118 (void) C_Finalize(NULL); 119 initialized = B_FALSE; 120 } 121 122 /* 123 * Create a PKCS#11 session on the given slot, and set state information. 124 * If session is already open, check that the read-only/read-write state 125 * requested matches that of the session. If it doesn't, make it so. 126 */ 127 CK_RV 128 open_sess(CK_SLOT_ID slot_id, CK_FLAGS sess_flags, CK_SESSION_HANDLE_PTR sess) 129 { 130 CK_RV rv = CKR_OK; 131 132 cryptodebug("inside open_sess"); 133 134 /* If the session is already open, check the session flags. */ 135 if (session_opened) { 136 /* 137 * If requesting R/W session and it is currently R/O, 138 * need to close the session and reopen it R/W. The 139 * other cases are considered acceptable: 140 * sess_flags current state 141 * ---------- ------------- 142 * ~CKF_RW_SESSION !session_writable 143 * ~CKF_RW_SESSION session_writable 144 * CKF_RW_SESSION session_writable 145 */ 146 if ((sess_flags & CKF_RW_SESSION) && !session_writable) 147 close_sess(*sess); 148 else 149 return (CKR_OK); 150 } 151 152 /* Make sure the PKCS#11 is already initialized. */ 153 if (!initialized) 154 if ((rv = init_pk11()) != CKR_OK) 155 return (rv); 156 157 /* Create a session for subsequent operations. */ 158 cryptodebug("calling C_OpenSession()"); 159 if ((rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION|sess_flags, 160 NULL, NULL, sess)) != CKR_OK) 161 return (rv); 162 session_opened = B_TRUE; 163 session_writable = (sess_flags & CKF_RW_SESSION) ? B_TRUE : B_FALSE; 164 return (CKR_OK); 165 } 166 167 /* 168 * Close PKCS#11 session and reset state variables. Any logins are 169 * logged out. 170 */ 171 void 172 close_sess(CK_SESSION_HANDLE sess) 173 { 174 cryptodebug("inside close_sess"); 175 176 if (sess == NULL) { 177 cryptodebug("session handle is null"); 178 return; 179 } 180 181 /* If session is already closed, nothing to do here. */ 182 session_writable = B_FALSE; 183 if (!session_opened) 184 return; 185 186 /* Make sure user is logged out of token. */ 187 logout_token(sess); 188 189 cryptodebug("calling C_CloseSession()"); 190 (void) C_CloseSession(sess); 191 session_opened = B_FALSE; 192 } 193 194 /* 195 * Log user into token in given slot. If this first login ever for this 196 * token, the initial PIN is "changeme", C_Login() will succeed, but all 197 * PKCS#11 calls following the C_Login() will fail with CKR_PIN_EXPIRED. 198 */ 199 CK_RV 200 login_token(CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG pinlen, 201 CK_SESSION_HANDLE_PTR sess) 202 { 203 CK_RV rv = CKR_OK; 204 205 cryptodebug("inside login_token"); 206 207 /* If already logged in, nothing to do here. */ 208 if (logged_in) 209 return (CKR_OK); 210 211 /* Make sure we have a session first, assume R/O is enough. */ 212 if (!session_opened) 213 if ((rv = open_sess(slot_id, CKF_SERIAL_SESSION, sess)) != 214 CKR_OK) 215 return (rv); 216 217 /* Log the user into the token. */ 218 cryptodebug("calling C_Login()"); 219 if ((rv = C_Login(*sess, CKU_USER, pin, pinlen)) != CKR_OK) { 220 cryptodebug("C_Login returns %s", pkcs11_strerror(rv)); 221 return (rv); 222 } 223 224 logged_in = B_TRUE; 225 return (CKR_OK); 226 } 227 228 /* 229 * Log user out of token and reset status variable. 230 */ 231 void 232 logout_token(CK_SESSION_HANDLE sess) 233 { 234 cryptodebug("inside logout_token"); 235 236 if (sess == NULL) { 237 cryptodebug("session handle is null"); 238 return; 239 } 240 241 /* If already logged out, nothing to do here. */ 242 if (!logged_in) 243 return; 244 245 cryptodebug("calling C_Logout()"); 246 (void) C_Logout(sess); 247 logged_in = B_FALSE; 248 } 249 250 /* 251 * Shortcut function to get from an uninitialized state to user logged in. 252 * If the library is already initialized, the session is already opened, 253 * or the user is already logged in, those steps are skipped and the next 254 * step is checked. 255 */ 256 CK_RV 257 quick_start(CK_SLOT_ID slot_id, CK_FLAGS sess_flags, CK_UTF8CHAR_PTR pin, 258 CK_ULONG pinlen, CK_SESSION_HANDLE_PTR sess) 259 { 260 CK_RV rv = CKR_OK; 261 262 cryptodebug("inside quick_start"); 263 264 /* Call open_sess() explicitly if R/W session is needed. */ 265 if (sess_flags & CKF_RW_SESSION) 266 if ((rv = open_sess(slot_id, sess_flags, sess)) != CKR_OK) 267 return (rv); 268 269 if ((rv = login_token(slot_id, pin, pinlen, sess)) != CKR_OK) 270 return (rv); 271 272 return (CKR_OK); 273 } 274 275 /* 276 * Shortcut function to go from any state to uninitialized PKCS#11 library. 277 */ 278 void 279 quick_finish(CK_SESSION_HANDLE sess) 280 { 281 cryptodebug("inside quick_finish"); 282 283 /* All the needed calls are done implicitly. */ 284 final_pk11(sess); 285 } 286 287 /* 288 * Gets PIN from user. Caller needs to free the returned PIN when done. 289 * If two prompts are given, the PIN is confirmed with second prompt. 290 * Note that getphassphrase() may return data in static memory area. 291 */ 292 CK_RV 293 get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen) 294 { 295 char *save_phrase, *phrase1, *phrase2; 296 297 cryptodebug("inside get_pin"); 298 299 /* Prompt user for a PIN. */ 300 if (prompt1 == NULL) { 301 cryptodebug("no passphrase prompt given"); 302 return (CKR_ARGUMENTS_BAD); 303 } 304 if ((phrase1 = getpassphrase(prompt1)) == NULL) { 305 cryptodebug("getpassphrase() failed"); 306 return (CKR_FUNCTION_FAILED); 307 } 308 309 /* Duplicate 1st PIN in separate chunk of memory. */ 310 if ((save_phrase = strdup(phrase1)) == NULL) 311 return (CKR_HOST_MEMORY); 312 313 /* If second prompt given, PIN confirmation is requested. */ 314 if (prompt2 != NULL) { 315 if ((phrase2 = getpassphrase(prompt2)) == NULL) { 316 cryptodebug("getpassphrase() confirmation failed"); 317 free(save_phrase); 318 return (CKR_FUNCTION_FAILED); 319 } 320 if (strcmp(save_phrase, phrase2) != 0) { 321 cryptodebug("passphrases do not match"); 322 free(save_phrase); 323 return (CKR_PIN_INCORRECT); 324 } 325 } 326 327 *pin = (CK_UTF8CHAR_PTR)save_phrase; 328 *pinlen = strlen(save_phrase); 329 return (CKR_OK); 330 } 331 332 /* 333 * Gets yes/no response from user. If either no prompt is supplied, a 334 * default prompt is used. If not message for invalid input is supplied, 335 * a default will not be provided. If the user provides no response, 336 * the input default B_TRUE == yes, B_FALSE == no is returned. 337 * Otherwise, B_TRUE is returned for yes, and B_FALSE for no. 338 */ 339 boolean_t 340 yesno(char *prompt, char *invalid, boolean_t dflt) 341 { 342 char *response, buf[1024]; 343 char *yes = gettext("yes"); 344 char *no = gettext("no"); 345 346 cryptodebug("inside yesno"); 347 348 if (prompt == NULL) 349 prompt = gettext("Enter (y)es or (n)o? "); 350 351 for (;;) { 352 /* Prompt user. */ 353 (void) printf("%s", prompt); 354 (void) fflush(stdout); 355 356 /* Get the response. */ 357 if ((response = fgets(buf, sizeof (buf), stdin)) == NULL) 358 break; /* go to default response */ 359 360 /* Skip any leading white space. */ 361 while (isspace(*response)) 362 response++; 363 if (*response == '\0') 364 break; /* go to default response */ 365 366 /* Is it valid input? Return appropriately. */ 367 if (strncasecmp(response, yes, 1) == 0) 368 return (B_TRUE); 369 if (strncasecmp(response, no, 1) == 0) 370 return (B_FALSE); 371 372 /* Indicate invalid input, and try again. */ 373 if (invalid != NULL) 374 (void) printf("%s", invalid); 375 } 376 return (dflt); 377 } 378 379 /* 380 * Gets the list of slots which have tokens in them. Keeps adjusting 381 * the size of the slot list buffer until the call is successful or an 382 * irrecoverable error occurs. 383 */ 384 CK_RV 385 get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count) 386 { 387 CK_ULONG tmp_count = 0; 388 CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR; 389 int rv = CKR_OK; 390 391 cryptodebug("inside get_token_slots"); 392 393 if (!initialized) 394 if ((rv = init_pk11()) != CKR_OK) 395 return (rv); 396 397 /* 398 * Get the slot count first because we don't know how many 399 * slots there are and how many of those slots even have tokens. 400 * Don't specify an arbitrary buffer size for the slot list; 401 * it may be too small (see section 11.5 of PKCS#11 spec). 402 * Also select only those slots that have tokens in them, 403 * because this tool has no need to know about empty slots. 404 */ 405 cryptodebug("calling C_GetSlotList() for slot count"); 406 if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK) 407 return (rv); 408 409 if (tmp_count == 0) { 410 cryptodebug("no slots with tokens found"); 411 *slot_list = NULL_PTR; 412 *slot_count = 0; 413 return (CKR_OK); 414 } 415 416 /* Allocate initial space for the slot list. */ 417 if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count * 418 sizeof (CK_SLOT_ID))) == NULL) 419 return (CKR_HOST_MEMORY); 420 421 /* Then get the slot list itself. */ 422 for (;;) { 423 cryptodebug("calling C_GetSlotList()"); 424 if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) { 425 *slot_list = tmp_list; 426 *slot_count = tmp_count; 427 break; 428 } 429 430 if (rv != CKR_BUFFER_TOO_SMALL) { 431 free(tmp_list); 432 break; 433 } 434 435 /* If the number of slots grew, try again. */ 436 cryptodebug("number of tokens present increased"); 437 if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list, 438 tmp_count * sizeof (CK_SLOT_ID))) == NULL) { 439 free(tmp_list); 440 rv = CKR_HOST_MEMORY; 441 break; 442 } 443 tmp_list = tmp2_list; 444 } 445 446 return (rv); 447 } 448 449 /* 450 * memcmp_pad_max() is a specialized version of memcmp() which 451 * compares two pieces of data up to a maximum length. If the 452 * the two data match up the maximum length, they are considered 453 * matching. Trailing blanks do not cause the match to fail if 454 * one of the data is shorted. 455 * 456 * Examples of matches: 457 * "one" | 458 * "one " | 459 * ^maximum length 460 * 461 * "Number One | X" (X is beyond maximum length) 462 * "Number One " | 463 * ^maximum length 464 * 465 * Examples of mismatches: 466 * " one" 467 * "one" 468 * 469 * "Number One X|" 470 * "Number One |" 471 * ^maximum length 472 */ 473 static int 474 memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz) 475 { 476 uint_t len, extra_len; 477 char *marker; 478 479 /* No point in comparing anything beyond max_sz */ 480 if (d1_len > max_sz) 481 d1_len = max_sz; 482 if (d2_len > max_sz) 483 d2_len = max_sz; 484 485 /* Find shorter of the two data. */ 486 if (d1_len <= d2_len) { 487 len = d1_len; 488 extra_len = d2_len; 489 marker = d2; 490 } else { /* d1_len > d2_len */ 491 len = d2_len; 492 extra_len = d1_len; 493 marker = d1; 494 } 495 496 /* Have a match in the shortest length of data? */ 497 if (memcmp(d1, d2, len) != 0) 498 /* CONSTCOND */ 499 return (!0); 500 501 /* If the rest of longer data is nulls or blanks, call it a match. */ 502 while (len < extra_len) 503 if (!isspace(marker[len++])) 504 /* CONSTCOND */ 505 return (!0); 506 return (0); 507 } 508 509 /* 510 * Locate a token slot whose token matches the label, manufacturer ID, and 511 * serial number given. Token label must be specified, manufacturer ID and 512 * serial number are optional. When the token is located, the PIN state 513 * is also returned to determine if it still has the default PIN. 514 */ 515 CK_RV 516 find_token_slot(char *token_name, char *manuf_id, char *serial_no, 517 CK_SLOT_ID *slot_id, CK_FLAGS *pin_state) 518 { 519 CK_SLOT_ID_PTR slot_list; 520 CK_TOKEN_INFO token_info; 521 CK_ULONG slot_count = 0; 522 int rv = CKR_OK; 523 int i; 524 uint_t len, max_sz; 525 boolean_t tok_match = B_FALSE, 526 man_match = B_FALSE, 527 ser_match = B_FALSE; 528 529 cryptodebug("inside find_token_slot"); 530 531 if (token_name == NULL) 532 return (CKR_ARGUMENTS_BAD); 533 534 /* Get a list of all slots with tokens present. */ 535 if ((rv = get_token_slots(&slot_list, &slot_count)) != CKR_OK) 536 return (rv); 537 538 /* If there are no such slots, the desired token won't be found. */ 539 if (slot_count == 0) 540 return (CKR_TOKEN_NOT_PRESENT); 541 542 /* Search the slot list for the token. */ 543 for (i = 0; i < slot_count; i++) { 544 cryptodebug("calling C_GetTokenInfo()"); 545 if ((rv = C_GetTokenInfo(slot_list[i], &token_info)) != 546 CKR_OK) { 547 cryptodebug("token in slot %d returns %s", i, 548 pkcs11_strerror(rv)); 549 continue; 550 } 551 552 /* See if the token label matches. */ 553 len = strlen(token_name); 554 max_sz = sizeof (token_info.label); 555 if (memcmp_pad_max(&(token_info.label), max_sz, token_name, len, 556 max_sz) == 0) 557 tok_match = B_TRUE; 558 559 /* 560 * If manufacturer id was given, see if it actually matches. 561 * If no manufacturer id was given, assume match is true. 562 */ 563 if (manuf_id) { 564 len = strlen(manuf_id); 565 max_sz = sizeof ((char *)(token_info.manufacturerID)); 566 if (memcmp_pad_max(&(token_info.manufacturerID), max_sz, 567 manuf_id, len, max_sz) == 0) 568 man_match = B_TRUE; 569 } else 570 man_match = B_TRUE; 571 572 /* 573 * If serial number was given, see if it actually matches. 574 * If no serial number was given, assume match is true. 575 */ 576 if (serial_no) { 577 len = strlen(serial_no); 578 max_sz = sizeof ((char *)(token_info.serialNumber)); 579 if (memcmp_pad_max(&(token_info.serialNumber), max_sz, 580 serial_no, len, max_sz) == 0) 581 ser_match = B_TRUE; 582 } else 583 ser_match = B_TRUE; 584 585 cryptodebug("slot %d:", i); 586 cryptodebug("\tlabel = \"%.32s\"%s", token_info.label, 587 tok_match ? " match" : ""); 588 cryptodebug("\tmanuf = \"%.32s\"%s", token_info.manufacturerID, 589 man_match ? " match" : ""); 590 cryptodebug("\tserno = \"%.16s\"%s", token_info.serialNumber, 591 ser_match ? " match" : ""); 592 cryptodebug("\tmodel = \"%.16s\"", token_info.model); 593 594 cryptodebug("\tCKF_USER_PIN_INITIALIZED = %s", 595 (token_info.flags & CKF_USER_PIN_INITIALIZED) ? 596 "true" : "false"); 597 cryptodebug("\tCKF_USER_PIN_TO_BE_CHANGED = %s", 598 (token_info.flags & CKF_USER_PIN_TO_BE_CHANGED) ? 599 "true" : "false"); 600 601 if (tok_match && man_match && ser_match) 602 break; /* found it! */ 603 } 604 605 /* Scanned the whole list without finding the token. */ 606 if (i == slot_count) { 607 cryptodebug("token not found"); 608 free(slot_list); 609 return (CKR_TOKEN_NOT_PRESENT); 610 } 611 612 /* Return slot id where token was found and its PIN state. */ 613 cryptodebug("token found at slot %d", i); 614 *slot_id = slot_list[i]; 615 *pin_state = (token_info.flags & CKF_USER_PIN_TO_BE_CHANGED); 616 free(slot_list); 617 return (CKR_OK); 618 } 619 620 /* 621 * Returns pointer to either null-terminator or next unescaped colon. The 622 * string to be extracted starts at the beginning and goes until one character 623 * before this pointer. If NULL is returned, the string itself is NULL. 624 */ 625 static char * 626 find_unescaped_colon(char *str) 627 { 628 char *end; 629 630 if (str == NULL) 631 return (NULL); 632 633 while ((end = strchr(str, ':')) != NULL) { 634 if (end != str && *(end-1) != '\\') 635 return (end); 636 str = end + 1; /* could point to null-terminator */ 637 } 638 if (end == NULL) 639 end = strchr(str, '\0'); 640 return (end); 641 } 642 643 /* 644 * Compresses away any characters escaped with backslash from given string. 645 * The string is altered in-place. Example, "ab\:\\e" becomes "ab:\e". 646 */ 647 static void 648 unescape_str(char *str) 649 { 650 boolean_t escaped = B_FALSE; 651 char *mark; 652 653 if (str == NULL) 654 return; 655 656 for (mark = str; *str != '\0'; str++) { 657 if (*str != '\\' || escaped == B_TRUE) { 658 *mark++ = *str; 659 escaped = B_FALSE; 660 } else { 661 escaped = B_TRUE; 662 } 663 } 664 *mark = '\0'; 665 } 666 667 /* 668 * Given a colon-separated token specifier, this functions splits it into 669 * its label, manufacturer ID (if any), and serial number (if any). Literal 670 * colons within the label/manuf/serial can be escaped with a backslash. 671 * Fields can left blank and trailing colons can be omitted, however leading 672 * colons are required as placeholders. For example, these are equivalent: 673 * (a) "lbl", "lbl:", "lbl::" (b) "lbl:man", "lbl:man:" 674 * but these are not: 675 * (c) "man", ":man" (d) "ser", "::ser" 676 * Furthermore, the token label is required always. 677 * 678 * The buffer containing the token specifier is altered by replacing the 679 * colons to null-terminators, and pointers returned are pointers into this 680 * string. No new memory is allocated. 681 */ 682 int 683 parse_token_spec(char *token_spec, char **token_name, char **manuf_id, 684 char **serial_no) 685 { 686 char *mark; 687 688 if (token_spec == NULL || *token_spec == '\0') { 689 cryptodebug("token specifier is empty"); 690 return (-1); 691 } 692 693 *token_name = NULL; 694 *manuf_id = NULL; 695 *serial_no = NULL; 696 697 /* Token label (required) */ 698 mark = find_unescaped_colon(token_spec); 699 *token_name = token_spec; 700 if (*mark != '\0') 701 *mark++ = '\0'; /* mark points to next field, if any */ 702 unescape_str(*token_name); 703 704 if (*(*token_name) == '\0') { /* token label is required */ 705 cryptodebug("no token label found"); 706 return (-1); 707 } 708 709 if (*mark == '\0' || *(mark+1) == '\0') /* no more fields */ 710 return (0); 711 token_spec = mark; 712 713 /* Manufacturer identifier (optional) */ 714 mark = find_unescaped_colon(token_spec); 715 *manuf_id = token_spec; 716 if (*mark != '\0') 717 *mark++ = '\0'; /* mark points to next field, if any */ 718 unescape_str(*manuf_id); 719 720 if (*mark == '\0' || *(mark+1) == '\0') /* no more fields */ 721 return (0); 722 token_spec = mark; 723 724 /* Serial number (optional) */ 725 mark = find_unescaped_colon(token_spec); 726 *serial_no = token_spec; 727 if (*mark != '\0') 728 *mark++ = '\0'; /* null-terminate, just in case */ 729 unescape_str(*serial_no); 730 731 return (0); 732 } 733 734 /* 735 * Constructs a fully qualified token name from its label, manufacturer ID 736 * (if any), and its serial number (if any). Note that the given buf must 737 * be big enough. Do NOT i18n/l10n. 738 * 739 * FULL_NAME_LEN is defined in common.h to be 91 because a fully qualified 740 * token name adds up this way: 741 * =32(label) + 32(manuf) + 16(serial) + 4("", ) + 4("", ) + 3("" and nul) 742 */ 743 void 744 full_token_name(char *token_name, char *manuf_id, char *serial_no, char *buf) 745 { 746 char *marker = buf; 747 int n_written = 0; 748 int space_left = FULL_NAME_LEN; 749 750 if (!token_name) 751 return; 752 753 n_written = sprintf(buf, "\"%.32s\"", token_name); 754 marker += n_written; 755 space_left -= n_written; 756 757 n_written = sprintf(marker, ", \"%.32s\"", manuf_id ? manuf_id : ""); 758 marker += n_written; 759 space_left -= n_written; 760 761 n_written = sprintf(marker, ", \"%.16s\"", serial_no ? serial_no : ""); 762 marker += n_written; 763 space_left -= n_written; 764 765 /* space_left should always be >= 1 */ 766 } 767 768 /* 769 * Find how many token objects with the given label. 770 */ 771 CK_RV 772 find_obj_count(CK_SESSION_HANDLE sess, int obj_type, CK_BYTE *label, 773 CK_ULONG *count) 774 { 775 CK_RV rv = CKR_OK; 776 CK_ATTRIBUTE attrs[4] = { 777 { CKA_TOKEN, &pk_true, sizeof (pk_true) }, 778 { 0, NULL, 0 }, 779 { 0, NULL, 0 }, 780 { 0, NULL, 0 } 781 }; 782 CK_ULONG num_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE); 783 CK_ULONG cur_attr = 1; /* CKA_TOKEN already set */ 784 CK_OBJECT_CLASS obj_class; 785 CK_OBJECT_HANDLE tmp_obj; 786 CK_ULONG obj_count = 0; 787 788 cryptodebug("inside find_obj_count"); 789 790 if (!session_opened || sess == NULL) { 791 cryptodebug("session handle is null"); 792 return (CKR_SESSION_HANDLE_INVALID); 793 } 794 795 if (label) { 796 cryptodebug("object label was specified"); 797 attrs[cur_attr].type = CKA_LABEL; 798 attrs[cur_attr].pValue = label; 799 attrs[cur_attr].ulValueLen = strlen((char *)label); 800 cur_attr++; 801 } 802 803 if ((obj_type & PK_PRIVATE_OBJ) && !(obj_type & PK_PUBLIC_OBJ)) { 804 cryptodebug("only searching for private objects"); 805 attrs[cur_attr].type = CKA_PRIVATE; 806 attrs[cur_attr].pValue = &pk_true; 807 attrs[cur_attr].ulValueLen = sizeof (pk_true); 808 cur_attr++; 809 } 810 811 /* 812 * If "certs and all keys" is not specified, but at least either 813 * "certs" or some "keys" is specified, then go into this block. 814 * If all certs and keys were specified, there's no point in 815 * putting that fact in the attribute template -- leave that open, 816 * and all certs and keys will be matched automatically. 817 * In other words, only if at least one of 0x10,0x20,0x40,0x80 818 * bits is off, go into this code block. 819 * 820 * NOTE: For now, only one of cert or key types is allowed. 821 * This needs to change in the future. 822 */ 823 if ((obj_type & (PK_CERT_OBJ|PK_KEY_OBJ)) != (PK_CERT_OBJ|PK_KEY_OBJ) && 824 ((obj_type & PK_CERT_OBJ) || (obj_type & PK_KEY_OBJ))) { 825 if (obj_type & PK_CERT_OBJ) { 826 cryptodebug("only searching for certificates"); 827 obj_class = CKO_CERTIFICATE; 828 } else if (obj_type & PK_PRIKEY_OBJ) { 829 cryptodebug("only searching for private keys"); 830 obj_class = CKO_PRIVATE_KEY; 831 } else if (obj_type & PK_PUBKEY_OBJ) { 832 cryptodebug("only searching for public keys"); 833 obj_class = CKO_PUBLIC_KEY; 834 } else if (obj_type & PK_SECKEY_OBJ) { 835 cryptodebug("only searching for secret keys"); 836 obj_class = CKO_SECRET_KEY; 837 } 838 839 attrs[cur_attr].type = CKA_CLASS; 840 attrs[cur_attr].pValue = &obj_class; 841 attrs[cur_attr].ulValueLen = sizeof (CK_OBJECT_CLASS); 842 cur_attr++; 843 } 844 845 /* 846 * This can't happen now. When finding objects is enhanced in the 847 * future. this could lead to buffer overruns. 848 */ 849 if (cur_attr > num_attrs) 850 cryptodebug("internal error: attr template overrun"); 851 852 cryptodebug("calling C_FindObjectsInit"); 853 if ((rv = C_FindObjectsInit(sess, attrs, cur_attr)) != CKR_OK) 854 return (rv); 855 856 /* Look for the object, checking if there are more than one. */ 857 cryptodebug("calling C_FindObjects"); 858 for (*count = 0; /* empty */; (*count)++) { 859 if ((rv = C_FindObjects(sess, &tmp_obj, 1, &obj_count)) != 860 CKR_OK) 861 break; 862 863 /* No more found. */ 864 if (obj_count == 0) 865 break; 866 } 867 868 cryptodebug("%d matching objects found", *count); 869 870 cryptodebug("calling C_FindObjectsFinal"); 871 (void) C_FindObjectsFinal(sess); 872 return (rv); 873 } 874 875 /* 876 * Find the token object with the given label. 877 */ 878 CK_RV 879 find_objs(CK_SESSION_HANDLE sess, int obj_type, CK_BYTE *label, 880 CK_OBJECT_HANDLE_PTR *obj, CK_ULONG *count) 881 { 882 CK_RV rv = CKR_OK; 883 CK_ATTRIBUTE attrs[4] = { 884 { CKA_TOKEN, &pk_true, sizeof (pk_true) }, 885 { 0, NULL, 0 }, 886 { 0, NULL, 0 }, 887 { 0, NULL, 0 } 888 }; 889 CK_ULONG num_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE); 890 CK_ULONG cur_attr = 1; /* CKA_TOKEN already set */ 891 CK_OBJECT_CLASS obj_class; 892 CK_OBJECT_HANDLE tmp_obj; 893 CK_ULONG obj_count = 0; 894 int i; 895 896 cryptodebug("inside find_obj"); 897 898 if ((rv = find_obj_count(sess, obj_type, label, count)) != CKR_OK) 899 return (rv); 900 901 if (*count == 0) 902 return (CKR_OK); 903 904 if ((*obj = (CK_OBJECT_HANDLE_PTR) malloc((*count) * 905 sizeof (CK_OBJECT_HANDLE))) == NULL) { 906 cryptodebug("no memory for found object"); 907 return (CKR_HOST_MEMORY); 908 } 909 910 if (label) { 911 cryptodebug("object label was specified"); 912 attrs[cur_attr].type = CKA_LABEL; 913 attrs[cur_attr].pValue = label; 914 attrs[cur_attr].ulValueLen = strlen((char *)label); 915 cur_attr++; 916 } 917 918 if ((obj_type & PK_PRIVATE_OBJ) && !(obj_type & PK_PUBLIC_OBJ)) { 919 cryptodebug("only searching for private objects"); 920 attrs[cur_attr].type = CKA_PRIVATE; 921 attrs[cur_attr].pValue = &pk_true; 922 attrs[cur_attr].ulValueLen = sizeof (pk_true); 923 cur_attr++; 924 } 925 926 /* 927 * If "certs and all keys" is not specified, but at least either 928 * "certs" or some "keys" is specified, then go into this block. 929 * If all certs and keys were specified, there's no point in 930 * putting that fact in the attribute template -- leave that open, 931 * and all certs and keys will be matched automatically. 932 * In other words, only if at least one of 0x10,0x20,0x40,0x80 933 * bits is off, go into this code block. 934 * 935 * NOTE: For now, only one of cert or key types is allowed. 936 * This needs to change in the future. 937 */ 938 if ((obj_type & (PK_CERT_OBJ|PK_KEY_OBJ)) != (PK_CERT_OBJ|PK_KEY_OBJ) && 939 ((obj_type & PK_CERT_OBJ) || (obj_type & PK_KEY_OBJ))) { 940 if (obj_type & PK_CERT_OBJ) { 941 cryptodebug("only searching for certificates"); 942 obj_class = CKO_CERTIFICATE; 943 } else if (obj_type & PK_PRIKEY_OBJ) { 944 cryptodebug("only searching for private keys"); 945 obj_class = CKO_PRIVATE_KEY; 946 } else if (obj_type & PK_PUBKEY_OBJ) { 947 cryptodebug("only searching for public keys"); 948 obj_class = CKO_PUBLIC_KEY; 949 } else if (obj_type & PK_SECKEY_OBJ) { 950 cryptodebug("only searching for secret keys"); 951 obj_class = CKO_SECRET_KEY; 952 } 953 954 attrs[cur_attr].type = CKA_CLASS; 955 attrs[cur_attr].pValue = &obj_class; 956 attrs[cur_attr].ulValueLen = sizeof (CK_OBJECT_CLASS); 957 cur_attr++; 958 } 959 960 /* 961 * This can't happen now. When finding objects is enhanced in the 962 * future. this could lead to buffer overruns. 963 */ 964 if (cur_attr > num_attrs) 965 cryptodebug("internal error: attr template overrun"); 966 967 cryptodebug("calling C_FindObjectsInit"); 968 if ((rv = C_FindObjectsInit(sess, attrs, cur_attr)) != CKR_OK) { 969 free(*obj); 970 return (rv); 971 } 972 973 /* 974 * Find all the matching objects. The loop goes 1 more beyond 975 * the number of objects found to determine if any new objects 976 * were created since the time the object count was done. 977 */ 978 cryptodebug("calling C_FindObjects"); 979 for (i = 0; i < (*count) + 1; i++) { 980 if ((rv = C_FindObjects(sess, &tmp_obj, 1, &obj_count)) != 981 CKR_OK) 982 break; 983 984 /* No more found. */ 985 if (obj_count == 0) 986 break; 987 988 /* 989 * Save the object in the list being created, as long as 990 * we don't overrun the size of the list. 991 */ 992 if (i < *count) 993 (*obj)[i] = tmp_obj; 994 else 995 cryptodebug("number of objects changed since last count"); 996 } 997 998 if (rv != CKR_OK) { 999 free(*obj); 1000 } else { 1001 /* 1002 * There are three cases to handle: (1) fewer objects were 1003 * found than originally counted => change *count to the 1004 * smaller number; (2) the number of objects found matches 1005 * the number originally counted => do nothing; (3) more 1006 * objects found than originally counted => list passed 1007 * in is too small to contain the extra object(s), flag 1008 * that in the debug output but don't change number of 1009 * objects returned. The caller can double-check by 1010 * calling find_obj_count() after this function to make 1011 * sure the numbers match, if desired. 1012 */ 1013 /* Case 1: Fewer objects. */ 1014 if (i < *count) { 1015 cryptodebug("%d objects found, expected %d", i, *count); 1016 *count = i; 1017 /* Case 3: More objects. */ 1018 } else if (i > *count) { 1019 cryptodebug("at least %d objects found, expected %d", 1020 i, *count); 1021 } 1022 /* 1023 * Case 2: Same number of objects. 1024 * 1025 * else if (i == *count) 1026 * ; 1027 */ 1028 } 1029 1030 cryptodebug("calling C_FindObjectsFinal"); 1031 (void) C_FindObjectsFinal(sess); 1032 return (rv); 1033 } 1034 1035 char * 1036 class_str(CK_OBJECT_CLASS class) 1037 { 1038 switch (class) { 1039 case CKO_DATA: return (gettext("data")); 1040 case CKO_CERTIFICATE: return (gettext("certificate")); 1041 case CKO_PUBLIC_KEY: return (gettext("public key")); 1042 case CKO_PRIVATE_KEY: return (gettext("private key")); 1043 case CKO_SECRET_KEY: return (gettext("secret key")); 1044 case CKO_DOMAIN_PARAMETERS: return (gettext("domain parameter")); 1045 default: return (gettext("unknown object")); 1046 } 1047 } 1048 1049 char * 1050 keytype_str(CK_KEY_TYPE keytype) 1051 { 1052 switch (keytype) { 1053 case CKK_RSA: return (gettext("RSA")); 1054 case CKK_DSA: return (gettext("DSA")); 1055 case CKK_DH: return (gettext("Diffie-Hellman")); 1056 case CKK_X9_42_DH: return (gettext("X9.42 Diffie-Hellman")); 1057 case CKK_GENERIC_SECRET: return (gettext("generic")); 1058 case CKK_RC2: return (gettext("RC2")); 1059 case CKK_RC4: return (gettext("RC4")); 1060 case CKK_DES: return (gettext("DES")); 1061 case CKK_DES2: return (gettext("Double-DES")); 1062 case CKK_DES3: return (gettext("Triple-DES")); 1063 case CKK_RC5: return (gettext("RC5")); 1064 case CKK_AES: return (gettext("AES")); 1065 default: return (gettext("typeless")); 1066 } 1067 } 1068 1069 char * 1070 attr_str(CK_ATTRIBUTE_TYPE attrtype) 1071 { 1072 switch (attrtype) { 1073 case CKA_PRIVATE: return (gettext("private")); 1074 case CKA_LOCAL: return (gettext("local")); 1075 case CKA_SENSITIVE: return (gettext("sensitive")); 1076 case CKA_EXTRACTABLE: return (gettext("extractable")); 1077 case CKA_ENCRYPT: return (gettext("encrypt")); 1078 case CKA_DECRYPT: return (gettext("decrypt")); 1079 case CKA_WRAP: return (gettext("wrap")); 1080 case CKA_UNWRAP: return (gettext("unwrap")); 1081 case CKA_SIGN: return (gettext("sign")); 1082 case CKA_SIGN_RECOVER: return (gettext("sign-recover")); 1083 case CKA_VERIFY: return (gettext("verify")); 1084 case CKA_VERIFY_RECOVER: return (gettext("verify-recover")); 1085 case CKA_DERIVE: return (gettext("derive")); 1086 case CKA_ALWAYS_SENSITIVE: return (gettext("always sensitive")); 1087 case CKA_NEVER_EXTRACTABLE: return (gettext("never extractable")); 1088 default: return (gettext("unknown capability")); 1089 } 1090 } 1091 1092 /* 1093 * Convert a byte string into a string of octets formatted like this: 1094 * oo oo oo oo oo ... oo 1095 * where each "oo" is an octet is space separated and in the form: 1096 * [0-f][0-f] if the octet is a non-printable character 1097 * <space><char> if the octet is a printable character 1098 * 1099 * Note: octets_sz must be 3 * str_sz + 1, or at least as long as "blank" 1100 */ 1101 void 1102 octetify(CK_BYTE *str, CK_ULONG str_sz, char *octets, int octets_sz, 1103 boolean_t stop_on_nul, boolean_t do_ascii, int limit, char *indent, 1104 char *blank) 1105 { 1106 char *marker; 1107 int nc; 1108 int newline; 1109 int indent_len; 1110 boolean_t first = B_TRUE; 1111 1112 cryptodebug("inside octetify"); 1113 1114 cryptodebug(stop_on_nul ? "stopping on first nul found" : 1115 "continuing to full length of buffer"); 1116 cryptodebug(do_ascii ? "using ascii chars where printable" : 1117 "using only hex octets"); 1118 cryptodebug("every %d characters indent with \"%s\"\n ", limit, indent); 1119 cryptodebug("return \"%s\" if buffer is null or empty", blank); 1120 1121 /* If string is empty, write as much of the blank string and leave. */ 1122 if (str_sz == 0) { 1123 (void) snprintf(octets, octets_sz, "%s", blank); 1124 return; 1125 } 1126 1127 /* If only limit or indent is set, pick default for the other. */ 1128 if (limit > 0 && indent == NULL) 1129 indent = "\n"; 1130 if (indent != NULL && limit == 0) 1131 limit = 60; 1132 indent_len = strlen(indent); 1133 1134 for (marker = octets, newline = 0, first = B_TRUE; 1135 (stop_on_nul && *str != '\0') || 1136 (!stop_on_nul && str_sz > 0 && octets_sz > 0); 1137 str++, str_sz--, marker += nc, octets_sz -= nc) { 1138 if (!first) { 1139 if (limit > 0 && ((marker - octets) / limit) > 1140 newline) { 1141 nc = snprintf(marker, indent_len, "%s", indent); 1142 newline++; 1143 continue; 1144 } 1145 nc = sprintf(marker, 1146 ((do_ascii && isprint(*str) && !isspace(*str)) ? 1147 "%s%c" : "%s%02x"), (do_ascii ? " " : ":"), *str); 1148 } else { 1149 nc = sprintf(marker, 1150 ((do_ascii && isprint(*str) && !isspace(*str)) ? 1151 "%c" : "%02x"), *str); 1152 first = B_FALSE; 1153 } 1154 } 1155 *marker = '\0'; 1156 } 1157 1158 /* 1159 * Copies a biginteger_t to a template attribute. 1160 * Should be a macro instead of a function. 1161 */ 1162 void 1163 copy_bigint_to_attr(biginteger_t big, CK_ATTRIBUTE_PTR attr) 1164 { 1165 attr->pValue = big.big_value; 1166 attr->ulValueLen = big.big_value_len; 1167 } 1168 1169 /* 1170 * Copies a string and its length to a template attribute. 1171 * Should be a macro instead of a function. 1172 */ 1173 void 1174 copy_string_to_attr(CK_BYTE *buf, CK_ULONG buflen, CK_ATTRIBUTE_PTR attr) 1175 { 1176 attr->pValue = buf; 1177 attr->ulValueLen = buflen; 1178 } 1179 1180 /* 1181 * Copies a template attribute to a biginteger_t. 1182 * Should be a macro instead of a function. 1183 */ 1184 void 1185 copy_attr_to_bigint(CK_ATTRIBUTE_PTR attr, biginteger_t *big) 1186 { 1187 big->big_value = attr->pValue; 1188 big->big_value_len = attr->ulValueLen; 1189 } 1190 1191 /* 1192 * Copies a template attribute to a string and its length. 1193 * Should be a macro instead of a function. 1194 */ 1195 void 1196 copy_attr_to_string(CK_ATTRIBUTE_PTR attr, CK_BYTE **buf, CK_ULONG *buflen) 1197 { 1198 *buf = attr->pValue; 1199 *buflen = attr->ulValueLen; 1200 } 1201 1202 /* 1203 * Copies a template attribute to a date and its length. 1204 * Should be a macro instead of a function. 1205 */ 1206 void 1207 copy_attr_to_date(CK_ATTRIBUTE_PTR attr, CK_DATE **buf, CK_ULONG *buflen) 1208 { 1209 *buf = (CK_DATE *)attr->pValue; 1210 *buflen = attr->ulValueLen; 1211 } 1212 1213 /* 1214 * Breaks out the getopt-style option string into a structure that can be 1215 * traversed later for calls to getopt_av(). Option string is NOT altered, 1216 * but the struct fields point to locations within option string. 1217 */ 1218 static int 1219 populate_opts(char *optstring) 1220 { 1221 int i; 1222 av_opts *temp; 1223 char *marker; 1224 1225 if (optstring == NULL || *optstring == '\0') 1226 return (0); 1227 1228 /* 1229 * This tries to imitate getopt(3c) Each option must conform to: 1230 * <short name char> [ ':' ] [ '(' <long name string> ')' ] 1231 * If long name is missing, the short name is used for long name. 1232 */ 1233 for (i = 0; *optstring != '\0'; i++) { 1234 if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) : 1235 realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) { 1236 free(opts_av); 1237 opts_av = NULL; 1238 return (0); 1239 } else 1240 opts_av = (av_opts *)temp; 1241 1242 marker = optstring; /* may need optstring later */ 1243 1244 opts_av[i].shortnm = *marker++; /* set short name */ 1245 1246 if (*marker == ':') { /* check for opt arg */ 1247 marker++; 1248 opts_av[i].has_arg = B_TRUE; 1249 } 1250 1251 if (*marker == '(') { /* check and set long name */ 1252 marker++; 1253 opts_av[i].longnm = marker; 1254 opts_av[i].longnm_len = strcspn(marker, ")"); 1255 optstring = marker + opts_av[i].longnm_len + 1; 1256 } else { 1257 /* use short name option character */ 1258 opts_av[i].longnm = optstring; 1259 opts_av[i].longnm_len = 1; 1260 optstring = marker; 1261 } 1262 } 1263 1264 return (i); 1265 } 1266 1267 /* 1268 * getopt_av() is very similar to getopt(3c) in that the takes an option 1269 * string, compares command line arguments for matches, and returns a single 1270 * letter option when a match is found. However, getopt_av() differs from 1271 * getopt(3c) by requiring that only longname options and values be found 1272 * on the command line and all leading dashes are omitted. In other words, 1273 * it tries to enforce only longname "option=value" arguments on the command 1274 * line. Boolean options are not allowed either. 1275 */ 1276 int 1277 getopt_av(int argc, char * const *argv, const char *optstring) 1278 { 1279 int i; 1280 int len; 1281 1282 if (optind_av >= argc) 1283 return (EOF); 1284 1285 /* First time or when optstring changes from previous one */ 1286 if (_save_optstr != optstring) { 1287 if (opts_av != NULL) 1288 free(opts_av); 1289 opts_av = NULL; 1290 _save_optstr = optstring; 1291 _save_numopts = populate_opts((char *)optstring); 1292 } 1293 1294 for (i = 0; i < _save_numopts; i++) { 1295 if (strcmp(argv[optind_av], "--") == 0) { 1296 optind_av++; 1297 break; 1298 } 1299 1300 len = strcspn(argv[optind_av], "="); 1301 1302 if (len == opts_av[i].longnm_len && strncmp(argv[optind_av], 1303 opts_av[i].longnm, opts_av[i].longnm_len) == 0) { 1304 /* matched */ 1305 if (!opts_av[i].has_arg) { 1306 optind_av++; 1307 return (opts_av[i].shortnm); 1308 } 1309 1310 /* needs optarg */ 1311 if (argv[optind_av][len] == '=') { 1312 optarg_av = &(argv[optind_av][len+1]); 1313 optind_av++; 1314 return (opts_av[i].shortnm); 1315 } 1316 1317 optarg_av = NULL; 1318 optind_av++; 1319 return ((int)'?'); 1320 } 1321 } 1322 1323 return (EOF); 1324 } 1325