softSessionUtil.c revision d288ba7491829a622697c947c3f1a30aec18c133
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <md5.h>
#include <pthread.h>
#include <syslog.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <security/cryptoki.h>
#include "softGlobal.h"
#include "softSession.h"
#include "softObject.h"
#include "softOps.h"
#include "softKeystore.h"
#include "softKeystoreUtil.h"
/*
* Delete all the sessions. First, obtain the global session
* list lock. Then start to delete one session at a time.
* Release the global session list lock before returning to
* caller.
*/
{
/* Acquire the global session list lock */
(void) pthread_mutex_lock(&soft_sessionlist_mutex);
/* Delete all the sessions in the session list */
while (session_p) {
/*
* Delete a session by calling soft_delete_session()
* with a session pointer and a boolean arguments.
* Boolean value TRUE is used to indicate that the
* caller holds the lock on the global session list.
*
*/
/* Record the very first error code */
}
}
/* No session left */
/* Release the global session list lock */
(void) pthread_mutex_unlock(&soft_sessionlist_mutex);
return (rv);
}
/*
* Create a new session struct, and add it to the session linked list.
*
* This function will acquire the global session list lock, and release
* it after adding the session to the session linked list.
*/
{
/* Allocate a new session struct */
return (CKR_HOST_MEMORY);
}
new_sp->ses_refcnt = 0;
new_sp->ses_close_sync = 0;
(void) pthread_mutex_lock(&soft_giant_mutex);
if (soft_slot.authenticated) {
(void) pthread_mutex_unlock(&soft_giant_mutex);
if (flags & CKF_RW_SESSION) {
} else {
}
} else {
(void) pthread_mutex_unlock(&soft_giant_mutex);
if (flags & CKF_RW_SESSION) {
} else {
}
}
/* Initialize the lock for the newly created session */
return (CKR_CANT_LOCK);
}
/* Acquire the global session list lock */
(void) pthread_mutex_lock(&soft_sessionlist_mutex);
/* Insert the new session in front of session list */
if (soft_session_list == NULL) {
} else {
}
/* Type casting the address of a session struct to a session handle */
if (flags & CKF_RW_SESSION)
if (soft_session_cnt == 1)
/*
* This is the first session to be opened, so we can set
* validate the public token objects in token list now.
*/
/* Release the global session list lock */
(void) pthread_mutex_unlock(&soft_sessionlist_mutex);
return (CKR_OK);
}
/*
* This function adds the to-be-freed session to a linked list.
* When the number of sessions queued in the linked list reaches the
* maximum threshold MAX_SES_TO_BE_FREED, it will free the first
* session (FIFO) in the list.
*/
void
{
/* Add the newly deleted session at the end of the list */
} else {
}
/*
* Free the first session in the list only if
* the total count reaches maximum threshold.
*/
}
}
/*
* Delete a session:
* - Remove the session from the session linked list.
* Holding the lock on the global session list is needed to do this.
* - Release all the objects created by the session.
*
* The boolean argument lock_held is used to indicate that whether
* the caller of this function holds the lock on the global session
* list or not.
* - When called by soft_delete_all_sessions(), which is called by
* C_Finalize() or C_CloseAllSessions() -- the lock_held = TRUE.
* - When called by C_CloseSession() -- the lock_held = FALSE.
*
* When the caller does not hold the lock on the global session
* list, this function will acquire that lock in order to proceed,
* and also release that lock before returning to caller.
*/
{
/*
* Check to see if the caller holds the lock on the global
* session list. If not, we need to acquire that lock in
* order to proceed.
*/
if (!lock_held) {
/* Acquire the global session list lock */
(void) pthread_mutex_lock(&soft_sessionlist_mutex);
}
/*
* Remove the session from the session linked list first.
*/
if (soft_session_list == session_p) {
/* Session is the first one in the list */
} else {
/* Session is the only one in the list */
}
} else {
/* Session is not the first one in the list */
/* Session is in the middle of the list */
} else {
/* Session is the last one in the list */
}
}
if (!lock_held) {
/*
* If the global session list lock is obtained by
* this function, then release that lock after
* removing the session from session linked list.
* We want the releasing of the objects of the
* session, and freeing of the session itself to
* be done without holding the global session list
* lock.
*/
(void) pthread_mutex_unlock(&soft_sessionlist_mutex);
}
/* Acquire the individual session lock */
/*
* Make sure another thread hasn't freed the session.
*/
return (CKR_OK);
}
/*
* The deletion of a session must be blocked when the session
* reference count is not zero. This means if any session related
* operation starts prior to the session close operation gets in,
* the session closing thread must wait for the non-closing
* operation to be completed before it can proceed the close
* operation.
*
* Unless we are being forced to shut everything down, this only
* happens if the libraries _fini() is running not of someone
* explicitly called C_Finalize().
*/
if (force)
session_p->ses_refcnt = 0;
while (session_p->ses_refcnt != 0) {
/*
* We set the SESSION_REFCNT_WAITING flag before we put
* this closing thread in a wait state, so other non-closing
* operation thread will signal to wake it up only when
* the session reference count becomes zero and this flag
* is set.
*/
}
/*
* Remove all the objects created in this session.
*/
/*
* Mark session as no longer valid. This can only be done after all
* objects created by this session are free'd since the marker is
* still needed in the process of removing objects from the session.
*/
session_p->magic_marker = 0;
/* In case application did not call Final */
/*
* 1st B_TRUE: encrypt
* 2nd B_TRUE: caller is holding session_mutex.
*/
/*
* 1st B_FALSE: decrypt
* 2nd B_TRUE: caller is holding session_mutex.
*/
}
/* Reset SESSION_IS_CLOSIN flag. */
/* Destroy the individual session lock */
/* Delay freeing the session */
return (CKR_OK);
}
/*
* This function is used to type cast a session handle to a pointer to
* the session struct. Also, it does the following things:
* 1) Check to see if the session struct is tagged with a session
* magic number. This is to detect when an application passes
* a bogus session pointer.
* 2) Acquire the lock on the designated session.
* 3) Check to see if the session is in the closing state that another
* thread is performing.
* 4) Increment the session reference count by one. This is to prevent
* this session from being closed by other thread.
* 5) Release the lock held on the designated session.
*/
{
/*
* No need to hold soft_sessionlist_mutex as we are
* just reading the value and 32-bit reads are atomic.
*/
if (all_sessions_closing) {
return (CKR_SESSION_CLOSED);
}
return (CKR_SESSION_HANDLE_INVALID);
}
return (CKR_SESSION_CLOSED);
}
/* Increment session ref count. */
sp->ses_refcnt++;
return (CKR_OK);
}
/*
* The format to be saved in the pOperationState will be:
* 1. internal_op_state_t
* 2. crypto_active_op_t
* 3. actual context of the active operation
*/
{
CK_ULONG op_data_len = 0;
if (pulOperationStateLen == NULL)
return (CKR_ARGUMENTS_BAD);
/* Check to see if encrypt operation is active. */
goto unlock_session;
}
/* Check to see if decrypt operation is active. */
goto unlock_session;
}
/* Check to see if sign operation is active. */
goto unlock_session;
}
/* Check to see if verify operation is active. */
goto unlock_session;
}
/* Check to see if digest operation is active. */
op_data_len = sizeof (internal_op_state_t) +
sizeof (crypto_active_op_t);
case CKM_MD5:
op_data_len += sizeof (MD5_CTX);
break;
case CKM_SHA_1:
op_data_len += sizeof (SHA1_CTX);
break;
default:
goto unlock_session;
}
if (pOperationState == NULL_PTR) {
goto unlock_session;
} else {
if (*pulOperationStateLen < op_data_len) {
goto unlock_session;
}
}
/* Save internal_op_state_t */
/* LINTED E_BAD_PTR_CAST_ALIGN */
/* Save crypto_active_op_t */
sizeof (internal_op_state_t),
sizeof (crypto_active_op_t));
case CKM_MD5:
/* Save MD5_CTX for the active digest operation */
sizeof (internal_op_state_t) +
sizeof (crypto_active_op_t),
sizeof (MD5_CTX));
break;
case CKM_SHA_1:
/* Save SHA1_CTX for the active digest operation */
sizeof (internal_op_state_t) +
sizeof (crypto_active_op_t),
sizeof (SHA1_CTX));
break;
default:
}
} else {
goto unlock_session;
}
return (rv);
}
{
switch (mech) {
case CKM_MD5:
break;
case CKM_SHA_1:
break;
}
return (ret_val);
}
/*
* The format to be restored from the pOperationState will be:
* 1. internal_op_state_t
* 2. crypto_active_op_t
* 3. actual context of the saved operation
*/
{
/* LINTED E_BAD_PTR_CAST_ALIGN */
/*
* The supplied data length does not match with
* the saved data length.
*/
return (CKR_SAVED_STATE_INVALID);
}
return (CKR_SAVED_STATE_INVALID);
if ((hAuthenticationKey != 0) || (hEncryptionKey != 0)) {
return (CKR_KEY_NOT_NEEDED);
}
offset = sizeof (internal_op_state_t);
/* LINTED E_BAD_PTR_CAST_ALIGN */
offset += sizeof (crypto_active_op_t);
if (!DIGEST_MECH_OK(mech)) {
return (CKR_SAVED_STATE_INVALID);
}
/*
* We may reuse digest.context in case the digest mechanisms (the one,
* which belongs to session and the operation, which we are restoring)
* are the same. If digest mechanisms are different, we have to release
* the digest context, which belongs to session and allocate a new one.
*/
/*
* The supplied session state does not match with
* the saved session state.
*/
goto unlock_session;
}
}
/*
* put back original context into session in case
* allocation of new context has failed.
*/
goto unlock_session;
}
}
/* Restore crypto_active_op_t */
switch (mech) {
case CKM_MD5:
/* Restore MD5_CTX from the saved digest operation */
sizeof (MD5_CTX));
break;
case CKM_SHA_1:
/* Restore SHA1_CTX from the saved digest operation */
sizeof (SHA1_CTX));
break;
default:
/* never reached */
}
return (rv);
}
{
/*
* Authenticate the input PIN.
*/
}
void
soft_logout(void)
{
/*
* Delete all the private token objects from the "token_object_list".
*/
return;
}
void
{
/* Iterate through sessions acquiring all mutexes */
while (session_p) {
}
}
void
{
/* Iterate through sessions releasing all mutexes */
while (session_p) {
/*
* N.B. Ideally, should go in opposite order to guarantee
* lock-order requirements but there is no tail pointer.
*/
}
}