You've already forked opencryptoki
mirror of
https://github.com/opencryptoki/opencryptoki.git
synced 2026-10-24 05:39:17 +03:00
Make sure that C_Login, C_SetPIN, C_InitPIN, C_InitToken do not read or update any token files or any field in the token shared memory without holding the XProcLock. Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
4854 lines
155 KiB
C
4854 lines
155 KiB
C
/*
|
|
* COPYRIGHT (c) International Business Machines Corp. 2001-2017
|
|
*
|
|
* This program is provided under the terms of the Common Public License,
|
|
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
* found in the file LICENSE file or at
|
|
* https://opensource.org/licenses/cpl1.0.php
|
|
*/
|
|
|
|
/***************************************************************************
|
|
Change Log
|
|
==========
|
|
4/25/03 Kapil Sood (kapil@corrent.com)
|
|
Added DH key pair generation and DH shared key derivation
|
|
functions.
|
|
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <string.h>
|
|
#include <strings.h>
|
|
#include <errno.h>
|
|
#include <syslog.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <grp.h>
|
|
#include <pwd.h>
|
|
#include <openssl/crypto.h>
|
|
#include <openssl/evp.h>
|
|
|
|
#include "pkcs11types.h"
|
|
#include "stdll.h"
|
|
|
|
#include "defs.h"
|
|
#include "host_defs.h"
|
|
#include "h_extern.h"
|
|
#include "tok_spec_struct.h"
|
|
#include "pkcs32.h"
|
|
#include "trace.h"
|
|
#include "slotmgr.h"
|
|
#include "attributes.h"
|
|
#include "constant_time.h"
|
|
|
|
#include "../api/apiproto.h"
|
|
#include "../api/policy.h"
|
|
|
|
void SC_SetFunctionList(void);
|
|
CK_RV SC_Logout(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession);
|
|
CK_RV SC_Finalize(STDLL_TokData_t *tokdata, CK_SLOT_ID sid, SLOT_INFO *sinfp,
|
|
struct trace_handle_t *t, CK_BBOOL in_fork_initializer);
|
|
|
|
/* verify that the mech specified is in the
|
|
* mech list for this token...
|
|
*/
|
|
CK_RV valid_mech(STDLL_TokData_t *tokdata, CK_MECHANISM_PTR m, CK_FLAGS f)
|
|
{
|
|
CK_RV rc;
|
|
CK_MECHANISM_INFO info;
|
|
|
|
if (m && token_specific.t_get_mechanism_info) {
|
|
memset(&info, 0, sizeof(info));
|
|
rc = token_specific.t_get_mechanism_info(tokdata, m->mechanism, &info);
|
|
if (rc != CKR_OK || !(info.flags & (f)))
|
|
return CKR_MECHANISM_INVALID;
|
|
}
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
|
|
/* In an STDLL this is called once for each card in the system
|
|
* therefore the initialized only flags certain one time things.
|
|
*/
|
|
CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber,
|
|
SLOT_INFO *sinfp, struct trace_handle_t t)
|
|
{
|
|
CK_RV rc = CKR_OK;
|
|
char abs_tokdir_name[PATH_MAX];
|
|
CK_BBOOL newdatastore;
|
|
policy_t policy = sltp->TokData->policy;
|
|
|
|
/* set trace info */
|
|
set_trace(t);
|
|
|
|
rc = bt_init(&sltp->TokData->sess_btree, free);
|
|
rc |= bt_init(&sltp->TokData->object_map_btree, free);
|
|
rc |= bt_init(&sltp->TokData->sess_obj_btree, call_object_free);
|
|
rc |= bt_init(&sltp->TokData->priv_token_obj_btree, call_object_free);
|
|
rc |= bt_init(&sltp->TokData->publ_token_obj_btree, call_object_free);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Btree init failed\n");
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
|
|
if (strlen(sinfp->tokname)) {
|
|
if (strcmp(sinfp->tokname, "HSM_MK_CHANGE") == 0) {
|
|
TRACE_ERROR("tokname 'HSM_MK_CHANGE' is reserved\n");
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
if (!is_valid_filename_component(sinfp->tokname)) {
|
|
TRACE_ERROR("tokname '%s' is not valid (must not be empty, "
|
|
"must not be '.' or '..', and must not contain '/')\n",
|
|
sinfp->tokname);
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
if (ock_snprintf(abs_tokdir_name, PATH_MAX, "%s/%s",
|
|
CONFIG_PATH, sinfp->tokname) != 0) {
|
|
TRACE_ERROR("token directory path buffer overflow\n");
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
TRACE_DEVEL("Token directory: %s\n", abs_tokdir_name);
|
|
rc = init_data_store(sltp->TokData, (char *) abs_tokdir_name,
|
|
sltp->TokData->data_store,
|
|
sizeof(sltp->TokData->data_store));
|
|
} else {
|
|
rc = init_data_store(sltp->TokData, (char *) PK_DIR,
|
|
sltp->TokData->data_store,
|
|
sizeof(sltp->TokData->data_store));
|
|
}
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("init_data_store failed with buffer error.\n");
|
|
goto done;
|
|
}
|
|
|
|
sltp->TokData->version = sinfp->version;
|
|
TRACE_DEVEL("Token version: %u.%u\n",
|
|
(unsigned int)(sinfp->version >> 16),
|
|
(unsigned int)(sinfp->version & 0xffff));
|
|
/* Check token store encryption against policy */
|
|
newdatastore = sinfp->version >= TOK_NEW_DATA_STORE ? CK_TRUE : CK_FALSE;
|
|
rc = policy->check_token_store(policy, newdatastore,
|
|
token_specific.data_store.encryption_algorithm,
|
|
SlotNumber, &sltp->TokData->store_strength);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("POLICY VIOLATION: Token cannot load since data store encryption is too weak for policy.\n");
|
|
goto done;
|
|
}
|
|
|
|
/* Initialize Lock */
|
|
if (XProcLock_Init(sltp->TokData) != CKR_OK) {
|
|
TRACE_ERROR("Thread lock failed.\n");
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
|
|
/* Create lockfile */
|
|
if (CreateXProcLock(sinfp->tokname, sltp->TokData) != CKR_OK) {
|
|
TRACE_ERROR("Process lock failed.\n");
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
|
|
/* Validate confname: relative names are restricted to safe filename
|
|
* components; absolute paths are used as-is and need no further check. */
|
|
if (strlen(sinfp->confname) > 0 && sinfp->confname[0] != '/' &&
|
|
!is_valid_filename_component(sinfp->confname)) {
|
|
TRACE_ERROR("confname '%s' is not valid (must not be empty, "
|
|
"must not be '.' or '..', and must not contain '/')\n",
|
|
sinfp->confname);
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
|
|
/* Handle global initialization issues first if we have not
|
|
* been initialized.
|
|
*/
|
|
if (sltp->TokData->initialized == FALSE) {
|
|
rc = attach_shm(sltp->TokData, SlotNumber);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Could not attach to shared memory.\n");
|
|
goto done;
|
|
}
|
|
|
|
sltp->TokData->nv_token_data =
|
|
&(sltp->TokData->global_shm->nv_token_data);
|
|
SC_SetFunctionList();
|
|
|
|
/* Always call the token_specific_init function.... */
|
|
rc = token_specific.t_init(sltp->TokData, SlotNumber, sinfp->confname);
|
|
if (rc != 0) {
|
|
sltp->FcnList = NULL;
|
|
detach_shm(sltp->TokData, 0);
|
|
final_data_store(sltp->TokData);
|
|
TRACE_DEVEL("Token Specific Init failed.\n");
|
|
goto done;
|
|
}
|
|
sltp->TokData->initialized = TRUE;
|
|
}
|
|
|
|
rc = load_token_data(sltp->TokData, SlotNumber);
|
|
if (rc != CKR_OK) {
|
|
sltp->FcnList = NULL;
|
|
final_data_store(sltp->TokData);
|
|
TRACE_DEVEL("Failed to load token data. (rc=0x%02lx)\n", rc);
|
|
goto done;
|
|
}
|
|
|
|
rc = XProcLock(sltp->TokData);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
/* no need to return error here, we load the token data we can
|
|
* and syslog the rest
|
|
*/
|
|
load_public_token_objects(sltp->TokData);
|
|
|
|
sltp->TokData->global_shm->publ_loaded = TRUE;
|
|
|
|
rc = XProcUnLock(sltp->TokData);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
init_slotInfo(&(sltp->TokData->slot_info));
|
|
|
|
(sltp->FcnList) = &function_list;
|
|
|
|
done:
|
|
if (rc != CKR_OK && sltp->TokData != NULL) {
|
|
if (sltp->TokData->initialized) {
|
|
SC_Finalize(sltp->TokData, SlotNumber, sinfp, NULL, 0);
|
|
} else {
|
|
CloseXProcLock(sltp->TokData);
|
|
final_data_store(sltp->TokData);
|
|
bt_destroy(&sltp->TokData->sess_btree);
|
|
bt_destroy(&sltp->TokData->object_map_btree);
|
|
bt_destroy(&sltp->TokData->sess_obj_btree);
|
|
bt_destroy(&sltp->TokData->priv_token_obj_btree);
|
|
bt_destroy(&sltp->TokData->publ_token_obj_btree);
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* What does this really have to do in this new token... probably
|
|
* need to close the adapters that are opened, and clear the other
|
|
* stuff
|
|
*/
|
|
CK_RV SC_Finalize(STDLL_TokData_t *tokdata, CK_SLOT_ID sid, SLOT_INFO *sinfp,
|
|
struct trace_handle_t *t, CK_BBOOL in_fork_initializer)
|
|
{
|
|
CK_RV rc = CKR_OK;
|
|
|
|
UNUSED(sid);
|
|
UNUSED(sinfp);
|
|
|
|
if (t != NULL)
|
|
set_trace(*t);
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
}
|
|
|
|
tokdata->initialized = FALSE;
|
|
|
|
session_mgr_close_all_sessions(tokdata);
|
|
object_mgr_purge_token_objects(tokdata);
|
|
|
|
/* Finally free the nodes on free list. */
|
|
bt_destroy(&tokdata->sess_btree);
|
|
bt_destroy(&tokdata->object_map_btree);
|
|
bt_destroy(&tokdata->sess_obj_btree);
|
|
bt_destroy(&tokdata->priv_token_obj_btree);
|
|
bt_destroy(&tokdata->publ_token_obj_btree);
|
|
|
|
detach_shm(tokdata, in_fork_initializer);
|
|
/* close spin lock file */
|
|
CloseXProcLock(tokdata);
|
|
if (token_specific.t_final != NULL) {
|
|
rc = token_specific.t_final(tokdata, in_fork_initializer);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Token specific final call failed.\n");
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
final_data_store(tokdata);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_GetTokenInfo(STDLL_TokData_t *tokdata, CK_SLOT_ID sid,
|
|
CK_TOKEN_INFO_PTR pInfo)
|
|
{
|
|
CK_RV rc = CKR_OK;
|
|
time_t now;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
if (!pInfo) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
if (sid >= NUMBER_SLOTS_MANAGED) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID));
|
|
rc = CKR_SLOT_ID_INVALID;
|
|
goto done;
|
|
}
|
|
copy_token_contents_sensibly(pInfo, tokdata->nv_token_data);
|
|
if (token_specific.t_get_token_info != NULL)
|
|
rc = token_specific.t_get_token_info(tokdata, pInfo);
|
|
|
|
/* Set the time */
|
|
now = time((time_t *) NULL);
|
|
strftime((char *) pInfo->utcTime, 16, "%Y%m%d%H%M%S", localtime(&now));
|
|
pInfo->utcTime[14] = '0';
|
|
pInfo->utcTime[15] = '0';
|
|
|
|
done:
|
|
TRACE_INFO("C_GetTokenInfo: rc = 0x%08lx\n", rc);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_WaitForSlotEvent(STDLL_TokData_t *tokdata, CK_FLAGS flags,
|
|
CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
|
|
{
|
|
UNUSED(flags);
|
|
UNUSED(pSlot);
|
|
UNUSED(pReserved);
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
}
|
|
|
|
TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
|
|
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
}
|
|
|
|
/*
|
|
* Get the mechanism type list for the current token.
|
|
*/
|
|
CK_RV SC_GetMechanismList(STDLL_TokData_t *tokdata, CK_SLOT_ID sid,
|
|
CK_MECHANISM_TYPE_PTR pMechList, CK_ULONG_PTR count)
|
|
{
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto out;
|
|
}
|
|
if (count == NULL) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto out;
|
|
}
|
|
if (sid >= NUMBER_SLOTS_MANAGED) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID));
|
|
rc = CKR_SLOT_ID_INVALID;
|
|
goto out;
|
|
}
|
|
if (!token_specific.t_get_mechanism_list) {
|
|
TRACE_ERROR("token specific GetMechanismList doesn't exist.\n");
|
|
rc = CKR_GENERAL_ERROR;
|
|
goto out;
|
|
}
|
|
rc = token_specific.t_get_mechanism_list(tokdata, pMechList, count);
|
|
if (rc == CKR_OK) {
|
|
/* To accomodate certain special cases, we may need to
|
|
* make adjustments to the token's mechanism list.
|
|
*/
|
|
mechanism_list_transformations(tokdata, pMechList, count);
|
|
}
|
|
|
|
out:
|
|
TRACE_INFO("C_GetMechanismList: rc = 0x%08lx, # mechanisms: %lu\n",
|
|
rc, (count ? *count : 0));
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* Get the mechanism info for the current type and token.
|
|
*/
|
|
CK_RV SC_GetMechanismInfo(STDLL_TokData_t *tokdata, CK_SLOT_ID sid,
|
|
CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
|
|
{
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto out;
|
|
}
|
|
if (pInfo == NULL) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto out;
|
|
}
|
|
if (sid >= NUMBER_SLOTS_MANAGED) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID));
|
|
rc = CKR_SLOT_ID_INVALID;
|
|
goto out;
|
|
}
|
|
if (!token_specific.t_get_mechanism_info) {
|
|
TRACE_ERROR("token specific GetMechanismInfo doesn't exist.\n");
|
|
rc = CKR_GENERAL_ERROR;
|
|
goto out;
|
|
}
|
|
rc = token_specific.t_get_mechanism_info(tokdata, type, pInfo);
|
|
|
|
out:
|
|
TRACE_INFO("C_GetMechanismInfo: rc = 0x%08lx, mech type = 0x%08lx\n",
|
|
rc, type);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* This routine should only be called if no other processes are
|
|
* attached to the token. we need to somehow check that this is the
|
|
* only process Meta API should prevent this since it knows session
|
|
* states in the shared memory.
|
|
*/
|
|
CK_RV SC_InitToken(STDLL_TokData_t *tokdata, 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_HASH_SIZE];
|
|
CK_BYTE so_pin_sha_snap[SHA1_HASH_SIZE];
|
|
unsigned char login_key[32];
|
|
TOKEN_DATA_VERSION dat_snap;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
}
|
|
if (!pPin || !pLabel) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (pthread_mutex_lock(&tokdata->login_mutex)) {
|
|
TRACE_ERROR("Failed to get mutex lock.\n");
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
if (tokdata->nv_token_data->token_info.flags & CKF_SO_PIN_LOCKED) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED));
|
|
rc = CKR_PIN_LOCKED;
|
|
goto done;
|
|
}
|
|
|
|
/* Check if token has a specific handler for this, otherwise fall back
|
|
* to default behaviour.
|
|
*/
|
|
if (token_specific.t_init_token) {
|
|
rc = token_specific.t_init_token(tokdata, sid, pPin, ulPinLen, pLabel);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
}
|
|
goto done;
|
|
}
|
|
|
|
/* Snapshot SO PIN material from shared memory under XProcLock. */
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
dat_snap = tokdata->nv_token_data->dat;
|
|
memcpy(so_pin_sha_snap, tokdata->nv_token_data->so_pin_sha,
|
|
SHA1_HASH_SIZE);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("compute_sha1 failed.\n");
|
|
goto done;
|
|
}
|
|
if (memcmp(so_pin_sha_snap, hash_sha, SHA1_HASH_SIZE) != 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
goto done;
|
|
}
|
|
} else {
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen,
|
|
dat_snap.so_login_salt, 64,
|
|
dat_snap.so_login_it, EVP_sha512(),
|
|
256 / 8, login_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
if (CRYPTO_memcmp(dat_snap.so_login_key, login_key, 32) != 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* Before we reconstruct all the data, we should delete the
|
|
* token objects from the filesystem.
|
|
*/
|
|
object_mgr_destroy_token_objects(tokdata);
|
|
delete_token_data(tokdata);
|
|
|
|
load_token_data(tokdata, sid);
|
|
init_slotInfo(&(tokdata->slot_info));
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
memcpy(tokdata->nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE);
|
|
} else {
|
|
memcpy(tokdata->nv_token_data->dat.so_login_key, login_key, 32);
|
|
}
|
|
tokdata->nv_token_data->token_info.flags |= CKF_TOKEN_INITIALIZED;
|
|
tokdata->nv_token_data->token_info.flags &= ~(CKF_USER_PIN_INITIALIZED |
|
|
CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY |
|
|
CKF_USER_PIN_COUNT_LOW);
|
|
memcpy(tokdata->nv_token_data->token_info.label, pLabel, 32);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = save_token_data(tokdata, sid);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("Failed to save token data.\n");
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
TRACE_INFO("C_InitToken: rc = 0x%08lx\n", rc);
|
|
|
|
pthread_mutex_unlock(&tokdata->login_mutex);
|
|
|
|
OPENSSL_cleanse(hash_sha, sizeof(hash_sha));
|
|
OPENSSL_cleanse(so_pin_sha_snap, sizeof(so_pin_sha_snap));
|
|
OPENSSL_cleanse(&dat_snap, sizeof(dat_snap));
|
|
OPENSSL_cleanse(login_key, sizeof(login_key));
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_InitPIN(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_BYTE hash_sha[SHA1_HASH_SIZE];
|
|
CK_BYTE hash_md5[MD5_HASH_SIZE];
|
|
CK_RV rc = CKR_OK;
|
|
CK_FLAGS_32 *flags = NULL;
|
|
TOKEN_DATA_VERSION *dat;
|
|
unsigned char login_key[32], wrap_key[32], login_salt[64], wrap_salt[64];
|
|
uint64_t login_it = 0, wrap_it = 0;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
}
|
|
if (!pPin) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (pthread_mutex_lock(&tokdata->login_mutex)) {
|
|
TRACE_ERROR("Failed to get mutex lock.\n");
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_locked(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED));
|
|
rc = CKR_PIN_LOCKED;
|
|
goto done;
|
|
}
|
|
if (sess->session_info.state != CKS_RW_SO_FUNCTIONS) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN));
|
|
rc = CKR_USER_NOT_LOGGED_IN;
|
|
goto done;
|
|
}
|
|
|
|
/* Check if token has a specific handler for this, otherwise fall back
|
|
* to default behaviour.
|
|
*/
|
|
if (token_specific.t_init_pin) {
|
|
rc = token_specific.t_init_pin(tokdata, sess, pPin, ulPinLen);
|
|
if (rc == CKR_OK) {
|
|
if (XProcLock(tokdata) != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
flags = &tokdata->nv_token_data->token_info.flags;
|
|
*flags &= ~(CKF_USER_PIN_LOCKED |
|
|
CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = save_token_data(tokdata, sess->session_info.slotID);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("Failed to save token data.\n");
|
|
}
|
|
goto done;
|
|
}
|
|
|
|
if ((ulPinLen < MIN_PIN_LEN) || (ulPinLen > MAX_PIN_LEN)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_LEN_RANGE));
|
|
rc = CKR_PIN_LEN_RANGE;
|
|
goto done;
|
|
}
|
|
|
|
|
|
dat = &tokdata->nv_token_data->dat;
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
/* compute the SHA and MD5 hashes of the user pin */
|
|
rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha);
|
|
rc |= compute_md5(tokdata, pPin, ulPinLen, hash_md5);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to compute sha or md5 for user pin.\n");
|
|
goto done;
|
|
}
|
|
} else {
|
|
login_it = USER_KDF_LOGIN_IT;
|
|
memcpy(login_salt, USER_KDF_LOGIN_PURPOSE, 32);
|
|
rng_generate(tokdata, login_salt + 32, 32);
|
|
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen,
|
|
login_salt, 64,
|
|
login_it, EVP_sha512(),
|
|
256 / 8, login_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
wrap_it = USER_KDF_WRAP_IT;
|
|
memcpy(wrap_salt, USER_KDF_WRAP_PURPOSE, 32);
|
|
rng_generate(tokdata, wrap_salt + 32, 32);
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen,
|
|
wrap_salt, 64,
|
|
wrap_it, EVP_sha512(),
|
|
256 / 8, wrap_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
memcpy(tokdata->nv_token_data->user_pin_sha, hash_sha, SHA1_HASH_SIZE);
|
|
} else {
|
|
memcpy(dat->user_login_key, login_key, 256 / 8);
|
|
memcpy(dat->user_login_salt, login_salt, 64);
|
|
dat->user_login_it = login_it;
|
|
/* wrap_salt/wrap_it also live in shared memory - write under lock */
|
|
memcpy(dat->user_wrap_salt, wrap_salt, 64);
|
|
dat->user_wrap_it = wrap_it;
|
|
}
|
|
|
|
tokdata->nv_token_data->token_info.flags |= CKF_USER_PIN_INITIALIZED;
|
|
tokdata->nv_token_data->token_info.flags &= ~(CKF_USER_PIN_TO_BE_CHANGED);
|
|
tokdata->nv_token_data->token_info.flags &= ~(CKF_USER_PIN_LOCKED);
|
|
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
memcpy(tokdata->user_pin_md5, hash_md5, MD5_HASH_SIZE);
|
|
} else {
|
|
memcpy(tokdata->user_wrap_key, wrap_key, 256 / 8);
|
|
}
|
|
|
|
rc = save_token_data(tokdata, sess->session_info.slotID);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("Failed to save token data.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = save_masterkey_user(tokdata);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("Failed to save user's masterkey.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_InitPin: rc = 0x%08lx, session = %lu\n",
|
|
rc, sSession->sessionh);
|
|
|
|
pthread_mutex_unlock(&tokdata->login_mutex);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
OPENSSL_cleanse(hash_sha, sizeof(hash_sha));
|
|
OPENSSL_cleanse(hash_md5, sizeof(hash_md5));
|
|
OPENSSL_cleanse(login_key, sizeof(login_key));
|
|
OPENSSL_cleanse(wrap_key, sizeof(wrap_key));
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_SetPIN(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin,
|
|
CK_ULONG ulNewLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_BYTE old_hash_sha[SHA1_HASH_SIZE];
|
|
CK_BYTE new_hash_sha[SHA1_HASH_SIZE];
|
|
CK_BYTE hash_md5[MD5_HASH_SIZE];
|
|
CK_BYTE pin_sha_snap[SHA1_HASH_SIZE];
|
|
CK_BYTE so_pin_sha_snap[SHA1_HASH_SIZE];
|
|
CK_RV rc = CKR_OK;
|
|
TOKEN_DATA_VERSION *dat;
|
|
TOKEN_DATA_VERSION dat_snap;
|
|
unsigned char old_login_key[32], new_login_key[32], new_wrap_key[32],
|
|
new_login_key_old_salt[32], login_salt[64], wrap_salt[64];
|
|
uint64_t login_it, wrap_it;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
}
|
|
|
|
if (pthread_mutex_lock(&tokdata->login_mutex)) {
|
|
TRACE_ERROR("Failed to get mutex lock.\n");
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_locked(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED));
|
|
rc = CKR_PIN_LOCKED;
|
|
goto done;
|
|
}
|
|
|
|
/* Check if token has a specific handler for this, otherwise fall back
|
|
* to default behaviour.
|
|
*/
|
|
if (token_specific.t_set_pin) {
|
|
rc = token_specific.t_set_pin(tokdata, sess, pOldPin, ulOldLen,
|
|
pNewPin, ulNewLen);
|
|
goto done;
|
|
}
|
|
|
|
if ((ulNewLen < MIN_PIN_LEN) || (ulNewLen > MAX_PIN_LEN)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_LEN_RANGE));
|
|
rc = CKR_PIN_LEN_RANGE;
|
|
goto done;
|
|
}
|
|
|
|
dat = &tokdata->nv_token_data->dat;
|
|
|
|
/* Snapshot PIN material from shared memory under XProcLock before any
|
|
* PBKDF2 derivation or SHA comparison. A concurrent SC_Login or
|
|
* SC_SetPIN from another process must not overwrite those fields
|
|
* mid-derivation.
|
|
*/
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
dat_snap = tokdata->nv_token_data->dat;
|
|
memcpy(pin_sha_snap, tokdata->nv_token_data->user_pin_sha, SHA1_HASH_SIZE);
|
|
memcpy(so_pin_sha_snap, tokdata->nv_token_data->so_pin_sha, SHA1_HASH_SIZE);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
rc = compute_sha1(tokdata, pOldPin, ulOldLen, old_hash_sha);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to compute sha for old pin.\n");
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of
|
|
* the user that is currently logged in, or the CKU_USER PIN
|
|
* if the session is not logged in." A non R/W session fails
|
|
* with CKR_SESSION_READ_ONLY.
|
|
*/
|
|
if ((sess->session_info.state == CKS_RW_USER_FUNCTIONS) ||
|
|
(sess->session_info.state == CKS_RW_PUBLIC_SESSION)) {
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
if (memcmp(pin_sha_snap, old_hash_sha,
|
|
SHA1_HASH_SIZE) != 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
goto done;
|
|
}
|
|
rc = compute_sha1(tokdata, pNewPin, ulNewLen, new_hash_sha);
|
|
rc |= compute_md5(tokdata, pNewPin, ulNewLen, hash_md5);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to compute hash for new pin.\n");
|
|
goto done;
|
|
}
|
|
/* The old PIN matches, now make sure its different
|
|
* than the new and is not the default. */
|
|
if ((memcmp(old_hash_sha, new_hash_sha, SHA1_HASH_SIZE) == 0) ||
|
|
(memcmp(new_hash_sha, default_user_pin_sha, SHA1_HASH_SIZE)
|
|
== 0)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID));
|
|
rc = CKR_PIN_INVALID;
|
|
goto done;
|
|
}
|
|
} else {
|
|
login_it = USER_KDF_LOGIN_IT;
|
|
memcpy(login_salt, USER_KDF_LOGIN_PURPOSE, 32);
|
|
rng_generate(tokdata, login_salt + 32, 32);
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen,
|
|
login_salt, 64,
|
|
login_it, EVP_sha512(),
|
|
256 / 8, new_login_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
wrap_it = USER_KDF_WRAP_IT;
|
|
memcpy(wrap_salt, USER_KDF_WRAP_PURPOSE, 32);
|
|
rng_generate(tokdata, wrap_salt + 32, 32);
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen,
|
|
wrap_salt, 64,
|
|
wrap_it, EVP_sha512(),
|
|
256 / 8, new_wrap_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pOldPin, ulOldLen,
|
|
dat_snap.user_login_salt, 64,
|
|
dat_snap.user_login_it,
|
|
EVP_sha512(), 256 / 8,
|
|
old_login_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen,
|
|
dat_snap.user_login_salt, 64,
|
|
dat_snap.user_login_it,
|
|
EVP_sha512(), 256 / 8,
|
|
new_login_key_old_salt);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
if (CRYPTO_memcmp(dat_snap.user_login_key,
|
|
old_login_key, 256 / 8) != 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID));
|
|
rc = CKR_PIN_INVALID;
|
|
goto done;
|
|
}
|
|
/* The old PIN matches, now make sure its different
|
|
* than the new and is not the default. */
|
|
if (CRYPTO_memcmp(old_login_key,
|
|
new_login_key_old_salt, 256 / 8) == 0)
|
|
{
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID));
|
|
rc = CKR_PIN_INVALID;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
memcpy(tokdata->nv_token_data->user_pin_sha, new_hash_sha,
|
|
SHA1_HASH_SIZE);
|
|
memcpy(tokdata->user_pin_md5, hash_md5, MD5_HASH_SIZE);
|
|
} else {
|
|
memcpy(dat->user_login_key, new_login_key, 256 / 8);
|
|
memcpy(dat->user_login_salt, login_salt, 64);
|
|
dat->user_login_it = login_it;
|
|
memcpy(tokdata->user_wrap_key, new_wrap_key, 256 / 8);
|
|
memcpy(dat->user_wrap_salt, wrap_salt, 64);
|
|
dat->user_wrap_it = wrap_it;
|
|
}
|
|
|
|
tokdata->nv_token_data->token_info.flags &=
|
|
~(CKF_USER_PIN_TO_BE_CHANGED);
|
|
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = save_token_data(tokdata, sess->session_info.slotID);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("Failed to save token data.\n");
|
|
goto done;
|
|
}
|
|
rc = save_masterkey_user(tokdata);
|
|
} else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) {
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
if (memcmp(so_pin_sha_snap, old_hash_sha,
|
|
SHA1_HASH_SIZE) != 0) {
|
|
rc = CKR_PIN_INCORRECT;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
goto done;
|
|
}
|
|
rc = compute_sha1(tokdata, pNewPin, ulNewLen, new_hash_sha);
|
|
rc |= compute_md5(tokdata, pNewPin, ulNewLen, hash_md5);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to compute hash for new pin.\n");
|
|
goto done;
|
|
}
|
|
/* The old PIN matches, now make sure its different
|
|
* than the new and is not the default.
|
|
*/
|
|
if ((memcmp(old_hash_sha, new_hash_sha, SHA1_HASH_SIZE) == 0) ||
|
|
(memcmp(new_hash_sha, default_so_pin_sha, SHA1_HASH_SIZE)
|
|
== 0)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID));
|
|
rc = CKR_PIN_INVALID;
|
|
goto done;
|
|
}
|
|
} else {
|
|
login_it = SO_KDF_LOGIN_IT;
|
|
memcpy(login_salt, SO_KDF_LOGIN_PURPOSE, 32);
|
|
rng_generate(tokdata, login_salt + 32, 32);
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen,
|
|
login_salt, 64,
|
|
login_it, EVP_sha512(),
|
|
256 / 8, new_login_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
wrap_it = SO_KDF_WRAP_IT;
|
|
memcpy(wrap_salt, SO_KDF_WRAP_PURPOSE, 32);
|
|
rng_generate(tokdata, wrap_salt + 32, 32);
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen,
|
|
wrap_salt, 64,
|
|
wrap_it, EVP_sha512(),
|
|
256 / 8, new_wrap_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pOldPin, ulOldLen,
|
|
dat_snap.so_login_salt, 64,
|
|
dat_snap.so_login_it,
|
|
EVP_sha512(), 256 / 8,
|
|
old_login_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pNewPin, ulNewLen,
|
|
dat_snap.so_login_salt, 64,
|
|
dat_snap.so_login_it,
|
|
EVP_sha512(), 256 / 8,
|
|
new_login_key_old_salt);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
if (CRYPTO_memcmp(dat_snap.so_login_key,
|
|
old_login_key, 256 / 8) != 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID));
|
|
rc = CKR_PIN_INVALID;
|
|
goto done;
|
|
}
|
|
/* The old PIN matches, now make sure its different
|
|
* than the new and is not the default. */
|
|
if (CRYPTO_memcmp(new_login_key_old_salt,
|
|
old_login_key, 256 / 8) == 0)
|
|
{
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID));
|
|
rc = CKR_PIN_INVALID;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
memcpy(tokdata->nv_token_data->so_pin_sha, new_hash_sha,
|
|
SHA1_HASH_SIZE);
|
|
memcpy(tokdata->so_pin_md5, hash_md5, MD5_HASH_SIZE);
|
|
} else {
|
|
memcpy(dat->so_login_key, new_login_key, 256 / 8);
|
|
memcpy(dat->so_login_salt, login_salt, 64);
|
|
dat->so_login_it = login_it;
|
|
memcpy(tokdata->so_wrap_key, new_wrap_key, 256 / 8);
|
|
memcpy(dat->so_wrap_salt, wrap_salt, 64);
|
|
dat->so_wrap_it = wrap_it;
|
|
}
|
|
|
|
tokdata->nv_token_data->token_info.flags &= ~(CKF_SO_PIN_TO_BE_CHANGED);
|
|
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = save_token_data(tokdata, sess->session_info.slotID);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("Failed to save token data.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = save_masterkey_so(tokdata);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("Failed to save SO's masterkey.\n");
|
|
} else {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY));
|
|
rc = CKR_SESSION_READ_ONLY;
|
|
}
|
|
|
|
done:
|
|
TRACE_INFO("C_SetPIN: rc = 0x%08lx, session = %lu\n",
|
|
rc, sSession->sessionh);
|
|
|
|
pthread_mutex_unlock(&tokdata->login_mutex);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
OPENSSL_cleanse(&dat_snap, sizeof(dat_snap));
|
|
OPENSSL_cleanse(pin_sha_snap, sizeof(pin_sha_snap));
|
|
OPENSSL_cleanse(so_pin_sha_snap, sizeof(so_pin_sha_snap));
|
|
OPENSSL_cleanse(old_login_key, sizeof(old_login_key));
|
|
OPENSSL_cleanse(new_login_key, sizeof(new_login_key));
|
|
OPENSSL_cleanse(new_wrap_key, sizeof(new_wrap_key));
|
|
OPENSSL_cleanse(new_login_key_old_salt, sizeof(new_login_key_old_salt));
|
|
OPENSSL_cleanse(old_hash_sha, sizeof(old_hash_sha));
|
|
OPENSSL_cleanse(new_hash_sha, sizeof(new_hash_sha));
|
|
OPENSSL_cleanse(hash_md5, sizeof(hash_md5));
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_OpenSession(STDLL_TokData_t *tokdata, CK_SLOT_ID sid, CK_FLAGS flags,
|
|
CK_SESSION_HANDLE_PTR phSession)
|
|
{
|
|
CK_RV rc = CKR_OK;
|
|
SESSION *sess;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
}
|
|
if (phSession == NULL) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
if (sid >= NUMBER_SLOTS_MANAGED) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID));
|
|
return CKR_SLOT_ID_INVALID;
|
|
}
|
|
flags |= CKF_SERIAL_SESSION;
|
|
if ((flags & CKF_RW_SESSION) == 0) {
|
|
if (session_mgr_so_session_exists(tokdata)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_WRITE_SO_EXISTS));
|
|
return CKR_SESSION_READ_WRITE_SO_EXISTS;
|
|
}
|
|
}
|
|
|
|
rc = session_mgr_new(tokdata, flags, sid, phSession);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("session_mgr_new() failed\n");
|
|
return rc;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, *phSession);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
return CKR_SESSION_HANDLE_INVALID;
|
|
}
|
|
|
|
sess->handle = *phSession;
|
|
|
|
TRACE_INFO("C_OpenSession: rc = 0x%08lx sess = %lu\n", rc, sess->handle);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_CloseSession(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BBOOL in_fork_initializer)
|
|
{
|
|
CK_RV rc = CKR_OK;
|
|
|
|
UNUSED(in_fork_initializer);
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
rc = session_mgr_close_session(tokdata, sSession->sessionh);
|
|
|
|
done:
|
|
TRACE_INFO("C_CloseSession: rc = 0x%08lx, sess = %lu\n",
|
|
rc, sSession->sessionh);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_CloseAllSessions(STDLL_TokData_t *tokdata, CK_SLOT_ID sid)
|
|
{
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
rc = session_mgr_close_all_sessions(tokdata);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("session_mgr_close_all_sessions() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_CloseAllSessions: rc = 0x%08lx, slot = %lu\n", rc, sid);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_GetSessionInfo(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_SESSION_INFO_PTR pInfo)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pInfo) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
memcpy(pInfo, &sess->session_info, sizeof(CK_SESSION_INFO));
|
|
|
|
done:
|
|
TRACE_INFO("C_GetSessionInfo: sess = %lu\n", sSession->sessionh);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_GetOperationState(STDLL_TokData_t *tokdata,
|
|
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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pulOperationStateLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (!pOperationState)
|
|
length_only = TRUE;
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
rc = session_mgr_get_op_state(tokdata, sess, length_only, pOperationState,
|
|
pulOperationStateLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("session_mgr_get_op_state() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_GetOperationState: rc = 0x%08lx, sess = %lu\n",
|
|
rc, sSession->sessionh);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_SetOperationState(STDLL_TokData_t *tokdata,
|
|
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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pOperationState || (ulOperationStateLen == 0)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
rc = session_mgr_set_op_state(tokdata, sess, hEncryptionKey,
|
|
hAuthenticationKey, pOperationState,
|
|
ulOperationStateLen);
|
|
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("session_mgr_set_op_state() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_SetOperationState: rc = 0x%08lx, sess = %lu\n",
|
|
rc, sSession->sessionh);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_SessionCancel(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_FLAGS flags)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
rc = session_mgr_cancel(tokdata, sess, flags);
|
|
|
|
done:
|
|
TRACE_INFO("SC_SessionCancel: sess = %lu\n", sSession->sessionh);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_Login(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_FLAGS_32 *flags = NULL;
|
|
CK_BYTE hash_sha[SHA1_HASH_SIZE];
|
|
CK_BYTE pin_sha_snap[SHA1_HASH_SIZE];
|
|
CK_RV rc = CKR_OK;
|
|
unsigned char login_key[32], wrap_key[32];
|
|
TOKEN_DATA_VERSION dat_snap;
|
|
|
|
/* In v2.11, logins should be exclusive, since token
|
|
* specific flags may need to be set for a bad login. - KEY
|
|
*/
|
|
if (pthread_mutex_lock(&tokdata->login_mutex)) {
|
|
TRACE_ERROR("Failed to get mutex lock.\n");
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
flags = &tokdata->nv_token_data->token_info.flags;
|
|
|
|
if (!pPin || ulPinLen > MAX_PIN_LEN) {
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
set_login_flags(userType, flags);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
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
|
|
*/
|
|
switch (userType) {
|
|
case CKU_USER:
|
|
if (session_mgr_so_session_exists(tokdata)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_ANOTHER_ALREADY_LOGGED_IN));
|
|
rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
|
|
}
|
|
if (session_mgr_user_session_exists(tokdata)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_ALREADY_LOGGED_IN));
|
|
rc = CKR_USER_ALREADY_LOGGED_IN;
|
|
}
|
|
break;
|
|
|
|
case CKU_SO:
|
|
if (session_mgr_user_session_exists(tokdata)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_ANOTHER_ALREADY_LOGGED_IN));
|
|
rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
|
|
}
|
|
if (session_mgr_so_session_exists(tokdata)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_ALREADY_LOGGED_IN));
|
|
rc = CKR_USER_ALREADY_LOGGED_IN;
|
|
}
|
|
if (session_mgr_readonly_session_exists(tokdata)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY_EXISTS));
|
|
rc = CKR_SESSION_READ_ONLY_EXISTS;
|
|
}
|
|
break;
|
|
|
|
case CKU_CONTEXT_SPECIFIC:
|
|
/*
|
|
* Although not explicitly required by the PKCS#11 standard, check that
|
|
* a USER session exists. C_Login with CKU_CONTEXT_SPECIFIC is performed
|
|
* due to CKA_ALWAYS_AUTHENTICATE=TRUE on a key used with an operation.
|
|
* CKA_ALWAYS_AUTHENTICATE=TRUE is only allowed for keys of class
|
|
* CKO_PRIVATE_KEY that have CKA_PRIVATE=TRUE. Key objects with
|
|
* CKA_PRIVATE=TRUE can only be accessed in a USER session, so a
|
|
* C_Login with CKU_CONTEXT_SPECIFIC can also only happen when a USER
|
|
* session exists.
|
|
*/
|
|
if (!session_mgr_user_session_exists(tokdata)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN));
|
|
rc = CKR_USER_NOT_LOGGED_IN;
|
|
}
|
|
if (!(sess->sign_ctx.active && sess->sign_ctx.auth_required) &&
|
|
!(sess->decr_ctx.active && sess->decr_ctx.auth_required)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
rc = CKR_USER_TYPE_INVALID;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_TYPE_INVALID));
|
|
break;
|
|
}
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
/*
|
|
* Snapshot the PIN material from shared memory under XProcLock so that a
|
|
* concurrent SC_SetPIN / SC_InitPIN in another process cannot overwrite it
|
|
* while we perform the (slow) PBKDF2 derivation below. Flag updates also
|
|
* happen under XProcLock so they are atomic with respect to other processes.
|
|
*/
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
dat_snap = tokdata->nv_token_data->dat;
|
|
memcpy(pin_sha_snap, tokdata->nv_token_data->user_pin_sha,
|
|
SHA1_HASH_SIZE);
|
|
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
switch (userType) {
|
|
case CKU_USER:
|
|
if (*flags & CKF_USER_PIN_LOCKED) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED));
|
|
rc = CKR_PIN_LOCKED;
|
|
goto done;
|
|
}
|
|
|
|
/*
|
|
* Check if token has a specific handler for this, otherwise
|
|
* fall back to default behavior.
|
|
*/
|
|
if (token_specific.t_login) {
|
|
// call the pluggable login function here - KEY
|
|
rc = token_specific.t_login(tokdata, sess, userType,
|
|
pPin, ulPinLen);
|
|
if (rc == CKR_OK || rc == CKR_PIN_INCORRECT) {
|
|
if (XProcLock(tokdata) != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
if (rc == CKR_OK)
|
|
*flags &= ~(CKF_USER_PIN_LOCKED |
|
|
CKF_USER_PIN_FINAL_TRY |
|
|
CKF_USER_PIN_COUNT_LOW);
|
|
else
|
|
set_login_flags(userType, flags);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
}
|
|
goto done;
|
|
}
|
|
|
|
if (!(*flags & CKF_USER_PIN_INITIALIZED)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_PIN_NOT_INITIALIZED));
|
|
rc = CKR_USER_PIN_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
if (memcmp(pin_sha_snap,
|
|
"00000000000000000000", SHA1_HASH_SIZE) == 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_PIN_NOT_INITIALIZED));
|
|
rc = CKR_USER_PIN_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("compute_sha1 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
if (memcmp(tokdata->nv_token_data->user_pin_sha, hash_sha,
|
|
SHA1_HASH_SIZE) != 0) {
|
|
set_login_flags(userType, flags);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
goto done;
|
|
}
|
|
/* Successful login, clear flags */
|
|
*flags &= ~(CKF_USER_PIN_LOCKED |
|
|
CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
compute_md5(tokdata, pPin, ulPinLen, tokdata->user_pin_md5);
|
|
memset(tokdata->so_pin_md5, 0x0, MD5_HASH_SIZE);
|
|
} else {
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen,
|
|
dat_snap.user_login_salt, 64,
|
|
dat_snap.user_login_it,
|
|
EVP_sha512(), 256 / 8, login_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen,
|
|
dat_snap.user_wrap_salt, 64,
|
|
dat_snap.user_wrap_it,
|
|
EVP_sha512(), 256 / 8, wrap_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
if (CRYPTO_memcmp(tokdata->nv_token_data->dat.user_login_key,
|
|
login_key, 256 / 8) != 0) {
|
|
set_login_flags(userType, flags);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
goto done;
|
|
}
|
|
|
|
/* Successful login, clear flags */
|
|
*flags &= ~(CKF_USER_PIN_LOCKED |
|
|
CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
memcpy(tokdata->user_wrap_key, wrap_key, 256 / 8);
|
|
memset(tokdata->so_wrap_key, 0, 256 / 8);
|
|
}
|
|
|
|
rc = load_masterkey_user(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("Failed to load user's masterkey.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
/* no need to return error here, we load the token data
|
|
* we can and syslog the rest
|
|
*/
|
|
load_private_token_objects(tokdata);
|
|
|
|
tokdata->global_shm->priv_loaded = TRUE;
|
|
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
break;
|
|
|
|
case CKU_SO:
|
|
if (*flags & CKF_SO_PIN_LOCKED) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED));
|
|
rc = CKR_PIN_LOCKED;
|
|
goto done;
|
|
}
|
|
|
|
/*
|
|
* Check if token has a specific handler for this, otherwise
|
|
* fall back to default behavior.
|
|
*/
|
|
if (token_specific.t_login) {
|
|
/* call the pluggable login function here - KEY */
|
|
rc = token_specific.t_login(tokdata, sess, userType,
|
|
pPin, ulPinLen);
|
|
if (rc == CKR_OK || rc == CKR_PIN_INCORRECT) {
|
|
if (XProcLock(tokdata) != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
if (rc == CKR_OK)
|
|
*flags &= ~(CKF_SO_PIN_LOCKED |
|
|
CKF_SO_PIN_FINAL_TRY | CKF_SO_PIN_COUNT_LOW);
|
|
else
|
|
set_login_flags(userType, flags);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
}
|
|
goto done;
|
|
}
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("compute_sha1 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
if (memcmp(tokdata->nv_token_data->so_pin_sha, hash_sha,
|
|
SHA1_HASH_SIZE) != 0) {
|
|
set_login_flags(userType, flags);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
goto done;
|
|
}
|
|
/* Successful login, clear flags */
|
|
*flags &= ~(CKF_SO_PIN_LOCKED | CKF_SO_PIN_FINAL_TRY |
|
|
CKF_SO_PIN_COUNT_LOW);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
compute_md5(tokdata, pPin, ulPinLen, tokdata->so_pin_md5);
|
|
memset(tokdata->user_pin_md5, 0x0, MD5_HASH_SIZE);
|
|
} else {
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen,
|
|
dat_snap.so_login_salt, 64,
|
|
dat_snap.so_login_it,
|
|
EVP_sha512(), 256 / 8, login_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen,
|
|
dat_snap.so_wrap_salt, 64,
|
|
dat_snap.so_wrap_it,
|
|
EVP_sha512(), 256 / 8, wrap_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
if (CRYPTO_memcmp(tokdata->nv_token_data->dat.so_login_key,
|
|
login_key, 256 / 8) != 0) {
|
|
set_login_flags(userType, flags);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
goto done;
|
|
}
|
|
|
|
/* Successful login, clear flags */
|
|
*flags &= ~(CKF_SO_PIN_LOCKED | CKF_SO_PIN_FINAL_TRY |
|
|
CKF_SO_PIN_COUNT_LOW);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
|
|
memcpy(tokdata->so_wrap_key, wrap_key, 256 / 8);
|
|
memset(tokdata->user_wrap_key, 0, 256 / 8);
|
|
}
|
|
|
|
rc = load_masterkey_so(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("Failed to load SO's masterkey.\n");
|
|
}
|
|
break;
|
|
|
|
case CKU_CONTEXT_SPECIFIC:
|
|
if (*flags & CKF_USER_PIN_LOCKED) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED));
|
|
rc = CKR_PIN_LOCKED;
|
|
goto done;
|
|
}
|
|
|
|
/*
|
|
* Check if token has a specific handler for this, otherwise
|
|
* fall back to default behavior.
|
|
*/
|
|
if (token_specific.t_login) {
|
|
// call the pluggable login function here - KEY
|
|
rc = token_specific.t_login(tokdata, sess, userType,
|
|
pPin, ulPinLen);
|
|
if (rc == CKR_OK || rc == CKR_PIN_INCORRECT) {
|
|
if (XProcLock(tokdata) != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
rc = CKR_FUNCTION_FAILED;
|
|
goto done;
|
|
}
|
|
if (rc == CKR_OK)
|
|
*flags &= ~(CKF_USER_PIN_LOCKED |
|
|
CKF_USER_PIN_FINAL_TRY |
|
|
CKF_USER_PIN_COUNT_LOW);
|
|
else
|
|
set_login_flags(userType, flags);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
}
|
|
goto done;
|
|
}
|
|
|
|
if (!(*flags & CKF_USER_PIN_INITIALIZED)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_PIN_NOT_INITIALIZED));
|
|
rc = CKR_USER_PIN_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (tokdata->version < TOK_NEW_DATA_STORE) {
|
|
rc = compute_sha1(tokdata, pPin, ulPinLen, hash_sha);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("compute_sha1 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
if (memcmp(tokdata->nv_token_data->user_pin_sha, hash_sha,
|
|
SHA1_HASH_SIZE) != 0) {
|
|
set_login_flags(userType, flags);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
goto done;
|
|
}
|
|
/* Successful login, clear flags */
|
|
*flags &= ~(CKF_USER_PIN_LOCKED |
|
|
CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
} else {
|
|
rc = compute_PKCS5_PBKDF2_HMAC(tokdata, pPin, ulPinLen,
|
|
dat_snap.user_login_salt, 64,
|
|
dat_snap.user_login_it,
|
|
EVP_sha512(), 256 / 8, login_key);
|
|
if (rc != CKR_OK) {
|
|
TRACE_DEVEL("PBKDF2 failed.\n");
|
|
goto done;
|
|
}
|
|
|
|
rc = XProcLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to get process lock.\n");
|
|
goto done;
|
|
}
|
|
if (CRYPTO_memcmp(tokdata->nv_token_data->dat.user_login_key,
|
|
login_key, 256 / 8) != 0) {
|
|
set_login_flags(userType, flags);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT));
|
|
rc = CKR_PIN_INCORRECT;
|
|
goto done;
|
|
}
|
|
|
|
/* Successful login, clear flags */
|
|
*flags &= ~(CKF_USER_PIN_LOCKED |
|
|
CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW);
|
|
rc = XProcUnLock(tokdata);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("Failed to release process lock.\n");
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Reset flag in operation context to indicate that a login has been
|
|
* successfully performed
|
|
*/
|
|
if (sess->sign_ctx.active && sess->sign_ctx.auth_required)
|
|
sess->sign_ctx.auth_required = FALSE;
|
|
if (sess->decr_ctx.active && sess->decr_ctx.auth_required)
|
|
sess->decr_ctx.auth_required = FALSE;
|
|
break;
|
|
|
|
default:
|
|
rc = CKR_USER_TYPE_INVALID;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_TYPE_INVALID));
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
if (rc == CKR_OK && userType != CKU_CONTEXT_SPECIFIC) {
|
|
rc = session_mgr_login_all(tokdata, userType);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("session_mgr_login_all failed.\n");
|
|
}
|
|
|
|
/*
|
|
* PKCS#11 states for failing C_Login with user type CKU_CONTEXT_SPECIFIC:
|
|
* '... repeated failed re-authentication attempts may cause the PIN to be
|
|
* locked. C_Login returns in this case CKR_PIN_LOCKED and this also logs
|
|
* the user out from the token'
|
|
*/
|
|
if (userType == CKU_CONTEXT_SPECIFIC &&
|
|
rc == CKR_PIN_INCORRECT &&
|
|
pin_locked(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags)) {
|
|
TRACE_DEVEL("USER pin now locked, logout the user\n");
|
|
session_mgr_logout_all(tokdata);
|
|
if (token_specific.t_logout) {
|
|
token_specific.t_logout(tokdata);
|
|
} else {
|
|
memset(tokdata->user_pin_md5, 0x0, MD5_HASH_SIZE);
|
|
memset(tokdata->so_pin_md5, 0x0, MD5_HASH_SIZE);
|
|
object_mgr_purge_private_token_objects(tokdata);
|
|
}
|
|
rc = CKR_PIN_LOCKED;
|
|
}
|
|
|
|
TRACE_INFO("C_Login: rc = 0x%08lx\n", rc);
|
|
if (sess)
|
|
save_token_data(tokdata, sess->session_info.slotID);
|
|
|
|
pthread_mutex_unlock(&tokdata->login_mutex);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
OPENSSL_cleanse(hash_sha, sizeof(hash_sha));
|
|
OPENSSL_cleanse(pin_sha_snap, sizeof(pin_sha_snap));
|
|
OPENSSL_cleanse(&dat_snap, sizeof(dat_snap));
|
|
OPENSSL_cleanse(login_key, sizeof(login_key));
|
|
OPENSSL_cleanse(wrap_key, sizeof(wrap_key));
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_Logout(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
}
|
|
|
|
if (pthread_mutex_lock(&tokdata->login_mutex)) {
|
|
TRACE_ERROR("Failed to get mutex lock.\n");
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
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(tokdata)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN));
|
|
rc = CKR_USER_NOT_LOGGED_IN;
|
|
goto done;
|
|
}
|
|
|
|
rc = session_mgr_logout_all(tokdata);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("session_mgr_logout_all failed.\n");
|
|
|
|
/* Check if token has a specific handler for this, otherwise fall back
|
|
* to default behaviour.
|
|
*/
|
|
if (token_specific.t_logout) {
|
|
rc = token_specific.t_logout(tokdata);
|
|
goto done;
|
|
}
|
|
|
|
memset(tokdata->user_pin_md5, 0x0, MD5_HASH_SIZE);
|
|
memset(tokdata->so_pin_md5, 0x0, MD5_HASH_SIZE);
|
|
|
|
object_mgr_purge_private_token_objects(tokdata);
|
|
|
|
done:
|
|
TRACE_INFO("C_Logout: rc = 0x%08lx\n", rc);
|
|
|
|
pthread_mutex_unlock(&tokdata->login_mutex);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_CreateObject(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|
CK_OBJECT_HANDLE_PTR phObject)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
/* Enforces policy */
|
|
rc = object_mgr_add(tokdata, sess, pTemplate, ulCount, phObject,
|
|
MODE_CREATE);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("object_mgr_add() failed.\n");
|
|
|
|
done:
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
TRACE_INFO("C_CreateObject: rc = 0x%08lx\n", rc);
|
|
|
|
#ifdef DEBUG
|
|
CK_ULONG i;
|
|
|
|
for (i = 0; i < ulCount; i++) {
|
|
if (pTemplate[i].type == CKA_CLASS &&
|
|
pTemplate[i].ulValueLen == sizeof(CK_ULONG) &&
|
|
pTemplate[i].pValue != NULL) {
|
|
TRACE_DEBUG("Object Type: 0x%02lx\n",
|
|
*((CK_ULONG *) pTemplate[i].pValue));
|
|
}
|
|
}
|
|
if (rc == CKR_OK)
|
|
TRACE_DEBUG("Handle: %lu\n", *phObject);
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_CopyObject(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
/* Enforces policy */
|
|
rc = object_mgr_copy(tokdata, sess, pTemplate, ulCount, hObject,
|
|
phNewObject);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("object_mgr_copy() failed\n");
|
|
|
|
done:
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
TRACE_INFO("C_CopyObject:rc = 0x%08lx,old handle = %lu, "
|
|
"new handle = %lu\n", rc, hObject, *phNewObject);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_DestroyObject(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_OBJECT_HANDLE hObject)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
rc = object_mgr_destroy_object(tokdata, sess, hObject);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("object_mgr_destroy_object() failed\n");
|
|
|
|
done:
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
TRACE_INFO("C_DestroyObject: rc = 0x%08lx, handle = %lu\n", rc, hObject);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_GetObjectSize(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
rc = object_mgr_get_object_size(tokdata, hObject, pulSize);
|
|
if (rc != CKR_OK)
|
|
TRACE_ERROR("object_mgr_get_object_size() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_GetObjectSize: rc = 0x%08lx, handle = %lu\n", rc, hObject);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_GetAttributeValue(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession,
|
|
CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate,
|
|
CK_ULONG ulCount)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
rc = object_mgr_get_attribute_values(tokdata, sess, hObject, pTemplate,
|
|
ulCount);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("object_mgr_get_attribute_value() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_GetAttributeValue: rc = 0x%08lx, handle = %lu\n",
|
|
rc, hObject);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
#ifdef DEBUG
|
|
CK_ATTRIBUTE *attr = NULL;
|
|
CK_BYTE val[4];
|
|
CK_ULONG i;
|
|
|
|
attr = pTemplate;
|
|
for (i = 0; i < ulCount && attr != NULL; i++, attr++) {
|
|
TRACE_DEBUG("%lu: Attribute type: 0x%08lx, Value Length: %lu\n",
|
|
i, attr->type, attr->ulValueLen);
|
|
if (rc == CKR_OK && attr->ulValueLen != CK_UNAVAILABLE_INFORMATION) {
|
|
if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) {
|
|
memset(val, 0, sizeof(val));
|
|
memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ?
|
|
sizeof(val) : attr->ulValueLen);
|
|
TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n",
|
|
val[0], val[1], val[2], val[3]);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_SetAttributeValue(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession,
|
|
CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate,
|
|
CK_ULONG ulCount)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
rc = object_mgr_set_attribute_values(tokdata, sess, hObject, pTemplate,
|
|
ulCount);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("object_mgr_set_attribute_values() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_SetAttributeValue: rc = 0x%08lx, handle = %lu\n",
|
|
rc, hObject);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
#ifdef DEBUG
|
|
CK_ATTRIBUTE *attr = NULL;
|
|
CK_BYTE val[4];
|
|
CK_ULONG i;
|
|
|
|
attr = pTemplate;
|
|
for (i = 0; i < ulCount && attr != NULL; i++, attr++) {
|
|
TRACE_DEBUG("%lu: Attribute type: 0x%08lx, Value Length: %lu\n",
|
|
i, attr->type, attr->ulValueLen);
|
|
|
|
if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) {
|
|
memset(val, 0, sizeof(val));
|
|
memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ?
|
|
sizeof(val) : attr->ulValueLen);
|
|
TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n",
|
|
val[0], val[1], val[2], val[3]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_FindObjectsInit(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession,
|
|
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->find_active == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE));
|
|
rc = CKR_OPERATION_ACTIVE;
|
|
goto done;
|
|
}
|
|
|
|
rc = object_mgr_find_init(tokdata, sess, pTemplate, ulCount);
|
|
|
|
done:
|
|
TRACE_INFO("C_FindObjectsInit: rc = 0x%08lx\n", rc);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
#ifdef DEBUG
|
|
CK_ATTRIBUTE *attr = NULL;
|
|
CK_BYTE val[4];
|
|
CK_ULONG i;
|
|
|
|
attr = pTemplate;
|
|
for (i = 0; i < ulCount && attr != NULL; i++, attr++) {
|
|
TRACE_DEBUG("%lu: Attribute type: 0x%08lx, Value Length: %lu\n",
|
|
i, attr->type, attr->ulValueLen);
|
|
|
|
if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) {
|
|
memset(val, 0, sizeof(val));
|
|
memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ?
|
|
sizeof(val) : attr->ulValueLen);
|
|
TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n",
|
|
val[0], val[1], val[2], val[3]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_FindObjects(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!phObject || !pulObjectCount) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->find_active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!sess->find_list) {
|
|
TRACE_DEVEL("sess->find_list is NULL.\n");
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
count = MIN(ulMaxObjectCount, (sess->find_count - sess->find_idx));
|
|
|
|
memcpy(phObject, sess->find_list + sess->find_idx,
|
|
count * sizeof(CK_OBJECT_HANDLE));
|
|
*pulObjectCount = count;
|
|
|
|
sess->find_idx += count;
|
|
rc = CKR_OK;
|
|
|
|
done:
|
|
TRACE_INFO("C_FindObjects: rc = 0x%08lx, returned %lu objects\n",
|
|
rc, count);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_FindObjectsFinal(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->find_active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
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:
|
|
TRACE_INFO("C_FindObjectsFinal: rc = 0x%08lx\n", rc);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_EncryptInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
if (pMechanism == NULL) {
|
|
/* As per PKCS#11 v3.0 Init with NULL pMechanism cancels operation */
|
|
rc = session_mgr_cancel(tokdata, sess, CKF_ENCRYPT);
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_ENCRYPT);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
if (sess->encr_ctx.active == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE));
|
|
rc = CKR_OPERATION_ACTIVE;
|
|
goto done;
|
|
}
|
|
|
|
sess->encr_ctx.count_statistics = TRUE;
|
|
rc = encr_mgr_init(tokdata, sess, &sess->encr_ctx, OP_ENCRYPT_INIT,
|
|
pMechanism, hKey, TRUE);
|
|
|
|
done:
|
|
TRACE_INFO("C_EncryptInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pMechanism ? pMechanism->mechanism : (CK_ULONG)(-1)));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_Encrypt(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pData || !pulEncryptedDataLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->encr_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pEncryptedData)
|
|
length_only = TRUE;
|
|
|
|
rc = encr_mgr_encrypt(tokdata, sess, length_only, &sess->encr_ctx, pData,
|
|
ulDataLen, pEncryptedData, pulEncryptedDataLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("encr_mgr_encrypt() failed.\n");
|
|
|
|
done:
|
|
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
|
|
if (sess)
|
|
encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
|
|
}
|
|
|
|
TRACE_INFO("C_Encrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_EncryptUpdate(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if ((!pPart && ulPartLen != 0) || !pulEncryptedPartLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->encr_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pEncryptedPart)
|
|
length_only = TRUE;
|
|
|
|
rc = encr_mgr_encrypt_update(tokdata, sess, length_only,
|
|
&sess->encr_ctx, pPart, ulPartLen,
|
|
pEncryptedPart, pulEncryptedPartLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("encr_mgr_encrypt_update() failed.\n");
|
|
|
|
done:
|
|
if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) {
|
|
if (sess)
|
|
encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
|
|
}
|
|
|
|
TRACE_INFO("C_EncryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_EncryptFinal(STDLL_TokData_t * tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pulLastEncryptedPartLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->encr_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pLastEncryptedPart)
|
|
length_only = TRUE;
|
|
|
|
rc = encr_mgr_encrypt_final(tokdata, sess, length_only, &sess->encr_ctx,
|
|
pLastEncryptedPart, pulLastEncryptedPartLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_ERROR("encr_mgr_encrypt_final() failed.\n");
|
|
|
|
done:
|
|
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
|
|
if (sess)
|
|
encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
|
|
}
|
|
|
|
TRACE_INFO("C_EncryptFinal: rc = 0x%08lx, sess = %ld\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_DecryptInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
if (pMechanism == NULL) {
|
|
/* As per PKCS#11 v3.0 Init with NULL pMechanism cancels operation */
|
|
rc = session_mgr_cancel(tokdata, sess, CKF_DECRYPT);
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_DECRYPT);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
if (sess->decr_ctx.active == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE));
|
|
rc = CKR_OPERATION_ACTIVE;
|
|
goto done;
|
|
}
|
|
|
|
sess->decr_ctx.count_statistics = TRUE;
|
|
rc = decr_mgr_init(tokdata, sess, &sess->decr_ctx, OP_DECRYPT_INIT,
|
|
pMechanism, hKey, TRUE, TRUE);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("decr_mgr_init() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_DecryptInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pMechanism ? pMechanism->mechanism : (CK_ULONG)-1));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, 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;
|
|
unsigned int mask;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pEncryptedData || !pulDataLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->decr_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pData)
|
|
length_only = TRUE;
|
|
|
|
rc = decr_mgr_decrypt(tokdata, sess, length_only, &sess->decr_ctx,
|
|
pEncryptedData, ulEncryptedDataLen, pData,
|
|
pulDataLen);
|
|
/* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
|
|
mask = constant_time_is_zero(
|
|
is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
|
|
mask &= ~constant_time_eq(rc, CKR_OK);
|
|
if (mask)
|
|
TRACE_DEVEL("decr_mgr_decrypt() failed.\n");
|
|
|
|
done:
|
|
/* (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) */
|
|
mask = ~constant_time_eq(rc, CKR_OK);
|
|
mask |= constant_time_is_zero(length_only);
|
|
mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
|
|
if (mask) {
|
|
if (sess)
|
|
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
|
|
}
|
|
|
|
TRACE_INFO("C_Decrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
ulEncryptedDataLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
|
|
CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_BBOOL length_only = FALSE;
|
|
CK_RV rc = CKR_OK;
|
|
unsigned int mask;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if ((!pEncryptedPart && ulEncryptedPartLen != 0) || !pulPartLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->decr_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pPart)
|
|
length_only = TRUE;
|
|
|
|
rc = decr_mgr_decrypt_update(tokdata, sess, length_only,
|
|
&sess->decr_ctx, pEncryptedPart,
|
|
ulEncryptedPartLen, pPart, pulPartLen);
|
|
/* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
|
|
mask = constant_time_is_zero(
|
|
is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
|
|
mask &= ~constant_time_eq(rc, CKR_OK);
|
|
if (mask)
|
|
TRACE_DEVEL("decr_mgr_decrypt_update() failed.\n");
|
|
|
|
done:
|
|
/* (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL */
|
|
mask = ~constant_time_eq(rc, CKR_OK);
|
|
mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
|
|
if (mask) {
|
|
if (sess)
|
|
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
|
|
}
|
|
|
|
TRACE_INFO("C_DecryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
ulEncryptedPartLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_BBOOL length_only = FALSE;
|
|
CK_RV rc = CKR_OK;
|
|
unsigned int mask;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pulLastPartLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->decr_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pLastPart)
|
|
length_only = TRUE;
|
|
|
|
rc = decr_mgr_decrypt_final(tokdata, sess, length_only, &sess->decr_ctx,
|
|
pLastPart, pulLastPartLen);
|
|
/* (!is_rsa_mechanism(sess->decr_ctx.mech.mechanism) && rc != CKR_OK) */
|
|
mask = constant_time_is_zero(
|
|
is_rsa_mechanism(sess->decr_ctx.mech.mechanism));
|
|
mask &= ~constant_time_eq(rc, CKR_OK);
|
|
if (mask)
|
|
TRACE_DEVEL("decr_mgr_decrypt_final() failed.\n");
|
|
|
|
done:
|
|
/* (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) */
|
|
mask = ~constant_time_eq(rc, CKR_OK);
|
|
mask |= constant_time_is_zero(length_only);
|
|
mask &= ~constant_time_eq(rc, CKR_BUFFER_TOO_SMALL);
|
|
if (mask) {
|
|
if (sess)
|
|
decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
|
|
}
|
|
|
|
TRACE_INFO("C_DecryptFinal: rc = 0x%08lx, sess = %ld, amount = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pulLastPartLen ? *pulLastPartLen : 0));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_DigestInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_MECHANISM_PTR pMechanism)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
if (pMechanism == NULL) {
|
|
/* As per PKCS#11 v3.0 Init with NULL pMechanism cancels operation */
|
|
rc = session_mgr_cancel(tokdata, sess, CKF_DIGEST);
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_DIGEST);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
if (sess->digest_ctx.active == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE));
|
|
rc = CKR_OPERATION_ACTIVE;
|
|
goto done;
|
|
}
|
|
|
|
sess->digest_ctx.count_statistics = TRUE;
|
|
rc = digest_mgr_init(tokdata, sess, &sess->digest_ctx, pMechanism, TRUE);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("digest_mgr_init() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_DigestInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pMechanism ? pMechanism->mechanism : (CK_ULONG)-1));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_Digest(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->digest_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pDigest)
|
|
length_only = TRUE;
|
|
|
|
rc = digest_mgr_digest(tokdata, sess, length_only, &sess->digest_ctx,
|
|
pData, ulDataLen, pDigest, pulDigestLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("digest_mgr_digest() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_Digest: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_DigestUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->digest_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
/* If there is data to hash, do so. */
|
|
if (ulPartLen) {
|
|
rc = digest_mgr_digest_update(tokdata, sess, &sess->digest_ctx,
|
|
pPart, ulPartLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("digest_mgr_digest_update() failed.\n");
|
|
}
|
|
|
|
done:
|
|
TRACE_INFO("C_DigestUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_DigestKey(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_OBJECT_HANDLE hKey)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->digest_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
rc = digest_mgr_digest_key(tokdata, sess, &sess->digest_ctx, hKey);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("digest_mgr_digest_key() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_DigestKey: rc = 0x%08lx, sess = %ld, key = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, hKey);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_DigestFinal(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->digest_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pDigest)
|
|
length_only = TRUE;
|
|
|
|
rc = digest_mgr_digest_final(tokdata, sess, length_only,
|
|
&sess->digest_ctx, pDigest, pulDigestLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_ERROR("digest_mgr_digest_final() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_DigestFinal: rc = 0x%08lx, sess = %ld\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_SignInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
if (pMechanism == NULL) {
|
|
/* As per PKCS#11 v3.0 Init with NULL pMechanism cancels operation */
|
|
rc = session_mgr_cancel(tokdata, sess, CKF_SIGN);
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_SIGN);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
if (sess->sign_ctx.active == TRUE) {
|
|
rc = CKR_OPERATION_ACTIVE;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE));
|
|
goto done;
|
|
}
|
|
|
|
sess->sign_ctx.count_statistics = TRUE;
|
|
rc = sign_mgr_init(tokdata, sess, &sess->sign_ctx, pMechanism, FALSE, hKey,
|
|
TRUE, TRUE);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("sign_mgr_init() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_SignInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pMechanism ? pMechanism->mechanism : (CK_ULONG)-1));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_Sign(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pData || !pulSignatureLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->sign_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pSignature)
|
|
length_only = TRUE;
|
|
|
|
rc = sign_mgr_sign(tokdata, sess, length_only, &sess->sign_ctx, pData,
|
|
ulDataLen, pSignature, pulSignatureLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("sign_mgr_sign() failed.\n");
|
|
|
|
done:
|
|
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
|
|
if (sess != NULL)
|
|
sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
|
|
}
|
|
|
|
TRACE_INFO("C_Sign: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_SignUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pPart && ulPartLen != 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->sign_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
rc = sign_mgr_sign_update(tokdata, sess, &sess->sign_ctx, pPart, ulPartLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("sign_mgr_sign_update() failed.\n");
|
|
|
|
done:
|
|
if (rc != CKR_OK && sess != NULL)
|
|
sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
|
|
|
|
TRACE_INFO("C_SignUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_SignFinal(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pulSignatureLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->sign_ctx.active == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pSignature)
|
|
length_only = TRUE;
|
|
|
|
rc = sign_mgr_sign_final(tokdata, sess, length_only, &sess->sign_ctx,
|
|
pSignature, pulSignatureLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_ERROR("sign_mgr_sign_final() failed.\n");
|
|
|
|
done:
|
|
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
|
|
if (sess != NULL)
|
|
sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
|
|
}
|
|
|
|
TRACE_INFO("C_SignFinal: rc = 0x%08lx, sess = %ld\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_SignRecoverInit(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession,
|
|
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
if (pMechanism == NULL) {
|
|
/* As per PKCS#11 v3.0 Init with NULL pMechanism cancels operation */
|
|
rc = session_mgr_cancel(tokdata, sess, CKF_SIGN_RECOVER);
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_SIGN_RECOVER);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
if (sess->sign_ctx.active == TRUE) {
|
|
rc = CKR_OPERATION_ACTIVE;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE));
|
|
goto done;
|
|
}
|
|
|
|
rc = sign_mgr_init(tokdata, sess, &sess->sign_ctx, pMechanism, TRUE, hKey,
|
|
TRUE, TRUE);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("sign_mgr_init() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_SignRecoverInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pMechanism ? pMechanism->mechanism : (CK_ULONG)-1));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_SignRecover(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pData || !pulSignatureLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if ((sess->sign_ctx.active == FALSE) || (sess->sign_ctx.recover == FALSE)) {
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
goto done;
|
|
}
|
|
|
|
if (!pSignature)
|
|
length_only = TRUE;
|
|
|
|
rc = sign_mgr_sign_recover(tokdata, sess, length_only, &sess->sign_ctx,
|
|
pData, ulDataLen, pSignature, pulSignatureLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("sign_mgr_sign_recover() failed.\n");
|
|
|
|
done:
|
|
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
|
|
if (sess != NULL)
|
|
sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
|
|
}
|
|
|
|
TRACE_INFO("C_SignRecover: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
static CK_RV VerifyInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
|
|
CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
if (pMechanism == NULL) {
|
|
/* As per PKCS#11 v3.0 Init with NULL pMechanism cancels operation */
|
|
rc = session_mgr_cancel(tokdata, sess, CKF_VERIFY);
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_VERIFY);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
if (sess->verify_ctx.active == TRUE) {
|
|
rc = CKR_OPERATION_ACTIVE;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE));
|
|
goto done;
|
|
}
|
|
|
|
if (pSignature != NULL && ulSignatureLen != 0) {
|
|
/* Save signature in context for later verification */
|
|
sess->verify_ctx.saved_signature = malloc(ulSignatureLen);
|
|
if (sess->verify_ctx.saved_signature == NULL) {
|
|
rc = CKR_HOST_MEMORY;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
goto done;
|
|
}
|
|
|
|
memcpy(sess->verify_ctx.saved_signature, pSignature, ulSignatureLen);
|
|
sess->verify_ctx.saved_signature_len = ulSignatureLen;
|
|
}
|
|
|
|
sess->verify_ctx.count_statistics = TRUE;
|
|
rc = verify_mgr_init(tokdata, sess, &sess->verify_ctx, pMechanism,
|
|
FALSE, hKey, TRUE);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("verify_mgr_init() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_Verify%sInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n",
|
|
pSignature != NULL && ulSignatureLen != 0 ? "Signature" : "",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pMechanism ? pMechanism->mechanism : (CK_ULONG)-1));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_VerifyInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
|
|
{
|
|
return VerifyInit(tokdata, sSession, pMechanism, hKey, NULL, 0);
|
|
}
|
|
|
|
static CK_RV Verify(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pData) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->verify_ctx.active == FALSE) {
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
goto done;
|
|
}
|
|
|
|
if (sess->verify_ctx.saved_signature == NULL && pSignature == NULL) {
|
|
/* Operation was initialized with C_VerifyInit() */
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->verify_ctx.saved_signature != NULL && pSignature != NULL) {
|
|
/* Operation was initialized with C_VerifySignatureInit() */
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
rc = verify_mgr_verify(tokdata, sess, &sess->verify_ctx, pData, ulDataLen,
|
|
sess->verify_ctx.saved_signature != NULL ?
|
|
sess->verify_ctx.saved_signature :
|
|
pSignature,
|
|
sess->verify_ctx.saved_signature != NULL ?
|
|
sess->verify_ctx.saved_signature_len :
|
|
ulSignatureLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("verify_mgr_verify() failed.\n");
|
|
|
|
done:
|
|
if (sess != NULL)
|
|
verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
|
|
|
|
TRACE_INFO("C_Verify%s: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
|
|
pSignature == NULL ? "Signature" : "",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_Verify(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
|
|
CK_ULONG ulSignatureLen)
|
|
{
|
|
return Verify(tokdata, sSession, pData, ulDataLen,
|
|
pSignature, ulSignatureLen);
|
|
}
|
|
|
|
static CK_RV VerifyUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pPart, CK_ULONG ulPartLen,
|
|
CK_BBOOL verify_message)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pPart && ulPartLen != 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->verify_ctx.active == FALSE) {
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
goto done;
|
|
}
|
|
|
|
if ((sess->verify_ctx.saved_signature != NULL) != verify_message) {
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
goto done;
|
|
}
|
|
|
|
rc = verify_mgr_verify_update(tokdata, sess, &sess->verify_ctx, pPart,
|
|
ulPartLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("verify_mgr_verify_update() failed.\n");
|
|
|
|
done:
|
|
if (rc != CKR_OK && sess != NULL)
|
|
verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
|
|
|
|
TRACE_INFO("C_Verify%sUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
|
|
(sess != NULL && sess->verify_ctx.saved_signature != NULL) ?
|
|
"Signature" : "",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_VerifyUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
|
|
{
|
|
return VerifyUpdate(tokdata, sSession, pPart, ulPartLen, FALSE);
|
|
}
|
|
|
|
static CK_RV VerifyFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->verify_ctx.active == FALSE) {
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
goto done;
|
|
}
|
|
|
|
if (pSignature == NULL && sess->verify_ctx.saved_signature == NULL) {
|
|
/* Operation was initialized with C_VerifyInit() */
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
goto done;
|
|
}
|
|
|
|
if (pSignature != NULL && sess->verify_ctx.saved_signature != NULL) {
|
|
/* Operation was initialized with C_VerifySignatureInit() */
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
goto done;
|
|
}
|
|
|
|
rc = verify_mgr_verify_final(tokdata, sess, &sess->verify_ctx,
|
|
sess->verify_ctx.saved_signature != NULL ?
|
|
sess->verify_ctx.saved_signature :
|
|
pSignature,
|
|
sess->verify_ctx.saved_signature != NULL ?
|
|
sess->verify_ctx.saved_signature_len :
|
|
ulSignatureLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("verify_mgr_verify_final() failed.\n");
|
|
|
|
done:
|
|
if (sess != NULL)
|
|
verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
|
|
|
|
TRACE_INFO("C_Verify%sFinal: rc = 0x%08lx, sess = %ld\n",
|
|
pSignature == NULL ? "Signature" : "",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_VerifyFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
|
|
{
|
|
if (pSignature == NULL || ulSignatureLen == 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
return VerifyFinal(tokdata, sSession, pSignature, ulSignatureLen);
|
|
}
|
|
|
|
CK_RV SC_VerifyRecoverInit(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession,
|
|
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
if (pMechanism == NULL) {
|
|
/* As per PKCS#11 v3.0 Init with NULL pMechanism cancels operation */
|
|
rc = session_mgr_cancel(tokdata, sess, CKF_VERIFY_RECOVER);
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_VERIFY_RECOVER);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
if (sess->verify_ctx.active == TRUE) {
|
|
rc = CKR_OPERATION_ACTIVE;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE));
|
|
goto done;
|
|
}
|
|
|
|
rc = verify_mgr_init(tokdata, sess, &sess->verify_ctx, pMechanism,
|
|
TRUE, hKey, TRUE);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("verify_mgr_init() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_VerifyRecoverInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pMechanism ? pMechanism->mechanism : (CK_ULONG)-1));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_VerifyRecover(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (!pSignature || !pulDataLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
if ((sess->verify_ctx.active == FALSE) ||
|
|
(sess->verify_ctx.recover == FALSE)) {
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
goto done;
|
|
}
|
|
|
|
if (!pData)
|
|
length_only = TRUE;
|
|
|
|
rc = verify_mgr_verify_recover(tokdata, sess, length_only,
|
|
&sess->verify_ctx, pSignature,
|
|
ulSignatureLen, pData, pulDataLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("verify_mgr_verify_recover() failed.\n");
|
|
|
|
done:
|
|
if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
|
|
if (sess != NULL)
|
|
verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
|
|
}
|
|
|
|
TRACE_INFO("C_VerifyRecover: rc = 0x%08lx, sess = %ld, recover len = %lu, "
|
|
"length_only = %d\n", rc,
|
|
(sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pulDataLen ? *pulDataLen : 0), length_only);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_VerifySignatureInit(STDLL_TokData_t *tokdata, ST_SESSION_T *sSession,
|
|
CK_MECHANISM_PTR pMechanism,
|
|
CK_OBJECT_HANDLE hKey,
|
|
CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
|
|
{
|
|
if (pSignature == NULL || ulSignatureLen == 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
return VerifyInit(tokdata, sSession, pMechanism, hKey,
|
|
pSignature, ulSignatureLen);
|
|
}
|
|
|
|
CK_RV SC_VerifySignature(STDLL_TokData_t *tokdata, ST_SESSION_T *sSession,
|
|
CK_BYTE_PTR pData, CK_ULONG ulDataLen)
|
|
{
|
|
return Verify(tokdata, sSession, pData, ulDataLen, NULL, 0);
|
|
}
|
|
|
|
CK_RV SC_VerifySignatureUpdate(STDLL_TokData_t *tokdata, ST_SESSION_T *sSession,
|
|
CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
|
|
{
|
|
return VerifyUpdate(tokdata, sSession, pPart, ulPartLen, TRUE);
|
|
}
|
|
|
|
CK_RV SC_VerifySignatureFinal(STDLL_TokData_t *tokdata, ST_SESSION_T *sSession)
|
|
{
|
|
return VerifyFinal(tokdata, sSession, NULL, 0);
|
|
}
|
|
|
|
CK_RV SC_DigestEncryptUpdate(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart,
|
|
CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
|
|
CK_ULONG_PTR pulEncryptedPartLen)
|
|
{
|
|
CK_RV rc;
|
|
|
|
rc = SC_EncryptUpdate(tokdata, sSession, pPart, ulPartLen,
|
|
pEncryptedPart, pulEncryptedPartLen);
|
|
if (rc != CKR_OK || pEncryptedPart == NULL)
|
|
goto out;
|
|
|
|
rc = SC_DigestUpdate(tokdata, sSession, pPart, ulPartLen);
|
|
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_DecryptDigestUpdate(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pEncryptedPart,
|
|
CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
|
|
CK_ULONG_PTR pulPartLen)
|
|
{
|
|
CK_RV rc;
|
|
|
|
rc = SC_DecryptUpdate(tokdata, sSession, pEncryptedPart,
|
|
ulEncryptedPartLen, pPart, pulPartLen);
|
|
if (rc != CKR_OK || pPart == NULL)
|
|
goto out;
|
|
|
|
rc = SC_DigestUpdate(tokdata, sSession, pPart, *pulPartLen);
|
|
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_SignEncryptUpdate(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart,
|
|
CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
|
|
CK_ULONG_PTR pulEncryptedPartLen)
|
|
{
|
|
CK_RV rc;
|
|
|
|
rc = SC_EncryptUpdate(tokdata, sSession, pPart, ulPartLen,
|
|
pEncryptedPart, pulEncryptedPartLen);
|
|
if (rc != CKR_OK || pEncryptedPart == NULL)
|
|
goto out;
|
|
|
|
rc = SC_SignUpdate(tokdata, sSession, pPart, ulPartLen);
|
|
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_DecryptVerifyUpdate(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pEncryptedPart,
|
|
CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
|
|
CK_ULONG_PTR pulPartLen)
|
|
{
|
|
CK_RV rc;
|
|
|
|
rc = SC_DecryptUpdate(tokdata, sSession, pEncryptedPart,
|
|
ulEncryptedPartLen, pPart, pulPartLen);
|
|
if (rc != CKR_OK || pPart == NULL)
|
|
goto out;
|
|
|
|
rc = SC_VerifyUpdate(tokdata, sSession, pPart, *pulPartLen);
|
|
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_GenerateKey(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate,
|
|
CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pMechanism || !phKey || (pTemplate == NULL && ulCount != 0)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_GENERATE);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
rc = tokdata->policy->is_mech_allowed(tokdata->policy, pMechanism, NULL,
|
|
POLICY_CHECK_KEYGEN, sess);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("POLICY VIOLATION: Key generation mechanism not allowed\n");
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
rc = key_mgr_generate_key(tokdata, sess, pMechanism, pTemplate,
|
|
ulCount, phKey, TRUE, OP_KEYGEN);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("key_mgr_generate_key() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_GenerateKey: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n", rc,
|
|
(sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pMechanism ? pMechanism->mechanism : (CK_ULONG)-1));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
#ifdef DEBUG
|
|
CK_ATTRIBUTE *attr = NULL;
|
|
CK_BYTE val[4];
|
|
CK_ULONG i;
|
|
|
|
attr = pTemplate;
|
|
for (i = 0; i < ulCount && attr != NULL; i++, attr++) {
|
|
TRACE_DEBUG("%lu: Attribute type: 0x%08lx, Value Length: %lu\n",
|
|
i, attr->type, attr->ulValueLen);
|
|
|
|
if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) {
|
|
memset(val, 0, sizeof(val));
|
|
memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ?
|
|
sizeof(val) : attr->ulValueLen);
|
|
TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n",
|
|
val[0], val[1], val[2], val[3]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_GenerateKeyPair(STDLL_TokData_t *tokdata,
|
|
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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pMechanism || !phPublicKey || !phPrivateKey ||
|
|
(!pPublicKeyTemplate && (ulPublicKeyAttributeCount != 0)) ||
|
|
(!pPrivateKeyTemplate && (ulPrivateKeyAttributeCount != 0))) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_GENERATE_KEY_PAIR);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
rc = tokdata->policy->is_mech_allowed(tokdata->policy, pMechanism, NULL,
|
|
POLICY_CHECK_KEYGEN, sess);
|
|
if (rc != CKR_OK) {
|
|
TRACE_ERROR("POLICY VIOLATION: Keypair generation mechanism not allowed\n");
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
rc = key_mgr_generate_key_pair(tokdata, sess, pMechanism,
|
|
pPublicKeyTemplate,
|
|
ulPublicKeyAttributeCount,
|
|
pPrivateKeyTemplate,
|
|
ulPrivateKeyAttributeCount,
|
|
phPublicKey, phPrivateKey, TRUE, OP_KEYGEN);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("key_mgr_generate_key_pair() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_GenerateKeyPair: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n",
|
|
rc, (sess == NULL) ? -1 : ((CK_LONG) sess->handle),
|
|
(pMechanism ? pMechanism->mechanism : (CK_ULONG)-1));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
#ifdef DEBUG
|
|
CK_ATTRIBUTE *attr;
|
|
CK_ULONG i;
|
|
|
|
if (rc == CKR_OK) {
|
|
TRACE_DEBUG("Public handle: %lu, Private handle: %lu\n",
|
|
*phPublicKey, *phPrivateKey);
|
|
}
|
|
|
|
TRACE_DEBUG("Public Template:\n");
|
|
attr = pPublicKeyTemplate;
|
|
for (i = 0; i < ulPublicKeyAttributeCount && attr != NULL; i++, attr++) {
|
|
TRACE_DEBUG_DUMPATTR(attr);
|
|
}
|
|
|
|
TRACE_DEBUG("Private Template:\n");
|
|
attr = pPrivateKeyTemplate;
|
|
for (i = 0; i < ulPrivateKeyAttributeCount && attr != NULL; i++, attr++) {
|
|
TRACE_DEBUG_DUMPATTR(attr);
|
|
}
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_WrapKey(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pMechanism || !pulWrappedKeyLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_WRAP);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
if (!pWrappedKey)
|
|
length_only = TRUE;
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
rc = key_mgr_wrap_key(tokdata, sess, length_only, pMechanism,
|
|
hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen,
|
|
TRUE, OP_WRAP);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("key_mgr_wrap_key() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_WrapKey: rc = 0x%08lx, sess = %ld, encrypting key = %lu, "
|
|
"wrapped key = %lu\n", rc,
|
|
(sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
hWrappingKey, hKey);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_UnwrapKey(STDLL_TokData_t *tokdata, 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;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pMechanism || !pWrappedKey || (!pTemplate && ulCount != 0) || !phKey) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_UNWRAP);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
rc = key_mgr_unwrap_key(tokdata, sess, pMechanism, pTemplate, ulCount,
|
|
pWrappedKey, ulWrappedKeyLen, hUnwrappingKey,
|
|
phKey, TRUE, OP_UNWRAP);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("key_mgr_unwrap_key() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_UnwrapKey: rc = 0x%08lx, sess = %ld, decrypting key = %lu,"
|
|
"unwrapped key = %lu\n", rc,
|
|
(sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
hUnwrappingKey, (phKey ? *phKey : 0));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
#ifdef DEBUG
|
|
CK_ATTRIBUTE *attr = NULL;
|
|
CK_BYTE val[4];
|
|
CK_ULONG i;
|
|
|
|
attr = pTemplate;
|
|
for (i = 0; i < ulCount && attr != NULL; i++, attr++) {
|
|
TRACE_DEBUG("%lu: Attribute type: 0x%08lx, Value Length: %lu\n",
|
|
i, attr->type, attr->ulValueLen);
|
|
|
|
if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) {
|
|
memset(val, 0, sizeof(val));
|
|
memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ?
|
|
sizeof(val) : attr->ulValueLen);
|
|
TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n",
|
|
val[0], val[1], val[2], val[3]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_DeriveKey(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
|
|
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|
CK_OBJECT_HANDLE_PTR phKey)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pMechanism || (!pTemplate && ulCount != 0)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
if (pMechanism->mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE && !phKey) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_DERIVE);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
rc = key_mgr_derive_key(tokdata, sess, pMechanism, hBaseKey, phKey,
|
|
pTemplate, ulCount, TRUE, OP_DERIVE);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("key_mgr_derive_key() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_DeriveKey: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pMechanism ? pMechanism->mechanism : (CK_ULONG)(-1)));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
#ifdef DEBUG
|
|
CK_ATTRIBUTE *attr = NULL;
|
|
CK_BYTE val[4];
|
|
CK_ULONG i;
|
|
|
|
if (rc == CKR_OK) {
|
|
switch (pMechanism->mechanism) {
|
|
case CKM_SSL3_KEY_AND_MAC_DERIVE:
|
|
{
|
|
CK_SSL3_KEY_MAT_PARAMS *pReq;
|
|
CK_SSL3_KEY_MAT_OUT *pPtr;
|
|
pReq = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter;
|
|
pPtr = pReq->pReturnedKeyMaterial;
|
|
|
|
TRACE_DEBUG("Client MAC key: %lu, Server MAC key: %lu, "
|
|
"Client Key: %lu, Server Key: %lu\n",
|
|
pPtr->hClientMacSecret,
|
|
pPtr->hServerMacSecret, pPtr->hClientKey,
|
|
pPtr->hServerKey);
|
|
}
|
|
break;
|
|
case CKM_DH_PKCS_DERIVE:
|
|
TRACE_DEBUG("DH Shared Secret:\n");
|
|
break;
|
|
default:
|
|
TRACE_DEBUG("Derived key: %lu\n", *phKey);
|
|
}
|
|
}
|
|
|
|
attr = pTemplate;
|
|
for (i = 0; i < ulCount && attr != NULL; i++, attr++) {
|
|
TRACE_DEBUG("%lu: Attribute type: 0x%08lx, Value Length: %lu\n",
|
|
i, attr->type, attr->ulValueLen);
|
|
|
|
if (attr->ulValueLen >= sizeof(val) && attr->pValue != NULL) {
|
|
memset(val, 0, sizeof(val));
|
|
memcpy(val, attr->pValue, attr->ulValueLen > sizeof(val) ?
|
|
sizeof(val) : attr->ulValueLen);
|
|
TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n",
|
|
val[0], val[1], val[2], val[3]);
|
|
}
|
|
}
|
|
#endif /* DEBUG */
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_SeedRandom(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
|
|
{
|
|
UNUSED(sSession);
|
|
UNUSED(pSeed);
|
|
UNUSED(ulSeedLen);
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
}
|
|
|
|
TRACE_ERROR("%s\n", ock_err(ERR_RANDOM_SEED_NOT_SUPPORTED));
|
|
|
|
return CKR_RANDOM_SEED_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
CK_RV SC_GenerateRandom(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pRandomData && ulRandomLen != 0) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (ulRandomLen == 0)
|
|
goto done;
|
|
|
|
rc = rng_generate(tokdata, pRandomData, ulRandomLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("rng_generate() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("C_GenerateRandom: rc = 0x%08lx, %lu bytes\n", rc, ulRandomLen);
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CK_RV SC_GetFunctionStatus(STDLL_TokData_t *tokdata,
|
|
ST_SESSION_HANDLE *sSession)
|
|
{
|
|
UNUSED(sSession);
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
}
|
|
|
|
TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_PARALLEL));
|
|
|
|
return CKR_FUNCTION_NOT_PARALLEL;
|
|
}
|
|
|
|
|
|
CK_RV SC_CancelFunction(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession)
|
|
{
|
|
UNUSED(sSession);
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
}
|
|
|
|
TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_PARALLEL));
|
|
|
|
return CKR_FUNCTION_NOT_PARALLEL;
|
|
}
|
|
|
|
CK_RV SC_EncapsulateKey(STDLL_TokData_t *tokdata, ST_SESSION_T *sSession,
|
|
CK_MECHANISM_PTR pMechanism,
|
|
CK_OBJECT_HANDLE hPublicKey,
|
|
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
|
|
CK_BYTE_PTR pCiphertext, CK_ULONG_PTR pulCiphertextLen,
|
|
CK_OBJECT_HANDLE_PTR phKey)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_BBOOL length_only = FALSE;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pMechanism || !pulCiphertextLen) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_ENCAPSULATE);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
if (!pCiphertext)
|
|
length_only = TRUE;
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
rc = key_mgr_encapsulate_key(tokdata, sess, length_only, pMechanism,
|
|
hPublicKey, pTemplate, ulAttributeCount,
|
|
pCiphertext, pulCiphertextLen, phKey,
|
|
TRUE);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("key_mgr_encapsulate_key() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("SC_EncapsulateKey: rc = 0x%08lx, sess = %ld, priv key = %lu, "
|
|
"ciphertext = %lu, encpsed key = %lu\n", rc,
|
|
(sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
hPublicKey, (pulCiphertextLen ? *pulCiphertextLen : 0),
|
|
(phKey ? *phKey : 0));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_DecapsulateKey(STDLL_TokData_t *tokdata, ST_SESSION_T *sSession,
|
|
CK_MECHANISM_PTR pMechanism,
|
|
CK_OBJECT_HANDLE hPrivateKey,
|
|
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
|
|
CK_BYTE_PTR pCiphertext, CK_ULONG ulCiphertextLen,
|
|
CK_OBJECT_HANDLE_PTR phKey)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pMechanism || !pCiphertext) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pMechanism, CKF_DECAPSULATE);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
rc = key_mgr_decapsulate_key(tokdata, sess, pMechanism,
|
|
hPrivateKey, pTemplate, ulAttributeCount,
|
|
pCiphertext, ulCiphertextLen, phKey,
|
|
TRUE);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("key_mgr_decapsulate_key() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("SC_DecapsulateKey: rc = 0x%08lx, sess = %ld, pub key = %lu, "
|
|
"encpsed key = %lu\n", rc,
|
|
(sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
hPrivateKey, (phKey ? *phKey : 0));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_IBM_ReencryptSingle(STDLL_TokData_t *tokdata, ST_SESSION_T *sSession,
|
|
CK_MECHANISM_PTR pDecrMech,
|
|
CK_OBJECT_HANDLE hDecrKey,
|
|
CK_MECHANISM_PTR pEncrMech,
|
|
CK_OBJECT_HANDLE hEncrKey,
|
|
CK_BYTE_PTR pEncryptedData,
|
|
CK_ULONG ulEncryptedDataLen,
|
|
CK_BYTE_PTR pReencryptedData,
|
|
CK_ULONG_PTR pulReencryptedDataLen)
|
|
{
|
|
SESSION *sess = NULL;
|
|
CK_RV rc = CKR_OK;
|
|
|
|
if (tokdata->initialized == FALSE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED));
|
|
rc = CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
goto done;
|
|
}
|
|
|
|
if (!pDecrMech || !pEncrMech) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD));
|
|
rc = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
|
|
sess = session_mgr_find_reset_error(tokdata, sSession->sessionh);
|
|
if (!sess) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
|
|
rc = CKR_SESSION_HANDLE_INVALID;
|
|
goto done;
|
|
}
|
|
|
|
rc = valid_mech(tokdata, pDecrMech, CKF_DECRYPT);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
rc = valid_mech(tokdata, pEncrMech, CKF_ENCRYPT);
|
|
if (rc != CKR_OK)
|
|
goto done;
|
|
|
|
if (pin_expired(&sess->session_info,
|
|
tokdata->nv_token_data->token_info.flags) == TRUE) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED));
|
|
rc = CKR_PIN_EXPIRED;
|
|
goto done;
|
|
}
|
|
|
|
if (sess->decr_ctx.active == TRUE || sess->encr_ctx.active == TRUE) {
|
|
rc = CKR_OPERATION_ACTIVE;
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE));
|
|
goto done;
|
|
}
|
|
|
|
sess->decr_ctx.count_statistics = TRUE;
|
|
sess->encr_ctx.count_statistics = TRUE;
|
|
rc = encr_mgr_reencrypt_single(tokdata, sess, &sess->decr_ctx, pDecrMech,
|
|
hDecrKey, &sess->encr_ctx, pEncrMech,
|
|
hEncrKey, pEncryptedData, ulEncryptedDataLen,
|
|
pReencryptedData, pulReencryptedDataLen);
|
|
if (rc != CKR_OK)
|
|
TRACE_DEVEL("encr_mgr_reencrypt_single() failed.\n");
|
|
|
|
done:
|
|
TRACE_INFO("SC_IBM_ReencryptSingle: rc = 0x%08lx, sess = %ld, "
|
|
"decrmech = 0x%lx, encrmech = 0x%lx\n",
|
|
rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle,
|
|
(pDecrMech ? pDecrMech->mechanism : (CK_ULONG)-1),
|
|
(pEncrMech ? pEncrMech->mechanism : (CK_ULONG)-1));
|
|
|
|
if (sess != NULL)
|
|
session_mgr_put(tokdata, sess);
|
|
|
|
return rc;
|
|
}
|
|
|
|
CK_RV SC_HandleEvent(STDLL_TokData_t *tokdata, unsigned int event_type,
|
|
unsigned int event_flags, const char *payload,
|
|
unsigned int payload_len)
|
|
{
|
|
CK_RV rc;
|
|
|
|
if (token_specific.t_handle_event == NULL)
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
|
|
rc = token_specific.t_handle_event(tokdata, event_type, event_flags,
|
|
payload, payload_len);
|
|
|
|
TRACE_INFO("SC_HandleEvent: rc = 0x%08lx, event_type = 0x%08x, "
|
|
"event_flags = 0x%08x\n", rc, event_type, event_flags);
|
|
|
|
return rc;
|
|
}
|
|
|
|
void SC_SetFunctionList(void)
|
|
{
|
|
function_list.ST_Initialize = ST_Initialize;
|
|
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 = SC_EncryptUpdate;
|
|
function_list.ST_EncryptFinal = SC_EncryptFinal;
|
|
function_list.ST_DecryptInit = SC_DecryptInit;
|
|
function_list.ST_Decrypt = SC_Decrypt;
|
|
function_list.ST_DecryptUpdate = SC_DecryptUpdate;
|
|
function_list.ST_DecryptFinal = 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 = SC_DigestEncryptUpdate;
|
|
function_list.ST_DecryptDigestUpdate = SC_DecryptDigestUpdate;
|
|
function_list.ST_SignEncryptUpdate = SC_SignEncryptUpdate;
|
|
function_list.ST_DecryptVerifyUpdate = SC_DecryptVerifyUpdate;
|
|
function_list.ST_GenerateKey = SC_GenerateKey;
|
|
function_list.ST_GenerateKeyPair = SC_GenerateKeyPair;
|
|
function_list.ST_WrapKey = SC_WrapKey;
|
|
function_list.ST_UnwrapKey = SC_UnwrapKey;
|
|
function_list.ST_DeriveKey = SC_DeriveKey;
|
|
function_list.ST_SeedRandom = SC_SeedRandom;
|
|
function_list.ST_GenerateRandom = SC_GenerateRandom;
|
|
function_list.ST_GetFunctionStatus = NULL; // SC_GetFunctionStatus;
|
|
function_list.ST_CancelFunction = NULL; // SC_CancelFunction;
|
|
function_list.ST_SessionCancel = SC_SessionCancel;
|
|
function_list.ST_EncapsulateKey = SC_EncapsulateKey;
|
|
function_list.ST_DecapsulateKey = SC_DecapsulateKey;
|
|
function_list.ST_VerifySignatureInit = SC_VerifySignatureInit;
|
|
function_list.ST_VerifySignature = SC_VerifySignature;
|
|
function_list.ST_VerifySignatureUpdate = SC_VerifySignatureUpdate;
|
|
function_list.ST_VerifySignatureFinal = SC_VerifySignatureFinal;
|
|
|
|
function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle;
|
|
|
|
function_list.ST_HandleEvent = SC_HandleEvent;
|
|
}
|