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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <cryptoutil.h> 27 #include <fcntl.h> 28 #include <libintl.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <strings.h> 32 #include <unistd.h> 33 #include <errno.h> 34 #include <dlfcn.h> 35 #include <link.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <security/cryptoki.h> 39 #include "cryptoadm.h" 40 41 #define HDR1 " P\n" 42 #define HDR2 " S V K a U D\n" 43 #define HDR3 " i e e i n e\n" 44 #define HDR4 " S g V r y r W w r\n" 45 #define HDR5 " E D D i n e i G G r r i\n" 46 #define HDR6 " H n e i g + r + e e a a v E\n" 47 #define HDR7 "min max W c c g n R i R n n p p e C\n" 48 49 50 static int err; /* To store errno which may be overwritten by gettext() */ 51 static boolean_t is_in_policylist(midstr_t, umechlist_t *); 52 static char *uent2str(uentry_t *); 53 static boolean_t check_random(CK_SLOT_ID, CK_FUNCTION_LIST_PTR); 54 55 static void display_slot_flags(CK_FLAGS flags) 56 { 57 (void) printf(gettext("Slot Flags: ")); 58 if (flags & CKF_TOKEN_PRESENT) 59 (void) printf("CKF_TOKEN_PRESENT "); 60 if (flags & CKF_REMOVABLE_DEVICE) 61 (void) printf("CKF_REMOVABLE_DEVICE "); 62 if (flags & CKF_HW_SLOT) 63 (void) printf("CKF_HW_SLOT "); 64 (void) printf("\n"); 65 } 66 67 void 68 display_token_flags(CK_FLAGS flags) 69 { 70 (void) printf(gettext("Flags: ")); 71 if (flags & CKF_RNG) 72 (void) printf("CKF_RNG "); 73 if (flags & CKF_WRITE_PROTECTED) 74 (void) printf("CKF_WRITE_PROTECTED "); 75 if (flags & CKF_LOGIN_REQUIRED) 76 (void) printf("CKF_LOGIN_REQUIRED "); 77 if (flags & CKF_USER_PIN_INITIALIZED) 78 (void) printf("CKF_USER_PIN_INITIALIZED "); 79 if (flags & CKF_RESTORE_KEY_NOT_NEEDED) 80 (void) printf("CKF_RESTORE_KEY_NOT_NEEDED "); 81 if (flags & CKF_CLOCK_ON_TOKEN) 82 (void) printf("CKF_CLOCK_ON_TOKEN "); 83 if (flags & CKF_PROTECTED_AUTHENTICATION_PATH) 84 (void) printf("CKF_PROTECTED_AUTHENTICATION_PATH "); 85 if (flags & CKF_DUAL_CRYPTO_OPERATIONS) 86 (void) printf("CKF_DUAL_CRYPTO_OPERATIONS "); 87 if (flags & CKF_TOKEN_INITIALIZED) 88 (void) printf("CKF_TOKEN_INITIALIZED "); 89 if (flags & CKF_SECONDARY_AUTHENTICATION) 90 (void) printf("CKF_SECONDARY_AUTHENTICATION "); 91 if (flags & CKF_USER_PIN_COUNT_LOW) 92 (void) printf("CKF_USER_PIN_COUNT_LOW "); 93 if (flags & CKF_USER_PIN_FINAL_TRY) 94 (void) printf("CKF_USER_PIN_FINAL_TRY "); 95 if (flags & CKF_USER_PIN_LOCKED) 96 (void) printf("CKF_USER_PIN_LOCKED "); 97 if (flags & CKF_USER_PIN_TO_BE_CHANGED) 98 (void) printf("CKF_USER_PIN_TO_BE_CHANGED "); 99 if (flags & CKF_SO_PIN_COUNT_LOW) 100 (void) printf("CKF_SO_PIN_COUNT_LOW "); 101 if (flags & CKF_SO_PIN_FINAL_TRY) 102 (void) printf("CKF_SO_PIN_FINAL_TRY "); 103 if (flags & CKF_SO_PIN_LOCKED) 104 (void) printf("CKF_SO_PIN_LOCKED "); 105 if (flags & CKF_SO_PIN_TO_BE_CHANGED) 106 (void) printf("CKF_SO_PIN_TO_BE_CHANGED "); 107 if (flags & CKF_SO_PIN_TO_BE_CHANGED) 108 (void) printf("CKF_SO_PIN_TO_BE_CHANGED "); 109 (void) printf("\n"); 110 } 111 112 void 113 display_mech_info(CK_MECHANISM_INFO *mechInfo) 114 { 115 CK_FLAGS ec_flags = CKF_EC_F_P | CKF_EC_F_2M | CKF_EC_ECPARAMETERS | 116 CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS | CKF_EC_COMPRESS; 117 118 (void) printf("%-4ld %-4ld ", mechInfo->ulMinKeySize, 119 mechInfo->ulMaxKeySize); 120 (void) printf("%s %s %s %s %s %s %s %s %s %s %s %s " 121 "%s %s", 122 (mechInfo->flags & CKF_HW) ? "X" : ".", 123 (mechInfo->flags & CKF_ENCRYPT) ? "X" : ".", 124 (mechInfo->flags & CKF_DECRYPT) ? "X" : ".", 125 (mechInfo->flags & CKF_DIGEST) ? "X" : ".", 126 (mechInfo->flags & CKF_SIGN) ? "X" : ".", 127 (mechInfo->flags & CKF_SIGN_RECOVER) ? "X" : ".", 128 (mechInfo->flags & CKF_VERIFY) ? "X" : ".", 129 (mechInfo->flags & CKF_VERIFY_RECOVER) ? "X" : ".", 130 (mechInfo->flags & CKF_GENERATE) ? "X" : ".", 131 (mechInfo->flags & CKF_GENERATE_KEY_PAIR) ? "X" : ".", 132 (mechInfo->flags & CKF_WRAP) ? "X" : ".", 133 (mechInfo->flags & CKF_UNWRAP) ? "X" : ".", 134 (mechInfo->flags & CKF_DERIVE) ? "X" : ".", 135 (mechInfo->flags & ec_flags) ? "X" : "."); 136 } 137 138 /* 139 * Converts the provided list of mechanism names in their string format to 140 * their corresponding PKCS#11 mechanism IDs. 141 * 142 * The list of mechanism names to be converted is provided in the 143 * "mlist" argument. The list of converted mechanism IDs is returned 144 * in the "pmech_list" argument. 145 * 146 * This function is called by list_metaslot_info() and 147 * list_mechlist_for_lib() functions. 148 */ 149 int 150 convert_mechlist(CK_MECHANISM_TYPE **pmech_list, CK_ULONG *mech_count, 151 mechlist_t *mlist) 152 { 153 int i, n = 0; 154 mechlist_t *p = mlist; 155 156 while (p != NULL) { 157 p = p->next; 158 n++; 159 } 160 161 *pmech_list = malloc(n * sizeof (CK_MECHANISM_TYPE)); 162 if (pmech_list == NULL) { 163 cryptodebug("out of memory"); 164 return (FAILURE); 165 } 166 p = mlist; 167 for (i = 0; i < n; i++) { 168 if (pkcs11_str2mech(p->name, &(*pmech_list[i])) != CKR_OK) { 169 free(*pmech_list); 170 return (FAILURE); 171 } 172 p = p->next; 173 } 174 *mech_count = n; 175 return (SUCCESS); 176 } 177 178 /* 179 * Display the mechanism list for a user-level library 180 */ 181 int 182 list_mechlist_for_lib(char *libname, mechlist_t *mlist, 183 flag_val_t *rng_flag, boolean_t no_warn, 184 boolean_t verbose, boolean_t show_mechs) 185 { 186 CK_RV rv = CKR_OK; 187 CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR); 188 CK_FUNCTION_LIST_PTR prov_funcs; /* Provider's function list */ 189 CK_SLOT_ID_PTR prov_slots = NULL; /* Provider's slot list */ 190 CK_MECHANISM_TYPE_PTR pmech_list; /* mechanism list for a slot */ 191 CK_SLOT_INFO slotinfo; 192 CK_ULONG slot_count; 193 CK_ULONG mech_count; 194 uentry_t *puent = NULL; 195 boolean_t lib_initialized = B_FALSE; 196 void *dldesc = NULL; 197 char *dl_error; 198 const char *mech_name; 199 char *isa; 200 char libpath[MAXPATHLEN]; 201 char buf[MAXPATHLEN]; 202 int i, j; 203 int rc = SUCCESS; 204 205 if (libname == NULL) { 206 /* should not happen */ 207 cryptoerror(LOG_STDERR, gettext("internal error.")); 208 cryptodebug("list_mechlist_for_lib() - libname is NULL."); 209 return (FAILURE); 210 } 211 212 /* Check if the library is in the pkcs11.conf file */ 213 if ((puent = getent_uef(libname)) == NULL) { 214 cryptoerror(LOG_STDERR, 215 gettext("%s does not exist."), libname); 216 return (FAILURE); 217 } 218 free_uentry(puent); 219 220 /* Remove $ISA from the library name */ 221 if (strlcpy(buf, libname, sizeof (buf)) >= sizeof (buf)) { 222 (void) printf(gettext("%s: the provider name is too long."), 223 libname); 224 return (FAILURE); 225 } 226 227 if ((isa = strstr(buf, PKCS11_ISA)) != NULL) { 228 *isa = '\000'; 229 isa += strlen(PKCS11_ISA); 230 (void) snprintf(libpath, MAXPATHLEN, "%s%s%s", buf, "/", isa); 231 } else { 232 (void) strlcpy(libpath, libname, sizeof (libpath)); 233 } 234 235 /* Open the provider */ 236 dldesc = dlopen(libpath, RTLD_NOW); 237 if (dldesc == NULL) { 238 dl_error = dlerror(); 239 cryptodebug("Cannot load PKCS#11 library %s. dlerror: %s", 240 libname, dl_error != NULL ? dl_error : "Unknown"); 241 rc = FAILURE; 242 goto clean_exit; 243 } 244 245 /* Get the pointer to provider's C_GetFunctionList() */ 246 Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList"); 247 if (Tmp_C_GetFunctionList == NULL) { 248 cryptodebug("Cannot get the address of the C_GetFunctionList " 249 "from %s", libname); 250 rc = FAILURE; 251 goto clean_exit; 252 } 253 254 /* Get the provider's function list */ 255 rv = Tmp_C_GetFunctionList(&prov_funcs); 256 if (rv != CKR_OK) { 257 cryptodebug("failed to call C_GetFunctionList from %s", 258 libname); 259 rc = FAILURE; 260 goto clean_exit; 261 } 262 263 /* Initialize this provider */ 264 rv = prov_funcs->C_Initialize(NULL_PTR); 265 if (rv != CKR_OK) { 266 cryptodebug("failed to call C_Initialize from %s, " 267 "return code = %d", libname, rv); 268 rc = FAILURE; 269 goto clean_exit; 270 } else { 271 lib_initialized = B_TRUE; 272 } 273 274 /* 275 * Find out how many slots this provider has, call with tokenPresent 276 * set to FALSE so all potential slots are returned. 277 */ 278 rv = prov_funcs->C_GetSlotList(FALSE, NULL_PTR, &slot_count); 279 if (rv != CKR_OK) { 280 cryptodebug("failed to get the slotlist from %s.", libname); 281 rc = FAILURE; 282 goto clean_exit; 283 } else if (slot_count == 0) { 284 if (!no_warn) 285 (void) printf(gettext("%s: no slots presented.\n"), 286 libname); 287 rc = SUCCESS; 288 goto clean_exit; 289 } 290 291 /* Allocate memory for the slot list */ 292 prov_slots = malloc(slot_count * sizeof (CK_SLOT_ID)); 293 if (prov_slots == NULL) { 294 cryptodebug("out of memory."); 295 rc = FAILURE; 296 goto clean_exit; 297 } 298 299 /* Get the slot list from provider */ 300 rv = prov_funcs->C_GetSlotList(FALSE, prov_slots, &slot_count); 301 if (rv != CKR_OK) { 302 cryptodebug("failed to call C_GetSlotList() from %s.", 303 libname); 304 rc = FAILURE; 305 goto clean_exit; 306 } 307 308 if (verbose) { 309 (void) printf(gettext("Number of slots: %d\n"), slot_count); 310 } 311 312 /* Get the mechanism list for each slot */ 313 for (i = 0; i < slot_count; i++) { 314 if (verbose) 315 /* 316 * TRANSLATION_NOTE 317 * In some languages, the # symbol should be 318 * converted to "no", an "n" followed by a 319 * superscript "o".. 320 */ 321 (void) printf(gettext("\nSlot #%d\n"), i+1); 322 323 if ((rng_flag != NULL) && (*rng_flag == NO_RNG)) { 324 if (check_random(prov_slots[i], prov_funcs)) { 325 *rng_flag = HAS_RNG; 326 rc = SUCCESS; 327 goto clean_exit; 328 } else 329 continue; 330 } 331 332 rv = prov_funcs->C_GetSlotInfo(prov_slots[i], &slotinfo); 333 if (rv != CKR_OK) { 334 cryptodebug("failed to get slotinfo from %s", libname); 335 rc = FAILURE; 336 break; 337 } 338 if (verbose) { 339 CK_TOKEN_INFO tokeninfo; 340 341 (void) printf(gettext("Description: %.64s\n" 342 "Manufacturer: %.32s\n" 343 "PKCS#11 Version: %d.%d\n"), 344 slotinfo.slotDescription, 345 slotinfo.manufacturerID, 346 prov_funcs->version.major, 347 prov_funcs->version.minor); 348 349 (void) printf(gettext("Hardware Version: %d.%d\n" 350 "Firmware Version: %d.%d\n"), 351 slotinfo.hardwareVersion.major, 352 slotinfo.hardwareVersion.minor, 353 slotinfo.firmwareVersion.major, 354 slotinfo.firmwareVersion.minor); 355 356 (void) printf(gettext("Token Present: %s\n"), 357 (slotinfo.flags & CKF_TOKEN_PRESENT ? 358 gettext("True") : gettext("False"))); 359 360 display_slot_flags(slotinfo.flags); 361 362 rv = prov_funcs->C_GetTokenInfo(prov_slots[i], 363 &tokeninfo); 364 if (rv != CKR_OK) { 365 cryptodebug("Failed to get " 366 "token info from %s", libname); 367 rc = FAILURE; 368 break; 369 } 370 371 (void) printf(gettext("Token Label: %.32s\n" 372 "Manufacturer ID: %.32s\n" 373 "Model: %.16s\n" 374 "Serial Number: %.16s\n" 375 "Hardware Version: %d.%d\n" 376 "Firmware Version: %d.%d\n" 377 "UTC Time: %.16s\n" 378 "PIN Min Length: %d\n" 379 "PIN Max Length: %d\n"), 380 tokeninfo.label, 381 tokeninfo.manufacturerID, 382 tokeninfo.model, 383 tokeninfo.serialNumber, 384 tokeninfo.hardwareVersion.major, 385 tokeninfo.hardwareVersion.minor, 386 tokeninfo.firmwareVersion.major, 387 tokeninfo.firmwareVersion.minor, 388 tokeninfo.utcTime, 389 tokeninfo.ulMinPinLen, 390 tokeninfo.ulMaxPinLen); 391 392 display_token_flags(tokeninfo.flags); 393 } 394 395 if (mlist == NULL) { 396 rv = prov_funcs->C_GetMechanismList(prov_slots[i], 397 NULL_PTR, &mech_count); 398 if (rv != CKR_OK) { 399 cryptodebug( 400 "failed to call C_GetMechanismList() " 401 "from %s.", libname); 402 rc = FAILURE; 403 break; 404 } 405 406 if (mech_count == 0) { 407 /* no mechanisms in this slot */ 408 continue; 409 } 410 411 pmech_list = malloc(mech_count * 412 sizeof (CK_MECHANISM_TYPE)); 413 if (pmech_list == NULL) { 414 cryptodebug("out of memory"); 415 rc = FAILURE; 416 break; 417 } 418 419 /* Get the actual mechanism list */ 420 rv = prov_funcs->C_GetMechanismList(prov_slots[i], 421 pmech_list, &mech_count); 422 if (rv != CKR_OK) { 423 cryptodebug( 424 "failed to call C_GetMechanismList() " 425 "from %s.", libname); 426 (void) free(pmech_list); 427 rc = FAILURE; 428 break; 429 } 430 } else { 431 /* use the mechanism list passed in */ 432 rc = convert_mechlist(&pmech_list, &mech_count, mlist); 433 if (rc != SUCCESS) { 434 goto clean_exit; 435 } 436 } 437 if (show_mechs) 438 (void) printf(gettext("Mechanisms:\n")); 439 440 if (verbose && show_mechs) { 441 display_verbose_mech_header(); 442 } 443 /* 444 * Merge the current mechanism list into the returning 445 * mechanism list. 446 */ 447 for (j = 0; show_mechs && j < mech_count; j++) { 448 CK_MECHANISM_TYPE mech = pmech_list[j]; 449 450 if (mech >= CKM_VENDOR_DEFINED) { 451 (void) printf("%#lx", mech); 452 } else { 453 mech_name = pkcs11_mech2str(mech); 454 (void) printf("%-29s", mech_name); 455 } 456 457 if (verbose) { 458 CK_MECHANISM_INFO mech_info; 459 rv = prov_funcs->C_GetMechanismInfo( 460 prov_slots[i], mech, &mech_info); 461 if (rv != CKR_OK) { 462 cryptodebug( 463 "failed to call " 464 "C_GetMechanismInfo() from %s.", 465 libname); 466 (void) free(pmech_list); 467 rc = FAILURE; 468 break; 469 } 470 display_mech_info(&mech_info); 471 } 472 (void) printf("\n"); 473 } 474 (void) free(pmech_list); 475 if (rc == FAILURE) { 476 break; 477 } 478 } 479 480 if (rng_flag != NULL || rc == FAILURE) { 481 goto clean_exit; 482 } 483 484 clean_exit: 485 486 if (rc == FAILURE) { 487 (void) printf(gettext( 488 "%s: failed to retrieve the mechanism list.\n"), libname); 489 } 490 491 if (lib_initialized) { 492 (void) prov_funcs->C_Finalize(NULL_PTR); 493 } 494 495 if (dldesc != NULL) { 496 (void) dlclose(dldesc); 497 } 498 499 if (prov_slots != NULL) { 500 (void) free(prov_slots); 501 } 502 503 return (rc); 504 } 505 506 507 /* 508 * Display the mechanism policy for a user-level library 509 */ 510 int 511 list_policy_for_lib(char *libname) 512 { 513 uentry_t *puent = NULL; 514 int rc; 515 516 if (libname == NULL) { 517 /* should not happen */ 518 cryptoerror(LOG_STDERR, gettext("internal error.")); 519 cryptodebug("list_policy_for_lib() - libname is NULL."); 520 return (FAILURE); 521 } 522 523 /* Get the library entry from the pkcs11.conf file */ 524 if ((puent = getent_uef(libname)) == NULL) { 525 cryptoerror(LOG_STDERR, 526 gettext("%s does not exist."), libname); 527 return (FAILURE); 528 } 529 530 /* Print the policy for this library */ 531 rc = print_uef_policy(puent); 532 free_uentry(puent); 533 534 return (rc); 535 } 536 537 538 /* 539 * Disable mechanisms for a user-level library 540 */ 541 int 542 disable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag, 543 mechlist_t *marglist) 544 { 545 uentry_t *puent; 546 int rc; 547 548 if (libname == NULL) { 549 /* should not happen */ 550 cryptoerror(LOG_STDERR, gettext("internal error.")); 551 cryptodebug("disable_uef_lib() - libname is NULL."); 552 return (FAILURE); 553 } 554 555 /* Get the provider entry from the pkcs11.conf file */ 556 if ((puent = getent_uef(libname)) == NULL) { 557 cryptoerror(LOG_STDERR, 558 gettext("%s does not exist."), libname); 559 return (FAILURE); 560 } 561 562 /* 563 * Update the mechanism policy of this library entry, based on 564 * the current policy mode of the library and the mechanisms specified 565 * in CLI. 566 */ 567 if (allflag) { 568 /* 569 * If disabling all, just need to clean up the policylist and 570 * set the flag_enabledlist flag to be B_TRUE. 571 */ 572 free_umechlist(puent->policylist); 573 puent->policylist = NULL; 574 puent->count = 0; 575 puent->flag_enabledlist = B_TRUE; 576 rc = SUCCESS; 577 } else if (marglist != NULL) { 578 if (puent->flag_enabledlist == B_TRUE) { 579 /* 580 * The current default policy mode of this library 581 * is "all are disabled, except ...", so if a 582 * specified mechanism is in the exception list 583 * (the policylist), delete it from the policylist. 584 */ 585 rc = update_policylist(puent, marglist, DELETE_MODE); 586 } else { 587 /* 588 * The current default policy mode of this library 589 * is "all are enabled", so if a specified mechanism 590 * is not in the exception list (policylist), add 591 * it into the policylist. 592 */ 593 rc = update_policylist(puent, marglist, ADD_MODE); 594 } 595 } else if (!rndflag) { 596 /* should not happen */ 597 cryptoerror(LOG_STDERR, gettext("internal error.")); 598 cryptodebug("disable_uef_lib() - wrong arguments."); 599 return (FAILURE); 600 } 601 602 if (rndflag) 603 puent->flag_norandom = B_TRUE; 604 605 if (rc == FAILURE) { 606 free_uentry(puent); 607 return (FAILURE); 608 } 609 610 /* Update the pkcs11.conf file with the updated entry */ 611 rc = update_pkcs11conf(puent); 612 free_uentry(puent); 613 return (rc); 614 } 615 616 617 /* 618 * Enable disabled mechanisms for a user-level library. 619 */ 620 int 621 enable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag, 622 mechlist_t *marglist) 623 { 624 uentry_t *puent; 625 int rc = SUCCESS; 626 627 if (libname == NULL) { 628 /* should not happen */ 629 cryptoerror(LOG_STDERR, gettext("internal error.")); 630 cryptodebug("enable_uef_lib() - libname is NULL."); 631 return (FAILURE); 632 } 633 634 /* Get the provider entry from the pkcs11.conf file */ 635 if ((puent = getent_uef(libname)) == NULL) { 636 cryptoerror(LOG_STDERR, 637 gettext("%s does not exist."), libname); 638 return (FAILURE); 639 } 640 641 /* 642 * Update the mechanism policy of this library entry, based on 643 * the current policy mode of the library and the mechanisms 644 * specified in CLI. 645 */ 646 if (allflag) { 647 /* 648 * If enabling all, what needs to be done are cleaning up the 649 * policylist and setting the "flag_enabledlist" flag to 650 * B_FALSE. 651 */ 652 free_umechlist(puent->policylist); 653 puent->policylist = NULL; 654 puent->count = 0; 655 puent->flag_enabledlist = B_FALSE; 656 rc = SUCCESS; 657 } else if (marglist != NULL) { 658 if (puent->flag_enabledlist == B_TRUE) { 659 /* 660 * The current default policy mode of this library 661 * is "all are disabled, except ...", so if a 662 * specified mechanism is not in the exception list 663 * (policylist), add it. 664 */ 665 rc = update_policylist(puent, marglist, ADD_MODE); 666 } else { 667 /* 668 * The current default policy mode of this library 669 * is "all are enabled, except", so if a specified 670 * mechanism is in the exception list (policylist), 671 * delete it. 672 */ 673 rc = update_policylist(puent, marglist, DELETE_MODE); 674 } 675 } else if (!rndflag) { 676 /* should not come here */ 677 cryptoerror(LOG_STDERR, gettext("internal error.")); 678 cryptodebug("enable_uef_lib() - wrong arguments."); 679 return (FAILURE); 680 } 681 682 if (rndflag) 683 puent->flag_norandom = B_FALSE; 684 685 if (rc == FAILURE) { 686 free_uentry(puent); 687 return (FAILURE); 688 } 689 690 /* Update the pkcs11.conf file with the updated entry */ 691 rc = update_pkcs11conf(puent); 692 free_uentry(puent); 693 return (rc); 694 } 695 696 697 /* 698 * Install a user-level library. 699 */ 700 int 701 install_uef_lib(char *libname) 702 { 703 uentry_t *puent; 704 struct stat statbuf; 705 char libpath[MAXPATHLEN]; 706 char libbuf[MAXPATHLEN]; 707 char *isa; 708 709 if (libname == NULL) { 710 /* should not happen */ 711 cryptoerror(LOG_STDERR, gettext("internal error.")); 712 cryptodebug("install_uef_lib() - libname is NULL."); 713 return (FAILURE); 714 } 715 716 /* Check if the provider already exists in the framework */ 717 if ((puent = getent_uef(libname)) != NULL) { 718 cryptoerror(LOG_STDERR, gettext("%s exists already."), 719 libname); 720 free_uentry(puent); 721 return (FAILURE); 722 } 723 724 /* 725 * Check if the library exists in the system. if $ISA is in the 726 * path, only check the 32bit version. 727 */ 728 if (strlcpy(libbuf, libname, MAXPATHLEN) >= MAXPATHLEN) { 729 cryptoerror(LOG_STDERR, 730 gettext("the provider name is too long - %s"), libname); 731 return (FAILURE); 732 } 733 734 if ((isa = strstr(libbuf, PKCS11_ISA)) != NULL) { 735 *isa = '\000'; 736 isa += strlen(PKCS11_ISA); 737 (void) snprintf(libpath, sizeof (libpath), "%s%s%s", libbuf, 738 "/", isa); 739 } else { 740 (void) strlcpy(libpath, libname, sizeof (libpath)); 741 } 742 743 /* Check if it is same as the framework library */ 744 if (strcmp(libpath, UEF_FRAME_LIB) == 0) { 745 cryptoerror(LOG_STDERR, gettext( 746 "The framework library %s can not be installed."), 747 libname); 748 return (FAILURE); 749 } 750 751 if (stat(libpath, &statbuf) != 0) { 752 cryptoerror(LOG_STDERR, gettext("%s not found"), libname); 753 return (FAILURE); 754 } 755 756 /* Need to add "\n" to libname for adding into the config file */ 757 if (strlcat(libname, "\n", MAXPATHLEN) >= MAXPATHLEN) { 758 cryptoerror(LOG_STDERR, gettext( 759 "can not install %s; the name is too long."), libname); 760 return (FAILURE); 761 } 762 763 return (update_conf(_PATH_PKCS11_CONF, libname)); 764 765 } 766 767 768 /* 769 * Uninstall a user-level library. 770 */ 771 int 772 uninstall_uef_lib(char *libname) 773 { 774 uentry_t *puent; 775 FILE *pfile; 776 FILE *pfile_tmp; 777 char buffer[BUFSIZ]; 778 char buffer2[BUFSIZ]; 779 char tmpfile_name[MAXPATHLEN]; 780 char *name; 781 boolean_t found; 782 boolean_t in_package; 783 int len; 784 int rc = SUCCESS; 785 786 if (libname == NULL) { 787 /* should not happen */ 788 cryptoerror(LOG_STDERR, gettext("internal error.")); 789 cryptodebug("uninstall_uef_lib() - libname is NULL."); 790 return (FAILURE); 791 } 792 793 /* Check if the provider exists */ 794 if ((puent = getent_uef(libname)) == NULL) { 795 cryptoerror(LOG_STDERR, 796 gettext("%s does not exist."), libname); 797 return (FAILURE); 798 } 799 free_uentry(puent); 800 801 /* Open the pkcs11.conf file and lock it */ 802 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) { 803 err = errno; 804 cryptoerror(LOG_STDERR, 805 gettext("failed to update the configuration - %s"), 806 strerror(err)); 807 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF); 808 return (FAILURE); 809 } 810 811 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 812 err = errno; 813 cryptoerror(LOG_STDERR, 814 gettext("failed to lock the configuration - %s"), 815 strerror(err)); 816 (void) fclose(pfile); 817 return (FAILURE); 818 } 819 820 /* 821 * Create a temporary file in the /etc/crypto directory to save 822 * the new configuration file first. 823 */ 824 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 825 if (mkstemp(tmpfile_name) == -1) { 826 err = errno; 827 cryptoerror(LOG_STDERR, 828 gettext("failed to create a temporary file - %s"), 829 strerror(err)); 830 (void) fclose(pfile); 831 return (FAILURE); 832 } 833 834 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 835 err = errno; 836 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 837 tmpfile_name, strerror(err)); 838 if (unlink(tmpfile_name) != 0) { 839 err = errno; 840 cryptoerror(LOG_STDERR, gettext( 841 "(Warning) failed to remove %s: %s"), 842 tmpfile_name, strerror(err)); 843 } 844 (void) fclose(pfile); 845 return (FAILURE); 846 } 847 848 849 /* 850 * Loop thru the config file. If the library to be uninstalled 851 * is in a package, just comment it off. 852 */ 853 in_package = B_FALSE; 854 while (fgets(buffer, BUFSIZ, pfile) != NULL) { 855 found = B_FALSE; 856 if (!(buffer[0] == ' ' || buffer[0] == '\n' || 857 buffer[0] == '\t')) { 858 if (strstr(buffer, " Start ") != NULL) { 859 in_package = B_TRUE; 860 } else if (strstr(buffer, " End ") != NULL) { 861 in_package = B_FALSE; 862 } else if (buffer[0] != '#') { 863 (void) strlcpy(buffer2, buffer, BUFSIZ); 864 865 /* get rid of trailing '\n' */ 866 len = strlen(buffer2); 867 if (buffer2[len-1] == '\n') { 868 len--; 869 } 870 buffer2[len] = '\0'; 871 872 if ((name = strtok(buffer2, SEP_COLON)) 873 == NULL) { 874 rc = FAILURE; 875 break; 876 } else if (strcmp(libname, name) == 0) { 877 found = B_TRUE; 878 } 879 } 880 } 881 882 if (found) { 883 if (in_package) { 884 (void) snprintf(buffer2, sizeof (buffer2), 885 "%s%s%s", "#", libname, "\n"); 886 if (fputs(buffer2, pfile_tmp) == EOF) { 887 rc = FAILURE; 888 } 889 } 890 } else { 891 if (fputs(buffer, pfile_tmp) == EOF) { 892 rc = FAILURE; 893 } 894 } 895 896 if (rc == FAILURE) { 897 break; 898 } 899 } 900 901 if (rc == FAILURE) { 902 cryptoerror(LOG_STDERR, gettext("write error.")); 903 (void) fclose(pfile); 904 (void) fclose(pfile_tmp); 905 if (unlink(tmpfile_name) != 0) { 906 err = errno; 907 cryptoerror(LOG_STDERR, gettext( 908 "(Warning) failed to remove %s: %s"), 909 tmpfile_name, strerror(err)); 910 } 911 return (FAILURE); 912 } 913 914 (void) fclose(pfile); 915 if (fclose(pfile_tmp) != 0) { 916 err = errno; 917 cryptoerror(LOG_STDERR, 918 gettext("failed to close a temporary file - %s"), 919 strerror(err)); 920 return (FAILURE); 921 } 922 923 /* Now update the real config file */ 924 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) { 925 err = errno; 926 cryptoerror(LOG_STDERR, 927 gettext("failed to update the configuration - %s"), 928 strerror(err)); 929 cryptodebug("failed to rename %s to %s: %s", tmpfile, 930 _PATH_PKCS11_CONF, strerror(err)); 931 rc = FAILURE; 932 } else if (chmod(_PATH_PKCS11_CONF, 933 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 934 err = errno; 935 cryptoerror(LOG_STDERR, 936 gettext("failed to update the configuration - %s"), 937 strerror(err)); 938 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF, 939 strerror(err)); 940 rc = FAILURE; 941 } else { 942 rc = SUCCESS; 943 } 944 945 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 946 err = errno; 947 cryptoerror(LOG_STDERR, gettext( 948 "(Warning) failed to remove %s: %s"), 949 tmpfile_name, strerror(err)); 950 } 951 952 return (rc); 953 } 954 955 956 int 957 display_policy(uentry_t *puent) 958 { 959 CK_MECHANISM_TYPE mech_id; 960 const char *mech_name; 961 umechlist_t *ptr; 962 963 if (puent == NULL) { 964 return (SUCCESS); 965 } 966 967 if (puent->flag_enabledlist == B_FALSE) { 968 (void) printf(gettext("%s: all mechanisms are enabled"), 969 puent->name); 970 ptr = puent->policylist; 971 if (ptr == NULL) { 972 (void) printf("."); 973 } else { 974 (void) printf(gettext(", except ")); 975 while (ptr != NULL) { 976 mech_id = strtoul(ptr->name, NULL, 0); 977 if (mech_id & CKO_VENDOR_DEFINED) { 978 /* vendor defined mechanism */ 979 (void) printf("%s", ptr->name); 980 } else { 981 if (mech_id >= CKM_VENDOR_DEFINED) { 982 (void) printf("%#lx", mech_id); 983 } else { 984 mech_name = pkcs11_mech2str( 985 mech_id); 986 if (mech_name == NULL) { 987 return (FAILURE); 988 } 989 (void) printf("%s", mech_name); 990 } 991 } 992 993 ptr = ptr->next; 994 if (ptr == NULL) { 995 (void) printf("."); 996 } else { 997 (void) printf(","); 998 } 999 } 1000 } 1001 } else { /* puent->flag_enabledlist == B_TRUE */ 1002 (void) printf(gettext("%s: all mechanisms are disabled"), 1003 puent->name); 1004 ptr = puent->policylist; 1005 if (ptr == NULL) { 1006 (void) printf("."); 1007 } else { 1008 (void) printf(gettext(", except ")); 1009 while (ptr != NULL) { 1010 mech_id = strtoul(ptr->name, NULL, 0); 1011 if (mech_id & CKO_VENDOR_DEFINED) { 1012 /* vendor defined mechanism */ 1013 (void) printf("%s", ptr->name); 1014 } else { 1015 mech_name = pkcs11_mech2str(mech_id); 1016 if (mech_name == NULL) { 1017 return (FAILURE); 1018 } 1019 (void) printf("%s", mech_name); 1020 } 1021 ptr = ptr->next; 1022 if (ptr == NULL) { 1023 (void) printf("."); 1024 } else { 1025 (void) printf(","); 1026 } 1027 } 1028 } 1029 } 1030 return (SUCCESS); 1031 } 1032 1033 1034 1035 /* 1036 * Print out the mechanism policy for a user-level provider pointed by puent. 1037 */ 1038 int 1039 print_uef_policy(uentry_t *puent) 1040 { 1041 flag_val_t rng_flag; 1042 1043 if (puent == NULL) { 1044 return (FAILURE); 1045 } 1046 1047 rng_flag = NO_RNG; 1048 if (list_mechlist_for_lib(puent->name, NULL, &rng_flag, B_TRUE, 1049 B_FALSE, B_FALSE) != SUCCESS) { 1050 cryptoerror(LOG_STDERR, 1051 gettext("%s internal error."), puent->name); 1052 return (FAILURE); 1053 } 1054 1055 if (display_policy(puent) != SUCCESS) { 1056 goto failed_exit; 1057 } 1058 1059 1060 if (puent->flag_norandom == B_TRUE) 1061 /* 1062 * TRANSLATION_NOTE 1063 * "random" is a keyword and not to be translated. 1064 */ 1065 (void) printf(gettext(" %s is disabled."), "random"); 1066 else { 1067 if (rng_flag == HAS_RNG) 1068 /* 1069 * TRANSLATION_NOTE 1070 * "random" is a keyword and not to be translated. 1071 */ 1072 (void) printf(gettext(" %s is enabled."), "random"); 1073 } 1074 (void) printf("\n"); 1075 1076 return (SUCCESS); 1077 1078 failed_exit: 1079 1080 (void) printf(gettext("\nout of memory.\n")); 1081 return (FAILURE); 1082 } 1083 1084 1085 /* 1086 * Check if the mechanism is in the mechanism list. 1087 */ 1088 static boolean_t 1089 is_in_policylist(midstr_t mechname, umechlist_t *plist) 1090 { 1091 boolean_t found = B_FALSE; 1092 1093 if (mechname == NULL) { 1094 return (B_FALSE); 1095 } 1096 1097 while (plist != NULL) { 1098 if (strcmp(plist->name, mechname) == 0) { 1099 found = B_TRUE; 1100 break; 1101 } 1102 plist = plist->next; 1103 } 1104 1105 return (found); 1106 } 1107 1108 1109 /* 1110 * Update the pkcs11.conf file with the updated entry. 1111 */ 1112 int 1113 update_pkcs11conf(uentry_t *puent) 1114 { 1115 FILE *pfile; 1116 FILE *pfile_tmp; 1117 char buffer[BUFSIZ]; 1118 char buffer2[BUFSIZ]; 1119 char tmpfile_name[MAXPATHLEN]; 1120 char *name; 1121 char *str; 1122 int len; 1123 int rc = SUCCESS; 1124 boolean_t found; 1125 1126 if (puent == NULL) { 1127 cryptoerror(LOG_STDERR, gettext("internal error.")); 1128 return (FAILURE); 1129 } 1130 1131 /* Open the pkcs11.conf file */ 1132 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) { 1133 err = errno; 1134 cryptoerror(LOG_STDERR, 1135 gettext("failed to update the configuration - %s"), 1136 strerror(err)); 1137 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF); 1138 return (FAILURE); 1139 } 1140 1141 /* Lock the pkcs11.conf file */ 1142 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 1143 err = errno; 1144 cryptoerror(LOG_STDERR, 1145 gettext("failed to update the configuration - %s"), 1146 strerror(err)); 1147 (void) fclose(pfile); 1148 return (FAILURE); 1149 } 1150 1151 /* 1152 * Create a temporary file in the /etc/crypto directory to save 1153 * updated configuration file first. 1154 */ 1155 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 1156 if (mkstemp(tmpfile_name) == -1) { 1157 err = errno; 1158 cryptoerror(LOG_STDERR, 1159 gettext("failed to create a temporary file - %s"), 1160 strerror(err)); 1161 (void) fclose(pfile); 1162 return (FAILURE); 1163 } 1164 1165 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 1166 err = errno; 1167 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 1168 tmpfile_name, strerror(err)); 1169 if (unlink(tmpfile_name) != 0) { 1170 err = errno; 1171 cryptoerror(LOG_STDERR, gettext( 1172 "(Warning) failed to remove %s: %s"), 1173 tmpfile_name, strerror(err)); 1174 } 1175 (void) fclose(pfile); 1176 return (FAILURE); 1177 } 1178 1179 1180 /* 1181 * Loop thru entire pkcs11.conf file, update the entry to be 1182 * updated and save the updated file to the temporary file first. 1183 */ 1184 while (fgets(buffer, BUFSIZ, pfile) != NULL) { 1185 found = B_FALSE; 1186 if (!(buffer[0] == '#' || buffer[0] == ' ' || 1187 buffer[0] == '\n'|| buffer[0] == '\t')) { 1188 /* 1189 * Get the provider name from this line and check if 1190 * this is the entry to be updated. Note: can not use 1191 * "buffer" directly because strtok will change its 1192 * value. 1193 */ 1194 (void) strlcpy(buffer2, buffer, BUFSIZ); 1195 1196 /* get rid of trailing '\n' */ 1197 len = strlen(buffer2); 1198 if (buffer2[len-1] == '\n') { 1199 len--; 1200 } 1201 buffer2[len] = '\0'; 1202 1203 if ((name = strtok(buffer2, SEP_COLON)) == NULL) { 1204 rc = FAILURE; 1205 break; 1206 } else if (strcmp(puent->name, name) == 0) { 1207 found = B_TRUE; 1208 } 1209 } 1210 1211 if (found) { 1212 /* 1213 * This is the entry to be modified, get the updated 1214 * string. 1215 */ 1216 if ((str = uent2str(puent)) == NULL) { 1217 rc = FAILURE; 1218 break; 1219 } else { 1220 (void) strlcpy(buffer, str, BUFSIZ); 1221 free(str); 1222 } 1223 } 1224 1225 if (fputs(buffer, pfile_tmp) == EOF) { 1226 err = errno; 1227 cryptoerror(LOG_STDERR, gettext( 1228 "failed to write to a temp file: %s."), 1229 strerror(err)); 1230 rc = FAILURE; 1231 break; 1232 } 1233 } 1234 1235 if (rc == FAILURE) { 1236 (void) fclose(pfile); 1237 (void) fclose(pfile_tmp); 1238 if (unlink(tmpfile_name) != 0) { 1239 err = errno; 1240 cryptoerror(LOG_STDERR, gettext( 1241 "(Warning) failed to remove %s: %s"), 1242 tmpfile_name, strerror(err)); 1243 } 1244 return (FAILURE); 1245 } 1246 1247 (void) fclose(pfile); 1248 if (fclose(pfile_tmp) != 0) { 1249 err = errno; 1250 cryptoerror(LOG_STDERR, 1251 gettext("failed to close %s: %s"), tmpfile_name, 1252 strerror(err)); 1253 return (FAILURE); 1254 } 1255 1256 /* Copy the temporary file to the pkcs11.conf file */ 1257 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) { 1258 err = errno; 1259 cryptoerror(LOG_STDERR, 1260 gettext("failed to update the configuration - %s"), 1261 strerror(err)); 1262 cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 1263 _PATH_PKCS11_CONF, strerror(err)); 1264 rc = FAILURE; 1265 } else if (chmod(_PATH_PKCS11_CONF, 1266 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 1267 err = errno; 1268 cryptoerror(LOG_STDERR, 1269 gettext("failed to update the configuration - %s"), 1270 strerror(err)); 1271 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF, 1272 strerror(err)); 1273 rc = FAILURE; 1274 } else { 1275 rc = SUCCESS; 1276 } 1277 1278 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 1279 err = errno; 1280 cryptoerror(LOG_STDERR, gettext( 1281 "(Warning) failed to remove %s: %s"), 1282 tmpfile_name, strerror(err)); 1283 } 1284 1285 return (rc); 1286 } 1287 1288 1289 /* 1290 * Convert an uentry to a character string 1291 */ 1292 static char * 1293 uent2str(uentry_t *puent) 1294 { 1295 umechlist_t *phead; 1296 boolean_t tok1_present = B_FALSE; 1297 char *buf; 1298 char blank_buf[128]; 1299 1300 if (puent == NULL) { 1301 cryptoerror(LOG_STDERR, gettext("internal error.")); 1302 return (NULL); 1303 } 1304 1305 buf = malloc(BUFSIZ); 1306 if (buf == NULL) { 1307 cryptoerror(LOG_STDERR, gettext("out of memory.")); 1308 return (NULL); 1309 } 1310 1311 /* convert the library name */ 1312 if (strlcpy(buf, puent->name, BUFSIZ) >= BUFSIZ) { 1313 free(buf); 1314 return (NULL); 1315 } 1316 1317 1318 /* convert the enabledlist or the disabledlist */ 1319 if (puent->flag_enabledlist == B_TRUE) { 1320 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) { 1321 free(buf); 1322 return (NULL); 1323 } 1324 1325 if (strlcat(buf, EF_ENABLED, BUFSIZ) >= BUFSIZ) { 1326 free(buf); 1327 return (NULL); 1328 } 1329 1330 phead = puent->policylist; 1331 while (phead != NULL) { 1332 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) { 1333 free(buf); 1334 return (NULL); 1335 } 1336 1337 phead = phead->next; 1338 if (phead != NULL) { 1339 if (strlcat(buf, SEP_COMMA, BUFSIZ) 1340 >= BUFSIZ) { 1341 free(buf); 1342 return (NULL); 1343 } 1344 } 1345 } 1346 tok1_present = B_TRUE; 1347 } else if (puent->policylist != NULL) { 1348 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) { 1349 free(buf); 1350 return (NULL); 1351 } 1352 1353 if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) { 1354 free(buf); 1355 return (NULL); 1356 } 1357 phead = puent->policylist; 1358 while (phead != NULL) { 1359 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) { 1360 free(buf); 1361 return (NULL); 1362 } 1363 1364 phead = phead->next; 1365 if (phead != NULL) { 1366 if (strlcat(buf, SEP_COMMA, BUFSIZ) 1367 >= BUFSIZ) { 1368 free(buf); 1369 return (NULL); 1370 } 1371 } 1372 } 1373 tok1_present = B_TRUE; 1374 } 1375 1376 if (puent->flag_norandom == B_TRUE) { 1377 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON), 1378 BUFSIZ) >= BUFSIZ) { 1379 free(buf); 1380 return (NULL); 1381 } 1382 1383 if (strlcat(buf, EF_NORANDOM, BUFSIZ) >= BUFSIZ) { 1384 free(buf); 1385 return (NULL); 1386 } 1387 } 1388 1389 if (strcmp(puent->name, METASLOT_KEYWORD) == 0) { 1390 1391 /* write the metaslot_status= value */ 1392 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON), 1393 BUFSIZ) >= BUFSIZ) { 1394 free(buf); 1395 return (NULL); 1396 } 1397 1398 if (strlcat(buf, METASLOT_STATUS, BUFSIZ) >= BUFSIZ) { 1399 free(buf); 1400 return (NULL); 1401 } 1402 1403 if (puent->flag_metaslot_enabled) { 1404 if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) { 1405 free(buf); 1406 return (NULL); 1407 } 1408 } else { 1409 if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ) 1410 >= BUFSIZ) { 1411 free(buf); 1412 return (NULL); 1413 } 1414 } 1415 1416 if (!tok1_present) { 1417 tok1_present = B_TRUE; 1418 } 1419 1420 if (strlcat(buf, SEP_SEMICOLON, BUFSIZ) >= BUFSIZ) { 1421 free(buf); 1422 return (NULL); 1423 } 1424 1425 if (strlcat(buf, METASLOT_AUTO_KEY_MIGRATE, BUFSIZ) >= BUFSIZ) { 1426 free(buf); 1427 return (NULL); 1428 } 1429 1430 if (puent->flag_metaslot_auto_key_migrate) { 1431 if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) { 1432 free(buf); 1433 return (NULL); 1434 } 1435 } else { 1436 if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ) >= BUFSIZ) { 1437 free(buf); 1438 return (NULL); 1439 } 1440 } 1441 1442 bzero(blank_buf, sizeof (blank_buf)); 1443 1444 /* write metaslot_token= if specified */ 1445 if (memcmp(puent->metaslot_ks_token, blank_buf, 1446 TOKEN_LABEL_SIZE) != 0) { 1447 /* write the metaslot_status= value */ 1448 if (strlcat(buf, (tok1_present ? 1449 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) { 1450 free(buf); 1451 return (NULL); 1452 } 1453 1454 if (strlcat(buf, METASLOT_TOKEN, BUFSIZ) >= BUFSIZ) { 1455 free(buf); 1456 return (NULL); 1457 } 1458 1459 if (strlcat(buf, 1460 (const char *)puent->metaslot_ks_token, BUFSIZ) 1461 >= BUFSIZ) { 1462 free(buf); 1463 return (NULL); 1464 } 1465 } 1466 1467 /* write metaslot_slot= if specified */ 1468 if (memcmp(puent->metaslot_ks_slot, blank_buf, 1469 SLOT_DESCRIPTION_SIZE) != 0) { 1470 /* write the metaslot_status= value */ 1471 if (strlcat(buf, (tok1_present ? 1472 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) { 1473 free(buf); 1474 return (NULL); 1475 } 1476 1477 if (strlcat(buf, METASLOT_SLOT, BUFSIZ) >= BUFSIZ) { 1478 free(buf); 1479 return (NULL); 1480 } 1481 1482 if (strlcat(buf, 1483 (const char *)puent->metaslot_ks_slot, BUFSIZ) 1484 >= BUFSIZ) { 1485 free(buf); 1486 return (NULL); 1487 } 1488 } 1489 } 1490 1491 if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) { 1492 free(buf); 1493 return (NULL); 1494 } 1495 1496 return (buf); 1497 } 1498 1499 1500 /* 1501 * This function updates the default policy mode and the policy exception list 1502 * for a user-level provider based on the mechanism specified in the disable 1503 * or enable subcommand and the update mode. This function is called by the 1504 * enable_uef_lib() or disable_uef_lib(). 1505 */ 1506 int 1507 update_policylist(uentry_t *puent, mechlist_t *marglist, int update_mode) 1508 { 1509 CK_MECHANISM_TYPE mech_type; 1510 midstr_t midname; 1511 umechlist_t *phead; 1512 umechlist_t *pcur; 1513 umechlist_t *pumech; 1514 boolean_t found; 1515 int rc = SUCCESS; 1516 1517 if ((puent == NULL) || (marglist == NULL)) { 1518 /* should not happen */ 1519 cryptoerror(LOG_STDERR, gettext("internal error.")); 1520 cryptodebug("update_policylist()- puent or marglist is NULL."); 1521 return (FAILURE); 1522 } 1523 1524 if ((update_mode != ADD_MODE) && (update_mode != DELETE_MODE)) { 1525 /* should not happen */ 1526 cryptoerror(LOG_STDERR, gettext("internal error.")); 1527 cryptodebug("update_policylist() - update_mode is incorrect."); 1528 return (FAILURE); 1529 } 1530 1531 /* 1532 * For each mechanism operand, get its mechanism type first. 1533 * If fails to get the mechanism type, the mechanism operand must be 1534 * invalid, gives an warning and ignore it. Otherwise, 1535 * - convert the mechanism type to the internal representation (hex) 1536 * in the pkcs11.conf file 1537 * - If update_mode == DELETE_MODE, 1538 * If the mechanism is in the policy list, delete it. 1539 * If the mechanism is not in the policy list, do nothing. 1540 * - If update_mode == ADD_MODE, 1541 * If the mechanism is not in the policy list, add it. 1542 * If the mechanism is in the policy list already, do nothing. 1543 */ 1544 while (marglist) { 1545 if (pkcs11_str2mech(marglist->name, &mech_type) != CKR_OK) { 1546 /* 1547 * This mechanism is not a valid PKCS11 mechanism, 1548 * give warning and ignore it. 1549 */ 1550 cryptoerror(LOG_STDERR, gettext( 1551 "(Warning) %s is not a valid PKCS#11 mechanism."), 1552 marglist->name); 1553 rc = FAILURE; 1554 } else { 1555 (void) snprintf(midname, sizeof (midname), "%#010x", 1556 (int)mech_type); 1557 if (update_mode == DELETE_MODE) { 1558 found = B_FALSE; 1559 phead = pcur = puent->policylist; 1560 while (!found && pcur) { 1561 if (strcmp(pcur->name, midname) == 0) { 1562 found = B_TRUE; 1563 } else { 1564 phead = pcur; 1565 pcur = pcur->next; 1566 } 1567 } 1568 1569 if (found) { 1570 if (phead == pcur) { 1571 puent->policylist = 1572 puent->policylist->next; 1573 free(pcur); 1574 } else { 1575 phead->next = pcur->next; 1576 free(pcur); 1577 } 1578 puent->count--; 1579 if (puent->count == 0) { 1580 puent->policylist = NULL; 1581 } 1582 } 1583 } else if (update_mode == ADD_MODE) { 1584 if (!is_in_policylist(midname, 1585 puent->policylist)) { 1586 pumech = create_umech(midname); 1587 if (pumech == NULL) { 1588 rc = FAILURE; 1589 break; 1590 } 1591 phead = puent->policylist; 1592 puent->policylist = pumech; 1593 pumech->next = phead; 1594 puent->count++; 1595 } 1596 } 1597 } 1598 marglist = marglist->next; 1599 } 1600 1601 return (rc); 1602 } 1603 1604 /* 1605 * Open a session to the given slot and check if we can do 1606 * random numbers by asking for one byte. 1607 */ 1608 static boolean_t 1609 check_random(CK_SLOT_ID slot_id, CK_FUNCTION_LIST_PTR prov_funcs) 1610 { 1611 CK_RV rv; 1612 CK_SESSION_HANDLE hSession; 1613 CK_BYTE test_byte; 1614 CK_BYTE_PTR test_byte_ptr = &test_byte; 1615 1616 rv = prov_funcs->C_OpenSession(slot_id, CKF_SERIAL_SESSION, 1617 NULL_PTR, NULL, &hSession); 1618 if (rv != CKR_OK) 1619 return (B_FALSE); 1620 1621 /* We care only about the return value */ 1622 rv = prov_funcs->C_GenerateRandom(hSession, test_byte_ptr, 1623 sizeof (test_byte)); 1624 (void) prov_funcs->C_CloseSession(hSession); 1625 1626 /* 1627 * These checks are purely to determine whether the slot can do 1628 * random numbers. So, we don't check whether the routine 1629 * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that 1630 * this error effectively means CKR_FUNCTION_NOT_SUPPORTED. 1631 */ 1632 if (rv != CKR_FUNCTION_NOT_SUPPORTED && rv != CKR_RANDOM_NO_RNG) 1633 return (B_TRUE); 1634 else 1635 return (B_FALSE); 1636 } 1637 1638 void 1639 display_verbose_mech_header() 1640 { 1641 (void) printf("%28s %s", " ", HDR1); 1642 (void) printf("%28s %s", " ", HDR2); 1643 (void) printf("%28s %s", " ", HDR3); 1644 (void) printf("%28s %s", " ", HDR4); 1645 (void) printf("%28s %s", " ", HDR5); 1646 (void) printf("%28s %s", " ", HDR6); 1647 (void) printf("%-28.28s %s", gettext("mechanism name"), HDR7); 1648 /* 1649 * TRANSLATION_NOTE 1650 * Strictly for appearance's sake, the first header line should be 1651 * as long as the length of the translated text above. The format 1652 * lengths should all match too. 1653 */ 1654 (void) printf("%28s ---- ---- " 1655 "- - - - - - - - - - - - - -\n", 1656 gettext("----------------------------")); 1657 } 1658 1659 int 1660 fips_update_pkcs11conf(int action) 1661 { 1662 1663 char *str; 1664 1665 if (action == FIPS140_ENABLE) 1666 str = "fips-140:fips_status=enabled\n"; 1667 else 1668 str = "fips-140:fips_status=disabled\n"; 1669 1670 if (update_conf(_PATH_PKCS11_CONF, str) != SUCCESS) 1671 return (FAILURE); 1672 1673 return (SUCCESS); 1674 } 1675 1676 void 1677 fips_status_pkcs11conf(int *status) 1678 { 1679 1680 uentry_t *puent = NULL; 1681 1682 if ((puent = getent_uef(FIPS_KEYWORD)) == NULL) { 1683 /* 1684 * By default (no fips-140 entry), we assume fips-140 1685 * mode is disabled. 1686 */ 1687 *status = CRYPTO_FIPS_MODE_DISABLED; 1688 return; 1689 } 1690 1691 if (puent->flag_fips_enabled) 1692 *status = CRYPTO_FIPS_MODE_ENABLED; 1693 else 1694 *status = CRYPTO_FIPS_MODE_DISABLED; 1695 1696 return; 1697 1698 } 1699