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
C_Initialize(CK_VOID_PTR pInitArgs)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
C_Finalize(CK_VOID_PTR pReserved)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
finalize_common()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
cleanup_library()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
kernel_init()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
kernel_fini()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
C_GetInfo(CK_INFO_PTR pInfo)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
C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)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
C_GetFunctionStatus(CK_SESSION_HANDLE hSession)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
4594daf2311Srupertk /*
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
kernel_fork_prepare()4694daf2311Srupertk kernel_fork_prepare()
4704daf2311Srupertk {
4714daf2311Srupertk (void) pthread_mutex_lock(&globalmutex);
472*83140133SZdenek Kotala if (kernel_initialized) {
473*83140133SZdenek Kotala kernel_acquire_all_slots_mutexes();
474*83140133SZdenek Kotala (void) pthread_mutex_lock(
475*83140133SZdenek Kotala &obj_delay_freed.obj_to_be_free_mutex);
476*83140133SZdenek Kotala (void) pthread_mutex_lock(
477*83140133SZdenek Kotala &ses_delay_freed.ses_to_be_free_mutex);
478*83140133SZdenek Kotala (void) pthread_mutex_lock(&mechhash_mutex);
479*83140133SZdenek Kotala }
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
kernel_fork_after()487*83140133SZdenek Kotala kernel_fork_after()
4884daf2311Srupertk {
489*83140133SZdenek Kotala if (kernel_initialized) {
490*83140133SZdenek Kotala (void) pthread_mutex_unlock(&mechhash_mutex);
491*83140133SZdenek Kotala (void) pthread_mutex_unlock(
492*83140133SZdenek Kotala &ses_delay_freed.ses_to_be_free_mutex);
493*83140133SZdenek Kotala (void) pthread_mutex_unlock(
494*83140133SZdenek Kotala &obj_delay_freed.obj_to_be_free_mutex);
495*83140133SZdenek Kotala kernel_release_all_slots_mutexes();
496*83140133SZdenek Kotala }
4974daf2311Srupertk (void) pthread_mutex_unlock(&globalmutex);
4984daf2311Srupertk }
4994daf2311Srupertk
5007c478bd9Sstevel@tonic-gate /*
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
C_CancelFunction(CK_SESSION_HANDLE hSession)5067c478bd9Sstevel@tonic-gate C_CancelFunction(CK_SESSION_HANDLE hSession)
5077c478bd9Sstevel@tonic-gate {
5087c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_NOT_PARALLEL);
5097c478bd9Sstevel@tonic-gate }
510