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 5ba5f469cSkrishna * Common Development and Distribution License (the "License"). 6ba5f469cSkrishna * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*1f49a79aSZdenek 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 <pthread.h> 277c478bd9Sstevel@tonic-gate #include <syslog.h> 287c478bd9Sstevel@tonic-gate #include <stdlib.h> 297c478bd9Sstevel@tonic-gate #include <string.h> 307c478bd9Sstevel@tonic-gate #include <errno.h> 317c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h> 327c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 337c478bd9Sstevel@tonic-gate #include "kernelGlobal.h" 347c478bd9Sstevel@tonic-gate #include "kernelSession.h" 357c478bd9Sstevel@tonic-gate #include "kernelSlot.h" 36ba5f469cSkrishna #include "kernelEmulate.h" 377c478bd9Sstevel@tonic-gate 3801223cbaSmcpowers static pthread_mutex_t delete_sessions_mutex = PTHREAD_MUTEX_INITIALIZER; 3901223cbaSmcpowers 407c478bd9Sstevel@tonic-gate /* 417c478bd9Sstevel@tonic-gate * Delete all the sessions. First, obtain the slot lock. 427c478bd9Sstevel@tonic-gate * Then start to delete one session at a time. The boolean wrapper_only 437c478bd9Sstevel@tonic-gate * argument indicates that whether the caller only wants to clean up the 447c478bd9Sstevel@tonic-gate * session wrappers and the object wrappers in the library. 457c478bd9Sstevel@tonic-gate * - When this function is called by C_CloseAllSessions or indirectly by 467c478bd9Sstevel@tonic-gate * C_Finalize, wrapper_only is FALSE. 477c478bd9Sstevel@tonic-gate * - When this function is called by cleanup_child, wrapper_only is TRUE. 487c478bd9Sstevel@tonic-gate */ 4901223cbaSmcpowers void 507c478bd9Sstevel@tonic-gate kernel_delete_all_sessions(CK_SLOT_ID slotID, boolean_t wrapper_only) 517c478bd9Sstevel@tonic-gate { 527c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 537c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 547c478bd9Sstevel@tonic-gate 5501223cbaSmcpowers (void) pthread_mutex_lock(&delete_sessions_mutex); 5601223cbaSmcpowers 577c478bd9Sstevel@tonic-gate pslot = slot_table[slotID]; 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * Delete all the sessions in the slot's session list. 617c478bd9Sstevel@tonic-gate * The routine kernel_delete_session() updates the linked list. 627c478bd9Sstevel@tonic-gate * So, we do not need to maintain the list here. 637c478bd9Sstevel@tonic-gate */ 6401223cbaSmcpowers for (;;) { 6501223cbaSmcpowers (void) pthread_mutex_lock(&pslot->sl_mutex); 6601223cbaSmcpowers if (pslot->sl_sess_list == NULL) 6701223cbaSmcpowers break; 6801223cbaSmcpowers 697c478bd9Sstevel@tonic-gate session_p = pslot->sl_sess_list; 707c478bd9Sstevel@tonic-gate /* 7101223cbaSmcpowers * Set SESSION_IS_CLOSING flag so any access to this 7201223cbaSmcpowers * session will be rejected. 737c478bd9Sstevel@tonic-gate */ 7401223cbaSmcpowers (void) pthread_mutex_lock(&session_p->session_mutex); 7501223cbaSmcpowers if (session_p->ses_close_sync & SESSION_IS_CLOSING) { 7601223cbaSmcpowers (void) pthread_mutex_unlock(&session_p->session_mutex); 7701223cbaSmcpowers continue; 787c478bd9Sstevel@tonic-gate } 7901223cbaSmcpowers session_p->ses_close_sync |= SESSION_IS_CLOSING; 8001223cbaSmcpowers (void) pthread_mutex_unlock(&session_p->session_mutex); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&pslot->sl_mutex); 8301223cbaSmcpowers kernel_delete_session(slotID, session_p, B_FALSE, wrapper_only); 847c478bd9Sstevel@tonic-gate } 8501223cbaSmcpowers (void) pthread_mutex_unlock(&pslot->sl_mutex); 8601223cbaSmcpowers (void) pthread_mutex_unlock(&delete_sessions_mutex); 8701223cbaSmcpowers } 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * Create a new session struct, and add it to the slot's session list. 917c478bd9Sstevel@tonic-gate * 927c478bd9Sstevel@tonic-gate * This function is called by C_OpenSession(), which hold the slot lock. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate CK_RV 957c478bd9Sstevel@tonic-gate kernel_add_session(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, 967c478bd9Sstevel@tonic-gate CK_NOTIFY notify, CK_ULONG *sessionhandle_p) 977c478bd9Sstevel@tonic-gate { 987c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 997c478bd9Sstevel@tonic-gate kernel_session_t *new_sp = NULL; 1007c478bd9Sstevel@tonic-gate crypto_open_session_t open_session; 1017c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 1027c478bd9Sstevel@tonic-gate int r; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* Allocate a new session struct */ 1057c478bd9Sstevel@tonic-gate new_sp = calloc(1, sizeof (kernel_session_t)); 1067c478bd9Sstevel@tonic-gate if (new_sp == NULL) { 1077c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate new_sp->magic_marker = KERNELTOKEN_SESSION_MAGIC; 1117c478bd9Sstevel@tonic-gate new_sp->pApplication = pApplication; 1127c478bd9Sstevel@tonic-gate new_sp->Notify = notify; 1137c478bd9Sstevel@tonic-gate new_sp->flags = flags; 1147c478bd9Sstevel@tonic-gate new_sp->ses_RO = (flags & CKF_RW_SESSION) ? B_FALSE : B_TRUE; 1157c478bd9Sstevel@tonic-gate new_sp->ses_slotid = slotID; 1167c478bd9Sstevel@tonic-gate new_sp->object_list = NULL; 1177c478bd9Sstevel@tonic-gate new_sp->ses_refcnt = 0; 1187c478bd9Sstevel@tonic-gate new_sp->ses_close_sync = 0; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* Initialize the lock for the newly created session */ 1217c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&new_sp->session_mutex, NULL) != 0) { 1227c478bd9Sstevel@tonic-gate free(new_sp); 1237c478bd9Sstevel@tonic-gate return (CKR_CANT_LOCK); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate pslot = slot_table[slotID]; 1277c478bd9Sstevel@tonic-gate open_session.os_provider_id = pslot->sl_provider_id; 1287c478bd9Sstevel@tonic-gate open_session.os_flags = flags; 1297c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_OPEN_SESSION, &open_session)) < 0) { 1307c478bd9Sstevel@tonic-gate if (errno != EINTR) 1317c478bd9Sstevel@tonic-gate break; 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate if (r < 0) { 1347c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 1357c478bd9Sstevel@tonic-gate } else { 1367c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(open_session.os_return_value); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1407c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&new_sp->session_mutex); 1417c478bd9Sstevel@tonic-gate free(new_sp); 1427c478bd9Sstevel@tonic-gate return (rv); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate new_sp->k_session = open_session.os_session; 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_sp->ses_free_mutex, NULL); 1487c478bd9Sstevel@tonic-gate (void) pthread_cond_init(&new_sp->ses_free_cond, NULL); 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate /* Insert the new session in front of the slot's session list */ 1517c478bd9Sstevel@tonic-gate if (pslot->sl_sess_list == NULL) { 1527c478bd9Sstevel@tonic-gate pslot->sl_sess_list = new_sp; 1537c478bd9Sstevel@tonic-gate new_sp->prev = NULL; 1547c478bd9Sstevel@tonic-gate new_sp->next = NULL; 1557c478bd9Sstevel@tonic-gate } else { 1567c478bd9Sstevel@tonic-gate pslot->sl_sess_list->prev = new_sp; 1577c478bd9Sstevel@tonic-gate new_sp->next = pslot->sl_sess_list; 1587c478bd9Sstevel@tonic-gate new_sp->prev = NULL; 1597c478bd9Sstevel@tonic-gate pslot->sl_sess_list = new_sp; 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* Type casting the address of a session struct to a session handle */ 1637c478bd9Sstevel@tonic-gate *sessionhandle_p = (CK_ULONG)new_sp; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate return (CKR_OK); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * Delete a session: 1707c478bd9Sstevel@tonic-gate * - Remove the session from the slot's session list. 1717c478bd9Sstevel@tonic-gate * - Release all the objects created by the session. 1727c478bd9Sstevel@tonic-gate * 1737c478bd9Sstevel@tonic-gate * The boolean argument slot_lock_held is used to indicate that whether 1747c478bd9Sstevel@tonic-gate * the caller of this function holds the slot lock or not. 1757c478bd9Sstevel@tonic-gate * - When called by kernel_delete_all_sessions(), which is called by 1767c478bd9Sstevel@tonic-gate * C_Finalize() or C_CloseAllSessions() -- slot_lock_held = TRUE. 1777c478bd9Sstevel@tonic-gate * - When called by C_CloseSession() -- slot_lock_held = FALSE. 1787c478bd9Sstevel@tonic-gate */ 17901223cbaSmcpowers void 1807c478bd9Sstevel@tonic-gate kernel_delete_session(CK_SLOT_ID slotID, kernel_session_t *session_p, 1817c478bd9Sstevel@tonic-gate boolean_t slot_lock_held, boolean_t wrapper_only) 1827c478bd9Sstevel@tonic-gate { 1837c478bd9Sstevel@tonic-gate crypto_session_id_t k_session; 1847c478bd9Sstevel@tonic-gate crypto_close_session_t close_session; 1857c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 1867c478bd9Sstevel@tonic-gate kernel_object_t *objp; 1877c478bd9Sstevel@tonic-gate kernel_object_t *objp1; 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * Check to see if the caller holds the lock on the global 1917c478bd9Sstevel@tonic-gate * session list. If not, we need to acquire that lock in 1927c478bd9Sstevel@tonic-gate * order to proceed. 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate pslot = slot_table[slotID]; 1957c478bd9Sstevel@tonic-gate if (!slot_lock_held) { 1967c478bd9Sstevel@tonic-gate /* Acquire the slot lock */ 1977c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&pslot->sl_mutex); 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * Remove the session from the slot's session list first. 2027c478bd9Sstevel@tonic-gate */ 2037c478bd9Sstevel@tonic-gate if (pslot->sl_sess_list == session_p) { 2047c478bd9Sstevel@tonic-gate /* Session is the first one in the list */ 2057c478bd9Sstevel@tonic-gate if (session_p->next) { 2067c478bd9Sstevel@tonic-gate pslot->sl_sess_list = session_p->next; 2077c478bd9Sstevel@tonic-gate session_p->next->prev = NULL; 2087c478bd9Sstevel@tonic-gate } else { 2097c478bd9Sstevel@tonic-gate /* Session is the only one in the list */ 2107c478bd9Sstevel@tonic-gate pslot->sl_sess_list = NULL; 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate } else { 2137c478bd9Sstevel@tonic-gate /* Session is not the first one in the list */ 2147c478bd9Sstevel@tonic-gate if (session_p->next) { 2157c478bd9Sstevel@tonic-gate /* Session is in the middle of the list */ 2167c478bd9Sstevel@tonic-gate session_p->prev->next = session_p->next; 2177c478bd9Sstevel@tonic-gate session_p->next->prev = session_p->prev; 2187c478bd9Sstevel@tonic-gate } else { 2197c478bd9Sstevel@tonic-gate /* Session is the last one in the list */ 2207c478bd9Sstevel@tonic-gate session_p->prev->next = NULL; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate if (!slot_lock_held) { 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * If the slot lock is obtained by 2277c478bd9Sstevel@tonic-gate * this function, then release that lock after 2287c478bd9Sstevel@tonic-gate * removing the session from session linked list. 2297c478bd9Sstevel@tonic-gate * We want the releasing of the objects of the 2307c478bd9Sstevel@tonic-gate * session, and freeing of the session itself to 2317c478bd9Sstevel@tonic-gate * be done without holding the slot's session list 2327c478bd9Sstevel@tonic-gate * lock. 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&pslot->sl_mutex); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* Acquire the individual session lock */ 2387c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * Make sure another thread hasn't freed the session. 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate if (session_p->magic_marker != KERNELTOKEN_SESSION_MAGIC) { 2447c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 24501223cbaSmcpowers return; 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * The deletion of a session must be blocked when the session reference 2507c478bd9Sstevel@tonic-gate * count is not zero. This means that if the thread that is attempting 2517c478bd9Sstevel@tonic-gate * to close the session must wait until the prior operations on this 2527c478bd9Sstevel@tonic-gate * session are finished. 2534daf2311Srupertk * 2544daf2311Srupertk * Unless we are being forced to shut everything down, this only 2554daf2311Srupertk * happens if the library's _fini() is running not if someone 2564daf2311Srupertk * explicitly called C_Finalize(). 2577c478bd9Sstevel@tonic-gate */ 2587c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->ses_free_mutex); 2597c478bd9Sstevel@tonic-gate 2604daf2311Srupertk if (wrapper_only) { 2614daf2311Srupertk session_p->ses_refcnt = 0; 2624daf2311Srupertk } 2634daf2311Srupertk 2647c478bd9Sstevel@tonic-gate while (session_p->ses_refcnt != 0) { 2657c478bd9Sstevel@tonic-gate /* 2667c478bd9Sstevel@tonic-gate * We set the SESSION_REFCNT_WAITING flag before we put 2677c478bd9Sstevel@tonic-gate * this closing thread in a wait state, so other non-closing 2687c478bd9Sstevel@tonic-gate * operation thread will wake it up only when 2697c478bd9Sstevel@tonic-gate * the session reference count becomes zero and this flag 2707c478bd9Sstevel@tonic-gate * is set. 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate session_p->ses_close_sync |= SESSION_REFCNT_WAITING; 2737c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 2747c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&session_p->ses_free_cond, 2757c478bd9Sstevel@tonic-gate &session_p->ses_free_mutex); 2767c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate session_p->ses_close_sync &= ~SESSION_REFCNT_WAITING; 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* Mark session as no longer valid. */ 2827c478bd9Sstevel@tonic-gate session_p->magic_marker = 0; 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->ses_free_mutex); 2857c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&session_p->ses_free_mutex); 2867c478bd9Sstevel@tonic-gate (void) pthread_cond_destroy(&session_p->ses_free_cond); 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* 28901223cbaSmcpowers * Remove all the objects created in this session, waiting 29001223cbaSmcpowers * until each object's refcnt is 0. 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate kernel_delete_all_objects_in_session(session_p, wrapper_only); 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /* In case application did not call Final */ 295ba5f469cSkrishna if (session_p->digest.context != NULL) { 296ba5f469cSkrishna digest_buf_t *bufp = session_p->digest.context; 297ba5f469cSkrishna 298ba5f469cSkrishna if (bufp->buf != NULL) { 299ba5f469cSkrishna free_soft_ctx(get_sp(&session_p->digest), OP_DIGEST); 300ba5f469cSkrishna bzero(bufp->buf, bufp->indata_len); 301ba5f469cSkrishna free(bufp->buf); 302ba5f469cSkrishna } 303ba5f469cSkrishna free(bufp); 304ba5f469cSkrishna } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if (session_p->encrypt.context != NULL) 3077c478bd9Sstevel@tonic-gate free(session_p->encrypt.context); 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate if (session_p->decrypt.context != NULL) 3107c478bd9Sstevel@tonic-gate free(session_p->decrypt.context); 3117c478bd9Sstevel@tonic-gate 312ba5f469cSkrishna if (session_p->sign.context != NULL) { 313ba5f469cSkrishna digest_buf_t *bufp = session_p->sign.context; 3147c478bd9Sstevel@tonic-gate 315ba5f469cSkrishna if (bufp->buf != NULL) { 316ba5f469cSkrishna free_soft_ctx(get_sp(&session_p->sign), OP_SIGN); 317ba5f469cSkrishna bzero(bufp->buf, bufp->indata_len); 318ba5f469cSkrishna free(bufp->buf); 319ba5f469cSkrishna } 320ba5f469cSkrishna free(bufp); 321ba5f469cSkrishna } 322ba5f469cSkrishna 323ba5f469cSkrishna if (session_p->verify.context != NULL) { 324ba5f469cSkrishna digest_buf_t *bufp = session_p->verify.context; 325ba5f469cSkrishna 326ba5f469cSkrishna if (bufp->buf != NULL) { 327ba5f469cSkrishna free_soft_ctx(get_sp(&session_p->verify), OP_VERIFY); 328ba5f469cSkrishna bzero(bufp->buf, bufp->indata_len); 329ba5f469cSkrishna free(bufp->buf); 330ba5f469cSkrishna } 331ba5f469cSkrishna free(bufp); 332ba5f469cSkrishna } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate k_session = session_p->k_session; 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* Reset SESSION_IS_CLOSING flag. */ 3377c478bd9Sstevel@tonic-gate session_p->ses_close_sync &= ~SESSION_IS_CLOSING; 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 3407c478bd9Sstevel@tonic-gate /* Destroy the individual session lock */ 3417c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&session_p->session_mutex); 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if (!wrapper_only) { 3447c478bd9Sstevel@tonic-gate close_session.cs_session = k_session; 34501223cbaSmcpowers while (ioctl(kernel_fd, CRYPTO_CLOSE_SESSION, 34601223cbaSmcpowers &close_session) < 0) { 3477c478bd9Sstevel@tonic-gate if (errno != EINTR) 3487c478bd9Sstevel@tonic-gate break; 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate /* 35101223cbaSmcpowers * Ignore ioctl return codes. If the library tells the kernel 35201223cbaSmcpowers * to close a session and the kernel says "I don't know what 35301223cbaSmcpowers * session you're talking about", there's not much that can be 35401223cbaSmcpowers * done. All sessions in the kernel will be closed when the 35501223cbaSmcpowers * application exits and closes /dev/crypto. 3567c478bd9Sstevel@tonic-gate */ 35701223cbaSmcpowers } 35801223cbaSmcpowers kernel_session_delay_free(session_p); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate /* 3617c478bd9Sstevel@tonic-gate * If there is no more session remained in this slot, reset the slot's 3627c478bd9Sstevel@tonic-gate * session state to CKU_PUBLIC. Also, clean up all the token object 3637c478bd9Sstevel@tonic-gate * wrappers in the library for this slot. 3647c478bd9Sstevel@tonic-gate */ 3657c478bd9Sstevel@tonic-gate /* Acquire the slot lock if lock is not held */ 3667c478bd9Sstevel@tonic-gate if (!slot_lock_held) { 3677c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&pslot->sl_mutex); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 37001223cbaSmcpowers if (pslot->sl_sess_list == NULL) { 37101223cbaSmcpowers /* Reset the session auth state. */ 3727c478bd9Sstevel@tonic-gate pslot->sl_state = CKU_PUBLIC; 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* Clean up token object wrappers. */ 3757c478bd9Sstevel@tonic-gate objp = pslot->sl_tobj_list; 3767c478bd9Sstevel@tonic-gate while (objp) { 3777c478bd9Sstevel@tonic-gate objp1 = objp->next; 3787c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&objp->object_mutex); 37901223cbaSmcpowers (void) kernel_object_delay_free(objp); 3807c478bd9Sstevel@tonic-gate objp = objp1; 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate pslot->sl_tobj_list = NULL; 38301223cbaSmcpowers } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* Release the slot lock if lock is not held */ 3867c478bd9Sstevel@tonic-gate if (!slot_lock_held) { 3877c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&pslot->sl_mutex); 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate /* 3927c478bd9Sstevel@tonic-gate * This function is used to type cast a session handle to a pointer to 3937c478bd9Sstevel@tonic-gate * the session struct. Also, it does the following things: 3947c478bd9Sstevel@tonic-gate * 1) Check to see if the session struct is tagged with a session 3957c478bd9Sstevel@tonic-gate * magic number. This is to detect when an application passes 3967c478bd9Sstevel@tonic-gate * a bogus session pointer. 397f243d98aSkrishna * 2) Acquire the locks on the designated session. 3987c478bd9Sstevel@tonic-gate * 3) Check to see if the session is in the closing state that another 3997c478bd9Sstevel@tonic-gate * thread is performing. 4007c478bd9Sstevel@tonic-gate * 4) Increment the session reference count by one. This is to prevent 4017c478bd9Sstevel@tonic-gate * this session from being closed by other thread. 402f243d98aSkrishna * 5) Release the locks on the designated session. 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate CK_RV 4057c478bd9Sstevel@tonic-gate handle2session(CK_SESSION_HANDLE hSession, kernel_session_t **session_p) 4067c478bd9Sstevel@tonic-gate { 4077c478bd9Sstevel@tonic-gate kernel_session_t *sp = (kernel_session_t *)(hSession); 4087c478bd9Sstevel@tonic-gate CK_RV rv; 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate if ((sp == NULL) || 4117c478bd9Sstevel@tonic-gate (sp->magic_marker != KERNELTOKEN_SESSION_MAGIC)) { 4127c478bd9Sstevel@tonic-gate return (CKR_SESSION_HANDLE_INVALID); 4137c478bd9Sstevel@tonic-gate } else { 4147c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&sp->session_mutex); 4157c478bd9Sstevel@tonic-gate if (sp->ses_close_sync & SESSION_IS_CLOSING) { 4167c478bd9Sstevel@tonic-gate rv = CKR_SESSION_CLOSED; 4177c478bd9Sstevel@tonic-gate } else { 4187c478bd9Sstevel@tonic-gate /* Increment session ref count. */ 4197c478bd9Sstevel@tonic-gate sp->ses_refcnt++; 4207c478bd9Sstevel@tonic-gate rv = CKR_OK; 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&sp->session_mutex); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate if (rv == CKR_OK) 4267c478bd9Sstevel@tonic-gate *session_p = sp; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate return (rv); 4297c478bd9Sstevel@tonic-gate } 43001223cbaSmcpowers 43101223cbaSmcpowers /* 43201223cbaSmcpowers * This function adds the to-be-freed session to a linked list. 43301223cbaSmcpowers * When the number of sessions queued in the linked list reaches the 43401223cbaSmcpowers * maximum threshold MAX_SES_TO_BE_FREED, it will free the first 43501223cbaSmcpowers * session (FIFO) in the list. 43601223cbaSmcpowers */ 43701223cbaSmcpowers void 43801223cbaSmcpowers kernel_session_delay_free(kernel_session_t *sp) 43901223cbaSmcpowers { 44001223cbaSmcpowers kernel_session_t *tmp; 44101223cbaSmcpowers 44201223cbaSmcpowers (void) pthread_mutex_lock(&ses_delay_freed.ses_to_be_free_mutex); 44301223cbaSmcpowers 44401223cbaSmcpowers /* Add the newly deleted session at the end of the list */ 44501223cbaSmcpowers sp->next = NULL; 44601223cbaSmcpowers if (ses_delay_freed.first == NULL) { 44701223cbaSmcpowers ses_delay_freed.last = sp; 44801223cbaSmcpowers ses_delay_freed.first = sp; 44901223cbaSmcpowers } else { 45001223cbaSmcpowers ses_delay_freed.last->next = sp; 45101223cbaSmcpowers ses_delay_freed.last = sp; 45201223cbaSmcpowers } 45301223cbaSmcpowers 45401223cbaSmcpowers if (++ses_delay_freed.count >= MAX_SES_TO_BE_FREED) { 45501223cbaSmcpowers /* 45601223cbaSmcpowers * Free the first session in the list only if 45701223cbaSmcpowers * the total count reaches maximum threshold. 45801223cbaSmcpowers */ 45901223cbaSmcpowers ses_delay_freed.count--; 46001223cbaSmcpowers tmp = ses_delay_freed.first->next; 46101223cbaSmcpowers free(ses_delay_freed.first); 46201223cbaSmcpowers ses_delay_freed.first = tmp; 46301223cbaSmcpowers } 46401223cbaSmcpowers (void) pthread_mutex_unlock(&ses_delay_freed.ses_to_be_free_mutex); 46501223cbaSmcpowers } 4664daf2311Srupertk 4674daf2311Srupertk /* 4684daf2311Srupertk * Acquire all slots' mutexes and all their sessions' mutexes. 4694daf2311Srupertk * Order: 4704daf2311Srupertk * 1. delete_sessions_mutex 4714daf2311Srupertk * for each slot: 4724daf2311Srupertk * 2. pslot->sl_mutex 4734daf2311Srupertk * for each session: 4744daf2311Srupertk * 3. session_p->session_mutex 4754daf2311Srupertk * 4. session_p->ses_free_mutex 4764daf2311Srupertk */ 4774daf2311Srupertk void 4784daf2311Srupertk kernel_acquire_all_slots_mutexes() 4794daf2311Srupertk { 4804daf2311Srupertk int slotID; 4814daf2311Srupertk kernel_slot_t *pslot; 4824daf2311Srupertk kernel_session_t *session_p; 4834daf2311Srupertk 4844daf2311Srupertk (void) pthread_mutex_lock(&delete_sessions_mutex); 485*1f49a79aSZdenek Kotala 4864daf2311Srupertk for (slotID = 0; slotID < slot_count; slotID++) { 4874daf2311Srupertk pslot = slot_table[slotID]; 4884daf2311Srupertk (void) pthread_mutex_lock(&pslot->sl_mutex); 4894daf2311Srupertk 4904daf2311Srupertk /* Iterate through sessions acquiring all mutexes */ 4914daf2311Srupertk session_p = pslot->sl_sess_list; 4924daf2311Srupertk while (session_p) { 493*1f49a79aSZdenek Kotala struct object *objp; 494*1f49a79aSZdenek Kotala 4954daf2311Srupertk (void) pthread_mutex_lock(&session_p->session_mutex); 496*1f49a79aSZdenek Kotala (void) pthread_mutex_lock(&session_p->ses_free_mutex); 497*1f49a79aSZdenek Kotala 498*1f49a79aSZdenek Kotala objp = session_p->object_list; 499*1f49a79aSZdenek Kotala while (objp) { 500*1f49a79aSZdenek Kotala (void) pthread_mutex_lock(&objp->object_mutex); 501*1f49a79aSZdenek Kotala objp = objp->next; 502*1f49a79aSZdenek Kotala } 503*1f49a79aSZdenek Kotala 5044daf2311Srupertk session_p = session_p->next; 5054daf2311Srupertk } 5064daf2311Srupertk } 5074daf2311Srupertk } 5084daf2311Srupertk 5094daf2311Srupertk /* Release in opposite order to kernel_acquire_all_slots_mutexes(). */ 5104daf2311Srupertk void 5114daf2311Srupertk kernel_release_all_slots_mutexes() 5124daf2311Srupertk { 5134daf2311Srupertk int slotID; 5144daf2311Srupertk kernel_slot_t *pslot; 5154daf2311Srupertk kernel_session_t *session_p; 5164daf2311Srupertk 5174daf2311Srupertk for (slotID = 0; slotID < slot_count; slotID++) { 5184daf2311Srupertk pslot = slot_table[slotID]; 5194daf2311Srupertk 5204daf2311Srupertk /* Iterate through sessions releasing all mutexes */ 5214daf2311Srupertk session_p = pslot->sl_sess_list; 5224daf2311Srupertk while (session_p) { 523*1f49a79aSZdenek Kotala struct object *objp; 524*1f49a79aSZdenek Kotala 525*1f49a79aSZdenek Kotala objp = session_p->object_list; 526*1f49a79aSZdenek Kotala while (objp) { 527*1f49a79aSZdenek Kotala (void) pthread_mutex_unlock( 528*1f49a79aSZdenek Kotala &objp->object_mutex); 529*1f49a79aSZdenek Kotala objp = objp->next; 530*1f49a79aSZdenek Kotala } 531*1f49a79aSZdenek Kotala 532*1f49a79aSZdenek Kotala (void) pthread_mutex_unlock(&session_p->ses_free_mutex); 5334daf2311Srupertk (void) pthread_mutex_unlock(&session_p->session_mutex); 5344daf2311Srupertk session_p = session_p->next; 5354daf2311Srupertk } 5364daf2311Srupertk 5374daf2311Srupertk (void) pthread_mutex_unlock(&pslot->sl_mutex); 5384daf2311Srupertk } 5394daf2311Srupertk 5404daf2311Srupertk (void) pthread_mutex_unlock(&delete_sessions_mutex); 5414daf2311Srupertk } 542