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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
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
51 C_GetSlotList(CK_BBOOL tokenPresent
, CK_SLOT_ID_PTR pSlotList
,
52 CK_ULONG_PTR pulCount
)
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
,
68 if (!pkcs11_initialized
) {
69 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
72 if (pulCount
== NULL
) {
73 return (CKR_ARGUMENTS_BAD
);
77 /* Need to allocate memory for pinfo */
78 pinfo
= malloc(sizeof (CK_SLOT_INFO
));
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 */
99 /* Check with provider */
101 prov_rv
= FUNCLIST(i
)->
102 C_GetSlotInfo(true_id
, pinfo
);
103 if ((prov_rv
!= CKR_OK
) ||
104 !(pinfo
->flags
& CKF_TOKEN_PRESENT
)) {
108 /* Fill in the given buffer if it is sufficient */
109 if (pSlotList
&& (*pulCount
> count
)) {
110 pSlotList
[count
] = slot_id
;
117 /* pSlotList set to NULL means caller only wants count */
118 if ((*pulCount
< count
) && (pSlotList
!= NULL
)) {
119 rv
= CKR_BUFFER_TOO_SMALL
;
134 C_GetSlotInfo(CK_SLOT_ID slotID
, CK_SLOT_INFO_PTR pInfo
)
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
);
169 C_GetTokenInfo(CK_SLOT_ID slotID
, CK_TOKEN_INFO_PTR pInfo
)
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
);
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.
213 C_WaitForSlotEvent(CK_FLAGS flags
, CK_SLOT_ID_PTR pSlot
, CK_VOID_PTR pReserved
)
217 int32_t last_prov_id
= -1;
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
,
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
);
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
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
);
269 * This event has been captured, clear the function's
270 * active status. Other threads may now enter this
273 (void) pthread_mutex_lock(&slottable
->st_mutex
);
274 slottable
->st_wfse_active
= B_FALSE
;
275 (void) pthread_mutex_unlock(&slottable
->st_mutex
);
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
) {
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
);
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
,
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.
344 slottable
->st_slots
[j
]->sl_prov_id
) {
346 /* Find the slot, remap pSlot */
347 if (*pSlot
== TRUEID(j
)) {
349 (void) pthread_mutex_lock(
350 &slottable
->st_mutex
);
351 slottable
->st_wfse_active
=
353 (void) pthread_mutex_unlock(
354 &slottable
->st_mutex
);
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
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
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
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
) {
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
;
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
);
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
=
545 (void) pthread_mutex_unlock(&slottable
->
546 st_slots
[event_slot
]->sl_mutex
);
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
);
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.
582 C_GetMechanismList(CK_SLOT_ID slotID
, CK_MECHANISM_TYPE_PTR pMechanismList
,
583 CK_ULONG_PTR pulCount
)
587 CK_ULONG tmpmech_count
;
588 CK_MECHANISM_TYPE_PTR pmech_list
, tmpmech_list
;
590 CK_SLOT_ID fw_st_id
; /* id for accessing framework's slottable */
591 CK_FUNCTION_LIST_PTR prov_funcs
;
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
,
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
) {
617 prov_funcs
= fast_funcs
;
619 true_id
= TRUEID(fw_st_id
);
620 prov_funcs
= FUNCLIST(fw_st_id
);
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
) {
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.
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
])) {
691 * Only set pMechanismList if enough memory
692 * is available. If it was set to NULL
693 * originally, this loop will just be counting
696 if (pMechanismList
&& (*pulCount
> mech_count
)) {
697 pMechanismList
[mech_count
] = pmech_list
[i
];
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
708 if ((*pulCount
< mech_count
) && (pMechanismList
!= NULL
)) {
709 *pulCount
= mech_count
;
711 return (CKR_BUFFER_TOO_SMALL
);
714 *pulCount
= mech_count
;
722 C_GetMechanismInfo(CK_SLOT_ID slotID
, CK_MECHANISM_TYPE type
,
723 CK_MECHANISM_INFO_PTR pInfo
)
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
) {
751 prov_funcs
= fast_funcs
;
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
);
774 C_InitToken(CK_SLOT_ID slotID
, CK_UTF8CHAR_PTR pPin
, CK_ULONG ulPinLen
,
775 CK_UTF8CHAR_PTR pLabel
)
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
,
789 if (slotID
== METASLOT_FRAMEWORK_ID
) {
790 /* just need to get metaslot information */
791 return (meta_InitToken(METASLOT_SLOTID
, pPin
, ulPinLen
,
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
,
803 /* Present consistent interface to the application */
804 if (rv
== CKR_FUNCTION_NOT_SUPPORTED
) {
805 return (CKR_FUNCTION_FAILED
);
812 C_InitPIN(CK_SESSION_HANDLE hSession
, CK_UTF8CHAR_PTR pPin
, CK_ULONG ulPinLen
)
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
);
834 /* Initialize the PIN with the provider */
835 rv
= FUNCLIST(sessp
->se_slotid
)->C_InitPIN(sessp
->se_handle
,
838 /* Present consistent interface to the application */
839 if (rv
== CKR_FUNCTION_NOT_SUPPORTED
) {
840 return (CKR_FUNCTION_FAILED
);
847 C_SetPIN(CK_SESSION_HANDLE hSession
, CK_UTF8CHAR_PTR pOldPin
,
848 CK_ULONG ulOldPinLen
, CK_UTF8CHAR_PTR pNewPin
,
849 CK_ULONG ulNewPinLen
)
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
);
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
);
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
893 listener_waitforslotevent(void *arg
) {
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 */
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
);
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
);
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 */
969 * child_waitforslotevent is used as a child thread to contact
970 * underlying provider's C_WaitForSlotEvent().
973 child_waitforslotevent(void *arg
) {
975 wfse_args_t
*wfse
= (wfse_args_t
*)arg
;
981 rv
= FUNCLIST(wfse
->slotid
)->C_WaitForSlotEvent(wfse
->flags
, &slot
,
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
);
1003 (void) pthread_mutex_lock(&slottable
->st_mutex
);
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
) {
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
->
1047 (void) pthread_mutex_unlock(
1048 &slottable
->st_mutex
);
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 */