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 1419e1a718fSdarrenm pkcs11_fork_prepare(void) 1429e1a718fSdarrenm { 1434daf2311Srupertk int i; 144*83140133SZdenek Kotala if (pkcs11_initialized) { 1454daf2311Srupertk if (slottable != NULL) { 1464daf2311Srupertk (void) pthread_mutex_lock(&slottable->st_mutex); 1474daf2311Srupertk 1484daf2311Srupertk /* Take the sl_mutex of all slots */ 149*83140133SZdenek Kotala for (i = slottable->st_first; 150*83140133SZdenek Kotala i <= slottable->st_last; i++) { 1514daf2311Srupertk if (slottable->st_slots[i] != NULL) { 1524daf2311Srupertk (void) pthread_mutex_lock( 1534daf2311Srupertk &slottable->st_slots[i]->sl_mutex); 1544daf2311Srupertk } 1554daf2311Srupertk } 1564daf2311Srupertk } 1579e1a718fSdarrenm } 158*83140133SZdenek Kotala } 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 1669e1a718fSdarrenm pkcs11_fork_parent(void) 1679e1a718fSdarrenm { 1684daf2311Srupertk int i; 169*83140133SZdenek Kotala if (pkcs11_initialized) { 1704daf2311Srupertk if (slottable != NULL) { 1714daf2311Srupertk /* Release the sl_mutex of all slots */ 172*83140133SZdenek Kotala for (i = slottable->st_first; 173*83140133SZdenek Kotala i <= slottable->st_last; i++) { 1744daf2311Srupertk if (slottable->st_slots[i] != NULL) { 1754daf2311Srupertk (void) pthread_mutex_unlock( 1764daf2311Srupertk &slottable->st_slots[i]->sl_mutex); 1774daf2311Srupertk } 1784daf2311Srupertk } 179*83140133SZdenek Kotala } 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 1969e1a718fSdarrenm pkcs11_fork_child(void) 1979e1a718fSdarrenm { 1984daf2311Srupertk int i; 199*83140133SZdenek Kotala if (pkcs11_initialized) { 2004daf2311Srupertk if (slottable != NULL) { 2014daf2311Srupertk /* Release the sl_mutex of all slots */ 202*83140133SZdenek Kotala for (i = slottable->st_first; 203*83140133SZdenek Kotala i <= slottable->st_last; i++) { 2044daf2311Srupertk if (slottable->st_slots[i] != NULL) { 2054daf2311Srupertk (void) pthread_mutex_unlock( 2064daf2311Srupertk &slottable->st_slots[i]->sl_mutex); 2074daf2311Srupertk } 2084daf2311Srupertk } 209*83140133SZdenek Kotala } 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 219*83140133SZdenek Kotala pkcs11_fork_child_fini(void) 220*83140133SZdenek Kotala { 2219e1a718fSdarrenm pkcs11_fini(); 2229e1a718fSdarrenm } 2239e1a718fSdarrenm 2247c478bd9Sstevel@tonic-gate CK_RV 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 = 2587c478bd9Sstevel@tonic-gate (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) && 2717c478bd9Sstevel@tonic-gate (initargs->LockMutex != NULL) && 2727c478bd9Sstevel@tonic-gate (initargs->UnlockMutex != NULL) && 2737c478bd9Sstevel@tonic-gate (initargs->DestroyMutex != NULL)) || 2747c478bd9Sstevel@tonic-gate ((initargs->CreateMutex == NULL) && 2757c478bd9Sstevel@tonic-gate (initargs->LockMutex == NULL) && 2767c478bd9Sstevel@tonic-gate (initargs->UnlockMutex == NULL) && 2777c478bd9Sstevel@tonic-gate (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 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 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( 4207c478bd9Sstevel@tonic-gate &slottable->st_wait_cond); 4217c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock( 4227c478bd9Sstevel@tonic-gate &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 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 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 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 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 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 5587c478bd9Sstevel@tonic-gate C_CancelFunction(CK_SESSION_HANDLE hSession) 5597c478bd9Sstevel@tonic-gate { 5607c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_NOT_PARALLEL); 5617c478bd9Sstevel@tonic-gate } 562