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 56f3f1c68Skrishna * Common Development and Distribution License (the "License"). 66f3f1c68Skrishna * 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 /* 221f49a79aSZdenek 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 <fcntl.h> 277c478bd9Sstevel@tonic-gate #include <pthread.h> 287c478bd9Sstevel@tonic-gate #include <strings.h> 297c478bd9Sstevel@tonic-gate #include <unistd.h> /* for pid */ 307c478bd9Sstevel@tonic-gate #include <errno.h> 317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 327c478bd9Sstevel@tonic-gate #include "kernelGlobal.h" 337c478bd9Sstevel@tonic-gate #include "kernelSession.h" 347c478bd9Sstevel@tonic-gate #include "kernelSlot.h" 357c478bd9Sstevel@tonic-gate 36*83140133SZdenek Kotala #pragma init(kernel_init) 377c478bd9Sstevel@tonic-gate #pragma fini(kernel_fini) 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate static struct CK_FUNCTION_LIST functionList = { 40f66d273dSizick { 2, 20 }, /* version */ 417c478bd9Sstevel@tonic-gate C_Initialize, 427c478bd9Sstevel@tonic-gate C_Finalize, 437c478bd9Sstevel@tonic-gate C_GetInfo, 447c478bd9Sstevel@tonic-gate C_GetFunctionList, 457c478bd9Sstevel@tonic-gate C_GetSlotList, 467c478bd9Sstevel@tonic-gate C_GetSlotInfo, 477c478bd9Sstevel@tonic-gate C_GetTokenInfo, 487c478bd9Sstevel@tonic-gate C_GetMechanismList, 497c478bd9Sstevel@tonic-gate C_GetMechanismInfo, 507c478bd9Sstevel@tonic-gate C_InitToken, 517c478bd9Sstevel@tonic-gate C_InitPIN, 527c478bd9Sstevel@tonic-gate C_SetPIN, 537c478bd9Sstevel@tonic-gate C_OpenSession, 547c478bd9Sstevel@tonic-gate C_CloseSession, 557c478bd9Sstevel@tonic-gate C_CloseAllSessions, 567c478bd9Sstevel@tonic-gate C_GetSessionInfo, 577c478bd9Sstevel@tonic-gate C_GetOperationState, 587c478bd9Sstevel@tonic-gate C_SetOperationState, 597c478bd9Sstevel@tonic-gate C_Login, 607c478bd9Sstevel@tonic-gate C_Logout, 617c478bd9Sstevel@tonic-gate C_CreateObject, 627c478bd9Sstevel@tonic-gate C_CopyObject, 637c478bd9Sstevel@tonic-gate C_DestroyObject, 647c478bd9Sstevel@tonic-gate C_GetObjectSize, 657c478bd9Sstevel@tonic-gate C_GetAttributeValue, 667c478bd9Sstevel@tonic-gate C_SetAttributeValue, 677c478bd9Sstevel@tonic-gate C_FindObjectsInit, 687c478bd9Sstevel@tonic-gate C_FindObjects, 697c478bd9Sstevel@tonic-gate C_FindObjectsFinal, 707c478bd9Sstevel@tonic-gate C_EncryptInit, 717c478bd9Sstevel@tonic-gate C_Encrypt, 727c478bd9Sstevel@tonic-gate C_EncryptUpdate, 737c478bd9Sstevel@tonic-gate C_EncryptFinal, 747c478bd9Sstevel@tonic-gate C_DecryptInit, 757c478bd9Sstevel@tonic-gate C_Decrypt, 767c478bd9Sstevel@tonic-gate C_DecryptUpdate, 777c478bd9Sstevel@tonic-gate C_DecryptFinal, 787c478bd9Sstevel@tonic-gate C_DigestInit, 797c478bd9Sstevel@tonic-gate C_Digest, 807c478bd9Sstevel@tonic-gate C_DigestUpdate, 817c478bd9Sstevel@tonic-gate C_DigestKey, 827c478bd9Sstevel@tonic-gate C_DigestFinal, 837c478bd9Sstevel@tonic-gate C_SignInit, 847c478bd9Sstevel@tonic-gate C_Sign, 857c478bd9Sstevel@tonic-gate C_SignUpdate, 867c478bd9Sstevel@tonic-gate C_SignFinal, 877c478bd9Sstevel@tonic-gate C_SignRecoverInit, 887c478bd9Sstevel@tonic-gate C_SignRecover, 897c478bd9Sstevel@tonic-gate C_VerifyInit, 907c478bd9Sstevel@tonic-gate C_Verify, 917c478bd9Sstevel@tonic-gate C_VerifyUpdate, 927c478bd9Sstevel@tonic-gate C_VerifyFinal, 937c478bd9Sstevel@tonic-gate C_VerifyRecoverInit, 947c478bd9Sstevel@tonic-gate C_VerifyRecover, 957c478bd9Sstevel@tonic-gate C_DigestEncryptUpdate, 967c478bd9Sstevel@tonic-gate C_DecryptDigestUpdate, 977c478bd9Sstevel@tonic-gate C_SignEncryptUpdate, 987c478bd9Sstevel@tonic-gate C_DecryptVerifyUpdate, 997c478bd9Sstevel@tonic-gate C_GenerateKey, 1007c478bd9Sstevel@tonic-gate C_GenerateKeyPair, 1017c478bd9Sstevel@tonic-gate C_WrapKey, 1027c478bd9Sstevel@tonic-gate C_UnwrapKey, 1037c478bd9Sstevel@tonic-gate C_DeriveKey, 1047c478bd9Sstevel@tonic-gate C_SeedRandom, 1057c478bd9Sstevel@tonic-gate C_GenerateRandom, 1067c478bd9Sstevel@tonic-gate C_GetFunctionStatus, 1077c478bd9Sstevel@tonic-gate C_CancelFunction, 1087c478bd9Sstevel@tonic-gate C_WaitForSlotEvent 1097c478bd9Sstevel@tonic-gate }; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate boolean_t kernel_initialized = B_FALSE; 1127c478bd9Sstevel@tonic-gate static pid_t kernel_pid = 0; 1137c478bd9Sstevel@tonic-gate 1141f49a79aSZdenek Kotala extern pthread_mutex_t mechhash_mutex; 1151f49a79aSZdenek Kotala 1167c478bd9Sstevel@tonic-gate int kernel_fd = -1; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* protects kernel_initialized and entrance to C_Initialize/Finalize */ 1207c478bd9Sstevel@tonic-gate static pthread_mutex_t globalmutex = PTHREAD_MUTEX_INITIALIZER; 1217c478bd9Sstevel@tonic-gate 12201223cbaSmcpowers ses_to_be_freed_list_t ses_delay_freed; 12301223cbaSmcpowers object_to_be_freed_list_t obj_delay_freed; 1246f3f1c68Skrishna kmh_elem_t **kernel_mechhash; /* Hash table for kCF mech numbers */ 12501223cbaSmcpowers 12601223cbaSmcpowers static void finalize_common(); 1277c478bd9Sstevel@tonic-gate static void cleanup_library(); 128*83140133SZdenek Kotala static void kernel_init(); 1297c478bd9Sstevel@tonic-gate static void kernel_fini(); 1304daf2311Srupertk static void kernel_fork_prepare(); 131*83140133SZdenek Kotala static void kernel_fork_after(); 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate CK_RV 1347c478bd9Sstevel@tonic-gate C_Initialize(CK_VOID_PTR pInitArgs) 1357c478bd9Sstevel@tonic-gate { 1367c478bd9Sstevel@tonic-gate int initialize_pid; 1377c478bd9Sstevel@tonic-gate boolean_t supplied_ok; 1387c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* 1417c478bd9Sstevel@tonic-gate * Grab lock to insure that only one thread enters this 1427c478bd9Sstevel@tonic-gate * function at a time. 1437c478bd9Sstevel@tonic-gate */ 1447c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&globalmutex); 1457c478bd9Sstevel@tonic-gate initialize_pid = getpid(); 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate if (kernel_initialized) { 1487c478bd9Sstevel@tonic-gate if (initialize_pid == kernel_pid) { 1497c478bd9Sstevel@tonic-gate /* 1507c478bd9Sstevel@tonic-gate * This process has called C_Initialize already 1517c478bd9Sstevel@tonic-gate */ 1527c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex); 1537c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_ALREADY_INITIALIZED); 1547c478bd9Sstevel@tonic-gate } else { 1557c478bd9Sstevel@tonic-gate /* 1567c478bd9Sstevel@tonic-gate * A fork has happened and the child is 1577c478bd9Sstevel@tonic-gate * reinitializing. Do a cleanup_library to close 1587c478bd9Sstevel@tonic-gate * out any state from the parent, and then 1597c478bd9Sstevel@tonic-gate * continue on. 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate cleanup_library(); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate if (pInitArgs != NULL) { 1667c478bd9Sstevel@tonic-gate CK_C_INITIALIZE_ARGS *initargs1 = 1677c478bd9Sstevel@tonic-gate (CK_C_INITIALIZE_ARGS *) pInitArgs; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* pReserved must be NULL */ 1707c478bd9Sstevel@tonic-gate if (initargs1->pReserved != NULL) { 1717c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex); 1727c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * ALL supplied function pointers need to have the value 1777c478bd9Sstevel@tonic-gate * either NULL or non-NULL. 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate supplied_ok = (initargs1->CreateMutex == NULL && 1807c478bd9Sstevel@tonic-gate initargs1->DestroyMutex == NULL && 1817c478bd9Sstevel@tonic-gate initargs1->LockMutex == NULL && 1827c478bd9Sstevel@tonic-gate initargs1->UnlockMutex == NULL) || 1837c478bd9Sstevel@tonic-gate (initargs1->CreateMutex != NULL && 1847c478bd9Sstevel@tonic-gate initargs1->DestroyMutex != NULL && 1857c478bd9Sstevel@tonic-gate initargs1->LockMutex != NULL && 1867c478bd9Sstevel@tonic-gate initargs1->UnlockMutex != NULL); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (!supplied_ok) { 1897c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex); 1907c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate /* 1947c478bd9Sstevel@tonic-gate * When the CKF_OS_LOCKING_OK flag isn't set and mutex 1957c478bd9Sstevel@tonic-gate * function pointers are supplied by an application, 1967c478bd9Sstevel@tonic-gate * return an error. We must be able to use our own locks. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate if (!(initargs1->flags & CKF_OS_LOCKING_OK) && 1997c478bd9Sstevel@tonic-gate (initargs1->CreateMutex != NULL)) { 2007c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex); 2017c478bd9Sstevel@tonic-gate return (CKR_CANT_LOCK); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate while ((kernel_fd = open(CRYPTO_DEVICE, O_RDWR)) < 0) { 2067c478bd9Sstevel@tonic-gate if (errno != EINTR) 2077c478bd9Sstevel@tonic-gate break; 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate if (kernel_fd < 0) { 2107c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex); 2117c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* Mark kernel_fd "close on exec" */ 2157c478bd9Sstevel@tonic-gate (void) fcntl(kernel_fd, F_SETFD, FD_CLOEXEC); 2167c478bd9Sstevel@tonic-gate 2176f3f1c68Skrishna /* Create the hash table */ 2186f3f1c68Skrishna kernel_mechhash = calloc(KMECH_HASHTABLE_SIZE, sizeof (void *)); 2196f3f1c68Skrishna if (kernel_mechhash == NULL) { 2206f3f1c68Skrishna (void) close(kernel_fd); 2216f3f1c68Skrishna (void) pthread_mutex_unlock(&globalmutex); 2226f3f1c68Skrishna return (CKR_HOST_MEMORY); 2236f3f1c68Skrishna } 2246f3f1c68Skrishna 2257c478bd9Sstevel@tonic-gate /* Initialize the slot table */ 2267c478bd9Sstevel@tonic-gate rv = kernel_slottable_init(); 2277c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2286f3f1c68Skrishna free(kernel_mechhash); 2297c478bd9Sstevel@tonic-gate (void) close(kernel_fd); 2307c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex); 2317c478bd9Sstevel@tonic-gate return (rv); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 23401223cbaSmcpowers /* Initialize the object_to_be_freed list */ 23501223cbaSmcpowers (void) pthread_mutex_init(&obj_delay_freed.obj_to_be_free_mutex, NULL); 23601223cbaSmcpowers obj_delay_freed.count = 0; 23701223cbaSmcpowers obj_delay_freed.first = NULL; 23801223cbaSmcpowers obj_delay_freed.last = NULL; 23901223cbaSmcpowers 24001223cbaSmcpowers /* Initialize the session_to_be_freed list */ 24101223cbaSmcpowers (void) pthread_mutex_init(&ses_delay_freed.ses_to_be_free_mutex, NULL); 24201223cbaSmcpowers ses_delay_freed.count = 0; 24301223cbaSmcpowers ses_delay_freed.first = NULL; 24401223cbaSmcpowers ses_delay_freed.last = NULL; 24501223cbaSmcpowers 2467c478bd9Sstevel@tonic-gate kernel_initialized = B_TRUE; 2477c478bd9Sstevel@tonic-gate kernel_pid = initialize_pid; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex); 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate return (CKR_OK); 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * C_Finalize is a wrapper around finalize_common. The 2587c478bd9Sstevel@tonic-gate * globalmutex should be locked by C_Finalize(). 2597c478bd9Sstevel@tonic-gate */ 2607c478bd9Sstevel@tonic-gate CK_RV 2617c478bd9Sstevel@tonic-gate C_Finalize(CK_VOID_PTR pReserved) 2627c478bd9Sstevel@tonic-gate { 26301223cbaSmcpowers int i; 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&globalmutex); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate if (!kernel_initialized) { 26870456467Sdinak (void) pthread_mutex_unlock(&globalmutex); 2697c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* Check to see if pReseved is NULL */ 2737c478bd9Sstevel@tonic-gate if (pReserved != NULL) { 27470456467Sdinak (void) pthread_mutex_unlock(&globalmutex); 2757c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate /* 2797c478bd9Sstevel@tonic-gate * Delete all the sessions for each slot and release the allocated 2807c478bd9Sstevel@tonic-gate * resources 2817c478bd9Sstevel@tonic-gate */ 2827c478bd9Sstevel@tonic-gate for (i = 0; i < slot_count; i++) { 28301223cbaSmcpowers kernel_delete_all_sessions(i, B_FALSE); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 28601223cbaSmcpowers finalize_common(); 28701223cbaSmcpowers 28801223cbaSmcpowers (void) pthread_mutex_unlock(&globalmutex); 28901223cbaSmcpowers 29001223cbaSmcpowers return (CKR_OK); 29101223cbaSmcpowers } 29201223cbaSmcpowers 29301223cbaSmcpowers /* 29401223cbaSmcpowers * finalize_common() does the work for C_Finalize. globalmutex 29501223cbaSmcpowers * must be held before calling this function. 29601223cbaSmcpowers */ 29701223cbaSmcpowers static void 29801223cbaSmcpowers finalize_common() { 29901223cbaSmcpowers 30001223cbaSmcpowers int i; 3016f3f1c68Skrishna kmh_elem_t *elem, *next; 30201223cbaSmcpowers kernel_object_t *delay_free_obj, *tmpo; 30301223cbaSmcpowers kernel_session_t *delay_free_ses, *tmps; 30401223cbaSmcpowers 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * Free the resources allocated for the slot table and reset 3077c478bd9Sstevel@tonic-gate * slot_count to 0. 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate if (slot_count > 0) { 3107c478bd9Sstevel@tonic-gate for (i = 0; i < slot_count; i++) { 3117c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&slot_table[i]->sl_mutex); 3127c478bd9Sstevel@tonic-gate (void) free(slot_table[i]); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate (void) free(slot_table); 3157c478bd9Sstevel@tonic-gate slot_count = 0; 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate /* Close CRYPTO_DEVICE */ 3197c478bd9Sstevel@tonic-gate if (kernel_fd >= 0) { 3207c478bd9Sstevel@tonic-gate (void) close(kernel_fd); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3236f3f1c68Skrishna /* Walk the hash table and free all entries */ 3246f3f1c68Skrishna for (i = 0; i < KMECH_HASHTABLE_SIZE; i++) { 3256f3f1c68Skrishna elem = kernel_mechhash[i]; 3266f3f1c68Skrishna while (elem != NULL) { 3276f3f1c68Skrishna next = elem->knext; 3286f3f1c68Skrishna free(elem); 3296f3f1c68Skrishna elem = next; 3306f3f1c68Skrishna } 3316f3f1c68Skrishna } 3326f3f1c68Skrishna 3336f3f1c68Skrishna free(kernel_mechhash); 3346f3f1c68Skrishna 3357c478bd9Sstevel@tonic-gate kernel_fd = -1; 3367c478bd9Sstevel@tonic-gate kernel_initialized = B_FALSE; 3377c478bd9Sstevel@tonic-gate kernel_pid = 0; 3387c478bd9Sstevel@tonic-gate 33901223cbaSmcpowers /* 34001223cbaSmcpowers * free all entries in the delay_freed list 34101223cbaSmcpowers */ 34201223cbaSmcpowers delay_free_obj = obj_delay_freed.first; 34301223cbaSmcpowers while (delay_free_obj != NULL) { 34401223cbaSmcpowers tmpo = delay_free_obj->next; 34501223cbaSmcpowers free(delay_free_obj); 34601223cbaSmcpowers delay_free_obj = tmpo; 34701223cbaSmcpowers } 34801223cbaSmcpowers (void) pthread_mutex_destroy(&obj_delay_freed.obj_to_be_free_mutex); 34901223cbaSmcpowers 35001223cbaSmcpowers delay_free_ses = ses_delay_freed.first; 35101223cbaSmcpowers while (delay_free_ses != NULL) { 35201223cbaSmcpowers tmps = delay_free_ses->next; 35301223cbaSmcpowers free(delay_free_ses); 35401223cbaSmcpowers delay_free_ses = tmps; 35501223cbaSmcpowers } 35601223cbaSmcpowers (void) pthread_mutex_destroy(&ses_delay_freed.ses_to_be_free_mutex); 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate /* 3607c478bd9Sstevel@tonic-gate * This function cleans up all the resources in the library (user space only) 3617c478bd9Sstevel@tonic-gate */ 3627c478bd9Sstevel@tonic-gate static void 3637c478bd9Sstevel@tonic-gate cleanup_library() 3647c478bd9Sstevel@tonic-gate { 3657c478bd9Sstevel@tonic-gate int i; 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * Delete all the sessions for each slot and release the allocated 3697c478bd9Sstevel@tonic-gate * resources from the library. The boolean argument TRUE indicates 3707c478bd9Sstevel@tonic-gate * that we only wants to clean up the resource in the library only. 3717c478bd9Sstevel@tonic-gate * We don't want to clean up the corresponding kernel part of 3727c478bd9Sstevel@tonic-gate * resources, because they are used by the parent process still. 3737c478bd9Sstevel@tonic-gate */ 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate for (i = 0; i < slot_count; i++) { 37601223cbaSmcpowers kernel_delete_all_sessions(i, B_TRUE); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 37901223cbaSmcpowers finalize_common(); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 382*83140133SZdenek Kotala static void 383*83140133SZdenek Kotala kernel_init() 384*83140133SZdenek Kotala { 385*83140133SZdenek Kotala (void) pthread_atfork(kernel_fork_prepare, kernel_fork_after, 386*83140133SZdenek Kotala kernel_fork_after); 387*83140133SZdenek Kotala } 388*83140133SZdenek Kotala 3897c478bd9Sstevel@tonic-gate /* 3907c478bd9Sstevel@tonic-gate * kernel_fini() function required to make sure complete cleanup 3917c478bd9Sstevel@tonic-gate * is done if pkcs11_kernel is ever unloaded without 3927c478bd9Sstevel@tonic-gate * a C_Finalize() call. 3937c478bd9Sstevel@tonic-gate */ 3947c478bd9Sstevel@tonic-gate static void 3957c478bd9Sstevel@tonic-gate kernel_fini() 3967c478bd9Sstevel@tonic-gate { 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&globalmutex); 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate /* if we're not initilized, do not attempt to finalize */ 4017c478bd9Sstevel@tonic-gate if (!kernel_initialized) { 4027c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex); 4037c478bd9Sstevel@tonic-gate return; 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate cleanup_library(); 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&globalmutex); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate CK_RV 4127c478bd9Sstevel@tonic-gate C_GetInfo(CK_INFO_PTR pInfo) 4137c478bd9Sstevel@tonic-gate { 4147c478bd9Sstevel@tonic-gate if (!kernel_initialized) 4157c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate if (pInfo == NULL) { 4187c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* Check if the cryptoki was initialized */ 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR; 4247c478bd9Sstevel@tonic-gate pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR; 4257c478bd9Sstevel@tonic-gate (void) strncpy((char *)pInfo->manufacturerID, 4267c478bd9Sstevel@tonic-gate MANUFACTURER_ID, 32); 4277c478bd9Sstevel@tonic-gate pInfo->flags = 0; 4287c478bd9Sstevel@tonic-gate (void) strncpy((char *)pInfo->libraryDescription, 4297c478bd9Sstevel@tonic-gate LIBRARY_DESCRIPTION, 32); 4307c478bd9Sstevel@tonic-gate pInfo->libraryVersion.major = LIBRARY_VERSION_MAJOR; 4317c478bd9Sstevel@tonic-gate pInfo->libraryVersion.minor = LIBRARY_VERSION_MINOR; 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate return (CKR_OK); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate CK_RV 4377c478bd9Sstevel@tonic-gate C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) 4387c478bd9Sstevel@tonic-gate { 4397c478bd9Sstevel@tonic-gate if (ppFunctionList == NULL) { 4407c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate *ppFunctionList = &functionList; 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate return (CKR_OK); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* 4497c478bd9Sstevel@tonic-gate * PKCS#11 states that C_GetFunctionStatus should always return 4507c478bd9Sstevel@tonic-gate * CKR_FUNCTION_NOT_PARALLEL 4517c478bd9Sstevel@tonic-gate */ 4527c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4537c478bd9Sstevel@tonic-gate CK_RV 4547c478bd9Sstevel@tonic-gate C_GetFunctionStatus(CK_SESSION_HANDLE hSession) 4557c478bd9Sstevel@tonic-gate { 4567c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_NOT_PARALLEL); 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate /* 4604daf2311Srupertk * Take out all mutexes before fork. 4614daf2311Srupertk * Order: 4624daf2311Srupertk * 1. globalmutex 4634daf2311Srupertk * 2. all slots mutexes (and all their sessions) via 4644daf2311Srupertk * kernel_acquire_all_slots_mutexes() 4654daf2311Srupertk * 3. obj_delay_freed.obj_to_be_free_mutex; 4664daf2311Srupertk * 4. ses_delay_freed.ses_to_be_free_mutex 4674daf2311Srupertk */ 4684daf2311Srupertk void 4694daf2311Srupertk kernel_fork_prepare() 4704daf2311Srupertk { 4714daf2311Srupertk (void) pthread_mutex_lock(&globalmutex); 472*83140133SZdenek Kotala if (kernel_initialized) { 4734daf2311Srupertk kernel_acquire_all_slots_mutexes(); 4744daf2311Srupertk (void) pthread_mutex_lock( 4754daf2311Srupertk &obj_delay_freed.obj_to_be_free_mutex); 4764daf2311Srupertk (void) pthread_mutex_lock( 4774daf2311Srupertk &ses_delay_freed.ses_to_be_free_mutex); 4781f49a79aSZdenek Kotala (void) pthread_mutex_lock(&mechhash_mutex); 4794daf2311Srupertk } 4804daf2311Srupertk } 4814daf2311Srupertk 482*83140133SZdenek Kotala /* 483*83140133SZdenek Kotala * Release in opposite order to kernel_fork_prepare(). 484*83140133SZdenek Kotala * Function is used for parent and child. 485*83140133SZdenek Kotala */ 4864daf2311Srupertk void 487*83140133SZdenek Kotala kernel_fork_after() 4884daf2311Srupertk { 489*83140133SZdenek Kotala if (kernel_initialized) { 4901f49a79aSZdenek Kotala (void) pthread_mutex_unlock(&mechhash_mutex); 4914daf2311Srupertk (void) pthread_mutex_unlock( 4924daf2311Srupertk &ses_delay_freed.ses_to_be_free_mutex); 4934daf2311Srupertk (void) pthread_mutex_unlock( 4944daf2311Srupertk &obj_delay_freed.obj_to_be_free_mutex); 4954daf2311Srupertk kernel_release_all_slots_mutexes(); 496*83140133SZdenek Kotala } 4974daf2311Srupertk (void) pthread_mutex_unlock(&globalmutex); 4984daf2311Srupertk } 4994daf2311Srupertk 5004daf2311Srupertk /* 5017c478bd9Sstevel@tonic-gate * PKCS#11 states that C_CancelFunction should always return 5027c478bd9Sstevel@tonic-gate * CKR_FUNCTION_NOT_PARALLEL 5037c478bd9Sstevel@tonic-gate */ 5047c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 5057c478bd9Sstevel@tonic-gate CK_RV 5067c478bd9Sstevel@tonic-gate C_CancelFunction(CK_SESSION_HANDLE hSession) 5077c478bd9Sstevel@tonic-gate { 5087c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_NOT_PARALLEL); 5097c478bd9Sstevel@tonic-gate } 510