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