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