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
5f243d98aSkrishna * Common Development and Distribution License (the "License").
6f243d98aSkrishna * 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 /*
22d288ba74SAnthony Scarpino * 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 <md5.h>
277c478bd9Sstevel@tonic-gate #include <pthread.h>
287c478bd9Sstevel@tonic-gate #include <syslog.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <strings.h>
327c478bd9Sstevel@tonic-gate #include <sys/sha1.h>
337c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
347c478bd9Sstevel@tonic-gate #include "softGlobal.h"
357c478bd9Sstevel@tonic-gate #include "softSession.h"
367c478bd9Sstevel@tonic-gate #include "softObject.h"
377c478bd9Sstevel@tonic-gate #include "softOps.h"
387c478bd9Sstevel@tonic-gate #include "softKeystore.h"
397c478bd9Sstevel@tonic-gate #include "softKeystoreUtil.h"
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate CK_ULONG soft_session_cnt = 0; /* the number of opened sessions */
437c478bd9Sstevel@tonic-gate CK_ULONG soft_session_rw_cnt = 0; /* the number of opened R/W sessions */
447c478bd9Sstevel@tonic-gate
45588a1af0SAlexandr Nedvedicky #define DIGEST_MECH_OK(_m_) ((_m_) == CKM_MD5 || (_m_) == CKM_SHA_1)
46588a1af0SAlexandr Nedvedicky
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate * Delete all the sessions. First, obtain the global session
497c478bd9Sstevel@tonic-gate * list lock. Then start to delete one session at a time.
507c478bd9Sstevel@tonic-gate * Release the global session list lock before returning to
517c478bd9Sstevel@tonic-gate * caller.
527c478bd9Sstevel@tonic-gate */
537c478bd9Sstevel@tonic-gate CK_RV
soft_delete_all_sessions(boolean_t force)54a62b4373Sdarrenm soft_delete_all_sessions(boolean_t force)
557c478bd9Sstevel@tonic-gate {
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
587c478bd9Sstevel@tonic-gate CK_RV rv1;
597c478bd9Sstevel@tonic-gate soft_session_t *session_p;
607c478bd9Sstevel@tonic-gate soft_session_t *session_p1;
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate /* Acquire the global session list lock */
637c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&soft_sessionlist_mutex);
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate session_p = soft_session_list;
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate /* Delete all the sessions in the session list */
687c478bd9Sstevel@tonic-gate while (session_p) {
697c478bd9Sstevel@tonic-gate session_p1 = session_p->next;
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate * Delete a session by calling soft_delete_session()
737c478bd9Sstevel@tonic-gate * with a session pointer and a boolean arguments.
747c478bd9Sstevel@tonic-gate * Boolean value TRUE is used to indicate that the
757c478bd9Sstevel@tonic-gate * caller holds the lock on the global session list.
76a62b4373Sdarrenm *
777c478bd9Sstevel@tonic-gate */
78a62b4373Sdarrenm rv1 = soft_delete_session(session_p, force, B_TRUE);
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate /* Record the very first error code */
817c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
827c478bd9Sstevel@tonic-gate rv = rv1;
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate session_p = session_p1;
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate /* No session left */
897c478bd9Sstevel@tonic-gate soft_session_list = NULL;
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate /* Release the global session list lock */
927c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate return (rv);
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate * Create a new session struct, and add it to the session linked list.
1017c478bd9Sstevel@tonic-gate *
1027c478bd9Sstevel@tonic-gate * This function will acquire the global session list lock, and release
1037c478bd9Sstevel@tonic-gate * it after adding the session to the session linked list.
1047c478bd9Sstevel@tonic-gate */
1057c478bd9Sstevel@tonic-gate CK_RV
soft_add_session(CK_FLAGS flags,CK_VOID_PTR pApplication,CK_NOTIFY notify,CK_ULONG * sessionhandle_p)1067c478bd9Sstevel@tonic-gate soft_add_session(CK_FLAGS flags, CK_VOID_PTR pApplication,
1077c478bd9Sstevel@tonic-gate CK_NOTIFY notify, CK_ULONG *sessionhandle_p)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate soft_session_t *new_sp = NULL;
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate /* Allocate a new session struct */
1137c478bd9Sstevel@tonic-gate new_sp = calloc(1, sizeof (soft_session_t));
1147c478bd9Sstevel@tonic-gate if (new_sp == NULL) {
1157c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate new_sp->magic_marker = SOFTTOKEN_SESSION_MAGIC;
1197c478bd9Sstevel@tonic-gate new_sp->pApplication = pApplication;
1207c478bd9Sstevel@tonic-gate new_sp->Notify = notify;
1217c478bd9Sstevel@tonic-gate new_sp->flags = flags;
1227c478bd9Sstevel@tonic-gate new_sp->state = CKS_RO_PUBLIC_SESSION;
1237c478bd9Sstevel@tonic-gate new_sp->object_list = NULL;
1247c478bd9Sstevel@tonic-gate new_sp->ses_refcnt = 0;
1257c478bd9Sstevel@tonic-gate new_sp->ses_close_sync = 0;
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&soft_giant_mutex);
1287c478bd9Sstevel@tonic-gate if (soft_slot.authenticated) {
1297c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&soft_giant_mutex);
1307c478bd9Sstevel@tonic-gate if (flags & CKF_RW_SESSION) {
1317c478bd9Sstevel@tonic-gate new_sp->state = CKS_RW_USER_FUNCTIONS;
1327c478bd9Sstevel@tonic-gate } else {
1337c478bd9Sstevel@tonic-gate new_sp->state = CKS_RO_USER_FUNCTIONS;
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate } else {
1367c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&soft_giant_mutex);
1377c478bd9Sstevel@tonic-gate if (flags & CKF_RW_SESSION) {
1387c478bd9Sstevel@tonic-gate new_sp->state = CKS_RW_PUBLIC_SESSION;
1397c478bd9Sstevel@tonic-gate } else {
1407c478bd9Sstevel@tonic-gate new_sp->state = CKS_RO_PUBLIC_SESSION;
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate /* Initialize the lock for the newly created session */
1457c478bd9Sstevel@tonic-gate if (pthread_mutex_init(&new_sp->session_mutex, NULL) != 0) {
1467c478bd9Sstevel@tonic-gate free(new_sp);
1477c478bd9Sstevel@tonic-gate return (CKR_CANT_LOCK);
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate (void) pthread_cond_init(&new_sp->ses_free_cond, NULL);
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate /* Acquire the global session list lock */
1537c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&soft_sessionlist_mutex);
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate /* Insert the new session in front of session list */
1567c478bd9Sstevel@tonic-gate if (soft_session_list == NULL) {
1577c478bd9Sstevel@tonic-gate soft_session_list = new_sp;
1587c478bd9Sstevel@tonic-gate new_sp->next = NULL;
1597c478bd9Sstevel@tonic-gate new_sp->prev = NULL;
1607c478bd9Sstevel@tonic-gate } else {
1617c478bd9Sstevel@tonic-gate soft_session_list->prev = new_sp;
1627c478bd9Sstevel@tonic-gate new_sp->next = soft_session_list;
1637c478bd9Sstevel@tonic-gate new_sp->prev = NULL;
1647c478bd9Sstevel@tonic-gate soft_session_list = new_sp;
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate /* Type casting the address of a session struct to a session handle */
1687c478bd9Sstevel@tonic-gate *sessionhandle_p = (CK_ULONG)new_sp;
1697c478bd9Sstevel@tonic-gate ++soft_session_cnt;
1707c478bd9Sstevel@tonic-gate if (flags & CKF_RW_SESSION)
1717c478bd9Sstevel@tonic-gate ++soft_session_rw_cnt;
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate if (soft_session_cnt == 1)
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate * This is the first session to be opened, so we can set
1767c478bd9Sstevel@tonic-gate * validate the public token objects in token list now.
1777c478bd9Sstevel@tonic-gate */
1787c478bd9Sstevel@tonic-gate soft_validate_token_objects(B_TRUE);
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /* Release the global session list lock */
1817c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate return (CKR_OK);
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate /*
1887c478bd9Sstevel@tonic-gate * This function adds the to-be-freed session to a linked list.
1897c478bd9Sstevel@tonic-gate * When the number of sessions queued in the linked list reaches the
1907c478bd9Sstevel@tonic-gate * maximum threshold MAX_SES_TO_BE_FREED, it will free the first
1917c478bd9Sstevel@tonic-gate * session (FIFO) in the list.
1927c478bd9Sstevel@tonic-gate */
1937c478bd9Sstevel@tonic-gate void
session_delay_free(soft_session_t * sp)1947c478bd9Sstevel@tonic-gate session_delay_free(soft_session_t *sp)
1957c478bd9Sstevel@tonic-gate {
1967c478bd9Sstevel@tonic-gate soft_session_t *tmp;
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ses_delay_freed.ses_to_be_free_mutex);
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate /* Add the newly deleted session at the end of the list */
2017c478bd9Sstevel@tonic-gate sp->next = NULL;
2027c478bd9Sstevel@tonic-gate if (ses_delay_freed.first == NULL) {
2037c478bd9Sstevel@tonic-gate ses_delay_freed.last = sp;
2047c478bd9Sstevel@tonic-gate ses_delay_freed.first = sp;
2057c478bd9Sstevel@tonic-gate } else {
2067c478bd9Sstevel@tonic-gate ses_delay_freed.last->next = sp;
2077c478bd9Sstevel@tonic-gate ses_delay_freed.last = sp;
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate if (++ses_delay_freed.count >= MAX_SES_TO_BE_FREED) {
2117c478bd9Sstevel@tonic-gate /*
2127c478bd9Sstevel@tonic-gate * Free the first session in the list only if
2137c478bd9Sstevel@tonic-gate * the total count reaches maximum threshold.
2147c478bd9Sstevel@tonic-gate */
2157c478bd9Sstevel@tonic-gate ses_delay_freed.count--;
2167c478bd9Sstevel@tonic-gate tmp = ses_delay_freed.first->next;
2177c478bd9Sstevel@tonic-gate free(ses_delay_freed.first);
2187c478bd9Sstevel@tonic-gate ses_delay_freed.first = tmp;
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ses_delay_freed.ses_to_be_free_mutex);
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate /*
2247c478bd9Sstevel@tonic-gate * Delete a session:
2257c478bd9Sstevel@tonic-gate * - Remove the session from the session linked list.
2267c478bd9Sstevel@tonic-gate * Holding the lock on the global session list is needed to do this.
2277c478bd9Sstevel@tonic-gate * - Release all the objects created by the session.
2287c478bd9Sstevel@tonic-gate *
2297c478bd9Sstevel@tonic-gate * The boolean argument lock_held is used to indicate that whether
2307c478bd9Sstevel@tonic-gate * the caller of this function holds the lock on the global session
2317c478bd9Sstevel@tonic-gate * list or not.
2327c478bd9Sstevel@tonic-gate * - When called by soft_delete_all_sessions(), which is called by
2337c478bd9Sstevel@tonic-gate * C_Finalize() or C_CloseAllSessions() -- the lock_held = TRUE.
2347c478bd9Sstevel@tonic-gate * - When called by C_CloseSession() -- the lock_held = FALSE.
2357c478bd9Sstevel@tonic-gate *
2367c478bd9Sstevel@tonic-gate * When the caller does not hold the lock on the global session
2377c478bd9Sstevel@tonic-gate * list, this function will acquire that lock in order to proceed,
2387c478bd9Sstevel@tonic-gate * and also release that lock before returning to caller.
2397c478bd9Sstevel@tonic-gate */
2407c478bd9Sstevel@tonic-gate CK_RV
soft_delete_session(soft_session_t * session_p,boolean_t force,boolean_t lock_held)241a62b4373Sdarrenm soft_delete_session(soft_session_t *session_p,
242a62b4373Sdarrenm boolean_t force, boolean_t lock_held)
2437c478bd9Sstevel@tonic-gate {
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate * Check to see if the caller holds the lock on the global
2477c478bd9Sstevel@tonic-gate * session list. If not, we need to acquire that lock in
2487c478bd9Sstevel@tonic-gate * order to proceed.
2497c478bd9Sstevel@tonic-gate */
2507c478bd9Sstevel@tonic-gate if (!lock_held) {
2517c478bd9Sstevel@tonic-gate /* Acquire the global session list lock */
2527c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&soft_sessionlist_mutex);
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate /*
2567c478bd9Sstevel@tonic-gate * Remove the session from the session linked list first.
2577c478bd9Sstevel@tonic-gate */
2587c478bd9Sstevel@tonic-gate if (soft_session_list == session_p) {
2597c478bd9Sstevel@tonic-gate /* Session is the first one in the list */
2607c478bd9Sstevel@tonic-gate if (session_p->next) {
2617c478bd9Sstevel@tonic-gate soft_session_list = session_p->next;
2627c478bd9Sstevel@tonic-gate session_p->next->prev = NULL;
2637c478bd9Sstevel@tonic-gate } else {
2647c478bd9Sstevel@tonic-gate /* Session is the only one in the list */
2657c478bd9Sstevel@tonic-gate soft_session_list = NULL;
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate } else {
2687c478bd9Sstevel@tonic-gate /* Session is not the first one in the list */
2697c478bd9Sstevel@tonic-gate if (session_p->next) {
2707c478bd9Sstevel@tonic-gate /* Session is in the middle of the list */
2717c478bd9Sstevel@tonic-gate session_p->prev->next = session_p->next;
2727c478bd9Sstevel@tonic-gate session_p->next->prev = session_p->prev;
2737c478bd9Sstevel@tonic-gate } else {
2747c478bd9Sstevel@tonic-gate /* Session is the last one in the list */
2757c478bd9Sstevel@tonic-gate session_p->prev->next = NULL;
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate --soft_session_cnt;
2807c478bd9Sstevel@tonic-gate if (session_p->flags & CKF_RW_SESSION)
2817c478bd9Sstevel@tonic-gate --soft_session_rw_cnt;
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate if (!lock_held) {
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate * If the global session list lock is obtained by
2867c478bd9Sstevel@tonic-gate * this function, then release that lock after
2877c478bd9Sstevel@tonic-gate * removing the session from session linked list.
2887c478bd9Sstevel@tonic-gate * We want the releasing of the objects of the
2897c478bd9Sstevel@tonic-gate * session, and freeing of the session itself to
2907c478bd9Sstevel@tonic-gate * be done without holding the global session list
2917c478bd9Sstevel@tonic-gate * lock.
2927c478bd9Sstevel@tonic-gate */
2937c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate /* Acquire the individual session lock */
2987c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
2997c478bd9Sstevel@tonic-gate /*
3007c478bd9Sstevel@tonic-gate * Make sure another thread hasn't freed the session.
3017c478bd9Sstevel@tonic-gate */
3027c478bd9Sstevel@tonic-gate if (session_p->magic_marker != SOFTTOKEN_SESSION_MAGIC) {
3037c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
3047c478bd9Sstevel@tonic-gate return (CKR_OK);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate * The deletion of a session must be blocked when the session
3097c478bd9Sstevel@tonic-gate * reference count is not zero. This means if any session related
3107c478bd9Sstevel@tonic-gate * operation starts prior to the session close operation gets in,
3117c478bd9Sstevel@tonic-gate * the session closing thread must wait for the non-closing
3127c478bd9Sstevel@tonic-gate * operation to be completed before it can proceed the close
3137c478bd9Sstevel@tonic-gate * operation.
314a62b4373Sdarrenm *
315a62b4373Sdarrenm * Unless we are being forced to shut everything down, this only
316a62b4373Sdarrenm * happens if the libraries _fini() is running not of someone
317a62b4373Sdarrenm * explicitly called C_Finalize().
3187c478bd9Sstevel@tonic-gate */
319a62b4373Sdarrenm if (force)
320a62b4373Sdarrenm session_p->ses_refcnt = 0;
321a62b4373Sdarrenm
3227c478bd9Sstevel@tonic-gate while (session_p->ses_refcnt != 0) {
3237c478bd9Sstevel@tonic-gate /*
3247c478bd9Sstevel@tonic-gate * We set the SESSION_REFCNT_WAITING flag before we put
3257c478bd9Sstevel@tonic-gate * this closing thread in a wait state, so other non-closing
3267c478bd9Sstevel@tonic-gate * operation thread will signal to wake it up only when
3277c478bd9Sstevel@tonic-gate * the session reference count becomes zero and this flag
3287c478bd9Sstevel@tonic-gate * is set.
3297c478bd9Sstevel@tonic-gate */
3307c478bd9Sstevel@tonic-gate session_p->ses_close_sync |= SESSION_REFCNT_WAITING;
3317c478bd9Sstevel@tonic-gate (void) pthread_cond_wait(&session_p->ses_free_cond,
3327c478bd9Sstevel@tonic-gate &session_p->session_mutex);
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate session_p->ses_close_sync &= ~SESSION_REFCNT_WAITING;
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate /*
3387c478bd9Sstevel@tonic-gate * Remove all the objects created in this session.
3397c478bd9Sstevel@tonic-gate */
3401f49a79aSZdenek Kotala soft_delete_all_objects_in_session(session_p, force);
3417c478bd9Sstevel@tonic-gate
342429cc41dSVladimir Kotal /*
343429cc41dSVladimir Kotal * Mark session as no longer valid. This can only be done after all
344429cc41dSVladimir Kotal * objects created by this session are free'd since the marker is
345429cc41dSVladimir Kotal * still needed in the process of removing objects from the session.
346429cc41dSVladimir Kotal */
347429cc41dSVladimir Kotal session_p->magic_marker = 0;
348429cc41dSVladimir Kotal
349429cc41dSVladimir Kotal (void) pthread_cond_destroy(&session_p->ses_free_cond);
350429cc41dSVladimir Kotal
3517c478bd9Sstevel@tonic-gate /* In case application did not call Final */
3527c478bd9Sstevel@tonic-gate if (session_p->digest.context != NULL)
3537c478bd9Sstevel@tonic-gate free(session_p->digest.context);
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate if (session_p->encrypt.context != NULL)
3567c478bd9Sstevel@tonic-gate /*
3577c478bd9Sstevel@tonic-gate * 1st B_TRUE: encrypt
3587c478bd9Sstevel@tonic-gate * 2nd B_TRUE: caller is holding session_mutex.
3597c478bd9Sstevel@tonic-gate */
3607c478bd9Sstevel@tonic-gate soft_crypt_cleanup(session_p, B_TRUE, B_TRUE);
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate if (session_p->decrypt.context != NULL)
3637c478bd9Sstevel@tonic-gate /*
3647c478bd9Sstevel@tonic-gate * 1st B_FALSE: decrypt
3657c478bd9Sstevel@tonic-gate * 2nd B_TRUE: caller is holding session_mutex.
3667c478bd9Sstevel@tonic-gate */
3677c478bd9Sstevel@tonic-gate soft_crypt_cleanup(session_p, B_FALSE, B_TRUE);
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate if (session_p->sign.context != NULL)
3707c478bd9Sstevel@tonic-gate free(session_p->sign.context);
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate if (session_p->verify.context != NULL)
3737c478bd9Sstevel@tonic-gate free(session_p->verify.context);
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate if (session_p->find_objects.context != NULL) {
3767c478bd9Sstevel@tonic-gate find_context_t *fcontext;
3777c478bd9Sstevel@tonic-gate fcontext = (find_context_t *)session_p->find_objects.context;
3787c478bd9Sstevel@tonic-gate free(fcontext->objs_found);
3797c478bd9Sstevel@tonic-gate free(fcontext);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate /* Reset SESSION_IS_CLOSIN flag. */
3837c478bd9Sstevel@tonic-gate session_p->ses_close_sync &= ~SESSION_IS_CLOSING;
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
3867c478bd9Sstevel@tonic-gate /* Destroy the individual session lock */
3877c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&session_p->session_mutex);
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate /* Delay freeing the session */
3907c478bd9Sstevel@tonic-gate session_delay_free(session_p);
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate return (CKR_OK);
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate /*
3977c478bd9Sstevel@tonic-gate * This function is used to type cast a session handle to a pointer to
3987c478bd9Sstevel@tonic-gate * the session struct. Also, it does the following things:
3997c478bd9Sstevel@tonic-gate * 1) Check to see if the session struct is tagged with a session
4007c478bd9Sstevel@tonic-gate * magic number. This is to detect when an application passes
4017c478bd9Sstevel@tonic-gate * a bogus session pointer.
402f243d98aSkrishna * 2) Acquire the lock on the designated session.
4037c478bd9Sstevel@tonic-gate * 3) Check to see if the session is in the closing state that another
4047c478bd9Sstevel@tonic-gate * thread is performing.
4057c478bd9Sstevel@tonic-gate * 4) Increment the session reference count by one. This is to prevent
4067c478bd9Sstevel@tonic-gate * this session from being closed by other thread.
407f243d98aSkrishna * 5) Release the lock held on the designated session.
4087c478bd9Sstevel@tonic-gate */
4097c478bd9Sstevel@tonic-gate CK_RV
handle2session(CK_SESSION_HANDLE hSession,soft_session_t ** session_p)4107c478bd9Sstevel@tonic-gate handle2session(CK_SESSION_HANDLE hSession, soft_session_t **session_p)
4117c478bd9Sstevel@tonic-gate {
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate soft_session_t *sp = (soft_session_t *)(hSession);
4147c478bd9Sstevel@tonic-gate
415f243d98aSkrishna /*
416f243d98aSkrishna * No need to hold soft_sessionlist_mutex as we are
417f243d98aSkrishna * just reading the value and 32-bit reads are atomic.
418f243d98aSkrishna */
4197c478bd9Sstevel@tonic-gate if (all_sessions_closing) {
4207c478bd9Sstevel@tonic-gate return (CKR_SESSION_CLOSED);
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate if ((sp == NULL) ||
4247c478bd9Sstevel@tonic-gate (sp->magic_marker != SOFTTOKEN_SESSION_MAGIC)) {
4257c478bd9Sstevel@tonic-gate return (CKR_SESSION_HANDLE_INVALID);
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&sp->session_mutex);
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate if (sp->ses_close_sync & SESSION_IS_CLOSING) {
4307c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&sp->session_mutex);
4317c478bd9Sstevel@tonic-gate return (CKR_SESSION_CLOSED);
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate /* Increment session ref count. */
4357c478bd9Sstevel@tonic-gate sp->ses_refcnt++;
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&sp->session_mutex);
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate *session_p = sp;
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate return (CKR_OK);
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate /*
4457c478bd9Sstevel@tonic-gate * The format to be saved in the pOperationState will be:
4467c478bd9Sstevel@tonic-gate * 1. internal_op_state_t
4477c478bd9Sstevel@tonic-gate * 2. crypto_active_op_t
4487c478bd9Sstevel@tonic-gate * 3. actual context of the active operation
4497c478bd9Sstevel@tonic-gate */
4507c478bd9Sstevel@tonic-gate CK_RV
soft_get_operationstate(soft_session_t * session_p,CK_BYTE_PTR pOperationState,CK_ULONG_PTR pulOperationStateLen)4517c478bd9Sstevel@tonic-gate soft_get_operationstate(soft_session_t *session_p, CK_BYTE_PTR pOperationState,
4527c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulOperationStateLen)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate
455588a1af0SAlexandr Nedvedicky internal_op_state_t *p_op_state;
4567c478bd9Sstevel@tonic-gate CK_ULONG op_data_len = 0;
457588a1af0SAlexandr Nedvedicky CK_RV rv = CKR_OK;
458588a1af0SAlexandr Nedvedicky
459588a1af0SAlexandr Nedvedicky if (pulOperationStateLen == NULL)
460588a1af0SAlexandr Nedvedicky return (CKR_ARGUMENTS_BAD);
461588a1af0SAlexandr Nedvedicky
462588a1af0SAlexandr Nedvedicky (void) pthread_mutex_lock(&session_p->session_mutex);
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate /* Check to see if encrypt operation is active. */
4657c478bd9Sstevel@tonic-gate if (session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE) {
466588a1af0SAlexandr Nedvedicky rv = CKR_STATE_UNSAVEABLE;
467588a1af0SAlexandr Nedvedicky goto unlock_session;
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate /* Check to see if decrypt operation is active. */
4717c478bd9Sstevel@tonic-gate if (session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE) {
472588a1af0SAlexandr Nedvedicky rv = CKR_STATE_UNSAVEABLE;
473588a1af0SAlexandr Nedvedicky goto unlock_session;
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate /* Check to see if sign operation is active. */
4777c478bd9Sstevel@tonic-gate if (session_p->sign.flags & CRYPTO_OPERATION_ACTIVE) {
478588a1af0SAlexandr Nedvedicky rv = CKR_STATE_UNSAVEABLE;
479588a1af0SAlexandr Nedvedicky goto unlock_session;
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate /* Check to see if verify operation is active. */
4837c478bd9Sstevel@tonic-gate if (session_p->verify.flags & CRYPTO_OPERATION_ACTIVE) {
484588a1af0SAlexandr Nedvedicky rv = CKR_STATE_UNSAVEABLE;
485588a1af0SAlexandr Nedvedicky goto unlock_session;
4867c478bd9Sstevel@tonic-gate }
4877c478bd9Sstevel@tonic-gate
4887c478bd9Sstevel@tonic-gate /* Check to see if digest operation is active. */
4897c478bd9Sstevel@tonic-gate if (session_p->digest.flags & CRYPTO_OPERATION_ACTIVE) {
4907c478bd9Sstevel@tonic-gate op_data_len = sizeof (internal_op_state_t) +
4917c478bd9Sstevel@tonic-gate sizeof (crypto_active_op_t);
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate switch (session_p->digest.mech.mechanism) {
4947c478bd9Sstevel@tonic-gate case CKM_MD5:
4957c478bd9Sstevel@tonic-gate op_data_len += sizeof (MD5_CTX);
4967c478bd9Sstevel@tonic-gate break;
4977c478bd9Sstevel@tonic-gate case CKM_SHA_1:
4987c478bd9Sstevel@tonic-gate op_data_len += sizeof (SHA1_CTX);
4997c478bd9Sstevel@tonic-gate break;
5007c478bd9Sstevel@tonic-gate default:
501588a1af0SAlexandr Nedvedicky rv = CKR_STATE_UNSAVEABLE;
502588a1af0SAlexandr Nedvedicky goto unlock_session;
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate if (pOperationState == NULL_PTR) {
5067c478bd9Sstevel@tonic-gate *pulOperationStateLen = op_data_len;
507588a1af0SAlexandr Nedvedicky goto unlock_session;
5087c478bd9Sstevel@tonic-gate } else {
5097c478bd9Sstevel@tonic-gate if (*pulOperationStateLen < op_data_len) {
5107c478bd9Sstevel@tonic-gate *pulOperationStateLen = op_data_len;
511588a1af0SAlexandr Nedvedicky rv = CKR_BUFFER_TOO_SMALL;
512588a1af0SAlexandr Nedvedicky goto unlock_session;
5137c478bd9Sstevel@tonic-gate }
5147c478bd9Sstevel@tonic-gate }
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate /* Save internal_op_state_t */
517588a1af0SAlexandr Nedvedicky /* LINTED E_BAD_PTR_CAST_ALIGN */
518588a1af0SAlexandr Nedvedicky p_op_state = (internal_op_state_t *)pOperationState;
519588a1af0SAlexandr Nedvedicky p_op_state->op_len = op_data_len;
520588a1af0SAlexandr Nedvedicky p_op_state->op_active = DIGEST_OP;
521588a1af0SAlexandr Nedvedicky p_op_state->op_session_state = session_p->state;
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate /* Save crypto_active_op_t */
5247c478bd9Sstevel@tonic-gate (void) memcpy((CK_BYTE *)pOperationState +
5257c478bd9Sstevel@tonic-gate sizeof (internal_op_state_t),
5267c478bd9Sstevel@tonic-gate &session_p->digest,
5277c478bd9Sstevel@tonic-gate sizeof (crypto_active_op_t));
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate switch (session_p->digest.mech.mechanism) {
5307c478bd9Sstevel@tonic-gate case CKM_MD5:
5317c478bd9Sstevel@tonic-gate /* Save MD5_CTX for the active digest operation */
5327c478bd9Sstevel@tonic-gate (void) memcpy((CK_BYTE *)pOperationState +
5337c478bd9Sstevel@tonic-gate sizeof (internal_op_state_t) +
5347c478bd9Sstevel@tonic-gate sizeof (crypto_active_op_t),
5357c478bd9Sstevel@tonic-gate session_p->digest.context,
5367c478bd9Sstevel@tonic-gate sizeof (MD5_CTX));
5377c478bd9Sstevel@tonic-gate break;
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate case CKM_SHA_1:
5407c478bd9Sstevel@tonic-gate /* Save SHA1_CTX for the active digest operation */
5417c478bd9Sstevel@tonic-gate (void) memcpy((CK_BYTE *)pOperationState +
5427c478bd9Sstevel@tonic-gate sizeof (internal_op_state_t) +
5437c478bd9Sstevel@tonic-gate sizeof (crypto_active_op_t),
5447c478bd9Sstevel@tonic-gate session_p->digest.context,
5457c478bd9Sstevel@tonic-gate sizeof (SHA1_CTX));
5467c478bd9Sstevel@tonic-gate break;
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate default:
549588a1af0SAlexandr Nedvedicky rv = CKR_STATE_UNSAVEABLE;
5507c478bd9Sstevel@tonic-gate }
551d288ba74SAnthony Scarpino } else {
552d288ba74SAnthony Scarpino rv = CKR_OPERATION_NOT_INITIALIZED;
553d288ba74SAnthony Scarpino goto unlock_session;
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate
5567c478bd9Sstevel@tonic-gate *pulOperationStateLen = op_data_len;
5577c478bd9Sstevel@tonic-gate
558588a1af0SAlexandr Nedvedicky unlock_session:
559588a1af0SAlexandr Nedvedicky (void) pthread_mutex_unlock(&session_p->session_mutex);
560588a1af0SAlexandr Nedvedicky
561588a1af0SAlexandr Nedvedicky return (rv);
562588a1af0SAlexandr Nedvedicky
563588a1af0SAlexandr Nedvedicky }
564588a1af0SAlexandr Nedvedicky
alloc_digest(CK_ULONG mech)565588a1af0SAlexandr Nedvedicky static CK_BYTE_PTR alloc_digest(CK_ULONG mech)
566588a1af0SAlexandr Nedvedicky {
567588a1af0SAlexandr Nedvedicky CK_BYTE_PTR ret_val;
568588a1af0SAlexandr Nedvedicky
569588a1af0SAlexandr Nedvedicky switch (mech) {
570588a1af0SAlexandr Nedvedicky case CKM_MD5:
571588a1af0SAlexandr Nedvedicky ret_val = (CK_BYTE_PTR) malloc(sizeof (MD5_CTX));
572588a1af0SAlexandr Nedvedicky break;
573588a1af0SAlexandr Nedvedicky case CKM_SHA_1:
574588a1af0SAlexandr Nedvedicky ret_val = (CK_BYTE_PTR) malloc(sizeof (SHA1_CTX));
575588a1af0SAlexandr Nedvedicky break;
576588a1af0SAlexandr Nedvedicky default: ret_val = NULL;
577588a1af0SAlexandr Nedvedicky }
578588a1af0SAlexandr Nedvedicky
579588a1af0SAlexandr Nedvedicky return (ret_val);
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate /*
5837c478bd9Sstevel@tonic-gate * The format to be restored from the pOperationState will be:
5847c478bd9Sstevel@tonic-gate * 1. internal_op_state_t
5857c478bd9Sstevel@tonic-gate * 2. crypto_active_op_t
5867c478bd9Sstevel@tonic-gate * 3. actual context of the saved operation
5877c478bd9Sstevel@tonic-gate */
5887c478bd9Sstevel@tonic-gate CK_RV
soft_set_operationstate(soft_session_t * session_p,CK_BYTE_PTR pOperationState,CK_ULONG ulOperationStateLen,CK_OBJECT_HANDLE hEncryptionKey,CK_OBJECT_HANDLE hAuthenticationKey)5897c478bd9Sstevel@tonic-gate soft_set_operationstate(soft_session_t *session_p, CK_BYTE_PTR pOperationState,
5907c478bd9Sstevel@tonic-gate CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey,
5917c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hAuthenticationKey)
5927c478bd9Sstevel@tonic-gate {
5937c478bd9Sstevel@tonic-gate
594588a1af0SAlexandr Nedvedicky CK_RV rv = CKR_OK;
595588a1af0SAlexandr Nedvedicky internal_op_state_t *p_op_state;
596588a1af0SAlexandr Nedvedicky crypto_active_op_t *p_active_op;
5977c478bd9Sstevel@tonic-gate CK_ULONG offset = 0;
598588a1af0SAlexandr Nedvedicky CK_ULONG mech;
599588a1af0SAlexandr Nedvedicky void *free_it = NULL;
6007c478bd9Sstevel@tonic-gate
601588a1af0SAlexandr Nedvedicky /* LINTED E_BAD_PTR_CAST_ALIGN */
602588a1af0SAlexandr Nedvedicky p_op_state = (internal_op_state_t *)pOperationState;
6037c478bd9Sstevel@tonic-gate
604588a1af0SAlexandr Nedvedicky if (p_op_state->op_len != ulOperationStateLen) {
6057c478bd9Sstevel@tonic-gate /*
6067c478bd9Sstevel@tonic-gate * The supplied data length does not match with
6077c478bd9Sstevel@tonic-gate * the saved data length.
6087c478bd9Sstevel@tonic-gate */
6097c478bd9Sstevel@tonic-gate return (CKR_SAVED_STATE_INVALID);
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate
612588a1af0SAlexandr Nedvedicky if (p_op_state->op_active != DIGEST_OP)
613588a1af0SAlexandr Nedvedicky return (CKR_SAVED_STATE_INVALID);
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate if ((hAuthenticationKey != 0) || (hEncryptionKey != 0)) {
6167c478bd9Sstevel@tonic-gate return (CKR_KEY_NOT_NEEDED);
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate
619588a1af0SAlexandr Nedvedicky offset = sizeof (internal_op_state_t);
620588a1af0SAlexandr Nedvedicky /* LINTED E_BAD_PTR_CAST_ALIGN */
621588a1af0SAlexandr Nedvedicky p_active_op = (crypto_active_op_t *)(pOperationState + offset);
622588a1af0SAlexandr Nedvedicky offset += sizeof (crypto_active_op_t);
623588a1af0SAlexandr Nedvedicky mech = p_active_op->mech.mechanism;
6247c478bd9Sstevel@tonic-gate
625588a1af0SAlexandr Nedvedicky if (!DIGEST_MECH_OK(mech)) {
6267c478bd9Sstevel@tonic-gate return (CKR_SAVED_STATE_INVALID);
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate /*
630588a1af0SAlexandr Nedvedicky * We may reuse digest.context in case the digest mechanisms (the one,
631588a1af0SAlexandr Nedvedicky * which belongs to session and the operation, which we are restoring)
632588a1af0SAlexandr Nedvedicky * are the same. If digest mechanisms are different, we have to release
633588a1af0SAlexandr Nedvedicky * the digest context, which belongs to session and allocate a new one.
6347c478bd9Sstevel@tonic-gate */
6357c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
636588a1af0SAlexandr Nedvedicky
637588a1af0SAlexandr Nedvedicky if (session_p->state != p_op_state->op_session_state) {
638588a1af0SAlexandr Nedvedicky /*
639588a1af0SAlexandr Nedvedicky * The supplied session state does not match with
640588a1af0SAlexandr Nedvedicky * the saved session state.
641588a1af0SAlexandr Nedvedicky */
642588a1af0SAlexandr Nedvedicky rv = CKR_SAVED_STATE_INVALID;
643588a1af0SAlexandr Nedvedicky goto unlock_session;
644588a1af0SAlexandr Nedvedicky }
645588a1af0SAlexandr Nedvedicky
646588a1af0SAlexandr Nedvedicky if (session_p->digest.context &&
647588a1af0SAlexandr Nedvedicky (session_p->digest.mech.mechanism != mech)) {
648588a1af0SAlexandr Nedvedicky free_it = session_p->digest.context;
649588a1af0SAlexandr Nedvedicky session_p->digest.context = NULL;
650588a1af0SAlexandr Nedvedicky }
6517c478bd9Sstevel@tonic-gate
6527c478bd9Sstevel@tonic-gate if (session_p->digest.context == NULL) {
653588a1af0SAlexandr Nedvedicky session_p->digest.context = alloc_digest(mech);
654588a1af0SAlexandr Nedvedicky
655588a1af0SAlexandr Nedvedicky if (session_p->digest.context == NULL) {
656588a1af0SAlexandr Nedvedicky /*
657588a1af0SAlexandr Nedvedicky * put back original context into session in case
658588a1af0SAlexandr Nedvedicky * allocation of new context has failed.
659588a1af0SAlexandr Nedvedicky */
660588a1af0SAlexandr Nedvedicky session_p->digest.context = free_it;
661588a1af0SAlexandr Nedvedicky free_it = NULL;
662588a1af0SAlexandr Nedvedicky rv = CKR_HOST_MEMORY;
663588a1af0SAlexandr Nedvedicky goto unlock_session;
6647c478bd9Sstevel@tonic-gate }
6657c478bd9Sstevel@tonic-gate }
6667c478bd9Sstevel@tonic-gate
667588a1af0SAlexandr Nedvedicky /* Restore crypto_active_op_t */
668588a1af0SAlexandr Nedvedicky session_p->digest.mech.mechanism = mech;
669588a1af0SAlexandr Nedvedicky session_p->digest.flags = p_active_op->flags;
670588a1af0SAlexandr Nedvedicky
671588a1af0SAlexandr Nedvedicky switch (mech) {
672588a1af0SAlexandr Nedvedicky case CKM_MD5:
6737c478bd9Sstevel@tonic-gate /* Restore MD5_CTX from the saved digest operation */
6747c478bd9Sstevel@tonic-gate (void) memcpy((CK_BYTE *)session_p->digest.context,
6757c478bd9Sstevel@tonic-gate (CK_BYTE *)pOperationState + offset,
6767c478bd9Sstevel@tonic-gate sizeof (MD5_CTX));
6777c478bd9Sstevel@tonic-gate break;
6787c478bd9Sstevel@tonic-gate case CKM_SHA_1:
6797c478bd9Sstevel@tonic-gate /* Restore SHA1_CTX from the saved digest operation */
6807c478bd9Sstevel@tonic-gate (void) memcpy((CK_BYTE *)session_p->digest.context,
6817c478bd9Sstevel@tonic-gate (CK_BYTE *)pOperationState + offset,
6827c478bd9Sstevel@tonic-gate sizeof (SHA1_CTX));
683588a1af0SAlexandr Nedvedicky break;
684588a1af0SAlexandr Nedvedicky default:
685588a1af0SAlexandr Nedvedicky /* never reached */
686588a1af0SAlexandr Nedvedicky rv = CKR_SAVED_STATE_INVALID;
687588a1af0SAlexandr Nedvedicky }
6887c478bd9Sstevel@tonic-gate
689588a1af0SAlexandr Nedvedicky unlock_session:
6907c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
6917c478bd9Sstevel@tonic-gate
692588a1af0SAlexandr Nedvedicky if (free_it != NULL)
693588a1af0SAlexandr Nedvedicky free(free_it);
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate return (rv);
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate CK_RV
soft_login(CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen)7007c478bd9Sstevel@tonic-gate soft_login(CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
7017c478bd9Sstevel@tonic-gate {
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate /*
7047c478bd9Sstevel@tonic-gate * Authenticate the input PIN.
7057c478bd9Sstevel@tonic-gate */
7067c478bd9Sstevel@tonic-gate return (soft_verify_pin(pPin, ulPinLen));
7077c478bd9Sstevel@tonic-gate
7087c478bd9Sstevel@tonic-gate }
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate void
soft_logout(void)7117c478bd9Sstevel@tonic-gate soft_logout(void)
7127c478bd9Sstevel@tonic-gate {
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate /*
7157c478bd9Sstevel@tonic-gate * Delete all the private token objects from the "token_object_list".
7167c478bd9Sstevel@tonic-gate */
7177c478bd9Sstevel@tonic-gate soft_delete_all_in_core_token_objects(PRIVATE_TOKEN);
7187c478bd9Sstevel@tonic-gate return;
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate }
7214daf2311Srupertk
7224daf2311Srupertk void
soft_acquire_all_session_mutexes(soft_session_t * session_p)723*83140133SZdenek Kotala soft_acquire_all_session_mutexes(soft_session_t *session_p)
7244daf2311Srupertk {
7254daf2311Srupertk /* Iterate through sessions acquiring all mutexes */
7264daf2311Srupertk while (session_p) {
7271f49a79aSZdenek Kotala soft_object_t *object_p;
7281f49a79aSZdenek Kotala
7294daf2311Srupertk (void) pthread_mutex_lock(&session_p->session_mutex);
7301f49a79aSZdenek Kotala object_p = session_p->object_list;
7311f49a79aSZdenek Kotala
7321f49a79aSZdenek Kotala /* Lock also all objects related to session */
7331f49a79aSZdenek Kotala while (object_p) {
7341f49a79aSZdenek Kotala (void) pthread_mutex_lock(&object_p->object_mutex);
7351f49a79aSZdenek Kotala object_p = object_p->next;
7361f49a79aSZdenek Kotala }
7374daf2311Srupertk session_p = session_p->next;
7384daf2311Srupertk }
7394daf2311Srupertk }
7404daf2311Srupertk
7414daf2311Srupertk void
soft_release_all_session_mutexes(soft_session_t * session_p)742*83140133SZdenek Kotala soft_release_all_session_mutexes(soft_session_t *session_p)
7434daf2311Srupertk {
7444daf2311Srupertk /* Iterate through sessions releasing all mutexes */
7454daf2311Srupertk while (session_p) {
7464daf2311Srupertk /*
7474daf2311Srupertk * N.B. Ideally, should go in opposite order to guarantee
7484daf2311Srupertk * lock-order requirements but there is no tail pointer.
7494daf2311Srupertk */
7501f49a79aSZdenek Kotala soft_object_t *object_p = session_p->object_list;
7511f49a79aSZdenek Kotala
7521f49a79aSZdenek Kotala /* Unlock also all objects related to session */
7531f49a79aSZdenek Kotala while (object_p) {
7541f49a79aSZdenek Kotala (void) pthread_mutex_unlock(&object_p->object_mutex);
7551f49a79aSZdenek Kotala object_p = object_p->next;
7561f49a79aSZdenek Kotala }
7574daf2311Srupertk (void) pthread_mutex_unlock(&session_p->session_mutex);
7584daf2311Srupertk session_p = session_p->next;
7594daf2311Srupertk }
7604daf2311Srupertk }
761