comparison nss/lib/pk11wrap/pk11util.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
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/. */
4 /*
5 * Initialize the PCKS 11 subsystem
6 */
7 #include "seccomon.h"
8 #include "secmod.h"
9 #include "nssilock.h"
10 #include "secmodi.h"
11 #include "secmodti.h"
12 #include "pk11func.h"
13 #include "pki3hack.h"
14 #include "secerr.h"
15 #include "dev.h"
16 #include "utilpars.h"
17
18 /* these are for displaying error messages */
19
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;
27
28 int secmod_PrivateModuleCount = 0;
29
30 extern const PK11DefaultArrayEntry PK11_DefaultArray[];
31 extern const int num_pk11_default_mechanisms;
32
33
34 void
35 SECMOD_Init()
36 {
37 /* don't initialize twice */
38 if (moduleLock) return;
39
40 moduleLock = SECMOD_NewListLock();
41 PK11_InitSlotLists();
42 }
43
44
45 SECStatus
46 SECMOD_Shutdown()
47 {
48 /* destroy the lock */
49 if (moduleLock) {
50 SECMOD_DestroyListLock(moduleLock);
51 moduleLock = NULL;
52 }
53 /* free the internal module */
54 if (internalModule) {
55 SECMOD_DestroyModule(internalModule);
56 internalModule = NULL;
57 }
58
59 /* free the default database module */
60 if (defaultDBModule) {
61 SECMOD_DestroyModule(defaultDBModule);
62 defaultDBModule = NULL;
63 }
64
65 /* destroy the list */
66 if (modules) {
67 SECMOD_DestroyModuleList(modules);
68 modules = NULL;
69 }
70
71 if (modulesDB) {
72 SECMOD_DestroyModuleList(modulesDB);
73 modulesDB = NULL;
74 }
75
76 if (modulesUnload) {
77 SECMOD_DestroyModuleList(modulesUnload);
78 modulesUnload = NULL;
79 }
80
81 /* make all the slots and the lists go away */
82 PK11_DestroySlotLists();
83
84 nss_DumpModuleLog();
85
86 #ifdef DEBUG
87 if (PR_GetEnv("NSS_STRICT_SHUTDOWN")) {
88 PORT_Assert(secmod_PrivateModuleCount == 0);
89 }
90 #endif
91 if (secmod_PrivateModuleCount) {
92 PORT_SetError(SEC_ERROR_BUSY);
93 return SECFailure;
94 }
95 return SECSuccess;
96 }
97
98
99 /*
100 * retrieve the internal module
101 */
102 SECMODModule *
103 SECMOD_GetInternalModule(void)
104 {
105 return internalModule;
106 }
107
108
109 SECStatus
110 secmod_AddModuleToList(SECMODModuleList **moduleList,SECMODModule *newModule)
111 {
112 SECMODModuleList *mlp, *newListElement, *last = NULL;
113
114 newListElement = SECMOD_NewModuleListElement();
115 if (newListElement == NULL) {
116 return SECFailure;
117 }
118
119 newListElement->module = SECMOD_ReferenceModule(newModule);
120
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) {
126 last = mlp;
127 }
128
129 if (last == NULL) {
130 *moduleList = newListElement;
131 } else {
132 SECMOD_AddList(last,newListElement,NULL);
133 }
134 SECMOD_ReleaseWriteLock(moduleLock);
135 return SECSuccess;
136 }
137
138 SECStatus
139 SECMOD_AddModuleToList(SECMODModule *newModule)
140 {
141 if (newModule->internal && !internalModule) {
142 internalModule = SECMOD_ReferenceModule(newModule);
143 }
144 return secmod_AddModuleToList(&modules,newModule);
145 }
146
147 SECStatus
148 SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule)
149 {
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);
155 }
156 return secmod_AddModuleToList(&modulesDB,newModule);
157 }
158
159 SECStatus
160 SECMOD_AddModuleToUnloadList(SECMODModule *newModule)
161 {
162 return secmod_AddModuleToList(&modulesUnload,newModule);
163 }
164
165 /*
166 * get the list of PKCS11 modules that are available.
167 */
168 SECMODModuleList * SECMOD_GetDefaultModuleList() { return modules; }
169 SECMODModuleList *SECMOD_GetDeadModuleList() { return modulesUnload; }
170 SECMODModuleList *SECMOD_GetDBModuleList() { return modulesDB; }
171
172 /*
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.
182 */
183 SECMODListLock *SECMOD_GetDefaultModuleListLock() { return moduleLock; }
184
185
186
187 /*
188 * find a module by name, and add a reference to it.
189 * return that module.
190 */
191 SECMODModule *
192 SECMOD_FindModule(const char *name)
193 {
194 SECMODModuleList *mlp;
195 SECMODModule *module = NULL;
196
197 if (!moduleLock) {
198 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
199 return module;
200 }
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);
206 break;
207 }
208 }
209 if (module) {
210 goto found;
211 }
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);
216 break;
217 }
218 }
219
220 found:
221 SECMOD_ReleaseReadLock(moduleLock);
222
223 return module;
224 }
225
226 /*
227 * find a module by ID, and add a reference to it.
228 * return that module.
229 */
230 SECMODModule *
231 SECMOD_FindModuleByID(SECMODModuleID id)
232 {
233 SECMODModuleList *mlp;
234 SECMODModule *module = NULL;
235
236 if (!moduleLock) {
237 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
238 return module;
239 }
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);
245 break;
246 }
247 }
248 SECMOD_ReleaseReadLock(moduleLock);
249 if (module == NULL) {
250 PORT_SetError(SEC_ERROR_NO_MODULE);
251 }
252 return module;
253 }
254
255 /*
256 * find the function pointer.
257 */
258 SECMODModule *
259 secmod_FindModuleByFuncPtr(void *funcPtr)
260 {
261 SECMODModuleList *mlp;
262 SECMODModule *module = NULL;
263
264 SECMOD_GetReadLock(moduleLock);
265 for(mlp = modules; mlp != NULL; mlp = mlp->next) {
266 /* paranoia, shouldn't ever happen */
267 if (!mlp->module) {
268 continue;
269 }
270 if (funcPtr == mlp->module->functionList) {
271 module = mlp->module;
272 SECMOD_ReferenceModule(module);
273 break;
274 }
275 }
276 SECMOD_ReleaseReadLock(moduleLock);
277 if (module == NULL) {
278 PORT_SetError(SEC_ERROR_NO_MODULE);
279 }
280 return module;
281 }
282
283 /*
284 * Find the Slot based on ID and the module.
285 */
286 PK11SlotInfo *
287 SECMOD_FindSlotByID(SECMODModule *module, CK_SLOT_ID slotID)
288 {
289 int i;
290 PK11SlotInfo *slot = NULL;
291
292 if (!moduleLock) {
293 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
294 return slot;
295 }
296 SECMOD_GetReadLock(moduleLock);
297 for (i=0; i < module->slotCount; i++) {
298 PK11SlotInfo *cSlot = module->slots[i];
299
300 if (cSlot->slotID == slotID) {
301 slot = PK11_ReferenceSlot(cSlot);
302 break;
303 }
304 }
305 SECMOD_ReleaseReadLock(moduleLock);
306
307 if (slot == NULL) {
308 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
309 }
310 return slot;
311 }
312
313 /*
314 * lookup the Slot module based on it's module ID and slot ID.
315 */
316 PK11SlotInfo *
317 SECMOD_LookupSlot(SECMODModuleID moduleID,CK_SLOT_ID slotID)
318 {
319 SECMODModule *module;
320 PK11SlotInfo *slot;
321
322 module = SECMOD_FindModuleByID(moduleID);
323 if (module == NULL) return NULL;
324
325 slot = SECMOD_FindSlotByID(module, slotID);
326 SECMOD_DestroyModule(module);
327 return slot;
328 }
329
330
331 /*
332 * find a module by name or module pointer and delete it off the module list.
333 * optionally remove it from secmod.db.
334 */
335 SECStatus
336 SECMOD_DeleteModuleEx(const char *name, SECMODModule *mod,
337 int *type, PRBool permdb)
338 {
339 SECMODModuleList *mlp;
340 SECMODModuleList **mlpp;
341 SECStatus rv = SECFailure;
342
343 if (!moduleLock) {
344 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
345 return rv;
346 }
347
348 *type = SECMOD_EXTERNAL;
349
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) {
361 *type = SECMOD_FIPS;
362 } else {
363 *type = SECMOD_INTERNAL;
364 }
365 break;
366 }
367 }
368 if (mlp) {
369 goto found;
370 }
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);
379 rv = SECSuccess;
380 } else if (mlp->module->isFIPS) {
381 *type = SECMOD_FIPS;
382 } else {
383 *type = SECMOD_INTERNAL;
384 }
385 break;
386 }
387 }
388 found:
389 SECMOD_ReleaseWriteLock(moduleLock);
390
391
392 if (rv == SECSuccess) {
393 if (permdb) {
394 SECMOD_DeletePermDB(mlp->module);
395 }
396 SECMOD_DestroyModuleListElement(mlp);
397 }
398 return rv;
399 }
400
401 /*
402 * find a module by name and delete it off the module list
403 */
404 SECStatus
405 SECMOD_DeleteModule(const char *name, int *type)
406 {
407 return SECMOD_DeleteModuleEx(name, NULL, type, PR_TRUE);
408 }
409
410 /*
411 * find a module by name and delete it off the module list
412 */
413 SECStatus
414 SECMOD_DeleteInternalModule(const char *name)
415 {
416 SECMODModuleList *mlp;
417 SECMODModuleList **mlpp;
418 SECStatus rv = SECFailure;
419
420 if (pendingModule) {
421 PORT_SetError(SEC_ERROR_MODULE_STUCK);
422 return rv;
423 }
424 if (!moduleLock) {
425 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
426 return rv;
427 }
428
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);
437 }
438 break;
439 }
440 }
441 SECMOD_ReleaseWriteLock(moduleLock);
442
443 if (rv == SECSuccess) {
444 SECMODModule *newModule,*oldModule;
445
446 if (mlp->module->isFIPS) {
447 newModule = SECMOD_CreateModule(NULL, SECMOD_INT_NAME,
448 NULL, SECMOD_INT_FLAGS);
449 } else {
450 newModule = SECMOD_CreateModule(NULL, SECMOD_FIPS_NAME,
451 NULL, SECMOD_FIPS_FLAGS);
452 }
453 if (newModule) {
454 PK11SlotInfo *slot;
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);
459 if (slot) {
460 secmod_SetInternalKeySlotFlag(newModule, PR_TRUE);
461 }
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);
467 newModule = NULL;
468 }
469 /* free the old explicit internal key slot, we now have a new one */
470 if (slot) {
471 PK11_FreeSlot(slot);
472 }
473 }
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
478 * the list */
479 SECMOD_GetWriteLock(moduleLock);
480 for(mlp2 = modules; mlp2 != NULL; mlp2 = mlp->next) {
481 last = mlp2;
482 }
483
484 if (last == NULL) {
485 modules = mlp;
486 } else {
487 SECMOD_AddList(last,mlp,NULL);
488 }
489 SECMOD_ReleaseWriteLock(moduleLock);
490 return SECFailure;
491 }
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 */
498 }
499 return rv;
500 }
501
502 SECStatus
503 SECMOD_AddModule(SECMODModule *newModule)
504 {
505 SECStatus rv;
506 SECMODModule *oldModule;
507
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. */
517 }
518
519 rv = secmod_LoadPKCS11Module(newModule, NULL);
520 if (rv != SECSuccess) {
521 return rv;
522 }
523
524 if (newModule->parent == NULL) {
525 newModule->parent = SECMOD_ReferenceModule(defaultDBModule);
526 }
527
528 SECMOD_AddPermDB(newModule);
529 SECMOD_AddModuleToList(newModule);
530
531 rv = STAN_AddModuleToDefaultTrustDomain(newModule);
532
533 return rv;
534 }
535
536 PK11SlotInfo *
537 SECMOD_FindSlot(SECMODModule *module,const char *name)
538 {
539 int i;
540 char *string;
541 PK11SlotInfo *retSlot = NULL;
542
543 if (!moduleLock) {
544 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
545 return retSlot;
546 }
547 SECMOD_GetReadLock(moduleLock);
548 for (i=0; i < module->slotCount; i++) {
549 PK11SlotInfo *slot = module->slots[i];
550
551 if (PK11_IsPresent(slot)) {
552 string = PK11_GetTokenName(slot);
553 } else {
554 string = PK11_GetSlotName(slot);
555 }
556 if (PORT_Strcmp(name,string) == 0) {
557 retSlot = PK11_ReferenceSlot(slot);
558 break;
559 }
560 }
561 SECMOD_ReleaseReadLock(moduleLock);
562
563 if (retSlot == NULL) {
564 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
565 }
566 return retSlot;
567 }
568
569 SECStatus
570 PK11_GetModInfo(SECMODModule *mod,CK_INFO *info)
571 {
572 CK_RV crv;
573
574 if (mod->functionList == NULL) return SECFailure;
575 crv = PK11_GETTAB(mod)->C_GetInfo(info);
576 if (crv != CKR_OK) {
577 PORT_SetError(PK11_MapError(crv));
578 }
579 return (crv == CKR_OK) ? SECSuccess : SECFailure;
580 }
581
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
584 * SSL
585 */
586 PRBool
587 PK11_IsFIPS(void)
588 {
589 SECMODModule *mod = SECMOD_GetInternalModule();
590
591 if (mod && mod->internal) {
592 return mod->isFIPS;
593 }
594
595 return PR_FALSE;
596 }
597
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 */
601 SECStatus
602 SECMOD_AddNewModuleEx(const char* moduleName, const char* dllPath,
603 unsigned long defaultMechanismFlags,
604 unsigned long cipherEnableFlags,
605 char* modparms, char* nssparms)
606 {
607 SECMODModule *module;
608 SECStatus result = SECFailure;
609 int s,i;
610 PK11SlotInfo* slot;
611
612 PR_SetErrorText(0, NULL);
613 if (!moduleLock) {
614 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
615 return result;
616 }
617
618 module = SECMOD_CreateModule(dllPath, moduleName, modparms, nssparms);
619
620 if (module == NULL) {
621 return result;
622 }
623
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;
630
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 ? */
638 PRBool add =
639 (PK11_DefaultArray[i].flag & defaultMechanismFlags) ?
640 PR_TRUE: PR_FALSE;
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);
647 }
648 } /* for each slot of this module */
649 SECMOD_ReleaseReadLock(moduleLock);
650
651 /* delete and re-add module in order to save changes
652 * to the module */
653 result = SECMOD_UpdateModule(module);
654 }
655 }
656 }
657 SECMOD_DestroyModule(module);
658 return result;
659 }
660
661 SECStatus
662 SECMOD_AddNewModule(const char* moduleName, const char* dllPath,
663 unsigned long defaultMechanismFlags,
664 unsigned long cipherEnableFlags)
665 {
666 return SECMOD_AddNewModuleEx(moduleName, dllPath, defaultMechanismFlags,
667 cipherEnableFlags,
668 NULL, NULL); /* don't pass module or nss params */
669 }
670
671 SECStatus
672 SECMOD_UpdateModule(SECMODModule *module)
673 {
674 SECStatus result;
675
676 result = SECMOD_DeletePermDB(module);
677
678 if (result == SECSuccess) {
679 result = SECMOD_AddPermDB(module);
680 }
681 return result;
682 }
683
684 /* Public & Internal(Security Library) representation of
685 * encryption mechanism flags conversion */
686
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
690 */
691 unsigned long
692 SECMOD_PubMechFlagstoInternal(unsigned long publicFlags)
693 {
694 unsigned long internalFlags = publicFlags;
695
696 if (publicFlags & PUBLIC_MECH_RANDOM_FLAG) {
697 internalFlags &= ~PUBLIC_MECH_RANDOM_FLAG;
698 internalFlags |= SECMOD_RANDOM_FLAG;
699 }
700 return internalFlags;
701 }
702
703 unsigned long
704 SECMOD_InternaltoPubMechFlags(unsigned long internalFlags)
705 {
706 unsigned long publicFlags = internalFlags;
707
708 if (internalFlags & SECMOD_RANDOM_FLAG) {
709 publicFlags &= ~SECMOD_RANDOM_FLAG;
710 publicFlags |= PUBLIC_MECH_RANDOM_FLAG;
711 }
712 return publicFlags;
713 }
714
715
716 /* Public & Internal(Security Library) representation of */
717 /* cipher flags conversion */
718 /* Note: currently they are just stubs */
719 unsigned long
720 SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags)
721 {
722 return publicFlags;
723 }
724
725 unsigned long
726 SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags)
727 {
728 return internalFlags;
729 }
730
731 /* Funtion reports true if module of modType is installed/configured */
732 PRBool
733 SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags )
734 {
735 PRBool result = PR_FALSE;
736 SECMODModuleList *mods;
737
738 if (!moduleLock) {
739 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
740 return result;
741 }
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)) {
747 result = PR_TRUE;
748 }
749 }
750
751 SECMOD_ReleaseReadLock(moduleLock);
752 return result;
753 }
754
755 /* create a new ModuleListElement */
756 SECMODModuleList *SECMOD_NewModuleListElement(void)
757 {
758 SECMODModuleList *newModList;
759
760 newModList= (SECMODModuleList *) PORT_Alloc(sizeof(SECMODModuleList));
761 if (newModList) {
762 newModList->next = NULL;
763 newModList->module = NULL;
764 }
765 return newModList;
766 }
767
768 /*
769 * make a new reference to a module so It doesn't go away on us
770 */
771 SECMODModule *
772 SECMOD_ReferenceModule(SECMODModule *module)
773 {
774 PZ_Lock(module->refLock);
775 PORT_Assert(module->refCount > 0);
776
777 module->refCount++;
778 PZ_Unlock(module->refLock);
779 return module;
780 }
781
782
783 /* destroy an existing module */
784 void
785 SECMOD_DestroyModule(SECMODModule *module)
786 {
787 PRBool willfree = PR_FALSE;
788 int slotCount;
789 int i;
790
791 PZ_Lock(module->refLock);
792 if (module->refCount-- == 1) {
793 willfree = PR_TRUE;
794 }
795 PORT_Assert(willfree || (module->refCount > 0));
796 PZ_Unlock(module->refLock);
797
798 if (!willfree) {
799 return;
800 }
801
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);
807 }
808
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);
814 return;
815 }
816
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]);
822 }
823 PK11_FreeSlot(module->slots[i]);
824 }
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 */
827 }
828
829
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. */
832 void
833 SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot)
834 {
835 PRBool willfree = PR_FALSE;
836 if (fromSlot) {
837 PORT_Assert(module->refCount == 0);
838 PZ_Lock(module->refLock);
839 if (module->slotCount-- == 1) {
840 willfree = PR_TRUE;
841 }
842 PORT_Assert(willfree || (module->slotCount > 0));
843 PZ_Unlock(module->refLock);
844 if (!willfree) return;
845 }
846
847 if (module == pendingModule) {
848 pendingModule = NULL;
849 }
850
851 if (module->loaded) {
852 SECMOD_UnloadModule(module);
853 }
854 PZ_DestroyLock(module->refLock);
855 PORT_FreeArena(module->arena,PR_FALSE);
856 secmod_PrivateModuleCount--;
857 }
858
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 */
863 SECMODModuleList *
864 SECMOD_DestroyModuleListElement(SECMODModuleList *element)
865 {
866 SECMODModuleList *next = element->next;
867
868 if (element->module) {
869 SECMOD_DestroyModule(element->module);
870 element->module = NULL;
871 }
872 PORT_Free(element);
873 return next;
874 }
875
876
877 /*
878 * Destroy an entire module list
879 */
880 void
881 SECMOD_DestroyModuleList(SECMODModuleList *list)
882 {
883 SECMODModuleList *lp;
884
885 for ( lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) ;
886 }
887
888 PRBool
889 SECMOD_CanDeleteInternalModule(void)
890 {
891 return (PRBool) (pendingModule == NULL);
892 }
893
894 /*
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.
901 */
902 SECStatus
903 SECMOD_UpdateSlotList(SECMODModule *mod)
904 {
905 CK_RV crv;
906 CK_ULONG count;
907 CK_ULONG i, oldCount;
908 PRBool freeRef = PR_FALSE;
909 void *mark = NULL;
910 CK_ULONG *slotIDs = NULL;
911 PK11SlotInfo **newSlots = NULL;
912 PK11SlotInfo **oldSlots = NULL;
913
914 if (!moduleLock) {
915 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
916 return SECFailure;
917 }
918
919 /* C_GetSlotList is not a session function, make sure
920 * calls are serialized */
921 PZ_Lock(mod->refLock);
922 freeRef = PR_TRUE;
923 /* see if the number of slots have changed */
924 crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, NULL, &count);
925 if (crv != CKR_OK) {
926 PORT_SetError(PK11_MapError(crv));
927 goto loser;
928 }
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);
933 return SECSuccess;
934 }
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 );
938 goto loser;
939 }
940
941 /* get the new slot list */
942 slotIDs = PORT_NewArray(CK_SLOT_ID, count);
943 if (slotIDs == NULL) {
944 goto loser;
945 }
946
947 crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, slotIDs, &count);
948 if (crv != CKR_OK) {
949 PORT_SetError(PK11_MapError(crv));
950 goto loser;
951 }
952 freeRef = PR_FALSE;
953 PZ_Unlock(mod->refLock);
954 mark = PORT_ArenaMark(mod->arena);
955 if (mark == NULL) {
956 goto loser;
957 }
958 newSlots = PORT_ArenaZNewArray(mod->arena,PK11SlotInfo *,count);
959
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
962 * slots. */
963 for (i=0; i < count; i++) {
964 PK11SlotInfo *slot = SECMOD_FindSlotByID(mod,slotIDs[i]);
965
966 if (!slot) {
967 /* we have a new slot create a new slot data structure */
968 slot = PK11_NewSlotInfo(mod);
969 if (!slot) {
970 goto loser;
971 }
972 PK11_InitSlot(mod, slotIDs[i], slot);
973 STAN_InitTokenForSlotInfo(NULL, slot);
974 }
975 newSlots[i] = slot;
976 }
977 STAN_ResetTokenInterator(NULL);
978 PORT_Free(slotIDs);
979 slotIDs = NULL;
980 PORT_ArenaUnmark(mod->arena, mark);
981
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
986 * moduleLock */
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]);
998 }
999 return SECSuccess;
1000
1001 loser:
1002 if (freeRef) {
1003 PZ_Unlock(mod->refLock);
1004 }
1005 if (slotIDs) {
1006 PORT_Free(slotIDs);
1007 }
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. */
1012 if (newSlots) {
1013 for (i=0; i < count; i++) {
1014 if (newSlots[i] == NULL) {
1015 break; /* hit the last one */
1016 }
1017 PK11_FreeSlot(newSlots[i]);
1018 }
1019 }
1020 /* must come after freeing newSlots */
1021 if (mark) {
1022 PORT_ArenaRelease(mod->arena, mark);
1023 }
1024 return SECFailure;
1025 }
1026
1027 /*
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.
1031 */
1032 PK11SlotInfo *
1033 secmod_HandleWaitForSlotEvent(SECMODModule *mod, unsigned long flags,
1034 PRIntervalTime latency)
1035 {
1036 PRBool removableSlotsFound = PR_FALSE;
1037 int i;
1038 int error = SEC_ERROR_NO_EVENT;
1039
1040 if (!moduleLock) {
1041 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1042 return NULL;
1043 }
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);
1049 return NULL;
1050 }
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);
1056
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];
1061 PRUint16 series;
1062 PRBool present;
1063
1064 /* perm modules do not change */
1065 if (slot->isPerm) {
1066 continue;
1067 }
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);
1081 }
1082 }
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);
1088 break;
1089 }
1090 if (flags & CKF_DONT_BLOCK) {
1091 PZ_Lock(mod->refLock);
1092 break;
1093 }
1094 PR_Sleep(latency);
1095 PZ_Lock(mod->refLock);
1096 }
1097 mod->evControlMask &= ~SECMOD_END_WAIT;
1098 PZ_Unlock(mod->refLock);
1099 PORT_SetError(error);
1100 return NULL;
1101 }
1102
1103 /*
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).
1108 */
1109 PK11SlotInfo *
1110 SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags,
1111 PRIntervalTime latency)
1112 {
1113 CK_SLOT_ID id;
1114 CK_RV crv;
1115 PK11SlotInfo *slot;
1116
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
1123 * exist */
1124 return secmod_HandleWaitForSlotEvent(mod, flags, latency);
1125 }
1126 /* first the the PKCS #11 call */
1127 PZ_Lock(mod->refLock);
1128 if (mod->evControlMask & SECMOD_END_WAIT) {
1129 goto end_wait;
1130 }
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) {
1139 goto end_wait;
1140 }
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);
1145 }
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
1150 * was no event. */
1151 if (crv == CKR_CRYPTOKI_NOT_INITIALIZED) {
1152 PORT_SetError(SEC_ERROR_NO_EVENT);
1153 } else {
1154 PORT_SetError(PK11_MapError(crv));
1155 }
1156 return NULL;
1157 }
1158 slot = SECMOD_FindSlotByID(mod, id);
1159 if (slot == NULL) {
1160 /* possibly a new slot that was added? */
1161 SECMOD_UpdateSlotList(mod);
1162 slot = SECMOD_FindSlotByID(mod, id);
1163 }
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);
1168 }
1169 return slot;
1170
1171 /* must be called with the lock on. */
1172 end_wait:
1173 mod->evControlMask &= ~SECMOD_END_WAIT;
1174 PZ_Unlock(mod->refLock);
1175 PORT_SetError(SEC_ERROR_NO_EVENT);
1176 return NULL;
1177 }
1178
1179 /*
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.
1184 */
1185 SECStatus
1186 SECMOD_CancelWait(SECMODModule *mod)
1187 {
1188 unsigned long controlMask = mod->evControlMask;
1189 SECStatus rv = SECSuccess;
1190 CK_RV crv;
1191
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 */
1198 PORT_Assert(0);
1199 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1200 rv = SECFailure;
1201 goto loser;
1202 }
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);
1214 } else {
1215 /* Finalized failed for some reason, notify the application
1216 * so maybe it has a prayer of recovering... */
1217 PORT_SetError(PK11_MapError(crv));
1218 rv = SECFailure;
1219 }
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 */
1224 }
1225 loser:
1226 PZ_Unlock(mod->refLock);
1227 return rv;
1228 }
1229
1230 /*
1231 * check to see if the module has removable slots that we may need to
1232 * watch for.
1233 */
1234 PRBool
1235 SECMOD_HasRemovableSlots(SECMODModule *mod)
1236 {
1237 int i;
1238 PRBool ret = PR_FALSE;
1239
1240 if (!moduleLock) {
1241 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1242 return ret;
1243 }
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 */
1248 if (slot->isPerm) {
1249 continue;
1250 }
1251 ret = PR_TRUE;
1252 break;
1253 }
1254 if (mod->slotCount == 0 ) {
1255 ret = PR_TRUE;
1256 }
1257 SECMOD_ReleaseReadLock(moduleLock);
1258 return ret;
1259 }
1260
1261 /*
1262 * helper function to actually create and destroy user defined slots
1263 */
1264 static SECStatus
1265 secmod_UserDBOp(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass,
1266 const char *sendSpec)
1267 {
1268 CK_OBJECT_HANDLE dummy;
1269 CK_ATTRIBUTE template[2] ;
1270 CK_ATTRIBUTE *attrs = template;
1271 CK_RV crv;
1272
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++;
1276
1277 PORT_Assert(attrs-template <= 2);
1278
1279
1280 PK11_EnterSlotMonitor(slot);
1281 crv = PK11_CreateNewObject(slot, slot->session,
1282 template, attrs-template, PR_FALSE, &dummy);
1283 PK11_ExitSlotMonitor(slot);
1284
1285 if (crv != CKR_OK) {
1286 PORT_SetError(PK11_MapError(crv));
1287 return SECFailure;
1288 }
1289 return SECMOD_UpdateSlotList(slot->module);
1290 }
1291
1292 /*
1293 * return true if the selected slot ID is not present or doesn't exist
1294 */
1295 static PRBool
1296 secmod_SlotIsEmpty(SECMODModule *mod, CK_SLOT_ID slotID)
1297 {
1298 PK11SlotInfo *slot = SECMOD_LookupSlot(mod->moduleID, slotID);
1299 if (slot) {
1300 PRBool present = PK11_IsPresent(slot);
1301 PK11_FreeSlot(slot);
1302 if (present) {
1303 return PR_FALSE;
1304 }
1305 }
1306 /* it doesn't exist or isn't present, it's available */
1307 return PR_TRUE;
1308 }
1309
1310 /*
1311 * Find an unused slot id in module.
1312 */
1313 static CK_SLOT_ID
1314 secmod_FindFreeSlot(SECMODModule *mod)
1315 {
1316 CK_SLOT_ID i, minSlotID, maxSlotID;
1317
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;
1322 } else {
1323 minSlotID = SFTK_MIN_USER_SLOT_ID;
1324 maxSlotID = SFTK_MAX_USER_SLOT_ID;
1325 }
1326 for (i=minSlotID; i < maxSlotID; i++) {
1327 if (secmod_SlotIsEmpty(mod,i)) {
1328 return i;
1329 }
1330 }
1331 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
1332 return (CK_SLOT_ID) -1;
1333 }
1334
1335 /*
1336 * Attempt to open a new slot.
1337 *
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.
1344 *
1345 * NewSlots can be closed with SECMOD_CloseUserDB();
1346 *
1347 * Modulespec is module dependent.
1348 */
1349 PK11SlotInfo *
1350 SECMOD_OpenNewSlot(SECMODModule *mod, const char *moduleSpec)
1351 {
1352 CK_SLOT_ID slotID = 0;
1353 PK11SlotInfo *slot;
1354 char *escSpec;
1355 char *sendSpec;
1356 SECStatus rv;
1357
1358 slotID = secmod_FindFreeSlot(mod);
1359 if (slotID == (CK_SLOT_ID) -1) {
1360 return NULL;
1361 }
1362
1363 if (mod->slotCount == 0) {
1364 return NULL;
1365 }
1366
1367 /* just grab the first slot in the module, any present slot should work */
1368 slot = PK11_ReferenceSlot(mod->slots[0]);
1369 if (slot == NULL) {
1370 return NULL;
1371 }
1372
1373 /* we've found the slot, now build the moduleSpec */
1374 escSpec = NSSUTIL_DoubleEscape(moduleSpec, '>', ']');
1375 if (escSpec == NULL) {
1376 PK11_FreeSlot(slot);
1377 return NULL;
1378 }
1379 sendSpec = PR_smprintf("tokens=[0x%x=<%s>]", slotID, escSpec);
1380 PORT_Free(escSpec);
1381
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);
1386 return NULL;
1387 }
1388 rv = secmod_UserDBOp(slot, CKO_NETSCAPE_NEWSLOT, sendSpec);
1389 PR_smprintf_free(sendSpec);
1390 PK11_FreeSlot(slot);
1391 if (rv != SECSuccess) {
1392 return NULL;
1393 }
1394
1395 slot = SECMOD_FindSlotByID(mod, slotID);
1396 if (slot) {
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);
1401 }
1402 /* force the slot info structures to properly reset */
1403 (void)PK11_IsPresent(slot);
1404 }
1405 return slot;
1406 }
1407
1408 /*
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.
1413 *
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().
1420 *
1421 * Typical parameters here are configdir, tokenDescription and flags.
1422 *
1423 * a Full list is below:
1424 *
1425 *
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
1428 * will fail.
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.
1445 * Valid flags are:
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.
1456 */
1457 PK11SlotInfo *
1458 SECMOD_OpenUserDB(const char *moduleSpec)
1459 {
1460 SECMODModule *mod;
1461
1462 if (moduleSpec == NULL) {
1463 return NULL;
1464 }
1465
1466 /* NOTE: unlike most PK11 function, this does not return a reference
1467 * to the module */
1468 mod = SECMOD_GetInternalModule();
1469 if (!mod) {
1470 /* shouldn't happen */
1471 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1472 return NULL;
1473 }
1474 return SECMOD_OpenNewSlot(mod, moduleSpec);
1475 }
1476
1477
1478 /*
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().
1483 */
1484 SECStatus
1485 SECMOD_CloseUserDB(PK11SlotInfo *slot)
1486 {
1487 SECStatus rv;
1488 char *sendSpec;
1489
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);
1494 return SECFailure;
1495 }
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);
1504 }
1505 return rv;
1506 }
1507
1508 /*
1509 * Restart PKCS #11 modules after a fork(). See secmod.h for more information.
1510 */
1511 SECStatus
1512 SECMOD_RestartModules(PRBool force)
1513 {
1514 SECMODModuleList *mlp;
1515 SECStatus rrv = SECSuccess;
1516 int lastError = 0;
1517
1518 if (!moduleLock) {
1519 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1520 return SECFailure;
1521 }
1522
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;
1527 CK_ULONG count;
1528 SECStatus rv;
1529 int i;
1530
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();
1546 rrv = rv;
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;
1551 }
1552 continue;
1553 }
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();
1565 rrv = rv;
1566 /* disable the token */
1567 mod->slots[i]->disabled = PR_TRUE;
1568 mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1569 }
1570 }
1571 }
1572 }
1573 SECMOD_ReleaseReadLock(moduleLock);
1574
1575 /*
1576 * on multiple failures, we are only returning the lastError. The caller
1577 * can determine which slots are bad by calling PK11_IsDisabled().
1578 */
1579 if (rrv != SECSuccess) {
1580 /* restore the last error code */
1581 PORT_SetError(lastError);
1582 }
1583
1584 return rrv;
1585 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)