/*
* 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
*/
/*
*/
/*
* Session Management Functions
* (as defined in PKCS#11 spec section 11.6)
*/
#include <string.h>
#include "metaGlobal.h"
extern meta_session_t *meta_sessionlist_head;
extern CK_ULONG num_meta_sessions;
extern CK_ULONG num_rw_meta_sessions;
/*
* meta_OpenSession
*
* NOTES:
* 1) The pApplication and Notify args are not used, as the metaslot does not
* support application callbacks.
* 2) the slotID argument is not checked or used because this function
* is only called from the framework.
*/
/* ARGSUSED */
{
if (!metaslot_enabled) {
return (CKR_SLOT_ID_INVALID);
}
return (CKR_ARGUMENTS_BAD);
}
/* Check for any unknown flags. */
return (CKR_ARGUMENTS_BAD);
}
if (!(flags & CKF_SERIAL_SESSION)) {
return (CKR_SESSION_PARALLEL_NOT_SUPPORTED);
}
(flags & CKF_RW_SESSION)) {
return (CKR_TOKEN_WRITE_PROTECTED);
}
return (rv);
return (rv);
}
if (flags & CKF_RW_SESSION) {
}
return (CKR_OK);
}
/*
* meta_CloseSession
*
*/
{
return (rv);
/* save info about session flags before they are destroyed */
if (flags & CKF_RW_SESSION) {
}
return (rv);
}
/*
* meta_CloseAllSessions
*
* This is a simple loop that closes the sessionlist head (resulting in a
* new list head) until the list is empty.
*
*/
{
if (!metaslot_enabled) {
return (CKR_SLOT_ID_INVALID);
}
if (slotID != METASLOT_SLOTID)
return (CKR_SLOT_ID_INVALID);
(void) pthread_rwlock_wrlock(&meta_sessionlist_lock);
/*NOTREACHED*/
(void) pthread_rwlock_unlock(&meta_sessionlist_lock);
return (CKR_FUNCTION_FAILED);
}
}
(void) pthread_rwlock_unlock(&meta_sessionlist_lock);
/* All open sessions should be closed, just reset the variables */
num_meta_sessions = 0;
num_rw_meta_sessions = 0;
return (CKR_OK);
}
/*
* meta_GetSessionInfo
*
*/
{
return (CKR_ARGUMENTS_BAD);
return (rv);
if (metaslot_logged_in()) {
} else {
}
} else {
} else {
}
}
pInfo->ulDeviceError = 0;
return (CKR_OK);
}
{
*out_length = sizeof (meta_opstate_t);
*out_length += length;
}
return (rv);
}
/*
* meta_GetOperationState
*
*/
{
if (pulOperationStateLen == NULL)
return (CKR_ARGUMENTS_BAD);
return (rv);
/*
* If no operation is active, then bail out.
*/
goto endgetopstate;
}
/*
* If the caller did not give an OpState buffer,
* shortcut and just return the size needed to hold
* a metaslot OpState record later.
* The actual size of the returned state will be the
* sizeof(meta_opstate_t) + SIZE (op1 state),
* so we have to get the size of
* the operation states now.
*/
if (pOperationState == NULL) {
return (rv);
}
/*
* To be here, the caller must have supplied an
* already initialized meta_opstate_t pointer.
* Use it to get the real state info from the operation(s).
*
* The format of the Metaslot Opstate record:
* {
* struct metaopstate
* [ op1 state data ]
* }
*/
/*
* If the buffer is not even big enough for the metaslot
* opstate data, return error and set the returned
* state length to indicate the minimum needed.
*/
if (*pulOperationStateLen < sizeof (meta_opstate_t)) {
/*
* Remap the error so the caller knows that they
* used an invalid buffer size in the first place.
*/
goto endgetopstate;
}
sizeof (meta_opstate_t);
pOperationState + sizeof (meta_opstate_t),
if (rv == CKR_BUFFER_TOO_SMALL) {
/*
* This should not happen, but if it does,
* recalculate the entire size needed
* and return the error.
*/
}
goto endgetopstate;
} else {
statelen = sizeof (meta_opstate_t) +
if (*pulOperationStateLen < statelen) {
goto endgetopstate;
}
/* init operation was deferred. Save the mech and param */
/* Append parameter after meta_opstate_t */
(void) memcpy(pOperationState +
sizeof (meta_opstate_t),
}
}
sizeof (meta_opstate_t));
*pulOperationStateLen = sizeof (meta_opstate_t) +
}
return (rv);
}
static CK_RV
struct opstate_data *state,
{
return (rv);
}
}
return (rv);
}
}
/*
* Check to see if the keys are needed to restore the
* state on the first operation.
*/
/*
* If the operation did not need a key, try again.
*/
if (rv == CKR_KEY_NOT_NEEDED) {
/*
* Strange case... If the first try returned
* KEY_NOT_NEEDED, and this one returns KEY_NEEDED,
* we want to remap the return so the caller sees
* the original "CKR_KEY_NOT_NEEDED" return value.
* This ensures that a correct caller will retry
* without the unnecessary key argument and this
* 2nd attempt will not happen again.
*/
if (rv == CKR_KEY_NEEDED) {
}
}
return (rv);
}
/*
* meta_SetOperationState
*
*/
{
/*
* Make sure the opstate info buffer is big enough to be valid.
*/
if (ulOperationStateLen < sizeof (meta_opstate_t) ||
pOperationState == NULL)
return (CKR_ARGUMENTS_BAD);
/* Copy the opstate info into the structure */
/* verify that a metaslot operation state was supplied */
return (CKR_SAVED_STATE_INVALID);
/*
* Now, check the size again to make sure the "real" state
* data is present. Length of state provided must be exact.
*/
if (ulOperationStateLen != (sizeof (meta_opstate_t) +
return (CKR_SAVED_STATE_INVALID);
return (rv);
if (hEncryptionKey != CK_INVALID_HANDLE) {
goto cleanup;
}
if (hAuthenticationKey != CK_INVALID_HANDLE) {
goto cleanup;
}
/*
* If there is an ongoing operation associated with this session,
* clean the session.
*/
}
/*
* If the current session and the saved
* operation state shares the same slot,
* use current session.
*/
} else {
/*
* If the saved state has different slot than
* the current slot, release this session and
* acquire the new session.
*/
}
}
if (slot_session == NULL) {
goto cleanup;
}
goto cleanup;
}
pOperationState + sizeof (meta_opstate_t));
FALSE);
goto cleanup;
}
} else {
/* init operation was deferred. Restore the state accordingly */
goto cleanup;
}
goto cleanup;
}
pOperationState + sizeof (meta_opstate_t),
}
if (meta_enc_key != NULL) {
} else if (meta_auth_key != NULL) {
}
}
if (meta_enc_key != NULL)
if (meta_auth_key != NULL)
return (rv);
}
/*
* meta_Login
*
* This allows the user to login to the object token. The metaslot itself
* does not have any kind of PIN.
*
*/
{
return (rv);
if (metaslot_logged_in()) {
goto finish;
}
/* Note: CKU_SO is not supported. */
goto finish;
}
goto finish;
goto finish;
}
/*
* Note:
*
* For some slots (eg: the pkcs11_softtoken.so), C_Login()
* returning OK don't mean that the login is truly
* successful. For pkcs11_softtoken.so, the CKF_USER_PIN_TO_BE_CHANGED
* is set to indicate that the pin needs to be changed, and
* the login is not really successful. We will check
* that flag for this special condition. Checking for
* this flag shouldn't be harmful for other slots that doesn't
* behave like pkcs11_softtoken.so.
*/
goto finish;
}
}
if (login_session)
return (rv);
}
/*
* meta_Logout
*
*/
{
return (rv);
if (!metaslot_logged_in()) {
goto finish;
}
goto finish;
/* If the C_Logout fails, just ignore the error. */
if (logout_session)
return (rv);
}