dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / pkcs11 / libpkcs11 / common / pkcs11SlotToken.c
bloba4783c9a14f72b82d7a694afcfbf85e24fbe0021
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
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"
36 static void *listener_waitforslotevent(void *arg);
37 static void *child_waitforslotevent(void *arg);
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.
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.
50 CK_RV
51 C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
52 CK_ULONG_PTR pulCount)
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 */
62 /* Check for a fastpath */
63 if ((purefastpath || policyfastpath) && (!metaslot_enabled)) {
64 return (fast_funcs->C_GetSlotList(tokenPresent, pSlotList,
65 pulCount));
68 if (!pkcs11_initialized) {
69 return (CKR_CRYPTOKI_NOT_INITIALIZED);
72 if (pulCount == NULL) {
73 return (CKR_ARGUMENTS_BAD);
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);
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.
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))) {
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;
108 /* Fill in the given buffer if it is sufficient */
109 if (pSlotList && (*pulCount > count)) {
110 pSlotList[count] = slot_id;
111 slot_id++;
113 count++;
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;
124 *pulCount = count;
126 if (tokenPresent) {
127 free(pinfo);
130 return (rv);
133 CK_RV
134 C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
137 CK_RV rv;
138 CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */
140 if (!pkcs11_initialized) {
141 return (CKR_CRYPTOKI_NOT_INITIALIZED);
144 /* Check for a fastpath */
145 if ((purefastpath || policyfastpath) && !metaslot_enabled)
146 return (fast_funcs->C_GetSlotInfo(slotID, pInfo));
148 if (slotID == METASLOT_FRAMEWORK_ID) {
149 /* just need to get metaslot information */
150 return (meta_GetSlotInfo(METASLOT_SLOTID, pInfo));
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);
158 rv = FUNCLIST(fw_st_id)->C_GetSlotInfo(TRUEID(fw_st_id), pInfo);
160 /* Present consistent interface to the application */
161 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
162 return (CKR_FUNCTION_FAILED);
165 return (rv);
168 CK_RV
169 C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
171 CK_RV rv;
172 CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */
174 if (!pkcs11_initialized) {
175 return (CKR_CRYPTOKI_NOT_INITIALIZED);
178 /* Check for a fastpath */
179 if ((purefastpath || policyfastpath) && !metaslot_enabled)
180 return (fast_funcs->C_GetTokenInfo(slotID, pInfo));
182 if (slotID == METASLOT_FRAMEWORK_ID) {
183 /* just need to get metaslot information */
184 return (meta_GetTokenInfo(METASLOT_SLOTID, pInfo));
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);
192 rv = FUNCLIST(fw_st_id)->C_GetTokenInfo(TRUEID(fw_st_id), pInfo);
194 /* Present consistent interface to the application */
195 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
196 return (CKR_FUNCTION_FAILED);
199 return (rv);
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.
212 CK_RV
213 C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
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;
222 /* Check for a fastpath */
223 if (purefastpath || policyfastpath) {
224 return (fast_funcs->C_WaitForSlotEvent(flags, pSlot,
225 pReserved));
228 if (!pkcs11_initialized) {
229 return (CKR_CRYPTOKI_NOT_INITIALIZED);
232 if (pReserved != NULL) {
233 return (CKR_ARGUMENTS_BAD);
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.
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);
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.
255 for (i = slottable->st_first; i <= slottable->st_last; i++) {
257 cur_slot = slottable->st_slots[i];
259 if (cur_slot->sl_wfse_state == WFSE_EVENT) {
261 /* found one, clear event and notify application */
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;
269 * This event has been captured, clear the function's
270 * active status. Other threads may now enter this
271 * function.
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);
281 * We could not find any existing event, so let's see
282 * if we can block and start threads to watch for events.
284 if (flags & CKF_DONT_BLOCK) {
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.
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];
297 * Only do process once per provider.
299 if (prov_id == last_prov_id) {
300 continue;
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.
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;
315 cur_slot->sl_wfse_state = WFSE_ACTIVE;
319 * Release the hold on the slot's mutex while we
320 * are waiting for this function to complete.
322 (void) pthread_mutex_unlock(&cur_slot->sl_mutex);
324 rv = FUNCLIST(i)->C_WaitForSlotEvent(flags,
325 pSlot, pReserved);
327 (void) pthread_mutex_lock(&cur_slot->sl_mutex);
329 cur_slot->sl_wfse_state = WFSE_CLEAR;
331 (void) pthread_mutex_unlock(&cur_slot->sl_mutex);
333 /* See if we've found a slot with an event */
334 if ((rv == CKR_OK) && (pSlot != NULL)) {
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.
342 j = i;
343 while (prov_id ==
344 slottable->st_slots[j]->sl_prov_id) {
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);
357 j++;
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.
370 last_prov_id = prov_id;
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);
379 } else if (!(flags & CKF_DONT_BLOCK) && (pkcs11_cant_create_threads)) {
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.
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);
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.
397 (void) pthread_mutex_lock(&slottable->st_start_mutex);
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.
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);
413 (void) pthread_mutex_unlock(&slottable->st_mutex);
416 * Wait for the listening thread to get started before
417 * we spawn child threads.
419 (void) pthread_cond_wait(&slottable->st_start_cond,
420 &slottable->st_start_mutex);
421 (void) pthread_mutex_unlock(&slottable->st_start_mutex);
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.
430 (void) pthread_mutex_lock(&slottable->st_mutex);
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.
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];
444 * Only do process once per provider.
446 if (prov_id == last_prov_id) {
447 continue;
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.
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;
464 /* Set slot to active */
465 cur_slot->sl_wfse_state = WFSE_ACTIVE;
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.
472 if (cur_slot->sl_wfse_args == NULL) {
473 cur_slot->sl_wfse_args = malloc(sizeof (wfse_args_t));
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);
483 cur_slot->sl_wfse_args->flags = flags;
484 cur_slot->sl_wfse_args->pReserved = pReserved;
485 cur_slot->sl_wfse_args->slotid = i;
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;
496 (void) pthread_mutex_unlock(&cur_slot->sl_mutex);
499 * This counter is decremented every time a
500 * child_waitforslotevent() wakes up the listener.
502 slottable->st_thr_count++;
504 last_prov_id = prov_id;
507 /* If no children are listening, kill the listener */
508 if (slottable->st_thr_count == 0) {
509 (void) pthread_cancel(slottable->st_tid);
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);
517 (void) pthread_mutex_unlock(&slottable->st_mutex);
519 /* Wait for listener thread to terminate */
520 (void) pthread_join(slottable->st_tid, NULL);
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);
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);
535 if (pkcs11_is_valid_slot(event_slot) == CKR_OK) {
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) {
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);
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);
564 /* No provider reported any events, or no provider implemented this */
565 return (CKR_NO_EVENT);
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.
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.
581 CK_RV
582 C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
583 CK_ULONG_PTR pulCount)
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;
593 CK_ULONG i;
595 if (!pkcs11_initialized) {
596 return (CKR_CRYPTOKI_NOT_INITIALIZED);
599 /* Check for a fastpath */
600 if ((purefastpath || policyfastpath) && !metaslot_enabled)
601 return (fast_funcs->C_GetMechanismList(slotID,
602 pMechanismList, pulCount));
604 if (slotID == METASLOT_FRAMEWORK_ID) {
605 return (meta_GetMechanismList(METASLOT_SLOTID, pMechanismList,
606 pulCount));
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);
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);
623 mech_count = 0;
624 tmpmech_count = MECHLIST_SIZE;
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.
632 pmech_list = malloc(tmpmech_count * sizeof (CK_MECHANISM_TYPE));
634 if (pmech_list == NULL) {
635 return (CKR_HOST_MEMORY);
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.
643 rv = prov_funcs->C_GetMechanismList(true_id,
644 pmech_list, &tmpmech_count);
646 if (rv == CKR_BUFFER_TOO_SMALL) {
647 /* Need to use more space */
648 tmpmech_list = pmech_list;
649 pmech_list = reallocarray(tmpmech_list, tmpmech_count,
650 sizeof (CK_MECHANISM_TYPE));
652 if (pmech_list == NULL) {
653 free(tmpmech_list);
654 return (CKR_HOST_MEMORY);
657 /* Try again to get mechanism list. */
658 rv = prov_funcs->C_GetMechanismList(true_id,
659 pmech_list, &tmpmech_count);
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.
669 if (rv != CKR_OK) {
670 *pulCount = 0;
671 free(pmech_list);
672 return (CKR_OK);
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.
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;
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.
696 if (pMechanismList && (*pulCount > mech_count)) {
697 pMechanismList[mech_count] = pmech_list[i];
699 mech_count++;
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.
708 if ((*pulCount < mech_count) && (pMechanismList != NULL)) {
709 *pulCount = mech_count;
710 free(pmech_list);
711 return (CKR_BUFFER_TOO_SMALL);
714 *pulCount = mech_count;
715 free(pmech_list);
717 return (CKR_OK);
721 CK_RV
722 C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
723 CK_MECHANISM_INFO_PTR pInfo)
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;
730 if (!pkcs11_initialized) {
731 return (CKR_CRYPTOKI_NOT_INITIALIZED);
734 /* Check for a fastpath */
735 if ((purefastpath || policyfastpath) && !metaslot_enabled)
736 return (fast_funcs->C_GetMechanismInfo(slotID, type, pInfo));
738 if (slotID == METASLOT_FRAMEWORK_ID) {
739 /* just need to get metaslot information */
740 return (meta_GetMechanismInfo(METASLOT_SLOTID, type, pInfo));
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);
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);
757 /* Make sure this is not a disabled mechanism */
758 if (pkcs11_is_dismech(fw_st_id, type)) {
759 return (CKR_MECHANISM_INVALID);
762 rv = prov_funcs->C_GetMechanismInfo(true_id, type, pInfo);
764 /* Present consistent interface to the application */
765 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
766 return (CKR_FUNCTION_FAILED);
769 return (rv);
773 CK_RV
774 C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen,
775 CK_UTF8CHAR_PTR pLabel)
777 CK_RV rv;
778 CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */
780 if (!pkcs11_initialized) {
781 return (CKR_CRYPTOKI_NOT_INITIALIZED);
784 /* Check for a fastpath */
785 if ((purefastpath || policyfastpath) && !metaslot_enabled)
786 return (fast_funcs->C_InitToken(slotID, pPin, ulPinLen,
787 pLabel));
789 if (slotID == METASLOT_FRAMEWORK_ID) {
790 /* just need to get metaslot information */
791 return (meta_InitToken(METASLOT_SLOTID, pPin, ulPinLen,
792 pLabel));
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);
800 rv = FUNCLIST(fw_st_id)->C_InitToken(TRUEID(fw_st_id), pPin, ulPinLen,
801 pLabel);
803 /* Present consistent interface to the application */
804 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
805 return (CKR_FUNCTION_FAILED);
808 return (rv);
811 CK_RV
812 C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
815 CK_RV rv;
816 pkcs11_session_t *sessp;
818 /* Check for a fastpath */
819 if (purefastpath || policyfastpath) {
820 return (fast_funcs->C_InitPIN(hSession, pPin, ulPinLen));
823 if (!pkcs11_initialized) {
824 return (CKR_CRYPTOKI_NOT_INITIALIZED);
827 /* Obtain the session pointer */
828 HANDLE2SESSION(hSession, sessp, rv);
830 if (rv != CKR_OK) {
831 return (rv);
834 /* Initialize the PIN with the provider */
835 rv = FUNCLIST(sessp->se_slotid)->C_InitPIN(sessp->se_handle,
836 pPin, ulPinLen);
838 /* Present consistent interface to the application */
839 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
840 return (CKR_FUNCTION_FAILED);
843 return (rv);
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)
851 CK_RV rv;
852 pkcs11_session_t *sessp;
854 /* Check for a fastpath */
855 if (purefastpath || policyfastpath) {
856 return (fast_funcs->C_SetPIN(hSession, pOldPin, ulOldPinLen,
857 pNewPin, ulNewPinLen));
860 if (!pkcs11_initialized) {
861 return (CKR_CRYPTOKI_NOT_INITIALIZED);
864 /* Obtain the session pointer */
865 HANDLE2SESSION(hSession, sessp, rv);
867 if (rv != CKR_OK) {
868 return (rv);
871 /* Set the PIN with the provider */
872 rv = FUNCLIST(sessp->se_slotid)->C_SetPIN(sessp->se_handle,
873 pOldPin, ulOldPinLen, pNewPin, ulNewPinLen);
875 /* Present consistent interface to the application */
876 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
877 return (CKR_FUNCTION_FAILED);
880 return (rv);
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.
891 /*ARGSUSED*/
892 static void *
893 listener_waitforslotevent(void *arg) {
895 CK_SLOT_ID eventID;
897 /* Mark slottable in state blocking */
898 (void) pthread_mutex_lock(&slottable->st_mutex);
899 slottable->st_blocking = B_TRUE;
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);
906 /* wait for an event, or number of threads to reach zero */
907 for (;;) {
910 * Make sure we've really been signaled, and not waking
911 * for another reason.
913 while (slottable->st_list_signaled != B_TRUE) {
914 (void) pthread_cond_wait(&slottable->st_wait_cond,
915 &slottable->st_mutex);
918 slottable->st_list_signaled = B_FALSE;
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);
927 /* A thread has finished, decrement counter */
928 slottable->st_thr_count--;
930 eventID = slottable->st_event_slot;
932 if (pkcs11_is_valid_slot(eventID) == CKR_OK) {
934 (void) pthread_mutex_lock(&slottable->
935 st_slots[eventID]->sl_mutex);
937 if (slottable->st_slots[eventID]->
938 sl_wfse_state == WFSE_EVENT) {
939 (void) pthread_mutex_unlock(&slottable->
940 st_slots[eventID]->sl_mutex);
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().
947 (void) pthread_mutex_unlock(
948 &slottable->st_mutex);
950 pthread_exit(0);
951 } else {
952 (void) pthread_mutex_unlock(&slottable->
953 st_slots[eventID]->sl_mutex);
956 if (slottable->st_thr_count == 0) {
957 (void) pthread_mutex_unlock(&slottable->st_mutex);
959 /* No more threads, no events found */
960 pthread_exit(0);
964 /*NOTREACHED*/
965 return (NULL);
969 * child_waitforslotevent is used as a child thread to contact
970 * underlying provider's C_WaitForSlotEvent().
972 static void *
973 child_waitforslotevent(void *arg) {
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;
981 rv = FUNCLIST(wfse->slotid)->C_WaitForSlotEvent(wfse->flags, &slot,
982 wfse->pReserved);
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.
993 (void) pthread_mutex_lock(&slottable->st_mutex);
995 while (slottable->st_list_signaled == B_TRUE) {
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.
1001 (void) pthread_mutex_unlock(&slottable->st_mutex);
1002 (void) sleep(1);
1003 (void) pthread_mutex_lock(&slottable->st_mutex);
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;
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).
1015 (void) pthread_mutex_lock(&slottable->
1016 st_slots[wfse->slotid]->sl_mutex);
1018 slottable->st_slots[wfse->slotid]->sl_wfse_state = WFSE_CLEAR;
1020 (void) pthread_mutex_unlock(&slottable->
1021 st_slots[wfse->slotid]->sl_mutex);
1024 for (i = wfse->slotid; i <= slottable->st_last; i++) {
1025 if (cur_prov != slottable->st_slots[i]->sl_prov_id) {
1026 break;
1029 if (slot == slottable->st_slots[i]->sl_id) {
1030 (void) pthread_mutex_lock(&slottable->
1031 st_slots[i]->sl_mutex);
1033 slottable->st_slots[i]->
1034 sl_wfse_state = WFSE_EVENT;
1036 (void) pthread_mutex_unlock(&slottable->
1037 st_slots[i]->sl_mutex);
1039 slottable->st_event_slot = i;
1041 if (slottable->st_blocking) {
1042 slottable->st_list_signaled = B_TRUE;
1043 (void) pthread_cond_signal(&slottable->
1044 st_wait_cond);
1047 (void) pthread_mutex_unlock(
1048 &slottable->st_mutex);
1050 pthread_exit(0);
1056 (void) pthread_mutex_lock(&slottable->
1057 st_slots[wfse->slotid]->sl_mutex);
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.
1065 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
1066 slottable->st_slots[wfse->slotid]->sl_no_wfse = B_TRUE;
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).
1074 slottable->st_slots[wfse->slotid]->sl_wfse_state = WFSE_CLEAR;
1075 (void) pthread_mutex_unlock(&slottable->
1076 st_slots[wfse->slotid]->sl_mutex);
1079 if (slottable->st_blocking) {
1080 slottable->st_list_signaled = B_TRUE;
1081 (void) pthread_cond_signal(&slottable->st_wait_cond);
1084 (void) pthread_mutex_unlock(&slottable->st_mutex);
1086 /* Manually exit the thread, since nobody will join to it */
1087 pthread_exit(0);
1089 /*NOTREACHED*/
1090 return (NULL);