Import 1.9b4 NSS tag from cvs
[mozilla-nss.git] / security / nss / lib / pk11wrap / pk11util.c
blobe4edaf2e6770170e49961b02f5941c89d4c2cb44
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 * Initialize the PCKS 11 subsystem
39 #include "seccomon.h"
40 #include "secmod.h"
41 #include "nssilock.h"
42 #include "secmodi.h"
43 #include "secmodti.h"
44 #include "pk11func.h"
45 #include "pki3hack.h"
46 #include "secerr.h"
47 #include "dev.h"
48 #include "pkcs11ni.h"
50 /* these are for displaying error messages */
52 static SECMODModuleList *modules = NULL;
53 static SECMODModuleList *modulesDB = NULL;
54 static SECMODModuleList *modulesUnload = NULL;
55 static SECMODModule *internalModule = NULL;
56 static SECMODModule *defaultDBModule = NULL;
57 static SECMODModule *pendingModule = NULL;
58 static SECMODListLock *moduleLock = NULL;
60 int secmod_PrivateModuleCount = 0;
62 extern PK11DefaultArrayEntry PK11_DefaultArray[];
63 extern int num_pk11_default_mechanisms;
66 void
67 SECMOD_Init()
69 /* don't initialize twice */
70 if (moduleLock) return;
72 moduleLock = SECMOD_NewListLock();
73 PK11_InitSlotLists();
77 SECStatus
78 SECMOD_Shutdown()
80 /* destroy the lock */
81 if (moduleLock) {
82 SECMOD_DestroyListLock(moduleLock);
83 moduleLock = NULL;
85 /* free the internal module */
86 if (internalModule) {
87 SECMOD_DestroyModule(internalModule);
88 internalModule = NULL;
91 /* free the default database module */
92 if (defaultDBModule) {
93 SECMOD_DestroyModule(defaultDBModule);
94 defaultDBModule = NULL;
97 /* destroy the list */
98 if (modules) {
99 SECMOD_DestroyModuleList(modules);
100 modules = NULL;
103 if (modulesDB) {
104 SECMOD_DestroyModuleList(modulesDB);
105 modulesDB = NULL;
108 if (modulesUnload) {
109 SECMOD_DestroyModuleList(modulesUnload);
110 modulesUnload = NULL;
113 /* make all the slots and the lists go away */
114 PK11_DestroySlotLists();
116 nss_DumpModuleLog();
118 #ifdef DEBUG
119 if (PR_GetEnv("NSS_STRICT_SHUTDOWN")) {
120 PORT_Assert(secmod_PrivateModuleCount == 0);
122 #endif
123 if (secmod_PrivateModuleCount) {
124 PORT_SetError(SEC_ERROR_BUSY);
125 return SECFailure;
127 return SECSuccess;
132 * retrieve the internal module
134 SECMODModule *
135 SECMOD_GetInternalModule(void)
137 return internalModule;
141 SECStatus
142 secmod_AddModuleToList(SECMODModuleList **moduleList,SECMODModule *newModule)
144 SECMODModuleList *mlp, *newListElement, *last = NULL;
146 newListElement = SECMOD_NewModuleListElement();
147 if (newListElement == NULL) {
148 return SECFailure;
151 newListElement->module = SECMOD_ReferenceModule(newModule);
153 SECMOD_GetWriteLock(moduleLock);
154 /* Added it to the end (This is very inefficient, but Adding a module
155 * on the fly should happen maybe 2-3 times through the life this program
156 * on a given computer, and this list should be *SHORT*. */
157 for(mlp = *moduleList; mlp != NULL; mlp = mlp->next) {
158 last = mlp;
161 if (last == NULL) {
162 *moduleList = newListElement;
163 } else {
164 SECMOD_AddList(last,newListElement,NULL);
166 SECMOD_ReleaseWriteLock(moduleLock);
167 return SECSuccess;
170 SECStatus
171 SECMOD_AddModuleToList(SECMODModule *newModule)
173 if (newModule->internal && !internalModule) {
174 internalModule = SECMOD_ReferenceModule(newModule);
176 return secmod_AddModuleToList(&modules,newModule);
179 SECStatus
180 SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule)
182 if (defaultDBModule == NULL) {
183 defaultDBModule = SECMOD_ReferenceModule(newModule);
185 return secmod_AddModuleToList(&modulesDB,newModule);
188 SECStatus
189 SECMOD_AddModuleToUnloadList(SECMODModule *newModule)
191 return secmod_AddModuleToList(&modulesUnload,newModule);
195 * get the list of PKCS11 modules that are available.
197 SECMODModuleList * SECMOD_GetDefaultModuleList() { return modules; }
198 SECMODModuleList *SECMOD_GetDeadModuleList() { return modulesUnload; }
199 SECMODModuleList *SECMOD_GetDBModuleList() { return modulesDB; }
202 * This lock protects the global module lists.
203 * it also protects changes to the slot array (module->slots[]) and slot count
204 * (module->slotCount) in each module. It is a read/write lock with multiple
205 * readers or one writer. Writes are uncommon.
206 * Because of legacy considerations protection of the slot array and count is
207 * only necessary in applications if the application calls
208 * SECMOD_UpdateSlotList() or SECMOD_WaitForAnyTokenEvent(), though all new
209 * applications are encouraged to acquire this lock when reading the
210 * slot array information directly.
212 SECMODListLock *SECMOD_GetDefaultModuleListLock() { return moduleLock; }
217 * find a module by name, and add a reference to it.
218 * return that module.
220 SECMODModule *
221 SECMOD_FindModule(const char *name)
223 SECMODModuleList *mlp;
224 SECMODModule *module = NULL;
226 SECMOD_GetReadLock(moduleLock);
227 for(mlp = modules; mlp != NULL; mlp = mlp->next) {
228 if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
229 module = mlp->module;
230 SECMOD_ReferenceModule(module);
231 break;
234 if (module) {
235 goto found;
237 for(mlp = modulesUnload; mlp != NULL; mlp = mlp->next) {
238 if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
239 module = mlp->module;
240 SECMOD_ReferenceModule(module);
241 break;
245 found:
246 SECMOD_ReleaseReadLock(moduleLock);
248 return module;
252 * find a module by ID, and add a reference to it.
253 * return that module.
255 SECMODModule *
256 SECMOD_FindModuleByID(SECMODModuleID id)
258 SECMODModuleList *mlp;
259 SECMODModule *module = NULL;
261 SECMOD_GetReadLock(moduleLock);
262 for(mlp = modules; mlp != NULL; mlp = mlp->next) {
263 if (id == mlp->module->moduleID) {
264 module = mlp->module;
265 SECMOD_ReferenceModule(module);
266 break;
269 SECMOD_ReleaseReadLock(moduleLock);
270 if (module == NULL) {
271 PORT_SetError(SEC_ERROR_NO_MODULE);
273 return module;
277 * Find the Slot based on ID and the module.
279 PK11SlotInfo *
280 SECMOD_FindSlotByID(SECMODModule *module, CK_SLOT_ID slotID)
282 int i;
283 PK11SlotInfo *slot = NULL;
285 SECMOD_GetReadLock(moduleLock);
286 for (i=0; i < module->slotCount; i++) {
287 PK11SlotInfo *cSlot = module->slots[i];
289 if (cSlot->slotID == slotID) {
290 slot = PK11_ReferenceSlot(cSlot);
291 break;
294 SECMOD_ReleaseReadLock(moduleLock);
296 if (slot == NULL) {
297 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
299 return slot;
303 * lookup the Slot module based on it's module ID and slot ID.
305 PK11SlotInfo *
306 SECMOD_LookupSlot(SECMODModuleID moduleID,CK_SLOT_ID slotID)
308 SECMODModule *module;
309 PK11SlotInfo *slot;
311 module = SECMOD_FindModuleByID(moduleID);
312 if (module == NULL) return NULL;
314 slot = SECMOD_FindSlotByID(module, slotID);
315 SECMOD_DestroyModule(module);
316 return slot;
321 * find a module by name or module pointer and delete it off the module list.
322 * optionally remove it from secmod.db.
324 SECStatus
325 SECMOD_DeleteModuleEx(const char *name, SECMODModule *mod,
326 int *type, PRBool permdb)
328 SECMODModuleList *mlp;
329 SECMODModuleList **mlpp;
330 SECStatus rv = SECFailure;
332 *type = SECMOD_EXTERNAL;
334 SECMOD_GetWriteLock(moduleLock);
335 for (mlpp = &modules,mlp = modules;
336 mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
337 if ((name && (PORT_Strcmp(name,mlp->module->commonName) == 0)) ||
338 mod == mlp->module) {
339 /* don't delete the internal module */
340 if (!mlp->module->internal) {
341 SECMOD_RemoveList(mlpp,mlp);
342 /* delete it after we release the lock */
343 rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module);
344 } else if (mlp->module->isFIPS) {
345 *type = SECMOD_FIPS;
346 } else {
347 *type = SECMOD_INTERNAL;
349 break;
352 if (mlp) {
353 goto found;
355 /* not on the internal list, check the unload list */
356 for (mlpp = &modulesUnload,mlp = modulesUnload;
357 mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
358 if ((name && (PORT_Strcmp(name,mlp->module->commonName) == 0)) ||
359 mod == mlp->module) {
360 /* don't delete the internal module */
361 if (!mlp->module->internal) {
362 SECMOD_RemoveList(mlpp,mlp);
363 rv = SECSuccess;
364 } else if (mlp->module->isFIPS) {
365 *type = SECMOD_FIPS;
366 } else {
367 *type = SECMOD_INTERNAL;
369 break;
372 found:
373 SECMOD_ReleaseWriteLock(moduleLock);
376 if (rv == SECSuccess) {
377 if (permdb) {
378 SECMOD_DeletePermDB(mlp->module);
380 SECMOD_DestroyModuleListElement(mlp);
382 return rv;
386 * find a module by name and delete it off the module list
388 SECStatus
389 SECMOD_DeleteModule(const char *name, int *type)
391 return SECMOD_DeleteModuleEx(name, NULL, type, PR_TRUE);
395 * find a module by name and delete it off the module list
397 SECStatus
398 SECMOD_DeleteInternalModule(const char *name)
400 SECMODModuleList *mlp;
401 SECMODModuleList **mlpp;
402 SECStatus rv = SECFailure;
404 if (pendingModule) {
405 PORT_SetError(SEC_ERROR_MODULE_STUCK);
406 return rv;
409 SECMOD_GetWriteLock(moduleLock);
410 for(mlpp = &modules,mlp = modules;
411 mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
412 if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
413 /* don't delete the internal module */
414 if (mlp->module->internal) {
415 SECMOD_RemoveList(mlpp,mlp);
416 rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module);
418 break;
421 SECMOD_ReleaseWriteLock(moduleLock);
423 if (rv == SECSuccess) {
424 SECMODModule *newModule,*oldModule;
426 if (mlp->module->isFIPS) {
427 newModule = SECMOD_CreateModule(NULL, SECMOD_INT_NAME,
428 NULL, SECMOD_INT_FLAGS);
429 } else {
430 newModule = SECMOD_CreateModule(NULL, SECMOD_FIPS_NAME,
431 NULL, SECMOD_FIPS_FLAGS);
433 if (newModule) {
434 newModule->libraryParams =
435 PORT_ArenaStrdup(newModule->arena,mlp->module->libraryParams);
436 rv = SECMOD_AddModule(newModule);
437 if (rv != SECSuccess) {
438 SECMOD_DestroyModule(newModule);
439 newModule = NULL;
442 if (newModule == NULL) {
443 SECMODModuleList *last = NULL,*mlp2;
444 /* we're in pretty deep trouble if this happens...Security
445 * not going to work well... try to put the old module back on
446 * the list */
447 SECMOD_GetWriteLock(moduleLock);
448 for(mlp2 = modules; mlp2 != NULL; mlp2 = mlp->next) {
449 last = mlp2;
452 if (last == NULL) {
453 modules = mlp;
454 } else {
455 SECMOD_AddList(last,mlp,NULL);
457 SECMOD_ReleaseWriteLock(moduleLock);
458 return SECFailure;
460 pendingModule = oldModule = internalModule;
461 internalModule = NULL;
462 SECMOD_DestroyModule(oldModule);
463 SECMOD_DeletePermDB(mlp->module);
464 SECMOD_DestroyModuleListElement(mlp);
465 internalModule = newModule; /* adopt the module */
467 return rv;
470 SECStatus
471 SECMOD_AddModule(SECMODModule *newModule)
473 SECStatus rv;
474 SECMODModule *oldModule;
476 /* Test if a module w/ the same name already exists */
477 /* and return SECWouldBlock if so. */
478 /* We should probably add a new return value such as */
479 /* SECDublicateModule, but to minimize ripples, I'll */
480 /* give SECWouldBlock a new meaning */
481 if ((oldModule = SECMOD_FindModule(newModule->commonName)) != NULL) {
482 SECMOD_DestroyModule(oldModule);
483 return SECWouldBlock;
484 /* module already exists. */
487 rv = SECMOD_LoadPKCS11Module(newModule);
488 if (rv != SECSuccess) {
489 return rv;
492 if (newModule->parent == NULL) {
493 newModule->parent = SECMOD_ReferenceModule(defaultDBModule);
496 SECMOD_AddPermDB(newModule);
497 SECMOD_AddModuleToList(newModule);
499 rv = STAN_AddModuleToDefaultTrustDomain(newModule);
501 return rv;
504 PK11SlotInfo *
505 SECMOD_FindSlot(SECMODModule *module,const char *name)
507 int i;
508 char *string;
509 PK11SlotInfo *retSlot = NULL;
511 SECMOD_GetReadLock(moduleLock);
512 for (i=0; i < module->slotCount; i++) {
513 PK11SlotInfo *slot = module->slots[i];
515 if (PK11_IsPresent(slot)) {
516 string = PK11_GetTokenName(slot);
517 } else {
518 string = PK11_GetSlotName(slot);
520 if (PORT_Strcmp(name,string) == 0) {
521 retSlot = PK11_ReferenceSlot(slot);
522 break;
525 SECMOD_ReleaseReadLock(moduleLock);
527 if (retSlot == NULL) {
528 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
530 return retSlot;
533 SECStatus
534 PK11_GetModInfo(SECMODModule *mod,CK_INFO *info)
536 CK_RV crv;
538 if (mod->functionList == NULL) return SECFailure;
539 crv = PK11_GETTAB(mod)->C_GetInfo(info);
540 if (crv != CKR_OK) {
541 PORT_SetError(PK11_MapError(crv));
543 return (crv == CKR_OK) ? SECSuccess : SECFailure;
546 /* Determine if we have the FIP's module loaded as the default
547 * module to trigger other bogus FIPS requirements in PKCS #12 and
548 * SSL
550 PRBool
551 PK11_IsFIPS(void)
553 SECMODModule *mod = SECMOD_GetInternalModule();
555 if (mod && mod->internal) {
556 return mod->isFIPS;
559 return PR_FALSE;
562 /* combines NewModule() & AddModule */
563 /* give a string for the module name & the full-path for the dll, */
564 /* installs the PKCS11 module & update registry */
565 SECStatus
566 SECMOD_AddNewModuleEx(const char* moduleName, const char* dllPath,
567 unsigned long defaultMechanismFlags,
568 unsigned long cipherEnableFlags,
569 char* modparms, char* nssparms)
571 SECMODModule *module;
572 SECStatus result = SECFailure;
573 int s,i;
574 PK11SlotInfo* slot;
576 PR_SetErrorText(0, NULL);
578 module = SECMOD_CreateModule(dllPath, moduleName, modparms, nssparms);
580 if (module == NULL) {
581 return result;
584 if (module->dllName != NULL) {
585 if (module->dllName[0] != 0) {
586 result = SECMOD_AddModule(module);
587 if (result == SECSuccess) {
588 /* turn on SSL cipher enable flags */
589 module->ssl[0] = cipherEnableFlags;
591 SECMOD_GetReadLock(moduleLock);
592 /* check each slot to turn on appropriate mechanisms */
593 for (s = 0; s < module->slotCount; s++) {
594 slot = (module->slots)[s];
595 /* for each possible mechanism */
596 for (i=0; i < num_pk11_default_mechanisms; i++) {
597 /* we are told to turn it on by default ? */
598 PRBool add =
599 (PK11_DefaultArray[i].flag & defaultMechanismFlags) ?
600 PR_TRUE: PR_FALSE;
601 result = PK11_UpdateSlotAttribute(slot,
602 &(PK11_DefaultArray[i]), add);
603 } /* for each mechanism */
604 /* disable each slot if the defaultFlags say so */
605 if (defaultMechanismFlags & PK11_DISABLE_FLAG) {
606 PK11_UserDisableSlot(slot);
608 } /* for each slot of this module */
609 SECMOD_ReleaseReadLock(moduleLock);
611 /* delete and re-add module in order to save changes
612 * to the module */
613 result = SECMOD_UpdateModule(module);
617 SECMOD_DestroyModule(module);
618 return result;
621 SECStatus
622 SECMOD_AddNewModule(const char* moduleName, const char* dllPath,
623 unsigned long defaultMechanismFlags,
624 unsigned long cipherEnableFlags)
626 return SECMOD_AddNewModuleEx(moduleName, dllPath, defaultMechanismFlags,
627 cipherEnableFlags,
628 NULL, NULL); /* don't pass module or nss params */
631 SECStatus
632 SECMOD_UpdateModule(SECMODModule *module)
634 SECStatus result;
636 result = SECMOD_DeletePermDB(module);
638 if (result == SECSuccess) {
639 result = SECMOD_AddPermDB(module);
641 return result;
644 /* Public & Internal(Security Library) representation of
645 * encryption mechanism flags conversion */
647 /* Currently, the only difference is that internal representation
648 * puts RANDOM_FLAG at bit 31 (Most-significant bit), but
649 * public representation puts this bit at bit 28
651 unsigned long
652 SECMOD_PubMechFlagstoInternal(unsigned long publicFlags)
654 unsigned long internalFlags = publicFlags;
656 if (publicFlags & PUBLIC_MECH_RANDOM_FLAG) {
657 internalFlags &= ~PUBLIC_MECH_RANDOM_FLAG;
658 internalFlags |= SECMOD_RANDOM_FLAG;
660 return internalFlags;
663 unsigned long
664 SECMOD_InternaltoPubMechFlags(unsigned long internalFlags)
666 unsigned long publicFlags = internalFlags;
668 if (internalFlags & SECMOD_RANDOM_FLAG) {
669 publicFlags &= ~SECMOD_RANDOM_FLAG;
670 publicFlags |= PUBLIC_MECH_RANDOM_FLAG;
672 return publicFlags;
676 /* Public & Internal(Security Library) representation of */
677 /* cipher flags conversion */
678 /* Note: currently they are just stubs */
679 unsigned long
680 SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags)
682 return publicFlags;
685 unsigned long
686 SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags)
688 return internalFlags;
691 /* Funtion reports true if module of modType is installed/configured */
692 PRBool
693 SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags )
695 PRBool result = PR_FALSE;
696 SECMODModuleList *mods = SECMOD_GetDefaultModuleList();
697 SECMOD_GetReadLock(moduleLock);
700 for ( ; mods != NULL; mods = mods->next) {
701 if (mods->module->ssl[0] &
702 SECMOD_PubCipherFlagstoInternal(pubCipherEnableFlags)) {
703 result = PR_TRUE;
707 SECMOD_ReleaseReadLock(moduleLock);
708 return result;
711 /* create a new ModuleListElement */
712 SECMODModuleList *SECMOD_NewModuleListElement(void)
714 SECMODModuleList *newModList;
716 newModList= (SECMODModuleList *) PORT_Alloc(sizeof(SECMODModuleList));
717 if (newModList) {
718 newModList->next = NULL;
719 newModList->module = NULL;
721 return newModList;
725 * make a new reference to a module so It doesn't go away on us
727 SECMODModule *
728 SECMOD_ReferenceModule(SECMODModule *module)
730 PZ_Lock(module->refLock);
731 PORT_Assert(module->refCount > 0);
733 module->refCount++;
734 PZ_Unlock(module->refLock);
735 return module;
739 /* destroy an existing module */
740 void
741 SECMOD_DestroyModule(SECMODModule *module)
743 PRBool willfree = PR_FALSE;
744 int slotCount;
745 int i;
747 PZ_Lock(module->refLock);
748 if (module->refCount-- == 1) {
749 willfree = PR_TRUE;
751 PORT_Assert(willfree || (module->refCount > 0));
752 PZ_Unlock(module->refLock);
754 if (!willfree) {
755 return;
758 if (module->parent != NULL) {
759 SECMODModule *parent = module->parent;
760 /* paranoia, don't loop forever if the modules are looped */
761 module->parent = NULL;
762 SECMOD_DestroyModule(parent);
765 /* slots can't really disappear until our module starts freeing them,
766 * so this check is safe */
767 slotCount = module->slotCount;
768 if (slotCount == 0) {
769 SECMOD_SlotDestroyModule(module,PR_FALSE);
770 return;
773 /* now free all out slots, when they are done, they will cause the
774 * module to disappear altogether */
775 for (i=0 ; i < slotCount; i++) {
776 if (!module->slots[i]->disabled) {
777 PK11_ClearSlotList(module->slots[i]);
779 PK11_FreeSlot(module->slots[i]);
781 /* WARNING: once the last slot has been freed is it possible (even likely)
782 * that module is no more... touching it now is a good way to go south */
786 /* we can only get here if we've destroyed the module, or some one has
787 * erroneously freed a slot that wasn't referenced. */
788 void
789 SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot)
791 PRBool willfree = PR_FALSE;
792 if (fromSlot) {
793 PORT_Assert(module->refCount == 0);
794 PZ_Lock(module->refLock);
795 if (module->slotCount-- == 1) {
796 willfree = PR_TRUE;
798 PORT_Assert(willfree || (module->slotCount > 0));
799 PZ_Unlock(module->refLock);
800 if (!willfree) return;
803 if (module == pendingModule) {
804 pendingModule = NULL;
807 if (module->loaded) {
808 SECMOD_UnloadModule(module);
810 PZ_DestroyLock(module->refLock);
811 PORT_FreeArena(module->arena,PR_FALSE);
812 secmod_PrivateModuleCount--;
815 /* destroy a list element
816 * this destroys a single element, and returns the next element
817 * on the chain. It makes it easy to implement for loops to delete
818 * the chain. It also make deleting a single element easy */
819 SECMODModuleList *
820 SECMOD_DestroyModuleListElement(SECMODModuleList *element)
822 SECMODModuleList *next = element->next;
824 if (element->module) {
825 SECMOD_DestroyModule(element->module);
826 element->module = NULL;
828 PORT_Free(element);
829 return next;
834 * Destroy an entire module list
836 void
837 SECMOD_DestroyModuleList(SECMODModuleList *list)
839 SECMODModuleList *lp;
841 for ( lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) ;
844 PRBool
845 SECMOD_CanDeleteInternalModule(void)
847 return (PRBool) (pendingModule == NULL);
851 * check to see if the module has added new slots. PKCS 11 v2.20 allows for
852 * modules to add new slots, but never remove them. Slots cannot be added
853 * between a call to C_GetSlotLlist(Flag, NULL, &count) and the subsequent
854 * C_GetSlotList(flag, &data, &count) so that the array doesn't accidently
855 * grow on the caller. It is permissible for the slots to increase between
856 * successive calls with NULL to get the size.
858 SECStatus
859 SECMOD_UpdateSlotList(SECMODModule *mod)
861 CK_RV crv;
862 CK_ULONG count;
863 CK_ULONG i, oldCount;
864 PRBool freeRef = PR_FALSE;
865 void *mark = NULL;
866 CK_ULONG *slotIDs = NULL;
867 PK11SlotInfo **newSlots = NULL;
868 PK11SlotInfo **oldSlots = NULL;
870 /* C_GetSlotList is not a session function, make sure
871 * calls are serialized */
872 PZ_Lock(mod->refLock);
873 freeRef = PR_TRUE;
874 /* see if the number of slots have changed */
875 crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, NULL, &count);
876 if (crv != CKR_OK) {
877 PORT_SetError(PK11_MapError(crv));
878 goto loser;
880 /* nothing new, blow out early, we want this function to be quick
881 * and cheap in the normal case */
882 if (count == mod->slotCount) {
883 PZ_Unlock(mod->refLock);
884 return SECSuccess;
886 if (count < (CK_ULONG)mod->slotCount) {
887 /* shouldn't happen with a properly functioning PKCS #11 module */
888 PORT_SetError( SEC_ERROR_INCOMPATIBLE_PKCS11 );
889 goto loser;
892 /* get the new slot list */
893 slotIDs = PORT_NewArray(CK_SLOT_ID, count);
894 if (slotIDs == NULL) {
895 goto loser;
898 crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, slotIDs, &count);
899 if (crv != CKR_OK) {
900 PORT_SetError(PK11_MapError(crv));
901 goto loser;
903 freeRef = PR_FALSE;
904 PZ_Unlock(mod->refLock);
905 mark = PORT_ArenaMark(mod->arena);
906 if (mark == NULL) {
907 goto loser;
909 newSlots = PORT_ArenaZNewArray(mod->arena,PK11SlotInfo *,count);
911 /* walk down the new slot ID list returned from the module. We keep
912 * the old slots which match a returned ID, and we initialize the new
913 * slots. */
914 for (i=0; i < count; i++) {
915 PK11SlotInfo *slot = SECMOD_FindSlotByID(mod,slotIDs[i]);
917 if (!slot) {
918 /* we have a new slot create a new slot data structure */
919 slot = PK11_NewSlotInfo(mod);
920 if (!slot) {
921 goto loser;
923 PK11_InitSlot(mod, slotIDs[i], slot);
924 STAN_InitTokenForSlotInfo(NULL, slot);
926 newSlots[i] = slot;
928 STAN_ResetTokenInterator(NULL);
929 PORT_Free(slotIDs);
930 slotIDs = NULL;
931 PORT_ArenaUnmark(mod->arena, mark);
933 /* until this point we're still using the old slot list. Now we update
934 * module slot list. We update the slots (array) first then the count,
935 * since we've already guarrenteed that count has increased (just in case
936 * someone is looking at the slots field of module without holding the
937 * moduleLock */
938 SECMOD_GetWriteLock(moduleLock);
939 oldCount =mod->slotCount;
940 oldSlots = mod->slots;
941 mod->slots = newSlots; /* typical arena 'leak'... old mod->slots is
942 * allocated out of the module arena and won't
943 * be freed until the module is freed */
944 mod->slotCount = count;
945 SECMOD_ReleaseWriteLock(moduleLock);
946 /* free our old references before forgetting about oldSlot*/
947 for (i=0; i < oldCount; i++) {
948 PK11_FreeSlot(oldSlots[i]);
950 return SECSuccess;
952 loser:
953 if (freeRef) {
954 PZ_Unlock(mod->refLock);
956 if (slotIDs) {
957 PORT_Free(slotIDs);
959 /* free all the slots we allocated. newSlots are part of the
960 * mod arena. NOTE: the newSlots array contain both new and old
961 * slots, but we kept a reference to the old slots when we built the new
962 * array, so we need to free all the slots in newSlots array. */
963 if (newSlots) {
964 for (i=0; i < count; i++) {
965 if (newSlots[i] == NULL) {
966 break; /* hit the last one */
968 PK11_FreeSlot(newSlots[i]);
971 /* must come after freeing newSlots */
972 if (mark) {
973 PORT_ArenaRelease(mod->arena, mark);
975 return SECFailure;
979 * this handles modules that do not support C_WaitForSlotEvent().
980 * The internal flags are stored. Note that C_WaitForSlotEvent() does not
981 * have a timeout, so we don't have one for handleWaitForSlotEvent() either.
983 PK11SlotInfo *
984 secmod_HandleWaitForSlotEvent(SECMODModule *mod, unsigned long flags,
985 PRIntervalTime latency)
987 PRBool removableSlotsFound = PR_FALSE;
988 int i;
989 int error = SEC_ERROR_NO_EVENT;
991 PZ_Lock(mod->refLock);
992 if (mod->evControlMask & SECMOD_END_WAIT) {
993 mod->evControlMask &= ~SECMOD_END_WAIT;
994 PZ_Unlock(mod->refLock);
995 PORT_SetError(SEC_ERROR_NO_EVENT);
996 return NULL;
998 mod->evControlMask |= SECMOD_WAIT_SIMULATED_EVENT;
999 while (mod->evControlMask & SECMOD_WAIT_SIMULATED_EVENT) {
1000 PZ_Unlock(mod->refLock);
1001 /* now is a good time to see if new slots have been added */
1002 SECMOD_UpdateSlotList(mod);
1004 /* loop through all the slots on a module */
1005 SECMOD_GetReadLock(moduleLock);
1006 for (i=0; i < mod->slotCount; i++) {
1007 PK11SlotInfo *slot = mod->slots[i];
1008 uint16 series;
1009 PRBool present;
1011 /* perm modules do not change */
1012 if (slot->isPerm) {
1013 continue;
1015 removableSlotsFound = PR_TRUE;
1016 /* simulate the PKCS #11 module flags. are the flags different
1017 * from the last time we called? */
1018 series = slot->series;
1019 present = PK11_IsPresent(slot);
1020 if ((slot->flagSeries != series) || (slot->flagState != present)) {
1021 slot->flagState = present;
1022 slot->flagSeries = series;
1023 SECMOD_ReleaseReadLock(moduleLock);
1024 PZ_Lock(mod->refLock);
1025 mod->evControlMask &= ~SECMOD_END_WAIT;
1026 PZ_Unlock(mod->refLock);
1027 return PK11_ReferenceSlot(slot);
1030 SECMOD_ReleaseReadLock(moduleLock);
1031 /* if everything was perm modules, don't lock up forever */
1032 if (!removableSlotsFound) {
1033 error =SEC_ERROR_NO_SLOT_SELECTED;
1034 PZ_Lock(mod->refLock);
1035 break;
1037 if (flags & CKF_DONT_BLOCK) {
1038 PZ_Lock(mod->refLock);
1039 break;
1041 PR_Sleep(latency);
1042 PZ_Lock(mod->refLock);
1044 mod->evControlMask &= ~SECMOD_END_WAIT;
1045 PZ_Unlock(mod->refLock);
1046 PORT_SetError(error);
1047 return NULL;
1051 * this function waits for a token event on any slot of a given module
1052 * This function should not be called from more than one thread of the
1053 * same process (though other threads can make other library calls
1054 * on this module while this call is blocked).
1056 PK11SlotInfo *
1057 SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags,
1058 PRIntervalTime latency)
1060 CK_SLOT_ID id;
1061 CK_RV crv;
1062 PK11SlotInfo *slot;
1064 if (!pk11_getFinalizeModulesOption() ||
1065 ((mod->cryptokiVersion.major == 2) &&
1066 (mod->cryptokiVersion.minor < 1))) {
1067 /* if we are sharing the module with other software in our
1068 * address space, we can't reliably use C_WaitForSlotEvent(),
1069 * and if the module is version 2.0, C_WaitForSlotEvent() doesn't
1070 * exist */
1071 return secmod_HandleWaitForSlotEvent(mod, flags, latency);
1073 /* first the the PKCS #11 call */
1074 PZ_Lock(mod->refLock);
1075 if (mod->evControlMask & SECMOD_END_WAIT) {
1076 goto end_wait;
1078 mod->evControlMask |= SECMOD_WAIT_PKCS11_EVENT;
1079 PZ_Unlock(mod->refLock);
1080 crv = PK11_GETTAB(mod)->C_WaitForSlotEvent(flags, &id, NULL);
1081 PZ_Lock(mod->refLock);
1082 mod->evControlMask &= ~SECMOD_WAIT_PKCS11_EVENT;
1083 /* if we are in end wait, short circuit now, don't even risk
1084 * going into secmod_HandleWaitForSlotEvent */
1085 if (mod->evControlMask & SECMOD_END_WAIT) {
1086 goto end_wait;
1088 PZ_Unlock(mod->refLock);
1089 if (crv == CKR_FUNCTION_NOT_SUPPORTED) {
1090 /* module doesn't support that call, simulate it */
1091 return secmod_HandleWaitForSlotEvent(mod, flags, latency);
1093 if (crv != CKR_OK) {
1094 /* we can get this error if finalize was called while we were
1095 * still running. This is the only way to force a C_WaitForSlotEvent()
1096 * to return in PKCS #11. In this case, just return that there
1097 * was no event. */
1098 if (crv == CKR_CRYPTOKI_NOT_INITIALIZED) {
1099 PORT_SetError(SEC_ERROR_NO_EVENT);
1100 } else {
1101 PORT_SetError(PK11_MapError(crv));
1103 return NULL;
1105 slot = SECMOD_FindSlotByID(mod, id);
1106 if (slot == NULL) {
1107 /* possibly a new slot that was added? */
1108 SECMOD_UpdateSlotList(mod);
1109 slot = SECMOD_FindSlotByID(mod, id);
1111 /* if we are in the delay period for the "isPresent" call, reset
1112 * the delay since we know things have probably changed... */
1113 if (slot && slot->nssToken && slot->nssToken->slot) {
1114 nssSlot_ResetDelay(slot->nssToken->slot);
1116 return slot;
1118 /* must be called with the lock on. */
1119 end_wait:
1120 mod->evControlMask &= ~SECMOD_END_WAIT;
1121 PZ_Unlock(mod->refLock);
1122 PORT_SetError(SEC_ERROR_NO_EVENT);
1123 return NULL;
1127 * This function "wakes up" WaitForAnyTokenEvent. It's a pretty drastic
1128 * function, possibly bringing down the pkcs #11 module in question. This
1129 * should be OK because 1) it does reinitialize, and 2) it should only be
1130 * called when we are on our way to tear the whole system down anyway.
1132 SECStatus
1133 SECMOD_CancelWait(SECMODModule *mod)
1135 unsigned long controlMask = mod->evControlMask;
1136 SECStatus rv = SECSuccess;
1137 CK_RV crv;
1139 PZ_Lock(mod->refLock);
1140 mod->evControlMask |= SECMOD_END_WAIT;
1141 controlMask = mod->evControlMask;
1142 if (controlMask & SECMOD_WAIT_PKCS11_EVENT) {
1143 if (!pk11_getFinalizeModulesOption()) {
1144 /* can't get here unless pk11_getFinalizeModulesOption is set */
1145 PORT_Assert(0);
1146 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1147 rv = SECFailure;
1148 goto loser;
1150 /* NOTE: this call will drop all transient keys, in progress
1151 * operations, and any authentication. This is the only documented
1152 * way to get WaitForSlotEvent to return. Also note: for non-thread
1153 * safe tokens, we need to hold the module lock, this is not yet at
1154 * system shutdown/startup time, so we need to protect these calls */
1155 crv = PK11_GETTAB(mod)->C_Finalize(NULL);
1156 /* ok, we slammed the module down, now we need to reinit it in case
1157 * we intend to use it again */
1158 if (CKR_OK == crv) {
1159 PRBool alreadyLoaded;
1160 secmod_ModuleInit(mod, &alreadyLoaded);
1161 } else {
1162 /* Finalized failed for some reason, notify the application
1163 * so maybe it has a prayer of recovering... */
1164 PORT_SetError(PK11_MapError(crv));
1165 rv = SECFailure;
1167 } else if (controlMask & SECMOD_WAIT_SIMULATED_EVENT) {
1168 mod->evControlMask &= ~SECMOD_WAIT_SIMULATED_EVENT;
1169 /* Simulated events will eventually timeout
1170 * and wake up in the loop */
1172 loser:
1173 PZ_Unlock(mod->refLock);
1174 return rv;
1178 * check to see if the module has removable slots that we may need to
1179 * watch for.
1181 PRBool
1182 SECMOD_HasRemovableSlots(SECMODModule *mod)
1184 int i;
1185 PRBool ret = PR_FALSE;
1187 SECMOD_GetReadLock(moduleLock);
1188 for (i=0; i < mod->slotCount; i++) {
1189 PK11SlotInfo *slot = mod->slots[i];
1190 /* perm modules are not inserted or removed */
1191 if (slot->isPerm) {
1192 continue;
1194 ret = PR_TRUE;
1195 break;
1197 SECMOD_ReleaseReadLock(moduleLock);
1198 return ret;
1202 * helper function to actually create and destroy user defined slots
1204 static SECStatus
1205 secmod_UserDBOp(CK_OBJECT_CLASS objClass, const char *sendSpec)
1207 PK11SlotInfo *slot = PK11_GetInternalSlot();
1208 CK_OBJECT_HANDLE dummy;
1209 CK_ATTRIBUTE template[2] ;
1210 CK_ATTRIBUTE *attrs = template;
1211 SECStatus rv;
1212 CK_RV crv;
1214 PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); attrs++;
1215 PK11_SETATTRS(attrs, CKA_NETSCAPE_MODULE_SPEC , (unsigned char *)sendSpec,
1216 strlen(sendSpec)+1); attrs++;
1218 PORT_Assert(attrs-template <= 2);
1221 PK11_EnterSlotMonitor(slot);
1222 crv = PK11_CreateNewObject(slot, slot->session,
1223 template, attrs-template, PR_FALSE, &dummy);
1224 PK11_ExitSlotMonitor(slot);
1226 if (crv != CKR_OK) {
1227 PK11_FreeSlot(slot);
1228 PORT_SetError(PK11_MapError(crv));
1229 return SECFailure;
1231 rv = SECMOD_UpdateSlotList(slot->module);
1232 PK11_FreeSlot(slot);
1233 return rv;
1237 * add escapes to protect quote characters...
1239 static char *
1240 nss_addEscape(const char *string, char quote)
1242 char *newString = 0;
1243 int escapes = 0, size = 0;
1244 const char *src;
1245 char *dest;
1247 for (src=string; *src ; src++) {
1248 if ((*src == quote) || (*src == '\\')) escapes++;
1249 size++;
1252 newString = PORT_ZAlloc(escapes+size+1);
1253 if (newString == NULL) {
1254 return NULL;
1257 for (src=string, dest=newString; *src; src++,dest++) {
1258 if ((*src == '\\') || (*src == quote)) {
1259 *dest++ = '\\';
1261 *dest = *src;
1264 return newString;
1267 static char *
1268 nss_doubleEscape(const char *string)
1270 char *round1 = NULL;
1271 char *retValue = NULL;
1272 if (string == NULL) {
1273 goto done;
1275 round1 = nss_addEscape(string,'>');
1276 if (round1) {
1277 retValue = nss_addEscape(round1,']');
1278 PORT_Free(round1);
1281 done:
1282 if (retValue == NULL) {
1283 retValue = PORT_Strdup("");
1285 return retValue;
1289 * Open a new database using the softoken. The caller is responsible for making
1290 * sure the module spec is correct and usable. The caller should ask for one
1291 * new database per call if the caller wants to get meaningful information
1292 * about the new database.
1294 * moduleSpec is the same data that you would pass to softoken at
1295 * initialization time under the 'tokens' options. For example, if you were
1296 * to specify tokens=<0x4=[configdir='./mybackup' tokenDescription='Backup']>
1297 * You would specify "configdir='./mybackup' tokenDescription='Backup'" as your
1298 * module spec here. The slot ID will be calculated for you by
1299 * SECMOD_OpenUserDB().
1301 * Typical parameters here are configdir, tokenDescription and flags.
1303 * a Full list is below:
1306 * configDir - The location of the databases for this token. If configDir is
1307 * not specified, and noCertDB and noKeyDB is not specified, the load
1308 * will fail.
1309 * certPrefix - Cert prefix for this token.
1310 * keyPrefix - Prefix for the key database for this token. (if not specified,
1311 * certPrefix will be used).
1312 * tokenDescription - The label value for this token returned in the
1313 * CK_TOKEN_INFO structure with an internationalize string (UTF8).
1314 * This value will be truncated at 32 bytes (no NULL, partial UTF8
1315 * characters dropped). You should specify a user friendly name here
1316 * as this is the value the token will be refered to in most
1317 * application UI's. You should make sure tokenDescription is unique.
1318 * slotDescription - The slotDescription value for this token returned
1319 * in the CK_SLOT_INFO structure with an internationalize string
1320 * (UTF8). This value will be truncated at 64 bytes (no NULL, partial
1321 * UTF8 characters dropped). This name will not change after the
1322 * database is closed. It should have some number to make this unique.
1323 * minPWLen - minimum password length for this token.
1324 * flags - comma separated list of flag values, parsed case-insensitive.
1325 * Valid flags are:
1326 * readOnly - Databases should be opened read only.
1327 * noCertDB - Don't try to open a certificate database.
1328 * noKeyDB - Don't try to open a key database.
1329 * forceOpen - Don't fail to initialize the token if the
1330 * databases could not be opened.
1331 * passwordRequired - zero length passwords are not acceptable
1332 * (valid only if there is a keyDB).
1333 * optimizeSpace - allocate smaller hash tables and lock tables.
1334 * When this flag is not specified, Softoken will allocate
1335 * large tables to prevent lock contention.
1337 PK11SlotInfo *
1338 SECMOD_OpenUserDB(const char *moduleSpec)
1340 CK_SLOT_ID slotID = 0;
1341 char *escSpec;
1342 char *sendSpec;
1343 SECStatus rv;
1344 SECMODModule *mod;
1345 CK_SLOT_ID i, minSlotID, maxSlotID;
1346 PRBool found = PR_FALSE;
1348 if (moduleSpec == NULL) {
1349 return NULL;
1352 /* NOTE: unlike most PK11 function, this does not return a reference
1353 * to the module */
1354 mod = SECMOD_GetInternalModule();
1355 if (!mod) {
1356 /* shouldn't happen */
1357 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1358 return NULL;
1361 /* look for a free slot id on the internal module */
1362 if (mod->isFIPS) {
1363 minSlotID = SFTK_MIN_FIPS_USER_SLOT_ID;
1364 maxSlotID = SFTK_MAX_FIPS_USER_SLOT_ID;
1365 } else {
1366 minSlotID = SFTK_MIN_USER_SLOT_ID;
1367 maxSlotID = SFTK_MAX_USER_SLOT_ID;
1369 for (i=minSlotID; i < maxSlotID; i++) {
1370 PK11SlotInfo *slot = SECMOD_LookupSlot(mod->moduleID, i);
1371 if (slot) {
1372 PRBool present = PK11_IsPresent(slot);
1373 PK11_FreeSlot(slot);
1374 if (present) {
1375 continue;
1377 /* not present means it's available */
1379 /* it doesn't exist or isn't present, it's available */
1380 slotID = i;
1381 found = PR_TRUE;
1382 break;
1385 if (!found) {
1386 /* this could happen if we try to open too many slots */
1387 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
1388 return NULL;
1391 /* we've found the slot, now build the moduleSpec */
1393 escSpec = nss_doubleEscape(moduleSpec);
1394 if (escSpec == NULL) {
1395 return NULL;
1397 sendSpec = PR_smprintf("tokens=[0x%x=<%s>]", slotID, escSpec);
1398 PORT_Free(escSpec);
1400 if (sendSpec == NULL) {
1401 /* PR_smprintf does not set no memory error */
1402 PORT_SetError(SEC_ERROR_NO_MEMORY);
1403 return NULL;
1405 rv = secmod_UserDBOp(CKO_NETSCAPE_NEWSLOT, sendSpec);
1406 PR_smprintf_free(sendSpec);
1407 if (rv != SECSuccess) {
1408 return NULL;
1411 return SECMOD_FindSlotByID(mod, slotID);
1415 * close an already opened user database. NOTE: the database must be
1416 * in the internal token, and must be one created with SECMOD_OpenUserDB().
1417 * Once the database is closed, the slot will remain as an empty slot
1418 * until it's used again with SECMOD_OpenUserDB().
1420 SECStatus
1421 SECMOD_CloseUserDB(PK11SlotInfo *slot)
1423 SECStatus rv;
1424 char *sendSpec;
1426 if (!slot->isInternal) {
1427 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1428 return SECFailure;
1431 sendSpec = PR_smprintf("tokens=[0x%x=<>]", slot->slotID);
1432 if (sendSpec == NULL) {
1433 /* PR_smprintf does not set no memory error */
1434 PORT_SetError(SEC_ERROR_NO_MEMORY);
1435 return SECFailure;
1437 rv = secmod_UserDBOp(CKO_NETSCAPE_DELSLOT, sendSpec);
1438 PR_smprintf_free(sendSpec);
1439 return rv;