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
C_GetSlotList(CK_BBOOL tokenPresent,CK_SLOT_ID_PTR pSlotList,CK_ULONG_PTR pulCount)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
C_GetSlotInfo(CK_SLOT_ID slotID,CK_SLOT_INFO_PTR pInfo)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
C_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)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
C_WaitForSlotEvent(CK_FLAGS flags,CK_SLOT_ID_PTR pSlot,CK_VOID_PTR pReserved)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
C_GetMechanismList(CK_SLOT_ID slotID,CK_MECHANISM_TYPE_PTR pMechanismList,CK_ULONG_PTR pulCount)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
C_GetMechanismInfo(CK_SLOT_ID slotID,CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo)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
C_InitToken(CK_SLOT_ID slotID,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen,CK_UTF8CHAR_PTR pLabel)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
C_InitPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen)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
C_SetPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pOldPin,CK_ULONG ulOldPinLen,CK_UTF8CHAR_PTR pNewPin,CK_ULONG ulNewPinLen)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 *
listener_waitforslotevent(void * arg)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 *
child_waitforslotevent(void * arg)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