/*
* The Initial Developer of the Original Code is International
* Business Machines Corporation. Portions created by IBM
* Corporation are Copyright (C) 2005 International Business
* Machines Corporation. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the Common Public License as published by
* IBM Corporation; either version 1 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Common Public License for more details.
*
* You should have received a copy of the Common Public License
* along with this program; if not, a copy can be viewed at
* http://www.opensource.org/licenses/cpl1.0.php.
*/
/* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */
/*
* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
*/
#include <pwd.h>
#include <grp.h>
#include "tpmtok_int.h"
#include "tpmtok_defs.h"
extern pthread_rwlock_t obj_list_rw_mutex;
void SC_SetFunctionList(void);
struct ST_FCN_LIST function_list;
int debugfile = 0;
pid_t initedpid = 0; // for initialized pid
CK_C_INITIALIZE_ARGS cinit_args = {NULL, NULL, NULL, NULL, 0, NULL};
extern void stlogterm();
extern void stloginit();
extern void stlogit2(int type, char *fmt, ...);
extern void stlogit(char *fmt, ...);
CK_BBOOL
st_Initialized()
{
return (initedpid == getpid());
}
void
Fork_Initializer(void)
{
stlogterm();
stloginit(); // Initialize Logging so we can capture EVERYTHING
// Force logout. This cleans out the private session and list
// and cleans out the private object map
(void) session_mgr_logout_all();
// Clean out the public object map
// First parm is no longer used..
(void) object_mgr_purge_map((SESSION *)0xFFFF, PUBLIC);
(void) object_mgr_purge_map((SESSION *)0xFFFF, PRIVATE);
// This should clear the entire session list out
(void) session_mgr_close_all_sessions();
next_session_handle = 1;
next_object_handle = 1;
while (priv_token_obj_list) {
priv_token_obj_list = dlist_remove_node(priv_token_obj_list,
priv_token_obj_list);
}
while (publ_token_obj_list) {
publ_token_obj_list = dlist_remove_node(publ_token_obj_list,
publ_token_obj_list);
}
}
#define SESSION_HANDLE sSession.sessionh
#define SESS_SET \
CK_SESSION_HANDLE hSession = sSession.sessionh;
static CK_RV
validate_mechanism(CK_MECHANISM_PTR pMechanism)
{
CK_ULONG i;
for (i = 0; i < mech_list_len; i++) {
if (pMechanism->mechanism == mech_list[i].mech_type) {
return (CKR_OK);
}
}
return (CKR_MECHANISM_INVALID);
}
#define VALID_MECH(p) \
if (validate_mechanism(p) != CKR_OK) { \
rc = CKR_MECHANISM_INVALID; \
goto done; \
}
CK_RV
ST_Initialize(void *FunctionList,
CK_SLOT_ID SlotNumber,
unsigned char *Correlator)
{
CK_RV rc = CKR_OK;
struct ST_FCN_LIST *flist = (struct ST_FCN_LIST *)FunctionList;
TSS_HCONTEXT hContext = 0;
stlogterm();
stloginit();
if (st_Initialized() == TRUE) {
return (CKR_OK);
}
// assume that the upper API prevents multiple calls of initialize
// since that only happens on C_Initialize and that is the
// responsibility of the upper layer..
initialized = FALSE;
// check for other completing this before creating mutexes...
// make sure that the same process tried to to the init...
// thread issues should be caught up above...
if (st_Initialized() == TRUE) {
goto done;
}
Fork_Initializer();
(void) pthread_mutex_init(&pkcs_mutex, NULL);
(void) pthread_mutex_init(&obj_list_mutex, NULL);
(void) pthread_rwlock_init(&obj_list_rw_mutex, NULL);
(void) pthread_mutex_init(&sess_list_mutex, NULL);
(void) pthread_mutex_init(&login_mutex, NULL);
if (st_Initialized() == FALSE) {
if ((rc = attach_shm()) != CKR_OK)
goto done;
nv_token_data = &global_shm->nv_token_data;
initialized = TRUE;
initedpid = getpid();
SC_SetFunctionList();
if (flist != NULL)
(*flist) = function_list;
/* Always call the token_specific_init function.... */
rc = token_specific.t_init((char *)Correlator, SlotNumber,
&hContext);
if (rc != 0) {
/*
* The token could not be initialized, return OK, but
* present no slots.
*/
rc = CKR_OK;
goto done;
} else {
/* Mark the token as available */
global_shm->token_available = TRUE;
}
}
rc = load_token_data(hContext, nv_token_data);
if (rc != CKR_OK) {
goto done;
}
rc = load_public_token_objects();
if (rc != CKR_OK)
goto done;
(void) XProcLock(xproclock);
global_shm->publ_loaded = TRUE;
(void) XProcUnLock(xproclock);
init_slot_info(nv_token_data);
done:
if (hContext)
Tspi_Context_Close(hContext);
return (rc);
}
/*ARGSUSED*/
CK_RV
SC_Finalize(void *argptr)
{
CK_RV rc;
TSS_HCONTEXT hContext;
if (st_Initialized() == FALSE) {
return (CKR_CRYPTOKI_NOT_INITIALIZED);
}
rc = pthread_mutex_lock(&pkcs_mutex);
if (rc != CKR_OK) {
return (rc);
}
//
// If somebody else has taken care of things, leave...
//
if (st_Initialized() == FALSE) {
(void) pthread_mutex_unlock(&pkcs_mutex);
return (CKR_CRYPTOKI_NOT_INITIALIZED);
}
if (open_tss_context(&hContext) == 0) {
if (token_specific.t_final != NULL)
token_specific.t_final(hContext);
(void) session_mgr_close_all_sessions();
(void) object_mgr_purge_token_objects(hContext);
(void) Tspi_Context_Close(hContext);
}
(void) detach_shm();
initialized = FALSE;
rc = pthread_mutex_unlock(&pkcs_mutex);
if (rc != CKR_OK) {
return (rc);
}
return (CKR_OK);
}
/*ARGSUSED*/
CK_RV
SC_GetTokenInfo(CK_SLOT_ID sid, CK_TOKEN_INFO_PTR pInfo)
{
CK_RV rc = CKR_OK;
time_t now;
if (st_Initialized() == FALSE)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
if (pInfo == NULL)
return (CKR_FUNCTION_FAILED);
if (sid != TPM_SLOTID)
return (CKR_SLOT_ID_INVALID);
(void) memcpy(pInfo, &nv_token_data->token_info,
sizeof (CK_TOKEN_INFO));
now = time((time_t *)NULL);
(void) strftime((char *)pInfo->utcTime, 16, "%X", localtime(&now));
return (rc);
}
/*ARGSUSED*/
CK_RV
SC_GetMechanismList(
CK_SLOT_ID sid,
CK_MECHANISM_TYPE_PTR pMechList,
CK_ULONG_PTR count)
{
CK_ULONG i;
CK_RV rc = CKR_OK;
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (count == NULL) {
rc = CKR_FUNCTION_FAILED;
goto done;
}
if (sid != TPM_SLOTID) {
rc = CKR_SLOT_ID_INVALID;
goto done;
}
if (pMechList == NULL) {
*count = mech_list_len;
rc = CKR_OK;
goto done;
}
if (*count < mech_list_len) {
*count = mech_list_len;
rc = CKR_BUFFER_TOO_SMALL;
goto done;
}
for (i = 0; i < mech_list_len; i++)
pMechList[i] = mech_list[i].mech_type;
*count = mech_list_len;
rc = CKR_OK;
done:
if (debugfile) {
stlogit2(debugfile,
"% - 25s: rc = 0x%08x, # mechanisms: %d\n",
"C_GetMechanismList", rc, *count);
}
return (rc);
}
/*ARGSUSED*/
CK_RV
SC_GetMechanismInfo(
CK_SLOT_ID sid,
CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo)
{
CK_ULONG i;
CK_RV rc = CKR_OK;
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (pInfo == NULL) {
rc = CKR_FUNCTION_FAILED;
goto done;
}
if (sid != TPM_SLOTID) {
rc = CKR_SLOT_ID_INVALID;
goto done;
}
for (i = 0; i < mech_list_len; i++) {
if (mech_list[i].mech_type == type) {
(void) memcpy(pInfo, &mech_list[i].mech_info,
sizeof (CK_MECHANISM_INFO));
rc = CKR_OK;
goto done;
}
}
rc = CKR_MECHANISM_INVALID;
done:
if (debugfile) {
stlogit2(debugfile, "% - 25s: "
"rc = 0x%08x, mech type = 0x%08x\n",
"C_GetMechanismInfo", rc, type);
}
return (rc);
}
/*ARGSUSED*/
CK_RV
SC_InitToken(
CK_SLOT_ID sid,
CK_CHAR_PTR pPin,
CK_ULONG ulPinLen,
CK_CHAR_PTR pLabel)
{
CK_RV rc = CKR_OK;
CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
TOKEN_DATA newtoken;
TSS_HCONTEXT hContext = 0;
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (sid != TPM_SLOTID) {
rc = CKR_SLOT_ID_INVALID;
goto done;
}
if (! pPin || ! pLabel) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
if (open_tss_context(&hContext)) {
rc = CKR_FUNCTION_FAILED;
goto done;
}
rc = load_token_data(hContext, &newtoken);
if (rc != CKR_OK) {
goto done;
}
if (newtoken.token_info.flags & CKF_SO_PIN_LOCKED) {
rc = CKR_PIN_LOCKED;
goto done;
}
rc = token_specific.t_verify_so_pin(hContext, pPin, ulPinLen);
if (rc != CKR_OK) {
rc = CKR_PIN_INCORRECT;
goto done;
}
/*
* Before we reconstruct all the data, we should delete the
* token objects from the filesystem.
*
* Construct a string to delete the token objects.
*/
(void) object_mgr_destroy_token_objects(hContext);
(void) init_token_data(hContext, &newtoken);
(void) init_slot_info(&newtoken);
/* change the label */
(void) strncpy((char *)newtoken.token_info.label, (char *)pLabel,
sizeof (newtoken.token_info.label));
(void) memcpy(newtoken.so_pin_sha, hash_sha,
SHA1_DIGEST_LENGTH);
newtoken.token_info.flags |= CKF_TOKEN_INITIALIZED;
rc = save_token_data(&newtoken);
done:
if (hContext)
(void) Tspi_Context_Close(hContext);
return (rc);
}
CK_RV
SC_InitPIN(
ST_SESSION_HANDLE sSession,
CK_CHAR_PTR pPin,
CK_ULONG ulPinLen)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
CK_FLAGS * flags = NULL;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pPin) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_locked(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_LOCKED;
goto done;
}
if (sess->session_info.state != CKS_RW_SO_FUNCTIONS) {
rc = CKR_USER_NOT_LOGGED_IN;
goto done;
}
rc = token_specific.t_init_pin(sess->hContext, pPin, ulPinLen);
if (rc == CKR_OK) {
flags = &nv_token_data->token_info.flags;
*flags &= ~(CKF_USER_PIN_LOCKED |
CKF_USER_PIN_FINAL_TRY |
CKF_USER_PIN_COUNT_LOW);
rc = save_token_data(nv_token_data);
if (rc != CKR_OK) {
goto done;
}
}
done:
if (debugfile) {
stlogit2(debugfile, "% - 25s: session = %08x\n",
"C_InitPin", rc, hSession);
}
return (rc);
}
CK_RV
SC_SetPIN(ST_SESSION_HANDLE sSession,
CK_CHAR_PTR pOldPin,
CK_ULONG ulOldLen,
CK_CHAR_PTR pNewPin,
CK_ULONG ulNewLen)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_locked(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_LOCKED;
goto done;
}
rc = token_specific.t_set_pin(sSession, pOldPin,
ulOldLen, pNewPin, ulNewLen);
done:
if (debugfile) {
stlogit2(debugfile, "% - 25s: session = %08x\n",
"C_SetPin", rc, hSession);
}
return (rc);
}
CK_RV
SC_OpenSession(
CK_SLOT_ID sid,
CK_FLAGS flags,
CK_SESSION_HANDLE_PTR phSession)
{
SESSION *sess;
CK_RV rc = CKR_OK;
TSS_HCONTEXT hContext;
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if ((flags & CKF_RW_SESSION) == 0) {
if (session_mgr_so_session_exists()) {
return (CKR_SESSION_READ_WRITE_SO_EXISTS);
}
}
if (sid != TPM_SLOTID) {
rc = CKR_SLOT_ID_INVALID;
goto done;
}
if (open_tss_context(&hContext)) {
rc = CKR_FUNCTION_FAILED;
goto done;
}
rc = pthread_mutex_lock(&pkcs_mutex);
if (rc != CKR_OK) {
(void) pthread_mutex_unlock(&pkcs_mutex);
Tspi_Context_Close(hContext);
goto done;
}
token_specific.t_session(sid);
(void) pthread_mutex_unlock(&pkcs_mutex);
rc = session_mgr_new(flags, &sess);
if (rc != CKR_OK) {
Tspi_Context_Close(hContext);
goto done;
}
*phSession = sess->handle;
sess->session_info.slotID = sid;
/* Open a new context for each session */
sess->hContext = hContext;
done:
return (rc);
}
CK_RV
SC_CloseSession(ST_SESSION_HANDLE sSession)
{
SESSION *sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (!sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (token_specific.t_final != NULL) {
token_specific.t_final(sess->hContext);
}
rc = session_mgr_close_session(sess);
done:
return (rc);
}
/*ARGSUSED*/
CK_RV
SC_CloseAllSessions(CK_SLOT_ID sid)
{
CK_RV rc = CKR_OK;
if (st_Initialized() == FALSE)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
if (sid != TPM_SLOTID)
return (CKR_SLOT_ID_INVALID);
rc = session_mgr_close_all_sessions();
return (rc);
}
CK_RV
SC_GetSessionInfo(ST_SESSION_HANDLE sSession,
CK_SESSION_INFO_PTR pInfo)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pInfo) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
(void) memcpy(pInfo, &sess->session_info, sizeof (CK_SESSION_INFO));
done:
return (rc);
}
CK_RV SC_GetOperationState(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pOperationState,
CK_ULONG_PTR pulOperationStateLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pulOperationStateLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
if (! pOperationState)
length_only = TRUE;
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
rc = session_mgr_get_op_state(sess, length_only,
pOperationState, pulOperationStateLen);
done:
return (rc);
}
CK_RV
SC_SetOperationState(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pOperationState,
CK_ULONG ulOperationStateLen,
CK_OBJECT_HANDLE hEncryptionKey,
CK_OBJECT_HANDLE hAuthenticationKey)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
return (CKR_CRYPTOKI_NOT_INITIALIZED);
}
if (!pOperationState || (ulOperationStateLen == 0)) {
return (CKR_ARGUMENTS_BAD);
}
sess = session_mgr_find(hSession);
if (! sess) {
return (CKR_SESSION_HANDLE_INVALID);
}
rc = session_mgr_set_op_state(sess,
hEncryptionKey, hAuthenticationKey,
pOperationState);
return (rc);
}
CK_RV
SC_Login(ST_SESSION_HANDLE sSession,
CK_USER_TYPE userType,
CK_CHAR_PTR pPin,
CK_ULONG ulPinLen)
{
SESSION * sess = NULL;
CK_FLAGS * flags = NULL, flagcheck, flagmask;
CK_RV rc = CKR_OK;
SESS_SET
// In v2.11, logins should be exclusive, since token
// specific flags may need to be set for a bad login. - KEY
rc = pthread_mutex_lock(&login_mutex);
if (rc != CKR_OK) {
return (CKR_FUNCTION_FAILED);
}
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
flags = &nv_token_data->token_info.flags;
if (pPin == NULL) {
set_login_flags(userType, flags);
rc = CKR_ARGUMENTS_BAD;
goto done;
}
if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) {
set_login_flags(userType, flags);
rc = CKR_PIN_LEN_RANGE;
goto done;
}
/*
* PKCS #11 v2.01 requires that all sessions have the same login status:
* --> all sessions are public, all are SO or all are USER
*/
if (userType == CKU_USER) {
if (session_mgr_so_session_exists()) {
rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
}
if (session_mgr_user_session_exists()) {
rc = CKR_USER_ALREADY_LOGGED_IN;
}
} else if (userType == CKU_SO) {
if (session_mgr_user_session_exists()) {
rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
}
if (session_mgr_so_session_exists()) {
rc = CKR_USER_ALREADY_LOGGED_IN;
}
if (session_mgr_readonly_exists()) {
rc = CKR_SESSION_READ_ONLY_EXISTS;
}
} else {
rc = CKR_USER_TYPE_INVALID;
}
if (rc != CKR_OK)
goto done;
if (userType == CKU_USER) {
flagcheck = CKF_USER_PIN_LOCKED;
flagmask = (CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY |
CKF_USER_PIN_COUNT_LOW);
} else {
flagcheck = CKF_SO_PIN_LOCKED;
flagmask = (CKF_SO_PIN_LOCKED |
CKF_SO_PIN_FINAL_TRY |
CKF_SO_PIN_COUNT_LOW);
}
if (*flags & flagcheck) {
rc = CKR_PIN_LOCKED;
goto done;
}
/* call the pluggable login function here */
rc = token_specific.t_login(sess->hContext, userType, pPin, ulPinLen);
if (rc == CKR_OK) {
*flags &= ~(flagmask);
} else if (rc == CKR_PIN_INCORRECT) {
set_login_flags(userType, flags);
goto done;
} else {
goto done;
}
rc = session_mgr_login_all(userType);
done:
if (rc == CKR_OK)
rc = save_token_data(nv_token_data);
(void) pthread_mutex_unlock(&login_mutex);
return (rc);
}
CK_RV
SC_Logout(ST_SESSION_HANDLE sSession)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
// all sessions have the same state so we just have to check one
//
if (session_mgr_public_session_exists()) {
rc = CKR_USER_NOT_LOGGED_IN;
goto done;
}
(void) session_mgr_logout_all();
rc = token_specific.t_logout(sess->hContext);
done:
return (rc);
}
CK_RV
SC_CreateObject(ST_SESSION_HANDLE sSession,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phObject)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
rc = object_mgr_add(sess, pTemplate, ulCount, phObject);
done:
return (rc);
}
CK_RV
SC_CopyObject(
ST_SESSION_HANDLE sSession,
CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phNewObject)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
rc = object_mgr_copy(sess, pTemplate, ulCount,
hObject, phNewObject);
done:
return (rc);
}
CK_RV
SC_DestroyObject(ST_SESSION_HANDLE sSession,
CK_OBJECT_HANDLE hObject)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
rc = object_mgr_destroy_object(sess, hObject);
done:
return (rc);
}
CK_RV
SC_GetObjectSize(
ST_SESSION_HANDLE sSession,
CK_OBJECT_HANDLE hObject,
CK_ULONG_PTR pulSize)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
rc = object_mgr_get_object_size(sess->hContext, hObject, pulSize);
done:
return (rc);
}
CK_RV
SC_GetAttributeValue(ST_SESSION_HANDLE sSession,
CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
rc = object_mgr_get_attribute_values(sess, hObject, pTemplate, ulCount);
done:
return (rc);
}
CK_RV
SC_SetAttributeValue(ST_SESSION_HANDLE sSession,
CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
rc = object_mgr_set_attribute_values(sess, hObject, pTemplate, ulCount);
done:
return (rc);
}
CK_RV
SC_FindObjectsInit(ST_SESSION_HANDLE sSession,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
if (sess->find_active == TRUE) {
rc = CKR_OPERATION_ACTIVE;
goto done;
}
rc = object_mgr_find_init(sess, pTemplate, ulCount);
done:
return (rc);
}
CK_RV
SC_FindObjects(ST_SESSION_HANDLE sSession,
CK_OBJECT_HANDLE_PTR phObject,
CK_ULONG ulMaxObjectCount,
CK_ULONG_PTR pulObjectCount)
{
SESSION * sess = NULL;
CK_ULONG count = 0;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! phObject || ! pulObjectCount) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->find_active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! sess->find_list) {
rc = CKR_FUNCTION_FAILED;
goto done;
}
count = MIN(ulMaxObjectCount, (sess->find_count - sess->find_idx));
(void) memcpy(phObject, sess->find_list + sess->find_idx,
count * sizeof (CK_OBJECT_HANDLE));
*pulObjectCount = count;
sess->find_idx += count;
rc = CKR_OK;
done:
return (rc);
}
CK_RV
SC_FindObjectsFinal(ST_SESSION_HANDLE sSession)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->find_active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (sess->find_list)
free(sess->find_list);
sess->find_list = NULL;
sess->find_len = 0;
sess->find_idx = 0;
sess->find_active = FALSE;
rc = CKR_OK;
done:
return (rc);
}
CK_RV
SC_EncryptInit(ST_SESSION_HANDLE sSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pMechanism) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
VALID_MECH(pMechanism);
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
if (sess->encr_ctx.active == TRUE) {
rc = CKR_OPERATION_ACTIVE;
goto done;
}
rc = encr_mgr_init(sess, &sess->encr_ctx, OP_ENCRYPT_INIT,
pMechanism, hKey);
done:
return (rc);
}
CK_RV
SC_Encrypt(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pEncryptedData,
CK_ULONG_PTR pulEncryptedDataLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (! pData || ! pulEncryptedDataLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
if (sess->encr_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! pEncryptedData)
length_only = TRUE;
rc = encr_mgr_encrypt(sess, length_only,
&sess->encr_ctx, pData, ulDataLen,
pEncryptedData, pulEncryptedDataLen);
done:
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE))
(void) encr_mgr_cleanup(&sess->encr_ctx);
return (rc);
}
#if 0
CK_RV
SC_EncryptUpdate(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen,
CK_BYTE_PTR pEncryptedPart,
CK_ULONG_PTR pulEncryptedPartLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pPart || ! pulEncryptedPartLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->encr_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! pEncryptedPart)
length_only = TRUE;
rc = encr_mgr_encrypt_update(sess, length_only,
&sess->encr_ctx, pPart, ulPartLen,
pEncryptedPart, pulEncryptedPartLen);
done:
if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL)
(void) encr_mgr_cleanup(&sess->encr_ctx);
return (rc);
}
CK_RV
SC_EncryptFinal(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pLastEncryptedPart,
CK_ULONG_PTR pulLastEncryptedPartLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pulLastEncryptedPartLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->encr_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! pLastEncryptedPart)
length_only = TRUE;
rc = encr_mgr_encrypt_final(sess, length_only, &sess->encr_ctx,
pLastEncryptedPart, pulLastEncryptedPartLen);
done:
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE))
(void) encr_mgr_cleanup(&sess->encr_ctx);
return (rc);
}
#endif
CK_RV
SC_DecryptInit(ST_SESSION_HANDLE sSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pMechanism) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
VALID_MECH(pMechanism);
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
if (sess->decr_ctx.active == TRUE) {
rc = CKR_OPERATION_ACTIVE;
goto done;
}
rc = decr_mgr_init(sess, &sess->decr_ctx,
OP_DECRYPT_INIT, pMechanism, hKey);
done:
return (rc);
}
CK_RV
SC_Decrypt(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pEncryptedData,
CK_ULONG ulEncryptedDataLen,
CK_BYTE_PTR pData,
CK_ULONG_PTR pulDataLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (! pEncryptedData || ! pulDataLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
if (sess->decr_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! pData)
length_only = TRUE;
rc = decr_mgr_decrypt(sess,
length_only,
&sess->decr_ctx,
pEncryptedData,
ulEncryptedDataLen,
pData,
pulDataLen);
done:
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE))
(void) decr_mgr_cleanup(&sess->decr_ctx);
return (rc);
}
CK_RV
SC_DigestInit(ST_SESSION_HANDLE sSession,
CK_MECHANISM_PTR pMechanism)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pMechanism) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
VALID_MECH(pMechanism);
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
if (sess->digest_ctx.active == TRUE) {
rc = CKR_OPERATION_ACTIVE;
goto done;
}
rc = digest_mgr_init(sess, &sess->digest_ctx, pMechanism);
done:
return (rc);
}
CK_RV
SC_Digest(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pDigest,
CK_ULONG_PTR pulDigestLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (! pData || ! pulDigestLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
if (sess->digest_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! pDigest)
length_only = TRUE;
rc = digest_mgr_digest(sess, length_only,
&sess->digest_ctx, pData, ulDataLen,
pDigest, pulDigestLen);
done:
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE))
(void) digest_mgr_cleanup(&sess->digest_ctx);
return (rc);
}
CK_RV
SC_DigestUpdate(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pPart && ulPartLen != 0) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->digest_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (pPart) {
rc = digest_mgr_digest_update(sess, &sess->digest_ctx,
pPart, ulPartLen);
}
done:
if (rc != CKR_OK)
(void) digest_mgr_cleanup(&sess->digest_ctx);
return (rc);
}
CK_RV
SC_DigestKey(ST_SESSION_HANDLE sSession,
CK_OBJECT_HANDLE hKey)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->digest_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
rc = digest_mgr_digest_key(sess, &sess->digest_ctx, hKey);
done:
if (rc != CKR_OK)
(void) digest_mgr_cleanup(&sess->digest_ctx);
return (rc);
}
CK_RV
SC_DigestFinal(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pDigest,
CK_ULONG_PTR pulDigestLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pulDigestLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->digest_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! pDigest)
length_only = TRUE;
rc = digest_mgr_digest_final(sess,
&sess->digest_ctx, pDigest, pulDigestLen);
done:
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE))
(void) digest_mgr_cleanup(&sess->digest_ctx);
return (rc);
}
CK_RV
SC_SignInit(ST_SESSION_HANDLE sSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pMechanism) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
VALID_MECH(pMechanism);
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
if (sess->sign_ctx.active == TRUE) {
rc = CKR_OPERATION_ACTIVE;
goto done;
}
rc = sign_mgr_init(sess, &sess->sign_ctx, pMechanism, FALSE, hKey);
done:
return (rc);
}
CK_RV
SC_Sign(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (!pData || !pulSignatureLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
if (sess->sign_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! pSignature)
length_only = TRUE;
rc = sign_mgr_sign(sess, length_only,
&sess->sign_ctx, pData, ulDataLen,
pSignature, pulSignatureLen);
done:
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE))
(void) sign_mgr_cleanup(&sess->sign_ctx);
return (rc);
}
CK_RV
SC_SignUpdate(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pPart) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->sign_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
rc = sign_mgr_sign_update(sess, &sess->sign_ctx, pPart, ulPartLen);
done:
if (rc != CKR_OK)
(void) sign_mgr_cleanup(&sess->sign_ctx);
return (rc);
}
CK_RV
SC_SignFinal(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pulSignatureLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->sign_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! pSignature)
length_only = TRUE;
rc = sign_mgr_sign_final(sess, length_only,
&sess->sign_ctx, pSignature, pulSignatureLen);
done:
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE))
(void) sign_mgr_cleanup(&sess->sign_ctx);
return (rc);
}
CK_RV
SC_SignRecoverInit(ST_SESSION_HANDLE sSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pMechanism) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
VALID_MECH(pMechanism);
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
if (sess->sign_ctx.active == TRUE) {
rc = CKR_OPERATION_ACTIVE;
goto done;
}
rc = sign_mgr_init(sess, &sess->sign_ctx, pMechanism, TRUE, hKey);
done:
return (rc);
}
CK_RV
SC_SignRecover(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (!pData || !pulSignatureLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
if ((sess->sign_ctx.active == FALSE) ||
(sess->sign_ctx.recover == FALSE)) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! pSignature)
length_only = TRUE;
rc = sign_mgr_sign_recover(sess, length_only,
&sess->sign_ctx, pData, ulDataLen,
pSignature, pulSignatureLen);
done:
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE))
(void) sign_mgr_cleanup(&sess->sign_ctx);
return (rc);
}
CK_RV
SC_VerifyInit(ST_SESSION_HANDLE sSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pMechanism) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
VALID_MECH(pMechanism);
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
if (sess->verify_ctx.active == TRUE) {
rc = CKR_OPERATION_ACTIVE;
goto done;
}
rc = verify_mgr_init(sess, &sess->verify_ctx, pMechanism, FALSE, hKey);
done:
return (rc);
}
CK_RV
SC_Verify(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (! pData || ! pSignature) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
if (sess->verify_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
rc = verify_mgr_verify(sess,
&sess->verify_ctx, pData, ulDataLen,
pSignature, ulSignatureLen);
done:
(void) verify_mgr_cleanup(&sess->verify_ctx);
return (rc);
}
CK_RV
SC_VerifyUpdate(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pPart) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->verify_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
rc = verify_mgr_verify_update(sess, &sess->verify_ctx,
pPart, ulPartLen);
done:
if (rc != CKR_OK)
(void) verify_mgr_cleanup(&sess->verify_ctx);
return (rc);
}
CK_RV
SC_VerifyFinal(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pSignature) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (sess->verify_ctx.active == FALSE) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
rc = verify_mgr_verify_final(sess, &sess->verify_ctx,
pSignature, ulSignatureLen);
done:
(void) verify_mgr_cleanup(&sess->verify_ctx);
return (rc);
}
CK_RV
SC_VerifyRecoverInit(ST_SESSION_HANDLE sSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pMechanism) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
VALID_MECH(pMechanism);
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
if (sess->verify_ctx.active == TRUE) {
rc = CKR_OPERATION_ACTIVE;
goto done;
}
rc = verify_mgr_init(sess, &sess->verify_ctx, pMechanism, TRUE, hKey);
done:
return (rc);
}
CK_RV
SC_VerifyRecover(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen,
CK_BYTE_PTR pData,
CK_ULONG_PTR pulDataLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (!pSignature || !pulDataLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
if ((sess->verify_ctx.active == FALSE) ||
(sess->verify_ctx.recover == FALSE)) {
rc = CKR_OPERATION_NOT_INITIALIZED;
goto done;
}
if (! pData)
length_only = TRUE;
rc = verify_mgr_verify_recover(sess, length_only,
&sess->verify_ctx, pSignature, ulSignatureLen,
pData, pulDataLen);
done:
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE))
(void) verify_mgr_cleanup(&sess->verify_ctx);
return (rc);
}
CK_RV
SC_GenerateKeyPair(ST_SESSION_HANDLE sSession,
CK_MECHANISM_PTR pMechanism,
CK_ATTRIBUTE_PTR pPublicKeyTemplate,
CK_ULONG ulPublicKeyAttributeCount,
CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
CK_ULONG ulPrivateKeyAttributeCount,
CK_OBJECT_HANDLE_PTR phPublicKey,
CK_OBJECT_HANDLE_PTR phPrivateKey)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pMechanism || ! phPublicKey || ! phPrivateKey ||
(! pPublicKeyTemplate && (ulPublicKeyAttributeCount != 0)) ||
(! pPrivateKeyTemplate && (ulPrivateKeyAttributeCount != 0))) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
VALID_MECH(pMechanism);
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
rc = key_mgr_generate_key_pair(sess, pMechanism,
pPublicKeyTemplate, ulPublicKeyAttributeCount,
pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
phPublicKey, phPrivateKey);
done:
return (rc);
}
CK_RV
SC_WrapKey(ST_SESSION_HANDLE sSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hWrappingKey,
CK_OBJECT_HANDLE hKey,
CK_BYTE_PTR pWrappedKey,
CK_ULONG_PTR pulWrappedKeyLen)
{
SESSION * sess = NULL;
CK_BBOOL length_only = FALSE;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pMechanism || ! pulWrappedKeyLen) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
VALID_MECH(pMechanism);
if (! pWrappedKey)
length_only = TRUE;
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
rc = key_mgr_wrap_key(sess, length_only,
pMechanism, hWrappingKey, hKey,
pWrappedKey, pulWrappedKeyLen);
done:
return (rc);
}
CK_RV
SC_UnwrapKey(ST_SESSION_HANDLE sSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hUnwrappingKey,
CK_BYTE_PTR pWrappedKey,
CK_ULONG ulWrappedKeyLen,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phKey)
{
SESSION * sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pMechanism || ! pWrappedKey ||
(! pTemplate && ulCount != 0) || ! phKey) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
VALID_MECH(pMechanism);
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
if (pin_expired(&sess->session_info,
nv_token_data->token_info.flags) == TRUE) {
rc = CKR_PIN_EXPIRED;
goto done;
}
rc = key_mgr_unwrap_key(sess, pMechanism,
pTemplate, ulCount,
pWrappedKey, ulWrappedKeyLen,
hUnwrappingKey, phKey);
done:
return (rc);
}
/*ARGSUSED*/
CK_RV
SC_SeedRandom(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pSeed,
CK_ULONG ulSeedLen)
{
if (st_Initialized() == FALSE) {
return (CKR_CRYPTOKI_NOT_INITIALIZED);
}
if (pSeed == NULL || ulSeedLen == NULL)
return (CKR_ARGUMENTS_BAD);
return (CKR_OK);
}
CK_RV
SC_GenerateRandom(ST_SESSION_HANDLE sSession,
CK_BYTE_PTR pRandomData,
CK_ULONG ulRandomLen)
{
SESSION *sess = NULL;
CK_RV rc = CKR_OK;
SESS_SET
if (st_Initialized() == FALSE) {
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
goto done;
}
if (! pRandomData && ulRandomLen != 0) {
rc = CKR_ARGUMENTS_BAD;
goto done;
}
sess = session_mgr_find(hSession);
if (! sess) {
rc = CKR_SESSION_HANDLE_INVALID;
goto done;
}
rc = token_rng(sess->hContext, pRandomData, ulRandomLen);
done:
return (rc);
}
void
SC_SetFunctionList(void) {
function_list.ST_Initialize = ST_Initialize;
function_list.ST_Finalize = SC_Finalize;
function_list.ST_GetTokenInfo = SC_GetTokenInfo;
function_list.ST_GetMechanismList = SC_GetMechanismList;
function_list.ST_GetMechanismInfo = SC_GetMechanismInfo;
function_list.ST_InitToken = SC_InitToken;
function_list.ST_InitPIN = SC_InitPIN;
function_list.ST_SetPIN = SC_SetPIN;
function_list.ST_OpenSession = SC_OpenSession;
function_list.ST_CloseSession = SC_CloseSession;
function_list.ST_GetSessionInfo = SC_GetSessionInfo;
function_list.ST_GetOperationState = SC_GetOperationState;
function_list.ST_SetOperationState = SC_SetOperationState;
function_list.ST_Login = SC_Login;
function_list.ST_Logout = SC_Logout;
function_list.ST_CreateObject = SC_CreateObject;
function_list.ST_CopyObject = SC_CopyObject;
function_list.ST_DestroyObject = SC_DestroyObject;
function_list.ST_GetObjectSize = SC_GetObjectSize;
function_list.ST_GetAttributeValue = SC_GetAttributeValue;
function_list.ST_SetAttributeValue = SC_SetAttributeValue;
function_list.ST_FindObjectsInit = SC_FindObjectsInit;
function_list.ST_FindObjects = SC_FindObjects;
function_list.ST_FindObjectsFinal = SC_FindObjectsFinal;
function_list.ST_EncryptInit = SC_EncryptInit;
function_list.ST_Encrypt = SC_Encrypt;
function_list.ST_EncryptUpdate = NULL /* SC_EncryptUpdate */;
function_list.ST_EncryptFinal = NULL /* SC_EncryptFinal */;
function_list.ST_DecryptInit = SC_DecryptInit;
function_list.ST_Decrypt = SC_Decrypt;
function_list.ST_DecryptUpdate = NULL /* SC_DecryptUpdate */;
function_list.ST_DecryptFinal = NULL /* SC_DecryptFinal */;
function_list.ST_DigestInit = SC_DigestInit;
function_list.ST_Digest = SC_Digest;
function_list.ST_DigestUpdate = SC_DigestUpdate;
function_list.ST_DigestKey = SC_DigestKey;
function_list.ST_DigestFinal = SC_DigestFinal;
function_list.ST_SignInit = SC_SignInit;
function_list.ST_Sign = SC_Sign;
function_list.ST_SignUpdate = SC_SignUpdate;
function_list.ST_SignFinal = SC_SignFinal;
function_list.ST_SignRecoverInit = SC_SignRecoverInit;
function_list.ST_SignRecover = SC_SignRecover;
function_list.ST_VerifyInit = SC_VerifyInit;
function_list.ST_Verify = SC_Verify;
function_list.ST_VerifyUpdate = SC_VerifyUpdate;
function_list.ST_VerifyFinal = SC_VerifyFinal;
function_list.ST_VerifyRecoverInit = SC_VerifyRecoverInit;
function_list.ST_VerifyRecover = SC_VerifyRecover;
function_list.ST_DigestEncryptUpdate = NULL;
function_list.ST_DecryptDigestUpdate = NULL;
function_list.ST_SignEncryptUpdate = NULL;
function_list.ST_DecryptVerifyUpdate = NULL;
function_list.ST_GenerateKey = NULL;
function_list.ST_GenerateKeyPair = SC_GenerateKeyPair;
function_list.ST_WrapKey = SC_WrapKey;
function_list.ST_UnwrapKey = SC_UnwrapKey;
function_list.ST_DeriveKey = NULL;
function_list.ST_SeedRandom = SC_SeedRandom;
function_list.ST_GenerateRandom = SC_GenerateRandom;
function_list.ST_GetFunctionStatus = NULL;
function_list.ST_CancelFunction = NULL;
}