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