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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <pthread.h> 29 #include <time.h> 30 #include <security/cryptoki.h> 31 #include "pkcs11Global.h" 32 #include "pkcs11Conf.h" 33 #include "pkcs11Slot.h" 34 #include "metaGlobal.h" 35 36 static void *listener_waitforslotevent(void *arg); 37 static void *child_waitforslotevent(void *arg); 38 39 /* 40 * C_GetSlotList is implemented entirely within this framework, 41 * using the slottable that was created during the call to 42 * C_Initialize in pkcs11_slot_mapping(). The plugged in providers 43 * are only queried when tokenPresent is set. 44 * 45 * If metaslot is enabled, the slot that provides keystore support 46 * needs to be hidden. Therefore, even when fastpath is enabled, 47 * we can't go through fastpath because the slot needs to be 48 * hidden. 49 */ 50 CK_RV 51 C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, 52 CK_ULONG_PTR pulCount) 53 { 54 55 CK_RV rv; 56 CK_RV prov_rv; 57 CK_SLOT_ID true_id; 58 CK_SLOT_INFO_PTR pinfo; 59 CK_SLOT_ID count = 0, i; 60 CK_SLOT_ID slot_id; /* slot ID for returning to the application */ 61 62 /* Check for a fastpath */ 63 if ((purefastpath || policyfastpath) && (!metaslot_enabled)) { 64 return (fast_funcs->C_GetSlotList(tokenPresent, pSlotList, 65 pulCount)); 66 } 67 68 if (!pkcs11_initialized) { 69 return (CKR_CRYPTOKI_NOT_INITIALIZED); 70 } 71 72 if (pulCount == NULL) { 73 return (CKR_ARGUMENTS_BAD); 74 } 75 76 if (tokenPresent) { 77 /* Need to allocate memory for pinfo */ 78 pinfo = malloc(sizeof (CK_SLOT_INFO)); 79 if (pinfo == NULL) { 80 return (CKR_HOST_MEMORY); 81 } 82 } 83 84 /* 85 * Count the number of valid slots for returning to the application. 86 * If metaslot is enabled, the slot providing keystore support for 87 * metaslot is skipped. Therefore, we can't simply sequentially 88 * assign "i" as the slot id to be returned to the application. 89 * The variable "slot_id" is used for keeping track of the 90 * next slot id to be assigned. 91 */ 92 slot_id = slottable->st_first; 93 for (i = slottable->st_first; i <= slottable->st_last; i++) { 94 if ((pkcs11_is_valid_slot(i) == CKR_OK) && 95 ((!metaslot_enabled) || (i != metaslot_keystore_slotid))) { 96 97 /* Check if token present is required */ 98 if (tokenPresent) { 99 /* Check with provider */ 100 true_id = TRUEID(i); 101 prov_rv = FUNCLIST(i)-> 102 C_GetSlotInfo(true_id, pinfo); 103 if ((prov_rv != CKR_OK) || 104 !(pinfo->flags & CKF_TOKEN_PRESENT)) { 105 continue; 106 } 107 } 108 /* Fill in the given buffer if it is sufficient */ 109 if (pSlotList && (*pulCount > count)) { 110 pSlotList[count] = slot_id; 111 slot_id++; 112 } 113 count++; 114 } 115 } 116 117 /* pSlotList set to NULL means caller only wants count */ 118 if ((*pulCount < count) && (pSlotList != NULL)) { 119 rv = CKR_BUFFER_TOO_SMALL; 120 } else { 121 rv = CKR_OK; 122 } 123 124 *pulCount = count; 125 126 if (tokenPresent) { 127 free(pinfo); 128 } 129 130 return (rv); 131 } 132 133 CK_RV 134 C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) 135 { 136 137 CK_RV rv; 138 CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */ 139 140 if (!pkcs11_initialized) { 141 return (CKR_CRYPTOKI_NOT_INITIALIZED); 142 } 143 144 /* Check for a fastpath */ 145 if ((purefastpath || policyfastpath) && !metaslot_enabled) 146 return (fast_funcs->C_GetSlotInfo(slotID, pInfo)); 147 148 if (slotID == METASLOT_FRAMEWORK_ID) { 149 /* just need to get metaslot information */ 150 return (meta_GetSlotInfo(METASLOT_SLOTID, pInfo)); 151 } 152 153 /* Check that slotID is valid */ 154 if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id) != CKR_OK) { 155 return (CKR_SLOT_ID_INVALID); 156 } 157 158 rv = FUNCLIST(fw_st_id)->C_GetSlotInfo(TRUEID(fw_st_id), pInfo); 159 160 /* Present consistent interface to the application */ 161 if (rv == CKR_FUNCTION_NOT_SUPPORTED) { 162 return (CKR_FUNCTION_FAILED); 163 } 164 165 return (rv); 166 } 167 168 CK_RV 169 C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) 170 { 171 CK_RV rv; 172 CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */ 173 174 if (!pkcs11_initialized) { 175 return (CKR_CRYPTOKI_NOT_INITIALIZED); 176 } 177 178 /* Check for a fastpath */ 179 if ((purefastpath || policyfastpath) && !metaslot_enabled) 180 return (fast_funcs->C_GetTokenInfo(slotID, pInfo)); 181 182 if (slotID == METASLOT_FRAMEWORK_ID) { 183 /* just need to get metaslot information */ 184 return (meta_GetTokenInfo(METASLOT_SLOTID, pInfo)); 185 } 186 187 /* Check that slotID is valid */ 188 if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id) != CKR_OK) { 189 return (CKR_SLOT_ID_INVALID); 190 } 191 192 rv = FUNCLIST(fw_st_id)->C_GetTokenInfo(TRUEID(fw_st_id), pInfo); 193 194 /* Present consistent interface to the application */ 195 if (rv == CKR_FUNCTION_NOT_SUPPORTED) { 196 return (CKR_FUNCTION_FAILED); 197 } 198 199 return (rv); 200 } 201 202 /* 203 * C_WaitForSlotEvent cannot be a direct pass through to the underlying 204 * provider (except in the case of fastpath), due to the complex nature 205 * of this function. The calling application is asking to be alerted 206 * when an event has occurred on any of the slots in the framework, so 207 * we need to check with all underlying providers and ask for events 208 * on any of their slots. If this is called in blocking mode, we will 209 * need to start threads to wait for slot events for each provider 210 * plugged into the framework. 211 */ 212 CK_RV 213 C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) 214 { 215 CK_SLOT_ID i, j; 216 uint32_t prov_id; 217 int32_t last_prov_id = -1; 218 CK_RV rv = CKR_OK; 219 CK_SLOT_ID event_slot; 220 pkcs11_slot_t *cur_slot; 221 222 /* Check for a fastpath */ 223 if (purefastpath || policyfastpath) { 224 return (fast_funcs->C_WaitForSlotEvent(flags, pSlot, 225 pReserved)); 226 } 227 228 if (!pkcs11_initialized) { 229 return (CKR_CRYPTOKI_NOT_INITIALIZED); 230 } 231 232 if (pReserved != NULL) { 233 return (CKR_ARGUMENTS_BAD); 234 } 235 236 /* 237 * Check to see if we're already blocking on another threads 238 * call to this function. If so, behaviour is undefined so 239 * we should return to application. 240 */ 241 (void) pthread_mutex_lock(&slottable->st_mutex); 242 if ((slottable->st_blocking) || (slottable->st_wfse_active)) { 243 (void) pthread_mutex_unlock(&slottable->st_mutex); 244 return (CKR_FUNCTION_FAILED); 245 } else { 246 slottable->st_wfse_active = B_TRUE; 247 (void) pthread_mutex_unlock(&slottable->st_mutex); 248 } 249 250 /* 251 * Check first to see if any events have been recorded 252 * already on any of the slots, regardless of blocking or 253 * thread status. 254 */ 255 for (i = slottable->st_first; i <= slottable->st_last; i++) { 256 257 cur_slot = slottable->st_slots[i]; 258 259 if (cur_slot->sl_wfse_state == WFSE_EVENT) { 260 261 /* found one, clear event and notify application */ 262 263 (void) pthread_mutex_lock(&cur_slot->sl_mutex); 264 cur_slot->sl_wfse_state = WFSE_CLEAR; 265 (void) pthread_mutex_unlock(&cur_slot->sl_mutex); 266 *pSlot = i; 267 268 /* 269 * This event has been captured, clear the function's 270 * active status. Other threads may now enter this 271 * function. 272 */ 273 (void) pthread_mutex_lock(&slottable->st_mutex); 274 slottable->st_wfse_active = B_FALSE; 275 (void) pthread_mutex_unlock(&slottable->st_mutex); 276 return (CKR_OK); 277 } 278 } 279 280 /* 281 * We could not find any existing event, so let's see 282 * if we can block and start threads to watch for events. 283 */ 284 if (flags & CKF_DONT_BLOCK) { 285 /* 286 * Application does not want us to block so check with 287 * underlying providers to see if any events have occurred. 288 * Not every provider will have implemented this function, 289 * so error codes or CKR_NO_EVENT can be ignored. 290 */ 291 292 for (i = slottable->st_first; i <= slottable->st_last; i++) { 293 prov_id = slottable->st_slots[i]->sl_prov_id; 294 cur_slot = slottable->st_slots[i]; 295 296 /* 297 * Only do process once per provider. 298 */ 299 if (prov_id == last_prov_id) { 300 continue; 301 } 302 303 /* 304 * Check to make sure a child thread is not already 305 * running, due to another of the application's 306 * thread calling this function. 307 */ 308 (void) pthread_mutex_lock(&cur_slot->sl_mutex); 309 if (cur_slot->sl_wfse_state == WFSE_ACTIVE) { 310 (void) pthread_mutex_unlock( 311 &cur_slot->sl_mutex); 312 continue; 313 } 314 315 cur_slot->sl_wfse_state = WFSE_ACTIVE; 316 317 318 /* 319 * Release the hold on the slot's mutex while we 320 * are waiting for this function to complete. 321 */ 322 (void) pthread_mutex_unlock(&cur_slot->sl_mutex); 323 324 rv = FUNCLIST(i)->C_WaitForSlotEvent(flags, 325 pSlot, pReserved); 326 327 (void) pthread_mutex_lock(&cur_slot->sl_mutex); 328 329 cur_slot->sl_wfse_state = WFSE_CLEAR; 330 331 (void) pthread_mutex_unlock(&cur_slot->sl_mutex); 332 333 /* See if we've found a slot with an event */ 334 if ((rv == CKR_OK) && (pSlot != NULL)) { 335 /* 336 * Try to map the returned slotid to a slot 337 * allocated by the framework. All slots from 338 * one provider are adjacent in the framework's 339 * slottable, so search for a mapping while 340 * the prov_id field is the same. 341 */ 342 j = i; 343 while (prov_id == 344 slottable->st_slots[j]->sl_prov_id) { 345 346 /* Find the slot, remap pSlot */ 347 if (*pSlot == TRUEID(j)) { 348 *pSlot = j; 349 (void) pthread_mutex_lock( 350 &slottable->st_mutex); 351 slottable->st_wfse_active = 352 B_FALSE; 353 (void) pthread_mutex_unlock( 354 &slottable->st_mutex); 355 return (CKR_OK); 356 } 357 j++; 358 } 359 360 } 361 362 /* 363 * If we reach this part of the loop, this 364 * provider either had no events, did not support 365 * this function, or set pSlot to a value we 366 * could not find in the slots associated with 367 * this provider. Continue checking with remaining 368 * providers. 369 */ 370 last_prov_id = prov_id; 371 } 372 373 /* No provider had any events */ 374 (void) pthread_mutex_lock(&slottable->st_mutex); 375 slottable->st_wfse_active = B_FALSE; 376 (void) pthread_mutex_unlock(&slottable->st_mutex); 377 return (CKR_NO_EVENT); 378 379 } else if (!(flags & CKF_DONT_BLOCK) && (pkcs11_cant_create_threads)) { 380 /* 381 * Application has asked us to block, but forbidden 382 * us from creating threads. This is too risky to perform 383 * with underlying providers (we may block indefinitely), 384 * so will return an error in this case. 385 */ 386 (void) pthread_mutex_lock(&slottable->st_mutex); 387 slottable->st_wfse_active = B_FALSE; 388 (void) pthread_mutex_unlock(&slottable->st_mutex); 389 return (CKR_FUNCTION_FAILED); 390 } 391 392 /* 393 * Grab the st_start_mutex now, which will prevent the listener 394 * thread from signaling on st_start_cond before we're ready to 395 * wait for it. 396 */ 397 (void) pthread_mutex_lock(&slottable->st_start_mutex); 398 399 /* 400 * Application allows us to create threads and has 401 * asked us to block. Create listener thread to wait for 402 * child threads to return. 403 */ 404 (void) pthread_mutex_lock(&slottable->st_mutex); 405 if (pthread_create(&slottable->st_tid, NULL, 406 listener_waitforslotevent, NULL) != 0) { 407 slottable->st_wfse_active = B_FALSE; 408 (void) pthread_mutex_unlock(&slottable->st_mutex); 409 (void) pthread_mutex_unlock(&slottable->st_start_mutex); 410 return (CKR_FUNCTION_FAILED); 411 } 412 413 (void) pthread_mutex_unlock(&slottable->st_mutex); 414 415 /* 416 * Wait for the listening thread to get started before 417 * we spawn child threads. 418 */ 419 (void) pthread_cond_wait(&slottable->st_start_cond, 420 &slottable->st_start_mutex); 421 (void) pthread_mutex_unlock(&slottable->st_start_mutex); 422 423 /* 424 * Need to hold the mutex on the entire slottable for the 425 * entire setup of the child threads. Otherwise, the first 426 * child thread may complete before a later child thread is 427 * fully started, resulting in an inaccurate value of 428 * st_thr_count and a potential race condition. 429 */ 430 (void) pthread_mutex_lock(&slottable->st_mutex); 431 432 /* 433 * Create child threads to check with the plugged in providers 434 * to check for events. Keep a count of the current open threads, 435 * so the listener thread knows when there are no more children 436 * to listen for. Also, make sure a thread is not already active 437 * for that provider. 438 */ 439 for (i = slottable->st_first; i <= slottable->st_last; i++) { 440 prov_id = slottable->st_slots[i]->sl_prov_id; 441 cur_slot = slottable->st_slots[i]; 442 443 /* 444 * Only do process once per provider. 445 */ 446 if (prov_id == last_prov_id) { 447 continue; 448 } 449 450 /* 451 * Check to make sure a child thread is not already running, 452 * due to another of the application's threads calling 453 * this function. Also, check that the provider has actually 454 * implemented this function. 455 */ 456 (void) pthread_mutex_lock(&cur_slot->sl_mutex); 457 if ((cur_slot->sl_wfse_state == WFSE_ACTIVE) || 458 (cur_slot->sl_no_wfse)) { 459 (void) pthread_mutex_unlock(&cur_slot->sl_mutex); 460 last_prov_id = prov_id; 461 continue; 462 } 463 464 /* Set slot to active */ 465 cur_slot->sl_wfse_state = WFSE_ACTIVE; 466 467 /* 468 * set up variable to pass arguments to child threads. 469 * Only need to set up once, as values will remain the 470 * same for each successive call. 471 */ 472 if (cur_slot->sl_wfse_args == NULL) { 473 cur_slot->sl_wfse_args = malloc(sizeof (wfse_args_t)); 474 475 if (cur_slot->sl_wfse_args == NULL) { 476 (void) pthread_mutex_unlock( 477 &cur_slot->sl_mutex); 478 slottable->st_wfse_active = B_FALSE; 479 (void) pthread_mutex_unlock( 480 &slottable->st_mutex); 481 return (CKR_HOST_MEMORY); 482 } 483 cur_slot->sl_wfse_args->flags = flags; 484 cur_slot->sl_wfse_args->pReserved = pReserved; 485 cur_slot->sl_wfse_args->slotid = i; 486 } 487 488 /* Create child thread */ 489 if (pthread_create(&cur_slot->sl_tid, NULL, 490 child_waitforslotevent, 491 (void *)cur_slot->sl_wfse_args) != 0) { 492 (void) pthread_mutex_unlock(&cur_slot->sl_mutex); 493 continue; 494 } 495 496 (void) pthread_mutex_unlock(&cur_slot->sl_mutex); 497 498 /* 499 * This counter is decremented every time a 500 * child_waitforslotevent() wakes up the listener. 501 */ 502 slottable->st_thr_count++; 503 504 last_prov_id = prov_id; 505 } 506 507 /* If no children are listening, kill the listener */ 508 if (slottable->st_thr_count == 0) { 509 (void) pthread_cancel(slottable->st_tid); 510 511 /* If there are no child threads, no event will occur */ 512 slottable->st_wfse_active = B_FALSE; 513 (void) pthread_mutex_unlock(&slottable->st_mutex); 514 return (CKR_NO_EVENT); 515 } 516 517 (void) pthread_mutex_unlock(&slottable->st_mutex); 518 519 /* Wait for listener thread to terminate */ 520 (void) pthread_join(slottable->st_tid, NULL); 521 522 /* Make sure C_Finalize has not been called */ 523 if (!pkcs11_initialized) { 524 (void) pthread_mutex_lock(&slottable->st_mutex); 525 slottable->st_wfse_active = B_FALSE; 526 (void) pthread_mutex_unlock(&slottable->st_mutex); 527 return (CKR_CRYPTOKI_NOT_INITIALIZED); 528 } 529 530 /* See if any events actually occurred */ 531 (void) pthread_mutex_lock(&slottable->st_mutex); 532 event_slot = slottable->st_event_slot; 533 (void) pthread_mutex_unlock(&slottable->st_mutex); 534 535 if (pkcs11_is_valid_slot(event_slot) == CKR_OK) { 536 537 (void) pthread_mutex_lock(&slottable-> 538 st_slots[event_slot]->sl_mutex); 539 if (slottable->st_slots[event_slot]-> 540 sl_wfse_state == WFSE_EVENT) { 541 542 /* An event has occurred on this slot */ 543 slottable->st_slots[event_slot]->sl_wfse_state = 544 WFSE_CLEAR; 545 (void) pthread_mutex_unlock(&slottable-> 546 st_slots[event_slot]->sl_mutex); 547 *pSlot = event_slot; 548 (void) pthread_mutex_lock(&slottable->st_mutex); 549 slottable->st_blocking = B_FALSE; 550 slottable->st_wfse_active = B_FALSE; 551 (void) pthread_mutex_unlock(&slottable->st_mutex); 552 return (CKR_OK); 553 } else { 554 (void) pthread_mutex_unlock(&slottable-> 555 st_slots[event_slot]->sl_mutex); 556 } 557 } 558 559 (void) pthread_mutex_lock(&slottable->st_mutex); 560 slottable->st_blocking = B_FALSE; 561 slottable->st_wfse_active = B_FALSE; 562 (void) pthread_mutex_unlock(&slottable->st_mutex); 563 564 /* No provider reported any events, or no provider implemented this */ 565 return (CKR_NO_EVENT); 566 } 567 568 /* 569 * C_GetMechanismList cannot just be a direct pass through to the 570 * underlying provider, because we allow the administrator to 571 * disable certain mechanisms from specific providers. This affects 572 * both pulCount and pMechanismList. Only when the fastpath with 573 * no policy is in effect can we pass through directly to the 574 * underlying provider. 575 * 576 * It is necessary, for policy filtering, to get the actual list 577 * of mechanisms from the underlying provider, even if the calling 578 * application is just requesting a count. It is the only way to 579 * get an accurate count of the number of mechanisms actually available. 580 */ 581 CK_RV 582 C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, 583 CK_ULONG_PTR pulCount) 584 { 585 CK_RV rv = CKR_OK; 586 CK_ULONG mech_count; 587 CK_ULONG tmpmech_count; 588 CK_MECHANISM_TYPE_PTR pmech_list, tmpmech_list; 589 CK_SLOT_ID true_id; 590 CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */ 591 CK_FUNCTION_LIST_PTR prov_funcs; 592 593 CK_ULONG i; 594 595 if (!pkcs11_initialized) { 596 return (CKR_CRYPTOKI_NOT_INITIALIZED); 597 } 598 599 /* Check for a fastpath */ 600 if ((purefastpath || policyfastpath) && !metaslot_enabled) 601 return (fast_funcs->C_GetMechanismList(slotID, 602 pMechanismList, pulCount)); 603 604 if (slotID == METASLOT_FRAMEWORK_ID) { 605 return (meta_GetMechanismList(METASLOT_SLOTID, pMechanismList, 606 pulCount)); 607 } 608 609 /* Check that slotID is valid */ 610 if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id) != CKR_OK) { 611 return (CKR_SLOT_ID_INVALID); 612 } 613 614 if (policyfastpath) { 615 true_id = fw_st_id; 616 slotID = fast_slot; 617 prov_funcs = fast_funcs; 618 } else { 619 true_id = TRUEID(fw_st_id); 620 prov_funcs = FUNCLIST(fw_st_id); 621 } 622 623 mech_count = 0; 624 tmpmech_count = MECHLIST_SIZE; 625 626 /* 627 * Allocate memory for a mechanism list. We are assuming 628 * that most mechanism lists will be less than MECHLIST_SIZE. 629 * If that is not enough memory, we will try a second time 630 * with more memory allocated. 631 */ 632 pmech_list = malloc(tmpmech_count * sizeof (CK_MECHANISM_TYPE)); 633 634 if (pmech_list == NULL) { 635 return (CKR_HOST_MEMORY); 636 } 637 638 /* 639 * Attempt to get the mechanism list. PKCS11 supports 640 * removable media, so the mechanism list of a slot can vary 641 * over the life of the application. 642 */ 643 rv = prov_funcs->C_GetMechanismList(true_id, 644 pmech_list, &tmpmech_count); 645 646 if (rv == CKR_BUFFER_TOO_SMALL) { 647 /* Need to use more space */ 648 tmpmech_list = pmech_list; 649 pmech_list = realloc 650 (tmpmech_list, tmpmech_count * sizeof (CK_MECHANISM_TYPE)); 651 652 if (pmech_list == NULL) { 653 free(tmpmech_list); 654 return (CKR_HOST_MEMORY); 655 } 656 657 /* Try again to get mechanism list. */ 658 rv = prov_funcs->C_GetMechanismList(true_id, 659 pmech_list, &tmpmech_count); 660 661 } 662 663 /* 664 * Present consistent face to calling application. 665 * If something strange has happened, or this function 666 * is not supported by this provider, return a count 667 * of zero mechanisms. 668 */ 669 if (rv != CKR_OK) { 670 *pulCount = 0; 671 free(pmech_list); 672 return (CKR_OK); 673 } 674 675 /* 676 * Process the mechanism list, removing any mechanisms 677 * that are disabled via the framework. Even if the 678 * application is only asking for a count, we must 679 * process the actual mechanisms being offered by this slot. 680 * We could not just subtract our stored count of disabled 681 * mechanisms, since it is not guaranteed that those 682 * mechanisms are actually supported by the slot. 683 */ 684 for (i = 0; i < tmpmech_count; i++) { 685 /* Filter out the disabled mechanisms */ 686 if (pkcs11_is_dismech(fw_st_id, pmech_list[i])) { 687 continue; 688 } 689 690 /* 691 * Only set pMechanismList if enough memory 692 * is available. If it was set to NULL 693 * originally, this loop will just be counting 694 * mechanims. 695 */ 696 if (pMechanismList && (*pulCount > mech_count)) { 697 pMechanismList[mech_count] = pmech_list[i]; 698 } 699 mech_count++; 700 } 701 702 /* 703 * Catch the case where pMechanismList was not set to NULL, 704 * yet the buffer was not large enough. If pMechanismList is 705 * set to NULL, this function will simply set pulCount and 706 * return CKR_OK. 707 */ 708 if ((*pulCount < mech_count) && (pMechanismList != NULL)) { 709 *pulCount = mech_count; 710 free(pmech_list); 711 return (CKR_BUFFER_TOO_SMALL); 712 } 713 714 *pulCount = mech_count; 715 free(pmech_list); 716 717 return (CKR_OK); 718 } 719 720 721 CK_RV 722 C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, 723 CK_MECHANISM_INFO_PTR pInfo) 724 { 725 CK_RV rv; 726 CK_SLOT_ID true_id; 727 CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */ 728 CK_FUNCTION_LIST_PTR prov_funcs; 729 730 if (!pkcs11_initialized) { 731 return (CKR_CRYPTOKI_NOT_INITIALIZED); 732 } 733 734 /* Check for a fastpath */ 735 if ((purefastpath || policyfastpath) && !metaslot_enabled) 736 return (fast_funcs->C_GetMechanismInfo(slotID, type, pInfo)); 737 738 if (slotID == METASLOT_FRAMEWORK_ID) { 739 /* just need to get metaslot information */ 740 return (meta_GetMechanismInfo(METASLOT_SLOTID, type, pInfo)); 741 } 742 743 /* Check that slotID is valid */ 744 if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id) != CKR_OK) { 745 return (CKR_SLOT_ID_INVALID); 746 } 747 748 if (policyfastpath) { 749 true_id = fw_st_id; 750 slotID = fast_slot; 751 prov_funcs = fast_funcs; 752 } else { 753 true_id = TRUEID(fw_st_id); 754 prov_funcs = FUNCLIST(fw_st_id); 755 } 756 757 /* Make sure this is not a disabled mechanism */ 758 if (pkcs11_is_dismech(fw_st_id, type)) { 759 return (CKR_MECHANISM_INVALID); 760 } 761 762 rv = prov_funcs->C_GetMechanismInfo(true_id, type, pInfo); 763 764 /* Present consistent interface to the application */ 765 if (rv == CKR_FUNCTION_NOT_SUPPORTED) { 766 return (CKR_FUNCTION_FAILED); 767 } 768 769 return (rv); 770 } 771 772 773 CK_RV 774 C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, 775 CK_UTF8CHAR_PTR pLabel) 776 { 777 CK_RV rv; 778 CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */ 779 780 if (!pkcs11_initialized) { 781 return (CKR_CRYPTOKI_NOT_INITIALIZED); 782 } 783 784 /* Check for a fastpath */ 785 if ((purefastpath || policyfastpath) && !metaslot_enabled) 786 return (fast_funcs->C_InitToken(slotID, pPin, ulPinLen, 787 pLabel)); 788 789 if (slotID == METASLOT_FRAMEWORK_ID) { 790 /* just need to get metaslot information */ 791 return (meta_InitToken(METASLOT_SLOTID, pPin, ulPinLen, 792 pLabel)); 793 } 794 795 /* Check that slotID is valid */ 796 if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id) != CKR_OK) { 797 return (CKR_SLOT_ID_INVALID); 798 } 799 800 rv = FUNCLIST(fw_st_id)->C_InitToken(TRUEID(fw_st_id), pPin, ulPinLen, 801 pLabel); 802 803 /* Present consistent interface to the application */ 804 if (rv == CKR_FUNCTION_NOT_SUPPORTED) { 805 return (CKR_FUNCTION_FAILED); 806 } 807 808 return (rv); 809 } 810 811 CK_RV 812 C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) 813 { 814 815 CK_RV rv; 816 pkcs11_session_t *sessp; 817 818 /* Check for a fastpath */ 819 if (purefastpath || policyfastpath) { 820 return (fast_funcs->C_InitPIN(hSession, pPin, ulPinLen)); 821 } 822 823 if (!pkcs11_initialized) { 824 return (CKR_CRYPTOKI_NOT_INITIALIZED); 825 } 826 827 /* Obtain the session pointer */ 828 HANDLE2SESSION(hSession, sessp, rv); 829 830 if (rv != CKR_OK) { 831 return (rv); 832 } 833 834 /* Initialize the PIN with the provider */ 835 rv = FUNCLIST(sessp->se_slotid)->C_InitPIN(sessp->se_handle, 836 pPin, ulPinLen); 837 838 /* Present consistent interface to the application */ 839 if (rv == CKR_FUNCTION_NOT_SUPPORTED) { 840 return (CKR_FUNCTION_FAILED); 841 } 842 843 return (rv); 844 } 845 846 CK_RV 847 C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, 848 CK_ULONG ulOldPinLen, CK_UTF8CHAR_PTR pNewPin, 849 CK_ULONG ulNewPinLen) 850 { 851 CK_RV rv; 852 pkcs11_session_t *sessp; 853 854 /* Check for a fastpath */ 855 if (purefastpath || policyfastpath) { 856 return (fast_funcs->C_SetPIN(hSession, pOldPin, ulOldPinLen, 857 pNewPin, ulNewPinLen)); 858 } 859 860 if (!pkcs11_initialized) { 861 return (CKR_CRYPTOKI_NOT_INITIALIZED); 862 } 863 864 /* Obtain the session pointer */ 865 HANDLE2SESSION(hSession, sessp, rv); 866 867 if (rv != CKR_OK) { 868 return (rv); 869 } 870 871 /* Set the PIN with the provider */ 872 rv = FUNCLIST(sessp->se_slotid)->C_SetPIN(sessp->se_handle, 873 pOldPin, ulOldPinLen, pNewPin, ulNewPinLen); 874 875 /* Present consistent interface to the application */ 876 if (rv == CKR_FUNCTION_NOT_SUPPORTED) { 877 return (CKR_FUNCTION_FAILED); 878 } 879 880 return (rv); 881 882 } 883 884 /* 885 * listener_waitforslotevent is spawned by the main C_WaitForSlotEvent() 886 * to listen for events from any of the providers. It also watches the 887 * count of threads, which may go to zero with no recorded events, if 888 * none of the underlying providers have actually implemented this 889 * function. 890 */ 891 /*ARGSUSED*/ 892 static void * 893 listener_waitforslotevent(void *arg) { 894 895 CK_SLOT_ID eventID; 896 897 /* Mark slottable in state blocking */ 898 (void) pthread_mutex_lock(&slottable->st_mutex); 899 slottable->st_blocking = B_TRUE; 900 901 /* alert calling thread that this thread has started */ 902 (void) pthread_mutex_lock(&slottable->st_start_mutex); 903 (void) pthread_cond_signal(&slottable->st_start_cond); 904 (void) pthread_mutex_unlock(&slottable->st_start_mutex); 905 906 /* wait for an event, or number of threads to reach zero */ 907 for (;;) { 908 909 /* 910 * Make sure we've really been signaled, and not waking 911 * for another reason. 912 */ 913 while (slottable->st_list_signaled != B_TRUE) { 914 (void) pthread_cond_wait(&slottable->st_wait_cond, 915 &slottable->st_mutex); 916 } 917 918 slottable->st_list_signaled = B_FALSE; 919 920 /* See why we were woken up */ 921 if (!pkcs11_initialized) { 922 /* Another thread has called C_Finalize() */ 923 (void) pthread_mutex_unlock(&slottable->st_mutex); 924 return (NULL); 925 } 926 927 /* A thread has finished, decrement counter */ 928 slottable->st_thr_count--; 929 930 eventID = slottable->st_event_slot; 931 932 if (pkcs11_is_valid_slot(eventID) == CKR_OK) { 933 934 (void) pthread_mutex_lock(&slottable-> 935 st_slots[eventID]->sl_mutex); 936 937 if (slottable->st_slots[eventID]-> 938 sl_wfse_state == WFSE_EVENT) { 939 (void) pthread_mutex_unlock(&slottable-> 940 st_slots[eventID]->sl_mutex); 941 942 /* 943 * st_event_slot is set to a valid value, event 944 * flag is set for that slot. The flag will 945 * be cleared by main C_WaitForSlotEvent(). 946 */ 947 (void) pthread_mutex_unlock( 948 &slottable->st_mutex); 949 950 pthread_exit(0); 951 } else { 952 (void) pthread_mutex_unlock(&slottable-> 953 st_slots[eventID]->sl_mutex); 954 } 955 } 956 if (slottable->st_thr_count == 0) { 957 (void) pthread_mutex_unlock(&slottable->st_mutex); 958 959 /* No more threads, no events found */ 960 pthread_exit(0); 961 } 962 } 963 964 /*NOTREACHED*/ 965 return (NULL); 966 } 967 968 /* 969 * child_waitforslotevent is used as a child thread to contact 970 * underlying provider's C_WaitForSlotEvent(). 971 */ 972 static void * 973 child_waitforslotevent(void *arg) { 974 975 wfse_args_t *wfse = (wfse_args_t *)arg; 976 CK_SLOT_ID slot; 977 CK_RV rv; 978 uint32_t cur_prov; 979 CK_SLOT_ID i; 980 981 rv = FUNCLIST(wfse->slotid)->C_WaitForSlotEvent(wfse->flags, &slot, 982 wfse->pReserved); 983 984 /* 985 * Need to hold the mutex while processing the results, to 986 * keep things synchronized with the listener thread and 987 * the slottable. Otherwise, due to the timing 988 * at which some underlying providers complete, the listener 989 * thread may not actually be blocking on st_wait_cond when 990 * this child signals. Holding the lock a bit longer prevents 991 * this from happening. 992 */ 993 (void) pthread_mutex_lock(&slottable->st_mutex); 994 995 while (slottable->st_list_signaled == B_TRUE) { 996 /* 997 * We've taken the mutex when the listener should have 998 * control. Release the mutex, thread scheduler should 999 * give control back to the listener. 1000 */ 1001 (void) pthread_mutex_unlock(&slottable->st_mutex); 1002 (void) sleep(1); 1003 (void) pthread_mutex_lock(&slottable->st_mutex); 1004 } 1005 1006 if (rv == CKR_OK) { 1007 /* we've had an event, find slot and store it */ 1008 cur_prov = slottable->st_slots[wfse->slotid]->sl_prov_id; 1009 1010 /* 1011 * It is safe to unset active status now, since call to 1012 * underlying provider has already terminated, and we 1013 * hold the slottable wide mutex (st_mutex). 1014 */ 1015 (void) pthread_mutex_lock(&slottable-> 1016 st_slots[wfse->slotid]->sl_mutex); 1017 1018 slottable->st_slots[wfse->slotid]->sl_wfse_state = WFSE_CLEAR; 1019 1020 (void) pthread_mutex_unlock(&slottable-> 1021 st_slots[wfse->slotid]->sl_mutex); 1022 1023 1024 for (i = wfse->slotid; i <= slottable->st_last; i++) { 1025 if (cur_prov != slottable->st_slots[i]->sl_prov_id) { 1026 break; 1027 } 1028 1029 if (slot == slottable->st_slots[i]->sl_id) { 1030 (void) pthread_mutex_lock(&slottable-> 1031 st_slots[i]->sl_mutex); 1032 1033 slottable->st_slots[i]-> 1034 sl_wfse_state = WFSE_EVENT; 1035 1036 (void) pthread_mutex_unlock(&slottable-> 1037 st_slots[i]->sl_mutex); 1038 1039 slottable->st_event_slot = i; 1040 1041 if (slottable->st_blocking) { 1042 slottable->st_list_signaled = B_TRUE; 1043 (void) pthread_cond_signal(&slottable-> 1044 st_wait_cond); 1045 } 1046 1047 (void) pthread_mutex_unlock( 1048 &slottable->st_mutex); 1049 1050 pthread_exit(0); 1051 } 1052 } 1053 1054 } 1055 1056 (void) pthread_mutex_lock(&slottable-> 1057 st_slots[wfse->slotid]->sl_mutex); 1058 1059 /* 1060 * If the provider told us that it does not support 1061 * this function, we should mark it so we do not waste 1062 * time later with it. If an error returned, we'll clean 1063 * up this thread now and possibly try it again later. 1064 */ 1065 if (rv == CKR_FUNCTION_NOT_SUPPORTED) { 1066 slottable->st_slots[wfse->slotid]->sl_no_wfse = B_TRUE; 1067 } 1068 1069 /* 1070 * It is safe to unset active status now, since call to 1071 * underlying provider has already terminated, and we 1072 * hold the slottable wide mutex (st_mutex). 1073 */ 1074 slottable->st_slots[wfse->slotid]->sl_wfse_state = WFSE_CLEAR; 1075 (void) pthread_mutex_unlock(&slottable-> 1076 st_slots[wfse->slotid]->sl_mutex); 1077 1078 1079 if (slottable->st_blocking) { 1080 slottable->st_list_signaled = B_TRUE; 1081 (void) pthread_cond_signal(&slottable->st_wait_cond); 1082 } 1083 1084 (void) pthread_mutex_unlock(&slottable->st_mutex); 1085 1086 /* Manually exit the thread, since nobody will join to it */ 1087 pthread_exit(0); 1088 1089 /*NOTREACHED*/ 1090 return (NULL); 1091 } 1092