gecko-dev/security/nss/lib/fortcrypt/fortpk11.c
2001-09-20 23:19:15 +00:00

4554 lines
130 KiB
C

/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*
* This file implements PKCS 11 for FORTEZZA using MACI
* drivers. Except for the Mac. They only have CI libraries, so
* that's what we use there.
*
* For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
*
* This implementations queries the MACI to figure out how
* many slots exist on a given system. There is an artificial boundary
* of 32 slots, because allocating slots dynamically caused memory
* problems in the client when first this module was first developed.
* Some how the heap was being corrupted and we couldn't find out where.
* Subsequent attempts to allocate dynamic memory caused no problem.
*
* In this implementation, session objects are only visible to the session
* that created or generated them.
*/
#include "fpkmem.h"
#include "seccomon.h"
#include "fpkcs11.h"
#include "fpkcs11i.h"
#include "cryptint.h"
#include "pk11func.h"
#include "fortsock.h"
#include "fmutex.h"
#ifdef notdef
#include <ctype.h>
#include <stdio.h>
#endif
/* sigh */
#ifndef EOF
/* stdio was not included */
extern int sprintf(char *out, char *fmt, ...);
#endif
#ifdef XP_MAC
#ifndef __POWERPC__
#include <A4Stuff.h>
#endif
/* This is not a 4.0 project, so I can't depend on
* 4.0 defines, so instead I depend on CodeWarrior
* defines. I define XP_MAC in fpkmem.h
*/
#if __POWERPC__
#elif __CFM68K__
#else
/* These include are taken fromn npmac.cpp which are used
* by the plugin group to properly set-up a plug-in for
* dynamic loading on 68K.
*/
#include <Quickdraw.h>
/*
** The Mixed Mode procInfos defined in npupp.h assume Think C-
** style calling conventions. These conventions are used by
** Metrowerks with the exception of pointer return types, which
** in Metrowerks 68K are returned in A0, instead of the standard
** D0. Thus, since NPN_MemAlloc and NPN_UserAgent return pointers,
** Mixed Mode will return the values to a 68K plugin in D0, but
** a 68K plugin compiled by Metrowerks will expect the result in
** A0. The following pragma forces Metrowerks to use D0 instead.
*/
#ifdef __MWERKS__
#ifndef powerc
#pragma pointers_in_D0
#endif
#endif
#ifdef __MWERKS__
#ifndef powerc
#pragma pointers_in_A0
#endif
#endif
/* The following fix for static initializers fixes a previous
** incompatibility with some parts of PowerPlant.
*/
#ifdef __MWERKS__
#ifdef __cplusplus
extern "C" {
#endif
#ifndef powerc
extern void __InitCode__(void);
#else
extern void __sinit(void);
#endif
extern void __destroy_global_chain(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __MWERKS__ */
#endif
#endif
typedef struct {
unsigned char *data;
int len;
} CertItem;
/*
* ******************** Static data *******************************
*/
/* The next three strings must be exactly 32 characters long */
static char *manufacturerID = "Netscape Communications Corp ";
static char *libraryDescription = "Communicator Fortezza Crypto Svc";
typedef enum {DSA_KEY, KEA_KEY, V1_KEY, INVALID_KEY } PrivKeyType;
static PK11Slot fort11_slot[NUM_SLOTS];
static FortezzaSocket fortezzaSockets[NUM_SLOTS];
static PRBool init = PR_FALSE;
static CK_ULONG kNumSockets = 0;
#define __PASTE(x,y) x##y
#undef CK_FUNC
#undef CK_EXTERN
#undef CK_NEED_ARG_LIST
#undef _CK_RV
#define fort11_attr_expand(ap) (ap)->type,(ap)->pValue,(ap)->ulValueLen
#define fort11_SlotFromSession pk11_SlotFromSession
#define fort11_isToken pk11_isToken
static CK_FUNCTION_LIST fort11_funcList = {
{ 2, 1 },
#undef CK_FUNC
#undef CK_EXTERN
#undef CK_NEED_ARG_LIST
#undef _CK_RV
#define CK_EXTERN
#define CK_FUNC(name) name,
#define _CK_RV
#include "fpkcs11f.h"
};
#undef CK_FUNC
#undef CK_EXTERN
#undef _CK_RV
#undef __PASTE
#undef pk11_SlotFromSessionHandle
#undef pk11_SlotFromID
#define MAJOR_VERSION_MASK 0xFF00
#define MINOR_VERSION_MASK 0x00FF
/* Mechanisms */
struct mechanismList {
CK_MECHANISM_TYPE type;
CK_MECHANISM_INFO domestic;
PRBool privkey;
};
static struct mechanismList mechanisms[] = {
{CKM_DSA, {512,1024,CKF_SIGN}, PR_TRUE},
{CKM_SKIPJACK_KEY_GEN, {92, 92, CKF_GENERATE}, PR_TRUE},
{CKM_SKIPJACK_CBC64, {92, 92, CKF_ENCRYPT | CKF_DECRYPT}, PR_TRUE},
{CKM_SKIPJACK_WRAP, {92, 92, CKF_WRAP}, PR_TRUE},
{CKM_KEA_KEY_DERIVE, {128, 128, CKF_DERIVE}, PR_TRUE},
};
static CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]);
/*************Static function prototypes********************************/
static PRBool fort11_isTrue(PK11Object *object,CK_ATTRIBUTE_TYPE type);
static void fort11_FreeAttribute(PK11Attribute *attribute);
static void fort11_DestroyAttribute(PK11Attribute *attribute);
static PK11Object* fort11_NewObject(PK11Slot *slot);
static PK11FreeStatus fort11_FreeObject(PK11Object *object);
static CK_RV fort11_AddAttributeType(PK11Object *object,
CK_ATTRIBUTE_TYPE type,
void *valPtr,
CK_ULONG length);
static void fort11_AddSlotObject(PK11Slot *slot, PK11Object *object);
static PK11Attribute* fort11_FindAttribute(PK11Object *object,
CK_ATTRIBUTE_TYPE type);
static PK11Attribute* fort11_NewAttribute(CK_ATTRIBUTE_TYPE type,
CK_VOID_PTR value, CK_ULONG len);
static void fort11_DeleteAttributeType(PK11Object *object,
CK_ATTRIBUTE_TYPE type);
static void fort11_AddAttribute(PK11Object *object,
PK11Attribute *attribute);
static void fort11_AddObject(PK11Session *session,
PK11Object *object);
static PK11Object * fort11_ObjectFromHandle(CK_OBJECT_HANDLE handle,
PK11Session *session);
static void fort11_DeleteObject(PK11Session *session,PK11Object *object);
static CK_RV fort11_DestroyObject(PK11Object *object);
void fort11_FreeSession(PK11Session *session);
#define FIRST_SLOT_SESS_ID 0x00000100L
#define ADD_NEXT_SESS_ID 0x00000100L
#define SLOT_MASK 0x000000FFL
#define FAILED CKR_FUNCTION_FAILED
static void
fort11_FreeFortezzaKey (void *inFortezzaKey) {
RemoveKey ((FortezzaKey*) inFortezzaKey);
}
static void
fort11_DestroySlotObjects (PK11Slot *slot, PK11Session *session) {
PK11Object *currObject, *nextObject = NULL, *oldObject;
int i;
for (i=0; i<HASH_SIZE; i++) {
currObject = slot->tokObjects[i];
slot->tokObjects[i] = NULL;
do {
FMUTEX_Lock(slot->sessionLock);
if (currObject) {
nextObject = currObject->next;
FMUTEX_Lock(currObject->refLock);
currObject->refCount++;
FMUTEX_Unlock(currObject->refLock);
fort11_DeleteObject(session, currObject);
}
FMUTEX_Unlock(slot->sessionLock);
if (currObject) {
oldObject = currObject;
currObject = nextObject;
fort11_FreeObject(oldObject);
}
} while (currObject != NULL);
}
}
static void
fort11_TokenRemoved(PK11Slot *slot, PK11Session *session) {
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
LogoutFromSocket (socket);
slot->isLoggedIn = PR_FALSE;
if (session && session->notify) {
/*If no session pointer exists, lots of leaked memory*/
session->notify (session->handle, CKN_SURRENDER,
session->appData);
fort11_FreeSession(session); /* Release the reference held
* by the slot with the session
*/
}
fort11_DestroySlotObjects(slot, session);
fort11_FreeSession(session); /* Release the reference held
* by the slot with the session
*/
/* All keys will have been freed at this point so we can
* NULL out this pointer
*/
socket->keys = NULL;
}
PRBool
fort11_FortezzaIsUserCert(unsigned char * label) {
if ( (!PORT_Memcmp(label, "KEAK", 4)) || /* v3 user certs */
(!PORT_Memcmp(label, "DSA1", 4)) ||
(!PORT_Memcmp(label, "DSAI", 4)) ||
(!PORT_Memcmp(label, "DSAO", 4)) ||
(!PORT_Memcmp(label, "INKS", 4)) || /* v1 user certs */
(!PORT_Memcmp(label, "INKX", 4)) ||
(!PORT_Memcmp(label, "ONKS", 4)) ||
(!PORT_Memcmp(label, "ONKX", 4)) ||
(!PORT_Memcmp(label, "3IXS", 4)) || /* old v3 user certs */
(!PORT_Memcmp(label, "3OXS", 4)) ||
(!PORT_Memcmp(label, "3IKX", 4)) ) {
return PR_TRUE;
} else { return PR_FALSE; }
}
static PRBool
fort11_FortezzaIsACert(unsigned char * label) {
if (label == NULL) return PR_FALSE;
if ( (!PORT_Memcmp(label, "DSA1", 4)) || /* v3 certs */
(!PORT_Memcmp(label, "DSAI", 4)) ||
(!PORT_Memcmp(label, "DSAO", 4)) ||
(!PORT_Memcmp(label, "DSAX", 4)) ||
(!PORT_Memcmp(label, "KEAK", 4)) ||
(!PORT_Memcmp(label, "KEAX", 4)) ||
(!PORT_Memcmp(label, "CAX1", 4)) ||
(!PORT_Memcmp(label, "PCA1", 4)) ||
(!PORT_Memcmp(label, "PAA1", 4)) ||
(!PORT_Memcmp(label, "ICA1", 4)) ||
(!PORT_Memcmp(label, "3IXS", 4)) || /* old v3 certs */
(!PORT_Memcmp(label, "3OXS", 4)) ||
(!PORT_Memcmp(label, "3CAX", 4)) ||
(!PORT_Memcmp(label, "3IKX", 4)) ||
(!PORT_Memcmp(label, "3PCA", 4)) ||
(!PORT_Memcmp(label, "3PAA", 4)) ||
(!PORT_Memcmp(label, "3ICA", 4)) ||
(!PORT_Memcmp(label, "INKS", 4)) || /* v1 certs */
(!PORT_Memcmp(label, "INKX", 4)) ||
(!PORT_Memcmp(label, "ONKS", 4)) ||
(!PORT_Memcmp(label, "ONKX", 4)) ||
(!PORT_Memcmp(label, "RRXX", 4)) ||
(!PORT_Memcmp(label, "RTXX", 4)) ||
(!PORT_Memcmp(label, "LAXX", 4)) ) {
return PR_TRUE;
}
return PR_FALSE;
}
static
int fort11_cert_length(unsigned char *buf, int length) {
unsigned char tag;
int used_length= 0;
int data_length;
tag = buf[used_length++];
/* blow out when we come to the end */
if (tag == 0) {
return 0;
}
data_length = buf[used_length++];
if (data_length&0x80) {
int len_count = data_length & 0x7f;
data_length = 0;
while (len_count-- > 0) {
data_length = (data_length << 8) | buf[used_length++];
}
}
if (data_length > (length-used_length) ) {
return length;
}
return (data_length + used_length);
}
unsigned char *fort11_data_start(unsigned char *buf, int length,
int *data_length, PRBool includeTag) {
unsigned char tag;
int used_length= 0;
tag = buf[used_length++];
/* blow out when we come to the end */
if (tag == 0) {
return NULL;
}
*data_length = buf[used_length++];
if (*data_length&0x80) {
int len_count = *data_length & 0x7f;
*data_length = 0;
while (len_count-- > 0) {
*data_length = (*data_length << 8) | buf[used_length++];
}
}
if (*data_length > (length-used_length) ) {
*data_length = length-used_length;
return NULL;
}
if (includeTag) *data_length += used_length;
return (buf + (includeTag ? 0 : used_length));
}
int
fort11_GetCertFields(unsigned char *cert,int cert_length,CertItem *issuer,
CertItem *serial,CertItem *subject)
{
unsigned char *buf;
int buf_length;
unsigned char *date;
int datelen;
/* get past the signature wrap */
buf = fort11_data_start(cert,cert_length,&buf_length,PR_FALSE);
if (buf == NULL) return FAILED;
/* get into the raw cert data */
buf = fort11_data_start(buf,buf_length,&buf_length,PR_FALSE);
if (buf == NULL) return FAILED;
/* skip past any optional version number */
if ((buf[0] & 0xa0) == 0xa0) {
date = fort11_data_start(buf,buf_length,&datelen,PR_FALSE);
if (date == NULL) return FAILED;
buf_length -= (date-buf) + datelen;
buf = date + datelen;
}
/* serial number */
serial->data = fort11_data_start(buf,buf_length,&serial->len,PR_FALSE);
if (serial->data == NULL) return FAILED;
buf_length -= (serial->data-buf) + serial->len;
buf = serial->data + serial->len;
/* skip the OID */
date = fort11_data_start(buf,buf_length,&datelen,PR_FALSE);
if (date == NULL) return FAILED;
buf_length -= (date-buf) + datelen;
buf = date + datelen;
/* issuer */
issuer->data = fort11_data_start(buf,buf_length,&issuer->len,PR_TRUE);
if (issuer->data == NULL) return FAILED;
buf_length -= (issuer->data-buf) + issuer->len;
buf = issuer->data + issuer->len;
/* skip the date */
date = fort11_data_start(buf,buf_length,&datelen,PR_FALSE);
if (date == NULL) return FAILED;
buf_length -= (date-buf) + datelen;
buf = date + datelen;
/*subject */
subject->data=fort11_data_start(buf,buf_length,&subject->len,PR_TRUE);
if (subject->data == NULL) return FAILED;
buf_length -= (subject->data-buf) + subject->len;
buf = subject->data +subject->len;
/*subject */
return CKR_OK;
}
/* quick tohex function to get rid of scanf */
static
int fort11_tohex(char *s) {
int val = 0;
for(;*s;s++) {
if ((*s >= '0') && (*s <= '9')) {
val = (val << 4) + (*s - '0');
continue;
} else if ((*s >= 'a') && (*s <= 'f')) {
val = (val << 4) + (*s - 'a') + 10;
continue;
} else if ((*s >= 'A') && (*s <= 'F')) {
val = (val << 4) + (*s - 'A') + 10;
continue;
}
break;
}
return val;
}
/* only should be called for V3 KEA cert labels. */
static int
fort11_GetSibling(CI_CERT_STR label) {
int value = 0;
char s[3];
label +=4;
strcpy(s,"00");
memcpy(s, label, 2);
value = fort11_tohex(s);
/* sibling of 255 means no sibling */
if (value == 255) {
value = -1;
}
return value;
}
static PrivKeyType
fort11_GetKeyType(CI_CERT_STR label) {
if (label == NULL) return INVALID_KEY;
if ( (!PORT_Memcmp(label, "DSA1", 4)) || /* v3 certs */
(!PORT_Memcmp(label, "DSAI", 4)) ||
(!PORT_Memcmp(label, "DSAO", 4)) ||
(!PORT_Memcmp(label, "3IXS", 4)) || /* old v3 certs */
(!PORT_Memcmp(label, "3OXS", 4)) ) {
return DSA_KEY;
}
if ( (!PORT_Memcmp(label, "KEAK", 4)) ||
(!PORT_Memcmp(label, "3IKX", 4)) ) {
return KEA_KEY;
}
if ( (!PORT_Memcmp(label, "INKS", 4)) || /* V1 Certs*/
(!PORT_Memcmp(label, "INKX", 4)) ||
(!PORT_Memcmp(label, "ONKS", 4)) ||
(!PORT_Memcmp(label, "ONKX", 4)) ||
(!PORT_Memcmp(label, "RRXX", 4)) ||
(!PORT_Memcmp(label, "RTXX", 4)) ||
(!PORT_Memcmp(label, "LAXX", 4)) ) {
return V1_KEY;
}
return INVALID_KEY;
}
static CK_RV
fort11_ConvertToDSAKey(PK11Object *privateKey, PK11Slot *slot) {
CK_KEY_TYPE key_type = CKK_DSA;
CK_BBOOL cktrue = TRUE;
CK_BBOOL ckfalse = FALSE;
CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
CK_CHAR label[] = "A DSA Private Key";
/* Fill in the common Default values */
if (fort11_AddAttributeType(privateKey,CKA_START_DATE, NULL, 0) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey,CKA_END_DATE, NULL, 0) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey,CKA_SUBJECT, NULL, 0) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_CLASS, &privClass,
sizeof (CK_OBJECT_CLASS)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type,
sizeof(CK_KEY_TYPE)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType (privateKey, CKA_TOKEN, &cktrue,
sizeof (CK_BBOOL)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType (privateKey, CKA_LABEL, label,
PORT_Strlen((char*)label)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_SENSITIVE, &cktrue,
sizeof (CK_BBOOL)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_SIGN, &cktrue,
sizeof (CK_BBOOL)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_DERIVE, &cktrue,
sizeof(cktrue)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_LOCAL, &ckfalse,
sizeof(ckfalse)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_DECRYPT, &ckfalse,
sizeof(ckfalse)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_SIGN_RECOVER, &ckfalse,
sizeof(ckfalse)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_UNWRAP, &ckfalse,
sizeof(ckfalse)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_EXTRACTABLE, &ckfalse,
sizeof(ckfalse)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_ALWAYS_SENSITIVE, &cktrue,
sizeof(cktrue)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_NEVER_EXTRACTABLE, &cktrue,
sizeof(ckfalse)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_PRIME, NULL, 0) != CKR_OK){
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_SUBPRIME, NULL, 0) != CKR_OK){
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_BASE, NULL, 0) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_VALUE, NULL, 0) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_PRIVATE, &cktrue,
sizeof(cktrue)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_MODIFIABLE,&ckfalse,
sizeof(ckfalse)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
FMUTEX_Lock(slot->objectLock);
privateKey->handle = slot->tokenIDCount++;
privateKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
FMUTEX_Unlock(slot->objectLock);
privateKey->objclass = privClass;
privateKey->slot = slot;
privateKey->inDB = PR_TRUE;
return CKR_OK;
}
static int
fort11_LoadRootPAAKey(PK11Slot *slot, PK11Session *session) {
CK_OBJECT_CLASS theClass = CKO_SECRET_KEY;
int id = 0;
CK_BBOOL True = TRUE;
CK_BBOOL False = FALSE;
CK_CHAR label[] = "Trusted Root PAA Key";
PK11Object *rootKey;
FortezzaKey *newKey;
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
/*Don't know the key type. Does is matter?*/
rootKey = fort11_NewObject(slot);
if (rootKey == NULL) {
return CKR_HOST_MEMORY;
}
if (fort11_AddAttributeType(rootKey, CKA_CLASS, &theClass,
sizeof(theClass)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(rootKey, CKA_TOKEN, &True,
sizeof(True)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(rootKey, CKA_LABEL, label,
sizeof(label)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(rootKey, CKA_PRIVATE, &True,
sizeof (True)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(rootKey,CKA_MODIFIABLE, &False,
sizeof(False)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(rootKey, CKA_ID, &id,
sizeof(int)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(rootKey, CKA_DERIVE, &True,
sizeof(True)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(rootKey, CKA_SENSITIVE, &True,
sizeof(True)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
FMUTEX_Lock(slot->objectLock);
rootKey->handle = slot->tokenIDCount++;
rootKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
FMUTEX_Unlock(slot->objectLock);
rootKey->objclass = theClass;
rootKey->slot = slot;
rootKey->inDB = PR_TRUE;
newKey = NewFortezzaKey(socket, Ks, NULL, 0);
if (newKey == NULL) {
fort11_FreeObject(rootKey);
return CKR_HOST_MEMORY;
}
rootKey->objectInfo = (void*)newKey;
rootKey->infoFree = fort11_FreeFortezzaKey;
fort11_AddObject(session, rootKey);
return CKR_OK;
}
static CK_RV
fort11_ConvertToKEAKey (PK11Object *privateKey, PK11Slot *slot) {
CK_OBJECT_CLASS theClass = CKO_PRIVATE_KEY;
CK_KEY_TYPE keyType = CKK_KEA;
CK_CHAR label[] = "A KEA private key Object";
CK_BBOOL True = TRUE;
CK_BBOOL False = FALSE;
if (fort11_AddAttributeType(privateKey, CKA_CLASS, &theClass,
sizeof (CK_OBJECT_CLASS)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_KEY_TYPE, &keyType,
sizeof (CK_KEY_TYPE)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_TOKEN, &True,
sizeof(CK_BBOOL)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType (privateKey, CKA_LABEL, label,
PORT_Strlen((char*)label)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType (privateKey, CKA_SENSITIVE,
&True, sizeof(CK_BBOOL)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType (privateKey, CKA_DERIVE,
&True, sizeof(CK_BBOOL)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_PRIVATE, &True,
sizeof(True)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_START_DATE, NULL, 0) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_END_DATE, NULL, 0) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
if (fort11_AddAttributeType(privateKey, CKA_LOCAL, &False,
sizeof(False)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
FMUTEX_Lock(slot->objectLock);
privateKey->handle = slot->tokenIDCount++;
privateKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
FMUTEX_Unlock(slot->objectLock);
privateKey->objclass = theClass;
privateKey->slot = slot;
privateKey->inDB = PR_TRUE;
return CKR_OK;
}
static CK_RV
fort11_ConvertToV1Key (PK11Object* privateKey, PK11Slot *slot) {
CK_RV rv;
CK_BBOOL True = TRUE;
rv = fort11_ConvertToDSAKey(privateKey, slot);
if (rv != CKR_OK) {
return rv;
}
if (fort11_AddAttributeType(privateKey, CKA_DERIVE, &True,
sizeof (CK_BBOOL)) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
return CKR_OK;
}
static CK_RV
fort11_NewPrivateKey(PK11Object *privKeyObject, PK11Slot *slot,CI_PERSON currPerson) {
PrivKeyType keyType = fort11_GetKeyType(currPerson.CertLabel);
CK_RV rv;
switch (keyType) {
case DSA_KEY:
rv = fort11_ConvertToDSAKey(privKeyObject, slot);
break;
case KEA_KEY:
rv = fort11_ConvertToKEAKey(privKeyObject, slot);
break;
case V1_KEY:
rv = fort11_ConvertToV1Key(privKeyObject, slot);
break;
default:
rv = CKR_GENERAL_ERROR;
break;
}
return rv;
}
PRBool
fort11_LoadCertObjectForSearch(CI_PERSON currPerson, PK11Slot *slot,
PK11Session *session, CI_PERSON *pers_array) {
PK11Object *certObject, *privKeyObject;
PK11Attribute *attribute, *newAttribute;
int ci_rv;
CI_CERTIFICATE cert;
CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
CK_CERTIFICATE_TYPE certType = CKC_X_509;
CK_BBOOL cktrue = TRUE;
CK_BBOOL ckfalse = FALSE;
CertItem issuer, serial, subject;
int certSize;
char nickname[50];
char *cursor;
PrivKeyType priv_key;
int sibling;
certObject = fort11_NewObject(slot);
if (certObject == NULL)
return PR_FALSE;
ci_rv = MACI_GetCertificate (fortezzaSockets[slot->slotID-1].maciSession,
currPerson.CertificateIndex, cert);
if (ci_rv != CI_OK){
fort11_FreeObject(certObject);
return PR_FALSE;
}
ci_rv = fort11_GetCertFields(cert,CI_CERT_SIZE,&issuer,&serial,&subject);
if (ci_rv != CKR_OK) {
fort11_FreeObject(certObject);
return PR_FALSE;
}
if (fort11_AddAttributeType(certObject, CKA_CLASS, &certClass,
sizeof (CK_OBJECT_CLASS)) != CKR_OK) {
fort11_FreeObject (certObject);
return PR_FALSE;
}
if (fort11_AddAttributeType(certObject, CKA_TOKEN, &cktrue,
sizeof (CK_BBOOL)) != CKR_OK) {
fort11_FreeObject(certObject);
return PR_FALSE;
}
if (fort11_AddAttributeType(certObject, CKA_PRIVATE, &ckfalse,
sizeof (CK_BBOOL)) != CKR_OK) {
fort11_FreeObject(certObject);
return PR_FALSE;
}
/* check if the label represents a KEA key. if so, the
nickname should be made the same as the corresponding DSA
sibling cert. */
priv_key = fort11_GetKeyType(currPerson.CertLabel);
if (priv_key == KEA_KEY) {
sibling = fort11_GetSibling(currPerson.CertLabel);
/* check for failure of fort11_GetSibling. also check that
the sibling is not zero. */
if (sibling > 0) {
/* assign the KEA cert label to be the same as the
sibling DSA label */
sprintf (nickname, "%s", &pers_array[sibling-1].CertLabel[8] );
} else {
sprintf (nickname, "%s", &currPerson.CertLabel[8]);
}
} else {
sprintf (nickname, "%s", &currPerson.CertLabel[8]);
}
cursor = nickname+PORT_Strlen(nickname)-1;
while ((*cursor) == ' ') {
cursor--;
}
cursor[1] = '\0';
if (fort11_AddAttributeType(certObject, CKA_LABEL, nickname,
PORT_Strlen(nickname)) != CKR_OK) {
fort11_FreeObject(certObject);
return PR_FALSE;
}
if (fort11_AddAttributeType(certObject, CKA_CERTIFICATE_TYPE, &certType,
sizeof(CK_CERTIFICATE_TYPE)) != CKR_OK) {
fort11_FreeObject(certObject);
return PR_FALSE;
}
certSize = fort11_cert_length(cert,CI_CERT_SIZE);
if (fort11_AddAttributeType (certObject, CKA_VALUE, cert, certSize)
!= CI_OK) {
fort11_FreeObject(certObject);
return PR_FALSE;
}
if (fort11_AddAttributeType(certObject, CKA_ISSUER, issuer.data,
issuer.len) != CKR_OK) {
fort11_FreeObject (certObject);
return PR_FALSE;
}
if (fort11_AddAttributeType(certObject, CKA_SUBJECT, subject.data,
subject.len) != CKR_OK) {
fort11_FreeObject (certObject);
return PR_FALSE;
}
if (fort11_AddAttributeType(certObject, CKA_SERIAL_NUMBER,
serial.data, serial.len) != CKR_OK) {
fort11_FreeObject(certObject);
return PR_FALSE;
}
/*Change this to a byte array later*/
if (fort11_AddAttributeType(certObject, CKA_ID,
&currPerson.CertificateIndex,
sizeof(int)) != CKR_OK) {
fort11_FreeObject(certObject);
return PR_FALSE;
}
certObject->objectInfo = NULL;
certObject->infoFree = NULL;
certObject->objclass = certClass;
certObject->slot = slot;
certObject->inDB = PR_TRUE;
FMUTEX_Lock(slot->objectLock);
certObject->handle = slot->tokenIDCount++;
certObject->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_CERT);
FMUTEX_Unlock(slot->objectLock);
if (fort11_FortezzaIsUserCert (currPerson.CertLabel)) {
privKeyObject = fort11_NewObject(slot);
if (fort11_NewPrivateKey(privKeyObject, slot, currPerson) != CKR_OK) {
fort11_FreeObject(privKeyObject);
fort11_FreeObject(certObject);
return PR_FALSE;
}
if(fort11_AddAttributeType(privKeyObject,CKA_ID,
&currPerson.CertificateIndex,
sizeof(int)) != CKR_OK) {
fort11_FreeObject(privKeyObject);
fort11_FreeObject(certObject);
return PR_FALSE;
}
attribute = fort11_FindAttribute(certObject,CKA_SUBJECT);
newAttribute=
fort11_NewAttribute(pk11_attr_expand(&attribute->attrib));
fort11_FreeAttribute(attribute);
if (newAttribute != NULL) {
fort11_DeleteAttributeType(privKeyObject,
CKA_SUBJECT);
fort11_AddAttribute(privKeyObject,
newAttribute);
}
fort11_AddObject (session, privKeyObject);
}
fort11_AddObject (session, certObject);
return PR_TRUE;
}
#define TRUSTED_PAA "00000000Trusted Root PAA"
static int
fort11_BuildCertObjects(FortezzaSocket *currSocket, PK11Slot *slot,
PK11Session *session) {
int i;
CI_PERSON rootPAA;
PORT_Memcpy (rootPAA.CertLabel, TRUSTED_PAA, 1+PORT_Strlen (TRUSTED_PAA));
rootPAA.CertificateIndex = 0;
if (!fort11_LoadCertObjectForSearch(rootPAA, slot, session,
currSocket->personalityList)) {
return CKR_GENERAL_ERROR;
}
if (fort11_LoadRootPAAKey(slot, session) != CKR_OK) {
return CKR_GENERAL_ERROR;
}
for (i=0 ; i < currSocket->numPersonalities; i++) {
if (fort11_FortezzaIsACert (currSocket->personalityList[i].CertLabel)){
if (!fort11_LoadCertObjectForSearch(currSocket->personalityList[i],
slot, session,
currSocket->personalityList)){
return CKR_GENERAL_ERROR;
}
}
}
return CKR_OK;
}
PK11Slot*
fort11_SlotFromSessionHandle(CK_SESSION_HANDLE inHandle) {
CK_SESSION_HANDLE whichSlot = inHandle & SLOT_MASK;
if (whichSlot >= kNumSockets) return NULL_PTR;
return &fort11_slot[whichSlot];
}
PK11Slot*
fort11_SlotFromID (CK_SLOT_ID inSlotID) {
if (inSlotID == 0 || inSlotID > kNumSockets)
return NULL;
return &fort11_slot[inSlotID-1];
}
CK_ULONG fort11_firstSessionID (int inSlotNum) {
return (CK_ULONG)(inSlotNum);
}
/*
* Utility to convert passed in PIN to a CI_PIN
*/
void fort11_convertToCIPin (CI_PIN ciPin,CK_CHAR_PTR pPin, CK_ULONG ulLen) {
unsigned long i;
for (i=0; i<ulLen; i++) {
ciPin[i] = pPin[i];
}
ciPin[ulLen] = '\0';
}
/*
* return true if object has attribute
*/
static PRBool
fort11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) {
PK11Attribute *attribute;
FMUTEX_Lock(object->attributeLock);
pk11queue_find(attribute,type,object->head,HASH_SIZE);
FMUTEX_Unlock(object->attributeLock);
return (PRBool)(attribute != NULL);
}
/*
* create a new attribute with type, value, and length. Space is allocated
* to hold value.
*/
static PK11Attribute *
fort11_NewAttribute(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, CK_ULONG len) {
PK11Attribute *attribute;
CK_RV mrv;
attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute));
if (attribute == NULL) return NULL;
attribute->attrib.type = type;
if (value) {
attribute->attrib.pValue = (CK_VOID_PTR)PORT_Alloc(len);
if (attribute->attrib.pValue == NULL) {
PORT_Free(attribute);
return NULL;
}
PORT_Memcpy(attribute->attrib.pValue,value,len);
attribute->attrib.ulValueLen = len;
} else {
attribute->attrib.pValue = NULL;
attribute->attrib.ulValueLen = 0;
}
attribute->handle = type;
attribute->next = attribute->prev = NULL;
attribute->refCount = 1;
if (FMUTEX_MutexEnabled()) {
mrv = FMUTEX_Create (&attribute->refLock);
if (mrv != CKR_OK) {
if (attribute->attrib.pValue) PORT_Free(attribute->attrib.pValue);
PORT_Free(attribute);
return NULL;
}
} else {
attribute->refLock = NULL;
}
return attribute;
}
/*
* add an attribute to an object
*/
static
void fort11_AddAttribute(PK11Object *object,PK11Attribute *attribute) {
FMUTEX_Lock (object->attributeLock);
pk11queue_add(attribute,attribute->handle,object->head,HASH_SIZE);
FMUTEX_Unlock(object->attributeLock);
}
static CK_RV
fort11_AddAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *valPtr,
CK_ULONG length) {
PK11Attribute *attribute;
attribute = fort11_NewAttribute(type,valPtr,length);
if (attribute == NULL) { return CKR_HOST_MEMORY; }
fort11_AddAttribute(object,attribute);
return CKR_OK;
}
/* Make sure a given attribute exists. If it doesn't, initialize it to
* value and len
*/
static CK_RV
fort11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *value,
unsigned int len) {
if ( !fort11_hasAttribute(object, type)) {
return fort11_AddAttributeType(object,type,value,len);
}
return CKR_OK;
}
/*
* look up and attribute structure from a type and Object structure.
* The returned attribute is referenced and needs to be freed when
* it is no longer needed.
*/
static PK11Attribute *
fort11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) {
PK11Attribute *attribute;
FMUTEX_Lock(object->attributeLock);
pk11queue_find(attribute,type,object->head,HASH_SIZE);
if (attribute) {
/* atomic increment would be nice here */
FMUTEX_Lock(attribute->refLock);
attribute->refCount++;
FMUTEX_Unlock(attribute->refLock);
}
FMUTEX_Unlock(object->attributeLock);
return(attribute);
}
/*
* this is only valid for CK_BBOOL type attributes. Return the state
* of that attribute.
*/
static PRBool
fort11_isTrue(PK11Object *object,CK_ATTRIBUTE_TYPE type) {
PK11Attribute *attribute;
PRBool tok = PR_FALSE;
attribute=fort11_FindAttribute(object,type);
if (attribute == NULL) { return PR_FALSE; }
tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue);
fort11_FreeAttribute(attribute);
return tok;
}
/*
* add an object to a slot and session queue
*/
static
void fort11_AddSlotObject(PK11Slot *slot, PK11Object *object) {
FMUTEX_Lock(slot->objectLock);
pk11queue_add(object,object->handle,slot->tokObjects,HASH_SIZE);
FMUTEX_Unlock(slot->objectLock);
}
static
void fort11_AddObject(PK11Session *session, PK11Object *object) {
PK11Slot *slot = fort11_SlotFromSession(session);
if (!fort11_isToken(object->handle)) {
FMUTEX_Lock(session->objectLock);
pk11queue_add(&object->sessionList,0,session->objects,0);
FMUTEX_Unlock(session->objectLock);
}
fort11_AddSlotObject(slot,object);
}
/*
* free all the data associated with an object. Object reference count must
* be 'zero'.
*/
static CK_RV
fort11_DestroyObject(PK11Object *object) {
int i;
CK_RV crv = CKR_OK;
/* PORT_Assert(object->refCount == 0);*/
if (object->label) PORT_Free(object->label);
/* clean out the attributes */
/* since no one is referencing us, it's safe to walk the chain
* without a lock */
for (i=0; i < HASH_SIZE; i++) {
PK11Attribute *ap,*next;
for (ap = object->head[i]; ap != NULL; ap = next) {
next = ap->next;
/* paranoia */
ap->next = ap->prev = NULL;
fort11_FreeAttribute(ap);
}
object->head[i] = NULL;
}
FMUTEX_Destroy(object->attributeLock);
FMUTEX_Destroy(object->refLock);
if (object->objectInfo) {
(*object->infoFree)(object->objectInfo);
}
PORT_Free(object);
return crv;
}
/*
* release a reference to an attribute structure
*/
static void
fort11_FreeAttribute(PK11Attribute *attribute) {
PRBool destroy = PR_FALSE;
FMUTEX_Lock(attribute->refLock);
if (attribute->refCount == 1) destroy = PR_TRUE;
attribute->refCount--;
FMUTEX_Unlock(attribute->refLock);
if (destroy) fort11_DestroyAttribute(attribute);
}
/*
* release a reference to an object handle
*/
static PK11FreeStatus
fort11_FreeObject(PK11Object *object) {
PRBool destroy = PR_FALSE;
CK_RV crv;
FMUTEX_Lock(object->refLock);
if (object->refCount == 1) destroy = PR_TRUE;
object->refCount--;
FMUTEX_Unlock(object->refLock);
if (destroy) {
crv = fort11_DestroyObject(object);
if (crv != CKR_OK) {
return PK11_DestroyFailure;
}
return PK11_Destroyed;
}
return PK11_Busy;
}
static void
fort11_update_state(PK11Slot *slot,PK11Session *session) {
if (slot->isLoggedIn) {
if (slot->ssoLoggedIn) {
session->info.state = CKS_RW_SO_FUNCTIONS;
} else if (session->info.flags & CKF_RW_SESSION) {
session->info.state = CKS_RW_USER_FUNCTIONS;
} else {
session->info.state = CKS_RO_USER_FUNCTIONS;
}
} else {
if (session->info.flags & CKF_RW_SESSION) {
session->info.state = CKS_RW_PUBLIC_SESSION;
} else {
session->info.state = CKS_RO_PUBLIC_SESSION;
}
}
}
/* update the state of all the sessions on a slot */
static void
fort11_update_all_states(PK11Slot *slot) {
int i;
PK11Session *session;
for (i=0; i < SESSION_HASH_SIZE; i++) {
FMUTEX_Lock(slot->sessionLock);
for (session = slot->head[i]; session; session = session->next) {
fort11_update_state(slot,session);
}
FMUTEX_Unlock(slot->sessionLock);
}
}
/*
* Create a new object
*/
static PK11Object *
fort11_NewObject(PK11Slot *slot) {
PK11Object *object;
CK_RV mrv;
int i;
object = (PK11Object*)PORT_Alloc(sizeof(PK11Object));
if (object == NULL) return NULL;
object->handle = 0;
object->next = object->prev = NULL;
object->sessionList.next = NULL;
object->sessionList.prev = NULL;
object->sessionList.parent = object;
object->inDB = PR_FALSE;
object->label = NULL;
object->refCount = 1;
object->session = NULL;
object->slot = slot;
object->objclass = 0xffff;
if (FMUTEX_MutexEnabled()) {
mrv = FMUTEX_Create(&object->refLock);
if (mrv != CKR_OK) {
PORT_Free(object);
return NULL;
}
mrv = FMUTEX_Create(&object->attributeLock);
if (mrv != CKR_OK) {
FMUTEX_Destroy(object->refLock);
PORT_Free(object);
return NULL;
}
} else {
object->attributeLock = NULL;
object->refLock = NULL;
}
for (i=0; i < HASH_SIZE; i++) {
object->head[i] = NULL;
}
object->objectInfo = NULL;
object->infoFree = NULL;
return object;
}
/*
* look up and object structure from a handle. OBJECT_Handles only make
* sense in terms of a given session. make a reference to that object
* structure returned.
*/
static PK11Object * fort11_ObjectFromHandle(CK_OBJECT_HANDLE handle,
PK11Session *session) {
PK11Object **head;
void *lock;
PK11Slot *slot = fort11_SlotFromSession(session);
PK11Object *object;
/*
* Token objects are stored in the slot. Session objects are stored
* with the session.
*/
head = slot->tokObjects;
lock = slot->objectLock;
FMUTEX_Lock(lock);
pk11queue_find(object,handle,head,HASH_SIZE);
if (object) {
FMUTEX_Lock(object->refLock);
object->refCount++;
FMUTEX_Unlock(object->refLock);
}
FMUTEX_Unlock(lock);
return(object);
}
/*
* add an object to a slot andsession queue
*/
static
void fort11_DeleteObject(PK11Session *session, PK11Object *object) {
PK11Slot *slot;
if (session == NULL)
return;
slot = fort11_SlotFromSession(session);
if (!fort11_isToken(object->handle)) {
FMUTEX_Lock(session->objectLock);
pk11queue_delete(&object->sessionList,0,session->objects,0);
FMUTEX_Unlock(session->objectLock);
}
FMUTEX_Lock(slot->objectLock);
pk11queue_delete(object,object->handle,slot->tokObjects,HASH_SIZE);
FMUTEX_Unlock(slot->objectLock);
fort11_FreeObject(object);
}
/*
* ******************** Search Utilities *******************************
*/
/* add an object to a search list */
CK_RV
fort11_AddToList(PK11ObjectListElement **list,PK11Object *object) {
PK11ObjectListElement *newelem =
(PK11ObjectListElement *)PORT_Alloc(sizeof(PK11ObjectListElement));
if (newelem == NULL) return CKR_HOST_MEMORY;
newelem->next = *list;
newelem->object = object;
FMUTEX_Lock(object->refLock);
object->refCount++;
FMUTEX_Unlock(object->refLock);
*list = newelem;
return CKR_OK;
}
/*
* free a single list element. Return the Next object in the list.
*/
PK11ObjectListElement *
fort11_FreeObjectListElement(PK11ObjectListElement *objectList) {
PK11ObjectListElement *ol = objectList->next;
fort11_FreeObject(objectList->object);
PORT_Free(objectList);
return ol;
}
/* free an entire object list */
void
fort11_FreeObjectList(PK11ObjectListElement *objectList) {
PK11ObjectListElement *ol;
for (ol= objectList; ol != NULL; ol = fort11_FreeObjectListElement(ol)) {}
}
/*
* free a search structure
*/
void
fort11_FreeSearch(PK11SearchResults *search) {
if (search->handles) {
PORT_Free(search->handles);
}
PORT_Free(search);
}
/*
* Free up all the memory associated with an attribute. Reference count
* must be zero to call this.
*/
static void
fort11_DestroyAttribute(PK11Attribute *attribute) {
/*PORT_Assert(attribute->refCount == 0);*/
FMUTEX_Destroy(attribute->refLock);
if (attribute->attrib.pValue) {
/* clear out the data in the attribute value... it may have been
* sensitive data */
PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
PORT_Free(attribute->attrib.pValue);
}
PORT_Free(attribute);
}
/*
* delete an attribute from an object
*/
static void
fort11_DeleteAttribute(PK11Object *object, PK11Attribute *attribute) {
FMUTEX_Lock(object->attributeLock);
if (attribute->next || attribute->prev) {
pk11queue_delete(attribute,attribute->handle,
object->head,HASH_SIZE);
}
FMUTEX_Unlock(object->attributeLock);
fort11_FreeAttribute(attribute);
}
/*
* decode when a particular attribute may be modified
* PK11_NEVER: This attribute must be set at object creation time and
* can never be modified.
* PK11_ONCOPY: This attribute may be modified only when you copy the
* object.
* PK11_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from
* FALSE to TRUE.
* PK11_ALWAYS: This attribute can always be modified.
* Some attributes vary their modification type based on the class of the
* object.
*/
PK11ModifyType
fort11_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass) {
/* if we don't know about it, user user defined, always allow modify */
PK11ModifyType mtype = PK11_ALWAYS;
switch(type) {
/* NEVER */
case CKA_CLASS:
case CKA_CERTIFICATE_TYPE:
case CKA_KEY_TYPE:
case CKA_MODULUS:
case CKA_MODULUS_BITS:
case CKA_PUBLIC_EXPONENT:
case CKA_PRIVATE_EXPONENT:
case CKA_PRIME:
case CKA_SUBPRIME:
case CKA_BASE:
case CKA_PRIME_1:
case CKA_PRIME_2:
case CKA_EXPONENT_1:
case CKA_EXPONENT_2:
case CKA_COEFFICIENT:
case CKA_VALUE_LEN:
mtype = PK11_NEVER;
break;
/* ONCOPY */
case CKA_TOKEN:
case CKA_PRIVATE:
mtype = PK11_ONCOPY;
break;
/* SENSITIVE */
case CKA_SENSITIVE:
mtype = PK11_SENSITIVE;
break;
/* ALWAYS */
case CKA_LABEL:
case CKA_APPLICATION:
case CKA_ID:
case CKA_SERIAL_NUMBER:
case CKA_START_DATE:
case CKA_END_DATE:
case CKA_DERIVE:
case CKA_ENCRYPT:
case CKA_DECRYPT:
case CKA_SIGN:
case CKA_VERIFY:
case CKA_SIGN_RECOVER:
case CKA_VERIFY_RECOVER:
case CKA_WRAP:
case CKA_UNWRAP:
mtype = PK11_ALWAYS;
break;
/* DEPENDS ON CLASS */
case CKA_VALUE:
mtype = (inClass == CKO_DATA) ? PK11_ALWAYS : PK11_NEVER;
break;
case CKA_SUBJECT:
mtype = (inClass == CKO_CERTIFICATE) ? PK11_NEVER : PK11_ALWAYS;
break;
default:
break;
}
return mtype;
}
/* decode if a particular attribute is sensitive (cannot be read
* back to the user of if the object is set to SENSITIVE) */
PRBool
fort11_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass) {
switch(type) {
/* ALWAYS */
case CKA_PRIVATE_EXPONENT:
case CKA_PRIME_1:
case CKA_PRIME_2:
case CKA_EXPONENT_1:
case CKA_EXPONENT_2:
case CKA_COEFFICIENT:
return PR_TRUE;
/* DEPENDS ON CLASS */
case CKA_VALUE:
/* PRIVATE and SECRET KEYS have SENSITIVE values */
return (PRBool)((inClass == CKO_PRIVATE_KEY) ||
(inClass == CKO_SECRET_KEY));
default:
break;
}
return PR_FALSE;
}
static void
fort11_DeleteAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type) {
PK11Attribute *attribute;
attribute = fort11_FindAttribute(object, type);
if (attribute == NULL) return ;
fort11_DeleteAttribute(object,attribute);
}
/*
* create a new nession. NOTE: The session handle is not set, and the
* session is not added to the slot's session queue.
*/
static PK11Session *
fort11_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify,
CK_VOID_PTR pApplication,
CK_FLAGS flags) {
PK11Session *session;
PK11Slot *slot = &fort11_slot[slotID-1];
CK_RV mrv;
if (slot == NULL) return NULL;
session = (PK11Session*)PORT_Alloc(sizeof(PK11Session));
if (session == NULL) return NULL;
session->next = session->prev = NULL;
session->refCount = 1;
session->context = NULL;
session->search = NULL;
session->objectIDCount = 1;
session->fortezzaContext.fortezzaKey = NULL;
session->fortezzaContext.fortezzaSocket = NULL;
if (FMUTEX_MutexEnabled()) {
mrv = FMUTEX_Create(&session->refLock);
if (mrv != CKR_OK) {
PORT_Free(session);
return NULL;
}
mrv = FMUTEX_Create(&session->objectLock);
if (mrv != CKR_OK) {
FMUTEX_Destroy(session->refLock);
PORT_Free(session);
return NULL;
}
} else {
session->refLock = NULL;
session->objectLock = NULL;
}
session->objects[0] = NULL;
session->slot = slot;
session->notify = notify;
session->appData = pApplication;
session->info.flags = flags;
session->info.slotID = slotID;
fort11_update_state(slot,session);
return session;
}
/*
* look up a session structure from a session handle
* generate a reference to it.
*/
PK11Session *
fort11_SessionFromHandle(CK_SESSION_HANDLE handle, PRBool isCloseSession) {
PK11Slot *slot = fort11_SlotFromSessionHandle(handle);
PK11Session *session;
if (!isCloseSession &&
!SocketStateUnchanged(&fortezzaSockets[slot->slotID-1]))
return NULL;
FMUTEX_Lock(slot->sessionLock);
pk11queue_find(session,handle,slot->head,SESSION_HASH_SIZE);
if (session) session->refCount++;
FMUTEX_Unlock(slot->sessionLock);
return (session);
}
/* free all the data associated with a session. */
static void
fort11_DestroySession(PK11Session *session)
{
PK11ObjectList *op,*next;
/* PORT_Assert(session->refCount == 0);*/
/* clean out the attributes */
FMUTEX_Lock(session->objectLock);
for (op = session->objects[0]; op != NULL; op = next) {
next = op->next;
/* paranoia */
op->next = op->prev = NULL;
fort11_DeleteObject(session,op->parent);
}
FMUTEX_Unlock(session->objectLock);
FMUTEX_Destroy(session->objectLock);
FMUTEX_Destroy(session->refLock);
if (session->search) {
fort11_FreeSearch(session->search);
}
pk11queue_delete(session, session->handle, session->slot->head,
SESSION_HASH_SIZE);
PORT_Free(session);
}
/*
* release a reference to a session handle
*/
void
fort11_FreeSession(PK11Session *session) {
PRBool destroy = PR_FALSE;
PK11Slot *slot = NULL;
if (!session) return; /*Quick fix to elminate crash*/
/*Fix in later version */
if (FMUTEX_MutexEnabled()) {
slot = fort11_SlotFromSession(session);
FMUTEX_Lock(slot->sessionLock);
}
if (session->refCount == 1) destroy = PR_TRUE;
session->refCount--;
if (FMUTEX_MutexEnabled()) {
FMUTEX_Unlock(slot->sessionLock);
}
if (destroy) {
fort11_DestroySession(session);
}
}
/* return true if the object matches the template */
PRBool
fort11_objectMatch(PK11Object *object,CK_ATTRIBUTE_PTR theTemplate,int count) {
int i;
for (i=0; i < count; i++) {
PK11Attribute *attribute =
fort11_FindAttribute(object,theTemplate[i].type);
if (attribute == NULL) {
return PR_FALSE;
}
if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) {
if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue,
theTemplate[i].ulValueLen) == 0) {
fort11_FreeAttribute(attribute);
continue;
}
}
fort11_FreeAttribute(attribute);
return PR_FALSE;
}
return PR_TRUE;
}
/* search through all the objects in the queue and return the template matches
* in the object list.
*/
CK_RV
fort11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head,
void *lock, CK_ATTRIBUTE_PTR theTemplate, int count) {
int i;
PK11Object *object;
CK_RV rv;
for(i=0; i < HASH_SIZE; i++) {
/* We need to hold the lock to copy a consistant version of
* the linked list. */
FMUTEX_Lock(lock);
for (object = head[i]; object != NULL; object= object->next) {
if (fort11_objectMatch(object,theTemplate,count)) {
rv = fort11_AddToList(objectList,object);
if (rv != CKR_OK) {
return rv;
}
}
}
FMUTEX_Unlock(lock);
}
return CKR_OK;
}
static PRBool
fort11_NotAllFuncsNULL (CK_C_INITIALIZE_ARGS_PTR pArgs) {
return (PRBool)(pArgs && pArgs->CreateMutex && pArgs->DestroyMutex &&
pArgs->LockMutex && pArgs->UnlockMutex);
}
static PRBool
fort11_InArgCheck(CK_C_INITIALIZE_ARGS_PTR pArgs) {
PRBool rv;
/* The only check for now, is to make sure that all of the
* function pointers are either all NULL or all Non-NULL.
* We also need to make sure the pReserved field in pArgs is
* set to NULL.
*/
if (pArgs == NULL) {
return PR_TRUE; /* If the argument is NULL, no
* inconsistencies can exist.
*/
}
if (pArgs->pReserved != NULL) {
return PR_FALSE;
}
if (pArgs->CreateMutex != NULL) {
rv = (PRBool) (pArgs->DestroyMutex != NULL &&
pArgs->LockMutex != NULL &&
pArgs->UnlockMutex != NULL);
} else { /*pArgs->CreateMutex == NULL*/
rv = (PRBool) (pArgs->DestroyMutex == NULL &&
pArgs->LockMutex == NULL &&
pArgs->UnlockMutex == NULL);
}
return rv;
}
/**********************************************************************
*
* Start of PKCS 11 functions
*
**********************************************************************/
/**********************************************************************
*
* In order to get this to work on 68K, we have to do some special tricks,
* First trick is that we need to make the module a Code Resource, and
* all Code Resources on 68K have to have a main function. So we
* define main to be a wrapper for C_GetFunctionList which will be the
* first funnction called by any software that uses the PKCS11 module.
*
* The second trick is that whenever you access a global variable from
* the Code Resource, it does funny things to the stack on 68K, so we
* need to call some macros that handle the stack for us. First thing
* you do is call EnterCodeResource() first thing in a function that
* accesses a global, right before you leave that function, you call
* ExitCodeResource. This will take care of stack management.
*
* Third trick is to call __InitCode__() when we first enter the module
* so that all of the global variables get initialized properly.
*
**********************************************************************/
#if defined(XP_MAC) && !defined(__POWERPC__)
#define FORT11_RETURN(exp) {ExitCodeResource(); return (exp);}
#define FORT11_ENTER() EnterCodeResource();
#else /*XP_MAC*/
#define FORT11_RETURN(exp) return (exp);
#define FORT11_ENTER()
#endif /*XP_MAC*/
#define CARD_OK(rv) if ((rv) != CI_OK) FORT11_RETURN (CKR_DEVICE_ERROR);
#define SLOT_OK(slot) if ((slot) > kNumSockets) FORT11_RETURN (CKR_SLOT_ID_INVALID);
#ifdef XP_MAC
/* This is not a 4.0 project, so I can't depend on
* 4.0 defines, so instead I depend on CodeWarrior
* defines.
*/
#if __POWERPC__
#elif __CFM68K__
#else
/* To get this to work on 68K, we need to have
* the symbol main. So we just make it a wrapper for C_GetFunctionList.
*/
PR_PUBLIC_API(CK_RV) main(CK_FUNCTION_LIST_PTR *pFunctionList) {
FORT11_ENTER()
CK_RV rv;
__InitCode__();
rv = C_GetFunctionList(pFunctionList);
FORT11_RETURN (rv);
}
#endif
#endif /*XP_MAC*/
/* Return the function list */
PR_PUBLIC_API(CK_RV) C_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) {
/* No need to do a FORT11_RETURN as this function will never be directly
* called in the case where we need to do stack management.
* The main function will call this after taking care of stack stuff.
*/
*pFunctionList = &fort11_funcList;
return CKR_OK;
}
/* C_Initialize initializes the Cryptoki library. */
PR_PUBLIC_API(CK_RV) C_Initialize(CK_VOID_PTR pReserved) {
FORT11_ENTER()
int i,j, tempNumSockets;
int rv = 1;
CK_C_INITIALIZE_ARGS_PTR pArgs = (CK_C_INITIALIZE_ARGS_PTR)pReserved;
CK_RV mrv;
/* intialize all the slots */
if (!init) {
init = PR_TRUE;
/* need to initialize locks before MACI_Initialize is called in
* software fortezza. */
if (pArgs) {
if (!fort11_InArgCheck(pArgs)) {
FORT11_RETURN (CKR_ARGUMENTS_BAD);
}
if (pArgs->flags & CKF_OS_LOCKING_OK){
if (!fort11_NotAllFuncsNULL(pArgs)) {
FORT11_RETURN (CKR_CANT_LOCK);
}
}
if (fort11_NotAllFuncsNULL(pArgs)) {
mrv = FMUTEX_Init(pArgs);
if (mrv != CKR_OK) {
return CKR_GENERAL_ERROR;
}
}
}
rv = MACI_Initialize (&tempNumSockets);
kNumSockets = (CK_ULONG)tempNumSockets;
CARD_OK (rv);
for (i=0; i < (int) kNumSockets; i++) {
if (FMUTEX_MutexEnabled()) {
mrv = FMUTEX_Create(&fort11_slot[i].sessionLock);
if (mrv != CKR_OK) {
FORT11_RETURN (CKR_GENERAL_ERROR);
}
mrv = FMUTEX_Create(&fort11_slot[i].objectLock);
if (mrv != CKR_OK) {
FMUTEX_Destroy(fort11_slot[i].sessionLock);
FORT11_RETURN (CKR_GENERAL_ERROR);
}
} else {
fort11_slot[i].sessionLock = NULL;
fort11_slot[i].objectLock = NULL;
}
for(j=0; j < SESSION_HASH_SIZE; j++) {
fort11_slot[i].head[j] = NULL;
}
for(j=0; j < HASH_SIZE; j++) {
fort11_slot[i].tokObjects[j] = NULL;
}
fort11_slot[i].password = NULL;
fort11_slot[i].hasTokens = PR_FALSE;
fort11_slot[i].sessionIDCount = fort11_firstSessionID (i);
fort11_slot[i].sessionCount = 0;
fort11_slot[i].rwSessionCount = 0;
fort11_slot[i].tokenIDCount = 1;
fort11_slot[i].needLogin = PR_TRUE;
fort11_slot[i].isLoggedIn = PR_FALSE;
fort11_slot[i].ssoLoggedIn = PR_FALSE;
fort11_slot[i].DB_loaded = PR_FALSE;
fort11_slot[i].slotID= i+1;
InitSocket(&fortezzaSockets[i], i+1);
}
}
FORT11_RETURN (CKR_OK);
}
/*C_Finalize indicates that an application is done with the Cryptoki library.*/
PR_PUBLIC_API(CK_RV) C_Finalize (CK_VOID_PTR pReserved) {
FORT11_ENTER()
int i;
for (i=0; i< (int) kNumSockets; i++) {
FreeSocket(&fortezzaSockets[i]);
}
MACI_Terminate(fortezzaSockets[0].maciSession);
init = PR_FALSE;
FORT11_RETURN (CKR_OK);
}
/* C_GetInfo returns general information about Cryptoki. */
PR_PUBLIC_API(CK_RV) C_GetInfo(CK_INFO_PTR pInfo) {
FORT11_ENTER()
pInfo->cryptokiVersion = fort11_funcList.version;
PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
pInfo->libraryVersion.major = 1;
pInfo->libraryVersion.minor = 7;
PORT_Memcpy(pInfo->libraryDescription,libraryDescription,32);
pInfo->flags = 0;
FORT11_RETURN (CKR_OK);
}
/* C_GetSlotList obtains a list of slots in the system. */
PR_PUBLIC_API(CK_RV) C_GetSlotList(CK_BBOOL tokenPresent,
CK_SLOT_ID_PTR pSlotList,
CK_ULONG_PTR pulCount) {
FORT11_ENTER()
int i;
if (pSlotList != NULL) {
if (*pulCount >= kNumSockets) {
for (i=0; i < (int) kNumSockets; i++) {
pSlotList[i] = i+1;
}
} else {
FORT11_RETURN (CKR_BUFFER_TOO_SMALL);
}
} else {
*pulCount = kNumSockets;
}
FORT11_RETURN (CKR_OK);
}
/* C_GetSlotInfo obtains information about a particular slot in the system. */
PR_PUBLIC_API(CK_RV) C_GetSlotInfo(CK_SLOT_ID slotID,
CK_SLOT_INFO_PTR pInfo) {
FORT11_ENTER()
int rv;
CI_CONFIG ciConfig;
CI_STATE ciState;
HSESSION maciSession;
char slotDescription[65];
FortezzaSocket *socket;
SLOT_OK(slotID);
socket = &fortezzaSockets[slotID-1];
if (!socket->isOpen) {
InitSocket(socket, slotID);
}
maciSession = socket->maciSession;
rv = MACI_Select(maciSession, slotID);
CARD_OK (rv)
rv = MACI_GetConfiguration (maciSession, &ciConfig);
pInfo->firmwareVersion.major = 0;
pInfo->firmwareVersion.minor = 0;
#ifdef SWFORT
PORT_Memcpy (pInfo->manufacturerID,"Netscape Communications Corp ",32);
PORT_Memcpy (slotDescription,"Netscape Software Slot # ",32);
#define _local_BASE 24
#else
PORT_Memcpy (pInfo->manufacturerID,"LITRONIC ",32);
PORT_Memcpy (slotDescription,"Litronic MACI Slot # ",32);
#define _local_BASE 20
#endif
slotDescription[_local_BASE] = (char )((slotID < 10) ? slotID :
slotID/10) + '0';
if (slotID >= 10) slotDescription[_local_BASE+1] =
(char)(slotID % 10) + '0';
PORT_Memcpy (&slotDescription[32]," ",32);
PORT_Memcpy (pInfo->slotDescription, slotDescription , 64);
if (rv == CI_OK) {
pInfo->hardwareVersion.major =
(ciConfig.ManufacturerVersion & MAJOR_VERSION_MASK) >> 8;
pInfo->hardwareVersion.minor =
ciConfig.ManufacturerVersion & MINOR_VERSION_MASK;
pInfo->flags = CKF_TOKEN_PRESENT;
} else {
pInfo->hardwareVersion.major = 0;
pInfo->hardwareVersion.minor = 0;
pInfo->flags = 0;
}
#ifdef SWFORT
/* do we need to make it a removable device as well?? */
pInfo->flags |= CKF_REMOVABLE_DEVICE;
#else
pInfo->flags |= (CKF_REMOVABLE_DEVICE | CKF_HW_SLOT);
#endif
rv = MACI_GetState(maciSession, &ciState);
if (rv == CI_OK) {
switch (ciState) {
case CI_ZEROIZE:
case CI_INTERNAL_FAILURE:
pInfo->flags &= (~CKF_TOKEN_PRESENT);
default:
break;
}
} else {
pInfo->flags &= (~CKF_TOKEN_PRESENT);
}
FORT11_RETURN (CKR_OK);
}
#define CKF_THREAD_SAFE 0x8000
/* C_GetTokenInfo obtains information about a particular token
in the system. */
PR_PUBLIC_API(CK_RV) C_GetTokenInfo(CK_SLOT_ID slotID,
CK_TOKEN_INFO_PTR pInfo) {
FORT11_ENTER()
CI_STATUS cardStatus;
CI_CONFIG ciConfig;
PK11Slot *slot;
int rv, i;
char tmp[33];
FortezzaSocket *socket;
SLOT_OK (slotID);
slot = &fort11_slot[slotID-1];
socket = &fortezzaSockets[slotID-1];
if (!socket->isOpen) {
InitSocket(socket, slotID);
}
rv = MACI_Select (socket->maciSession, slotID);
rv = MACI_GetStatus (socket->maciSession, &cardStatus);
if (rv != CI_OK) {
FORT11_RETURN (CKR_DEVICE_ERROR);
}
#ifdef SWFORT
sprintf (tmp, "Software FORTEZZA Slot #%d", (int) slotID);
#else
sprintf (tmp, "FORTEZZA Slot #%d", (int) slotID);
#endif
PORT_Memcpy (pInfo->label, tmp, PORT_Strlen(tmp)+1);
for (i=0; i<8; i++) {
int serNum;
serNum = (int)cardStatus.SerialNumber[i];
sprintf ((char*)&pInfo->serialNumber[2*i], "%.2x", serNum);
}
rv = MACI_GetTime (fortezzaSockets[slotID-1].maciSession, pInfo->utcTime);
if (rv == CI_OK) {
pInfo->flags = CKF_CLOCK_ON_TOKEN;
} else {
switch (rv) {
case CI_LIB_NOT_INIT:
case CI_INV_POINTER:
case CI_NO_CARD:
case CI_NO_SOCKET:
FORT11_RETURN (CKR_DEVICE_ERROR);
default:
pInfo->flags = 0;
break;
}
}
rv = MACI_GetConfiguration (fortezzaSockets[slotID-1].maciSession,
&ciConfig);
if (rv == CI_OK) {
PORT_Memcpy(pInfo->manufacturerID,ciConfig.ManufacturerName,
PORT_Strlen(ciConfig.ManufacturerName));
for (i=PORT_Strlen(ciConfig.ManufacturerName); i<32; i++) {
pInfo->manufacturerID[i] = ' ';
}
PORT_Memcpy(pInfo->model,ciConfig.ProcessorType,16);
}
pInfo->ulMaxPinLen = CI_PIN_SIZE;
pInfo->ulMinPinLen = 0;
pInfo->ulTotalPublicMemory = 0;
pInfo->ulFreePublicMemory = 0;
pInfo->flags |= CKF_RNG | CKF_LOGIN_REQUIRED| CKF_USER_PIN_INITIALIZED |
CKF_THREAD_SAFE | CKF_WRITE_PROTECTED;
pInfo->ulMaxSessionCount = 0;
pInfo->ulSessionCount = slot->sessionCount;
pInfo->ulMaxRwSessionCount = 0;
pInfo->ulRwSessionCount = slot->rwSessionCount;
if (rv == CI_OK) {
pInfo->firmwareVersion.major =
(ciConfig.ManufacturerSWVer & MAJOR_VERSION_MASK) >> 8;
pInfo->firmwareVersion.minor =
ciConfig.ManufacturerSWVer & MINOR_VERSION_MASK;
pInfo->hardwareVersion.major =
(ciConfig.ManufacturerVersion & MAJOR_VERSION_MASK) >> 8;
pInfo->hardwareVersion.minor =
ciConfig.ManufacturerVersion & MINOR_VERSION_MASK;
}
FORT11_RETURN (CKR_OK);
}
/* C_GetMechanismList obtains a list of mechanism types supported by a
token. */
PR_PUBLIC_API(CK_RV) C_GetMechanismList(CK_SLOT_ID slotID,
CK_MECHANISM_TYPE_PTR pMechanismList,
CK_ULONG_PTR pulCount) {
FORT11_ENTER()
CK_RV rv = CKR_OK;
int i;
SLOT_OK (slotID);
if (pMechanismList == NULL) {
*pulCount = mechanismCount;
} else {
if (*pulCount >= mechanismCount) {
*pulCount = mechanismCount;
for (i=0; i< (int)mechanismCount; i++) {
pMechanismList[i] = mechanisms[i].type;
}
} else {
rv = CKR_BUFFER_TOO_SMALL;
}
}
FORT11_RETURN (rv);
}
/* C_GetMechanismInfo obtains information about a particular mechanism
* possibly supported by a token. */
PR_PUBLIC_API(CK_RV) C_GetMechanismInfo(CK_SLOT_ID slotID,
CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo) {
int i;
FORT11_ENTER()
SLOT_OK (slotID);
for (i=0; i< (int)mechanismCount; i++) {
if (type == mechanisms[i].type) {
PORT_Memcpy (pInfo, &mechanisms[i].domestic, sizeof (CK_MECHANISM_INFO));
FORT11_RETURN (CKR_OK);
}
}
FORT11_RETURN (CKR_MECHANISM_INVALID);
}
/* C_InitToken initializes a token. */
PR_PUBLIC_API(CK_RV) C_InitToken(CK_SLOT_ID slotID,
CK_CHAR_PTR pPin,
CK_ULONG ulPinLen,
CK_CHAR_PTR pLabel) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_InitPIN initializes the normal user's PIN. */
PR_PUBLIC_API(CK_RV) C_InitPIN(CK_SESSION_HANDLE hSession,
CK_CHAR_PTR pPin,
CK_ULONG ulPinLen) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_SetPIN modifies the PIN of user that is currently logged in. */
/* NOTE: This is only valid for the PRIVATE_KEY_SLOT */
PR_PUBLIC_API(CK_RV) C_SetPIN(CK_SESSION_HANDLE hSession,
CK_CHAR_PTR pOldPin,
CK_ULONG ulOldLen,
CK_CHAR_PTR pNewPin,
CK_ULONG ulNewLen) {
FORT11_ENTER()
#ifndef SWFORT
CI_PIN ciOldPin, ciNewPin;
#endif
PK11Session *session;
PK11Slot *slot;
int rv;
session = fort11_SessionFromHandle (hSession, PR_FALSE);
slot = fort11_SlotFromSession (session);
SLOT_OK(slot->slotID)
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
rv = MACI_Select (fortezzaSockets[slot->slotID-1].maciSession, slot->slotID);
CARD_OK (rv)
if (slot->needLogin && session->info.state != CKS_RW_USER_FUNCTIONS) {
fort11_FreeSession (session);
FORT11_RETURN (CKR_USER_NOT_LOGGED_IN);
}
fort11_FreeSession (session);
if (ulNewLen > CI_PIN_SIZE || ulOldLen > CI_PIN_SIZE)
FORT11_RETURN (CKR_PIN_LEN_RANGE);
#ifndef SWFORT
fort11_convertToCIPin (ciOldPin,pOldPin, ulOldLen);
fort11_convertToCIPin (ciNewPin,pNewPin, ulNewLen);
rv = MACI_ChangePIN (fortezzaSockets[slot->slotID-1].maciSession,
CI_USER_PIN, ciOldPin, ciNewPin);
#else
rv = MACI_ChangePIN (fortezzaSockets[slot->slotID-1].maciSession,
CI_USER_PIN, pOldPin, pNewPin);
#endif
if (rv != CI_OK) {
switch (rv) {
case CI_FAIL:
FORT11_RETURN (CKR_PIN_INCORRECT);
default:
FORT11_RETURN (CKR_DEVICE_ERROR);
}
}
FORT11_RETURN (CKR_OK);
}
/* C_OpenSession opens a session between an application and a token. */
PR_PUBLIC_API(CK_RV) C_OpenSession(CK_SLOT_ID slotID,
CK_FLAGS flags,
CK_VOID_PTR pApplication,
CK_NOTIFY Notify,
CK_SESSION_HANDLE_PTR phSession) {
FORT11_ENTER()
PK11Slot *slot;
CK_SESSION_HANDLE sessionID;
PK11Session *session;
FortezzaSocket *socket;
SLOT_OK (slotID)
slot = &fort11_slot[slotID-1];
socket = &fortezzaSockets[slotID-1];
if (!socket->isOpen) {
if (InitSocket(socket, slotID) != SOCKET_SUCCESS) {
FORT11_RETURN (CKR_TOKEN_NOT_PRESENT);
}
}
session = fort11_NewSession (slotID, Notify, pApplication,
flags | CKF_SERIAL_SESSION);
if (session == NULL) FORT11_RETURN (CKR_HOST_MEMORY);
FMUTEX_Lock(slot->sessionLock);
slot->sessionIDCount += ADD_NEXT_SESS_ID;
sessionID = slot->sessionIDCount;
fort11_update_state (slot, session);
pk11queue_add (session, sessionID, slot->head, SESSION_HASH_SIZE);
slot->sessionCount++;
if (session->info.flags & CKF_RW_SESSION) {
slot->rwSessionCount++;
}
session->handle = sessionID;
session->info.ulDeviceError = 0;
FMUTEX_Unlock(slot->sessionLock);
*phSession = sessionID;
FORT11_RETURN (CKR_OK);
}
/* C_CloseSession closes a session between an application and a token. */
PR_PUBLIC_API(CK_RV) C_CloseSession(CK_SESSION_HANDLE hSession) {
FORT11_ENTER()
PK11Slot *slot;
PK11Session *session;
session = fort11_SessionFromHandle (hSession, PR_TRUE);
slot = fort11_SlotFromSessionHandle (hSession);
if (session == NULL) {
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
FMUTEX_Lock(slot->sessionLock);
if (session->next || session->prev) {
session->refCount--;
if (session->info.flags & CKF_RW_SESSION) {
slot->rwSessionCount--;
}
if (slot->sessionCount == 0) {
slot->isLoggedIn = PR_FALSE;
slot->password = NULL;
}
}
FMUTEX_Unlock(slot->sessionLock);
fort11_FreeSession (session);
FORT11_RETURN (CKR_OK);
}
/* C_CloseAllSessions closes all sessions with a token. */
PR_PUBLIC_API(CK_RV) C_CloseAllSessions (CK_SLOT_ID slotID) {
FORT11_ENTER()
PK11Slot *slot;
PK11Session *session;
int i;
slot = fort11_SlotFromID(slotID);
if (slot == NULL) FORT11_RETURN (CKR_SLOT_ID_INVALID);
/* first log out the card */
FMUTEX_Lock(slot->sessionLock);
slot->isLoggedIn = PR_FALSE;
slot->password = NULL;
FMUTEX_Unlock(slot->sessionLock);
/* now close all the current sessions */
/* NOTE: If you try to open new sessions before C_CloseAllSessions
* completes, some of those new sessions may or may not be closed by
* C_CloseAllSessions... but any session running when this code starts
* will guarrenteed be close, and no session will be partially closed */
for (i=0; i < SESSION_HASH_SIZE; i++) {
do {
FMUTEX_Lock(slot->sessionLock);
session = slot->head[i];
/* hand deque */
/* this duplicates much of C_close session functionality, but because
* we know that we are freeing all the sessions, we and do some
* more efficient processing */
if (session) {
slot->head[i] = session->next;
if (session->next) session->next->prev = NULL;
session->next = session->prev = NULL;
slot->sessionCount--;
if (session->info.flags & CKF_RW_SESSION) {
slot->rwSessionCount--;
}
}
FMUTEX_Unlock(slot->sessionLock);
if (session) fort11_FreeSession(session);
} while (session != NULL);
}
FORT11_RETURN (CKR_OK);
}
/* C_GetSessionInfo obtains information about the session. */
PR_PUBLIC_API(CK_RV) C_GetSessionInfo(CK_SESSION_HANDLE hSession,
CK_SESSION_INFO_PTR pInfo) {
FORT11_ENTER()
PK11Session *session;
PK11Slot *slot;
CI_STATE cardState;
FortezzaSocket *socket;
int ciRV;
session = fort11_SessionFromHandle (hSession, PR_FALSE);
slot = fort11_SlotFromSessionHandle(hSession);
socket = &fortezzaSockets[slot->slotID-1];
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
PORT_Memcpy (pInfo, &session->info, sizeof (CK_SESSION_INFO));
fort11_FreeSession(session);
ciRV = MACI_Select(socket->maciSession, slot->slotID);
CARD_OK(ciRV)
ciRV = MACI_GetState(socket->maciSession, &cardState);
CARD_OK(ciRV)
if (socket->isLoggedIn) {
switch (cardState) {
case CI_POWER_UP:
case CI_UNINITIALIZED:
case CI_INITIALIZED:
case CI_SSO_INITIALIZED:
case CI_LAW_INITIALIZED:
case CI_USER_INITIALIZED:
pInfo->state = CKS_RO_PUBLIC_SESSION;
break;
case CI_STANDBY:
case CI_READY:
pInfo->state = CKS_RO_USER_FUNCTIONS;
break;
default:
pInfo->state = CKS_RO_PUBLIC_SESSION;
break;
}
} else {
pInfo->state = CKS_RO_PUBLIC_SESSION;
}
FORT11_RETURN (CKR_OK);
}
/* C_Login logs a user into a token. */
PR_PUBLIC_API(CK_RV) C_Login(CK_SESSION_HANDLE hSession,
CK_USER_TYPE userType,
CK_CHAR_PTR pPin,
CK_ULONG ulPinLen) {
FORT11_ENTER()
PK11Slot *slot;
PK11Session *session;
#ifndef SWFORT
CI_PIN ciPin;
#endif
int rv, ciUserType;
slot = fort11_SlotFromSessionHandle (hSession);
session = fort11_SessionFromHandle(hSession, PR_FALSE);
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
fort11_FreeSession(session);
if (slot->isLoggedIn) FORT11_RETURN (CKR_USER_ALREADY_LOGGED_IN);
slot->ssoLoggedIn = PR_FALSE;
#ifndef SWFORT
if (ulPinLen > CI_PIN_SIZE) FORT11_RETURN (CKR_PIN_LEN_RANGE);
fort11_convertToCIPin (ciPin, pPin, ulPinLen);
#endif
switch (userType) {
case CKU_SO:
ciUserType = CI_SSO_PIN;
break;
case CKU_USER:
ciUserType = CI_USER_PIN;
break;
default:
FORT11_RETURN (CKR_USER_TYPE_INVALID);
}
#ifndef SWFORT
rv = LoginToSocket(&fortezzaSockets[slot->slotID-1], ciUserType, ciPin);
#else
rv = LoginToSocket(&fortezzaSockets[slot->slotID-1], ciUserType, pPin);
#endif
switch (rv) {
case SOCKET_SUCCESS:
break;
case CI_FAIL:
FORT11_RETURN (CKR_PIN_INCORRECT);
default:
FORT11_RETURN (CKR_DEVICE_ERROR);
}
FMUTEX_Lock(slot->sessionLock);
slot->isLoggedIn = PR_TRUE;
if (userType == CKU_SO) {
slot->ssoLoggedIn = PR_TRUE;
}
FMUTEX_Unlock(slot->sessionLock);
fort11_update_all_states(slot);
FORT11_RETURN (CKR_OK);
}
/* C_Logout logs a user out from a token. */
PR_PUBLIC_API(CK_RV) C_Logout(CK_SESSION_HANDLE hSession) {
FORT11_ENTER()
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
if (!slot->isLoggedIn)
FORT11_RETURN (CKR_USER_NOT_LOGGED_IN);
FMUTEX_Lock(slot->sessionLock);
slot->isLoggedIn = PR_FALSE;
slot->ssoLoggedIn = PR_FALSE;
slot->password = NULL;
LogoutFromSocket (&fortezzaSockets[slot->slotID-1]);
FMUTEX_Unlock(slot->sessionLock);
fort11_update_all_states(slot);
FORT11_RETURN (CKR_OK);
}
/* C_CreateObject creates a new object. */
PR_PUBLIC_API(CK_RV) C_CreateObject(CK_SESSION_HANDLE hSession,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phObject) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_CopyObject copies an object, creating a new object for the copy. */
PR_PUBLIC_API(CK_RV) C_CopyObject(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phNewObject) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_DestroyObject destroys an object. */
PR_PUBLIC_API(CK_RV) C_DestroyObject(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject) {
FORT11_ENTER()
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
PK11Session *session;
PK11Object *object;
PK11FreeStatus status;
/*
* This whole block just makes sure we really can destroy the
* requested object.
*/
session = fort11_SessionFromHandle(hSession, PR_FALSE);
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
object = fort11_ObjectFromHandle(hObject,session);
if (object == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_OBJECT_HANDLE_INVALID);
}
/* don't destroy a private object if we aren't logged in */
if ((!slot->isLoggedIn) && (slot->needLogin) &&
(fort11_isTrue(object,CKA_PRIVATE))) {
fort11_FreeSession(session);
fort11_FreeObject(object);
FORT11_RETURN (CKR_USER_NOT_LOGGED_IN);
}
/* don't destroy a token object if we aren't in a rw session */
if (((session->info.flags & CKF_RW_SESSION) == 0) &&
(fort11_isTrue(object,CKA_TOKEN))) {
fort11_FreeSession(session);
fort11_FreeObject(object);
FORT11_RETURN (CKR_SESSION_READ_ONLY);
}
/* ACTUALLY WE NEED TO DEAL WITH TOKEN OBJECTS AS WELL */
FMUTEX_Lock(session->objectLock);
fort11_DeleteObject(session,object);
FMUTEX_Unlock(session->objectLock);
fort11_FreeSession(session);
/*
* get some indication if the object is destroyed. Note: this is not
* 100%. Someone may have an object reference outstanding (though that
* should not be the case by here. Also now that the object is "half"
* destroyed. Our internal representation is destroyed, but it is still
* in the data base.
*/
status = fort11_FreeObject(object);
FORT11_RETURN ((status != PK11_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR);
}
/* C_GetObjectSize gets the size of an object in bytes. */
PR_PUBLIC_API(CK_RV) C_GetObjectSize(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject,
CK_ULONG_PTR pulSize) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
*pulSize = 0;
return CKR_OK;
}
/* C_GetAttributeValue obtains the value of one or more object attributes. */
PR_PUBLIC_API(CK_RV) C_GetAttributeValue(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount) {
FORT11_ENTER()
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
PK11Session *session;
PK11Object *object;
PK11Attribute *attribute;
PRBool sensitive;
int i;
/*
* make sure we're allowed
*/
session = fort11_SessionFromHandle(hSession, PR_FALSE);
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
object = fort11_ObjectFromHandle(hObject,session);
fort11_FreeSession(session);
if (object == NULL) {
FORT11_RETURN (CKR_OBJECT_HANDLE_INVALID);
}
/* don't read a private object if we aren't logged in */
if ((!slot->isLoggedIn) && (slot->needLogin) &&
(fort11_isTrue(object,CKA_PRIVATE))) {
fort11_FreeObject(object);
FORT11_RETURN (CKR_USER_NOT_LOGGED_IN);
}
sensitive = fort11_isTrue(object,CKA_SENSITIVE);
for (i=0; i < (int)ulCount; i++) {
/* Make sure that this attribute is retrievable */
if (sensitive && fort11_isSensitive(pTemplate[i].type,object->objclass)) {
fort11_FreeObject(object);
FORT11_RETURN (CKR_ATTRIBUTE_SENSITIVE);
}
attribute = fort11_FindAttribute(object,pTemplate[i].type);
if (attribute == NULL) {
fort11_FreeObject(object);
FORT11_RETURN (CKR_ATTRIBUTE_TYPE_INVALID);
}
if (pTemplate[i].pValue != NULL) {
PORT_Memcpy(pTemplate[i].pValue,attribute->attrib.pValue,
attribute->attrib.ulValueLen);
}
pTemplate[i].ulValueLen = attribute->attrib.ulValueLen;
fort11_FreeAttribute(attribute);
}
fort11_FreeObject(object);
FORT11_RETURN (CKR_OK);
}
/* C_SetAttributeValue modifies the value of one or more object attributes */
PR_PUBLIC_API(CK_RV) C_SetAttributeValue (CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_FindObjectsInit initializes a search for token and session objects
* that match a template. */
PR_PUBLIC_API(CK_RV) C_FindObjectsInit(CK_SESSION_HANDLE hSession,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount) {
FORT11_ENTER()
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
PK11Session *session;
PK11ObjectListElement *objectList = NULL;
PK11ObjectListElement *olp;
PK11SearchResults *search, *freeSearch;
FortezzaSocket *currSocket;
int rv, count, i;
if (slot == NULL) {
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
if ((!slot->isLoggedIn) && (slot->needLogin))
FORT11_RETURN (CKR_USER_NOT_LOGGED_IN);
session = fort11_SessionFromHandle(hSession, PR_FALSE);
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
currSocket = &fortezzaSockets[slot->slotID-1];
if (currSocket->personalityList == NULL) {
rv = FetchPersonalityList(currSocket);
if (rv != SOCKET_SUCCESS) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
rv = fort11_BuildCertObjects(currSocket, slot, session);
if (rv != CKR_OK) {
fort11_FreeSession(session);
FORT11_RETURN (rv);
}
}
rv = fort11_searchObjectList(&objectList, slot->tokObjects,
slot->objectLock, pTemplate, ulCount);
if (rv != CKR_OK) {
fort11_FreeObjectList(objectList);
fort11_FreeSession(session);
FORT11_RETURN (rv);
}
/*copy list to session*/
count = 0;
for(olp = objectList; olp != NULL; olp = olp->next) {
count++;
}
search = (PK11SearchResults *)PORT_Alloc(sizeof(PK11SearchResults));
if (search != NULL) {
search->handles = (CK_OBJECT_HANDLE *)
PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * count);
if (search->handles != NULL) {
for (i=0; i < count; i++) {
search->handles[i] = objectList->object->handle;
objectList = fort11_FreeObjectListElement(objectList);
}
} else {
PORT_Free(search);
search = NULL;
}
}
if (search == NULL) {
fort11_FreeObjectList(objectList);
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
/* store the search info */
search->index = 0;
search->size = count;
if ((freeSearch = session->search) != NULL) {
session->search = NULL;
fort11_FreeSearch(freeSearch);
}
session->search = search;
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
/* C_FindObjects continues a search for token and session objects
* that match a template, obtaining additional object handles. */
PR_PUBLIC_API(CK_RV) C_FindObjects(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE_PTR phObject,
CK_ULONG ulMaxObjectCount,
CK_ULONG_PTR pulObjectCount) {
FORT11_ENTER()
PK11Session *session;
PK11SearchResults *search;
PK11Slot *slot;
int transfer;
unsigned long left;
*pulObjectCount = 0;
session = fort11_SessionFromHandle(hSession,PR_FALSE);
slot = fort11_SlotFromSessionHandle(hSession);
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
if (session->search == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
search = session->search;
left = session->search->size - session->search->index;
transfer = (ulMaxObjectCount > left) ? left : ulMaxObjectCount;
PORT_Memcpy(phObject,&search->handles[search->index],
transfer*sizeof(CK_OBJECT_HANDLE_PTR));
search->index += transfer;
if (search->index == search->size) {
session->search = NULL;
fort11_FreeSearch(search);
}
fort11_FreeSession(session);
*pulObjectCount = transfer;
FORT11_RETURN (CKR_OK);
}
/* C_FindObjectsFinal finishes a search for token and session objects. */
PR_PUBLIC_API(CK_RV) C_FindObjectsFinal(CK_SESSION_HANDLE hSession) {
FORT11_ENTER()
PK11Session *session;
PK11SearchResults *search;
PK11Slot *slot;
session = fort11_SessionFromHandle(hSession, PR_FALSE);
slot = fort11_SlotFromSessionHandle(hSession);
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
search = session->search;
session->search = NULL;
if (search == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
fort11_FreeSearch(search);
/* UnloadPersonalityList(&fortezzaSockets[session->slot->slotID-1]); */
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
/* C_EncryptInit initializes an encryption operation. */
PR_PUBLIC_API(CK_RV) C_EncryptInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
PK11Object *keyObject;
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
FortezzaContext *context;
HSESSION hs = socket->maciSession;
FortezzaKey *fortezzaKey;
CI_IV fortezzaIV;
int ciRV, registerIndex;
if (pMechanism->mechanism != CKM_SKIPJACK_CBC64) {
if (session) {
fort11_FreeSession(session);
}
FORT11_RETURN (CKR_MECHANISM_INVALID);
}
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
keyObject = fort11_ObjectFromHandle (hKey, session);
if (keyObject == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_KEY_HANDLE_INVALID);
}
ciRV = MACI_Select (hs, slot->slotID);
if (ciRV != CI_OK) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
ciRV = MACI_SetMode(hs, CI_ENCRYPT_TYPE, CI_CBC64_MODE);
if (ciRV != CI_OK) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
/*Load the correct key into a key register*/
fortezzaKey = (FortezzaKey*)keyObject->objectInfo;
fort11_FreeObject (keyObject);
if (fortezzaKey == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_GENERAL_ERROR);
}
if (fortezzaKey->keyRegister == KeyNotLoaded) {
registerIndex = LoadKeyIntoRegister (fortezzaKey);
} else {
registerIndex = fortezzaKey->keyRegister;
}
if (registerIndex == KeyNotLoaded) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
ciRV = MACI_SetKey (hs,registerIndex);
if (ciRV != CI_OK) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
ciRV = MACI_GenerateIV(hs, fortezzaIV);
if (ciRV != CI_OK) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
context = &session->fortezzaContext;
InitContext(context, socket, hKey);
ciRV = SaveState(context, fortezzaIV, session, fortezzaKey,
CI_ENCRYPT_EXT_TYPE, pMechanism->mechanism);
if (ciRV != SOCKET_SUCCESS) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_GENERAL_ERROR);
}
if (pMechanism->pParameter != NULL &&
pMechanism->ulParameterLen >= sizeof(CI_IV)) {
PORT_Memcpy (pMechanism->pParameter, fortezzaIV, sizeof(CI_IV));
}
InitCryptoOperation(context, Encrypt);
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
/* C_Encrypt encrypts single-part data. */
PR_PUBLIC_API(CK_RV) C_Encrypt (CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pEncryptedData,
CK_ULONG_PTR pulEncryptedDataLen) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle (hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
FortezzaContext *context;
HSESSION hs;
CK_RV rv;
if (session == NULL) {
session = fort11_SessionFromHandle (hSession , PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
context = &session->fortezzaContext;
if (GetCryptoOperation(context) != Encrypt) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_OPERATION_NOT_INITIALIZED);
}
*pulEncryptedDataLen = ulDataLen;
if (pEncryptedData == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
hs = socket->maciSession;
FMUTEX_Lock(socket->registersLock);
MACI_Lock(hs, CI_BLOCK_LOCK_FLAG);
rv = EncryptData (context, pData, ulDataLen,
pEncryptedData, *pulEncryptedDataLen);
MACI_Unlock(hs);
FMUTEX_Unlock(socket->registersLock);
if (rv != SOCKET_SUCCESS) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_GENERAL_ERROR);
}
EndCryptoOperation(context, Encrypt);
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
/* C_EncryptUpdate continues a multiple-part encryption operation. */
PR_PUBLIC_API(CK_RV) C_EncryptUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen,
CK_BYTE_PTR pEncryptedPart,
CK_ULONG_PTR pulEncryptedPartLen) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession,PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
FortezzaContext *context;
int rv;
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved (slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
context = &session->fortezzaContext;
if (GetCryptoOperation(context) != Encrypt) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_OPERATION_NOT_INITIALIZED);
}
if (pEncryptedPart == NULL) {
*pulEncryptedPartLen = ulPartLen;
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
if (*pulEncryptedPartLen < ulPartLen) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_BUFFER_TOO_SMALL);
}
*pulEncryptedPartLen = ulPartLen;
FMUTEX_Lock(socket->registersLock);
MACI_Lock(socket->maciSession, CI_BLOCK_LOCK_FLAG);
rv = EncryptData(context,pPart, ulPartLen, pEncryptedPart,
*pulEncryptedPartLen);
MACI_Unlock(socket->maciSession);
FMUTEX_Unlock(socket->registersLock);
fort11_FreeSession(session);
if (rv != SOCKET_SUCCESS) {
FORT11_RETURN (CKR_GENERAL_ERROR);
}
FORT11_RETURN (CKR_OK);
}
/* C_EncryptFinal finishes a multiple-part encryption operation. */
PR_PUBLIC_API(CK_RV) C_EncryptFinal(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pLastEncryptedPart,
CK_ULONG_PTR pulLastEncryptedPartLen){
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaContext *context;
int rv;
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
context = &session->fortezzaContext;
rv = EndCryptoOperation(context, Encrypt);
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
/* C_DecryptInit initializes a decryption operation. */
PR_PUBLIC_API(CK_RV) C_DecryptInit( CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
PK11Object *keyObject;
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
FortezzaContext *context;
HSESSION hs = socket->maciSession;
FortezzaKey *fortezzaKey;
CI_IV fortezzaIV;
int ciRV, registerIndex;
if (pMechanism->mechanism != CKM_SKIPJACK_CBC64) {
if (session) fort11_FreeSession(session);
FORT11_RETURN (CKR_MECHANISM_INVALID);
}
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
keyObject = fort11_ObjectFromHandle (hKey, session);
if (keyObject == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_KEY_HANDLE_INVALID);
}
fortezzaKey = (FortezzaKey*)keyObject->objectInfo;
fort11_FreeObject(keyObject);
if (fortezzaKey == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_GENERAL_ERROR);
}
ciRV = MACI_Select (hs, slot->slotID);
if (ciRV != CI_OK) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
ciRV = MACI_SetMode(hs, CI_DECRYPT_TYPE, CI_CBC64_MODE);
if (ciRV != CI_OK) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
FMUTEX_Lock(socket->registersLock);
if (fortezzaKey->keyRegister == KeyNotLoaded) {
registerIndex = LoadKeyIntoRegister(fortezzaKey);
} else {
registerIndex = fortezzaKey->keyRegister;
}
if (registerIndex == KeyNotLoaded) {
FMUTEX_Unlock(socket->registersLock);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
if (pMechanism->pParameter == NULL ||
pMechanism->ulParameterLen < sizeof (CI_IV)) {
FORT11_RETURN (CKR_MECHANISM_PARAM_INVALID);
}
PORT_Memcpy (fortezzaIV, pMechanism->pParameter, sizeof(CI_IV));
ciRV = MACI_SetKey (hs, registerIndex);
if (ciRV != CI_OK) {
FMUTEX_Unlock(socket->registersLock);
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
ciRV = MACI_LoadIV (hs, fortezzaIV);
if (ciRV != CI_OK) {
FMUTEX_Unlock(socket->registersLock);
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
context = &session->fortezzaContext;
InitContext(context, socket, hKey);
ciRV = SaveState (context, fortezzaIV, session, fortezzaKey,
CI_DECRYPT_EXT_TYPE, pMechanism->mechanism);
FMUTEX_Unlock(socket->registersLock);
if (ciRV != SOCKET_SUCCESS) {
FORT11_RETURN (CKR_GENERAL_ERROR);
}
InitCryptoOperation (context, Decrypt);
fort11_FreeSession (session);
FORT11_RETURN (CKR_OK);
}
/* C_Decrypt decrypts encrypted data in a single part. */
PR_PUBLIC_API(CK_RV) C_Decrypt(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedData,
CK_ULONG ulEncryptedDataLen,
CK_BYTE_PTR pData,
CK_ULONG_PTR pulDataLen) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle (hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
FortezzaContext *context;
HSESSION hs;
CK_RV rv;
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
context = &session->fortezzaContext;
if (GetCryptoOperation(context) != Decrypt) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_OPERATION_NOT_INITIALIZED);
}
*pulDataLen = ulEncryptedDataLen;
if (pData == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
hs = socket->maciSession;
FMUTEX_Lock(socket->registersLock);
MACI_Lock(hs, CI_NULL_FLAG);
rv = DecryptData (context, pEncryptedData, ulEncryptedDataLen,
pData, *pulDataLen);
MACI_Unlock(hs);
FMUTEX_Unlock(socket->registersLock);
if (rv != SOCKET_SUCCESS) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_GENERAL_ERROR);
}
EndCryptoOperation (context, Decrypt);
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
/* C_DecryptUpdate continues a multiple-part decryption operation. */
PR_PUBLIC_API(CK_RV) C_DecryptUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedPart,
CK_ULONG ulEncryptedPartLen,
CK_BYTE_PTR pPart,
CK_ULONG_PTR pulPartLen) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession,PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
FortezzaContext *context;
HSESSION hs;
int rv;
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved (slot, session);
fort11_FreeSession (session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
context = &session->fortezzaContext;
hs = socket->maciSession;
if (GetCryptoOperation(context) != Decrypt) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_OPERATION_NOT_INITIALIZED);
}
if (pPart == NULL) {
*pulPartLen = ulEncryptedPartLen;
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
*pulPartLen = ulEncryptedPartLen;
FMUTEX_Lock(socket->registersLock);
MACI_Lock (hs, CI_NULL_FLAG);
rv = DecryptData (context, pEncryptedPart, ulEncryptedPartLen, pPart,
*pulPartLen);
MACI_Unlock(hs);
FMUTEX_Unlock(socket->registersLock);
fort11_FreeSession(session);
if (rv != SOCKET_SUCCESS) {
FORT11_RETURN (CKR_GENERAL_ERROR);
}
FORT11_RETURN (CKR_OK);
}
/* C_DecryptFinal finishes a multiple-part decryption operation. */
PR_PUBLIC_API(CK_RV) C_DecryptFinal(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pLastPart,
CK_ULONG_PTR pulLastPartLen) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaContext *context;
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved (slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
context = &session->fortezzaContext;
EndCryptoOperation (context, Decrypt);
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
/*
************** Crypto Functions: Digest (HASH) ************************
*/
/* C_DigestInit initializes a message-digesting operation. */
PR_PUBLIC_API(CK_RV) C_DigestInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_Digest digests data in a single part. */
PR_PUBLIC_API(CK_RV) C_Digest(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pDigest,
CK_ULONG_PTR pulDigestLen) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_DigestUpdate continues a multiple-part message-digesting operation. */
PR_PUBLIC_API(CK_RV) C_DigestUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_DigestFinal finishes a multiple-part message-digesting operation. */
PR_PUBLIC_API(CK_RV) C_DigestFinal(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pDigest,
CK_ULONG_PTR pulDigestLen) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/*
************** Crypto Functions: Sign ************************
*/
/* C_SignInit initializes a signature (private key encryption) operation,
* where the signature is (will be) an appendix to the data,
* and plaintext cannot be recovered from the signature */
PR_PUBLIC_API(CK_RV) C_SignInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle (hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
PK11Object *keyObject;
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
FortezzaContext *context;
PK11Attribute *idAttribute;
int personalityIndex;
HSESSION hs = socket->maciSession;
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
if (pMechanism->mechanism != CKM_DSA) {
FORT11_RETURN (CKR_MECHANISM_INVALID);
}
keyObject = fort11_ObjectFromHandle (hKey, session);
if (keyObject == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_KEY_HANDLE_INVALID);
}
context = &session->fortezzaContext;
InitContext(context, socket, hKey);
InitCryptoOperation (context, Sign);
fort11_FreeSession(session);
idAttribute = fort11_FindAttribute(keyObject, CKA_ID);
fort11_FreeObject(keyObject);
if (idAttribute == NULL) {
FORT11_RETURN (CKR_KEY_HANDLE_INVALID);
}
personalityIndex = *(int*)(idAttribute->attrib.pValue);
fort11_FreeAttribute(idAttribute);
MACI_Select (hs, slot->slotID);
if (MACI_SetPersonality (hs,personalityIndex) != CI_OK) {
FORT11_RETURN (CKR_GENERAL_ERROR);
}
FORT11_RETURN (CKR_OK);
}
/* C_Sign signs (encrypts with private key) data in a single part,
* where the signature is (will be) an appendix to the data,
* and plaintext cannot be recovered from the signature */
PR_PUBLIC_API(CK_RV) C_Sign(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaContext *context;
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
HSESSION hs = socket->maciSession;
PK11Object *keyObject;
PK11Attribute *idAttribute;
int ciRV, personalityIndex;
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved (slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
context = &session->fortezzaContext;
if (GetCryptoOperation(context) != Sign) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_OPERATION_NOT_INITIALIZED);
}
if (pSignature == NULL) {
*pulSignatureLen = 40;
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
if (ulDataLen > 20) {
FORT11_RETURN (CKR_DATA_LEN_RANGE);
}
if (*pulSignatureLen < 40) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_BUFFER_TOO_SMALL);
}
*pulSignatureLen = 40;
keyObject = fort11_ObjectFromHandle(context->hKey, session);
if (keyObject == NULL) {
fort11_FreeSession(session);
FORT11_RETURN(CKR_GENERAL_ERROR);
}
idAttribute = fort11_FindAttribute(keyObject, CKA_ID);
fort11_FreeObject(keyObject);
personalityIndex = *(int*)(idAttribute->attrib.pValue);
fort11_FreeAttribute(idAttribute);
MACI_Select(hs, slot->slotID);
MACI_Lock(hs, CI_BLOCK_LOCK_FLAG);
ciRV = MACI_SetPersonality(hs, personalityIndex);
if (ciRV != CI_OK) {
MACI_Unlock(hs);
fort11_FreeSession(session);
FORT11_RETURN(CKR_DEVICE_ERROR);
}
ciRV = MACI_Sign (hs, pData, pSignature);
if (ciRV != CI_OK) {
MACI_Unlock(hs);
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
MACI_Unlock(hs);
EndCryptoOperation (context, Sign);
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
/* C_SignUpdate continues a multiple-part signature operation,
* where the signature is (will be) an appendix to the data,
* and plaintext cannot be recovered from the signature */
PR_PUBLIC_API(CK_RV) C_SignUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_SignFinal finishes a multiple-part signature operation,
* FORT11_RETURNing the signature. */
PR_PUBLIC_API(CK_RV) C_SignFinal(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/*
************** Crypto Functions: Sign Recover ************************
*/
/* C_SignRecoverInit initializes a signature operation,
* where the (digest) data can be recovered from the signature.
* E.g. encryption with the user's private key */
PR_PUBLIC_API(CK_RV) C_SignRecoverInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_SignRecover signs data in a single operation
* where the (digest) data can be recovered from the signature.
* E.g. encryption with the user's private key */
PR_PUBLIC_API(CK_RV) C_SignRecover(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/*
************** Crypto Functions: verify ************************
*/
/* C_VerifyInit initializes a verification operation,
* where the signature is an appendix to the data,
* and plaintext cannot be recovered from the signature (e.g. DSA) */
PR_PUBLIC_API(CK_RV) C_VerifyInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_Verify verifies a signature in a single-part operation,
* where the signature is an appendix to the data,
* and plaintext cannot be recovered from the signature */
PR_PUBLIC_API(CK_RV) C_Verify(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_VerifyUpdate continues a multiple-part verification operation,
* where the signature is an appendix to the data,
* and plaintext cannot be recovered from the signature */
PR_PUBLIC_API(CK_RV) C_VerifyUpdate( CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen) {
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_VerifyFinal finishes a multiple-part verification operation,
* checking the signature. */
PR_PUBLIC_API(CK_RV) C_VerifyFinal(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/*
************** Crypto Functions: Verify Recover ************************
*/
/* C_VerifyRecoverInit initializes a signature verification operation,
* where the data is recovered from the signature.
* E.g. Decryption with the user's public key */
PR_PUBLIC_API(CK_RV) C_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey) {
/* For functions that don't access globals, we don't have to worry about the
* stack.
*/
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_VerifyRecover verifies a signature in a single-part operation,
* where the data is recovered from the signature.
* E.g. Decryption with the user's public key */
PR_PUBLIC_API(CK_RV) C_VerifyRecover(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen,
CK_BYTE_PTR pData,
CK_ULONG_PTR pulDataLen) {
return CKR_FUNCTION_NOT_SUPPORTED;
}
/*
**************************** Key Functions: ************************
*/
#define MAX_KEY_LEN 256
/* C_GenerateKey generates a secret key, creating a new key object. */
PR_PUBLIC_API(CK_RV) C_GenerateKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phKey) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
PK11Object *key;
FortezzaKey *newKey;
int i, keyRegister;
CK_ULONG key_length = 0;
CK_RV crv = CKR_OK;
CK_OBJECT_CLASS secretKey = CKO_SECRET_KEY;
CK_BBOOL False = FALSE;
CK_BBOOL cktrue = TRUE;
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved (slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
if (pMechanism->mechanism != CKM_SKIPJACK_KEY_GEN) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_MECHANISM_INVALID);
}
key = fort11_NewObject(slot);
if (key == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_HOST_MEMORY);
}
for (i=0; i < (int) ulCount; i++) {
if (pTemplate[i].type == CKA_VALUE_LEN) {
key_length = *(CK_ULONG *)pTemplate[i].pValue;
continue;
}
crv = fort11_AddAttributeType (key, pk11_attr_expand (&pTemplate[i]));
if (crv != CKR_OK)
break;
}
if (crv != CKR_OK) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (crv);
}
/* make sure we don't have any class, key_type, or value fields */
fort11_DeleteAttributeType(key,CKA_CLASS);
fort11_DeleteAttributeType(key,CKA_KEY_TYPE);
fort11_DeleteAttributeType(key,CKA_VALUE);
if (MAX_KEY_LEN < key_length) {
crv = CKR_TEMPLATE_INCONSISTENT;
}
if (crv != CKR_OK) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (crv);
}
if (fort11_AddAttributeType(key, CKA_CLASS,&secretKey,
sizeof(CK_OBJECT_CLASS)) != CKR_OK) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (CKR_GENERAL_ERROR);
}
if (fort11_AddAttributeType(key, CKA_TOKEN, &False,
sizeof(CK_BBOOL)) != CKR_OK) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (CKR_GENERAL_ERROR);
}
if (fort11_isTrue(key,CKA_SENSITIVE)) {
fort11_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,
sizeof(CK_BBOOL));
}
if (!fort11_isTrue(key,CKA_EXTRACTABLE)) {
fort11_forceAttribute(key,CKA_NEVER_EXTRACTABLE,&cktrue,
sizeof(CK_BBOOL));
}
FMUTEX_Lock(socket->registersLock);
keyRegister = GetBestKeyRegister(socket);
newKey = NewFortezzaKey(socket, MEK, NULL, keyRegister);
FMUTEX_Unlock(socket->registersLock);
if (newKey == NULL) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (CKR_HOST_MEMORY);
}
key->objectInfo = (void*)newKey;
key->infoFree = fort11_FreeFortezzaKey;
FMUTEX_Lock(slot->objectLock);
key->handle = slot->tokenIDCount++;
key->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
FMUTEX_Unlock(slot->objectLock);
key->objclass = secretKey;
key->slot = slot;
key->inDB = PR_TRUE;
fort11_AddObject(session, key);
fort11_FreeSession(session);
SetFortezzaKeyHandle(newKey, key->handle);
*phKey = key->handle;
FORT11_RETURN (CKR_OK);
}
/* C_GenerateKeyPair generates a public-key/private-key pair,
* creating new key objects. */
PR_PUBLIC_API(CK_RV) C_GenerateKeyPair
(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_ATTRIBUTE_PTR pPublicKeyTemplate,
CK_ULONG ulPublicKeyAttributeCount,
CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
CK_ULONG ulPrivateKeyAttributeCount,
CK_OBJECT_HANDLE_PTR phPrivateKey,
CK_OBJECT_HANDLE_PTR phPublicKey) {
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_WrapKey wraps (i.e., encrypts) a key. */
PR_PUBLIC_API(CK_RV) C_WrapKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hWrappingKey,
CK_OBJECT_HANDLE hKey,
CK_BYTE_PTR pWrappedKey,
CK_ULONG_PTR pulWrappedKeyLen) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle (hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
PK11Object *wrapKey;
PK11Object *srcKey;
FortezzaKey *wrapFortKey;
FortezzaKey *srcFortKey;
int rv;
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
if (!socket->isLoggedIn) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_USER_NOT_LOGGED_IN);
}
if (pMechanism->mechanism != CKM_SKIPJACK_WRAP) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_MECHANISM_INVALID);
}
wrapKey = fort11_ObjectFromHandle (hWrappingKey, session);
if ((wrapKey == NULL) || (wrapKey->objectInfo == NULL)) {
if (wrapKey)
fort11_FreeObject(wrapKey);
fort11_FreeSession(session);
FORT11_RETURN (CKR_KEY_HANDLE_INVALID);
}
srcKey = fort11_ObjectFromHandle (hKey, session);
fort11_FreeSession(session);
if ((srcKey == NULL) || (srcKey->objectInfo == NULL)) {
FORT11_RETURN (CKR_KEY_HANDLE_INVALID);
}
wrapFortKey = (FortezzaKey*)wrapKey->objectInfo;
fort11_FreeObject(wrapKey);
srcFortKey = (FortezzaKey*)srcKey->objectInfo;
fort11_FreeObject(srcKey);
FMUTEX_Lock(socket->registersLock);
if (wrapFortKey->keyRegister == KeyNotLoaded) {
if (LoadKeyIntoRegister(wrapFortKey) == KeyNotLoaded) {
FORT11_RETURN (CKR_DEVICE_ERROR);
}
}
if (srcFortKey->keyRegister == KeyNotLoaded) {
if (LoadKeyIntoRegister(srcFortKey) == KeyNotLoaded) {
FMUTEX_Unlock(socket->registersLock);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
}
MACI_Lock(socket->maciSession, CI_BLOCK_LOCK_FLAG);
rv = WrapKey (wrapFortKey, srcFortKey, pWrappedKey, *pulWrappedKeyLen);
MACI_Unlock(socket->maciSession);
FMUTEX_Unlock(socket->registersLock);
if (rv != SOCKET_SUCCESS) {
FORT11_RETURN (CKR_GENERAL_ERROR);
}
FORT11_RETURN (CKR_OK);
}
/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
PR_PUBLIC_API(CK_RV) C_UnwrapKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hUnwrappingKey,
CK_BYTE_PTR pWrappedKey,
CK_ULONG ulWrappedKeyLen,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulAttributeCount,
CK_OBJECT_HANDLE_PTR phKey) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
PK11Object *wrapKey;
PK11Object *newKey;
FortezzaKey *fortKey;
FortezzaKey *unwrapFort;
CK_ULONG key_length;
int i, newKeyRegister;
CK_RV crv = CKR_OK;
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
if (pMechanism->mechanism != CKM_SKIPJACK_WRAP){
fort11_FreeSession(session);
FORT11_RETURN (CKR_MECHANISM_INVALID);
}
if (!socket->isLoggedIn) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_USER_NOT_LOGGED_IN);
}
wrapKey = fort11_ObjectFromHandle(hUnwrappingKey, session);
if (wrapKey == NULL || wrapKey->objectInfo == NULL) {
if (wrapKey)
fort11_FreeObject(wrapKey);
fort11_FreeSession(session);
FORT11_RETURN (CKR_UNWRAPPING_KEY_HANDLE_INVALID);
}
fortKey = (FortezzaKey*)wrapKey->objectInfo;
fort11_FreeObject(wrapKey);
newKey = fort11_NewObject(slot);
if (newKey == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_HOST_MEMORY);
}
for (i=0; i< (int)ulAttributeCount; i++) {
if (pTemplate[i].type == CKA_VALUE_LEN) {
key_length = *(CK_ULONG*)pTemplate[i].pValue;
continue;
}
crv=fort11_AddAttributeType(newKey,fort11_attr_expand(&pTemplate[i]));
if (crv != CKR_OK) {
break;
}
}
if (crv != CKR_OK) {
fort11_FreeSession(session);
fort11_FreeObject(newKey);
FORT11_RETURN (crv);
}
/* make sure we don't have any class, key_type, or value fields */
if (!fort11_hasAttribute(newKey,CKA_CLASS)) {
fort11_FreeObject(newKey);
fort11_FreeSession(session);
FORT11_RETURN (CKR_TEMPLATE_INCOMPLETE);
}
if (!fort11_hasAttribute(newKey,CKA_KEY_TYPE)) {
fort11_FreeObject(newKey);
fort11_FreeSession(session);
FORT11_RETURN (CKR_TEMPLATE_INCOMPLETE);
}
FMUTEX_Lock(socket->registersLock);
newKeyRegister = UnwrapKey (pWrappedKey, fortKey);
if (newKeyRegister == KeyNotLoaded) {
/*Couldn't Unwrap the key*/
fort11_FreeObject(newKey);
fort11_FreeSession(session);
FMUTEX_Unlock(socket->registersLock);
FORT11_RETURN (CKR_GENERAL_ERROR);
}
unwrapFort = NewUnwrappedKey(newKeyRegister, fortKey->id, socket);
FMUTEX_Unlock(socket->registersLock);
if (unwrapFort == NULL) {
fort11_FreeObject(newKey);
fort11_FreeSession(session);
FORT11_RETURN (CKR_HOST_MEMORY);
}
newKey->objectInfo = unwrapFort;
newKey->infoFree = fort11_FreeFortezzaKey;
FMUTEX_Lock(slot->objectLock);
newKey->handle = slot->tokenIDCount++;
newKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
FMUTEX_Unlock(slot->objectLock);
newKey->objclass = CKO_SECRET_KEY;
newKey->slot = slot;
newKey->inDB = PR_TRUE;
fort11_AddObject (session, newKey);
fort11_FreeSession(session);
SetFortezzaKeyHandle(unwrapFort, newKey->handle);
*phKey = newKey->handle;
FORT11_RETURN (CKR_OK);
}
/* C_DeriveKey derives a key from a base key, creating a new key object. */
PR_PUBLIC_API(CK_RV) C_DeriveKey( CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hBaseKey,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulAttributeCount,
CK_OBJECT_HANDLE_PTR phKey) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
PK11Object *key, *sourceKey;
CK_ULONG i;
CK_ULONG key_length = 0;
CK_RV crv = 0;
CK_KEY_TYPE keyType = CKK_SKIPJACK;
CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
CK_BBOOL ckTrue = TRUE;
CK_BBOOL ckFalse = FALSE;
int ciRV;
int personality;
PK11Attribute *att;
CK_KEA_DERIVE_PARAMS_PTR params;
FortezzaKey *derivedKey;
CreateTEKInfo tekInfo;
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved (slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
if (pMechanism->mechanism != CKM_KEA_KEY_DERIVE) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_MECHANISM_INVALID);
}
key = fort11_NewObject (slot);
if (key == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_HOST_MEMORY);
}
for (i = 0; i < ulAttributeCount; i++) {
crv = fort11_AddAttributeType (key, fort11_attr_expand(&pTemplate[i]));
if (crv != CKR_OK) {
break;
}
if (pTemplate[i].type == CKA_KEY_TYPE) {
keyType = *(CK_KEY_TYPE*)pTemplate[i].pValue;
} else if (pTemplate[i].type == CKA_VALUE_LEN) {
key_length = *(CK_ULONG*)pTemplate[i].pValue;
}
}
if (crv != CKR_OK) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (crv);
}
if (key_length == 0) {
key_length = 12;
}
classType = CKO_SECRET_KEY;
crv = fort11_forceAttribute (key, CKA_CLASS, &classType,
sizeof(classType));
if (crv != CKR_OK) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (crv);
}
crv = fort11_forceAttribute (key, CKA_SENSITIVE, &ckTrue,
sizeof(CK_BBOOL));
if (crv != CKR_OK) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (crv);
}
crv = fort11_forceAttribute (key, CKA_EXTRACTABLE, &ckFalse,
sizeof(CK_BBOOL));
if (crv != CKR_OK) {
fort11_FreeSession(session);
fort11_FreeObject(key);
FORT11_RETURN (crv);
}
sourceKey = fort11_ObjectFromHandle (hBaseKey, session);
if (sourceKey == NULL) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (CKR_KEY_HANDLE_INVALID);
}
att = fort11_FindAttribute(sourceKey,CKA_ID);
fort11_FreeObject(sourceKey);
if (att == NULL) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (CKR_KEY_TYPE_INCONSISTENT);
}
personality = *(int *) att->attrib.pValue;
fort11_FreeAttribute(att);
params = (CK_KEA_DERIVE_PARAMS_PTR)pMechanism->pParameter;
if (params == NULL) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (CKR_MECHANISM_PARAM_INVALID);
}
ciRV = MACI_SetPersonality(socket->maciSession,personality);
if (ciRV != CI_OK) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
/*
* If we're sending, generate our own RA.
*/
if (params->isSender) {
ciRV = MACI_GenerateRa(socket->maciSession,params->pRandomA);
if (ciRV != CI_OK) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
}
PORT_Memcpy (tekInfo.Ra, params->pRandomA, params->ulRandomLen);
PORT_Memcpy (tekInfo.Rb, params->pRandomB, params->ulRandomLen);
tekInfo.randomLen = params->ulRandomLen;
tekInfo.personality = personality;
tekInfo.flag = (params->isSender) ? CI_INITIATOR_FLAG : CI_RECIPIENT_FLAG;
PORT_Memcpy (tekInfo.pY, params->pPublicData, params->ulPublicDataLen);
tekInfo.YSize = params->ulPublicDataLen;
FMUTEX_Lock(socket->registersLock);
derivedKey = NewFortezzaKey(socket, TEK, &tekInfo,
GetBestKeyRegister(socket));
FMUTEX_Unlock(socket->registersLock);
if (derivedKey == NULL) {
fort11_FreeObject(key);
fort11_FreeSession(session);
FORT11_RETURN (CKR_GENERAL_ERROR);
}
key->objectInfo = derivedKey;
key->infoFree = fort11_FreeFortezzaKey;
FMUTEX_Lock(slot->objectLock);
key->handle = slot->tokenIDCount++;
key->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
FMUTEX_Unlock(slot->objectLock);
key->objclass = classType;
key->slot = slot;
key->inDB = PR_TRUE;
fort11_AddObject (session, key);
fort11_FreeSession(session);
SetFortezzaKeyHandle(derivedKey, key->handle);
*phKey = key->handle;
FORT11_RETURN (CKR_OK);
}
/*
**************************** Random Functions: ************************
*/
/* C_SeedRandom mixes additional seed material into the token's random number
* generator. */
PR_PUBLIC_API(CK_RV) C_SeedRandom(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pSeed,
CK_ULONG ulSeedLen) {
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_GenerateRandom generates random data. */
PR_PUBLIC_API(CK_RV) C_GenerateRandom(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pRandomData,
CK_ULONG ulRandomLen) {
FORT11_ENTER()
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
PK11Session *session = fort11_SessionFromHandle(hSession,PR_FALSE);
CI_RANDOM randomNum;
CK_ULONG randomSize = sizeof (CI_RANDOM);
int ciRV;
CK_ULONG bytesCopied = 0, bytesToCopy;
CK_ULONG bufferSize = 0, bytesRemaining;
if (session == NULL) {
session = fort11_SessionFromHandle (hSession, PR_TRUE);
fort11_TokenRemoved(slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
fort11_FreeSession(session);
ciRV = MACI_Select(fortezzaSockets[slot->slotID-1].maciSession,
slot->slotID);
if (ciRV != CI_OK) {
FORT11_RETURN (CKR_DEVICE_ERROR);
}
while (bytesCopied < ulRandomLen) {
bytesRemaining = ulRandomLen - bytesCopied;
if (bufferSize < bytesRemaining) {
ciRV =
MACI_GenerateRandom(fortezzaSockets[slot->slotID-1].maciSession,
randomNum);
if (ciRV != CI_OK)
FORT11_RETURN (CKR_DEVICE_ERROR);
bufferSize = randomSize;
}
bytesToCopy = (bytesRemaining > randomSize) ? randomSize :
bytesRemaining;
PORT_Memcpy (&pRandomData[bytesCopied],
&randomNum[randomSize-bufferSize], bytesToCopy);
bytesCopied += bytesToCopy;
bufferSize -= bytesToCopy;
}
FORT11_RETURN (CKR_OK);
}
/* C_GetFunctionStatus obtains an updated status of a function running
* in parallel with an application. */
PR_PUBLIC_API(CK_RV) C_GetFunctionStatus(CK_SESSION_HANDLE hSession) {
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_CancelFunction cancels a function running in parallel */
PR_PUBLIC_API(CK_RV) C_CancelFunction(CK_SESSION_HANDLE hSession) {
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_GetOperationState saves the state of the cryptographic
*operation in a session. */
PR_PUBLIC_API(CK_RV) C_GetOperationState(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pOperationState,
CK_ULONG_PTR pulOperationStateLen) {
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaContext *context;
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved (slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
if (pOperationState == NULL) {
*pulOperationStateLen = sizeof (FortezzaContext);
fort11_FreeSession(session);
FORT11_RETURN (CKR_OK);
}
if (*pulOperationStateLen < sizeof (FortezzaContext)) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_BUFFER_TOO_SMALL);
}
context = &session->fortezzaContext;
fort11_FreeSession(session);
PORT_Memcpy (pOperationState, context, sizeof(FortezzaContext));
((FortezzaContext *)pOperationState)->session = NULL;
((FortezzaContext *)pOperationState)->fortezzaKey = NULL;
*pulOperationStateLen = sizeof(FortezzaContext);
FORT11_RETURN (CKR_OK);
}
/* C_SetOperationState restores the state of the cryptographic operation in a session. */
PR_PUBLIC_API(CK_RV) C_SetOperationState(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pOperationState,
CK_ULONG ulOperationStateLen,
CK_OBJECT_HANDLE hEncryptionKey,
CK_OBJECT_HANDLE hAuthenticationKey){
FORT11_ENTER()
PK11Session *session = fort11_SessionFromHandle(hSession, PR_FALSE);
PK11Slot *slot = fort11_SlotFromSessionHandle(hSession);
FortezzaContext *context;
FortezzaContext passedInCxt;
PK11Object *keyObject;
FortezzaKey *fortKey;
if (session == NULL) {
session = fort11_SessionFromHandle(hSession, PR_TRUE);
fort11_TokenRemoved (slot, session);
fort11_FreeSession(session);
FORT11_RETURN (CKR_SESSION_HANDLE_INVALID);
}
if (ulOperationStateLen != sizeof(FortezzaContext)) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_SAVED_STATE_INVALID);
}
PORT_Memcpy(&passedInCxt, pOperationState, sizeof(FortezzaContext));
if (passedInCxt.fortezzaSocket->slotID != slot->slotID) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_SAVED_STATE_INVALID);
}
passedInCxt.session = NULL;
passedInCxt.fortezzaKey = NULL;
if (hEncryptionKey != 0) {
keyObject = fort11_ObjectFromHandle(hEncryptionKey, session);
if (keyObject == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_KEY_HANDLE_INVALID);
}
fortKey = (FortezzaKey*)keyObject->objectInfo;
fort11_FreeObject(keyObject);
if (fortKey == NULL) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_SAVED_STATE_INVALID);
}
if (fortKey->keyRegister == KeyNotLoaded) {
if (LoadKeyIntoRegister (fortKey) == KeyNotLoaded) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
}
passedInCxt.fortezzaKey = fortKey;
}
if (hAuthenticationKey != 0) {
fort11_FreeSession(session);
FORT11_RETURN (CKR_DEVICE_ERROR);
}
passedInCxt.session = session;
context = &session->fortezzaContext;
fort11_FreeSession (session);
PORT_Memcpy (context, &passedInCxt, sizeof(passedInCxt));
FORT11_RETURN (CKR_OK);
}
/* Dual-function cryptographic operations */
/* C_DigestEncryptUpdate continues a multiple-part digesting and
encryption operation. */
PR_PUBLIC_API(CK_RV) C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen,
CK_BYTE_PTR pEncryptedPart,
CK_ULONG_PTR pulEncryptedPartLen){
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_DecryptDigestUpdate continues a multiple-part decryption and digesting
operation. */
PR_PUBLIC_API(CK_RV) C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedPart,
CK_ULONG ulEncryptedPartLen,
CK_BYTE_PTR pPart,
CK_ULONG_PTR pulPartLen){
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_SignEncryptUpdate continues a multiple-part signing and encryption
operation. */
PR_PUBLIC_API(CK_RV) C_SignEncryptUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen,
CK_BYTE_PTR pEncryptedPart,
CK_ULONG_PTR pulEncryptedPartLen){
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_DecryptVerifyUpdate continues a multiple-part decryption and verify
operation. */
PR_PUBLIC_API(CK_RV) C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedData,
CK_ULONG ulEncryptedDataLen,
CK_BYTE_PTR pData,
CK_ULONG_PTR pulDataLen){
return CKR_FUNCTION_NOT_SUPPORTED;
}
/* C_DigestKey continues a multi-part message-digesting operation,
* by digesting the value of a secret key as part of the data already digested.
*/
PR_PUBLIC_API(CK_RV) C_DigestKey(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hKey) {
return CKR_FUNCTION_NOT_SUPPORTED;
}
PR_PUBLIC_API(CK_RV) C_WaitForSlotEvent(CK_FLAGS flags,
CK_SLOT_ID_PTR pSlot,
CK_VOID_PTR pRserved) {
return CKR_FUNCTION_FAILED;
}