зеркало из https://github.com/mozilla/pjs.git
Bugzilla Bug 252702
NSS needs to handle better token insertion and removal. Applied from patch to NSS 3.9
This commit is contained in:
Родитель
dcd18c1baf
Коммит
a5a2371249
|
@ -797,6 +797,15 @@ PK11_UnlinkGenericObject;
|
|||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
;+NSS_3.9.3 { # NSS 3.9.3 release
|
||||
;+ global:
|
||||
SECMOD_CancelWait;
|
||||
SECMOD_HasRemovableSlots;
|
||||
SECMOD_UpdateSlotList;
|
||||
SECMOD_WaitForAnyTokenEvent;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
;+NSS_3.10 { # NSS 3.10 release
|
||||
;+ global:
|
||||
CERT_DecodeAltNameExtension;
|
||||
|
|
|
@ -90,6 +90,7 @@ PK11_MapError(CK_RV rv) {
|
|||
MAPERROR(CKR_KEY_TYPE_INCONSISTENT, SEC_ERROR_INVALID_KEY)
|
||||
MAPERROR(CKR_MECHANISM_INVALID, SEC_ERROR_BAD_DATA)
|
||||
MAPERROR(CKR_MECHANISM_PARAM_INVALID, SEC_ERROR_BAD_DATA)
|
||||
MAPERROR(CKR_NO_EVENT, SEC_ERROR_NO_EVENT)
|
||||
MAPERROR(CKR_OBJECT_HANDLE_INVALID, SEC_ERROR_BAD_DATA)
|
||||
MAPERROR(CKR_OPERATION_ACTIVE, SEC_ERROR_LIBRARY_FAILURE)
|
||||
MAPERROR(CKR_OPERATION_NOT_INITIALIZED,SEC_ERROR_LIBRARY_FAILURE )
|
||||
|
@ -124,6 +125,7 @@ PK11_MapError(CK_RV rv) {
|
|||
|
||||
|
||||
#ifdef PK11_ERROR_USE_ARRAY
|
||||
};
|
||||
|
||||
int
|
||||
PK11_MapError(CK_RV rv) {
|
||||
|
|
|
@ -43,37 +43,26 @@
|
|||
#include "secmod.h"
|
||||
#include "secmodi.h"
|
||||
#include "secmodti.h"
|
||||
|
||||
#define ISREADING 1
|
||||
#define ISWRITING 2
|
||||
#define WANTWRITE 4
|
||||
#define ISLOCKED 3
|
||||
#include "nssrwlk.h"
|
||||
|
||||
/*
|
||||
* create a new lock for a Module List
|
||||
*/
|
||||
SECMODListLock *SECMOD_NewListLock() {
|
||||
SECMODListLock *modLock;
|
||||
|
||||
modLock = (SECMODListLock*)PORT_Alloc(sizeof(SECMODListLock));
|
||||
SECMODListLock *SECMOD_NewListLock()
|
||||
{
|
||||
#ifdef PKCS11_USE_THREADS
|
||||
modLock->mutex = NULL;
|
||||
modLock->monitor = PZ_NewMonitor(nssILockList);
|
||||
return (SECMODListLock *) NSSRWLock_New( 10, "moduleListLock");
|
||||
#else
|
||||
modLock->mutex = NULL;
|
||||
modLock->monitor = NULL;
|
||||
return (SECMODListLock *) 1;
|
||||
#endif
|
||||
modLock->state = 0;
|
||||
modLock->count = 0;
|
||||
return modLock;
|
||||
}
|
||||
|
||||
/*
|
||||
* destroy the lock
|
||||
*/
|
||||
void SECMOD_DestroyListLock(SECMODListLock *lock) {
|
||||
PK11_USE_THREADS(PZ_DestroyMonitor(lock->monitor);)
|
||||
PORT_Free(lock);
|
||||
void SECMOD_DestroyListLock(SECMODListLock *lock)
|
||||
{
|
||||
PK11_USE_THREADS(NSSRWLock_Destroy((NSSRWLock *)lock);)
|
||||
}
|
||||
|
||||
|
||||
|
@ -81,52 +70,26 @@ void SECMOD_DestroyListLock(SECMODListLock *lock) {
|
|||
* Lock the List for Read: NOTE: this assumes the reading isn't so common
|
||||
* the writing will be starved.
|
||||
*/
|
||||
void SECMOD_GetReadLock(SECMODListLock *modLock) {
|
||||
#ifdef PKCS11_USE_THREADS
|
||||
if (modLock == NULL) return;
|
||||
PZ_EnterMonitor(modLock->monitor);
|
||||
while (modLock->state & ISWRITING) {
|
||||
PZ_Wait(modLock->monitor,PR_INTERVAL_NO_TIMEOUT); /* wait until woken up */
|
||||
}
|
||||
modLock->state |= ISREADING;
|
||||
modLock->count++;
|
||||
PZ_ExitMonitor(modLock->monitor);
|
||||
#endif
|
||||
void SECMOD_GetReadLock(SECMODListLock *modLock)
|
||||
{
|
||||
PK11_USE_THREADS(NSSRWLock_LockRead((NSSRWLock *)modLock);)
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the Read lock
|
||||
*/
|
||||
void SECMOD_ReleaseReadLock(SECMODListLock *modLock) {
|
||||
#ifdef PKCS11_USE_THREADS
|
||||
if (modLock == NULL) return;
|
||||
PZ_EnterMonitor(modLock->monitor);
|
||||
modLock->count--;
|
||||
if (modLock->count == 0) {
|
||||
modLock->state &= ~ISREADING;
|
||||
if (modLock->state & WANTWRITE) {
|
||||
PZ_Notify(modLock->monitor); /* only one writer at a time */
|
||||
}
|
||||
}
|
||||
PZ_ExitMonitor(modLock->monitor);
|
||||
#endif
|
||||
void SECMOD_ReleaseReadLock(SECMODListLock *modLock)
|
||||
{
|
||||
PK11_USE_THREADS(NSSRWLock_UnlockRead((NSSRWLock *)modLock);)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lock the list for Write
|
||||
*/
|
||||
void SECMOD_GetWriteLock(SECMODListLock *modLock) {
|
||||
#ifdef PKCS11_USE_THREADS
|
||||
if (modLock == NULL) return;
|
||||
PZ_EnterMonitor(modLock->monitor);
|
||||
while (modLock->state & ISLOCKED) {
|
||||
modLock->state |= WANTWRITE;
|
||||
PZ_Wait(modLock->monitor,PR_INTERVAL_NO_TIMEOUT); /* wait until woken up */
|
||||
}
|
||||
modLock->state = ISWRITING;
|
||||
PZ_ExitMonitor(modLock->monitor);
|
||||
#endif
|
||||
void SECMOD_GetWriteLock(SECMODListLock *modLock)
|
||||
{
|
||||
PK11_USE_THREADS(NSSRWLock_LockWrite((NSSRWLock *)modLock);)
|
||||
}
|
||||
|
||||
|
||||
|
@ -134,14 +97,9 @@ void SECMOD_GetWriteLock(SECMODListLock *modLock) {
|
|||
* Release the Write Lock: NOTE, this code is pretty inefficient if you have
|
||||
* lots of write collisions.
|
||||
*/
|
||||
void SECMOD_ReleaseWriteLock(SECMODListLock *modLock) {
|
||||
#ifdef PKCS11_USE_THREADS
|
||||
if (modLock == NULL) return;
|
||||
PZ_EnterMonitor(modLock->monitor);
|
||||
modLock->state = 0;
|
||||
PR_NotifyAll(modLock->monitor); /* enable all the readers */
|
||||
PZ_ExitMonitor(modLock->monitor);
|
||||
#endif
|
||||
void SECMOD_ReleaseWriteLock(SECMODListLock *modLock)
|
||||
{
|
||||
PK11_USE_THREADS(NSSRWLock_UnlockWrite((NSSRWLock *)modLock);)
|
||||
}
|
||||
|
||||
|
||||
|
@ -149,7 +107,8 @@ void SECMOD_ReleaseWriteLock(SECMODListLock *modLock) {
|
|||
* must Hold the Write lock
|
||||
*/
|
||||
void
|
||||
SECMOD_RemoveList(SECMODModuleList **parent, SECMODModuleList *child) {
|
||||
SECMOD_RemoveList(SECMODModuleList **parent, SECMODModuleList *child)
|
||||
{
|
||||
*parent = child->next;
|
||||
child->next = NULL;
|
||||
}
|
||||
|
@ -159,7 +118,8 @@ SECMOD_RemoveList(SECMODModuleList **parent, SECMODModuleList *child) {
|
|||
*/
|
||||
void
|
||||
SECMOD_AddList(SECMODModuleList *parent, SECMODModuleList *child,
|
||||
SECMODListLock *lock) {
|
||||
SECMODListLock *lock)
|
||||
{
|
||||
if (lock) { SECMOD_GetWriteLock(lock); }
|
||||
|
||||
child->next = parent->next;
|
||||
|
|
|
@ -90,6 +90,41 @@ static const CK_C_INITIALIZE_ARGS secmodLockFunctions = {
|
|||
,NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* collect the steps we need to initialize a module in a single function
|
||||
*/
|
||||
SECStatus
|
||||
secmod_ModuleInit(SECMODModule *mod)
|
||||
{
|
||||
CK_C_INITIALIZE_ARGS moduleArgs;
|
||||
CK_VOID_PTR pInitArgs;
|
||||
CK_RV crv;
|
||||
|
||||
if (mod->isThreadSafe == PR_FALSE) {
|
||||
pInitArgs = NULL;
|
||||
} else if (mod->libraryParams == NULL) {
|
||||
pInitArgs = (void *) &secmodLockFunctions;
|
||||
} else {
|
||||
moduleArgs = secmodLockFunctions;
|
||||
moduleArgs.LibraryParameters = (void *) mod->libraryParams;
|
||||
pInitArgs = &moduleArgs;
|
||||
}
|
||||
crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
|
||||
if (crv != CKR_OK) {
|
||||
if (pInitArgs == NULL) {
|
||||
PORT_SetError(PK11_MapError(crv));
|
||||
return SECFailure;
|
||||
}
|
||||
mod->isThreadSafe = PR_FALSE;
|
||||
crv = PK11_GETTAB(mod)->C_Initialize(NULL);
|
||||
if (crv != CKR_OK) {
|
||||
PORT_SetError(PK11_MapError(crv));
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* set the hasRootCerts flags in the module so it can be stored back
|
||||
* into the database.
|
||||
|
@ -142,8 +177,7 @@ SECMOD_LoadPKCS11Module(SECMODModule *mod) {
|
|||
char * full_name;
|
||||
CK_INFO info;
|
||||
CK_ULONG slotCount = 0;
|
||||
CK_C_INITIALIZE_ARGS moduleArgs;
|
||||
CK_VOID_PTR pInitArgs;
|
||||
SECStatus rv;
|
||||
|
||||
if (mod->loaded) return SECSuccess;
|
||||
|
||||
|
@ -228,17 +262,11 @@ SECMOD_LoadPKCS11Module(SECMODModule *mod) {
|
|||
#endif
|
||||
|
||||
mod->isThreadSafe = PR_TRUE;
|
||||
|
||||
/* Now we initialize the module */
|
||||
if (mod->libraryParams) {
|
||||
moduleArgs = secmodLockFunctions;
|
||||
moduleArgs.LibraryParameters = (void *) mod->libraryParams;
|
||||
pInitArgs = &moduleArgs;
|
||||
} else {
|
||||
pInitArgs = (void *) &secmodLockFunctions;
|
||||
}
|
||||
if (PK11_GETTAB(mod)->C_Initialize(pInitArgs) != CKR_OK) {
|
||||
mod->isThreadSafe = PR_FALSE;
|
||||
if (PK11_GETTAB(mod)->C_Initialize(NULL) != CKR_OK) goto fail;
|
||||
rv = secmod_ModuleInit(mod);
|
||||
if (rv != SECSuccess) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* check the version number */
|
||||
|
@ -260,7 +288,7 @@ SECMOD_LoadPKCS11Module(SECMODModule *mod) {
|
|||
if (PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, NULL, &slotCount) == CKR_OK) {
|
||||
CK_SLOT_ID *slotIDs;
|
||||
int i;
|
||||
CK_RV rv;
|
||||
CK_RV crv;
|
||||
|
||||
mod->slots = (PK11SlotInfo **)PORT_ArenaAlloc(mod->arena,
|
||||
sizeof(PK11SlotInfo *) * slotCount);
|
||||
|
@ -270,8 +298,8 @@ SECMOD_LoadPKCS11Module(SECMODModule *mod) {
|
|||
if (slotIDs == NULL) {
|
||||
goto fail2;
|
||||
}
|
||||
rv = PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, slotIDs, &slotCount);
|
||||
if (rv != CKR_OK) {
|
||||
crv = PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, slotIDs, &slotCount);
|
||||
if (crv != CKR_OK) {
|
||||
PORT_Free(slotIDs);
|
||||
goto fail2;
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@ secmod_NewModule(void)
|
|||
newMod->moduleDBOnly = PR_FALSE;
|
||||
newMod->trustOrder = 0;
|
||||
newMod->cipherOrder = 0;
|
||||
newMod->evControlMask = 0;
|
||||
#ifdef PKCS11_USE_THREADS
|
||||
newMod->refLock = (void *)PZ_NewLock(nssILockRefLock);
|
||||
if (newMod->refLock == NULL) {
|
||||
|
@ -163,9 +164,12 @@ pk11_mkModuleSpec(SECMODModule * module)
|
|||
{
|
||||
char *nss = NULL, *modSpec = NULL, **slotStrings = NULL;
|
||||
int slotCount, i, si;
|
||||
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
|
||||
|
||||
/* allocate target slot info strings */
|
||||
slotCount = 0;
|
||||
|
||||
SECMOD_GetReadLock(moduleLock);
|
||||
if (module->slotCount) {
|
||||
for (i=0; i < module->slotCount; i++) {
|
||||
if (module->slots[i]->defaultFlags !=0) {
|
||||
|
@ -178,6 +182,7 @@ pk11_mkModuleSpec(SECMODModule * module)
|
|||
|
||||
slotStrings = (char **)PORT_ZAlloc(slotCount*sizeof(char *));
|
||||
if (slotStrings == NULL) {
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
goto loser;
|
||||
}
|
||||
|
||||
|
@ -208,6 +213,7 @@ pk11_mkModuleSpec(SECMODModule * module)
|
|||
}
|
||||
}
|
||||
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
nss = pk11_mkNSS(slotStrings,slotCount,module->internal, module->isFIPS,
|
||||
module->isModuleDB, module->moduleDBOnly, module->isCritical,
|
||||
module->trustOrder,module->cipherOrder,module->ssl[0],module->ssl[1]);
|
||||
|
@ -386,8 +392,12 @@ SECMOD_LoadUserModule(char *modulespec,SECMODModule *parent, PRBool recurse)
|
|||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
SECMODModule * newmod = SECMOD_LoadModule(modulespec, parent, recurse);
|
||||
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
|
||||
|
||||
if (newmod) {
|
||||
SECMOD_GetReadLock(moduleLock);
|
||||
rv = STAN_AddModuleToDefaultTrustDomain(newmod);
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
if (SECSuccess != rv) {
|
||||
SECMOD_DestroyModule(newmod);
|
||||
return NULL;
|
||||
|
@ -404,10 +414,14 @@ SECStatus SECMOD_UnloadUserModule(SECMODModule *mod)
|
|||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
int atype = 0;
|
||||
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
|
||||
if (!mod) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECMOD_GetReadLock(moduleLock);
|
||||
rv = STAN_RemoveModuleFromDefaultTrustDomain(mod);
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
if (SECSuccess != rv) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,8 @@ extern int num_pk11_default_mechanisms;
|
|||
|
||||
|
||||
void
|
||||
SECMOD_Init() {
|
||||
SECMOD_Init()
|
||||
{
|
||||
/* don't initialize twice */
|
||||
if (moduleLock) return;
|
||||
|
||||
|
@ -72,7 +73,8 @@ SECMOD_Init() {
|
|||
|
||||
|
||||
SECStatus
|
||||
SECMOD_Shutdown() {
|
||||
SECMOD_Shutdown()
|
||||
{
|
||||
/* destroy the lock */
|
||||
if (moduleLock) {
|
||||
SECMOD_DestroyListLock(moduleLock);
|
||||
|
@ -128,13 +130,15 @@ SECMOD_Shutdown() {
|
|||
* retrieve the internal module
|
||||
*/
|
||||
SECMODModule *
|
||||
SECMOD_GetInternalModule(void) {
|
||||
SECMOD_GetInternalModule(void)
|
||||
{
|
||||
return internalModule;
|
||||
}
|
||||
|
||||
|
||||
SECStatus
|
||||
secmod_AddModuleToList(SECMODModuleList **moduleList,SECMODModule *newModule) {
|
||||
secmod_AddModuleToList(SECMODModuleList **moduleList,SECMODModule *newModule)
|
||||
{
|
||||
SECMODModuleList *mlp, *newListElement, *last = NULL;
|
||||
|
||||
newListElement = SECMOD_NewModuleListElement();
|
||||
|
@ -162,7 +166,8 @@ secmod_AddModuleToList(SECMODModuleList **moduleList,SECMODModule *newModule) {
|
|||
}
|
||||
|
||||
SECStatus
|
||||
SECMOD_AddModuleToList(SECMODModule *newModule) {
|
||||
SECMOD_AddModuleToList(SECMODModule *newModule)
|
||||
{
|
||||
if (newModule->internal && !internalModule) {
|
||||
internalModule = SECMOD_ReferenceModule(newModule);
|
||||
}
|
||||
|
@ -170,7 +175,8 @@ SECMOD_AddModuleToList(SECMODModule *newModule) {
|
|||
}
|
||||
|
||||
SECStatus
|
||||
SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule) {
|
||||
SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule)
|
||||
{
|
||||
if (defaultDBModule == NULL) {
|
||||
defaultDBModule = SECMOD_ReferenceModule(newModule);
|
||||
}
|
||||
|
@ -178,16 +184,29 @@ SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule) {
|
|||
}
|
||||
|
||||
SECStatus
|
||||
SECMOD_AddModuleToUnloadList(SECMODModule *newModule) {
|
||||
SECMOD_AddModuleToUnloadList(SECMODModule *newModule)
|
||||
{
|
||||
return secmod_AddModuleToList(&modulesUnload,newModule);
|
||||
}
|
||||
|
||||
/*
|
||||
* get the list of PKCS11 modules that are available.
|
||||
*/
|
||||
SECMODModuleList *SECMOD_GetDefaultModuleList() { return modules; }
|
||||
SECMODModuleList * SECMOD_GetDefaultModuleList() { return modules; }
|
||||
SECMODModuleList *SECMOD_GetDeadModuleList() { return modulesUnload; }
|
||||
SECMODModuleList *SECMOD_GetDBModuleList() { return modulesDB; }
|
||||
|
||||
/*
|
||||
* This lock protects the global module lists.
|
||||
* it also protects changes to the slot array (module->slots[]) and slot count
|
||||
* (module->slotCount) in each module. It is a read/write lock with multiple
|
||||
* readers or one writer. Writes are uncommon.
|
||||
* Because of legacy considerations protection of the slot array and count is
|
||||
* only necessary in applications if the application calls
|
||||
* SECMOD_UpdateSlotList() or SECMOD_WaitForAnyTokenEvent(), though all new
|
||||
* applications are encouraged to acquire this lock when reading the
|
||||
* slot array information directly.
|
||||
*/
|
||||
SECMODListLock *SECMOD_GetDefaultModuleListLock() { return moduleLock; }
|
||||
|
||||
|
||||
|
@ -196,7 +215,9 @@ SECMODListLock *SECMOD_GetDefaultModuleListLock() { return moduleLock; }
|
|||
* find a module by name, and add a reference to it.
|
||||
* return that module.
|
||||
*/
|
||||
SECMODModule *SECMOD_FindModule(const char *name) {
|
||||
SECMODModule *
|
||||
SECMOD_FindModule(const char *name)
|
||||
{
|
||||
SECMODModuleList *mlp;
|
||||
SECMODModule *module = NULL;
|
||||
|
||||
|
@ -229,7 +250,9 @@ found:
|
|||
* find a module by ID, and add a reference to it.
|
||||
* return that module.
|
||||
*/
|
||||
SECMODModule *SECMOD_FindModuleByID(SECMODModuleID id) {
|
||||
SECMODModule *
|
||||
SECMOD_FindModuleByID(SECMODModuleID id)
|
||||
{
|
||||
SECMODModuleList *mlp;
|
||||
SECMODModule *module = NULL;
|
||||
|
||||
|
@ -242,30 +265,53 @@ SECMODModule *SECMOD_FindModuleByID(SECMODModuleID id) {
|
|||
}
|
||||
}
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
|
||||
if (module == NULL) {
|
||||
PORT_SetError(SEC_ERROR_NO_MODULE);
|
||||
}
|
||||
return module;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the Slot based on ID and the module.
|
||||
*/
|
||||
PK11SlotInfo *
|
||||
SECMOD_FindSlotByID(SECMODModule *module, CK_SLOT_ID slotID)
|
||||
{
|
||||
int i;
|
||||
PK11SlotInfo *slot = NULL;
|
||||
|
||||
SECMOD_GetReadLock(moduleLock);
|
||||
for (i=0; i < module->slotCount; i++) {
|
||||
PK11SlotInfo *cSlot = module->slots[i];
|
||||
|
||||
if (cSlot->slotID == slotID) {
|
||||
slot = PK11_ReferenceSlot(cSlot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
|
||||
if (slot == NULL) {
|
||||
PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
/*
|
||||
* lookup the Slot module based on it's module ID and slot ID.
|
||||
*/
|
||||
PK11SlotInfo *SECMOD_LookupSlot(SECMODModuleID moduleID,CK_SLOT_ID slotID) {
|
||||
int i;
|
||||
PK11SlotInfo *
|
||||
SECMOD_LookupSlot(SECMODModuleID moduleID,CK_SLOT_ID slotID)
|
||||
{
|
||||
SECMODModule *module;
|
||||
PK11SlotInfo *slot;
|
||||
|
||||
module = SECMOD_FindModuleByID(moduleID);
|
||||
if (module == NULL) return NULL;
|
||||
|
||||
for (i=0; i < module->slotCount; i++) {
|
||||
PK11SlotInfo *slot = module->slots[i];
|
||||
|
||||
if (slot->slotID == slotID) {
|
||||
SECMOD_DestroyModule(module);
|
||||
return PK11_ReferenceSlot(slot);
|
||||
}
|
||||
}
|
||||
slot = SECMOD_FindSlotByID(module, slotID);
|
||||
SECMOD_DestroyModule(module);
|
||||
return NULL;
|
||||
return slot;
|
||||
}
|
||||
|
||||
|
||||
|
@ -338,7 +384,8 @@ found:
|
|||
* find a module by name and delete it off the module list
|
||||
*/
|
||||
SECStatus
|
||||
SECMOD_DeleteModule(const char *name, int *type) {
|
||||
SECMOD_DeleteModule(const char *name, int *type)
|
||||
{
|
||||
return SECMOD_DeleteModuleEx(name, NULL, type, PR_TRUE);
|
||||
}
|
||||
|
||||
|
@ -346,7 +393,8 @@ SECMOD_DeleteModule(const char *name, int *type) {
|
|||
* find a module by name and delete it off the module list
|
||||
*/
|
||||
SECStatus
|
||||
SECMOD_DeleteInternalModule(const char *name) {
|
||||
SECMOD_DeleteInternalModule(const char *name)
|
||||
{
|
||||
SECMODModuleList *mlp;
|
||||
SECMODModuleList **mlpp;
|
||||
SECStatus rv = SECFailure;
|
||||
|
@ -418,7 +466,8 @@ SECMOD_DeleteInternalModule(const char *name) {
|
|||
}
|
||||
|
||||
SECStatus
|
||||
SECMOD_AddModule(SECMODModule *newModule) {
|
||||
SECMOD_AddModule(SECMODModule *newModule)
|
||||
{
|
||||
SECStatus rv;
|
||||
SECMODModule *oldModule;
|
||||
|
||||
|
@ -450,10 +499,14 @@ SECMOD_AddModule(SECMODModule *newModule) {
|
|||
return rv;
|
||||
}
|
||||
|
||||
PK11SlotInfo *SECMOD_FindSlot(SECMODModule *module,const char *name) {
|
||||
PK11SlotInfo *
|
||||
SECMOD_FindSlot(SECMODModule *module,const char *name)
|
||||
{
|
||||
int i;
|
||||
char *string;
|
||||
PK11SlotInfo *retSlot = NULL;
|
||||
|
||||
SECMOD_GetReadLock(moduleLock);
|
||||
for (i=0; i < module->slotCount; i++) {
|
||||
PK11SlotInfo *slot = module->slots[i];
|
||||
|
||||
|
@ -463,10 +516,17 @@ PK11SlotInfo *SECMOD_FindSlot(SECMODModule *module,const char *name) {
|
|||
string = PK11_GetSlotName(slot);
|
||||
}
|
||||
if (PORT_Strcmp(name,string) == 0) {
|
||||
return PK11_ReferenceSlot(slot);
|
||||
retSlot = PK11_ReferenceSlot(slot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
|
||||
if (retSlot == NULL) {
|
||||
PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
|
||||
}
|
||||
return NULL;
|
||||
return retSlot;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
|
@ -501,11 +561,12 @@ PK11_IsFIPS(void)
|
|||
/* combines NewModule() & AddModule */
|
||||
/* give a string for the module name & the full-path for the dll, */
|
||||
/* installs the PKCS11 module & update registry */
|
||||
SECStatus SECMOD_AddNewModuleEx(const char* moduleName, const char* dllPath,
|
||||
SECStatus
|
||||
SECMOD_AddNewModuleEx(const char* moduleName, const char* dllPath,
|
||||
unsigned long defaultMechanismFlags,
|
||||
unsigned long cipherEnableFlags,
|
||||
char* modparms,
|
||||
char* nssparms) {
|
||||
char* modparms, char* nssparms)
|
||||
{
|
||||
SECMODModule *module;
|
||||
SECStatus result = SECFailure;
|
||||
int s,i;
|
||||
|
@ -526,26 +587,28 @@ SECStatus SECMOD_AddNewModuleEx(const char* moduleName, const char* dllPath,
|
|||
/* turn on SSL cipher enable flags */
|
||||
module->ssl[0] = cipherEnableFlags;
|
||||
|
||||
SECMOD_GetReadLock(moduleLock);
|
||||
/* check each slot to turn on appropriate mechanisms */
|
||||
for (s = 0; s < module->slotCount; s++) {
|
||||
slot = (module->slots)[s];
|
||||
/* for each possible mechanism */
|
||||
for (i=0; i < num_pk11_default_mechanisms; i++) {
|
||||
/* we are told to turn it on by default ? */
|
||||
if (PK11_DefaultArray[i].flag & defaultMechanismFlags) {
|
||||
/* it ignores if slot attribute update failes */
|
||||
result = PK11_UpdateSlotAttribute(slot, &(PK11_DefaultArray[i]), PR_TRUE);
|
||||
} else { /* turn this mechanism of the slot off by default */
|
||||
result = PK11_UpdateSlotAttribute(slot, &(PK11_DefaultArray[i]), PR_FALSE);
|
||||
}
|
||||
PRBool add =
|
||||
(PK11_DefaultArray[i].flag & defaultMechanismFlags) ?
|
||||
PR_TRUE: PR_FALSE;
|
||||
result = PK11_UpdateSlotAttribute(slot,
|
||||
&(PK11_DefaultArray[i]), add);
|
||||
} /* for each mechanism */
|
||||
/* disable each slot if the defaultFlags say so */
|
||||
if (defaultMechanismFlags & PK11_DISABLE_FLAG) {
|
||||
PK11_UserDisableSlot(slot);
|
||||
}
|
||||
} /* for each slot of this module */
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
|
||||
/* delete and re-add module in order to save changes to the module */
|
||||
/* delete and re-add module in order to save changes
|
||||
* to the module */
|
||||
result = SECMOD_UpdateModule(module);
|
||||
}
|
||||
}
|
||||
|
@ -554,7 +617,8 @@ SECStatus SECMOD_AddNewModuleEx(const char* moduleName, const char* dllPath,
|
|||
return result;
|
||||
}
|
||||
|
||||
SECStatus SECMOD_AddNewModule(const char* moduleName, const char* dllPath,
|
||||
SECStatus
|
||||
SECMOD_AddNewModule(const char* moduleName, const char* dllPath,
|
||||
unsigned long defaultMechanismFlags,
|
||||
unsigned long cipherEnableFlags)
|
||||
{
|
||||
|
@ -563,7 +627,8 @@ SECStatus SECMOD_AddNewModule(const char* moduleName, const char* dllPath,
|
|||
NULL, NULL); /* don't pass module or nss params */
|
||||
}
|
||||
|
||||
SECStatus SECMOD_UpdateModule(SECMODModule *module)
|
||||
SECStatus
|
||||
SECMOD_UpdateModule(SECMODModule *module)
|
||||
{
|
||||
SECStatus result;
|
||||
|
||||
|
@ -582,7 +647,9 @@ SECStatus SECMOD_UpdateModule(SECMODModule *module)
|
|||
* puts RANDOM_FLAG at bit 31 (Most-significant bit), but
|
||||
* public representation puts this bit at bit 28
|
||||
*/
|
||||
unsigned long SECMOD_PubMechFlagstoInternal(unsigned long publicFlags) {
|
||||
unsigned long
|
||||
SECMOD_PubMechFlagstoInternal(unsigned long publicFlags)
|
||||
{
|
||||
unsigned long internalFlags = publicFlags;
|
||||
|
||||
if (publicFlags & PUBLIC_MECH_RANDOM_FLAG) {
|
||||
|
@ -592,7 +659,9 @@ unsigned long SECMOD_PubMechFlagstoInternal(unsigned long publicFlags) {
|
|||
return internalFlags;
|
||||
}
|
||||
|
||||
unsigned long SECMOD_InternaltoPubMechFlags(unsigned long internalFlags) {
|
||||
unsigned long
|
||||
SECMOD_InternaltoPubMechFlags(unsigned long internalFlags)
|
||||
{
|
||||
unsigned long publicFlags = internalFlags;
|
||||
|
||||
if (internalFlags & SECMOD_RANDOM_FLAG) {
|
||||
|
@ -606,11 +675,15 @@ unsigned long SECMOD_InternaltoPubMechFlags(unsigned long internalFlags) {
|
|||
/* Public & Internal(Security Library) representation of */
|
||||
/* cipher flags conversion */
|
||||
/* Note: currently they are just stubs */
|
||||
unsigned long SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags) {
|
||||
unsigned long
|
||||
SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags)
|
||||
{
|
||||
return publicFlags;
|
||||
}
|
||||
|
||||
unsigned long SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags) {
|
||||
unsigned long
|
||||
SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags)
|
||||
{
|
||||
return internalFlags;
|
||||
}
|
||||
|
||||
|
@ -624,7 +697,8 @@ SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags )
|
|||
|
||||
|
||||
for ( ; mods != NULL; mods = mods->next) {
|
||||
if (mods->module->ssl[0] & SECMOD_PubCipherFlagstoInternal(pubCipherEnableFlags)) {
|
||||
if (mods->module->ssl[0] &
|
||||
SECMOD_PubCipherFlagstoInternal(pubCipherEnableFlags)) {
|
||||
result = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -634,7 +708,8 @@ SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags )
|
|||
}
|
||||
|
||||
/* create a new ModuleListElement */
|
||||
SECMODModuleList *SECMOD_NewModuleListElement(void) {
|
||||
SECMODModuleList *SECMOD_NewModuleListElement(void)
|
||||
{
|
||||
SECMODModuleList *newModList;
|
||||
|
||||
newModList= (SECMODModuleList *) PORT_Alloc(sizeof(SECMODModuleList));
|
||||
|
@ -644,11 +719,13 @@ SECMODModuleList *SECMOD_NewModuleListElement(void) {
|
|||
}
|
||||
return newModList;
|
||||
}
|
||||
|
||||
/*
|
||||
* make a new reference to a module so It doesn't go away on us
|
||||
*/
|
||||
SECMODModule *
|
||||
SECMOD_ReferenceModule(SECMODModule *module) {
|
||||
SECMOD_ReferenceModule(SECMODModule *module)
|
||||
{
|
||||
PK11_USE_THREADS(PZ_Lock((PZLock *)module->refLock);)
|
||||
PORT_Assert(module->refCount > 0);
|
||||
|
||||
|
@ -660,7 +737,8 @@ SECMOD_ReferenceModule(SECMODModule *module) {
|
|||
|
||||
/* destroy an existing module */
|
||||
void
|
||||
SECMOD_DestroyModule(SECMODModule *module) {
|
||||
SECMOD_DestroyModule(SECMODModule *module)
|
||||
{
|
||||
PRBool willfree = PR_FALSE;
|
||||
int slotCount;
|
||||
int i;
|
||||
|
@ -707,7 +785,8 @@ SECMOD_DestroyModule(SECMODModule *module) {
|
|||
/* we can only get here if we've destroyed the module, or some one has
|
||||
* erroneously freed a slot that wasn't referenced. */
|
||||
void
|
||||
SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot) {
|
||||
SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot)
|
||||
{
|
||||
PRBool willfree = PR_FALSE;
|
||||
if (fromSlot) {
|
||||
PORT_Assert(module->refCount == 0);
|
||||
|
@ -737,7 +816,8 @@ SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot) {
|
|||
* on the chain. It makes it easy to implement for loops to delete
|
||||
* the chain. It also make deleting a single element easy */
|
||||
SECMODModuleList *
|
||||
SECMOD_DestroyModuleListElement(SECMODModuleList *element) {
|
||||
SECMOD_DestroyModuleListElement(SECMODModuleList *element)
|
||||
{
|
||||
SECMODModuleList *next = element->next;
|
||||
|
||||
if (element->module) {
|
||||
|
@ -753,7 +833,8 @@ SECMOD_DestroyModuleListElement(SECMODModuleList *element) {
|
|||
* Destroy an entire module list
|
||||
*/
|
||||
void
|
||||
SECMOD_DestroyModuleList(SECMODModuleList *list) {
|
||||
SECMOD_DestroyModuleList(SECMODModuleList *list)
|
||||
{
|
||||
SECMODModuleList *lp;
|
||||
|
||||
for ( lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) ;
|
||||
|
@ -764,3 +845,330 @@ SECMOD_CanDeleteInternalModule(void)
|
|||
{
|
||||
return (PRBool) (pendingModule == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* check to see if the module has added new slots. PKCS 11 v2.20 allows for
|
||||
* modules to add new slots, but never remove them. Slots cannot be added
|
||||
* between a call to C_GetSlotLlist(Flag, NULL, &count) and the subsequent
|
||||
* C_GetSlotList(flag, &data, &count) so that the array doesn't accidently
|
||||
* grow on the caller. It is permissible for the slots to increase between
|
||||
* successive calls with NULL to get the size.
|
||||
*/
|
||||
SECStatus
|
||||
SECMOD_UpdateSlotList(SECMODModule *mod)
|
||||
{
|
||||
CK_RV crv;
|
||||
int count,i, oldCount;
|
||||
PRBool freeRef = PR_FALSE;
|
||||
void *mark;
|
||||
CK_ULONG *slotIDs = NULL;
|
||||
PK11SlotInfo **newSlots = NULL;
|
||||
PK11SlotInfo **oldSlots = NULL;
|
||||
|
||||
/* C_GetSlotList is not a session function, make sure
|
||||
* calls are serialized */
|
||||
PZ_Lock(mod->refLock);
|
||||
freeRef = PR_TRUE;
|
||||
/* see if the number of slots have changed */
|
||||
crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, NULL, &count);
|
||||
if (crv != CKR_OK) {
|
||||
PORT_SetError(PK11_MapError(crv));
|
||||
goto loser;
|
||||
}
|
||||
/* nothing new, blow out early, we want this function to be quick
|
||||
* and cheap in the normal case */
|
||||
if (count == mod->slotCount) {
|
||||
PZ_Unlock(mod->refLock);
|
||||
return SECSuccess;
|
||||
}
|
||||
if (count < mod->slotCount) {
|
||||
/* shouldn't happen with a properly functioning PKCS #11 module */
|
||||
PORT_SetError( SEC_ERROR_INCOMPATIBLE_PKCS11 );
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* get the new slot list */
|
||||
slotIDs = PORT_NewArray(CK_SLOT_ID, count);
|
||||
if (slotIDs == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, slotIDs, &count);
|
||||
if (crv != CKR_OK) {
|
||||
PORT_SetError(PK11_MapError(crv));
|
||||
goto loser;
|
||||
}
|
||||
freeRef = PR_FALSE;
|
||||
PZ_Unlock(mod->refLock);
|
||||
mark = PORT_ArenaMark(mod->arena);
|
||||
if (mark == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
newSlots = PORT_ArenaZNewArray(mod->arena,PK11SlotInfo *,count);
|
||||
|
||||
/* walk down the new slot ID list returned from the module. We keep
|
||||
* the old slots which match a returned ID, and we initialize the new
|
||||
* slots. */
|
||||
for (i=0; i < count; i++) {
|
||||
PK11SlotInfo *slot = SECMOD_FindSlotByID(mod,slotIDs[i]);
|
||||
|
||||
if (!slot) {
|
||||
/* we have a new slot create a new slot data structure */
|
||||
slot = PK11_NewSlotInfo(mod);
|
||||
if (!slot) {
|
||||
goto loser;
|
||||
}
|
||||
PK11_InitSlot(mod, slotIDs[i], slot);
|
||||
STAN_InitTokenForSlotInfo(NULL, slot);
|
||||
}
|
||||
newSlots[i] = slot;
|
||||
}
|
||||
STAN_ResetTokenInterator(NULL);
|
||||
PORT_Free(slotIDs);
|
||||
slotIDs = NULL;
|
||||
PORT_ArenaUnmark(mod->arena, mark);
|
||||
|
||||
/* until this point we're still using the old slot list. Now we update
|
||||
* module slot list. We update the slots (array) first then the count,
|
||||
* since we've already guarrenteed that count has increased (just in case
|
||||
* someone is looking at the slots field of module without holding the
|
||||
* moduleLock */
|
||||
SECMOD_GetWriteLock(moduleLock);
|
||||
oldCount =mod->slotCount;
|
||||
oldSlots = mod->slots;
|
||||
mod->slots = newSlots; /* typical arena 'leak'... old mod->slots is
|
||||
* allocated out of the module arena and won't
|
||||
* be freed until the module is freed */
|
||||
mod->slotCount = count;
|
||||
SECMOD_ReleaseWriteLock(moduleLock);
|
||||
/* free our old references before forgetting about oldSlot*/
|
||||
for (i=0; i < oldCount; i++) {
|
||||
PK11_FreeSlot(oldSlots[i]);
|
||||
}
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
if (freeRef) {
|
||||
PZ_Unlock(mod->refLock);
|
||||
}
|
||||
if (slotIDs) {
|
||||
PORT_Free(slotIDs);
|
||||
}
|
||||
/* free all the slots we allocated. newSlots are part of the
|
||||
* mod arena. NOTE: the newSlots array contain both new and old
|
||||
* slots, but we kept a reference to the old slots when we built the new
|
||||
* array, so we need to free all the slots in newSlots array. */
|
||||
if (newSlots) {
|
||||
for (i=0; i < count; i++) {
|
||||
if (newSlots[i] == NULL) {
|
||||
break; /* hit the last one */
|
||||
}
|
||||
PK11_FreeSlot(newSlots[i]);
|
||||
}
|
||||
}
|
||||
/* must come after freeing newSlots */
|
||||
if (mark) {
|
||||
PORT_ArenaRelease(mod->arena, mark);
|
||||
}
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/*
|
||||
* this handles modules that do not support C_WaitForSlotEvent().
|
||||
* The internal flags are stored. Note that C_WaitForSlotEvent() does not
|
||||
* have a timeout, so we don't have one for handleWaitForSlotEvent() either.
|
||||
*/
|
||||
PK11SlotInfo *
|
||||
secmod_HandleWaitForSlotEvent(SECMODModule *mod, unsigned long flags,
|
||||
PRIntervalTime latency)
|
||||
{
|
||||
PRBool removableSlotsFound = PR_FALSE;
|
||||
int i;
|
||||
int error = SEC_ERROR_NO_EVENT;
|
||||
|
||||
PZ_Lock(mod->refLock);
|
||||
if (mod->evControlMask & SECMOD_END_WAIT) {
|
||||
mod->evControlMask &= ~SECMOD_END_WAIT;
|
||||
PZ_Unlock(mod->refLock);
|
||||
PORT_SetError(SEC_ERROR_NO_EVENT);
|
||||
return NULL;
|
||||
}
|
||||
mod->evControlMask |= SECMOD_WAIT_SIMULATED_EVENT;
|
||||
while (mod->evControlMask & SECMOD_WAIT_SIMULATED_EVENT) {
|
||||
PZ_Unlock(mod->refLock);
|
||||
/* now is a good time to see if new slots have been added */
|
||||
SECMOD_UpdateSlotList(mod);
|
||||
|
||||
/* loop through all the slots on a module */
|
||||
SECMOD_GetReadLock(moduleLock);
|
||||
for (i=0; i < mod->slotCount; i++) {
|
||||
PK11SlotInfo *slot = mod->slots[i];
|
||||
uint16 series;
|
||||
PRBool present;
|
||||
|
||||
/* perm modules do not change */
|
||||
if (slot->isPerm) {
|
||||
continue;
|
||||
}
|
||||
removableSlotsFound = PR_TRUE;
|
||||
/* simulate the PKCS #11 module flags. are the flags different
|
||||
* from the last time we called? */
|
||||
series = slot->series;
|
||||
present = PK11_IsPresent(slot);
|
||||
if ((slot->flagSeries != series) || (slot->flagState != present)) {
|
||||
slot->flagState = present;
|
||||
slot->flagSeries = series;
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
PZ_Lock(mod->refLock);
|
||||
mod->evControlMask &= ~SECMOD_END_WAIT;
|
||||
PZ_Unlock(mod->refLock);
|
||||
return PK11_ReferenceSlot(slot);
|
||||
}
|
||||
}
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
/* if everything was perm modules, don't lock up forever */
|
||||
if (!removableSlotsFound) {
|
||||
error =SEC_ERROR_NO_SLOT_SELECTED;
|
||||
PZ_Lock(mod->refLock);
|
||||
break;
|
||||
}
|
||||
if (flags & CKF_DONT_BLOCK) {
|
||||
PZ_Lock(mod->refLock);
|
||||
break;
|
||||
}
|
||||
PR_Sleep(latency);
|
||||
PZ_Lock(mod->refLock);
|
||||
}
|
||||
mod->evControlMask &= ~SECMOD_END_WAIT;
|
||||
PZ_Unlock(mod->refLock);
|
||||
PORT_SetError(error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* this function waits for a token event on any slot of a given module
|
||||
* This function should not be called from more than one thread of the
|
||||
* same process (though other threads can make other library calls
|
||||
* on this module while this call is blocked).
|
||||
*/
|
||||
PK11SlotInfo *
|
||||
SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags,
|
||||
PRIntervalTime latency)
|
||||
{
|
||||
CK_SLOT_ID id;
|
||||
CK_RV crv;
|
||||
PK11SlotInfo *slot;
|
||||
|
||||
/* first the the PKCS #11 call */
|
||||
PZ_Lock(mod->refLock);
|
||||
if (mod->evControlMask & SECMOD_END_WAIT) {
|
||||
goto end_wait;
|
||||
}
|
||||
mod->evControlMask |= SECMOD_WAIT_PKCS11_EVENT;
|
||||
PZ_Unlock(mod->refLock);
|
||||
crv = PK11_GETTAB(mod)->C_WaitForSlotEvent(flags, &id, NULL);
|
||||
PZ_Lock(mod->refLock);
|
||||
mod->evControlMask &= ~SECMOD_WAIT_PKCS11_EVENT;
|
||||
/* if we are in end wait, short circuit now, don't even risk
|
||||
* going into secmod_HandleWaitForSlotEvent */
|
||||
if (mod->evControlMask & SECMOD_END_WAIT) {
|
||||
goto end_wait;
|
||||
}
|
||||
PZ_Unlock(mod->refLock);
|
||||
if (crv == CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
/* module doesn't support that call, simulate it */
|
||||
return secmod_HandleWaitForSlotEvent(mod, flags, latency);
|
||||
}
|
||||
if (crv != CKR_OK) {
|
||||
/* we can get this error if finalize was called while we were
|
||||
* still running. This is the only way to force a C_WaitForSlotEvent()
|
||||
* to return in PKCS #11. In this case, just return that there
|
||||
* was no event. */
|
||||
if (crv == CKR_CRYPTOKI_NOT_INITIALIZED) {
|
||||
PORT_SetError(SEC_ERROR_NO_EVENT);
|
||||
} else {
|
||||
PORT_SetError(PK11_MapError(crv));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
slot = SECMOD_FindSlotByID(mod, id);
|
||||
if (slot == NULL) {
|
||||
/* possibly a new slot that was added? */
|
||||
SECMOD_UpdateSlotList(mod);
|
||||
slot = SECMOD_FindSlotByID(mod, id);
|
||||
}
|
||||
return slot;
|
||||
|
||||
/* must be called with the lock on. */
|
||||
end_wait:
|
||||
mod->evControlMask &= ~SECMOD_END_WAIT;
|
||||
PZ_Unlock(mod->refLock);
|
||||
PORT_SetError(SEC_ERROR_NO_EVENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function "wakes up" WaitForAnyTokenEvent. It's a pretty drastic
|
||||
* function, possibly bringing down the pkcs #11 module in question. This
|
||||
* should be OK because 1) it does reinitialize, and 2) it should only be
|
||||
* called when we are on our way to tear the whole system down anyway.
|
||||
*/
|
||||
SECStatus
|
||||
SECMOD_CancelWait(SECMODModule *mod)
|
||||
{
|
||||
unsigned long controlMask = mod->evControlMask;
|
||||
SECStatus rv = SECSuccess;
|
||||
CK_RV crv;
|
||||
|
||||
PZ_Lock(mod->refLock);
|
||||
mod->evControlMask |= SECMOD_END_WAIT;
|
||||
controlMask = mod->evControlMask;
|
||||
if (controlMask & SECMOD_WAIT_PKCS11_EVENT) {
|
||||
/* NOTE: this call will drop all transient keys, in progress
|
||||
* operations, and any authentication. This is the only documented
|
||||
* way to get WaitForSlotEvent to return. Also note: for non-thread
|
||||
* safe tokens, we need to hold the module lock, this is not yet at
|
||||
* system shutdown/starup time, so we need to protect these calls */
|
||||
crv = PK11_GETTAB(mod)->C_Finalize(NULL);
|
||||
/* ok, we slammed the module down, now we need to reinit it in case
|
||||
* we intend to use it again */
|
||||
if (crv = CKR_OK) {
|
||||
secmod_ModuleInit(mod);
|
||||
} else {
|
||||
/* Finalized failed for some reason, notify the application
|
||||
* so maybe it has a prayer of recovering... */
|
||||
PORT_SetError(PK11_MapError(crv));
|
||||
rv = SECFailure;
|
||||
}
|
||||
} else if (controlMask & SECMOD_WAIT_SIMULATED_EVENT) {
|
||||
mod->evControlMask &= ~SECMOD_WAIT_SIMULATED_EVENT;
|
||||
/* Simulated events will eventually timeout
|
||||
* and wake up in the loop */
|
||||
}
|
||||
PZ_Unlock(mod->refLock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* check to see if the module has removable slots that we may need to
|
||||
* watch for.
|
||||
*/
|
||||
PRBool
|
||||
SECMOD_HasRemovableSlots(SECMODModule *mod)
|
||||
{
|
||||
int i;
|
||||
PRBool ret = PR_FALSE;
|
||||
|
||||
SECMOD_GetReadLock(moduleLock);
|
||||
for (i=0; i < mod->slotCount; i++) {
|
||||
PK11SlotInfo *slot = mod->slots[i];
|
||||
/* perm modules are not inserted or removed */
|
||||
if (slot->isPerm) {
|
||||
continue;
|
||||
}
|
||||
ret = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#define _SEDMOD_H_
|
||||
#include "seccomon.h"
|
||||
#include "secmodt.h"
|
||||
#include "prinrval.h"
|
||||
|
||||
#define PKCS11_USE_THREADS
|
||||
|
||||
|
@ -148,6 +149,25 @@ PRBool SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags );
|
|||
extern unsigned long SECMOD_PubMechFlagstoInternal(unsigned long publicFlags);
|
||||
extern unsigned long SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags);
|
||||
|
||||
PRBool SECMOD_HasRemovableSlots(SECMODModule *mod);
|
||||
PK11SlotInfo *SECMOD_WaitForAnyTokenEvent(SECMODModule *mod,
|
||||
unsigned long flags, PRIntervalTime latency);
|
||||
/*
|
||||
* Warning: the SECMOD_CancelWait function is highly destructive, potentially
|
||||
* finalizing the module 'mod' (causing inprogress operations to fail,
|
||||
* and session key material to disappear). It should only be called when
|
||||
* shutting down the module.
|
||||
*/
|
||||
SECStatus SECMOD_CancelWait(SECMODModule *mod);
|
||||
/*
|
||||
* check to see if the module has added new slots. PKCS 11 v2.20 allows for
|
||||
* modules to add new slots, but never remove them. Slots not be added between
|
||||
* a call to C_GetSlotLlist(Flag, NULL, &count) and the corresponding
|
||||
* C_GetSlotList(flag, &data, &count) so that the array doesn't accidently
|
||||
* grow on the caller. It is permissible for the slots to increase between
|
||||
* corresponding calls with NULL to get the size.
|
||||
*/
|
||||
SECStatus SECMOD_UpdateSlotList(SECMODModule *mod);
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,6 +65,7 @@ void nss_DumpModuleLog(void);
|
|||
extern int secmod_PrivateModuleCount;
|
||||
|
||||
extern void SECMOD_Init(void);
|
||||
SECStatus secmod_ModuleInit(SECMODModule *mod);
|
||||
|
||||
/* list managment */
|
||||
extern SECStatus SECMOD_AddModuleToList(SECMODModule *newModule);
|
||||
|
|
|
@ -93,8 +93,26 @@ struct SECMODModuleStr {
|
|||
PRBool moduleDBOnly; /* this module only has lists of PKCS #11 modules */
|
||||
int trustOrder; /* order for this module's certificate trust rollup */
|
||||
int cipherOrder; /* order for cipher operations */
|
||||
unsigned long evControlMask; /* control the running and shutdown of slot
|
||||
* events (SECMOD_WaitForAnyTokenEvent) */
|
||||
};
|
||||
|
||||
/* evControlMask flags */
|
||||
/*
|
||||
* These bits tell the current state of a SECMOD_WaitForAnyTokenEvent.
|
||||
*
|
||||
* SECMOD_WAIT_PKCS11_EVENT - we're waiting in the PKCS #11 module in
|
||||
* C_WaitForSlotEvent().
|
||||
* SECMOD_WAIT_SIMULATED_EVENT - we're waiting in the NSS simulation code
|
||||
* which polls for token insertion and removal events.
|
||||
* SECMOD_END_WAIT - SECMOD_CancelWait has been called while the module is
|
||||
* waiting in SECMOD_WaitForAnyTokenEvent. SECMOD_WaitForAnyTokenEvent
|
||||
* should return immediately to it's caller.
|
||||
*/
|
||||
#define SECMOD_END_WAIT 0x01
|
||||
#define SECMOD_WAIT_SIMULATED_EVENT 0x02
|
||||
#define SECMOD_WAIT_PKCS11_EVENT 0x04
|
||||
|
||||
struct SECMODModuleListStr {
|
||||
SECMODModuleList *next;
|
||||
SECMODModule *module;
|
||||
|
|
|
@ -122,6 +122,10 @@ struct PK11SlotInfoStr {
|
|||
uint16 series; /* break up the slot info into various groups of
|
||||
* inserted tokens so that keys and certs can be
|
||||
* invalidated */
|
||||
uint16 flagSeries; /* record the last series for the last event
|
||||
* returned for this slot */
|
||||
PRBool flagState; /* record the state of the last event returned for this
|
||||
* slot. */
|
||||
uint16 wrapKey; /* current wrapping key for SSL master secrets */
|
||||
CK_MECHANISM_TYPE wrapMechanism;
|
||||
/* current wrapping mechanism for current wrapKey */
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.82 $ $Date: 2004-07-21 18:18:05 $ $Name: $";
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.83 $ $Date: 2004-07-29 23:38:14 $ $Name: $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
|
@ -93,13 +93,40 @@ STAN_GetDefaultCryptoContext()
|
|||
extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
|
||||
extern const NSSError NSS_ERROR_INTERNAL_ERROR;
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot)
|
||||
{
|
||||
NSSToken *token;
|
||||
if (!td) {
|
||||
td = g_default_trust_domain;
|
||||
}
|
||||
token = nssToken_CreateFromPK11SlotInfo(td, slot);
|
||||
PK11Slot_SetNSSToken(slot, token);
|
||||
NSSRWLock_LockWrite(td->tokensLock);
|
||||
nssList_Add(td->tokenList, token);
|
||||
NSSRWLock_UnlockWrite(td->tokensLock);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
STAN_ResetTokenInterator(NSSTrustDomain *td)
|
||||
{
|
||||
if (!td) {
|
||||
td = g_default_trust_domain;
|
||||
}
|
||||
NSSRWLock_LockWrite(td->tokensLock);
|
||||
nssListIterator_Destroy(td->tokens);
|
||||
td->tokens = nssList_CreateIterator(td->tokenList);
|
||||
NSSRWLock_UnlockWrite(td->tokensLock);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
STAN_LoadDefaultNSS3TrustDomain (
|
||||
void
|
||||
)
|
||||
{
|
||||
NSSTrustDomain *td;
|
||||
NSSToken *token;
|
||||
SECMODModuleList *mlp;
|
||||
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
|
||||
int i;
|
||||
|
@ -113,41 +140,48 @@ STAN_LoadDefaultNSS3TrustDomain (
|
|||
if (!td) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
td->tokenList = nssList_Create(td->arena, PR_TRUE);
|
||||
/*
|
||||
* Deadlock warning: we should never acquire the moduleLock while
|
||||
* we hold the tokensLock. We can use the NSSRWLock Rank feature to
|
||||
* guarrentee this. tokensLock have a higher rank than module lock.
|
||||
*/
|
||||
SECMOD_GetReadLock(moduleLock);
|
||||
NSSRWLock_LockWrite(td->tokensLock);
|
||||
td->tokenList = nssList_Create(td->arena, PR_TRUE);
|
||||
for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp=mlp->next) {
|
||||
for (i=0; i < mlp->module->slotCount; i++) {
|
||||
token = nssToken_CreateFromPK11SlotInfo(td, mlp->module->slots[i]);
|
||||
PK11Slot_SetNSSToken(mlp->module->slots[i], token);
|
||||
nssList_Add(td->tokenList, token);
|
||||
STAN_InitTokenForSlotInfo(td, mlp->module->slots[i]);
|
||||
}
|
||||
}
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
td->tokens = nssList_CreateIterator(td->tokenList);
|
||||
NSSRWLock_UnlockWrite(td->tokensLock);
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
g_default_trust_domain = td;
|
||||
g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* must be called holding the ModuleListLock (either read or write).
|
||||
*/
|
||||
NSS_IMPLEMENT SECStatus
|
||||
STAN_AddModuleToDefaultTrustDomain (
|
||||
SECMODModule *module
|
||||
)
|
||||
{
|
||||
NSSToken *token;
|
||||
NSSTrustDomain *td;
|
||||
int i;
|
||||
td = STAN_GetDefaultTrustDomain();
|
||||
for (i=0; i<module->slotCount; i++) {
|
||||
token = nssToken_CreateFromPK11SlotInfo(td, module->slots[i]);
|
||||
PK11Slot_SetNSSToken(module->slots[i], token);
|
||||
nssList_Add(td->tokenList, token);
|
||||
STAN_InitTokenForSlotInfo(td, module->slots[i]);
|
||||
}
|
||||
nssListIterator_Destroy(td->tokens);
|
||||
td->tokens = nssList_CreateIterator(td->tokenList);
|
||||
STAN_ResetTokenInterator(td);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* must be called holding the ModuleListLock (either read or write).
|
||||
*/
|
||||
NSS_IMPLEMENT SECStatus
|
||||
STAN_RemoveModuleFromDefaultTrustDomain (
|
||||
SECMODModule *module
|
||||
|
@ -157,6 +191,7 @@ STAN_RemoveModuleFromDefaultTrustDomain (
|
|||
NSSTrustDomain *td;
|
||||
int i;
|
||||
td = STAN_GetDefaultTrustDomain();
|
||||
NSSRWLock_LockWrite(td->tokensLock);
|
||||
for (i=0; i<module->slotCount; i++) {
|
||||
token = PK11Slot_GetNSSToken(module->slots[i]);
|
||||
if (token) {
|
||||
|
@ -168,6 +203,7 @@ STAN_RemoveModuleFromDefaultTrustDomain (
|
|||
}
|
||||
nssListIterator_Destroy(td->tokens);
|
||||
td->tokens = nssList_CreateIterator(td->tokenList);
|
||||
NSSRWLock_UnlockWrite(td->tokensLock);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
@ -1015,9 +1051,11 @@ STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
|
|||
tok = stan_GetTrustToken(c);
|
||||
moving_object = PR_FALSE;
|
||||
if (tok && PK11_IsReadOnly(tok->pk11slot)) {
|
||||
NSSRWLock_LockRead(td->tokensLock);
|
||||
tokens = nssList_CreateIterator(td->tokenList);
|
||||
if (!tokens) {
|
||||
nssrv = PR_FAILURE;
|
||||
NSSRWLock_UnlockRead(td->tokensLock);
|
||||
goto done;
|
||||
}
|
||||
for (tok = (NSSToken *)nssListIterator_Start(tokens);
|
||||
|
@ -1028,6 +1066,7 @@ STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
|
|||
}
|
||||
nssListIterator_Finish(tokens);
|
||||
nssListIterator_Destroy(tokens);
|
||||
NSSRWLock_UnlockRead(td->tokensLock);
|
||||
moving_object = PR_TRUE;
|
||||
}
|
||||
if (tok) {
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#define PKINSS3HACK_H
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char PKINSS3HACK_CVS_ID[] = "@(#) $RCSfile: pki3hack.h,v $ $Revision: 1.17 $ $Date: 2004-07-21 18:18:05 $ $Name: $";
|
||||
static const char PKINSS3HACK_CVS_ID[] = "@(#) $RCSfile: pki3hack.h,v $ $Revision: 1.18 $ $Date: 2004-07-29 23:38:14 $ $Name: $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef NSSDEVT_H
|
||||
|
@ -74,25 +74,22 @@ NSS_EXTERN NSSCryptoContext *
|
|||
STAN_GetDefaultCryptoContext();
|
||||
|
||||
NSS_EXTERN PRStatus
|
||||
STAN_LoadDefaultNSS3TrustDomain
|
||||
(
|
||||
void
|
||||
);
|
||||
STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot);
|
||||
|
||||
NSS_EXTERN PRStatus
|
||||
STAN_ResetTokenInterator(NSSTrustDomain *td);
|
||||
|
||||
NSS_EXTERN PRStatus
|
||||
STAN_LoadDefaultNSS3TrustDomain(void);
|
||||
|
||||
NSS_EXTERN PRStatus
|
||||
STAN_Shutdown();
|
||||
|
||||
NSS_EXTERN SECStatus
|
||||
STAN_AddModuleToDefaultTrustDomain
|
||||
(
|
||||
SECMODModule *module
|
||||
);
|
||||
STAN_AddModuleToDefaultTrustDomain(SECMODModule *module);
|
||||
|
||||
NSS_EXTERN SECStatus
|
||||
STAN_RemoveModuleFromDefaultTrustDomain
|
||||
(
|
||||
SECMODModule *module
|
||||
);
|
||||
STAN_RemoveModuleFromDefaultTrustDomain(SECMODModule *module);
|
||||
|
||||
NSS_EXTERN CERTCertificate *
|
||||
STAN_ForceCERTCertificateUpdate(NSSCertificate *c);
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#define PKIT_H
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char PKIT_CVS_ID[] = "@(#) $RCSfile: pkit.h,v $ $Revision: 1.15 $ $Date: 2004-05-17 20:08:37 $ $Name: $";
|
||||
static const char PKIT_CVS_ID[] = "@(#) $RCSfile: pkit.h,v $ $Revision: 1.16 $ $Date: 2004-07-29 23:38:14 $ $Name: $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
|
@ -72,6 +72,10 @@ static const char PKIT_CVS_ID[] = "@(#) $RCSfile: pkit.h,v $ $Revision: 1.15 $ $
|
|||
#include "devt.h"
|
||||
#endif /* DEVT_H */
|
||||
|
||||
#ifndef nssrwlkt_h__
|
||||
#include "nssrwlkt.h"
|
||||
#endif /* nssrwlkt_h__ */
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
|
@ -174,6 +178,7 @@ struct NSSTrustDomainStr {
|
|||
nssList *tokenList;
|
||||
nssListIterator *tokens;
|
||||
nssTDCertificateCache *cache;
|
||||
NSSRWLock *tokensLock;
|
||||
#ifdef NSS_3_4_CODE
|
||||
void *spkDigestInfo;
|
||||
CERTStatusConfig *statusConfig;
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: trustdomain.c,v $ $Revision: 1.49 $ $Date: 2004-04-25 15:03:14 $ $Name: $";
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: trustdomain.c,v $ $Revision: 1.50 $ $Date: 2004-07-29 23:38:14 $ $Name: $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef DEV_H
|
||||
|
@ -55,6 +55,8 @@ static const char CVS_ID[] = "@(#) $RCSfile: trustdomain.c,v $ $Revision: 1.49 $
|
|||
#include "pki3hack.h"
|
||||
#endif
|
||||
|
||||
#include "nssrwlk.h"
|
||||
|
||||
#define NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE 32
|
||||
|
||||
#ifdef PURE_STAN_BUILD
|
||||
|
@ -93,6 +95,11 @@ NSSTrustDomain_Create (
|
|||
if (!rvTD) {
|
||||
goto loser;
|
||||
}
|
||||
/* protect the token list and the token iterator */
|
||||
rvTD->tokensLock = NSSRWLock_New(100, "tokens");
|
||||
if (!rvTD->tokensLock) {
|
||||
goto loser;
|
||||
}
|
||||
nssTrustDomain_InitializeCache(rvTD, NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE);
|
||||
rvTD->arena = arena;
|
||||
rvTD->refCount = 1;
|
||||
|
@ -101,6 +108,9 @@ NSSTrustDomain_Create (
|
|||
#endif
|
||||
return rvTD;
|
||||
loser:
|
||||
if (rvTD && rvTD->tokensLock) {
|
||||
NSSRWLock_Destroy(rvTD->tokensLock);
|
||||
}
|
||||
nssArena_Destroy(arena);
|
||||
return (NSSTrustDomain *)NULL;
|
||||
}
|
||||
|
@ -127,6 +137,7 @@ NSSTrustDomain_Destroy (
|
|||
nssList_Clear(td->tokenList, token_destructor);
|
||||
nssList_Destroy(td->tokenList);
|
||||
}
|
||||
NSSRWLock_Destroy(td->tokensLock);
|
||||
status = nssTrustDomain_DestroyCache(td);
|
||||
if (status == PR_FAILURE) {
|
||||
return status;
|
||||
|
@ -148,17 +159,21 @@ nssTrustDomain_GetActiveSlots (
|
|||
NSSSlot **slots = NULL;
|
||||
NSSToken **tp, **tokens;
|
||||
*updateLevel = 1;
|
||||
NSSRWLock_LockRead(td->tokensLock);
|
||||
count = nssList_Count(td->tokenList);
|
||||
tokens = nss_ZNEWARRAY(NULL, NSSToken *, count + 1);
|
||||
if (!tokens) {
|
||||
NSSRWLock_UnlockRead(td->tokensLock);
|
||||
return NULL;
|
||||
}
|
||||
slots = nss_ZNEWARRAY(NULL, NSSSlot *, count + 1);
|
||||
if (!slots) {
|
||||
NSSRWLock_UnlockRead(td->tokensLock);
|
||||
nss_ZFreeIf(tokens);
|
||||
return NULL;
|
||||
}
|
||||
nssList_GetArray(td->tokenList, (void **)tokens, count);
|
||||
NSSRWLock_UnlockRead(td->tokensLock);
|
||||
count = 0;
|
||||
for (tp = tokens; *tp; tp++) {
|
||||
slots[count++] = nssToken_GetSlot(*tp);
|
||||
|
@ -275,6 +290,7 @@ NSSTrustDomain_FindTokenByName (
|
|||
PRStatus nssrv;
|
||||
NSSUTF8 *myName;
|
||||
NSSToken *tok = NULL;
|
||||
NSSRWLock_LockRead(td->tokensLock);
|
||||
for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
|
||||
tok != (NSSToken *)NULL;
|
||||
tok = (NSSToken *)nssListIterator_Next(td->tokens))
|
||||
|
@ -285,6 +301,7 @@ NSSTrustDomain_FindTokenByName (
|
|||
}
|
||||
}
|
||||
nssListIterator_Finish(td->tokens);
|
||||
NSSRWLock_UnlockRead(td->tokensLock);
|
||||
return tok;
|
||||
}
|
||||
|
||||
|
|
|
@ -200,7 +200,9 @@ SEC_ERROR_REVOKED_CERTIFICATE_OCSP = (SEC_ERROR_BASE + 146),
|
|||
SEC_ERROR_CRL_INVALID_VERSION = (SEC_ERROR_BASE + 147),
|
||||
SEC_ERROR_CRL_V1_CRITICAL_EXTENSION = (SEC_ERROR_BASE + 148),
|
||||
SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION = (SEC_ERROR_BASE + 149),
|
||||
SEC_ERROR_UNKNOWN_OBJECT_TYPE = (SEC_ERROR_BASE + 150)
|
||||
SEC_ERROR_UNKNOWN_OBJECT_TYPE = (SEC_ERROR_BASE + 150),
|
||||
SEC_ERROR_INCOMPATIBLE_PKCS11 = (SEC_ERROR_BASE + 151),
|
||||
SEC_ERROR_NO_EVENT = (SEC_ERROR_BASE + 152)
|
||||
|
||||
} SECErrorCodes;
|
||||
#endif /* NO_SECURITY_ERROR_ENUM */
|
||||
|
|
Загрузка…
Ссылка в новой задаче