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