1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
* Initialize the PCKS 11 subsystem
18
/* these are for displaying error messages */
20
static SECMODModuleList *modules = NULL;
21
static SECMODModuleList *modulesDB = NULL;
22
static SECMODModuleList *modulesUnload = NULL;
23
static SECMODModule *internalModule = NULL;
24
static SECMODModule *defaultDBModule = NULL;
25
static SECMODModule *pendingModule = NULL;
26
static SECMODListLock *moduleLock = NULL;
28
int secmod_PrivateModuleCount = 0;
30
extern PK11DefaultArrayEntry PK11_DefaultArray[];
31
extern int num_pk11_default_mechanisms;
37
/* don't initialize twice */
38
if (moduleLock) return;
40
moduleLock = SECMOD_NewListLock();
48
/* destroy the lock */
50
SECMOD_DestroyListLock(moduleLock);
53
/* free the internal module */
55
SECMOD_DestroyModule(internalModule);
56
internalModule = NULL;
59
/* free the default database module */
60
if (defaultDBModule) {
61
SECMOD_DestroyModule(defaultDBModule);
62
defaultDBModule = NULL;
65
/* destroy the list */
67
SECMOD_DestroyModuleList(modules);
72
SECMOD_DestroyModuleList(modulesDB);
77
SECMOD_DestroyModuleList(modulesUnload);
81
/* make all the slots and the lists go away */
82
PK11_DestroySlotLists();
87
if (PR_GetEnv("NSS_STRICT_SHUTDOWN")) {
88
PORT_Assert(secmod_PrivateModuleCount == 0);
91
if (secmod_PrivateModuleCount) {
92
PORT_SetError(SEC_ERROR_BUSY);
100
* retrieve the internal module
103
SECMOD_GetInternalModule(void)
105
return internalModule;
110
secmod_AddModuleToList(SECMODModuleList **moduleList,SECMODModule *newModule)
112
SECMODModuleList *mlp, *newListElement, *last = NULL;
114
newListElement = SECMOD_NewModuleListElement();
115
if (newListElement == NULL) {
119
newListElement->module = SECMOD_ReferenceModule(newModule);
121
SECMOD_GetWriteLock(moduleLock);
122
/* Added it to the end (This is very inefficient, but Adding a module
123
* on the fly should happen maybe 2-3 times through the life this program
124
* on a given computer, and this list should be *SHORT*. */
125
for(mlp = *moduleList; mlp != NULL; mlp = mlp->next) {
130
*moduleList = newListElement;
132
SECMOD_AddList(last,newListElement,NULL);
134
SECMOD_ReleaseWriteLock(moduleLock);
139
SECMOD_AddModuleToList(SECMODModule *newModule)
141
if (newModule->internal && !internalModule) {
142
internalModule = SECMOD_ReferenceModule(newModule);
144
return secmod_AddModuleToList(&modules,newModule);
148
SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule)
150
if (defaultDBModule && SECMOD_GetDefaultModDBFlag(newModule)) {
151
SECMOD_DestroyModule(defaultDBModule);
152
defaultDBModule = SECMOD_ReferenceModule(newModule);
153
} else if (defaultDBModule == NULL) {
154
defaultDBModule = SECMOD_ReferenceModule(newModule);
156
return secmod_AddModuleToList(&modulesDB,newModule);
160
SECMOD_AddModuleToUnloadList(SECMODModule *newModule)
162
return secmod_AddModuleToList(&modulesUnload,newModule);
166
* get the list of PKCS11 modules that are available.
168
SECMODModuleList * SECMOD_GetDefaultModuleList() { return modules; }
169
SECMODModuleList *SECMOD_GetDeadModuleList() { return modulesUnload; }
170
SECMODModuleList *SECMOD_GetDBModuleList() { return modulesDB; }
173
* This lock protects the global module lists.
174
* it also protects changes to the slot array (module->slots[]) and slot count
175
* (module->slotCount) in each module. It is a read/write lock with multiple
176
* readers or one writer. Writes are uncommon.
177
* Because of legacy considerations protection of the slot array and count is
178
* only necessary in applications if the application calls
179
* SECMOD_UpdateSlotList() or SECMOD_WaitForAnyTokenEvent(), though all new
180
* applications are encouraged to acquire this lock when reading the
181
* slot array information directly.
183
SECMODListLock *SECMOD_GetDefaultModuleListLock() { return moduleLock; }
188
* find a module by name, and add a reference to it.
189
* return that module.
192
SECMOD_FindModule(const char *name)
194
SECMODModuleList *mlp;
195
SECMODModule *module = NULL;
198
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
201
SECMOD_GetReadLock(moduleLock);
202
for(mlp = modules; mlp != NULL; mlp = mlp->next) {
203
if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
204
module = mlp->module;
205
SECMOD_ReferenceModule(module);
212
for(mlp = modulesUnload; mlp != NULL; mlp = mlp->next) {
213
if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
214
module = mlp->module;
215
SECMOD_ReferenceModule(module);
221
SECMOD_ReleaseReadLock(moduleLock);
227
* find a module by ID, and add a reference to it.
228
* return that module.
231
SECMOD_FindModuleByID(SECMODModuleID id)
233
SECMODModuleList *mlp;
234
SECMODModule *module = NULL;
237
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
240
SECMOD_GetReadLock(moduleLock);
241
for(mlp = modules; mlp != NULL; mlp = mlp->next) {
242
if (id == mlp->module->moduleID) {
243
module = mlp->module;
244
SECMOD_ReferenceModule(module);
248
SECMOD_ReleaseReadLock(moduleLock);
249
if (module == NULL) {
250
PORT_SetError(SEC_ERROR_NO_MODULE);
256
* find the function pointer.
259
secmod_FindModuleByFuncPtr(void *funcPtr)
261
SECMODModuleList *mlp;
262
SECMODModule *module = NULL;
264
SECMOD_GetReadLock(moduleLock);
265
for(mlp = modules; mlp != NULL; mlp = mlp->next) {
266
/* paranoia, shouldn't ever happen */
270
if (funcPtr == mlp->module->functionList) {
271
module = mlp->module;
272
SECMOD_ReferenceModule(module);
276
SECMOD_ReleaseReadLock(moduleLock);
277
if (module == NULL) {
278
PORT_SetError(SEC_ERROR_NO_MODULE);
284
* Find the Slot based on ID and the module.
287
SECMOD_FindSlotByID(SECMODModule *module, CK_SLOT_ID slotID)
290
PK11SlotInfo *slot = NULL;
293
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
296
SECMOD_GetReadLock(moduleLock);
297
for (i=0; i < module->slotCount; i++) {
298
PK11SlotInfo *cSlot = module->slots[i];
300
if (cSlot->slotID == slotID) {
301
slot = PK11_ReferenceSlot(cSlot);
305
SECMOD_ReleaseReadLock(moduleLock);
308
PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
314
* lookup the Slot module based on it's module ID and slot ID.
317
SECMOD_LookupSlot(SECMODModuleID moduleID,CK_SLOT_ID slotID)
319
SECMODModule *module;
322
module = SECMOD_FindModuleByID(moduleID);
323
if (module == NULL) return NULL;
325
slot = SECMOD_FindSlotByID(module, slotID);
326
SECMOD_DestroyModule(module);
332
* find a module by name or module pointer and delete it off the module list.
333
* optionally remove it from secmod.db.
336
SECMOD_DeleteModuleEx(const char *name, SECMODModule *mod,
337
int *type, PRBool permdb)
339
SECMODModuleList *mlp;
340
SECMODModuleList **mlpp;
341
SECStatus rv = SECFailure;
344
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
348
*type = SECMOD_EXTERNAL;
350
SECMOD_GetWriteLock(moduleLock);
351
for (mlpp = &modules,mlp = modules;
352
mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
353
if ((name && (PORT_Strcmp(name,mlp->module->commonName) == 0)) ||
354
mod == mlp->module) {
355
/* don't delete the internal module */
356
if (!mlp->module->internal) {
357
SECMOD_RemoveList(mlpp,mlp);
358
/* delete it after we release the lock */
359
rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module);
360
} else if (mlp->module->isFIPS) {
363
*type = SECMOD_INTERNAL;
371
/* not on the internal list, check the unload list */
372
for (mlpp = &modulesUnload,mlp = modulesUnload;
373
mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
374
if ((name && (PORT_Strcmp(name,mlp->module->commonName) == 0)) ||
375
mod == mlp->module) {
376
/* don't delete the internal module */
377
if (!mlp->module->internal) {
378
SECMOD_RemoveList(mlpp,mlp);
380
} else if (mlp->module->isFIPS) {
383
*type = SECMOD_INTERNAL;
389
SECMOD_ReleaseWriteLock(moduleLock);
392
if (rv == SECSuccess) {
394
SECMOD_DeletePermDB(mlp->module);
396
SECMOD_DestroyModuleListElement(mlp);
402
* find a module by name and delete it off the module list
405
SECMOD_DeleteModule(const char *name, int *type)
407
return SECMOD_DeleteModuleEx(name, NULL, type, PR_TRUE);
411
* find a module by name and delete it off the module list
414
SECMOD_DeleteInternalModule(const char *name)
416
SECMODModuleList *mlp;
417
SECMODModuleList **mlpp;
418
SECStatus rv = SECFailure;
421
PORT_SetError(SEC_ERROR_MODULE_STUCK);
425
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
429
SECMOD_GetWriteLock(moduleLock);
430
for(mlpp = &modules,mlp = modules;
431
mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
432
if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
433
/* don't delete the internal module */
434
if (mlp->module->internal) {
435
SECMOD_RemoveList(mlpp,mlp);
436
rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module);
441
SECMOD_ReleaseWriteLock(moduleLock);
443
if (rv == SECSuccess) {
444
SECMODModule *newModule,*oldModule;
446
if (mlp->module->isFIPS) {
447
newModule = SECMOD_CreateModule(NULL, SECMOD_INT_NAME,
448
NULL, SECMOD_INT_FLAGS);
450
newModule = SECMOD_CreateModule(NULL, SECMOD_FIPS_NAME,
451
NULL, SECMOD_FIPS_FLAGS);
455
newModule->libraryParams =
456
PORT_ArenaStrdup(newModule->arena,mlp->module->libraryParams);
457
/* if an explicit internal key slot has been set, reset it */
458
slot = pk11_SwapInternalKeySlot(NULL);
460
secmod_SetInternalKeySlotFlag(newModule, PR_TRUE);
462
rv = SECMOD_AddModule(newModule);
463
if (rv != SECSuccess) {
464
/* load failed, restore the internal key slot */
465
pk11_SetInternalKeySlot(slot);
466
SECMOD_DestroyModule(newModule);
469
/* free the old explicit internal key slot, we now have a new one */
474
if (newModule == NULL) {
475
SECMODModuleList *last = NULL,*mlp2;
476
/* we're in pretty deep trouble if this happens...Security
477
* not going to work well... try to put the old module back on
479
SECMOD_GetWriteLock(moduleLock);
480
for(mlp2 = modules; mlp2 != NULL; mlp2 = mlp->next) {
487
SECMOD_AddList(last,mlp,NULL);
489
SECMOD_ReleaseWriteLock(moduleLock);
492
pendingModule = oldModule = internalModule;
493
internalModule = NULL;
494
SECMOD_DestroyModule(oldModule);
495
SECMOD_DeletePermDB(mlp->module);
496
SECMOD_DestroyModuleListElement(mlp);
497
internalModule = newModule; /* adopt the module */
503
SECMOD_AddModule(SECMODModule *newModule)
506
SECMODModule *oldModule;
508
/* Test if a module w/ the same name already exists */
509
/* and return SECWouldBlock if so. */
510
/* We should probably add a new return value such as */
511
/* SECDublicateModule, but to minimize ripples, I'll */
512
/* give SECWouldBlock a new meaning */
513
if ((oldModule = SECMOD_FindModule(newModule->commonName)) != NULL) {
514
SECMOD_DestroyModule(oldModule);
515
return SECWouldBlock;
516
/* module already exists. */
519
rv = secmod_LoadPKCS11Module(newModule, NULL);
520
if (rv != SECSuccess) {
524
if (newModule->parent == NULL) {
525
newModule->parent = SECMOD_ReferenceModule(defaultDBModule);
528
SECMOD_AddPermDB(newModule);
529
SECMOD_AddModuleToList(newModule);
531
rv = STAN_AddModuleToDefaultTrustDomain(newModule);
537
SECMOD_FindSlot(SECMODModule *module,const char *name)
541
PK11SlotInfo *retSlot = NULL;
544
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
547
SECMOD_GetReadLock(moduleLock);
548
for (i=0; i < module->slotCount; i++) {
549
PK11SlotInfo *slot = module->slots[i];
551
if (PK11_IsPresent(slot)) {
552
string = PK11_GetTokenName(slot);
554
string = PK11_GetSlotName(slot);
556
if (PORT_Strcmp(name,string) == 0) {
557
retSlot = PK11_ReferenceSlot(slot);
561
SECMOD_ReleaseReadLock(moduleLock);
563
if (retSlot == NULL) {
564
PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
570
PK11_GetModInfo(SECMODModule *mod,CK_INFO *info)
574
if (mod->functionList == NULL) return SECFailure;
575
crv = PK11_GETTAB(mod)->C_GetInfo(info);
577
PORT_SetError(PK11_MapError(crv));
579
return (crv == CKR_OK) ? SECSuccess : SECFailure;
582
/* Determine if we have the FIP's module loaded as the default
583
* module to trigger other bogus FIPS requirements in PKCS #12 and
589
SECMODModule *mod = SECMOD_GetInternalModule();
591
if (mod && mod->internal) {
598
/* combines NewModule() & AddModule */
599
/* give a string for the module name & the full-path for the dll, */
600
/* installs the PKCS11 module & update registry */
602
SECMOD_AddNewModuleEx(const char* moduleName, const char* dllPath,
603
unsigned long defaultMechanismFlags,
604
unsigned long cipherEnableFlags,
605
char* modparms, char* nssparms)
607
SECMODModule *module;
608
SECStatus result = SECFailure;
612
PR_SetErrorText(0, NULL);
614
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
618
module = SECMOD_CreateModule(dllPath, moduleName, modparms, nssparms);
620
if (module == NULL) {
624
if (module->dllName != NULL) {
625
if (module->dllName[0] != 0) {
626
result = SECMOD_AddModule(module);
627
if (result == SECSuccess) {
628
/* turn on SSL cipher enable flags */
629
module->ssl[0] = cipherEnableFlags;
631
SECMOD_GetReadLock(moduleLock);
632
/* check each slot to turn on appropriate mechanisms */
633
for (s = 0; s < module->slotCount; s++) {
634
slot = (module->slots)[s];
635
/* for each possible mechanism */
636
for (i=0; i < num_pk11_default_mechanisms; i++) {
637
/* we are told to turn it on by default ? */
639
(PK11_DefaultArray[i].flag & defaultMechanismFlags) ?
641
result = PK11_UpdateSlotAttribute(slot,
642
&(PK11_DefaultArray[i]), add);
643
} /* for each mechanism */
644
/* disable each slot if the defaultFlags say so */
645
if (defaultMechanismFlags & PK11_DISABLE_FLAG) {
646
PK11_UserDisableSlot(slot);
648
} /* for each slot of this module */
649
SECMOD_ReleaseReadLock(moduleLock);
651
/* delete and re-add module in order to save changes
653
result = SECMOD_UpdateModule(module);
657
SECMOD_DestroyModule(module);
662
SECMOD_AddNewModule(const char* moduleName, const char* dllPath,
663
unsigned long defaultMechanismFlags,
664
unsigned long cipherEnableFlags)
666
return SECMOD_AddNewModuleEx(moduleName, dllPath, defaultMechanismFlags,
668
NULL, NULL); /* don't pass module or nss params */
672
SECMOD_UpdateModule(SECMODModule *module)
676
result = SECMOD_DeletePermDB(module);
678
if (result == SECSuccess) {
679
result = SECMOD_AddPermDB(module);
684
/* Public & Internal(Security Library) representation of
685
* encryption mechanism flags conversion */
687
/* Currently, the only difference is that internal representation
688
* puts RANDOM_FLAG at bit 31 (Most-significant bit), but
689
* public representation puts this bit at bit 28
692
SECMOD_PubMechFlagstoInternal(unsigned long publicFlags)
694
unsigned long internalFlags = publicFlags;
696
if (publicFlags & PUBLIC_MECH_RANDOM_FLAG) {
697
internalFlags &= ~PUBLIC_MECH_RANDOM_FLAG;
698
internalFlags |= SECMOD_RANDOM_FLAG;
700
return internalFlags;
704
SECMOD_InternaltoPubMechFlags(unsigned long internalFlags)
706
unsigned long publicFlags = internalFlags;
708
if (internalFlags & SECMOD_RANDOM_FLAG) {
709
publicFlags &= ~SECMOD_RANDOM_FLAG;
710
publicFlags |= PUBLIC_MECH_RANDOM_FLAG;
716
/* Public & Internal(Security Library) representation of */
717
/* cipher flags conversion */
718
/* Note: currently they are just stubs */
720
SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags)
726
SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags)
728
return internalFlags;
731
/* Funtion reports true if module of modType is installed/configured */
733
SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags )
735
PRBool result = PR_FALSE;
736
SECMODModuleList *mods;
739
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
742
SECMOD_GetReadLock(moduleLock);
743
mods = SECMOD_GetDefaultModuleList();
744
for ( ; mods != NULL; mods = mods->next) {
745
if (mods->module->ssl[0] &
746
SECMOD_PubCipherFlagstoInternal(pubCipherEnableFlags)) {
751
SECMOD_ReleaseReadLock(moduleLock);
755
/* create a new ModuleListElement */
756
SECMODModuleList *SECMOD_NewModuleListElement(void)
758
SECMODModuleList *newModList;
760
newModList= (SECMODModuleList *) PORT_Alloc(sizeof(SECMODModuleList));
762
newModList->next = NULL;
763
newModList->module = NULL;
769
* make a new reference to a module so It doesn't go away on us
772
SECMOD_ReferenceModule(SECMODModule *module)
774
PZ_Lock(module->refLock);
775
PORT_Assert(module->refCount > 0);
778
PZ_Unlock(module->refLock);
783
/* destroy an existing module */
785
SECMOD_DestroyModule(SECMODModule *module)
787
PRBool willfree = PR_FALSE;
791
PZ_Lock(module->refLock);
792
if (module->refCount-- == 1) {
795
PORT_Assert(willfree || (module->refCount > 0));
796
PZ_Unlock(module->refLock);
802
if (module->parent != NULL) {
803
SECMODModule *parent = module->parent;
804
/* paranoia, don't loop forever if the modules are looped */
805
module->parent = NULL;
806
SECMOD_DestroyModule(parent);
809
/* slots can't really disappear until our module starts freeing them,
810
* so this check is safe */
811
slotCount = module->slotCount;
812
if (slotCount == 0) {
813
SECMOD_SlotDestroyModule(module,PR_FALSE);
817
/* now free all out slots, when they are done, they will cause the
818
* module to disappear altogether */
819
for (i=0 ; i < slotCount; i++) {
820
if (!module->slots[i]->disabled) {
821
PK11_ClearSlotList(module->slots[i]);
823
PK11_FreeSlot(module->slots[i]);
825
/* WARNING: once the last slot has been freed is it possible (even likely)
826
* that module is no more... touching it now is a good way to go south */
830
/* we can only get here if we've destroyed the module, or some one has
831
* erroneously freed a slot that wasn't referenced. */
833
SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot)
835
PRBool willfree = PR_FALSE;
837
PORT_Assert(module->refCount == 0);
838
PZ_Lock(module->refLock);
839
if (module->slotCount-- == 1) {
842
PORT_Assert(willfree || (module->slotCount > 0));
843
PZ_Unlock(module->refLock);
844
if (!willfree) return;
847
if (module == pendingModule) {
848
pendingModule = NULL;
851
if (module->loaded) {
852
SECMOD_UnloadModule(module);
854
PZ_DestroyLock(module->refLock);
855
PORT_FreeArena(module->arena,PR_FALSE);
856
secmod_PrivateModuleCount--;
859
/* destroy a list element
860
* this destroys a single element, and returns the next element
861
* on the chain. It makes it easy to implement for loops to delete
862
* the chain. It also make deleting a single element easy */
864
SECMOD_DestroyModuleListElement(SECMODModuleList *element)
866
SECMODModuleList *next = element->next;
868
if (element->module) {
869
SECMOD_DestroyModule(element->module);
870
element->module = NULL;
878
* Destroy an entire module list
881
SECMOD_DestroyModuleList(SECMODModuleList *list)
883
SECMODModuleList *lp;
885
for ( lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) ;
889
SECMOD_CanDeleteInternalModule(void)
891
return (PRBool) (pendingModule == NULL);
895
* check to see if the module has added new slots. PKCS 11 v2.20 allows for
896
* modules to add new slots, but never remove them. Slots cannot be added
897
* between a call to C_GetSlotLlist(Flag, NULL, &count) and the subsequent
898
* C_GetSlotList(flag, &data, &count) so that the array doesn't accidently
899
* grow on the caller. It is permissible for the slots to increase between
900
* successive calls with NULL to get the size.
903
SECMOD_UpdateSlotList(SECMODModule *mod)
907
CK_ULONG i, oldCount;
908
PRBool freeRef = PR_FALSE;
910
CK_ULONG *slotIDs = NULL;
911
PK11SlotInfo **newSlots = NULL;
912
PK11SlotInfo **oldSlots = NULL;
915
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
919
/* C_GetSlotList is not a session function, make sure
920
* calls are serialized */
921
PZ_Lock(mod->refLock);
923
/* see if the number of slots have changed */
924
crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, NULL, &count);
926
PORT_SetError(PK11_MapError(crv));
929
/* nothing new, blow out early, we want this function to be quick
930
* and cheap in the normal case */
931
if (count == mod->slotCount) {
932
PZ_Unlock(mod->refLock);
935
if (count < (CK_ULONG)mod->slotCount) {
936
/* shouldn't happen with a properly functioning PKCS #11 module */
937
PORT_SetError( SEC_ERROR_INCOMPATIBLE_PKCS11 );
941
/* get the new slot list */
942
slotIDs = PORT_NewArray(CK_SLOT_ID, count);
943
if (slotIDs == NULL) {
947
crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, slotIDs, &count);
949
PORT_SetError(PK11_MapError(crv));
953
PZ_Unlock(mod->refLock);
954
mark = PORT_ArenaMark(mod->arena);
958
newSlots = PORT_ArenaZNewArray(mod->arena,PK11SlotInfo *,count);
960
/* walk down the new slot ID list returned from the module. We keep
961
* the old slots which match a returned ID, and we initialize the new
963
for (i=0; i < count; i++) {
964
PK11SlotInfo *slot = SECMOD_FindSlotByID(mod,slotIDs[i]);
967
/* we have a new slot create a new slot data structure */
968
slot = PK11_NewSlotInfo(mod);
972
PK11_InitSlot(mod, slotIDs[i], slot);
973
STAN_InitTokenForSlotInfo(NULL, slot);
977
STAN_ResetTokenInterator(NULL);
980
PORT_ArenaUnmark(mod->arena, mark);
982
/* until this point we're still using the old slot list. Now we update
983
* module slot list. We update the slots (array) first then the count,
984
* since we've already guarrenteed that count has increased (just in case
985
* someone is looking at the slots field of module without holding the
987
SECMOD_GetWriteLock(moduleLock);
988
oldCount =mod->slotCount;
989
oldSlots = mod->slots;
990
mod->slots = newSlots; /* typical arena 'leak'... old mod->slots is
991
* allocated out of the module arena and won't
992
* be freed until the module is freed */
993
mod->slotCount = count;
994
SECMOD_ReleaseWriteLock(moduleLock);
995
/* free our old references before forgetting about oldSlot*/
996
for (i=0; i < oldCount; i++) {
997
PK11_FreeSlot(oldSlots[i]);
1003
PZ_Unlock(mod->refLock);
1008
/* free all the slots we allocated. newSlots are part of the
1009
* mod arena. NOTE: the newSlots array contain both new and old
1010
* slots, but we kept a reference to the old slots when we built the new
1011
* array, so we need to free all the slots in newSlots array. */
1013
for (i=0; i < count; i++) {
1014
if (newSlots[i] == NULL) {
1015
break; /* hit the last one */
1017
PK11_FreeSlot(newSlots[i]);
1020
/* must come after freeing newSlots */
1022
PORT_ArenaRelease(mod->arena, mark);
1028
* this handles modules that do not support C_WaitForSlotEvent().
1029
* The internal flags are stored. Note that C_WaitForSlotEvent() does not
1030
* have a timeout, so we don't have one for handleWaitForSlotEvent() either.
1033
secmod_HandleWaitForSlotEvent(SECMODModule *mod, unsigned long flags,
1034
PRIntervalTime latency)
1036
PRBool removableSlotsFound = PR_FALSE;
1038
int error = SEC_ERROR_NO_EVENT;
1041
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1044
PZ_Lock(mod->refLock);
1045
if (mod->evControlMask & SECMOD_END_WAIT) {
1046
mod->evControlMask &= ~SECMOD_END_WAIT;
1047
PZ_Unlock(mod->refLock);
1048
PORT_SetError(SEC_ERROR_NO_EVENT);
1051
mod->evControlMask |= SECMOD_WAIT_SIMULATED_EVENT;
1052
while (mod->evControlMask & SECMOD_WAIT_SIMULATED_EVENT) {
1053
PZ_Unlock(mod->refLock);
1054
/* now is a good time to see if new slots have been added */
1055
SECMOD_UpdateSlotList(mod);
1057
/* loop through all the slots on a module */
1058
SECMOD_GetReadLock(moduleLock);
1059
for (i=0; i < mod->slotCount; i++) {
1060
PK11SlotInfo *slot = mod->slots[i];
1064
/* perm modules do not change */
1068
removableSlotsFound = PR_TRUE;
1069
/* simulate the PKCS #11 module flags. are the flags different
1070
* from the last time we called? */
1071
series = slot->series;
1072
present = PK11_IsPresent(slot);
1073
if ((slot->flagSeries != series) || (slot->flagState != present)) {
1074
slot->flagState = present;
1075
slot->flagSeries = series;
1076
SECMOD_ReleaseReadLock(moduleLock);
1077
PZ_Lock(mod->refLock);
1078
mod->evControlMask &= ~SECMOD_END_WAIT;
1079
PZ_Unlock(mod->refLock);
1080
return PK11_ReferenceSlot(slot);
1083
SECMOD_ReleaseReadLock(moduleLock);
1084
/* if everything was perm modules, don't lock up forever */
1085
if ((mod->slotCount !=0) && !removableSlotsFound) {
1086
error =SEC_ERROR_NO_SLOT_SELECTED;
1087
PZ_Lock(mod->refLock);
1090
if (flags & CKF_DONT_BLOCK) {
1091
PZ_Lock(mod->refLock);
1095
PZ_Lock(mod->refLock);
1097
mod->evControlMask &= ~SECMOD_END_WAIT;
1098
PZ_Unlock(mod->refLock);
1099
PORT_SetError(error);
1104
* this function waits for a token event on any slot of a given module
1105
* This function should not be called from more than one thread of the
1106
* same process (though other threads can make other library calls
1107
* on this module while this call is blocked).
1110
SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags,
1111
PRIntervalTime latency)
1117
if (!pk11_getFinalizeModulesOption() ||
1118
((mod->cryptokiVersion.major == 2) &&
1119
(mod->cryptokiVersion.minor < 1))) {
1120
/* if we are sharing the module with other software in our
1121
* address space, we can't reliably use C_WaitForSlotEvent(),
1122
* and if the module is version 2.0, C_WaitForSlotEvent() doesn't
1124
return secmod_HandleWaitForSlotEvent(mod, flags, latency);
1126
/* first the the PKCS #11 call */
1127
PZ_Lock(mod->refLock);
1128
if (mod->evControlMask & SECMOD_END_WAIT) {
1131
mod->evControlMask |= SECMOD_WAIT_PKCS11_EVENT;
1132
PZ_Unlock(mod->refLock);
1133
crv = PK11_GETTAB(mod)->C_WaitForSlotEvent(flags, &id, NULL);
1134
PZ_Lock(mod->refLock);
1135
mod->evControlMask &= ~SECMOD_WAIT_PKCS11_EVENT;
1136
/* if we are in end wait, short circuit now, don't even risk
1137
* going into secmod_HandleWaitForSlotEvent */
1138
if (mod->evControlMask & SECMOD_END_WAIT) {
1141
PZ_Unlock(mod->refLock);
1142
if (crv == CKR_FUNCTION_NOT_SUPPORTED) {
1143
/* module doesn't support that call, simulate it */
1144
return secmod_HandleWaitForSlotEvent(mod, flags, latency);
1146
if (crv != CKR_OK) {
1147
/* we can get this error if finalize was called while we were
1148
* still running. This is the only way to force a C_WaitForSlotEvent()
1149
* to return in PKCS #11. In this case, just return that there
1151
if (crv == CKR_CRYPTOKI_NOT_INITIALIZED) {
1152
PORT_SetError(SEC_ERROR_NO_EVENT);
1154
PORT_SetError(PK11_MapError(crv));
1158
slot = SECMOD_FindSlotByID(mod, id);
1160
/* possibly a new slot that was added? */
1161
SECMOD_UpdateSlotList(mod);
1162
slot = SECMOD_FindSlotByID(mod, id);
1164
/* if we are in the delay period for the "isPresent" call, reset
1165
* the delay since we know things have probably changed... */
1166
if (slot && slot->nssToken && slot->nssToken->slot) {
1167
nssSlot_ResetDelay(slot->nssToken->slot);
1171
/* must be called with the lock on. */
1173
mod->evControlMask &= ~SECMOD_END_WAIT;
1174
PZ_Unlock(mod->refLock);
1175
PORT_SetError(SEC_ERROR_NO_EVENT);
1180
* This function "wakes up" WaitForAnyTokenEvent. It's a pretty drastic
1181
* function, possibly bringing down the pkcs #11 module in question. This
1182
* should be OK because 1) it does reinitialize, and 2) it should only be
1183
* called when we are on our way to tear the whole system down anyway.
1186
SECMOD_CancelWait(SECMODModule *mod)
1188
unsigned long controlMask = mod->evControlMask;
1189
SECStatus rv = SECSuccess;
1192
PZ_Lock(mod->refLock);
1193
mod->evControlMask |= SECMOD_END_WAIT;
1194
controlMask = mod->evControlMask;
1195
if (controlMask & SECMOD_WAIT_PKCS11_EVENT) {
1196
if (!pk11_getFinalizeModulesOption()) {
1197
/* can't get here unless pk11_getFinalizeModulesOption is set */
1199
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1203
/* NOTE: this call will drop all transient keys, in progress
1204
* operations, and any authentication. This is the only documented
1205
* way to get WaitForSlotEvent to return. Also note: for non-thread
1206
* safe tokens, we need to hold the module lock, this is not yet at
1207
* system shutdown/startup time, so we need to protect these calls */
1208
crv = PK11_GETTAB(mod)->C_Finalize(NULL);
1209
/* ok, we slammed the module down, now we need to reinit it in case
1210
* we intend to use it again */
1211
if (CKR_OK == crv) {
1212
PRBool alreadyLoaded;
1213
secmod_ModuleInit(mod, NULL, &alreadyLoaded);
1215
/* Finalized failed for some reason, notify the application
1216
* so maybe it has a prayer of recovering... */
1217
PORT_SetError(PK11_MapError(crv));
1220
} else if (controlMask & SECMOD_WAIT_SIMULATED_EVENT) {
1221
mod->evControlMask &= ~SECMOD_WAIT_SIMULATED_EVENT;
1222
/* Simulated events will eventually timeout
1223
* and wake up in the loop */
1226
PZ_Unlock(mod->refLock);
1231
* check to see if the module has removable slots that we may need to
1235
SECMOD_HasRemovableSlots(SECMODModule *mod)
1238
PRBool ret = PR_FALSE;
1241
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1244
SECMOD_GetReadLock(moduleLock);
1245
for (i=0; i < mod->slotCount; i++) {
1246
PK11SlotInfo *slot = mod->slots[i];
1247
/* perm modules are not inserted or removed */
1254
if (mod->slotCount == 0 ) {
1257
SECMOD_ReleaseReadLock(moduleLock);
1262
* helper function to actually create and destroy user defined slots
1265
secmod_UserDBOp(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass,
1266
const char *sendSpec)
1268
CK_OBJECT_HANDLE dummy;
1269
CK_ATTRIBUTE template[2] ;
1270
CK_ATTRIBUTE *attrs = template;
1273
PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); attrs++;
1274
PK11_SETATTRS(attrs, CKA_NETSCAPE_MODULE_SPEC , (unsigned char *)sendSpec,
1275
strlen(sendSpec)+1); attrs++;
1277
PORT_Assert(attrs-template <= 2);
1280
PK11_EnterSlotMonitor(slot);
1281
crv = PK11_CreateNewObject(slot, slot->session,
1282
template, attrs-template, PR_FALSE, &dummy);
1283
PK11_ExitSlotMonitor(slot);
1285
if (crv != CKR_OK) {
1286
PORT_SetError(PK11_MapError(crv));
1289
return SECMOD_UpdateSlotList(slot->module);
1293
* return true if the selected slot ID is not present or doesn't exist
1296
secmod_SlotIsEmpty(SECMODModule *mod, CK_SLOT_ID slotID)
1298
PK11SlotInfo *slot = SECMOD_LookupSlot(mod->moduleID, slotID);
1300
PRBool present = PK11_IsPresent(slot);
1301
PK11_FreeSlot(slot);
1306
/* it doesn't exist or isn't present, it's available */
1311
* Find an unused slot id in module.
1314
secmod_FindFreeSlot(SECMODModule *mod)
1316
CK_SLOT_ID i, minSlotID, maxSlotID;
1318
/* look for a free slot id on the internal module */
1319
if (mod->internal && mod->isFIPS) {
1320
minSlotID = SFTK_MIN_FIPS_USER_SLOT_ID;
1321
maxSlotID = SFTK_MAX_FIPS_USER_SLOT_ID;
1323
minSlotID = SFTK_MIN_USER_SLOT_ID;
1324
maxSlotID = SFTK_MAX_USER_SLOT_ID;
1326
for (i=minSlotID; i < maxSlotID; i++) {
1327
if (secmod_SlotIsEmpty(mod,i)) {
1331
PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
1332
return (CK_SLOT_ID) -1;
1336
* Attempt to open a new slot.
1338
* This works the same os OpenUserDB except it can be called against
1339
* any module that understands the softoken protocol for opening new
1340
* slots, not just the softoken itself. If the selected module does not
1341
* understand the protocol, C_CreateObject will fail with
1342
* CKR_INVALID_ATTRIBUTE, and SECMOD_OpenNewSlot will return NULL and set
1343
* SEC_ERROR_BAD_DATA.
1345
* NewSlots can be closed with SECMOD_CloseUserDB();
1347
* Modulespec is module dependent.
1350
SECMOD_OpenNewSlot(SECMODModule *mod, const char *moduleSpec)
1352
CK_SLOT_ID slotID = 0;
1358
slotID = secmod_FindFreeSlot(mod);
1359
if (slotID == (CK_SLOT_ID) -1) {
1363
if (mod->slotCount == 0) {
1367
/* just grab the first slot in the module, any present slot should work */
1368
slot = PK11_ReferenceSlot(mod->slots[0]);
1373
/* we've found the slot, now build the moduleSpec */
1374
escSpec = NSSUTIL_DoubleEscape(moduleSpec, '>', ']');
1375
if (escSpec == NULL) {
1376
PK11_FreeSlot(slot);
1379
sendSpec = PR_smprintf("tokens=[0x%x=<%s>]", slotID, escSpec);
1382
if (sendSpec == NULL) {
1383
/* PR_smprintf does not set SEC_ERROR_NO_MEMORY on failure. */
1384
PK11_FreeSlot(slot);
1385
PORT_SetError(SEC_ERROR_NO_MEMORY);
1388
rv = secmod_UserDBOp(slot, CKO_NETSCAPE_NEWSLOT, sendSpec);
1389
PR_smprintf_free(sendSpec);
1390
PK11_FreeSlot(slot);
1391
if (rv != SECSuccess) {
1395
slot = SECMOD_FindSlotByID(mod, slotID);
1397
/* if we are in the delay period for the "isPresent" call, reset
1398
* the delay since we know things have probably changed... */
1399
if (slot->nssToken && slot->nssToken->slot) {
1400
nssSlot_ResetDelay(slot->nssToken->slot);
1402
/* force the slot info structures to properly reset */
1403
(void)PK11_IsPresent(slot);
1409
* Open a new database using the softoken. The caller is responsible for making
1410
* sure the module spec is correct and usable. The caller should ask for one
1411
* new database per call if the caller wants to get meaningful information
1412
* about the new database.
1414
* moduleSpec is the same data that you would pass to softoken at
1415
* initialization time under the 'tokens' options. For example, if you were
1416
* to specify tokens=<0x4=[configdir='./mybackup' tokenDescription='Backup']>
1417
* You would specify "configdir='./mybackup' tokenDescription='Backup'" as your
1418
* module spec here. The slot ID will be calculated for you by
1419
* SECMOD_OpenUserDB().
1421
* Typical parameters here are configdir, tokenDescription and flags.
1423
* a Full list is below:
1426
* configDir - The location of the databases for this token. If configDir is
1427
* not specified, and noCertDB and noKeyDB is not specified, the load
1429
* certPrefix - Cert prefix for this token.
1430
* keyPrefix - Prefix for the key database for this token. (if not specified,
1431
* certPrefix will be used).
1432
* tokenDescription - The label value for this token returned in the
1433
* CK_TOKEN_INFO structure with an internationalize string (UTF8).
1434
* This value will be truncated at 32 bytes (no NULL, partial UTF8
1435
* characters dropped). You should specify a user friendly name here
1436
* as this is the value the token will be referred to in most
1437
* application UI's. You should make sure tokenDescription is unique.
1438
* slotDescription - The slotDescription value for this token returned
1439
* in the CK_SLOT_INFO structure with an internationalize string
1440
* (UTF8). This value will be truncated at 64 bytes (no NULL, partial
1441
* UTF8 characters dropped). This name will not change after the
1442
* database is closed. It should have some number to make this unique.
1443
* minPWLen - minimum password length for this token.
1444
* flags - comma separated list of flag values, parsed case-insensitive.
1446
* readOnly - Databases should be opened read only.
1447
* noCertDB - Don't try to open a certificate database.
1448
* noKeyDB - Don't try to open a key database.
1449
* forceOpen - Don't fail to initialize the token if the
1450
* databases could not be opened.
1451
* passwordRequired - zero length passwords are not acceptable
1452
* (valid only if there is a keyDB).
1453
* optimizeSpace - allocate smaller hash tables and lock tables.
1454
* When this flag is not specified, Softoken will allocate
1455
* large tables to prevent lock contention.
1458
SECMOD_OpenUserDB(const char *moduleSpec)
1462
if (moduleSpec == NULL) {
1466
/* NOTE: unlike most PK11 function, this does not return a reference
1468
mod = SECMOD_GetInternalModule();
1470
/* shouldn't happen */
1471
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1474
return SECMOD_OpenNewSlot(mod, moduleSpec);
1479
* close an already opened user database. NOTE: the database must be
1480
* in the internal token, and must be one created with SECMOD_OpenUserDB().
1481
* Once the database is closed, the slot will remain as an empty slot
1482
* until it's used again with SECMOD_OpenUserDB() or SECMOD_OpenNewSlot().
1485
SECMOD_CloseUserDB(PK11SlotInfo *slot)
1490
sendSpec = PR_smprintf("tokens=[0x%x=<>]", slot->slotID);
1491
if (sendSpec == NULL) {
1492
/* PR_smprintf does not set no memory error */
1493
PORT_SetError(SEC_ERROR_NO_MEMORY);
1496
rv = secmod_UserDBOp(slot, CKO_NETSCAPE_DELSLOT, sendSpec);
1497
PR_smprintf_free(sendSpec);
1498
/* if we are in the delay period for the "isPresent" call, reset
1499
* the delay since we know things have probably changed... */
1500
if (slot->nssToken && slot->nssToken->slot) {
1501
nssSlot_ResetDelay(slot->nssToken->slot);
1502
/* force the slot info structures to properly reset */
1503
(void)PK11_IsPresent(slot);
1509
* Restart PKCS #11 modules after a fork(). See secmod.h for more information.
1512
SECMOD_RestartModules(PRBool force)
1514
SECMODModuleList *mlp;
1515
SECStatus rrv = SECSuccess;
1519
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1523
/* Only need to restart the PKCS #11 modules that were initialized */
1524
SECMOD_GetReadLock(moduleLock);
1525
for (mlp = modules; mlp != NULL; mlp = mlp->next) {
1526
SECMODModule *mod = mlp->module;
1531
/* If the module needs to be reset, do so */
1532
if (force || (PK11_GETTAB(mod)->
1533
C_GetSlotList(CK_FALSE, NULL, &count) != CKR_OK)) {
1534
PRBool alreadyLoaded;
1535
/* first call Finalize. This is not required by PKCS #11, but some
1536
* older modules require it, and it doesn't hurt (compliant modules
1537
* will return CKR_NOT_INITIALIZED */
1538
(void) PK11_GETTAB(mod)->C_Finalize(NULL);
1539
/* now initialize the module, this function reinitializes
1540
* a module in place, preserving existing slots (even if they
1541
* no longer exist) */
1542
rv = secmod_ModuleInit(mod, NULL, &alreadyLoaded);
1543
if (rv != SECSuccess) {
1544
/* save the last error code */
1545
lastError = PORT_GetError();
1547
/* couldn't reinit the module, disable all its slots */
1548
for (i=0; i < mod->slotCount; i++) {
1549
mod->slots[i]->disabled = PR_TRUE;
1550
mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1554
for (i=0; i < mod->slotCount; i++) {
1555
/* get new token sessions, bump the series up so that
1556
* we refresh other old sessions. This will tell much of
1557
* NSS to flush cached handles it may hold as well */
1558
rv = PK11_InitToken(mod->slots[i],PR_TRUE);
1559
/* PK11_InitToken could fail if the slot isn't present.
1560
* If it is present, though, something is wrong and we should
1561
* disable the slot and let the caller know. */
1562
if (rv != SECSuccess && PK11_IsPresent(mod->slots[i])) {
1563
/* save the last error code */
1564
lastError = PORT_GetError();
1566
/* disable the token */
1567
mod->slots[i]->disabled = PR_TRUE;
1568
mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1573
SECMOD_ReleaseReadLock(moduleLock);
1576
* on multiple failures, we are only returning the lastError. The caller
1577
* can determine which slots are bad by calling PK11_IsDisabled().
1579
if (rrv != SECSuccess) {
1580
/* restore the last error code */
1581
PORT_SetError(lastError);