mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-11-04 10:05:51 +00:00
2390 lines
61 KiB
C
2390 lines
61 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* session.c
|
|
*
|
|
* This file implements the NSSCKFWSession type and methods.
|
|
*/
|
|
|
|
#ifndef CK_T
|
|
#include "ck.h"
|
|
#endif /* CK_T */
|
|
|
|
/*
|
|
* NSSCKFWSession
|
|
*
|
|
* -- create/destroy --
|
|
* nssCKFWSession_Create
|
|
* nssCKFWSession_Destroy
|
|
*
|
|
* -- public accessors --
|
|
* NSSCKFWSession_GetMDSession
|
|
* NSSCKFWSession_GetArena
|
|
* NSSCKFWSession_CallNotification
|
|
* NSSCKFWSession_IsRWSession
|
|
* NSSCKFWSession_IsSO
|
|
* NSSCKFWSession_GetFWSlot
|
|
*
|
|
* -- implement public accessors --
|
|
* nssCKFWSession_GetMDSession
|
|
* nssCKFWSession_GetArena
|
|
* nssCKFWSession_CallNotification
|
|
* nssCKFWSession_IsRWSession
|
|
* nssCKFWSession_IsSO
|
|
* nssCKFWSession_GetFWSlot
|
|
*
|
|
* -- private accessors --
|
|
* nssCKFWSession_GetSessionState
|
|
* nssCKFWSession_SetFWFindObjects
|
|
* nssCKFWSession_GetFWFindObjects
|
|
* nssCKFWSession_SetMDSession
|
|
* nssCKFWSession_SetHandle
|
|
* nssCKFWSession_GetHandle
|
|
* nssCKFWSession_RegisterSessionObject
|
|
* nssCKFWSession_DeegisterSessionObject
|
|
*
|
|
* -- module fronts --
|
|
* nssCKFWSession_GetDeviceError
|
|
* nssCKFWSession_Login
|
|
* nssCKFWSession_Logout
|
|
* nssCKFWSession_InitPIN
|
|
* nssCKFWSession_SetPIN
|
|
* nssCKFWSession_GetOperationStateLen
|
|
* nssCKFWSession_GetOperationState
|
|
* nssCKFWSession_SetOperationState
|
|
* nssCKFWSession_CreateObject
|
|
* nssCKFWSession_CopyObject
|
|
* nssCKFWSession_FindObjectsInit
|
|
* nssCKFWSession_SeedRandom
|
|
* nssCKFWSession_GetRandom
|
|
*/
|
|
|
|
struct NSSCKFWSessionStr {
|
|
NSSArena *arena;
|
|
NSSCKMDSession *mdSession;
|
|
NSSCKFWToken *fwToken;
|
|
NSSCKMDToken *mdToken;
|
|
NSSCKFWInstance *fwInstance;
|
|
NSSCKMDInstance *mdInstance;
|
|
CK_VOID_PTR pApplication;
|
|
CK_NOTIFY Notify;
|
|
|
|
/*
|
|
* Everything above is set at creation time, and then not modified.
|
|
* The items below are atomic. No locking required. If we fear
|
|
* about pointer-copies being nonatomic, we'll lock fwFindObjects.
|
|
*/
|
|
|
|
CK_BBOOL rw;
|
|
NSSCKFWFindObjects *fwFindObjects;
|
|
NSSCKFWCryptoOperation *fwOperationArray[NSSCKFWCryptoOperationState_Max];
|
|
nssCKFWHash *sessionObjectHash;
|
|
CK_SESSION_HANDLE hSession;
|
|
};
|
|
|
|
#ifdef DEBUG
|
|
/*
|
|
* But first, the pointer-tracking stuff.
|
|
*
|
|
* NOTE: the pointer-tracking support in NSS/base currently relies
|
|
* upon NSPR's CallOnce support. That, however, relies upon NSPR's
|
|
* locking, which is tied into the runtime. We need a pointer-tracker
|
|
* implementation that uses the locks supplied through C_Initialize.
|
|
* That support, however, can be filled in later. So for now, I'll
|
|
* just do this routines as no-ops.
|
|
*/
|
|
|
|
static CK_RV
|
|
session_add_pointer(
|
|
const NSSCKFWSession *fwSession)
|
|
{
|
|
return CKR_OK;
|
|
}
|
|
|
|
static CK_RV
|
|
session_remove_pointer(
|
|
const NSSCKFWSession *fwSession)
|
|
{
|
|
return CKR_OK;
|
|
}
|
|
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_verifyPointer(
|
|
const NSSCKFWSession *fwSession)
|
|
{
|
|
return CKR_OK;
|
|
}
|
|
|
|
#endif /* DEBUG */
|
|
|
|
/*
|
|
* nssCKFWSession_Create
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT NSSCKFWSession *
|
|
nssCKFWSession_Create(
|
|
NSSCKFWToken *fwToken,
|
|
CK_BBOOL rw,
|
|
CK_VOID_PTR pApplication,
|
|
CK_NOTIFY Notify,
|
|
CK_RV *pError)
|
|
{
|
|
NSSArena *arena = (NSSArena *)NULL;
|
|
NSSCKFWSession *fwSession;
|
|
NSSCKFWSlot *fwSlot;
|
|
|
|
#ifdef NSSDEBUG
|
|
if (!pError) {
|
|
return (NSSCKFWSession *)NULL;
|
|
}
|
|
|
|
*pError = nssCKFWToken_verifyPointer(fwToken);
|
|
if (CKR_OK != *pError) {
|
|
return (NSSCKFWSession *)NULL;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
arena = NSSArena_Create();
|
|
if (!arena) {
|
|
*pError = CKR_HOST_MEMORY;
|
|
return (NSSCKFWSession *)NULL;
|
|
}
|
|
|
|
fwSession = nss_ZNEW(arena, NSSCKFWSession);
|
|
if (!fwSession) {
|
|
*pError = CKR_HOST_MEMORY;
|
|
goto loser;
|
|
}
|
|
|
|
fwSession->arena = arena;
|
|
fwSession->mdSession = (NSSCKMDSession *)NULL; /* set later */
|
|
fwSession->fwToken = fwToken;
|
|
fwSession->mdToken = nssCKFWToken_GetMDToken(fwToken);
|
|
|
|
fwSlot = nssCKFWToken_GetFWSlot(fwToken);
|
|
fwSession->fwInstance = nssCKFWSlot_GetFWInstance(fwSlot);
|
|
fwSession->mdInstance = nssCKFWSlot_GetMDInstance(fwSlot);
|
|
|
|
fwSession->rw = rw;
|
|
fwSession->pApplication = pApplication;
|
|
fwSession->Notify = Notify;
|
|
|
|
fwSession->fwFindObjects = (NSSCKFWFindObjects *)NULL;
|
|
|
|
fwSession->sessionObjectHash = nssCKFWHash_Create(fwSession->fwInstance, arena, pError);
|
|
if (!fwSession->sessionObjectHash) {
|
|
if (CKR_OK == *pError) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
}
|
|
goto loser;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
*pError = session_add_pointer(fwSession);
|
|
if (CKR_OK != *pError) {
|
|
goto loser;
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
return fwSession;
|
|
|
|
loser:
|
|
if (arena) {
|
|
if (fwSession && fwSession->sessionObjectHash) {
|
|
(void)nssCKFWHash_Destroy(fwSession->sessionObjectHash);
|
|
}
|
|
NSSArena_Destroy(arena);
|
|
}
|
|
|
|
return (NSSCKFWSession *)NULL;
|
|
}
|
|
|
|
static void
|
|
nss_ckfw_session_object_destroy_iterator(
|
|
const void *key,
|
|
void *value,
|
|
void *closure)
|
|
{
|
|
NSSCKFWObject *fwObject = (NSSCKFWObject *)value;
|
|
nssCKFWObject_Finalize(fwObject, PR_TRUE);
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_Destroy
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_Destroy(
|
|
NSSCKFWSession *fwSession,
|
|
CK_BBOOL removeFromTokenHash)
|
|
{
|
|
CK_RV error = CKR_OK;
|
|
nssCKFWHash *sessionObjectHash;
|
|
NSSCKFWCryptoOperationState i;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (removeFromTokenHash) {
|
|
error = nssCKFWToken_RemoveSession(fwSession->fwToken, fwSession);
|
|
}
|
|
|
|
/*
|
|
* Invalidate session objects
|
|
*/
|
|
|
|
sessionObjectHash = fwSession->sessionObjectHash;
|
|
fwSession->sessionObjectHash = (nssCKFWHash *)NULL;
|
|
|
|
nssCKFWHash_Iterate(sessionObjectHash,
|
|
nss_ckfw_session_object_destroy_iterator,
|
|
(void *)NULL);
|
|
|
|
for (i = 0; i < NSSCKFWCryptoOperationState_Max; i++) {
|
|
if (fwSession->fwOperationArray[i]) {
|
|
nssCKFWCryptoOperation_Destroy(fwSession->fwOperationArray[i]);
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
(void)session_remove_pointer(fwSession);
|
|
#endif /* DEBUG */
|
|
(void)nssCKFWHash_Destroy(sessionObjectHash);
|
|
NSSArena_Destroy(fwSession->arena);
|
|
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_GetMDSession
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT NSSCKMDSession *
|
|
nssCKFWSession_GetMDSession(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return (NSSCKMDSession *)NULL;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
return fwSession->mdSession;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_GetArena
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT NSSArena *
|
|
nssCKFWSession_GetArena(
|
|
NSSCKFWSession *fwSession,
|
|
CK_RV *pError)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
if (!pError) {
|
|
return (NSSArena *)NULL;
|
|
}
|
|
|
|
*pError = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != *pError) {
|
|
return (NSSArena *)NULL;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
return fwSession->arena;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_CallNotification
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_CallNotification(
|
|
NSSCKFWSession *fwSession,
|
|
CK_NOTIFICATION event)
|
|
{
|
|
CK_RV error = CKR_OK;
|
|
CK_SESSION_HANDLE handle;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if ((CK_NOTIFY)NULL == fwSession->Notify) {
|
|
return CKR_OK;
|
|
}
|
|
|
|
handle = nssCKFWInstance_FindSessionHandle(fwSession->fwInstance, fwSession);
|
|
if ((CK_SESSION_HANDLE)0 == handle) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
|
|
error = fwSession->Notify(handle, event, fwSession->pApplication);
|
|
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_IsRWSession
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_BBOOL
|
|
nssCKFWSession_IsRWSession(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return CK_FALSE;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
return fwSession->rw;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_IsSO
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_BBOOL
|
|
nssCKFWSession_IsSO(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
CK_STATE state;
|
|
|
|
#ifdef NSSDEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return CK_FALSE;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
state = nssCKFWToken_GetSessionState(fwSession->fwToken);
|
|
switch (state) {
|
|
case CKS_RO_PUBLIC_SESSION:
|
|
case CKS_RO_USER_FUNCTIONS:
|
|
case CKS_RW_PUBLIC_SESSION:
|
|
case CKS_RW_USER_FUNCTIONS:
|
|
return CK_FALSE;
|
|
case CKS_RW_SO_FUNCTIONS:
|
|
return CK_TRUE;
|
|
default:
|
|
return CK_FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_GetFWSlot
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT NSSCKFWSlot *
|
|
nssCKFWSession_GetFWSlot(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return (NSSCKFWSlot *)NULL;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
return nssCKFWToken_GetFWSlot(fwSession->fwToken);
|
|
}
|
|
|
|
/*
|
|
* nssCFKWSession_GetSessionState
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_STATE
|
|
nssCKFWSession_GetSessionState(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return CKS_RO_PUBLIC_SESSION; /* whatever */
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
return nssCKFWToken_GetSessionState(fwSession->fwToken);
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_SetFWFindObjects
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_SetFWFindObjects(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWFindObjects *fwFindObjects)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
CK_RV error = CKR_OK;
|
|
#endif /* NSSDEBUG */
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
/* fwFindObjects may be null */
|
|
#endif /* NSSDEBUG */
|
|
|
|
if ((fwSession->fwFindObjects) &&
|
|
(fwFindObjects)) {
|
|
return CKR_OPERATION_ACTIVE;
|
|
}
|
|
|
|
fwSession->fwFindObjects = fwFindObjects;
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_GetFWFindObjects
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT NSSCKFWFindObjects *
|
|
nssCKFWSession_GetFWFindObjects(
|
|
NSSCKFWSession *fwSession,
|
|
CK_RV *pError)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
if (!pError) {
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
|
|
*pError = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != *pError) {
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (!fwSession->fwFindObjects) {
|
|
*pError = CKR_OPERATION_NOT_INITIALIZED;
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
|
|
return fwSession->fwFindObjects;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_SetMDSession
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_SetMDSession(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKMDSession *mdSession)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
CK_RV error = CKR_OK;
|
|
#endif /* NSSDEBUG */
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!mdSession) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
|
|
fwSession->mdSession = mdSession;
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_SetHandle
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_SetHandle(
|
|
NSSCKFWSession *fwSession,
|
|
CK_SESSION_HANDLE hSession)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
CK_RV error = CKR_OK;
|
|
#endif /* NSSDEBUG */
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if ((CK_SESSION_HANDLE)0 != fwSession->hSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
|
|
fwSession->hSession = hSession;
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_GetHandle
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_SESSION_HANDLE
|
|
nssCKFWSession_GetHandle(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return NULL;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
return fwSession->hSession;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_RegisterSessionObject
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_RegisterSessionObject(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWObject *fwObject)
|
|
{
|
|
CK_RV rv = CKR_OK;
|
|
|
|
#ifdef NSSDEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (fwSession->sessionObjectHash) {
|
|
rv = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_DeregisterSessionObject
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_DeregisterSessionObject(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWObject *fwObject)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (fwSession->sessionObjectHash) {
|
|
nssCKFWHash_Remove(fwSession->sessionObjectHash, fwObject);
|
|
}
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_GetDeviceError
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_ULONG
|
|
nssCKFWSession_GetDeviceError(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return (CK_ULONG)0;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return (CK_ULONG)0;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (!fwSession->mdSession->GetDeviceError) {
|
|
return (CK_ULONG)0;
|
|
}
|
|
|
|
return fwSession->mdSession->GetDeviceError(fwSession->mdSession,
|
|
fwSession, fwSession->mdToken, fwSession->fwToken,
|
|
fwSession->mdInstance, fwSession->fwInstance);
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_Login
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_Login(
|
|
NSSCKFWSession *fwSession,
|
|
CK_USER_TYPE userType,
|
|
NSSItem *pin)
|
|
{
|
|
CK_RV error = CKR_OK;
|
|
CK_STATE oldState;
|
|
CK_STATE newState;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
switch (userType) {
|
|
case CKU_SO:
|
|
case CKU_USER:
|
|
break;
|
|
default:
|
|
return CKR_USER_TYPE_INVALID;
|
|
}
|
|
|
|
if (!pin) {
|
|
if (CK_TRUE != nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken)) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
oldState = nssCKFWToken_GetSessionState(fwSession->fwToken);
|
|
|
|
/*
|
|
* It's not clear what happens when you're already logged in.
|
|
* I'll just fail; but if we decide to change, the logic is
|
|
* all right here.
|
|
*/
|
|
|
|
if (CKU_SO == userType) {
|
|
switch (oldState) {
|
|
case CKS_RO_PUBLIC_SESSION:
|
|
/*
|
|
* There's no such thing as a read-only security officer
|
|
* session, so fail. The error should be CKR_SESSION_READ_ONLY,
|
|
* except that C_Login isn't defined to return that. So we'll
|
|
* do CKR_SESSION_READ_ONLY_EXISTS, which is what is documented.
|
|
*/
|
|
return CKR_SESSION_READ_ONLY_EXISTS;
|
|
case CKS_RO_USER_FUNCTIONS:
|
|
return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
|
|
case CKS_RW_PUBLIC_SESSION:
|
|
newState =
|
|
CKS_RW_SO_FUNCTIONS;
|
|
break;
|
|
case CKS_RW_USER_FUNCTIONS:
|
|
return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
|
|
case CKS_RW_SO_FUNCTIONS:
|
|
return CKR_USER_ALREADY_LOGGED_IN;
|
|
default:
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
} else /* CKU_USER == userType */ {
|
|
switch (oldState) {
|
|
case CKS_RO_PUBLIC_SESSION:
|
|
newState =
|
|
CKS_RO_USER_FUNCTIONS;
|
|
break;
|
|
case CKS_RO_USER_FUNCTIONS:
|
|
return CKR_USER_ALREADY_LOGGED_IN;
|
|
case CKS_RW_PUBLIC_SESSION:
|
|
newState =
|
|
CKS_RW_USER_FUNCTIONS;
|
|
break;
|
|
case CKS_RW_USER_FUNCTIONS:
|
|
return CKR_USER_ALREADY_LOGGED_IN;
|
|
case CKS_RW_SO_FUNCTIONS:
|
|
return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
|
|
default:
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* So now we're in one of three cases:
|
|
*
|
|
* Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_SO_FUNCTIONS;
|
|
* Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_USER_FUNCTIONS;
|
|
* Old == CKS_RO_PUBLIC_SESSION, New == CKS_RO_USER_FUNCTIONS;
|
|
*/
|
|
|
|
if (!fwSession->mdSession->Login) {
|
|
/*
|
|
* The Module doesn't want to be informed (or check the pin)
|
|
* it'll just rely on the Framework as needed.
|
|
*/
|
|
;
|
|
} else {
|
|
error = fwSession->mdSession->Login(fwSession->mdSession, fwSession,
|
|
fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
|
|
fwSession->fwInstance, userType, pin, oldState, newState);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
}
|
|
|
|
(void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState);
|
|
return CKR_OK;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_Logout
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_Logout(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
CK_RV error = CKR_OK;
|
|
CK_STATE oldState;
|
|
CK_STATE newState;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
oldState = nssCKFWToken_GetSessionState(fwSession->fwToken);
|
|
|
|
switch (oldState) {
|
|
case CKS_RO_PUBLIC_SESSION:
|
|
return CKR_USER_NOT_LOGGED_IN;
|
|
case CKS_RO_USER_FUNCTIONS:
|
|
newState = CKS_RO_PUBLIC_SESSION;
|
|
break;
|
|
case CKS_RW_PUBLIC_SESSION:
|
|
return CKR_USER_NOT_LOGGED_IN;
|
|
case CKS_RW_USER_FUNCTIONS:
|
|
newState = CKS_RW_PUBLIC_SESSION;
|
|
break;
|
|
case CKS_RW_SO_FUNCTIONS:
|
|
newState = CKS_RW_PUBLIC_SESSION;
|
|
break;
|
|
default:
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
|
|
/*
|
|
* So now we're in one of three cases:
|
|
*
|
|
* Old == CKS_RW_SO_FUNCTIONS, New == CKS_RW_PUBLIC_SESSION;
|
|
* Old == CKS_RW_USER_FUNCTIONS, New == CKS_RW_PUBLIC_SESSION;
|
|
* Old == CKS_RO_USER_FUNCTIONS, New == CKS_RO_PUBLIC_SESSION;
|
|
*/
|
|
|
|
if (!fwSession->mdSession->Logout) {
|
|
/*
|
|
* The Module doesn't want to be informed. Okay.
|
|
*/
|
|
;
|
|
} else {
|
|
error = fwSession->mdSession->Logout(fwSession->mdSession, fwSession,
|
|
fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
|
|
fwSession->fwInstance, oldState, newState);
|
|
if (CKR_OK != error) {
|
|
/*
|
|
* Now what?! A failure really should end up with the Framework
|
|
* considering it logged out, right?
|
|
*/
|
|
;
|
|
}
|
|
}
|
|
|
|
(void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState);
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_InitPIN
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_InitPIN(
|
|
NSSCKFWSession *fwSession,
|
|
NSSItem *pin)
|
|
{
|
|
CK_RV error = CKR_OK;
|
|
CK_STATE state;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
state = nssCKFWToken_GetSessionState(fwSession->fwToken);
|
|
if (CKS_RW_SO_FUNCTIONS != state) {
|
|
return CKR_USER_NOT_LOGGED_IN;
|
|
}
|
|
|
|
if (!pin) {
|
|
CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
|
|
if (CK_TRUE != has) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
}
|
|
|
|
if (!fwSession->mdSession->InitPIN) {
|
|
return CKR_TOKEN_WRITE_PROTECTED;
|
|
}
|
|
|
|
error = fwSession->mdSession->InitPIN(fwSession->mdSession, fwSession,
|
|
fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
|
|
fwSession->fwInstance, pin);
|
|
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_SetPIN
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_SetPIN(
|
|
NSSCKFWSession *fwSession,
|
|
const NSSItem *oldPin,
|
|
NSSItem *newPin)
|
|
{
|
|
CK_RV error = CKR_OK;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (!newPin) {
|
|
CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
|
|
if (CK_TRUE != has) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
}
|
|
|
|
if (!oldPin) {
|
|
CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
|
|
if (CK_TRUE != has) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
}
|
|
|
|
if (!fwSession->mdSession->SetPIN) {
|
|
return CKR_TOKEN_WRITE_PROTECTED;
|
|
}
|
|
|
|
error = fwSession->mdSession->SetPIN(fwSession->mdSession, fwSession,
|
|
fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
|
|
fwSession->fwInstance, (NSSItem *)oldPin, newPin);
|
|
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_GetOperationStateLen
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_ULONG
|
|
nssCKFWSession_GetOperationStateLen(
|
|
NSSCKFWSession *fwSession,
|
|
CK_RV *pError)
|
|
{
|
|
CK_ULONG mdAmt;
|
|
CK_ULONG fwAmt;
|
|
|
|
#ifdef NSSDEBUG
|
|
if (!pError) {
|
|
return (CK_ULONG)0;
|
|
}
|
|
|
|
*pError = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != *pError) {
|
|
return (CK_ULONG)0;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
return (CK_ULONG)0;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (!fwSession->mdSession->GetOperationStateLen) {
|
|
*pError = CKR_STATE_UNSAVEABLE;
|
|
return (CK_ULONG)0;
|
|
}
|
|
|
|
/*
|
|
* We could check that the session is actually in some state..
|
|
*/
|
|
|
|
mdAmt = fwSession->mdSession->GetOperationStateLen(fwSession->mdSession,
|
|
fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
|
|
fwSession->fwInstance, pError);
|
|
|
|
if (((CK_ULONG)0 == mdAmt) && (CKR_OK != *pError)) {
|
|
return (CK_ULONG)0;
|
|
}
|
|
|
|
/*
|
|
* Add a bit of sanity-checking
|
|
*/
|
|
fwAmt = mdAmt + 2 * sizeof(CK_ULONG);
|
|
|
|
return fwAmt;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_GetOperationState
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_GetOperationState(
|
|
NSSCKFWSession *fwSession,
|
|
NSSItem *buffer)
|
|
{
|
|
CK_RV error = CKR_OK;
|
|
CK_ULONG fwAmt;
|
|
CK_ULONG *ulBuffer;
|
|
NSSItem i2;
|
|
CK_ULONG n, i;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!buffer) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (!buffer->data) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (!fwSession->mdSession->GetOperationState) {
|
|
return CKR_STATE_UNSAVEABLE;
|
|
}
|
|
|
|
/*
|
|
* Sanity-check the caller's buffer.
|
|
*/
|
|
|
|
error = CKR_OK;
|
|
fwAmt = nssCKFWSession_GetOperationStateLen(fwSession, &error);
|
|
if (((CK_ULONG)0 == fwAmt) && (CKR_OK != error)) {
|
|
return error;
|
|
}
|
|
|
|
if (buffer->size < fwAmt) {
|
|
return CKR_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
ulBuffer = (CK_ULONG *)buffer->data;
|
|
|
|
i2.size = buffer->size - 2 * sizeof(CK_ULONG);
|
|
i2.data = (void *)&ulBuffer[2];
|
|
|
|
error = fwSession->mdSession->GetOperationState(fwSession->mdSession,
|
|
fwSession, fwSession->mdToken, fwSession->fwToken,
|
|
fwSession->mdInstance, fwSession->fwInstance, &i2);
|
|
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* Add a little integrety/identity check.
|
|
* NOTE: right now, it's pretty stupid.
|
|
* A CRC or something would be better.
|
|
*/
|
|
|
|
ulBuffer[0] = 0x434b4657; /* CKFW */
|
|
ulBuffer[1] = 0;
|
|
n = i2.size / sizeof(CK_ULONG);
|
|
for (i = 0; i < n; i++) {
|
|
ulBuffer[1] ^= ulBuffer[2 + i];
|
|
}
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_SetOperationState
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_SetOperationState(
|
|
NSSCKFWSession *fwSession,
|
|
NSSItem *state,
|
|
NSSCKFWObject *encryptionKey,
|
|
NSSCKFWObject *authenticationKey)
|
|
{
|
|
CK_RV error = CKR_OK;
|
|
CK_ULONG *ulBuffer;
|
|
CK_ULONG n, i;
|
|
CK_ULONG x;
|
|
NSSItem s;
|
|
NSSCKMDObject *mdek;
|
|
NSSCKMDObject *mdak;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!state) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (!state->data) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (encryptionKey) {
|
|
error = nssCKFWObject_verifyPointer(encryptionKey);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
}
|
|
|
|
if (authenticationKey) {
|
|
error = nssCKFWObject_verifyPointer(authenticationKey);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
ulBuffer = (CK_ULONG *)state->data;
|
|
if (0x43b4657 != ulBuffer[0]) {
|
|
return CKR_SAVED_STATE_INVALID;
|
|
}
|
|
n = (state->size / sizeof(CK_ULONG)) - 2;
|
|
x = (CK_ULONG)0;
|
|
for (i = 0; i < n; i++) {
|
|
x ^= ulBuffer[2 + i];
|
|
}
|
|
|
|
if (x != ulBuffer[1]) {
|
|
return CKR_SAVED_STATE_INVALID;
|
|
}
|
|
|
|
if (!fwSession->mdSession->SetOperationState) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
|
|
s.size = state->size - 2 * sizeof(CK_ULONG);
|
|
s.data = (void *)&ulBuffer[2];
|
|
|
|
if (encryptionKey) {
|
|
mdek = nssCKFWObject_GetMDObject(encryptionKey);
|
|
} else {
|
|
mdek = (NSSCKMDObject *)NULL;
|
|
}
|
|
|
|
if (authenticationKey) {
|
|
mdak = nssCKFWObject_GetMDObject(authenticationKey);
|
|
} else {
|
|
mdak = (NSSCKMDObject *)NULL;
|
|
}
|
|
|
|
error = fwSession->mdSession->SetOperationState(fwSession->mdSession,
|
|
fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
|
|
fwSession->fwInstance, &s, mdek, encryptionKey, mdak, authenticationKey);
|
|
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* Here'd we restore any session data
|
|
*/
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
static CK_BBOOL
|
|
nss_attributes_form_token_object(
|
|
CK_ATTRIBUTE_PTR pTemplate,
|
|
CK_ULONG ulAttributeCount)
|
|
{
|
|
CK_ULONG i;
|
|
CK_BBOOL rv;
|
|
|
|
for (i = 0; i < ulAttributeCount; i++) {
|
|
if (CKA_TOKEN == pTemplate[i].type) {
|
|
/* If we sanity-check, we can remove this sizeof check */
|
|
if (sizeof(CK_BBOOL) == pTemplate[i].ulValueLen) {
|
|
(void)nsslibc_memcpy(&rv, pTemplate[i].pValue, sizeof(CK_BBOOL));
|
|
return rv;
|
|
} else {
|
|
return CK_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return CK_FALSE;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_CreateObject
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT NSSCKFWObject *
|
|
nssCKFWSession_CreateObject(
|
|
NSSCKFWSession *fwSession,
|
|
CK_ATTRIBUTE_PTR pTemplate,
|
|
CK_ULONG ulAttributeCount,
|
|
CK_RV *pError)
|
|
{
|
|
NSSArena *arena;
|
|
NSSCKMDObject *mdObject;
|
|
NSSCKFWObject *fwObject;
|
|
CK_BBOOL isTokenObject;
|
|
|
|
#ifdef NSSDEBUG
|
|
if (!pError) {
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
*pError = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != pError) {
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
if ((CK_ATTRIBUTE_PTR)NULL == pTemplate) {
|
|
*pError = CKR_ARGUMENTS_BAD;
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
/*
|
|
* Here would be an excellent place to sanity-check the object.
|
|
*/
|
|
|
|
isTokenObject = nss_attributes_form_token_object(pTemplate, ulAttributeCount);
|
|
if (CK_TRUE == isTokenObject) {
|
|
/* === TOKEN OBJECT === */
|
|
|
|
if (!fwSession->mdSession->CreateObject) {
|
|
*pError = CKR_TOKEN_WRITE_PROTECTED;
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
arena = nssCKFWToken_GetArena(fwSession->fwToken, pError);
|
|
if (!arena) {
|
|
if (CKR_OK == *pError) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
}
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
goto callmdcreateobject;
|
|
} else {
|
|
/* === SESSION OBJECT === */
|
|
|
|
arena = nssCKFWSession_GetArena(fwSession, pError);
|
|
if (!arena) {
|
|
if (CKR_OK == *pError) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
}
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
if (CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects(
|
|
fwSession->fwInstance)) {
|
|
/* --- module handles the session object -- */
|
|
|
|
if (!fwSession->mdSession->CreateObject) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
goto callmdcreateobject;
|
|
} else {
|
|
/* --- framework handles the session object -- */
|
|
mdObject = nssCKMDSessionObject_Create(fwSession->fwToken,
|
|
arena, pTemplate, ulAttributeCount, pError);
|
|
goto gotmdobject;
|
|
}
|
|
}
|
|
|
|
callmdcreateobject:
|
|
mdObject = fwSession->mdSession->CreateObject(fwSession->mdSession,
|
|
fwSession, fwSession->mdToken, fwSession->fwToken,
|
|
fwSession->mdInstance, fwSession->fwInstance, arena, pTemplate,
|
|
ulAttributeCount, pError);
|
|
|
|
gotmdobject:
|
|
if (!mdObject) {
|
|
if (CKR_OK == *pError) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
}
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
fwObject = nssCKFWObject_Create(arena, mdObject,
|
|
isTokenObject ? NULL
|
|
: fwSession,
|
|
fwSession->fwToken, fwSession->fwInstance, pError);
|
|
if (!fwObject) {
|
|
if (CKR_OK == *pError) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
}
|
|
|
|
if (mdObject->Destroy) {
|
|
(void)mdObject->Destroy(mdObject, (NSSCKFWObject *)NULL,
|
|
fwSession->mdSession, fwSession, fwSession->mdToken,
|
|
fwSession->fwToken, fwSession->mdInstance, fwSession->fwInstance);
|
|
}
|
|
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
if (CK_FALSE == isTokenObject) {
|
|
if (CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, fwObject)) {
|
|
*pError = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject);
|
|
if (CKR_OK != *pError) {
|
|
nssCKFWObject_Finalize(fwObject, PR_TRUE);
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return fwObject;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_CopyObject
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT NSSCKFWObject *
|
|
nssCKFWSession_CopyObject(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWObject *fwObject,
|
|
CK_ATTRIBUTE_PTR pTemplate,
|
|
CK_ULONG ulAttributeCount,
|
|
CK_RV *pError)
|
|
{
|
|
CK_BBOOL oldIsToken;
|
|
CK_BBOOL newIsToken;
|
|
CK_ULONG i;
|
|
NSSCKFWObject *rv;
|
|
|
|
#ifdef NSSDEBUG
|
|
if (!pError) {
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
*pError = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != *pError) {
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
*pError = nssCKFWObject_verifyPointer(fwObject);
|
|
if (CKR_OK != *pError) {
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
/*
|
|
* Sanity-check object
|
|
*/
|
|
|
|
if (!fwObject) {
|
|
*pError = CKR_ARGUMENTS_BAD;
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
oldIsToken = nssCKFWObject_IsTokenObject(fwObject);
|
|
|
|
newIsToken = oldIsToken;
|
|
for (i = 0; i < ulAttributeCount; i++) {
|
|
if (CKA_TOKEN == pTemplate[i].type) {
|
|
/* Since we sanity-checked the object, we know this is the right size. */
|
|
(void)nsslibc_memcpy(&newIsToken, pTemplate[i].pValue, sizeof(CK_BBOOL));
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the Module handles its session objects, or if both the new
|
|
* and old object are token objects, use CopyObject if it exists.
|
|
*/
|
|
|
|
if ((fwSession->mdSession->CopyObject) &&
|
|
(((CK_TRUE == oldIsToken) && (CK_TRUE == newIsToken)) ||
|
|
(CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects(
|
|
fwSession->fwInstance)))) {
|
|
/* use copy object */
|
|
NSSArena *arena;
|
|
NSSCKMDObject *mdOldObject;
|
|
NSSCKMDObject *mdObject;
|
|
|
|
mdOldObject = nssCKFWObject_GetMDObject(fwObject);
|
|
|
|
if (CK_TRUE == newIsToken) {
|
|
arena = nssCKFWToken_GetArena(fwSession->fwToken, pError);
|
|
} else {
|
|
arena = nssCKFWSession_GetArena(fwSession, pError);
|
|
}
|
|
if (!arena) {
|
|
if (CKR_OK == *pError) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
}
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
mdObject = fwSession->mdSession->CopyObject(fwSession->mdSession,
|
|
fwSession, fwSession->mdToken, fwSession->fwToken,
|
|
fwSession->mdInstance, fwSession->fwInstance, mdOldObject,
|
|
fwObject, arena, pTemplate, ulAttributeCount, pError);
|
|
if (!mdObject) {
|
|
if (CKR_OK == *pError) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
}
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
rv = nssCKFWObject_Create(arena, mdObject,
|
|
newIsToken ? NULL
|
|
: fwSession,
|
|
fwSession->fwToken, fwSession->fwInstance, pError);
|
|
|
|
if (CK_FALSE == newIsToken) {
|
|
if (CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, rv)) {
|
|
*pError = nssCKFWHash_Add(fwSession->sessionObjectHash, rv, rv);
|
|
if (CKR_OK != *pError) {
|
|
nssCKFWObject_Finalize(rv, PR_TRUE);
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
} else {
|
|
/* use create object */
|
|
NSSArena *tmpArena;
|
|
CK_ATTRIBUTE_PTR newTemplate;
|
|
CK_ULONG j, n, newLength, k;
|
|
CK_ATTRIBUTE_TYPE_PTR oldTypes;
|
|
|
|
n = nssCKFWObject_GetAttributeCount(fwObject, pError);
|
|
if ((0 == n) && (CKR_OK != *pError)) {
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
tmpArena = NSSArena_Create();
|
|
if (!tmpArena) {
|
|
*pError = CKR_HOST_MEMORY;
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
oldTypes = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE_TYPE, n);
|
|
if ((CK_ATTRIBUTE_TYPE_PTR)NULL == oldTypes) {
|
|
NSSArena_Destroy(tmpArena);
|
|
*pError = CKR_HOST_MEMORY;
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
*pError = nssCKFWObject_GetAttributeTypes(fwObject, oldTypes, n);
|
|
if (CKR_OK != *pError) {
|
|
NSSArena_Destroy(tmpArena);
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
newLength = n;
|
|
for (i = 0; i < ulAttributeCount; i++) {
|
|
for (j = 0; j < n; j++) {
|
|
if (oldTypes[j] == pTemplate[i].type) {
|
|
if ((CK_VOID_PTR)NULL ==
|
|
pTemplate[i].pValue) {
|
|
/* Removing the attribute */
|
|
newLength--;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (j == n) {
|
|
/* Not found */
|
|
newLength++;
|
|
}
|
|
}
|
|
|
|
newTemplate = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE, newLength);
|
|
if ((CK_ATTRIBUTE_PTR)NULL == newTemplate) {
|
|
NSSArena_Destroy(tmpArena);
|
|
*pError = CKR_HOST_MEMORY;
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
k = 0;
|
|
for (j = 0; j < n; j++) {
|
|
for (i = 0; i < ulAttributeCount; i++) {
|
|
if (oldTypes[j] == pTemplate[i].type) {
|
|
if ((CK_VOID_PTR)NULL ==
|
|
pTemplate[i].pValue) {
|
|
/* This attribute is being deleted */
|
|
;
|
|
} else {
|
|
/* This attribute is being replaced */
|
|
newTemplate[k].type =
|
|
pTemplate[i].type;
|
|
newTemplate[k].pValue =
|
|
pTemplate[i].pValue;
|
|
newTemplate[k].ulValueLen =
|
|
pTemplate[i].ulValueLen;
|
|
k++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (i == ulAttributeCount) {
|
|
/* This attribute is being copied over from the old object */
|
|
NSSItem item, *it;
|
|
item.size = 0;
|
|
item.data = (void *)NULL;
|
|
it = nssCKFWObject_GetAttribute(fwObject, oldTypes[j],
|
|
&item, tmpArena, pError);
|
|
if (!it) {
|
|
if (CKR_OK ==
|
|
*pError) {
|
|
*pError =
|
|
CKR_GENERAL_ERROR;
|
|
}
|
|
NSSArena_Destroy(tmpArena);
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
newTemplate[k].type = oldTypes[j];
|
|
newTemplate[k].pValue = it->data;
|
|
newTemplate[k].ulValueLen = it->size;
|
|
k++;
|
|
}
|
|
}
|
|
/* assert that k == newLength */
|
|
|
|
rv = nssCKFWSession_CreateObject(fwSession, newTemplate, newLength, pError);
|
|
if (!rv) {
|
|
if (CKR_OK == *pError) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
}
|
|
NSSArena_Destroy(tmpArena);
|
|
return (NSSCKFWObject *)NULL;
|
|
}
|
|
|
|
NSSArena_Destroy(tmpArena);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_FindObjectsInit
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT NSSCKFWFindObjects *
|
|
nssCKFWSession_FindObjectsInit(
|
|
NSSCKFWSession *fwSession,
|
|
CK_ATTRIBUTE_PTR pTemplate,
|
|
CK_ULONG ulAttributeCount,
|
|
CK_RV *pError)
|
|
{
|
|
NSSCKMDFindObjects *mdfo1 = (NSSCKMDFindObjects *)NULL;
|
|
NSSCKMDFindObjects *mdfo2 = (NSSCKMDFindObjects *)NULL;
|
|
|
|
#ifdef NSSDEBUG
|
|
if (!pError) {
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
|
|
*pError = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != *pError) {
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
|
|
if (((CK_ATTRIBUTE_PTR)NULL == pTemplate) && (ulAttributeCount != 0)) {
|
|
*pError = CKR_ARGUMENTS_BAD;
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (CK_TRUE != nssCKFWInstance_GetModuleHandlesSessionObjects(
|
|
fwSession->fwInstance)) {
|
|
CK_ULONG i;
|
|
|
|
/*
|
|
* Does the search criteria restrict us to token or session
|
|
* objects?
|
|
*/
|
|
|
|
for (i = 0; i < ulAttributeCount; i++) {
|
|
if (CKA_TOKEN == pTemplate[i].type) {
|
|
/* Yes, it does. */
|
|
CK_BBOOL isToken;
|
|
if (sizeof(CK_BBOOL) != pTemplate[i].ulValueLen) {
|
|
*pError =
|
|
CKR_ATTRIBUTE_VALUE_INVALID;
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
(void)nsslibc_memcpy(&isToken, pTemplate[i].pValue, sizeof(CK_BBOOL));
|
|
|
|
if (CK_TRUE == isToken) {
|
|
/* Pass it on to the module's search routine */
|
|
if (!fwSession->mdSession->FindObjectsInit) {
|
|
goto wrap;
|
|
}
|
|
|
|
mdfo1 =
|
|
fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
|
|
fwSession, fwSession->mdToken, fwSession->fwToken,
|
|
fwSession->mdInstance, fwSession->fwInstance,
|
|
pTemplate, ulAttributeCount, pError);
|
|
} else {
|
|
/* Do the search ourselves */
|
|
mdfo1 =
|
|
nssCKMDFindSessionObjects_Create(fwSession->fwToken,
|
|
pTemplate, ulAttributeCount, pError);
|
|
}
|
|
|
|
if (!mdfo1) {
|
|
if (CKR_OK ==
|
|
*pError) {
|
|
*pError =
|
|
CKR_GENERAL_ERROR;
|
|
}
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
|
|
goto wrap;
|
|
}
|
|
}
|
|
|
|
if (i == ulAttributeCount) {
|
|
/* No, it doesn't. Do a hybrid search. */
|
|
mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
|
|
fwSession, fwSession->mdToken, fwSession->fwToken,
|
|
fwSession->mdInstance, fwSession->fwInstance,
|
|
pTemplate, ulAttributeCount, pError);
|
|
|
|
if (!mdfo1) {
|
|
if (CKR_OK == *pError) {
|
|
*pError =
|
|
CKR_GENERAL_ERROR;
|
|
}
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
|
|
mdfo2 = nssCKMDFindSessionObjects_Create(fwSession->fwToken,
|
|
pTemplate, ulAttributeCount, pError);
|
|
if (!mdfo2) {
|
|
if (CKR_OK == *pError) {
|
|
*pError =
|
|
CKR_GENERAL_ERROR;
|
|
}
|
|
if (mdfo1->Final) {
|
|
mdfo1->Final(mdfo1, (NSSCKFWFindObjects *)NULL, fwSession->mdSession,
|
|
fwSession, fwSession->mdToken, fwSession->fwToken,
|
|
fwSession->mdInstance, fwSession->fwInstance);
|
|
}
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
|
|
goto wrap;
|
|
}
|
|
/*NOTREACHED*/
|
|
} else {
|
|
/* Module handles all its own objects. Pass on to module's search */
|
|
mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
|
|
fwSession, fwSession->mdToken, fwSession->fwToken,
|
|
fwSession->mdInstance, fwSession->fwInstance,
|
|
pTemplate, ulAttributeCount, pError);
|
|
|
|
if (!mdfo1) {
|
|
if (CKR_OK == *pError) {
|
|
*pError = CKR_GENERAL_ERROR;
|
|
}
|
|
return (NSSCKFWFindObjects *)NULL;
|
|
}
|
|
|
|
goto wrap;
|
|
}
|
|
|
|
wrap:
|
|
return nssCKFWFindObjects_Create(fwSession, fwSession->fwToken,
|
|
fwSession->fwInstance, mdfo1, mdfo2, pError);
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_SeedRandom
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_SeedRandom(
|
|
NSSCKFWSession *fwSession,
|
|
NSSItem *seed)
|
|
{
|
|
CK_RV error = CKR_OK;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!seed) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (!seed->data) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (0 == seed->size) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (!fwSession->mdSession->SeedRandom) {
|
|
return CKR_RANDOM_SEED_NOT_SUPPORTED;
|
|
}
|
|
|
|
error = fwSession->mdSession->SeedRandom(fwSession->mdSession, fwSession,
|
|
fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
|
|
fwSession->fwInstance, seed);
|
|
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_GetRandom
|
|
*
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_GetRandom(
|
|
NSSCKFWSession *fwSession,
|
|
NSSItem *buffer)
|
|
{
|
|
CK_RV error = CKR_OK;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!buffer) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (!buffer->data) {
|
|
return CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
if (!fwSession->mdSession->GetRandom) {
|
|
if (CK_TRUE == nssCKFWToken_GetHasRNG(fwSession->fwToken)) {
|
|
return CKR_GENERAL_ERROR;
|
|
} else {
|
|
return CKR_RANDOM_NO_RNG;
|
|
}
|
|
}
|
|
|
|
if (0 == buffer->size) {
|
|
return CKR_OK;
|
|
}
|
|
|
|
error = fwSession->mdSession->GetRandom(fwSession->mdSession, fwSession,
|
|
fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
|
|
fwSession->fwInstance, buffer);
|
|
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_SetCurrentCryptoOperation
|
|
*/
|
|
NSS_IMPLEMENT void
|
|
nssCKFWSession_SetCurrentCryptoOperation(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWCryptoOperation *fwOperation,
|
|
NSSCKFWCryptoOperationState state)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
CK_RV error = CKR_OK;
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return;
|
|
}
|
|
|
|
if (state >= NSSCKFWCryptoOperationState_Max) {
|
|
return;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
fwSession->fwOperationArray[state] = fwOperation;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_GetCurrentCryptoOperation
|
|
*/
|
|
NSS_IMPLEMENT NSSCKFWCryptoOperation *
|
|
nssCKFWSession_GetCurrentCryptoOperation(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWCryptoOperationState state)
|
|
{
|
|
#ifdef NSSDEBUG
|
|
CK_RV error = CKR_OK;
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return (NSSCKFWCryptoOperation *)NULL;
|
|
}
|
|
|
|
if (state >= NSSCKFWCryptoOperationState_Max) {
|
|
return (NSSCKFWCryptoOperation *)NULL;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return (NSSCKFWCryptoOperation *)NULL;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
return fwSession->fwOperationArray[state];
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_Final
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_Final(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWCryptoOperationType type,
|
|
NSSCKFWCryptoOperationState state,
|
|
CK_BYTE_PTR outBuf,
|
|
CK_ULONG_PTR outBufLen)
|
|
{
|
|
NSSCKFWCryptoOperation *fwOperation;
|
|
NSSItem outputBuffer;
|
|
CK_RV error = CKR_OK;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
/* make sure we have a valid operation initialized */
|
|
fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
|
|
if (!fwOperation) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
/* make sure it's the correct type */
|
|
if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
/* handle buffer issues, note for Verify, the type is an input buffer. */
|
|
if (NSSCKFWCryptoOperationType_Verify == type) {
|
|
if ((CK_BYTE_PTR)NULL == outBuf) {
|
|
error = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
} else {
|
|
CK_ULONG len = nssCKFWCryptoOperation_GetFinalLength(fwOperation, &error);
|
|
CK_ULONG maxBufLen = *outBufLen;
|
|
|
|
if (CKR_OK != error) {
|
|
goto done;
|
|
}
|
|
*outBufLen = len;
|
|
if ((CK_BYTE_PTR)NULL == outBuf) {
|
|
return CKR_OK;
|
|
}
|
|
|
|
if (len > maxBufLen) {
|
|
return CKR_BUFFER_TOO_SMALL;
|
|
}
|
|
}
|
|
outputBuffer.data = outBuf;
|
|
outputBuffer.size = *outBufLen;
|
|
|
|
error = nssCKFWCryptoOperation_Final(fwOperation, &outputBuffer);
|
|
done:
|
|
if (CKR_BUFFER_TOO_SMALL == error) {
|
|
return error;
|
|
}
|
|
/* clean up our state */
|
|
nssCKFWCryptoOperation_Destroy(fwOperation);
|
|
nssCKFWSession_SetCurrentCryptoOperation(fwSession, NULL, state);
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_Update
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_Update(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWCryptoOperationType type,
|
|
NSSCKFWCryptoOperationState state,
|
|
CK_BYTE_PTR inBuf,
|
|
CK_ULONG inBufLen,
|
|
CK_BYTE_PTR outBuf,
|
|
CK_ULONG_PTR outBufLen)
|
|
{
|
|
NSSCKFWCryptoOperation *fwOperation;
|
|
NSSItem inputBuffer;
|
|
NSSItem outputBuffer;
|
|
CK_ULONG len;
|
|
CK_ULONG maxBufLen;
|
|
CK_RV error = CKR_OK;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
/* make sure we have a valid operation initialized */
|
|
fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
|
|
if (!fwOperation) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
/* make sure it's the correct type */
|
|
if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
inputBuffer.data = inBuf;
|
|
inputBuffer.size = inBufLen;
|
|
|
|
/* handle buffer issues, note for Verify, the type is an input buffer. */
|
|
len = nssCKFWCryptoOperation_GetOperationLength(fwOperation, &inputBuffer,
|
|
&error);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
maxBufLen = *outBufLen;
|
|
|
|
*outBufLen = len;
|
|
if ((CK_BYTE_PTR)NULL == outBuf) {
|
|
return CKR_OK;
|
|
}
|
|
|
|
if (len > maxBufLen) {
|
|
return CKR_BUFFER_TOO_SMALL;
|
|
}
|
|
outputBuffer.data = outBuf;
|
|
outputBuffer.size = *outBufLen;
|
|
|
|
return nssCKFWCryptoOperation_Update(fwOperation,
|
|
&inputBuffer, &outputBuffer);
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_DigestUpdate
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_DigestUpdate(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWCryptoOperationType type,
|
|
NSSCKFWCryptoOperationState state,
|
|
CK_BYTE_PTR inBuf,
|
|
CK_ULONG inBufLen)
|
|
{
|
|
NSSCKFWCryptoOperation *fwOperation;
|
|
NSSItem inputBuffer;
|
|
CK_RV error = CKR_OK;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
/* make sure we have a valid operation initialized */
|
|
fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
|
|
if (!fwOperation) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
/* make sure it's the correct type */
|
|
if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
inputBuffer.data = inBuf;
|
|
inputBuffer.size = inBufLen;
|
|
|
|
error = nssCKFWCryptoOperation_DigestUpdate(fwOperation, &inputBuffer);
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_DigestUpdate
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_DigestKey(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWObject *fwKey)
|
|
{
|
|
NSSCKFWCryptoOperation *fwOperation;
|
|
NSSItem *inputBuffer;
|
|
CK_RV error = CKR_OK;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
/* make sure we have a valid operation initialized */
|
|
fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession,
|
|
NSSCKFWCryptoOperationState_Digest);
|
|
if (!fwOperation) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
/* make sure it's the correct type */
|
|
if (NSSCKFWCryptoOperationType_Digest !=
|
|
nssCKFWCryptoOperation_GetType(fwOperation)) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
error = nssCKFWCryptoOperation_DigestKey(fwOperation, fwKey);
|
|
if (CKR_FUNCTION_FAILED != error) {
|
|
return error;
|
|
}
|
|
|
|
/* no machine depended way for this to happen, do it by hand */
|
|
inputBuffer = nssCKFWObject_GetAttribute(fwKey, CKA_VALUE, NULL, NULL, &error);
|
|
if (!inputBuffer) {
|
|
/* couldn't get the value, just fail then */
|
|
return error;
|
|
}
|
|
error = nssCKFWCryptoOperation_DigestUpdate(fwOperation, inputBuffer);
|
|
nssItem_Destroy(inputBuffer);
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* nssCKFWSession_UpdateFinal
|
|
*/
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_UpdateFinal(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWCryptoOperationType type,
|
|
NSSCKFWCryptoOperationState state,
|
|
CK_BYTE_PTR inBuf,
|
|
CK_ULONG inBufLen,
|
|
CK_BYTE_PTR outBuf,
|
|
CK_ULONG_PTR outBufLen)
|
|
{
|
|
NSSCKFWCryptoOperation *fwOperation;
|
|
NSSItem inputBuffer;
|
|
NSSItem outputBuffer;
|
|
PRBool isEncryptDecrypt;
|
|
CK_RV error = CKR_OK;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
/* make sure we have a valid operation initialized */
|
|
fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
|
|
if (!fwOperation) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
/* make sure it's the correct type */
|
|
if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
inputBuffer.data = inBuf;
|
|
inputBuffer.size = inBufLen;
|
|
isEncryptDecrypt = (PRBool)((NSSCKFWCryptoOperationType_Encrypt == type) ||
|
|
(NSSCKFWCryptoOperationType_Decrypt == type));
|
|
|
|
/* handle buffer issues, note for Verify, the type is an input buffer. */
|
|
if (NSSCKFWCryptoOperationType_Verify == type) {
|
|
if ((CK_BYTE_PTR)NULL == outBuf) {
|
|
error = CKR_ARGUMENTS_BAD;
|
|
goto done;
|
|
}
|
|
} else {
|
|
CK_ULONG maxBufLen = *outBufLen;
|
|
CK_ULONG len;
|
|
|
|
len = (isEncryptDecrypt) ? nssCKFWCryptoOperation_GetOperationLength(fwOperation,
|
|
&inputBuffer, &error)
|
|
: nssCKFWCryptoOperation_GetFinalLength(fwOperation, &error);
|
|
|
|
if (CKR_OK != error) {
|
|
goto done;
|
|
}
|
|
|
|
*outBufLen = len;
|
|
if ((CK_BYTE_PTR)NULL == outBuf) {
|
|
return CKR_OK;
|
|
}
|
|
|
|
if (len > maxBufLen) {
|
|
return CKR_BUFFER_TOO_SMALL;
|
|
}
|
|
}
|
|
outputBuffer.data = outBuf;
|
|
outputBuffer.size = *outBufLen;
|
|
|
|
error = nssCKFWCryptoOperation_UpdateFinal(fwOperation,
|
|
&inputBuffer, &outputBuffer);
|
|
|
|
/* UpdateFinal isn't support, manually use Update and Final */
|
|
if (CKR_FUNCTION_FAILED == error) {
|
|
error = isEncryptDecrypt ? nssCKFWCryptoOperation_Update(fwOperation, &inputBuffer, &outputBuffer)
|
|
: nssCKFWCryptoOperation_DigestUpdate(fwOperation, &inputBuffer);
|
|
|
|
if (CKR_OK == error) {
|
|
error = nssCKFWCryptoOperation_Final(fwOperation, &outputBuffer);
|
|
}
|
|
}
|
|
|
|
done:
|
|
if (CKR_BUFFER_TOO_SMALL == error) {
|
|
/* if we return CKR_BUFFER_TOO_SMALL, we the caller is not expecting.
|
|
* the crypto state to be freed */
|
|
return error;
|
|
}
|
|
|
|
/* clean up our state */
|
|
nssCKFWCryptoOperation_Destroy(fwOperation);
|
|
nssCKFWSession_SetCurrentCryptoOperation(fwSession, NULL, state);
|
|
return error;
|
|
}
|
|
|
|
NSS_IMPLEMENT CK_RV
|
|
nssCKFWSession_UpdateCombo(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWCryptoOperationType encryptType,
|
|
NSSCKFWCryptoOperationType digestType,
|
|
NSSCKFWCryptoOperationState digestState,
|
|
CK_BYTE_PTR inBuf,
|
|
CK_ULONG inBufLen,
|
|
CK_BYTE_PTR outBuf,
|
|
CK_ULONG_PTR outBufLen)
|
|
{
|
|
NSSCKFWCryptoOperation *fwOperation;
|
|
NSSCKFWCryptoOperation *fwPeerOperation;
|
|
NSSItem inputBuffer;
|
|
NSSItem outputBuffer;
|
|
CK_ULONG maxBufLen = *outBufLen;
|
|
CK_ULONG len;
|
|
CK_RV error = CKR_OK;
|
|
|
|
#ifdef NSSDEBUG
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
if (!fwSession->mdSession) {
|
|
return CKR_GENERAL_ERROR;
|
|
}
|
|
#endif /* NSSDEBUG */
|
|
|
|
/* make sure we have a valid operation initialized */
|
|
fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession,
|
|
NSSCKFWCryptoOperationState_EncryptDecrypt);
|
|
if (!fwOperation) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
/* make sure it's the correct type */
|
|
if (encryptType != nssCKFWCryptoOperation_GetType(fwOperation)) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
/* make sure we have a valid operation initialized */
|
|
fwPeerOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession,
|
|
digestState);
|
|
if (!fwPeerOperation) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
/* make sure it's the correct type */
|
|
if (digestType != nssCKFWCryptoOperation_GetType(fwOperation)) {
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
|
|
inputBuffer.data = inBuf;
|
|
inputBuffer.size = inBufLen;
|
|
len = nssCKFWCryptoOperation_GetOperationLength(fwOperation,
|
|
&inputBuffer, &error);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
|
|
*outBufLen = len;
|
|
if ((CK_BYTE_PTR)NULL == outBuf) {
|
|
return CKR_OK;
|
|
}
|
|
|
|
if (len > maxBufLen) {
|
|
return CKR_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
outputBuffer.data = outBuf;
|
|
outputBuffer.size = *outBufLen;
|
|
|
|
error = nssCKFWCryptoOperation_UpdateCombo(fwOperation, fwPeerOperation,
|
|
&inputBuffer, &outputBuffer);
|
|
if (CKR_FUNCTION_FAILED == error) {
|
|
PRBool isEncrypt =
|
|
(PRBool)(NSSCKFWCryptoOperationType_Encrypt == encryptType);
|
|
|
|
if (isEncrypt) {
|
|
error = nssCKFWCryptoOperation_DigestUpdate(fwPeerOperation,
|
|
&inputBuffer);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
}
|
|
error = nssCKFWCryptoOperation_Update(fwOperation,
|
|
&inputBuffer, &outputBuffer);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
if (!isEncrypt) {
|
|
error = nssCKFWCryptoOperation_DigestUpdate(fwPeerOperation,
|
|
&outputBuffer);
|
|
}
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* NSSCKFWSession_GetMDSession
|
|
*
|
|
*/
|
|
|
|
NSS_IMPLEMENT NSSCKMDSession *
|
|
NSSCKFWSession_GetMDSession(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
#ifdef DEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return (NSSCKMDSession *)NULL;
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
return nssCKFWSession_GetMDSession(fwSession);
|
|
}
|
|
|
|
/*
|
|
* NSSCKFWSession_GetArena
|
|
*
|
|
*/
|
|
|
|
NSS_IMPLEMENT NSSArena *
|
|
NSSCKFWSession_GetArena(
|
|
NSSCKFWSession *fwSession,
|
|
CK_RV *pError)
|
|
{
|
|
#ifdef DEBUG
|
|
if (!pError) {
|
|
return (NSSArena *)NULL;
|
|
}
|
|
|
|
*pError = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != *pError) {
|
|
return (NSSArena *)NULL;
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
return nssCKFWSession_GetArena(fwSession, pError);
|
|
}
|
|
|
|
/*
|
|
* NSSCKFWSession_CallNotification
|
|
*
|
|
*/
|
|
|
|
NSS_IMPLEMENT CK_RV
|
|
NSSCKFWSession_CallNotification(
|
|
NSSCKFWSession *fwSession,
|
|
CK_NOTIFICATION event)
|
|
{
|
|
#ifdef DEBUG
|
|
CK_RV error = CKR_OK;
|
|
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return error;
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
return nssCKFWSession_CallNotification(fwSession, event);
|
|
}
|
|
|
|
/*
|
|
* NSSCKFWSession_IsRWSession
|
|
*
|
|
*/
|
|
|
|
NSS_IMPLEMENT CK_BBOOL
|
|
NSSCKFWSession_IsRWSession(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
#ifdef DEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return CK_FALSE;
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
return nssCKFWSession_IsRWSession(fwSession);
|
|
}
|
|
|
|
/*
|
|
* NSSCKFWSession_IsSO
|
|
*
|
|
*/
|
|
|
|
NSS_IMPLEMENT CK_BBOOL
|
|
NSSCKFWSession_IsSO(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
#ifdef DEBUG
|
|
if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
|
|
return CK_FALSE;
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
return nssCKFWSession_IsSO(fwSession);
|
|
}
|
|
|
|
NSS_IMPLEMENT NSSCKFWCryptoOperation *
|
|
NSSCKFWSession_GetCurrentCryptoOperation(
|
|
NSSCKFWSession *fwSession,
|
|
NSSCKFWCryptoOperationState state)
|
|
{
|
|
#ifdef DEBUG
|
|
CK_RV error = CKR_OK;
|
|
error = nssCKFWSession_verifyPointer(fwSession);
|
|
if (CKR_OK != error) {
|
|
return (NSSCKFWCryptoOperation *)NULL;
|
|
}
|
|
|
|
if (state >= NSSCKFWCryptoOperationState_Max) {
|
|
return (NSSCKFWCryptoOperation *)NULL;
|
|
}
|
|
#endif /* DEBUG */
|
|
return nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
|
|
}
|
|
|
|
/*
|
|
* NSSCKFWSession_GetFWSlot
|
|
*
|
|
*/
|
|
|
|
NSS_IMPLEMENT NSSCKFWSlot *
|
|
NSSCKFWSession_GetFWSlot(
|
|
NSSCKFWSession *fwSession)
|
|
{
|
|
return nssCKFWSession_GetFWSlot(fwSession);
|
|
}
|