xref: /onnv-gate/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGeneral.c (revision 10403:560db669cfa6)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52935Skrishna  * Common Development and Distribution License (the "License").
62935Skrishna  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
229661SZdenek.Kotala@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <fcntl.h>
270Sstevel@tonic-gate #include <pthread.h>
280Sstevel@tonic-gate #include <strings.h>
290Sstevel@tonic-gate #include <unistd.h> /* for pid */
300Sstevel@tonic-gate #include <errno.h>
310Sstevel@tonic-gate #include <security/cryptoki.h>
320Sstevel@tonic-gate #include "kernelGlobal.h"
330Sstevel@tonic-gate #include "kernelSession.h"
340Sstevel@tonic-gate #include "kernelSlot.h"
350Sstevel@tonic-gate 
36*10403SZdenek.Kotala@Sun.COM #pragma init(kernel_init)
370Sstevel@tonic-gate #pragma fini(kernel_fini)
380Sstevel@tonic-gate 
390Sstevel@tonic-gate static struct CK_FUNCTION_LIST functionList = {
40676Sizick 	{ 2, 20 },	/* version */
410Sstevel@tonic-gate 	C_Initialize,
420Sstevel@tonic-gate 	C_Finalize,
430Sstevel@tonic-gate 	C_GetInfo,
440Sstevel@tonic-gate 	C_GetFunctionList,
450Sstevel@tonic-gate 	C_GetSlotList,
460Sstevel@tonic-gate 	C_GetSlotInfo,
470Sstevel@tonic-gate 	C_GetTokenInfo,
480Sstevel@tonic-gate 	C_GetMechanismList,
490Sstevel@tonic-gate 	C_GetMechanismInfo,
500Sstevel@tonic-gate 	C_InitToken,
510Sstevel@tonic-gate 	C_InitPIN,
520Sstevel@tonic-gate 	C_SetPIN,
530Sstevel@tonic-gate 	C_OpenSession,
540Sstevel@tonic-gate 	C_CloseSession,
550Sstevel@tonic-gate 	C_CloseAllSessions,
560Sstevel@tonic-gate 	C_GetSessionInfo,
570Sstevel@tonic-gate 	C_GetOperationState,
580Sstevel@tonic-gate 	C_SetOperationState,
590Sstevel@tonic-gate 	C_Login,
600Sstevel@tonic-gate 	C_Logout,
610Sstevel@tonic-gate 	C_CreateObject,
620Sstevel@tonic-gate 	C_CopyObject,
630Sstevel@tonic-gate 	C_DestroyObject,
640Sstevel@tonic-gate 	C_GetObjectSize,
650Sstevel@tonic-gate 	C_GetAttributeValue,
660Sstevel@tonic-gate 	C_SetAttributeValue,
670Sstevel@tonic-gate 	C_FindObjectsInit,
680Sstevel@tonic-gate 	C_FindObjects,
690Sstevel@tonic-gate 	C_FindObjectsFinal,
700Sstevel@tonic-gate 	C_EncryptInit,
710Sstevel@tonic-gate 	C_Encrypt,
720Sstevel@tonic-gate 	C_EncryptUpdate,
730Sstevel@tonic-gate 	C_EncryptFinal,
740Sstevel@tonic-gate 	C_DecryptInit,
750Sstevel@tonic-gate 	C_Decrypt,
760Sstevel@tonic-gate 	C_DecryptUpdate,
770Sstevel@tonic-gate 	C_DecryptFinal,
780Sstevel@tonic-gate 	C_DigestInit,
790Sstevel@tonic-gate 	C_Digest,
800Sstevel@tonic-gate 	C_DigestUpdate,
810Sstevel@tonic-gate 	C_DigestKey,
820Sstevel@tonic-gate 	C_DigestFinal,
830Sstevel@tonic-gate 	C_SignInit,
840Sstevel@tonic-gate 	C_Sign,
850Sstevel@tonic-gate 	C_SignUpdate,
860Sstevel@tonic-gate 	C_SignFinal,
870Sstevel@tonic-gate 	C_SignRecoverInit,
880Sstevel@tonic-gate 	C_SignRecover,
890Sstevel@tonic-gate 	C_VerifyInit,
900Sstevel@tonic-gate 	C_Verify,
910Sstevel@tonic-gate 	C_VerifyUpdate,
920Sstevel@tonic-gate 	C_VerifyFinal,
930Sstevel@tonic-gate 	C_VerifyRecoverInit,
940Sstevel@tonic-gate 	C_VerifyRecover,
950Sstevel@tonic-gate 	C_DigestEncryptUpdate,
960Sstevel@tonic-gate 	C_DecryptDigestUpdate,
970Sstevel@tonic-gate 	C_SignEncryptUpdate,
980Sstevel@tonic-gate 	C_DecryptVerifyUpdate,
990Sstevel@tonic-gate 	C_GenerateKey,
1000Sstevel@tonic-gate 	C_GenerateKeyPair,
1010Sstevel@tonic-gate 	C_WrapKey,
1020Sstevel@tonic-gate 	C_UnwrapKey,
1030Sstevel@tonic-gate 	C_DeriveKey,
1040Sstevel@tonic-gate 	C_SeedRandom,
1050Sstevel@tonic-gate 	C_GenerateRandom,
1060Sstevel@tonic-gate 	C_GetFunctionStatus,
1070Sstevel@tonic-gate 	C_CancelFunction,
1080Sstevel@tonic-gate 	C_WaitForSlotEvent
1090Sstevel@tonic-gate };
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate boolean_t kernel_initialized = B_FALSE;
1120Sstevel@tonic-gate static pid_t kernel_pid = 0;
1130Sstevel@tonic-gate 
1149661SZdenek.Kotala@Sun.COM extern pthread_mutex_t mechhash_mutex;
1159661SZdenek.Kotala@Sun.COM 
1160Sstevel@tonic-gate int kernel_fd = -1;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate /* protects kernel_initialized and entrance to C_Initialize/Finalize */
1200Sstevel@tonic-gate static pthread_mutex_t globalmutex = PTHREAD_MUTEX_INITIALIZER;
1210Sstevel@tonic-gate 
122214Smcpowers ses_to_be_freed_list_t ses_delay_freed;
123214Smcpowers object_to_be_freed_list_t obj_delay_freed;
1242935Skrishna kmh_elem_t **kernel_mechhash;	/* Hash table for kCF mech numbers */
125214Smcpowers 
126214Smcpowers static void finalize_common();
1270Sstevel@tonic-gate static void cleanup_library();
128*10403SZdenek.Kotala@Sun.COM static void kernel_init();
1290Sstevel@tonic-gate static void kernel_fini();
1306824Srupertk static void kernel_fork_prepare();
131*10403SZdenek.Kotala@Sun.COM static void kernel_fork_after();
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate CK_RV
C_Initialize(CK_VOID_PTR pInitArgs)1340Sstevel@tonic-gate C_Initialize(CK_VOID_PTR pInitArgs)
1350Sstevel@tonic-gate {
1360Sstevel@tonic-gate 	int initialize_pid;
1370Sstevel@tonic-gate 	boolean_t supplied_ok;
1380Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	/*
1410Sstevel@tonic-gate 	 * Grab lock to insure that only one thread enters this
1420Sstevel@tonic-gate 	 * function at a time.
1430Sstevel@tonic-gate 	 */
1440Sstevel@tonic-gate 	(void) pthread_mutex_lock(&globalmutex);
1450Sstevel@tonic-gate 	initialize_pid = getpid();
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	if (kernel_initialized) {
1480Sstevel@tonic-gate 		if (initialize_pid == kernel_pid) {
1490Sstevel@tonic-gate 			/*
1500Sstevel@tonic-gate 			 * This process has called C_Initialize already
1510Sstevel@tonic-gate 			 */
1520Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&globalmutex);
1530Sstevel@tonic-gate 			return (CKR_CRYPTOKI_ALREADY_INITIALIZED);
1540Sstevel@tonic-gate 		} else {
1550Sstevel@tonic-gate 			/*
1560Sstevel@tonic-gate 			 * A fork has happened and the child is
1570Sstevel@tonic-gate 			 * reinitializing.  Do a cleanup_library to close
1580Sstevel@tonic-gate 			 * out any state from the parent, and then
1590Sstevel@tonic-gate 			 * continue on.
1600Sstevel@tonic-gate 			 */
1610Sstevel@tonic-gate 			cleanup_library();
1620Sstevel@tonic-gate 		}
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	if (pInitArgs != NULL) {
1660Sstevel@tonic-gate 		CK_C_INITIALIZE_ARGS *initargs1 =
1670Sstevel@tonic-gate 		    (CK_C_INITIALIZE_ARGS *) pInitArgs;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 		/* pReserved must be NULL */
1700Sstevel@tonic-gate 		if (initargs1->pReserved != NULL) {
1710Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&globalmutex);
1720Sstevel@tonic-gate 			return (CKR_ARGUMENTS_BAD);
1730Sstevel@tonic-gate 		}
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 		/*
1760Sstevel@tonic-gate 		 * ALL supplied function pointers need to have the value
1770Sstevel@tonic-gate 		 * either NULL or non-NULL.
1780Sstevel@tonic-gate 		 */
1790Sstevel@tonic-gate 		supplied_ok = (initargs1->CreateMutex == NULL &&
1800Sstevel@tonic-gate 		    initargs1->DestroyMutex == NULL &&
1810Sstevel@tonic-gate 		    initargs1->LockMutex == NULL &&
1820Sstevel@tonic-gate 		    initargs1->UnlockMutex == NULL) ||
1830Sstevel@tonic-gate 		    (initargs1->CreateMutex != NULL &&
1840Sstevel@tonic-gate 		    initargs1->DestroyMutex != NULL &&
1850Sstevel@tonic-gate 		    initargs1->LockMutex != NULL &&
1860Sstevel@tonic-gate 		    initargs1->UnlockMutex != NULL);
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 		if (!supplied_ok) {
1890Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&globalmutex);
1900Sstevel@tonic-gate 			return (CKR_ARGUMENTS_BAD);
1910Sstevel@tonic-gate 		}
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 		/*
1940Sstevel@tonic-gate 		 * When the CKF_OS_LOCKING_OK flag isn't set and mutex
1950Sstevel@tonic-gate 		 * function pointers are supplied by an application,
1960Sstevel@tonic-gate 		 * return an error.  We must be able to use our own locks.
1970Sstevel@tonic-gate 		 */
1980Sstevel@tonic-gate 		if (!(initargs1->flags & CKF_OS_LOCKING_OK) &&
1990Sstevel@tonic-gate 		    (initargs1->CreateMutex != NULL)) {
2000Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&globalmutex);
2010Sstevel@tonic-gate 			return (CKR_CANT_LOCK);
2020Sstevel@tonic-gate 		}
2030Sstevel@tonic-gate 	}
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	while ((kernel_fd = open(CRYPTO_DEVICE, O_RDWR)) < 0) {
2060Sstevel@tonic-gate 		if (errno != EINTR)
2070Sstevel@tonic-gate 			break;
2080Sstevel@tonic-gate 	}
2090Sstevel@tonic-gate 	if (kernel_fd < 0) {
2100Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&globalmutex);
2110Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
2120Sstevel@tonic-gate 	}
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	/* Mark kernel_fd "close on exec" */
2150Sstevel@tonic-gate 	(void) fcntl(kernel_fd, F_SETFD, FD_CLOEXEC);
2160Sstevel@tonic-gate 
2172935Skrishna 	/* Create the hash table */
2182935Skrishna 	kernel_mechhash = calloc(KMECH_HASHTABLE_SIZE, sizeof (void *));
2192935Skrishna 	if (kernel_mechhash == NULL) {
2202935Skrishna 		(void) close(kernel_fd);
2212935Skrishna 		(void) pthread_mutex_unlock(&globalmutex);
2222935Skrishna 		return (CKR_HOST_MEMORY);
2232935Skrishna 	}
2242935Skrishna 
2250Sstevel@tonic-gate 	/* Initialize the slot table */
2260Sstevel@tonic-gate 	rv = kernel_slottable_init();
2270Sstevel@tonic-gate 	if (rv != CKR_OK) {
2282935Skrishna 		free(kernel_mechhash);
2290Sstevel@tonic-gate 		(void) close(kernel_fd);
2300Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&globalmutex);
2310Sstevel@tonic-gate 		return (rv);
2320Sstevel@tonic-gate 	}
2330Sstevel@tonic-gate 
234214Smcpowers 	/* Initialize the object_to_be_freed list */
235214Smcpowers 	(void) pthread_mutex_init(&obj_delay_freed.obj_to_be_free_mutex, NULL);
236214Smcpowers 	obj_delay_freed.count = 0;
237214Smcpowers 	obj_delay_freed.first = NULL;
238214Smcpowers 	obj_delay_freed.last = NULL;
239214Smcpowers 
240214Smcpowers 	/* Initialize the session_to_be_freed list */
241214Smcpowers 	(void) pthread_mutex_init(&ses_delay_freed.ses_to_be_free_mutex, NULL);
242214Smcpowers 	ses_delay_freed.count = 0;
243214Smcpowers 	ses_delay_freed.first = NULL;
244214Smcpowers 	ses_delay_freed.last = NULL;
245214Smcpowers 
2460Sstevel@tonic-gate 	kernel_initialized = B_TRUE;
2470Sstevel@tonic-gate 	kernel_pid = initialize_pid;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&globalmutex);
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	return (CKR_OK);
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate }
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate /*
2570Sstevel@tonic-gate  * C_Finalize is a wrapper around finalize_common. The
2580Sstevel@tonic-gate  * globalmutex should be locked by C_Finalize().
2590Sstevel@tonic-gate  */
2600Sstevel@tonic-gate CK_RV
C_Finalize(CK_VOID_PTR pReserved)2610Sstevel@tonic-gate C_Finalize(CK_VOID_PTR pReserved)
2620Sstevel@tonic-gate {
263214Smcpowers 	int i;
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	(void) pthread_mutex_lock(&globalmutex);
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	if (!kernel_initialized) {
2681033Sdinak 		(void) pthread_mutex_unlock(&globalmutex);
2690Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
2700Sstevel@tonic-gate 	}
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	/* Check to see if pReseved is NULL */
2730Sstevel@tonic-gate 	if (pReserved != NULL) {
2741033Sdinak 		(void) pthread_mutex_unlock(&globalmutex);
2750Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
2760Sstevel@tonic-gate 	}
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	/*
2790Sstevel@tonic-gate 	 * Delete all the sessions for each slot and release the allocated
2800Sstevel@tonic-gate 	 * resources
2810Sstevel@tonic-gate 	 */
2820Sstevel@tonic-gate 	for (i = 0; i < slot_count; i++) {
283214Smcpowers 		kernel_delete_all_sessions(i, B_FALSE);
2840Sstevel@tonic-gate 	}
2850Sstevel@tonic-gate 
286214Smcpowers 	finalize_common();
287214Smcpowers 
288214Smcpowers 	(void) pthread_mutex_unlock(&globalmutex);
289214Smcpowers 
290214Smcpowers 	return (CKR_OK);
291214Smcpowers }
292214Smcpowers 
293214Smcpowers /*
294214Smcpowers  * finalize_common() does the work for C_Finalize.  globalmutex
295214Smcpowers  * must be held before calling this function.
296214Smcpowers  */
297214Smcpowers static void
finalize_common()298214Smcpowers finalize_common() {
299214Smcpowers 
300214Smcpowers 	int i;
3012935Skrishna 	kmh_elem_t *elem, *next;
302214Smcpowers 	kernel_object_t *delay_free_obj, *tmpo;
303214Smcpowers 	kernel_session_t *delay_free_ses, *tmps;
304214Smcpowers 
3050Sstevel@tonic-gate 	/*
3060Sstevel@tonic-gate 	 * Free the resources allocated for the slot table and reset
3070Sstevel@tonic-gate 	 * slot_count to 0.
3080Sstevel@tonic-gate 	 */
3090Sstevel@tonic-gate 	if (slot_count > 0) {
3100Sstevel@tonic-gate 		for (i = 0; i < slot_count; i++) {
3110Sstevel@tonic-gate 			(void) pthread_mutex_destroy(&slot_table[i]->sl_mutex);
3120Sstevel@tonic-gate 			(void) free(slot_table[i]);
3130Sstevel@tonic-gate 		}
3140Sstevel@tonic-gate 		(void) free(slot_table);
3150Sstevel@tonic-gate 		slot_count = 0;
3160Sstevel@tonic-gate 	}
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	/* Close CRYPTO_DEVICE */
3190Sstevel@tonic-gate 	if (kernel_fd >= 0) {
3200Sstevel@tonic-gate 		(void) close(kernel_fd);
3210Sstevel@tonic-gate 	}
3220Sstevel@tonic-gate 
3232935Skrishna 	/* Walk the hash table and free all entries */
3242935Skrishna 	for (i = 0; i < KMECH_HASHTABLE_SIZE; i++) {
3252935Skrishna 		elem = kernel_mechhash[i];
3262935Skrishna 		while (elem != NULL) {
3272935Skrishna 			next = elem->knext;
3282935Skrishna 			free(elem);
3292935Skrishna 			elem = next;
3302935Skrishna 		}
3312935Skrishna 	}
3322935Skrishna 
3332935Skrishna 	free(kernel_mechhash);
3342935Skrishna 
3350Sstevel@tonic-gate 	kernel_fd = -1;
3360Sstevel@tonic-gate 	kernel_initialized = B_FALSE;
3370Sstevel@tonic-gate 	kernel_pid = 0;
3380Sstevel@tonic-gate 
339214Smcpowers 	/*
340214Smcpowers 	 * free all entries in the delay_freed list
341214Smcpowers 	 */
342214Smcpowers 	delay_free_obj = obj_delay_freed.first;
343214Smcpowers 	while (delay_free_obj != NULL) {
344214Smcpowers 		tmpo = delay_free_obj->next;
345214Smcpowers 		free(delay_free_obj);
346214Smcpowers 		delay_free_obj = tmpo;
347214Smcpowers 	}
348214Smcpowers 	(void) pthread_mutex_destroy(&obj_delay_freed.obj_to_be_free_mutex);
349214Smcpowers 
350214Smcpowers 	delay_free_ses = ses_delay_freed.first;
351214Smcpowers 	while (delay_free_ses != NULL) {
352214Smcpowers 		tmps = delay_free_ses->next;
353214Smcpowers 		free(delay_free_ses);
354214Smcpowers 		delay_free_ses = tmps;
355214Smcpowers 	}
356214Smcpowers 	(void) pthread_mutex_destroy(&ses_delay_freed.ses_to_be_free_mutex);
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate /*
3600Sstevel@tonic-gate  * This function cleans up all the resources in the library (user space only)
3610Sstevel@tonic-gate  */
3620Sstevel@tonic-gate static void
cleanup_library()3630Sstevel@tonic-gate cleanup_library()
3640Sstevel@tonic-gate {
3650Sstevel@tonic-gate 	int i;
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	/*
3680Sstevel@tonic-gate 	 * Delete all the sessions for each slot and release the allocated
3690Sstevel@tonic-gate 	 * resources from the library.  The boolean argument TRUE indicates
3700Sstevel@tonic-gate 	 * that we only wants to clean up the resource in the library only.
3710Sstevel@tonic-gate 	 * We don't want to clean up the corresponding kernel part of
3720Sstevel@tonic-gate 	 * resources, because they are used by the parent process still.
3730Sstevel@tonic-gate 	 */
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	for (i = 0; i < slot_count; i++) {
376214Smcpowers 		kernel_delete_all_sessions(i, B_TRUE);
3770Sstevel@tonic-gate 	}
3780Sstevel@tonic-gate 
379214Smcpowers 	finalize_common();
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate 
382*10403SZdenek.Kotala@Sun.COM static void
kernel_init()383*10403SZdenek.Kotala@Sun.COM kernel_init()
384*10403SZdenek.Kotala@Sun.COM {
385*10403SZdenek.Kotala@Sun.COM 	(void) pthread_atfork(kernel_fork_prepare, kernel_fork_after,
386*10403SZdenek.Kotala@Sun.COM 	    kernel_fork_after);
387*10403SZdenek.Kotala@Sun.COM }
388*10403SZdenek.Kotala@Sun.COM 
3890Sstevel@tonic-gate /*
3900Sstevel@tonic-gate  * kernel_fini() function required to make sure complete cleanup
3910Sstevel@tonic-gate  * is done if pkcs11_kernel is ever unloaded without
3920Sstevel@tonic-gate  * a C_Finalize() call.
3930Sstevel@tonic-gate  */
3940Sstevel@tonic-gate static void
kernel_fini()3950Sstevel@tonic-gate kernel_fini()
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 	(void) pthread_mutex_lock(&globalmutex);
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	/* if we're not initilized, do not attempt to finalize */
4010Sstevel@tonic-gate 	if (!kernel_initialized) {
4020Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&globalmutex);
4030Sstevel@tonic-gate 		return;
4040Sstevel@tonic-gate 	}
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	cleanup_library();
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&globalmutex);
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate CK_RV
C_GetInfo(CK_INFO_PTR pInfo)4120Sstevel@tonic-gate C_GetInfo(CK_INFO_PTR pInfo)
4130Sstevel@tonic-gate {
4140Sstevel@tonic-gate 	if (!kernel_initialized)
4150Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	if (pInfo == NULL) {
4180Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
4190Sstevel@tonic-gate 	}
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	/* Check if the cryptoki was initialized */
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
4240Sstevel@tonic-gate 	pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
4250Sstevel@tonic-gate 	(void) strncpy((char *)pInfo->manufacturerID,
4260Sstevel@tonic-gate 	    MANUFACTURER_ID, 32);
4270Sstevel@tonic-gate 	pInfo->flags = 0;
4280Sstevel@tonic-gate 	(void) strncpy((char *)pInfo->libraryDescription,
4290Sstevel@tonic-gate 	    LIBRARY_DESCRIPTION, 32);
4300Sstevel@tonic-gate 	pInfo->libraryVersion.major = LIBRARY_VERSION_MAJOR;
4310Sstevel@tonic-gate 	pInfo->libraryVersion.minor = LIBRARY_VERSION_MINOR;
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	return (CKR_OK);
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate CK_RV
C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)4370Sstevel@tonic-gate C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
4380Sstevel@tonic-gate {
4390Sstevel@tonic-gate 	if (ppFunctionList == NULL) {
4400Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
4410Sstevel@tonic-gate 	}
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	*ppFunctionList = &functionList;
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	return (CKR_OK);
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate /*
4490Sstevel@tonic-gate  * PKCS#11 states that C_GetFunctionStatus should always return
4500Sstevel@tonic-gate  * CKR_FUNCTION_NOT_PARALLEL
4510Sstevel@tonic-gate  */
4520Sstevel@tonic-gate /*ARGSUSED*/
4530Sstevel@tonic-gate CK_RV
C_GetFunctionStatus(CK_SESSION_HANDLE hSession)4540Sstevel@tonic-gate C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
4550Sstevel@tonic-gate {
4560Sstevel@tonic-gate 	return (CKR_FUNCTION_NOT_PARALLEL);
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate /*
4606824Srupertk  * Take out all mutexes before fork.
4616824Srupertk  * Order:
4626824Srupertk  * 1. globalmutex
4636824Srupertk  * 2. all slots mutexes (and all their sessions) via
4646824Srupertk  *    kernel_acquire_all_slots_mutexes()
4656824Srupertk  * 3. obj_delay_freed.obj_to_be_free_mutex;
4666824Srupertk  * 4. ses_delay_freed.ses_to_be_free_mutex
4676824Srupertk  */
4686824Srupertk void
kernel_fork_prepare()4696824Srupertk kernel_fork_prepare()
4706824Srupertk {
4716824Srupertk 	(void) pthread_mutex_lock(&globalmutex);
472*10403SZdenek.Kotala@Sun.COM 	if (kernel_initialized) {
473*10403SZdenek.Kotala@Sun.COM 		kernel_acquire_all_slots_mutexes();
474*10403SZdenek.Kotala@Sun.COM 		(void) pthread_mutex_lock(
475*10403SZdenek.Kotala@Sun.COM 		    &obj_delay_freed.obj_to_be_free_mutex);
476*10403SZdenek.Kotala@Sun.COM 		(void) pthread_mutex_lock(
477*10403SZdenek.Kotala@Sun.COM 		    &ses_delay_freed.ses_to_be_free_mutex);
478*10403SZdenek.Kotala@Sun.COM 		(void) pthread_mutex_lock(&mechhash_mutex);
479*10403SZdenek.Kotala@Sun.COM 	}
4806824Srupertk }
4816824Srupertk 
482*10403SZdenek.Kotala@Sun.COM /*
483*10403SZdenek.Kotala@Sun.COM  * Release in opposite order to kernel_fork_prepare().
484*10403SZdenek.Kotala@Sun.COM  * Function is used for parent and child.
485*10403SZdenek.Kotala@Sun.COM  */
4866824Srupertk void
kernel_fork_after()487*10403SZdenek.Kotala@Sun.COM kernel_fork_after()
4886824Srupertk {
489*10403SZdenek.Kotala@Sun.COM 	if (kernel_initialized) {
490*10403SZdenek.Kotala@Sun.COM 		(void) pthread_mutex_unlock(&mechhash_mutex);
491*10403SZdenek.Kotala@Sun.COM 		(void) pthread_mutex_unlock(
492*10403SZdenek.Kotala@Sun.COM 		    &ses_delay_freed.ses_to_be_free_mutex);
493*10403SZdenek.Kotala@Sun.COM 		(void) pthread_mutex_unlock(
494*10403SZdenek.Kotala@Sun.COM 		    &obj_delay_freed.obj_to_be_free_mutex);
495*10403SZdenek.Kotala@Sun.COM 		kernel_release_all_slots_mutexes();
496*10403SZdenek.Kotala@Sun.COM 	}
4976824Srupertk 	(void) pthread_mutex_unlock(&globalmutex);
4986824Srupertk }
4996824Srupertk 
5006824Srupertk /*
5010Sstevel@tonic-gate  * PKCS#11 states that C_CancelFunction should always return
5020Sstevel@tonic-gate  * CKR_FUNCTION_NOT_PARALLEL
5030Sstevel@tonic-gate  */
5040Sstevel@tonic-gate /*ARGSUSED*/
5050Sstevel@tonic-gate CK_RV
C_CancelFunction(CK_SESSION_HANDLE hSession)5060Sstevel@tonic-gate C_CancelFunction(CK_SESSION_HANDLE hSession)
5070Sstevel@tonic-gate {
5080Sstevel@tonic-gate 	return (CKR_FUNCTION_NOT_PARALLEL);
5090Sstevel@tonic-gate }
510