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 reserved. 26 */ 27 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <dlfcn.h> 31 #include <fcntl.h> 32 #include <link.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <strings.h> 36 #include <errno.h> 37 #include <pthread.h> 38 #include <sys/mman.h> 39 40 #include <sys/crypto/elfsign.h> 41 #include <cryptoutil.h> 42 43 #include <security/cryptoki.h> 44 #include "pkcs11Global.h" 45 #include "pkcs11Conf.h" 46 #include "pkcs11Slot.h" 47 #include "metaGlobal.h" 48 49 /* 50 * Fastpath is used when there is only one slot available from a single provider 51 * plugged into the framework this is the common case. 52 * These globals are used to track the function pointers and policy when 53 * the fast-path is activated. 54 * This will need to be revisted if per-slot policy is ever 55 * implemented. 56 */ 57 boolean_t purefastpath = B_FALSE; 58 boolean_t policyfastpath = B_FALSE; 59 CK_FUNCTION_LIST_PTR fast_funcs = NULL; 60 CK_SLOT_ID fast_slot = 0; 61 boolean_t metaslot_enabled = B_FALSE; 62 boolean_t metaslot_auto_key_migrate = B_FALSE; 63 metaslot_config_t metaslot_config; 64 void (*Tmp_GetThreshold)(void *) = NULL; 65 cipher_mechs_threshold_t meta_mechs_threshold[MAX_NUM_THRESHOLD]; 66 67 static const char *conf_err = "See cryptoadm(1M). Skipping this plug-in."; 68 69 /* 70 * Set up metaslot for the framework using either user configuration 71 * or system wide configuration options 72 * 73 * Also sets up the global "slottable" to have the first slot be metaslot. 74 */ 75 static CK_RV 76 setup_metaslot(uentry_t *metaslot_entry) { 77 CK_RV rv; 78 CK_MECHANISM_TYPE_PTR prov_pol_mechs = NULL; 79 pkcs11_slot_t *cur_slot; 80 81 /* process policies for mechanisms */ 82 if ((metaslot_entry) && (metaslot_entry->count > 0)) { 83 rv = pkcs11_mech_parse(metaslot_entry->policylist, 84 &prov_pol_mechs, metaslot_entry->count); 85 86 if (rv == CKR_HOST_MEMORY) { 87 cryptoerror(LOG_ERR, 88 "libpkcs11: Could not parse configuration," 89 "out of memory. Cannot continue parsing " 90 "%s.\n", _PATH_PKCS11_CONF); 91 return (rv); 92 } else if (rv == CKR_MECHANISM_INVALID) { 93 /* 94 * Configuration file is corrupted for metaslot 95 */ 96 cryptoerror(LOG_ERR, 97 "libpkcs11: Policy invalid or corrupted " 98 "for metaslot. Use cryptoadm(1M) to fix " 99 "this. Disabling metaslot functionality.\n"); 100 metaslot_enabled = B_FALSE; 101 return (rv); 102 } 103 } 104 105 /* 106 * Check for metaslot policy. If all mechanisms are 107 * disabled, disable metaslot since there is nothing 108 * interesting for it to do 109 */ 110 if ((metaslot_entry) && (metaslot_entry->flag_enabledlist) && 111 (prov_pol_mechs == NULL)) { 112 metaslot_enabled = B_FALSE; 113 return (rv); 114 } 115 116 /* 117 * save system wide value for metaslot's keystore. 118 * If either slot description or token label is specified by 119 * the user, the system wide value for both is ignored. 120 */ 121 if ((metaslot_entry) && 122 (!metaslot_config.keystore_token_specified) && 123 (!metaslot_config.keystore_slot_specified)) { 124 /* 125 * blank_str is used for comparing with token label, 126 * and slot description, make sure it is better than 127 * the larger of both 128 */ 129 char blank_str[TOKEN_LABEL_SIZE + SLOT_DESCRIPTION_SIZE]; 130 131 bzero(blank_str, sizeof (blank_str)); 132 133 if (memcmp(metaslot_entry->metaslot_ks_token, 134 blank_str, TOKEN_LABEL_SIZE) != 0) { 135 metaslot_config.keystore_token_specified = B_TRUE; 136 (void) strlcpy( 137 (char *)metaslot_config.keystore_token, 138 (const char *)metaslot_entry->metaslot_ks_token, 139 TOKEN_LABEL_SIZE); 140 } 141 142 if (memcmp(metaslot_entry->metaslot_ks_slot, 143 blank_str, SLOT_DESCRIPTION_SIZE) != 0) { 144 metaslot_config.keystore_slot_specified = B_TRUE; 145 (void) strlcpy( 146 (char *)metaslot_config.keystore_slot, 147 (const char *)metaslot_entry->metaslot_ks_slot, 148 SLOT_DESCRIPTION_SIZE); 149 } 150 } 151 152 /* check system-wide value for auto_key_migrate */ 153 if (metaslot_config.auto_key_migrate_specified) { 154 /* take user's specified value */ 155 metaslot_auto_key_migrate = metaslot_config.auto_key_migrate; 156 } else { 157 if (metaslot_entry) { 158 /* use system-wide default */ 159 metaslot_auto_key_migrate = 160 metaslot_entry->flag_metaslot_auto_key_migrate; 161 } else { 162 /* 163 * there's no system wide metaslot entry, 164 * default auto_key_migrate to true 165 */ 166 metaslot_auto_key_migrate = B_TRUE; 167 } 168 } 169 170 171 /* Make first slotID be 0, for metaslot. */ 172 slottable->st_first = 0; 173 174 /* Set up the slottable entry for metaslot */ 175 slottable->st_slots[0] = NULL; 176 cur_slot = calloc(1, sizeof (pkcs11_slot_t)); 177 if (cur_slot == NULL) { 178 rv = CKR_HOST_MEMORY; 179 return (rv); 180 } 181 cur_slot->sl_wfse_state = WFSE_CLEAR; 182 cur_slot->sl_enabledpol = B_FALSE; 183 cur_slot->sl_no_wfse = B_FALSE; 184 (void) pthread_mutex_init(&cur_slot->sl_mutex, NULL); 185 186 /* 187 * The metaslot entry was prealloc'd by 188 * pkcs11_slottable_increase() 189 */ 190 (void) pthread_mutex_lock(&slottable->st_mutex); 191 slottable->st_slots[0] = cur_slot; 192 (void) pthread_mutex_unlock(&slottable->st_mutex); 193 194 (void) pthread_mutex_lock(&cur_slot->sl_mutex); 195 cur_slot->sl_id = METASLOT_SLOTID; 196 cur_slot->sl_func_list = &metaslot_functionList; 197 if (metaslot_entry) { 198 cur_slot->sl_enabledpol = metaslot_entry->flag_enabledlist; 199 cur_slot->sl_pol_count = metaslot_entry->count; 200 } else { 201 /* if no metaslot entry, assume all mechs are enabled */ 202 cur_slot->sl_enabledpol = B_FALSE; 203 cur_slot->sl_pol_count = 0; 204 } 205 cur_slot->sl_pol_mechs = prov_pol_mechs; 206 cur_slot->sl_dldesc = NULL; /* not applicable */ 207 cur_slot->sl_prov_id = 0; 208 (void) pthread_mutex_unlock(&cur_slot->sl_mutex); 209 210 /* Call the meta_Initialize() to initialize metaslot */ 211 rv = meta_Initialize(NULL); 212 if (rv != CKR_OK) { 213 cryptoerror(LOG_ERR, 214 "libpkcs11: Can't initialize metaslot (%s)", 215 pkcs11_strerror(rv)); 216 goto cleanup; 217 } 218 219 return (CKR_OK); 220 221 cleanup: 222 metaslot_enabled = B_FALSE; 223 slottable->st_slots[0] = NULL; 224 225 if (cur_slot) { 226 (void) pthread_mutex_destroy(&cur_slot->sl_mutex); 227 free(cur_slot); 228 } 229 return (rv); 230 } 231 232 /* 233 * For each provider found in pkcs11.conf: expand $ISA if necessary, 234 * verify the module is signed, load the provider, find all of its 235 * slots, and store the function list and disabled policy. 236 * 237 * This function requires that the uentrylist_t and pkcs11_slottable_t 238 * already have memory allocated, and that the uentrylist_t is already 239 * populated with provider and policy information. 240 * 241 * pInitArgs can be set to NULL, but is normally the same value 242 * the framework's C_Initialize() was called with. 243 * 244 * Unless metaslot is explicitly disabled, it is setup when all other 245 * providers are loaded. 246 */ 247 CK_RV 248 pkcs11_slot_mapping(uentrylist_t *pplist, CK_VOID_PTR pInitArgs) 249 { 250 CK_RV rv = CKR_OK; 251 CK_RV prov_rv; /* Provider's return code */ 252 CK_INFO prov_info; 253 CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR); 254 CK_FUNCTION_LIST_PTR prov_funcs = NULL; /* Provider's function list */ 255 CK_ULONG prov_slot_count; /* Number of slots */ 256 CK_SLOT_ID slot_id; /* slotID assigned for framework */ 257 CK_SLOT_ID_PTR prov_slots = NULL; /* Provider's slot list */ 258 /* Enabled or Disabled policy */ 259 CK_MECHANISM_TYPE_PTR prov_pol_mechs = NULL; 260 261 void *dldesc = NULL; 262 char *isa, *fullpath = NULL, *dl_error; 263 uentrylist_t *phead; 264 uint_t prov_count = 0; 265 pkcs11_slot_t *cur_slot; 266 CK_ULONG i; 267 size_t len; 268 uentry_t *metaslot_entry = NULL; 269 /* number of slots in the framework, not including metaslot */ 270 uint_t slot_count = 0; 271 272 phead = pplist; 273 274 /* Loop through all of the provider listed in pkcs11.conf */ 275 while (phead != NULL) { 276 if (!strcasecmp(phead->puent->name, "metaslot")) { 277 /* 278 * Skip standard processing for metaslot 279 * entry since it is not an actual library 280 * that can be dlopened. 281 * It will be initialized later. 282 */ 283 if (metaslot_entry != NULL) { 284 cryptoerror(LOG_ERR, 285 "libpkcs11: multiple entries for metaslot " 286 "detected. All but the first entry will " 287 "be ignored"); 288 } else { 289 metaslot_entry = phead->puent; 290 } 291 goto contparse; 292 } 293 294 if (!strcasecmp(phead->puent->name, FIPS_KEYWORD)) { 295 /* 296 * Skip standard processing for fips-140 297 * entry since it is not an actual library 298 * that can be dlopened. 299 */ 300 goto contparse; 301 } 302 303 /* Check for Instruction Set Architecture indicator */ 304 if ((isa = strstr(phead->puent->name, PKCS11_ISA)) != NULL) { 305 /* Substitute the architecture dependent path */ 306 len = strlen(phead->puent->name) - 307 strlen(PKCS11_ISA) + 308 strlen(PKCS11_ISA_DIR) + 1; 309 if ((fullpath = (char *)malloc(len)) == NULL) { 310 cryptoerror(LOG_ERR, 311 "libpksc11: parsing %s, out of memory. " 312 "Cannot continue parsing.", 313 _PATH_PKCS11_CONF); 314 rv = CKR_HOST_MEMORY; 315 goto conferror; 316 } 317 *isa = '\000'; 318 isa += strlen(PKCS11_ISA); 319 (void) snprintf(fullpath, len, "%s%s%s", 320 phead->puent->name, PKCS11_ISA_DIR, isa); 321 } else if ((fullpath = strdup(phead->puent->name)) == 0) { 322 cryptoerror(LOG_ERR, 323 "libpkcs11: parsing %s, out of memory. " 324 "Cannot continue parsing.", 325 _PATH_PKCS11_CONF); 326 rv = CKR_HOST_MEMORY; 327 goto conferror; 328 } 329 330 /* 331 * Open the provider. We assume all of our plugins have 332 * their symbols properly defined, so the use of RTLD_NOW 333 * to flush out errors immediately is not necessary. 334 * 335 * Note that for proper operation, all plugins must be 336 * built with direct bindings enabled. 337 */ 338 dldesc = dlopen(fullpath, RTLD_LAZY); 339 340 /* 341 * If we failed to load it, we will just skip this 342 * provider and move on to the next one. 343 */ 344 if (dldesc == NULL) { 345 dl_error = dlerror(); 346 cryptoerror(LOG_ERR, 347 "libpkcs11: Cannot load PKCS#11 library %s. " 348 "dlerror: %s. %s", 349 fullpath, dl_error != NULL ? dl_error : "Unknown", 350 conf_err); 351 goto contparse; 352 } 353 354 /* Get the pointer to provider's C_GetFunctionList() */ 355 Tmp_C_GetFunctionList = 356 (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList"); 357 358 /* 359 * If we failed to get the pointer to C_GetFunctionList(), 360 * skip this provider and continue to the next one. 361 */ 362 if (Tmp_C_GetFunctionList == NULL) { 363 cryptoerror(LOG_ERR, 364 "libpkcs11: Could not dlsym() C_GetFunctionList() " 365 "for %s. May not be a PKCS#11 library. %s", 366 fullpath, conf_err); 367 (void) dlclose(dldesc); 368 goto contparse; 369 } 370 371 372 /* Get the provider's function list */ 373 prov_rv = Tmp_C_GetFunctionList(&prov_funcs); 374 375 /* 376 * If we failed to get the provider's function list, 377 * skip this provider and continue to the next one. 378 */ 379 if (prov_rv != CKR_OK) { 380 cryptoerror(LOG_ERR, 381 "libpkcs11: Could not get function list for %s. " 382 "%s Error: %s.", 383 fullpath, conf_err, pkcs11_strerror(prov_rv)); 384 (void) dlclose(dldesc); 385 goto contparse; 386 } 387 388 /* Initialize this provider */ 389 prov_rv = prov_funcs->C_Initialize(pInitArgs); 390 391 /* 392 * If we failed to initialize this provider, 393 * skip this provider and continue to the next one. 394 */ 395 if ((prov_rv != CKR_OK) && 396 (prov_rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { 397 cryptoerror(LOG_ERR, 398 "libpkcs11: Could not initialize %s. " 399 "%s Error: %s.", 400 fullpath, conf_err, pkcs11_strerror(prov_rv)); 401 (void) dlclose(dldesc); 402 goto contparse; 403 } 404 405 /* 406 * Make sure this provider is implementing the same 407 * major version, and at least the same minor version 408 * that we are. 409 */ 410 prov_rv = prov_funcs->C_GetInfo(&prov_info); 411 412 /* 413 * If we can't verify that we are implementing the 414 * same major version, or if it is definitely not the same 415 * version, we need to skip this provider. 416 */ 417 if ((prov_rv != CKR_OK) || 418 (prov_info.cryptokiVersion.major != 419 CRYPTOKI_VERSION_MAJOR)) { 420 if (prov_rv != CKR_OK) { 421 cryptoerror(LOG_ERR, 422 "libpkcs11: Could not verify version of " 423 "%s. %s Error: %s.", fullpath, 424 conf_err, pkcs11_strerror(prov_rv)); 425 } else { 426 cryptoerror(LOG_ERR, 427 "libpkcs11: Only CRYPTOKI major version " 428 "%d is supported. %s is major " 429 "version %d. %s", 430 CRYPTOKI_VERSION_MAJOR, fullpath, 431 prov_info.cryptokiVersion.major, conf_err); 432 } 433 (void) prov_funcs->C_Finalize(NULL); 434 (void) dlclose(dldesc); 435 goto contparse; 436 } 437 438 /* 439 * Warn the administrator (at debug) that a provider with 440 * a significantly older or newer version of 441 * CRYPTOKI is being used. It should not cause 442 * problems, but logging a warning makes it easier 443 * to debug later. 444 */ 445 if ((prov_info.cryptokiVersion.minor < 446 CRYPTOKI_VERSION_WARN_MINOR) || 447 (prov_info.cryptokiVersion.minor > 448 CRYPTOKI_VERSION_MINOR)) { 449 cryptoerror(LOG_DEBUG, 450 "libpkcs11: %s CRYPTOKI minor version, %d, may " 451 "not be compatible with minor version %d.", 452 fullpath, prov_info.cryptokiVersion.minor, 453 CRYPTOKI_VERSION_MINOR); 454 } 455 456 /* 457 * Find out how many slots this provider has, 458 * call with tokenPresent set to FALSE so all 459 * potential slots are returned. 460 */ 461 prov_rv = prov_funcs->C_GetSlotList(FALSE, 462 NULL, &prov_slot_count); 463 464 /* 465 * If the call failed, or if no slots are returned, 466 * then skip this provider and continue to next one. 467 */ 468 if (prov_rv != CKR_OK) { 469 cryptoerror(LOG_ERR, 470 "libpksc11: Could not get slot list from %s. " 471 "%s Error: %s.", 472 fullpath, conf_err, pkcs11_strerror(prov_rv)); 473 (void) prov_funcs->C_Finalize(NULL); 474 (void) dlclose(dldesc); 475 goto contparse; 476 } 477 478 if (prov_slot_count == 0) { 479 cryptodebug("libpkcs11: No slots presented from %s. " 480 "Skipping this plug-in at this time.\n", 481 fullpath); 482 (void) prov_funcs->C_Finalize(NULL); 483 (void) dlclose(dldesc); 484 goto contparse; 485 } 486 487 /* Allocate memory for the slot list */ 488 prov_slots = calloc(prov_slot_count, sizeof (CK_SLOT_ID)); 489 490 if (prov_slots == NULL) { 491 cryptoerror(LOG_ERR, 492 "libpkcs11: Could not allocate memory for " 493 "plug-in slots. Cannot continue parsing %s\n", 494 _PATH_PKCS11_CONF); 495 rv = CKR_HOST_MEMORY; 496 goto conferror; 497 } 498 499 /* Get slot list from provider */ 500 prov_rv = prov_funcs->C_GetSlotList(FALSE, 501 prov_slots, &prov_slot_count); 502 503 /* if second call fails, drop this provider */ 504 if (prov_rv != CKR_OK) { 505 cryptoerror(LOG_ERR, 506 "libpkcs11: Second call to C_GetSlotList() for %s " 507 "failed. %s Error: %s.", 508 fullpath, conf_err, pkcs11_strerror(prov_rv)); 509 (void) prov_funcs->C_Finalize(NULL); 510 (void) dlclose(dldesc); 511 goto contparse; 512 } 513 514 /* 515 * Parse the list of disabled or enabled mechanisms, will 516 * apply to each of the provider's slots. 517 */ 518 if (phead->puent->count > 0) { 519 rv = pkcs11_mech_parse(phead->puent->policylist, 520 &prov_pol_mechs, phead->puent->count); 521 522 if (rv == CKR_HOST_MEMORY) { 523 cryptoerror(LOG_ERR, 524 "libpkcs11: Could not parse configuration," 525 "out of memory. Cannot continue parsing " 526 "%s.", _PATH_PKCS11_CONF); 527 goto conferror; 528 } else if (rv == CKR_MECHANISM_INVALID) { 529 /* 530 * Configuration file is corrupted for this 531 * provider. 532 */ 533 cryptoerror(LOG_ERR, 534 "libpkcs11: Policy invalid or corrupted " 535 "for %s. Use cryptoadm(1M) to fix " 536 "this. Skipping this plug-in.", 537 fullpath); 538 (void) prov_funcs->C_Finalize(NULL); 539 (void) dlclose(dldesc); 540 goto contparse; 541 } 542 } 543 544 /* Allocate memory in our slottable for these slots */ 545 rv = pkcs11_slottable_increase(prov_slot_count); 546 547 /* 548 * If any error is returned, it will be memory related, 549 * so we need to abort the attempt at filling the 550 * slottable. 551 */ 552 if (rv != CKR_OK) { 553 cryptoerror(LOG_ERR, 554 "libpkcs11: slottable could not increase. " 555 "Cannot continue parsing %s.", 556 _PATH_PKCS11_CONF); 557 goto conferror; 558 } 559 560 /* Configure information for each new slot */ 561 for (i = 0; i < prov_slot_count; i++) { 562 /* allocate slot in framework */ 563 rv = pkcs11_slot_allocate(&slot_id); 564 if (rv != CKR_OK) { 565 cryptoerror(LOG_ERR, 566 "libpkcs11: Could not allocate " 567 "new slot. Cannot continue parsing %s.", 568 _PATH_PKCS11_CONF); 569 goto conferror; 570 } 571 slot_count++; 572 cur_slot = slottable->st_slots[slot_id]; 573 (void) pthread_mutex_lock(&cur_slot->sl_mutex); 574 cur_slot->sl_id = prov_slots[i]; 575 cur_slot->sl_func_list = prov_funcs; 576 cur_slot->sl_enabledpol = 577 phead->puent->flag_enabledlist; 578 cur_slot->sl_pol_mechs = prov_pol_mechs; 579 cur_slot->sl_pol_count = phead->puent->count; 580 cur_slot->sl_norandom = phead->puent->flag_norandom; 581 cur_slot->sl_dldesc = dldesc; 582 cur_slot->sl_prov_id = prov_count + 1; 583 (void) pthread_mutex_unlock(&cur_slot->sl_mutex); 584 } 585 586 /* 587 * Get the pointer to private interface _SUNW_GetThreshold() 588 * in pkcs11_kernel. 589 */ 590 591 if (Tmp_GetThreshold == NULL) { 592 Tmp_GetThreshold = 593 (void(*)())dlsym(dldesc, "_SUNW_GetThreshold"); 594 595 /* Get the threshold values for the supported mechs */ 596 if (Tmp_GetThreshold != NULL) { 597 (void) memset(meta_mechs_threshold, 0, 598 sizeof (meta_mechs_threshold)); 599 Tmp_GetThreshold(meta_mechs_threshold); 600 } 601 } 602 603 /* Set and reset values to process next provider */ 604 prov_count++; 605 contparse: 606 prov_slot_count = 0; 607 Tmp_C_GetFunctionList = NULL; 608 prov_funcs = NULL; 609 dldesc = NULL; 610 if (fullpath != NULL) { 611 free(fullpath); 612 fullpath = NULL; 613 } 614 if (prov_slots != NULL) { 615 free(prov_slots); 616 prov_slots = NULL; 617 } 618 phead = phead->next; 619 } 620 621 if (slot_count == 0) { 622 /* 623 * there's no other slot in the framework, 624 * there is nothing to do 625 */ 626 goto config_complete; 627 } 628 629 /* determine if metaslot should be enabled */ 630 631 /* 632 * Check to see if any environment variable is defined 633 * by the user for configuring metaslot. Users' 634 * setting always take precedence over the system wide 635 * setting. So, we will first check for any user's 636 * defined env variables before looking at the system-wide 637 * configuration. 638 */ 639 get_user_metaslot_config(); 640 641 /* no metaslot entry in /etc/crypto/pkcs11.conf */ 642 if (!metaslot_entry) { 643 /* 644 * If user env variable indicates metaslot should be enabled, 645 * but there's no entry in /etc/crypto/pkcs11.conf for 646 * metaslot at all, will respect the user's defined value 647 */ 648 if ((metaslot_config.enabled_specified) && 649 (metaslot_config.enabled)) { 650 metaslot_enabled = B_TRUE; 651 } 652 } else { 653 if (!metaslot_config.enabled_specified) { 654 /* 655 * take system wide value if 656 * it is not specified by user 657 */ 658 metaslot_enabled 659 = metaslot_entry->flag_metaslot_enabled; 660 } else { 661 metaslot_enabled = metaslot_config.enabled; 662 } 663 } 664 665 /* 666 * 667 * As long as the user or system configuration file does not 668 * disable metaslot, it will be enabled regardless of the 669 * number of slots plugged into the framework. Therefore, 670 * metaslot is enabled even when there's only one slot 671 * plugged into the framework. This is necessary for 672 * presenting a consistent token label view to applications. 673 * 674 * However, for the case where there is only 1 slot plugged into 675 * the framework, we can use "fastpath". 676 * 677 * "fastpath" will pass all of the application's requests 678 * directly to the underlying provider. Only when policy is in 679 * effect will we need to keep slotID around. 680 * 681 * When metaslot is enabled, and fastpath is enabled, 682 * all the metaslot processing will be skipped. 683 * When there is only 1 slot, there's 684 * really not much metaslot can do in terms of combining functionality 685 * of different slots, and object migration. 686 * 687 */ 688 689 /* check to see if fastpath can be used */ 690 if (slottable->st_last == slottable->st_first) { 691 692 cur_slot = slottable->st_slots[slottable->st_first]; 693 694 (void) pthread_mutex_lock(&cur_slot->sl_mutex); 695 696 if ((cur_slot->sl_pol_count == 0) && 697 (!cur_slot->sl_enabledpol) && (!cur_slot->sl_norandom)) { 698 /* No policy is in effect, don't need slotid */ 699 fast_funcs = cur_slot->sl_func_list; 700 purefastpath = B_TRUE; 701 } else { 702 fast_funcs = cur_slot->sl_func_list; 703 fast_slot = slottable->st_first; 704 policyfastpath = B_TRUE; 705 } 706 707 (void) pthread_mutex_unlock(&cur_slot->sl_mutex); 708 } 709 710 if ((purefastpath || policyfastpath) && (!metaslot_enabled)) { 711 goto config_complete; 712 } 713 714 /* 715 * If we get here, there are more than 2 slots in the framework, 716 * we need to set up metaslot if it is enabled 717 */ 718 if (metaslot_enabled) { 719 rv = setup_metaslot(metaslot_entry); 720 if (rv != CKR_OK) { 721 goto conferror; 722 } 723 } 724 725 726 config_complete: 727 728 return (CKR_OK); 729 730 conferror: 731 /* 732 * This cleanup code is only exercised when a major, 733 * unrecoverable error like "out of memory". 734 */ 735 if (prov_funcs != NULL) { 736 (void) prov_funcs->C_Finalize(NULL); 737 } 738 if (dldesc != NULL) { 739 (void) dlclose(dldesc); 740 } 741 if (fullpath != NULL) { 742 free(fullpath); 743 fullpath = NULL; 744 } 745 if (prov_slots != NULL) { 746 free(prov_slots); 747 prov_slots = NULL; 748 } 749 750 return (rv); 751 } 752 753 /* 754 * pkcs11_mech_parse will take hex mechanism ids, as a list of 755 * strings, and convert them to CK_MECHANISM_TYPE_PTR. 756 */ 757 CK_RV 758 pkcs11_mech_parse(umechlist_t *str_list, CK_MECHANISM_TYPE_PTR *mech_list, 759 int mech_count) 760 { 761 CK_MECHANISM_TYPE_PTR tmp_list; 762 umechlist_t *shead = str_list; 763 764 tmp_list = malloc(mech_count * sizeof (CK_MECHANISM_TYPE)); 765 766 if (tmp_list == NULL) { 767 cryptoerror(LOG_ERR, "libpkcs11: parsing %s, out of memory. " 768 "Cannot continue.", 769 _PATH_PKCS11_CONF); 770 return (CKR_HOST_MEMORY); 771 } 772 773 *mech_list = tmp_list; 774 775 /* 776 * The following will loop mech_count times, as there are 777 * exactly mech_count items in the str_list. 778 */ 779 while (shead != NULL) { 780 CK_MECHANISM_TYPE cur_mech; 781 782 errno = 0; 783 784 /* 785 * "name" is a hexadecimal number, preceded by 0x. 786 */ 787 cur_mech = strtoul(shead->name, NULL, 16); 788 789 if ((cur_mech == 0) && 790 ((errno == EINVAL) || (errno == ERANGE))) { 791 free(mech_list); 792 return (CKR_MECHANISM_INVALID); 793 } 794 *tmp_list = (CK_MECHANISM_TYPE)cur_mech; 795 tmp_list++; 796 shead = shead->next; 797 } 798 799 return (CKR_OK); 800 } 801 802 /* 803 * pkcs11_is_dismech is provided a slotid and a mechanism. 804 * If mech is not disabled, then return B_FALSE. 805 */ 806 boolean_t 807 pkcs11_is_dismech(CK_SLOT_ID slotid, CK_MECHANISM_TYPE mech) 808 { 809 ulong_t i; 810 boolean_t enabled_pol; 811 CK_MECHANISM_TYPE_PTR pol_mechs; 812 ulong_t pol_count; 813 814 /* Find the associated slot and get the mech policy info */ 815 (void) pthread_mutex_lock(&slottable->st_slots[slotid]->sl_mutex); 816 enabled_pol = slottable->st_slots[slotid]->sl_enabledpol; 817 pol_mechs = slottable->st_slots[slotid]->sl_pol_mechs; 818 pol_count = slottable->st_slots[slotid]->sl_pol_count; 819 (void) pthread_mutex_unlock(&slottable->st_slots[slotid]->sl_mutex); 820 821 /* Check for policy */ 822 if ((!enabled_pol) && (pol_mechs == NULL)) { 823 /* no policy */ 824 return (B_FALSE); 825 } else if (pol_mechs == NULL) { 826 /* 827 * We have an empty enabled list, which means no 828 * mechanisms are exempted from this policy: all 829 * are disabled. 830 */ 831 return (B_TRUE); 832 } 833 834 for (i = 0; i < pol_count; i++) { 835 /* 836 * If it matches, return status based on this 837 * being and enabled or a disabled list of mechs. 838 */ 839 if (pol_mechs[i] == mech) { 840 return (enabled_pol ? B_FALSE : B_TRUE); 841 } 842 } 843 844 /* mech was not found in list */ 845 return (enabled_pol ? B_TRUE : B_FALSE); 846 } 847