17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
54daf2311Srupertk * Common Development and Distribution License (the "License").
64daf2311Srupertk * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*83140133SZdenek Kotala * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <unistd.h>
277c478bd9Sstevel@tonic-gate #include <string.h>
287c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
297c478bd9Sstevel@tonic-gate #include <pthread.h>
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
327c478bd9Sstevel@tonic-gate #include "pkcs11Global.h"
337c478bd9Sstevel@tonic-gate #include "pkcs11Slot.h"
347c478bd9Sstevel@tonic-gate #include "pkcs11Conf.h"
357c478bd9Sstevel@tonic-gate #include "pkcs11Session.h"
3651ed222cSwyllys #include "metaGlobal.h"
377c478bd9Sstevel@tonic-gate
38*83140133SZdenek Kotala #pragma init(pkcs11_init)
397c478bd9Sstevel@tonic-gate #pragma fini(pkcs11_fini)
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate static struct CK_FUNCTION_LIST functionList = {
42f66d273dSizick { 2, 20 }, /* version */
437c478bd9Sstevel@tonic-gate C_Initialize,
447c478bd9Sstevel@tonic-gate C_Finalize,
457c478bd9Sstevel@tonic-gate C_GetInfo,
467c478bd9Sstevel@tonic-gate C_GetFunctionList,
477c478bd9Sstevel@tonic-gate C_GetSlotList,
487c478bd9Sstevel@tonic-gate C_GetSlotInfo,
497c478bd9Sstevel@tonic-gate C_GetTokenInfo,
507c478bd9Sstevel@tonic-gate C_GetMechanismList,
517c478bd9Sstevel@tonic-gate C_GetMechanismInfo,
527c478bd9Sstevel@tonic-gate C_InitToken,
537c478bd9Sstevel@tonic-gate C_InitPIN,
547c478bd9Sstevel@tonic-gate C_SetPIN,
557c478bd9Sstevel@tonic-gate C_OpenSession,
567c478bd9Sstevel@tonic-gate C_CloseSession,
577c478bd9Sstevel@tonic-gate C_CloseAllSessions,
587c478bd9Sstevel@tonic-gate C_GetSessionInfo,
597c478bd9Sstevel@tonic-gate C_GetOperationState,
607c478bd9Sstevel@tonic-gate C_SetOperationState,
617c478bd9Sstevel@tonic-gate C_Login,
627c478bd9Sstevel@tonic-gate C_Logout,
637c478bd9Sstevel@tonic-gate C_CreateObject,
647c478bd9Sstevel@tonic-gate C_CopyObject,
657c478bd9Sstevel@tonic-gate C_DestroyObject,
667c478bd9Sstevel@tonic-gate C_GetObjectSize,
677c478bd9Sstevel@tonic-gate C_GetAttributeValue,
687c478bd9Sstevel@tonic-gate C_SetAttributeValue,
697c478bd9Sstevel@tonic-gate C_FindObjectsInit,
707c478bd9Sstevel@tonic-gate C_FindObjects,
717c478bd9Sstevel@tonic-gate C_FindObjectsFinal,
727c478bd9Sstevel@tonic-gate C_EncryptInit,
737c478bd9Sstevel@tonic-gate C_Encrypt,
747c478bd9Sstevel@tonic-gate C_EncryptUpdate,
757c478bd9Sstevel@tonic-gate C_EncryptFinal,
767c478bd9Sstevel@tonic-gate C_DecryptInit,
777c478bd9Sstevel@tonic-gate C_Decrypt,
787c478bd9Sstevel@tonic-gate C_DecryptUpdate,
797c478bd9Sstevel@tonic-gate C_DecryptFinal,
807c478bd9Sstevel@tonic-gate C_DigestInit,
817c478bd9Sstevel@tonic-gate C_Digest,
827c478bd9Sstevel@tonic-gate C_DigestUpdate,
837c478bd9Sstevel@tonic-gate C_DigestKey,
847c478bd9Sstevel@tonic-gate C_DigestFinal,
857c478bd9Sstevel@tonic-gate C_SignInit,
867c478bd9Sstevel@tonic-gate C_Sign,
877c478bd9Sstevel@tonic-gate C_SignUpdate,
887c478bd9Sstevel@tonic-gate C_SignFinal,
897c478bd9Sstevel@tonic-gate C_SignRecoverInit,
907c478bd9Sstevel@tonic-gate C_SignRecover,
917c478bd9Sstevel@tonic-gate C_VerifyInit,
927c478bd9Sstevel@tonic-gate C_Verify,
937c478bd9Sstevel@tonic-gate C_VerifyUpdate,
947c478bd9Sstevel@tonic-gate C_VerifyFinal,
957c478bd9Sstevel@tonic-gate C_VerifyRecoverInit,
967c478bd9Sstevel@tonic-gate C_VerifyRecover,
977c478bd9Sstevel@tonic-gate C_DigestEncryptUpdate,
987c478bd9Sstevel@tonic-gate C_DecryptDigestUpdate,
997c478bd9Sstevel@tonic-gate C_SignEncryptUpdate,
1007c478bd9Sstevel@tonic-gate C_DecryptVerifyUpdate,
1017c478bd9Sstevel@tonic-gate C_GenerateKey,
1027c478bd9Sstevel@tonic-gate C_GenerateKeyPair,
1037c478bd9Sstevel@tonic-gate C_WrapKey,
1047c478bd9Sstevel@tonic-gate C_UnwrapKey,
1057c478bd9Sstevel@tonic-gate C_DeriveKey,
1067c478bd9Sstevel@tonic-gate C_SeedRandom,
1077c478bd9Sstevel@tonic-gate C_GenerateRandom,
1087c478bd9Sstevel@tonic-gate C_GetFunctionStatus,
1097c478bd9Sstevel@tonic-gate C_CancelFunction,
1107c478bd9Sstevel@tonic-gate C_WaitForSlotEvent
1117c478bd9Sstevel@tonic-gate };
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate boolean_t pkcs11_initialized = B_FALSE;
1147c478bd9Sstevel@tonic-gate boolean_t pkcs11_cant_create_threads = B_FALSE;
1157c478bd9Sstevel@tonic-gate boolean_t fini_called = B_FALSE;
1164daf2311Srupertk static boolean_t pkcs11_atfork_initialized = B_FALSE;
1177c478bd9Sstevel@tonic-gate static pid_t pkcs11_pid = 0;
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /* protects pkcs11_[initialized|pid], and fastpath */
1207c478bd9Sstevel@tonic-gate static pthread_mutex_t globalmutex = PTHREAD_MUTEX_INITIALIZER;
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate static CK_RV finalize_common(CK_VOID_PTR pReserved);
123*83140133SZdenek Kotala static void pkcs11_init();
1247c478bd9Sstevel@tonic-gate static void pkcs11_fini();
1257c478bd9Sstevel@tonic-gate
1269e1a718fSdarrenm /*
1274daf2311Srupertk * Ensure that before a fork, all mutexes are taken.
128*83140133SZdenek Kotala * We cannot acquire globalmutex, because it can cause deadlock when
129*83140133SZdenek Kotala * atfork() and fork() are called in parallel. It can happen when
130*83140133SZdenek Kotala * C_Ininitialize() tries to dlopen() a provider. The dlopen() operation
131*83140133SZdenek Kotala * is protected by globalmutex and when another thread calls fork()
132*83140133SZdenek Kotala * pkcs11_fork_prepare cannot acquire the mutex again and thus it must wait.
133*83140133SZdenek Kotala * When a provider tries to register its atfork handler, atfork() must
134*83140133SZdenek Kotala * wait on fork(). See the comment in fork() libc function for more details.
135*83140133SZdenek Kotala *
1364daf2311Srupertk * Order:
137*83140133SZdenek Kotala * 1. slottable->st_mutex
138*83140133SZdenek Kotala * 2. all slottable->st_slots' mutexes
1399e1a718fSdarrenm */
1409e1a718fSdarrenm static void
pkcs11_fork_prepare(void)1419e1a718fSdarrenm pkcs11_fork_prepare(void)
1429e1a718fSdarrenm {
1434daf2311Srupertk int i;
144*83140133SZdenek Kotala if (pkcs11_initialized) {
145*83140133SZdenek Kotala if (slottable != NULL) {
146*83140133SZdenek Kotala (void) pthread_mutex_lock(&slottable->st_mutex);
147*83140133SZdenek Kotala
148*83140133SZdenek Kotala /* Take the sl_mutex of all slots */
149*83140133SZdenek Kotala for (i = slottable->st_first;
150*83140133SZdenek Kotala i <= slottable->st_last; i++) {
151*83140133SZdenek Kotala if (slottable->st_slots[i] != NULL) {
152*83140133SZdenek Kotala (void) pthread_mutex_lock(
153*83140133SZdenek Kotala &slottable->st_slots[i]->sl_mutex);
154*83140133SZdenek Kotala }
1554daf2311Srupertk }
1564daf2311Srupertk }
1574daf2311Srupertk }
1589e1a718fSdarrenm }
1599e1a718fSdarrenm
1609e1a718fSdarrenm
1619e1a718fSdarrenm /*
1624daf2311Srupertk * Ensure that after a fork, in the parent, all mutexes are released in opposite
1634daf2311Srupertk * order to pkcs11_fork_prepare().
1649e1a718fSdarrenm */
1659e1a718fSdarrenm static void
pkcs11_fork_parent(void)1669e1a718fSdarrenm pkcs11_fork_parent(void)
1679e1a718fSdarrenm {
1684daf2311Srupertk int i;
169*83140133SZdenek Kotala if (pkcs11_initialized) {
170*83140133SZdenek Kotala if (slottable != NULL) {
171*83140133SZdenek Kotala /* Release the sl_mutex of all slots */
172*83140133SZdenek Kotala for (i = slottable->st_first;
173*83140133SZdenek Kotala i <= slottable->st_last; i++) {
174*83140133SZdenek Kotala if (slottable->st_slots[i] != NULL) {
175*83140133SZdenek Kotala (void) pthread_mutex_unlock(
176*83140133SZdenek Kotala &slottable->st_slots[i]->sl_mutex);
177*83140133SZdenek Kotala }
1784daf2311Srupertk }
1794daf2311Srupertk }
1804daf2311Srupertk (void) pthread_mutex_unlock(&slottable->st_mutex);
1814daf2311Srupertk }
1829e1a718fSdarrenm }
1839e1a718fSdarrenm
1849e1a718fSdarrenm
1859e1a718fSdarrenm /*
1864daf2311Srupertk * Ensure that after a fork, in the child, all mutexes are released in opposite
1874daf2311Srupertk * order to pkcs11_fork_prepare() and cleanup is done.
188*83140133SZdenek Kotala * Because we need to handle fork correctly before library is initialized two
189*83140133SZdenek Kotala * handlers are necessary.
190*83140133SZdenek Kotala *
191*83140133SZdenek Kotala * 1) pkcs11_fork_child() - unlock mutexes
192*83140133SZdenek Kotala * 2) pkcs11_fork_child_fini() - cleanup library after fork, it is registered in
193*83140133SZdenek Kotala * C_Initialize() after providers initialization.
1949e1a718fSdarrenm */
1959e1a718fSdarrenm static void
pkcs11_fork_child(void)1969e1a718fSdarrenm pkcs11_fork_child(void)
1979e1a718fSdarrenm {
1984daf2311Srupertk int i;
199*83140133SZdenek Kotala if (pkcs11_initialized) {
200*83140133SZdenek Kotala if (slottable != NULL) {
201*83140133SZdenek Kotala /* Release the sl_mutex of all slots */
202*83140133SZdenek Kotala for (i = slottable->st_first;
203*83140133SZdenek Kotala i <= slottable->st_last; i++) {
204*83140133SZdenek Kotala if (slottable->st_slots[i] != NULL) {
205*83140133SZdenek Kotala (void) pthread_mutex_unlock(
206*83140133SZdenek Kotala &slottable->st_slots[i]->sl_mutex);
207*83140133SZdenek Kotala }
2084daf2311Srupertk }
2094daf2311Srupertk }
2104daf2311Srupertk (void) pthread_mutex_unlock(&slottable->st_mutex);
2114daf2311Srupertk }
212*83140133SZdenek Kotala
213*83140133SZdenek Kotala (void) pthread_mutex_destroy(&globalmutex);
214*83140133SZdenek Kotala (void) pthread_mutex_init(&globalmutex, NULL);
215*83140133SZdenek Kotala }
216*83140133SZdenek Kotala
217*83140133SZdenek Kotala /* Library cleanup have to be last afterfork child handler. */
218*83140133SZdenek Kotala static void
pkcs11_fork_child_fini(void)219*83140133SZdenek Kotala pkcs11_fork_child_fini(void)
220*83140133SZdenek Kotala {
2219e1a718fSdarrenm pkcs11_fini();
2229e1a718fSdarrenm }
2239e1a718fSdarrenm
2247c478bd9Sstevel@tonic-gate CK_RV
C_Initialize(CK_VOID_PTR pInitArgs)2257c478bd9Sstevel@tonic-gate C_Initialize(CK_VOID_PTR pInitArgs)
2267c478bd9Sstevel@tonic-gate {
2277c478bd9Sstevel@tonic-gate CK_RV rv;
2287c478bd9Sstevel@tonic-gate uentrylist_t *pliblist = NULL;
2297c478bd9Sstevel@tonic-gate int initialize_pid;
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate /*
2327c478bd9Sstevel@tonic-gate * Grab lock to insure only one thread enters
2337c478bd9Sstevel@tonic-gate * this function at a time.
2347c478bd9Sstevel@tonic-gate */
2357c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&globalmutex);
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate initialize_pid = getpid();
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate /* Make sure function hasn't been called twice */
2407c478bd9Sstevel@tonic-gate if (pkcs11_initialized) {
2417c478bd9Sstevel@tonic-gate if (initialize_pid == pkcs11_pid) {
2427c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex);
2437c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_ALREADY_INITIALIZED);
2447c478bd9Sstevel@tonic-gate } else {
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate * A fork has happened and the child is
2477c478bd9Sstevel@tonic-gate * reinitializing. Do a finalize_common() to close
2487c478bd9Sstevel@tonic-gate * out any state from the parent, and then
2497c478bd9Sstevel@tonic-gate * continue on.
2507c478bd9Sstevel@tonic-gate */
2517c478bd9Sstevel@tonic-gate (void) finalize_common(NULL);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate /* Check if application has provided mutex-handling functions */
2567c478bd9Sstevel@tonic-gate if (pInitArgs != NULL) {
2577c478bd9Sstevel@tonic-gate CK_C_INITIALIZE_ARGS_PTR initargs =
25851ed222cSwyllys (CK_C_INITIALIZE_ARGS_PTR) pInitArgs;
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate /* pReserved should not be set */
2617c478bd9Sstevel@tonic-gate if (initargs->pReserved != NULL) {
2627c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
2637c478bd9Sstevel@tonic-gate goto errorexit;
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate * Make sure function pointers are either all NULL or
2687c478bd9Sstevel@tonic-gate * all set.
2697c478bd9Sstevel@tonic-gate */
2707c478bd9Sstevel@tonic-gate if (!(((initargs->CreateMutex != NULL) &&
27151ed222cSwyllys (initargs->LockMutex != NULL) &&
27251ed222cSwyllys (initargs->UnlockMutex != NULL) &&
27351ed222cSwyllys (initargs->DestroyMutex != NULL)) ||
27451ed222cSwyllys ((initargs->CreateMutex == NULL) &&
27551ed222cSwyllys (initargs->LockMutex == NULL) &&
27651ed222cSwyllys (initargs->UnlockMutex == NULL) &&
27751ed222cSwyllys (initargs->DestroyMutex == NULL)))) {
2787c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
2797c478bd9Sstevel@tonic-gate goto errorexit;
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate if (!(initargs->flags & CKF_OS_LOCKING_OK)) {
2837c478bd9Sstevel@tonic-gate if (initargs->CreateMutex != NULL) {
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate * Do not accept application supplied
2867c478bd9Sstevel@tonic-gate * locking primitives.
2877c478bd9Sstevel@tonic-gate */
2887c478bd9Sstevel@tonic-gate rv = CKR_CANT_LOCK;
2897c478bd9Sstevel@tonic-gate goto errorexit;
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate if (initargs->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) {
2947c478bd9Sstevel@tonic-gate /*
2957c478bd9Sstevel@tonic-gate * Calling application does not want the library
2967c478bd9Sstevel@tonic-gate * to create threads. This will effect
2977c478bd9Sstevel@tonic-gate * C_WaitForSlotEvent().
2987c478bd9Sstevel@tonic-gate */
2997c478bd9Sstevel@tonic-gate pkcs11_cant_create_threads = B_TRUE;
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate /* Initialize slot table */
3047c478bd9Sstevel@tonic-gate rv = pkcs11_slottable_initialize();
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
3077c478bd9Sstevel@tonic-gate goto errorexit;
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate /* Get the list of providers */
3107c478bd9Sstevel@tonic-gate if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
3117c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
3127c478bd9Sstevel@tonic-gate goto errorexit;
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate /*
3167c478bd9Sstevel@tonic-gate * Load each provider, check for accessible slots,
3177c478bd9Sstevel@tonic-gate * and populate slottable. If metaslot is enabled,
3187c478bd9Sstevel@tonic-gate * it will be initialized as well.
3197c478bd9Sstevel@tonic-gate */
3207c478bd9Sstevel@tonic-gate rv = pkcs11_slot_mapping(pliblist, pInitArgs);
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
3237c478bd9Sstevel@tonic-gate goto errorexit;
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate pkcs11_initialized = B_TRUE;
3267c478bd9Sstevel@tonic-gate pkcs11_pid = initialize_pid;
3274daf2311Srupertk /* Children inherit parent's atfork handlers */
3284daf2311Srupertk if (!pkcs11_atfork_initialized) {
329*83140133SZdenek Kotala (void) pthread_atfork(NULL, NULL, pkcs11_fork_child_fini);
3304daf2311Srupertk pkcs11_atfork_initialized = B_TRUE;
3314daf2311Srupertk }
332*83140133SZdenek Kotala
3337c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex);
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate /* Cleanup data structures no longer needed */
3367c478bd9Sstevel@tonic-gate free_uentrylist(pliblist);
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate return (CKR_OK);
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate errorexit:
3417c478bd9Sstevel@tonic-gate /* Cleanup any data structures that have already been allocated */
3427c478bd9Sstevel@tonic-gate if (slottable)
3437c478bd9Sstevel@tonic-gate (void) pkcs11_slottable_delete();
3447c478bd9Sstevel@tonic-gate if (pliblist)
3457c478bd9Sstevel@tonic-gate (void) free_uentrylist(pliblist);
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex);
3487c478bd9Sstevel@tonic-gate return (rv);
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate /*
3537c478bd9Sstevel@tonic-gate * C_Finalize is a wrapper around finalize_common. The
3547c478bd9Sstevel@tonic-gate * globalmutex should be locked by C_Finalize().
3557c478bd9Sstevel@tonic-gate *
3567c478bd9Sstevel@tonic-gate * When an explicit C_Finalize() call is received, all
3577c478bd9Sstevel@tonic-gate * plugins currently in the slottable will also be
3587c478bd9Sstevel@tonic-gate * finalized. This must occur, even if libpkcs11(3lib)
3597c478bd9Sstevel@tonic-gate * was not the first one to initialize the plugins, since it
3607c478bd9Sstevel@tonic-gate * is the only way in PKCS#11 to force a refresh of the
3617c478bd9Sstevel@tonic-gate * slot listings (ie to get new hardware devices).
3627c478bd9Sstevel@tonic-gate */
3637c478bd9Sstevel@tonic-gate CK_RV
C_Finalize(CK_VOID_PTR pReserved)3647c478bd9Sstevel@tonic-gate C_Finalize(CK_VOID_PTR pReserved)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate CK_RV rv;
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&globalmutex);
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate rv = finalize_common(pReserved);
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex);
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate return (rv);
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate /*
3797c478bd9Sstevel@tonic-gate * finalize_common() does the work for C_Finalize. globalmutex
3807c478bd9Sstevel@tonic-gate * must be held before calling this function.
3817c478bd9Sstevel@tonic-gate */
3827c478bd9Sstevel@tonic-gate static CK_RV
finalize_common(CK_VOID_PTR pReserved)3837c478bd9Sstevel@tonic-gate finalize_common(CK_VOID_PTR pReserved)
3847c478bd9Sstevel@tonic-gate {
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate CK_RV rv;
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate if (!pkcs11_initialized) {
3897c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate if (pReserved != NULL) {
3937c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate purefastpath = B_FALSE;
3977c478bd9Sstevel@tonic-gate policyfastpath = B_FALSE;
3987c478bd9Sstevel@tonic-gate fast_funcs = NULL;
3997c478bd9Sstevel@tonic-gate fast_slot = 0;
4007c478bd9Sstevel@tonic-gate pkcs11_initialized = B_FALSE;
4017c478bd9Sstevel@tonic-gate pkcs11_cant_create_threads = B_FALSE;
4027c478bd9Sstevel@tonic-gate pkcs11_pid = 0;
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate /* Check if C_WaitForSlotEvent() is currently active */
4057c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&slottable->st_mutex);
4067c478bd9Sstevel@tonic-gate if (slottable->st_wfse_active) {
4077c478bd9Sstevel@tonic-gate /*
4087c478bd9Sstevel@tonic-gate * Wait for this thread to proceed far enough to block or
4097c478bd9Sstevel@tonic-gate * end on its own. Otherwise, teardown of slottable may
4107c478bd9Sstevel@tonic-gate * occurr before this active function completes.
4117c478bd9Sstevel@tonic-gate */
4127c478bd9Sstevel@tonic-gate while (slottable->st_wfse_active) {
4137c478bd9Sstevel@tonic-gate /*
4147c478bd9Sstevel@tonic-gate * If C_WaitForSlotEvent is blocking, wake it up and
4157c478bd9Sstevel@tonic-gate * return error to calling application.
4167c478bd9Sstevel@tonic-gate */
4177c478bd9Sstevel@tonic-gate if (slottable->st_blocking) {
4187c478bd9Sstevel@tonic-gate slottable->st_list_signaled = B_TRUE;
4197c478bd9Sstevel@tonic-gate (void) pthread_cond_signal(
42051ed222cSwyllys &slottable->st_wait_cond);
4217c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(
42251ed222cSwyllys &slottable->st_mutex);
4237c478bd9Sstevel@tonic-gate (void) pthread_join(slottable->st_tid, NULL);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate } else {
4277c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&slottable->st_mutex);
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate rv = pkcs11_slottable_delete();
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate return (rv);
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate
435*83140133SZdenek Kotala static void
pkcs11_init()436*83140133SZdenek Kotala pkcs11_init()
437*83140133SZdenek Kotala {
438*83140133SZdenek Kotala (void) pthread_atfork(pkcs11_fork_prepare,
439*83140133SZdenek Kotala pkcs11_fork_parent, pkcs11_fork_child);
440*83140133SZdenek Kotala }
441*83140133SZdenek Kotala
4427c478bd9Sstevel@tonic-gate /*
4437c478bd9Sstevel@tonic-gate * pkcs11_fini() function required to make sure complete cleanup
4447c478bd9Sstevel@tonic-gate * is done of plugins if the framework is ever unloaded without
4457c478bd9Sstevel@tonic-gate * a C_Finalize() call. This would be common when applications
4467c478bd9Sstevel@tonic-gate * load and unload other libraries that use libpkcs11(3lib), since
4477c478bd9Sstevel@tonic-gate * shared libraries should not call C_Finalize().
4487c478bd9Sstevel@tonic-gate *
4497c478bd9Sstevel@tonic-gate * If pkcs11_fini() is used, we set fini_called to B_TRUE so that
4507c478bd9Sstevel@tonic-gate * pkcs11_slottable_delete() will not call C_Finalize() on the plugins.
4517c478bd9Sstevel@tonic-gate *
4527c478bd9Sstevel@tonic-gate * This is to protect in cases where the application has dlopened
4537c478bd9Sstevel@tonic-gate * an object (for example, dlobj) that links to libpkcs11(3lib), but
4547c478bd9Sstevel@tonic-gate * the application is unaware that the object is doing PKCS#11 calls
4557c478bd9Sstevel@tonic-gate * underneath. This application may later directly dlopen one of the
4567c478bd9Sstevel@tonic-gate * plugins (like pkcs11_softtoken.so, or any other 3rd party provided
4577c478bd9Sstevel@tonic-gate * plugin) in order to directly perform PKCS#11 operations.
4587c478bd9Sstevel@tonic-gate *
4597c478bd9Sstevel@tonic-gate * While it is still actively using the PKCS#11 plugin directly,
4607c478bd9Sstevel@tonic-gate * the application may finish with dlobj and dlclose it. As the
4617c478bd9Sstevel@tonic-gate * reference count for libpkcs11(3lib) has become 0, pkcs11_fini()
4627c478bd9Sstevel@tonic-gate * will be run by the linker. Even though libpkcs11(3lib) was the
4637c478bd9Sstevel@tonic-gate * first to initialize the plugin in this case, it is not safe for
4647c478bd9Sstevel@tonic-gate * libpkcs11(3lib) to finalize the plugin, as the application would
4657c478bd9Sstevel@tonic-gate * lose state.
4667c478bd9Sstevel@tonic-gate */
4677c478bd9Sstevel@tonic-gate static void
pkcs11_fini()4687c478bd9Sstevel@tonic-gate pkcs11_fini()
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&globalmutex);
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate /* if we're not initilized, do not attempt to finalize */
4737c478bd9Sstevel@tonic-gate if (!pkcs11_initialized) {
4747c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex);
4757c478bd9Sstevel@tonic-gate return;
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate fini_called = B_TRUE;
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate (void) finalize_common(NULL_PTR);
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex);
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate }
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate CK_RV
C_GetInfo(CK_INFO_PTR pInfo)4877c478bd9Sstevel@tonic-gate C_GetInfo(CK_INFO_PTR pInfo)
4887c478bd9Sstevel@tonic-gate {
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate /* Check for a fastpath */
4917c478bd9Sstevel@tonic-gate if (purefastpath || policyfastpath) {
4927c478bd9Sstevel@tonic-gate return (fast_funcs->C_GetInfo(pInfo));
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate if (!pkcs11_initialized)
4967c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate if (pInfo == NULL) {
4997c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate /*
5037c478bd9Sstevel@tonic-gate * Copy data into the provided buffer, use strncpy() instead
5047c478bd9Sstevel@tonic-gate * of strlcpy() so that the strings are NOT NULL terminated,
5057c478bd9Sstevel@tonic-gate * as required by the PKCS#11 standard
5067c478bd9Sstevel@tonic-gate */
5077c478bd9Sstevel@tonic-gate (void) strncpy((char *)pInfo->manufacturerID, MANUFACTURER_ID,
5087c478bd9Sstevel@tonic-gate PKCS11_STRING_LENGTH);
5097c478bd9Sstevel@tonic-gate (void) strncpy((char *)pInfo->libraryDescription,
5107c478bd9Sstevel@tonic-gate LIBRARY_DESCRIPTION, PKCS11_STRING_LENGTH);
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
5137c478bd9Sstevel@tonic-gate pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
5147c478bd9Sstevel@tonic-gate pInfo->flags = 0;
5157c478bd9Sstevel@tonic-gate pInfo->libraryVersion.major = LIBRARY_VERSION_MAJOR;
5167c478bd9Sstevel@tonic-gate pInfo->libraryVersion.minor = LIBRARY_VERSION_MINOR;
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate return (CKR_OK);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate /*
5227c478bd9Sstevel@tonic-gate * This function is unaffected by the fast-path, since it is likely
5237c478bd9Sstevel@tonic-gate * called before C_Initialize is, so we will not yet know the status
5247c478bd9Sstevel@tonic-gate * of the fast-path. Additionally, policy will still need to be
5257c478bd9Sstevel@tonic-gate * enforced if applicable.
5267c478bd9Sstevel@tonic-gate */
5277c478bd9Sstevel@tonic-gate CK_RV
C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)5287c478bd9Sstevel@tonic-gate C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
5297c478bd9Sstevel@tonic-gate {
5307c478bd9Sstevel@tonic-gate if (ppFunctionList == NULL) {
5317c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate *ppFunctionList = &functionList;
5357c478bd9Sstevel@tonic-gate
5367c478bd9Sstevel@tonic-gate return (CKR_OK);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate /*
5417c478bd9Sstevel@tonic-gate * This function is no longer supported in this revision of the PKCS#11
5427c478bd9Sstevel@tonic-gate * standard. It is maintained for backwards compatibility only.
5437c478bd9Sstevel@tonic-gate */
5447c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5457c478bd9Sstevel@tonic-gate CK_RV
C_GetFunctionStatus(CK_SESSION_HANDLE hSession)5467c478bd9Sstevel@tonic-gate C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_NOT_PARALLEL);
5497c478bd9Sstevel@tonic-gate }
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate
5527c478bd9Sstevel@tonic-gate /*
5537c478bd9Sstevel@tonic-gate * This function is no longer supported in this revision of the PKCS#11
5547c478bd9Sstevel@tonic-gate * standard. It is maintained for backwards compatibility only.
5557c478bd9Sstevel@tonic-gate */
5567c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5577c478bd9Sstevel@tonic-gate CK_RV
C_CancelFunction(CK_SESSION_HANDLE hSession)5587c478bd9Sstevel@tonic-gate C_CancelFunction(CK_SESSION_HANDLE hSession)
5597c478bd9Sstevel@tonic-gate {
5607c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_NOT_PARALLEL);
5617c478bd9Sstevel@tonic-gate }
562