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