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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <fcntl.h>
307c478bd9Sstevel@tonic-gate #include <pthread.h>
317c478bd9Sstevel@tonic-gate #include <strings.h>
327c478bd9Sstevel@tonic-gate #include <unistd.h> /* for pid */
337c478bd9Sstevel@tonic-gate #include <errno.h>
347c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
357c478bd9Sstevel@tonic-gate #include "kernelGlobal.h"
367c478bd9Sstevel@tonic-gate #include "kernelSession.h"
377c478bd9Sstevel@tonic-gate #include "kernelSlot.h"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #pragma fini(kernel_fini)
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate static struct CK_FUNCTION_LIST functionList = {
427c478bd9Sstevel@tonic-gate 	{ 2, 11 },	/* 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 kernel_initialized = B_FALSE;
1147c478bd9Sstevel@tonic-gate static pid_t kernel_pid = 0;
1157c478bd9Sstevel@tonic-gate 
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 
122*01223cbaSmcpowers ses_to_be_freed_list_t ses_delay_freed;
123*01223cbaSmcpowers object_to_be_freed_list_t obj_delay_freed;
124*01223cbaSmcpowers 
125*01223cbaSmcpowers static void finalize_common();
1267c478bd9Sstevel@tonic-gate static void cleanup_library();
1277c478bd9Sstevel@tonic-gate static void kernel_fini();
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate CK_RV
1307c478bd9Sstevel@tonic-gate C_Initialize(CK_VOID_PTR pInitArgs)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	int initialize_pid;
1347c478bd9Sstevel@tonic-gate 	boolean_t supplied_ok;
1357c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/*
1387c478bd9Sstevel@tonic-gate 	 * Grab lock to insure that only one thread enters this
1397c478bd9Sstevel@tonic-gate 	 * function at a time.
1407c478bd9Sstevel@tonic-gate 	 */
1417c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&globalmutex);
1427c478bd9Sstevel@tonic-gate 	initialize_pid = getpid();
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if (kernel_initialized) {
1457c478bd9Sstevel@tonic-gate 		if (initialize_pid == kernel_pid) {
1467c478bd9Sstevel@tonic-gate 			/*
1477c478bd9Sstevel@tonic-gate 			 * This process has called C_Initialize already
1487c478bd9Sstevel@tonic-gate 			 */
1497c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&globalmutex);
1507c478bd9Sstevel@tonic-gate 			return (CKR_CRYPTOKI_ALREADY_INITIALIZED);
1517c478bd9Sstevel@tonic-gate 		} else {
1527c478bd9Sstevel@tonic-gate 			/*
1537c478bd9Sstevel@tonic-gate 			 * A fork has happened and the child is
1547c478bd9Sstevel@tonic-gate 			 * reinitializing.  Do a cleanup_library to close
1557c478bd9Sstevel@tonic-gate 			 * out any state from the parent, and then
1567c478bd9Sstevel@tonic-gate 			 * continue on.
1577c478bd9Sstevel@tonic-gate 			 */
1587c478bd9Sstevel@tonic-gate 			cleanup_library();
1597c478bd9Sstevel@tonic-gate 		}
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	if (pInitArgs != NULL) {
1637c478bd9Sstevel@tonic-gate 		CK_C_INITIALIZE_ARGS *initargs1 =
1647c478bd9Sstevel@tonic-gate 		    (CK_C_INITIALIZE_ARGS *) pInitArgs;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 		/* pReserved must be NULL */
1677c478bd9Sstevel@tonic-gate 		if (initargs1->pReserved != NULL) {
1687c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&globalmutex);
1697c478bd9Sstevel@tonic-gate 			return (CKR_ARGUMENTS_BAD);
1707c478bd9Sstevel@tonic-gate 		}
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 		/*
1737c478bd9Sstevel@tonic-gate 		 * ALL supplied function pointers need to have the value
1747c478bd9Sstevel@tonic-gate 		 * either NULL or non-NULL.
1757c478bd9Sstevel@tonic-gate 		 */
1767c478bd9Sstevel@tonic-gate 		supplied_ok = (initargs1->CreateMutex == NULL &&
1777c478bd9Sstevel@tonic-gate 		    initargs1->DestroyMutex == NULL &&
1787c478bd9Sstevel@tonic-gate 		    initargs1->LockMutex == NULL &&
1797c478bd9Sstevel@tonic-gate 		    initargs1->UnlockMutex == NULL) ||
1807c478bd9Sstevel@tonic-gate 		    (initargs1->CreateMutex != NULL &&
1817c478bd9Sstevel@tonic-gate 		    initargs1->DestroyMutex != NULL &&
1827c478bd9Sstevel@tonic-gate 		    initargs1->LockMutex != NULL &&
1837c478bd9Sstevel@tonic-gate 		    initargs1->UnlockMutex != NULL);
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 		if (!supplied_ok) {
1867c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&globalmutex);
1877c478bd9Sstevel@tonic-gate 			return (CKR_ARGUMENTS_BAD);
1887c478bd9Sstevel@tonic-gate 		}
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 		/*
1917c478bd9Sstevel@tonic-gate 		 * When the CKF_OS_LOCKING_OK flag isn't set and mutex
1927c478bd9Sstevel@tonic-gate 		 * function pointers are supplied by an application,
1937c478bd9Sstevel@tonic-gate 		 * return an error.  We must be able to use our own locks.
1947c478bd9Sstevel@tonic-gate 		 */
1957c478bd9Sstevel@tonic-gate 		if (!(initargs1->flags & CKF_OS_LOCKING_OK) &&
1967c478bd9Sstevel@tonic-gate 		    (initargs1->CreateMutex != NULL)) {
1977c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&globalmutex);
1987c478bd9Sstevel@tonic-gate 			return (CKR_CANT_LOCK);
1997c478bd9Sstevel@tonic-gate 		}
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	while ((kernel_fd = open(CRYPTO_DEVICE, O_RDWR)) < 0) {
2037c478bd9Sstevel@tonic-gate 		if (errno != EINTR)
2047c478bd9Sstevel@tonic-gate 			break;
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 	if (kernel_fd < 0) {
2077c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&globalmutex);
2087c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	/* Mark kernel_fd "close on exec" */
2127c478bd9Sstevel@tonic-gate 	(void) fcntl(kernel_fd, F_SETFD, FD_CLOEXEC);
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	/* Initialize the slot table */
2157c478bd9Sstevel@tonic-gate 	rv = kernel_slottable_init();
2167c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
2177c478bd9Sstevel@tonic-gate 		(void) close(kernel_fd);
2187c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&globalmutex);
2197c478bd9Sstevel@tonic-gate 		return (rv);
2207c478bd9Sstevel@tonic-gate 	}
2217c478bd9Sstevel@tonic-gate 
222*01223cbaSmcpowers 	/* Initialize the object_to_be_freed list */
223*01223cbaSmcpowers 	(void) pthread_mutex_init(&obj_delay_freed.obj_to_be_free_mutex, NULL);
224*01223cbaSmcpowers 	obj_delay_freed.count = 0;
225*01223cbaSmcpowers 	obj_delay_freed.first = NULL;
226*01223cbaSmcpowers 	obj_delay_freed.last = NULL;
227*01223cbaSmcpowers 
228*01223cbaSmcpowers 	/* Initialize the session_to_be_freed list */
229*01223cbaSmcpowers 	(void) pthread_mutex_init(&ses_delay_freed.ses_to_be_free_mutex, NULL);
230*01223cbaSmcpowers 	ses_delay_freed.count = 0;
231*01223cbaSmcpowers 	ses_delay_freed.first = NULL;
232*01223cbaSmcpowers 	ses_delay_freed.last = NULL;
233*01223cbaSmcpowers 
2347c478bd9Sstevel@tonic-gate 	kernel_initialized = B_TRUE;
2357c478bd9Sstevel@tonic-gate 	kernel_pid = initialize_pid;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&globalmutex);
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	return (CKR_OK);
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate  * C_Finalize is a wrapper around finalize_common. The
2467c478bd9Sstevel@tonic-gate  * globalmutex should be locked by C_Finalize().
2477c478bd9Sstevel@tonic-gate  */
2487c478bd9Sstevel@tonic-gate CK_RV
2497c478bd9Sstevel@tonic-gate C_Finalize(CK_VOID_PTR pReserved)
2507c478bd9Sstevel@tonic-gate {
251*01223cbaSmcpowers 	int i;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&globalmutex);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	if (!kernel_initialized) {
2567c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
2577c478bd9Sstevel@tonic-gate 	}
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	/* Check to see if pReseved is NULL */
2607c478bd9Sstevel@tonic-gate 	if (pReserved != NULL) {
2617c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	/*
2657c478bd9Sstevel@tonic-gate 	 * Delete all the sessions for each slot and release the allocated
2667c478bd9Sstevel@tonic-gate 	 * resources
2677c478bd9Sstevel@tonic-gate 	 */
2687c478bd9Sstevel@tonic-gate 	for (i = 0; i < slot_count; i++) {
269*01223cbaSmcpowers 		kernel_delete_all_sessions(i, B_FALSE);
2707c478bd9Sstevel@tonic-gate 	}
2717c478bd9Sstevel@tonic-gate 
272*01223cbaSmcpowers 	finalize_common();
273*01223cbaSmcpowers 
274*01223cbaSmcpowers 	(void) pthread_mutex_unlock(&globalmutex);
275*01223cbaSmcpowers 
276*01223cbaSmcpowers 	return (CKR_OK);
277*01223cbaSmcpowers }
278*01223cbaSmcpowers 
279*01223cbaSmcpowers /*
280*01223cbaSmcpowers  * finalize_common() does the work for C_Finalize.  globalmutex
281*01223cbaSmcpowers  * must be held before calling this function.
282*01223cbaSmcpowers  */
283*01223cbaSmcpowers static void
284*01223cbaSmcpowers finalize_common() {
285*01223cbaSmcpowers 
286*01223cbaSmcpowers 	int i;
287*01223cbaSmcpowers 	kernel_object_t *delay_free_obj, *tmpo;
288*01223cbaSmcpowers 	kernel_session_t *delay_free_ses, *tmps;
289*01223cbaSmcpowers 
2907c478bd9Sstevel@tonic-gate 	/*
2917c478bd9Sstevel@tonic-gate 	 * Free the resources allocated for the slot table and reset
2927c478bd9Sstevel@tonic-gate 	 * slot_count to 0.
2937c478bd9Sstevel@tonic-gate 	 */
2947c478bd9Sstevel@tonic-gate 	if (slot_count > 0) {
2957c478bd9Sstevel@tonic-gate 		for (i = 0; i < slot_count; i++) {
2967c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_destroy(&slot_table[i]->sl_mutex);
2977c478bd9Sstevel@tonic-gate 			(void) free(slot_table[i]);
2987c478bd9Sstevel@tonic-gate 		}
2997c478bd9Sstevel@tonic-gate 		(void) free(slot_table);
3007c478bd9Sstevel@tonic-gate 		slot_count = 0;
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	/* Close CRYPTO_DEVICE */
3047c478bd9Sstevel@tonic-gate 	if (kernel_fd >= 0) {
3057c478bd9Sstevel@tonic-gate 		(void) close(kernel_fd);
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	kernel_fd = -1;
3097c478bd9Sstevel@tonic-gate 	kernel_initialized = B_FALSE;
3107c478bd9Sstevel@tonic-gate 	kernel_pid = 0;
3117c478bd9Sstevel@tonic-gate 
312*01223cbaSmcpowers 	/*
313*01223cbaSmcpowers 	 * free all entries in the delay_freed list
314*01223cbaSmcpowers 	 */
315*01223cbaSmcpowers 	delay_free_obj = obj_delay_freed.first;
316*01223cbaSmcpowers 	while (delay_free_obj != NULL) {
317*01223cbaSmcpowers 		tmpo = delay_free_obj->next;
318*01223cbaSmcpowers 		free(delay_free_obj);
319*01223cbaSmcpowers 		delay_free_obj = tmpo;
320*01223cbaSmcpowers 	}
321*01223cbaSmcpowers 	(void) pthread_mutex_destroy(&obj_delay_freed.obj_to_be_free_mutex);
322*01223cbaSmcpowers 
323*01223cbaSmcpowers 	delay_free_ses = ses_delay_freed.first;
324*01223cbaSmcpowers 	while (delay_free_ses != NULL) {
325*01223cbaSmcpowers 		tmps = delay_free_ses->next;
326*01223cbaSmcpowers 		free(delay_free_ses);
327*01223cbaSmcpowers 		delay_free_ses = tmps;
328*01223cbaSmcpowers 	}
329*01223cbaSmcpowers 	(void) pthread_mutex_destroy(&ses_delay_freed.ses_to_be_free_mutex);
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate /*
3337c478bd9Sstevel@tonic-gate  * This function cleans up all the resources in the library (user space only)
3347c478bd9Sstevel@tonic-gate  */
3357c478bd9Sstevel@tonic-gate static void
3367c478bd9Sstevel@tonic-gate cleanup_library()
3377c478bd9Sstevel@tonic-gate {
3387c478bd9Sstevel@tonic-gate 	int i;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	/*
3417c478bd9Sstevel@tonic-gate 	 * Delete all the sessions for each slot and release the allocated
3427c478bd9Sstevel@tonic-gate 	 * resources from the library.  The boolean argument TRUE indicates
3437c478bd9Sstevel@tonic-gate 	 * that we only wants to clean up the resource in the library only.
3447c478bd9Sstevel@tonic-gate 	 * We don't want to clean up the corresponding kernel part of
3457c478bd9Sstevel@tonic-gate 	 * resources, because they are used by the parent process still.
3467c478bd9Sstevel@tonic-gate 	 */
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	for (i = 0; i < slot_count; i++) {
349*01223cbaSmcpowers 		kernel_delete_all_sessions(i, B_TRUE);
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 
352*01223cbaSmcpowers 	finalize_common();
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate /*
3567c478bd9Sstevel@tonic-gate  * kernel_fini() function required to make sure complete cleanup
3577c478bd9Sstevel@tonic-gate  * is done if pkcs11_kernel is ever unloaded without
3587c478bd9Sstevel@tonic-gate  * a C_Finalize() call.
3597c478bd9Sstevel@tonic-gate  */
3607c478bd9Sstevel@tonic-gate static void
3617c478bd9Sstevel@tonic-gate kernel_fini()
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&globalmutex);
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	/* if we're not initilized, do not attempt to finalize */
3677c478bd9Sstevel@tonic-gate 	if (!kernel_initialized) {
3687c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&globalmutex);
3697c478bd9Sstevel@tonic-gate 		return;
3707c478bd9Sstevel@tonic-gate 	}
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	cleanup_library();
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&globalmutex);
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate CK_RV
3787c478bd9Sstevel@tonic-gate C_GetInfo(CK_INFO_PTR pInfo)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
3817c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	if (pInfo == NULL) {
3847c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
3857c478bd9Sstevel@tonic-gate 	}
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	/* Check if the cryptoki was initialized */
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
3907c478bd9Sstevel@tonic-gate 	pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
3917c478bd9Sstevel@tonic-gate 	(void) strncpy((char *)pInfo->manufacturerID,
3927c478bd9Sstevel@tonic-gate 	    MANUFACTURER_ID, 32);
3937c478bd9Sstevel@tonic-gate 	pInfo->flags = 0;
3947c478bd9Sstevel@tonic-gate 	(void) strncpy((char *)pInfo->libraryDescription,
3957c478bd9Sstevel@tonic-gate 	    LIBRARY_DESCRIPTION, 32);
3967c478bd9Sstevel@tonic-gate 	pInfo->libraryVersion.major = LIBRARY_VERSION_MAJOR;
3977c478bd9Sstevel@tonic-gate 	pInfo->libraryVersion.minor = LIBRARY_VERSION_MINOR;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	return (CKR_OK);
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate CK_RV
4037c478bd9Sstevel@tonic-gate C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
4047c478bd9Sstevel@tonic-gate {
4057c478bd9Sstevel@tonic-gate 	if (ppFunctionList == NULL) {
4067c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
4077c478bd9Sstevel@tonic-gate 	}
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	*ppFunctionList = &functionList;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	return (CKR_OK);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate  * PKCS#11 states that C_GetFunctionStatus should always return
4167c478bd9Sstevel@tonic-gate  * CKR_FUNCTION_NOT_PARALLEL
4177c478bd9Sstevel@tonic-gate  */
4187c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4197c478bd9Sstevel@tonic-gate CK_RV
4207c478bd9Sstevel@tonic-gate C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
4217c478bd9Sstevel@tonic-gate {
4227c478bd9Sstevel@tonic-gate 	return (CKR_FUNCTION_NOT_PARALLEL);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate /*
4267c478bd9Sstevel@tonic-gate  * PKCS#11 states that C_CancelFunction should always return
4277c478bd9Sstevel@tonic-gate  * CKR_FUNCTION_NOT_PARALLEL
4287c478bd9Sstevel@tonic-gate  */
4297c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4307c478bd9Sstevel@tonic-gate CK_RV
4317c478bd9Sstevel@tonic-gate C_CancelFunction(CK_SESSION_HANDLE hSession)
4327c478bd9Sstevel@tonic-gate {
4337c478bd9Sstevel@tonic-gate 	return (CKR_FUNCTION_NOT_PARALLEL);
4347c478bd9Sstevel@tonic-gate }
435