mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-06 17:16:12 +00:00
4545 lines
130 KiB
C
4545 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
|
|
#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, *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", slotID);
|
|
#else
|
|
sprintf (tmp, "FORTEZZA Slot #%d", 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;
|
|
}
|
|
|