Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: nss/lib/pk11wrap/pk11util.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/pk11wrap/pk11slot.c ('k') | nss/lib/pk11wrap/secmod.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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_GetEnvSecure("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 if (result != SECSuccess) {
644 SECMOD_ReleaseReadLock(moduleLock);
645 SECMOD_DestroyModule(module);
646 return result;
647 }
648 } /* for each mechanism */
649 /* disable each slot if the defaultFlags say so */
650 if (defaultMechanismFlags & PK11_DISABLE_FLAG) {
651 PK11_UserDisableSlot(slot);
652 }
653 } /* for each slot of this module */
654 SECMOD_ReleaseReadLock(moduleLock);
655
656 /* delete and re-add module in order to save changes
657 * to the module */
658 result = SECMOD_UpdateModule(module);
659 }
660 }
661 }
662 SECMOD_DestroyModule(module);
663 return result;
664 }
665
666 SECStatus
667 SECMOD_AddNewModule(const char* moduleName, const char* dllPath,
668 unsigned long defaultMechanismFlags,
669 unsigned long cipherEnableFlags)
670 {
671 return SECMOD_AddNewModuleEx(moduleName, dllPath, defaultMechanismFlags,
672 cipherEnableFlags,
673 NULL, NULL); /* don't pass module or nss params */
674 }
675
676 SECStatus
677 SECMOD_UpdateModule(SECMODModule *module)
678 {
679 SECStatus result;
680
681 result = SECMOD_DeletePermDB(module);
682
683 if (result == SECSuccess) {
684 result = SECMOD_AddPermDB(module);
685 }
686 return result;
687 }
688
689 /* Public & Internal(Security Library) representation of
690 * encryption mechanism flags conversion */
691
692 /* Currently, the only difference is that internal representation
693 * puts RANDOM_FLAG at bit 31 (Most-significant bit), but
694 * public representation puts this bit at bit 28
695 */
696 unsigned long
697 SECMOD_PubMechFlagstoInternal(unsigned long publicFlags)
698 {
699 unsigned long internalFlags = publicFlags;
700
701 if (publicFlags & PUBLIC_MECH_RANDOM_FLAG) {
702 internalFlags &= ~PUBLIC_MECH_RANDOM_FLAG;
703 internalFlags |= SECMOD_RANDOM_FLAG;
704 }
705 return internalFlags;
706 }
707
708 unsigned long
709 SECMOD_InternaltoPubMechFlags(unsigned long internalFlags)
710 {
711 unsigned long publicFlags = internalFlags;
712
713 if (internalFlags & SECMOD_RANDOM_FLAG) {
714 publicFlags &= ~SECMOD_RANDOM_FLAG;
715 publicFlags |= PUBLIC_MECH_RANDOM_FLAG;
716 }
717 return publicFlags;
718 }
719
720
721 /* Public & Internal(Security Library) representation of */
722 /* cipher flags conversion */
723 /* Note: currently they are just stubs */
724 unsigned long
725 SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags)
726 {
727 return publicFlags;
728 }
729
730 unsigned long
731 SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags)
732 {
733 return internalFlags;
734 }
735
736 /* Funtion reports true if module of modType is installed/configured */
737 PRBool
738 SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags )
739 {
740 PRBool result = PR_FALSE;
741 SECMODModuleList *mods;
742
743 if (!moduleLock) {
744 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
745 return result;
746 }
747 SECMOD_GetReadLock(moduleLock);
748 mods = SECMOD_GetDefaultModuleList();
749 for ( ; mods != NULL; mods = mods->next) {
750 if (mods->module->ssl[0] &
751 SECMOD_PubCipherFlagstoInternal(pubCipherEnableFlags)) {
752 result = PR_TRUE;
753 }
754 }
755
756 SECMOD_ReleaseReadLock(moduleLock);
757 return result;
758 }
759
760 /* create a new ModuleListElement */
761 SECMODModuleList *SECMOD_NewModuleListElement(void)
762 {
763 SECMODModuleList *newModList;
764
765 newModList= (SECMODModuleList *) PORT_Alloc(sizeof(SECMODModuleList));
766 if (newModList) {
767 newModList->next = NULL;
768 newModList->module = NULL;
769 }
770 return newModList;
771 }
772
773 /*
774 * make a new reference to a module so It doesn't go away on us
775 */
776 SECMODModule *
777 SECMOD_ReferenceModule(SECMODModule *module)
778 {
779 PZ_Lock(module->refLock);
780 PORT_Assert(module->refCount > 0);
781
782 module->refCount++;
783 PZ_Unlock(module->refLock);
784 return module;
785 }
786
787
788 /* destroy an existing module */
789 void
790 SECMOD_DestroyModule(SECMODModule *module)
791 {
792 PRBool willfree = PR_FALSE;
793 int slotCount;
794 int i;
795
796 PZ_Lock(module->refLock);
797 if (module->refCount-- == 1) {
798 willfree = PR_TRUE;
799 }
800 PORT_Assert(willfree || (module->refCount > 0));
801 PZ_Unlock(module->refLock);
802
803 if (!willfree) {
804 return;
805 }
806
807 if (module->parent != NULL) {
808 SECMODModule *parent = module->parent;
809 /* paranoia, don't loop forever if the modules are looped */
810 module->parent = NULL;
811 SECMOD_DestroyModule(parent);
812 }
813
814 /* slots can't really disappear until our module starts freeing them,
815 * so this check is safe */
816 slotCount = module->slotCount;
817 if (slotCount == 0) {
818 SECMOD_SlotDestroyModule(module,PR_FALSE);
819 return;
820 }
821
822 /* now free all out slots, when they are done, they will cause the
823 * module to disappear altogether */
824 for (i=0 ; i < slotCount; i++) {
825 if (!module->slots[i]->disabled) {
826 PK11_ClearSlotList(module->slots[i]);
827 }
828 PK11_FreeSlot(module->slots[i]);
829 }
830 /* WARNING: once the last slot has been freed is it possible (even likely)
831 * that module is no more... touching it now is a good way to go south */
832 }
833
834
835 /* we can only get here if we've destroyed the module, or some one has
836 * erroneously freed a slot that wasn't referenced. */
837 void
838 SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot)
839 {
840 PRBool willfree = PR_FALSE;
841 if (fromSlot) {
842 PORT_Assert(module->refCount == 0);
843 PZ_Lock(module->refLock);
844 if (module->slotCount-- == 1) {
845 willfree = PR_TRUE;
846 }
847 PORT_Assert(willfree || (module->slotCount > 0));
848 PZ_Unlock(module->refLock);
849 if (!willfree) return;
850 }
851
852 if (module == pendingModule) {
853 pendingModule = NULL;
854 }
855
856 if (module->loaded) {
857 SECMOD_UnloadModule(module);
858 }
859 PZ_DestroyLock(module->refLock);
860 PORT_FreeArena(module->arena,PR_FALSE);
861 secmod_PrivateModuleCount--;
862 }
863
864 /* destroy a list element
865 * this destroys a single element, and returns the next element
866 * on the chain. It makes it easy to implement for loops to delete
867 * the chain. It also make deleting a single element easy */
868 SECMODModuleList *
869 SECMOD_DestroyModuleListElement(SECMODModuleList *element)
870 {
871 SECMODModuleList *next = element->next;
872
873 if (element->module) {
874 SECMOD_DestroyModule(element->module);
875 element->module = NULL;
876 }
877 PORT_Free(element);
878 return next;
879 }
880
881
882 /*
883 * Destroy an entire module list
884 */
885 void
886 SECMOD_DestroyModuleList(SECMODModuleList *list)
887 {
888 SECMODModuleList *lp;
889
890 for ( lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) ;
891 }
892
893 PRBool
894 SECMOD_CanDeleteInternalModule(void)
895 {
896 return (PRBool) (pendingModule == NULL);
897 }
898
899 /*
900 * check to see if the module has added new slots. PKCS 11 v2.20 allows for
901 * modules to add new slots, but never remove them. Slots cannot be added
902 * between a call to C_GetSlotLlist(Flag, NULL, &count) and the subsequent
903 * C_GetSlotList(flag, &data, &count) so that the array doesn't accidently
904 * grow on the caller. It is permissible for the slots to increase between
905 * successive calls with NULL to get the size.
906 */
907 SECStatus
908 SECMOD_UpdateSlotList(SECMODModule *mod)
909 {
910 CK_RV crv;
911 CK_ULONG count;
912 CK_ULONG i, oldCount;
913 PRBool freeRef = PR_FALSE;
914 void *mark = NULL;
915 CK_ULONG *slotIDs = NULL;
916 PK11SlotInfo **newSlots = NULL;
917 PK11SlotInfo **oldSlots = NULL;
918
919 if (!moduleLock) {
920 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
921 return SECFailure;
922 }
923
924 /* C_GetSlotList is not a session function, make sure
925 * calls are serialized */
926 PZ_Lock(mod->refLock);
927 freeRef = PR_TRUE;
928 /* see if the number of slots have changed */
929 crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, NULL, &count);
930 if (crv != CKR_OK) {
931 PORT_SetError(PK11_MapError(crv));
932 goto loser;
933 }
934 /* nothing new, blow out early, we want this function to be quick
935 * and cheap in the normal case */
936 if (count == mod->slotCount) {
937 PZ_Unlock(mod->refLock);
938 return SECSuccess;
939 }
940 if (count < (CK_ULONG)mod->slotCount) {
941 /* shouldn't happen with a properly functioning PKCS #11 module */
942 PORT_SetError( SEC_ERROR_INCOMPATIBLE_PKCS11 );
943 goto loser;
944 }
945
946 /* get the new slot list */
947 slotIDs = PORT_NewArray(CK_SLOT_ID, count);
948 if (slotIDs == NULL) {
949 goto loser;
950 }
951
952 crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, slotIDs, &count);
953 if (crv != CKR_OK) {
954 PORT_SetError(PK11_MapError(crv));
955 goto loser;
956 }
957 freeRef = PR_FALSE;
958 PZ_Unlock(mod->refLock);
959 mark = PORT_ArenaMark(mod->arena);
960 if (mark == NULL) {
961 goto loser;
962 }
963 newSlots = PORT_ArenaZNewArray(mod->arena,PK11SlotInfo *,count);
964
965 /* walk down the new slot ID list returned from the module. We keep
966 * the old slots which match a returned ID, and we initialize the new
967 * slots. */
968 for (i=0; i < count; i++) {
969 PK11SlotInfo *slot = SECMOD_FindSlotByID(mod,slotIDs[i]);
970
971 if (!slot) {
972 /* we have a new slot create a new slot data structure */
973 slot = PK11_NewSlotInfo(mod);
974 if (!slot) {
975 goto loser;
976 }
977 PK11_InitSlot(mod, slotIDs[i], slot);
978 STAN_InitTokenForSlotInfo(NULL, slot);
979 }
980 newSlots[i] = slot;
981 }
982 STAN_ResetTokenInterator(NULL);
983 PORT_Free(slotIDs);
984 slotIDs = NULL;
985 PORT_ArenaUnmark(mod->arena, mark);
986
987 /* until this point we're still using the old slot list. Now we update
988 * module slot list. We update the slots (array) first then the count,
989 * since we've already guarrenteed that count has increased (just in case
990 * someone is looking at the slots field of module without holding the
991 * moduleLock */
992 SECMOD_GetWriteLock(moduleLock);
993 oldCount =mod->slotCount;
994 oldSlots = mod->slots;
995 mod->slots = newSlots; /* typical arena 'leak'... old mod->slots is
996 * allocated out of the module arena and won't
997 * be freed until the module is freed */
998 mod->slotCount = count;
999 SECMOD_ReleaseWriteLock(moduleLock);
1000 /* free our old references before forgetting about oldSlot*/
1001 for (i=0; i < oldCount; i++) {
1002 PK11_FreeSlot(oldSlots[i]);
1003 }
1004 return SECSuccess;
1005
1006 loser:
1007 if (freeRef) {
1008 PZ_Unlock(mod->refLock);
1009 }
1010 if (slotIDs) {
1011 PORT_Free(slotIDs);
1012 }
1013 /* free all the slots we allocated. newSlots are part of the
1014 * mod arena. NOTE: the newSlots array contain both new and old
1015 * slots, but we kept a reference to the old slots when we built the new
1016 * array, so we need to free all the slots in newSlots array. */
1017 if (newSlots) {
1018 for (i=0; i < count; i++) {
1019 if (newSlots[i] == NULL) {
1020 break; /* hit the last one */
1021 }
1022 PK11_FreeSlot(newSlots[i]);
1023 }
1024 }
1025 /* must come after freeing newSlots */
1026 if (mark) {
1027 PORT_ArenaRelease(mod->arena, mark);
1028 }
1029 return SECFailure;
1030 }
1031
1032 /*
1033 * this handles modules that do not support C_WaitForSlotEvent().
1034 * The internal flags are stored. Note that C_WaitForSlotEvent() does not
1035 * have a timeout, so we don't have one for handleWaitForSlotEvent() either.
1036 */
1037 PK11SlotInfo *
1038 secmod_HandleWaitForSlotEvent(SECMODModule *mod, unsigned long flags,
1039 PRIntervalTime latency)
1040 {
1041 PRBool removableSlotsFound = PR_FALSE;
1042 int i;
1043 int error = SEC_ERROR_NO_EVENT;
1044
1045 if (!moduleLock) {
1046 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1047 return NULL;
1048 }
1049 PZ_Lock(mod->refLock);
1050 if (mod->evControlMask & SECMOD_END_WAIT) {
1051 mod->evControlMask &= ~SECMOD_END_WAIT;
1052 PZ_Unlock(mod->refLock);
1053 PORT_SetError(SEC_ERROR_NO_EVENT);
1054 return NULL;
1055 }
1056 mod->evControlMask |= SECMOD_WAIT_SIMULATED_EVENT;
1057 while (mod->evControlMask & SECMOD_WAIT_SIMULATED_EVENT) {
1058 PZ_Unlock(mod->refLock);
1059 /* now is a good time to see if new slots have been added */
1060 SECMOD_UpdateSlotList(mod);
1061
1062 /* loop through all the slots on a module */
1063 SECMOD_GetReadLock(moduleLock);
1064 for (i=0; i < mod->slotCount; i++) {
1065 PK11SlotInfo *slot = mod->slots[i];
1066 PRUint16 series;
1067 PRBool present;
1068
1069 /* perm modules do not change */
1070 if (slot->isPerm) {
1071 continue;
1072 }
1073 removableSlotsFound = PR_TRUE;
1074 /* simulate the PKCS #11 module flags. are the flags different
1075 * from the last time we called? */
1076 series = slot->series;
1077 present = PK11_IsPresent(slot);
1078 if ((slot->flagSeries != series) || (slot->flagState != present)) {
1079 slot->flagState = present;
1080 slot->flagSeries = series;
1081 SECMOD_ReleaseReadLock(moduleLock);
1082 PZ_Lock(mod->refLock);
1083 mod->evControlMask &= ~SECMOD_END_WAIT;
1084 PZ_Unlock(mod->refLock);
1085 return PK11_ReferenceSlot(slot);
1086 }
1087 }
1088 SECMOD_ReleaseReadLock(moduleLock);
1089 /* if everything was perm modules, don't lock up forever */
1090 if ((mod->slotCount !=0) && !removableSlotsFound) {
1091 error =SEC_ERROR_NO_SLOT_SELECTED;
1092 PZ_Lock(mod->refLock);
1093 break;
1094 }
1095 if (flags & CKF_DONT_BLOCK) {
1096 PZ_Lock(mod->refLock);
1097 break;
1098 }
1099 PR_Sleep(latency);
1100 PZ_Lock(mod->refLock);
1101 }
1102 mod->evControlMask &= ~SECMOD_END_WAIT;
1103 PZ_Unlock(mod->refLock);
1104 PORT_SetError(error);
1105 return NULL;
1106 }
1107
1108 /*
1109 * this function waits for a token event on any slot of a given module
1110 * This function should not be called from more than one thread of the
1111 * same process (though other threads can make other library calls
1112 * on this module while this call is blocked).
1113 */
1114 PK11SlotInfo *
1115 SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags,
1116 PRIntervalTime latency)
1117 {
1118 CK_SLOT_ID id;
1119 CK_RV crv;
1120 PK11SlotInfo *slot;
1121
1122 if (!pk11_getFinalizeModulesOption() ||
1123 ((mod->cryptokiVersion.major == 2) &&
1124 (mod->cryptokiVersion.minor < 1))) {
1125 /* if we are sharing the module with other software in our
1126 * address space, we can't reliably use C_WaitForSlotEvent(),
1127 * and if the module is version 2.0, C_WaitForSlotEvent() doesn't
1128 * exist */
1129 return secmod_HandleWaitForSlotEvent(mod, flags, latency);
1130 }
1131 /* first the the PKCS #11 call */
1132 PZ_Lock(mod->refLock);
1133 if (mod->evControlMask & SECMOD_END_WAIT) {
1134 goto end_wait;
1135 }
1136 mod->evControlMask |= SECMOD_WAIT_PKCS11_EVENT;
1137 PZ_Unlock(mod->refLock);
1138 crv = PK11_GETTAB(mod)->C_WaitForSlotEvent(flags, &id, NULL);
1139 PZ_Lock(mod->refLock);
1140 mod->evControlMask &= ~SECMOD_WAIT_PKCS11_EVENT;
1141 /* if we are in end wait, short circuit now, don't even risk
1142 * going into secmod_HandleWaitForSlotEvent */
1143 if (mod->evControlMask & SECMOD_END_WAIT) {
1144 goto end_wait;
1145 }
1146 PZ_Unlock(mod->refLock);
1147 if (crv == CKR_FUNCTION_NOT_SUPPORTED) {
1148 /* module doesn't support that call, simulate it */
1149 return secmod_HandleWaitForSlotEvent(mod, flags, latency);
1150 }
1151 if (crv != CKR_OK) {
1152 /* we can get this error if finalize was called while we were
1153 * still running. This is the only way to force a C_WaitForSlotEvent()
1154 * to return in PKCS #11. In this case, just return that there
1155 * was no event. */
1156 if (crv == CKR_CRYPTOKI_NOT_INITIALIZED) {
1157 PORT_SetError(SEC_ERROR_NO_EVENT);
1158 } else {
1159 PORT_SetError(PK11_MapError(crv));
1160 }
1161 return NULL;
1162 }
1163 slot = SECMOD_FindSlotByID(mod, id);
1164 if (slot == NULL) {
1165 /* possibly a new slot that was added? */
1166 SECMOD_UpdateSlotList(mod);
1167 slot = SECMOD_FindSlotByID(mod, id);
1168 }
1169 /* if we are in the delay period for the "isPresent" call, reset
1170 * the delay since we know things have probably changed... */
1171 if (slot && slot->nssToken && slot->nssToken->slot) {
1172 nssSlot_ResetDelay(slot->nssToken->slot);
1173 }
1174 return slot;
1175
1176 /* must be called with the lock on. */
1177 end_wait:
1178 mod->evControlMask &= ~SECMOD_END_WAIT;
1179 PZ_Unlock(mod->refLock);
1180 PORT_SetError(SEC_ERROR_NO_EVENT);
1181 return NULL;
1182 }
1183
1184 /*
1185 * This function "wakes up" WaitForAnyTokenEvent. It's a pretty drastic
1186 * function, possibly bringing down the pkcs #11 module in question. This
1187 * should be OK because 1) it does reinitialize, and 2) it should only be
1188 * called when we are on our way to tear the whole system down anyway.
1189 */
1190 SECStatus
1191 SECMOD_CancelWait(SECMODModule *mod)
1192 {
1193 unsigned long controlMask;
1194 SECStatus rv = SECSuccess;
1195 CK_RV crv;
1196
1197 PZ_Lock(mod->refLock);
1198 mod->evControlMask |= SECMOD_END_WAIT;
1199 controlMask = mod->evControlMask;
1200 if (controlMask & SECMOD_WAIT_PKCS11_EVENT) {
1201 if (!pk11_getFinalizeModulesOption()) {
1202 /* can't get here unless pk11_getFinalizeModulesOption is set */
1203 PORT_Assert(0);
1204 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1205 rv = SECFailure;
1206 goto loser;
1207 }
1208 /* NOTE: this call will drop all transient keys, in progress
1209 * operations, and any authentication. This is the only documented
1210 * way to get WaitForSlotEvent to return. Also note: for non-thread
1211 * safe tokens, we need to hold the module lock, this is not yet at
1212 * system shutdown/startup time, so we need to protect these calls */
1213 crv = PK11_GETTAB(mod)->C_Finalize(NULL);
1214 /* ok, we slammed the module down, now we need to reinit it in case
1215 * we intend to use it again */
1216 if (CKR_OK == crv) {
1217 PRBool alreadyLoaded;
1218 secmod_ModuleInit(mod, NULL, &alreadyLoaded);
1219 } else {
1220 /* Finalized failed for some reason, notify the application
1221 * so maybe it has a prayer of recovering... */
1222 PORT_SetError(PK11_MapError(crv));
1223 rv = SECFailure;
1224 }
1225 } else if (controlMask & SECMOD_WAIT_SIMULATED_EVENT) {
1226 mod->evControlMask &= ~SECMOD_WAIT_SIMULATED_EVENT;
1227 /* Simulated events will eventually timeout
1228 * and wake up in the loop */
1229 }
1230 loser:
1231 PZ_Unlock(mod->refLock);
1232 return rv;
1233 }
1234
1235 /*
1236 * check to see if the module has removable slots that we may need to
1237 * watch for.
1238 */
1239 PRBool
1240 SECMOD_HasRemovableSlots(SECMODModule *mod)
1241 {
1242 int i;
1243 PRBool ret = PR_FALSE;
1244
1245 if (!moduleLock) {
1246 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1247 return ret;
1248 }
1249 SECMOD_GetReadLock(moduleLock);
1250 for (i=0; i < mod->slotCount; i++) {
1251 PK11SlotInfo *slot = mod->slots[i];
1252 /* perm modules are not inserted or removed */
1253 if (slot->isPerm) {
1254 continue;
1255 }
1256 ret = PR_TRUE;
1257 break;
1258 }
1259 if (mod->slotCount == 0 ) {
1260 ret = PR_TRUE;
1261 }
1262 SECMOD_ReleaseReadLock(moduleLock);
1263 return ret;
1264 }
1265
1266 /*
1267 * helper function to actually create and destroy user defined slots
1268 */
1269 static SECStatus
1270 secmod_UserDBOp(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass,
1271 const char *sendSpec)
1272 {
1273 CK_OBJECT_HANDLE dummy;
1274 CK_ATTRIBUTE template[2] ;
1275 CK_ATTRIBUTE *attrs = template;
1276 CK_RV crv;
1277
1278 PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); attrs++;
1279 PK11_SETATTRS(attrs, CKA_NETSCAPE_MODULE_SPEC , (unsigned char *)sendSpec,
1280 strlen(sendSpec)+1); attrs++;
1281
1282 PORT_Assert(attrs-template <= 2);
1283
1284
1285 PK11_EnterSlotMonitor(slot);
1286 crv = PK11_CreateNewObject(slot, slot->session,
1287 template, attrs-template, PR_FALSE, &dummy);
1288 PK11_ExitSlotMonitor(slot);
1289
1290 if (crv != CKR_OK) {
1291 PORT_SetError(PK11_MapError(crv));
1292 return SECFailure;
1293 }
1294 return SECMOD_UpdateSlotList(slot->module);
1295 }
1296
1297 /*
1298 * return true if the selected slot ID is not present or doesn't exist
1299 */
1300 static PRBool
1301 secmod_SlotIsEmpty(SECMODModule *mod, CK_SLOT_ID slotID)
1302 {
1303 PK11SlotInfo *slot = SECMOD_LookupSlot(mod->moduleID, slotID);
1304 if (slot) {
1305 PRBool present = PK11_IsPresent(slot);
1306 PK11_FreeSlot(slot);
1307 if (present) {
1308 return PR_FALSE;
1309 }
1310 }
1311 /* it doesn't exist or isn't present, it's available */
1312 return PR_TRUE;
1313 }
1314
1315 /*
1316 * Find an unused slot id in module.
1317 */
1318 static CK_SLOT_ID
1319 secmod_FindFreeSlot(SECMODModule *mod)
1320 {
1321 CK_SLOT_ID i, minSlotID, maxSlotID;
1322
1323 /* look for a free slot id on the internal module */
1324 if (mod->internal && mod->isFIPS) {
1325 minSlotID = SFTK_MIN_FIPS_USER_SLOT_ID;
1326 maxSlotID = SFTK_MAX_FIPS_USER_SLOT_ID;
1327 } else {
1328 minSlotID = SFTK_MIN_USER_SLOT_ID;
1329 maxSlotID = SFTK_MAX_USER_SLOT_ID;
1330 }
1331 for (i=minSlotID; i < maxSlotID; i++) {
1332 if (secmod_SlotIsEmpty(mod,i)) {
1333 return i;
1334 }
1335 }
1336 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
1337 return (CK_SLOT_ID) -1;
1338 }
1339
1340 /*
1341 * Attempt to open a new slot.
1342 *
1343 * This works the same os OpenUserDB except it can be called against
1344 * any module that understands the softoken protocol for opening new
1345 * slots, not just the softoken itself. If the selected module does not
1346 * understand the protocol, C_CreateObject will fail with
1347 * CKR_INVALID_ATTRIBUTE, and SECMOD_OpenNewSlot will return NULL and set
1348 * SEC_ERROR_BAD_DATA.
1349 *
1350 * NewSlots can be closed with SECMOD_CloseUserDB();
1351 *
1352 * Modulespec is module dependent.
1353 */
1354 PK11SlotInfo *
1355 SECMOD_OpenNewSlot(SECMODModule *mod, const char *moduleSpec)
1356 {
1357 CK_SLOT_ID slotID = 0;
1358 PK11SlotInfo *slot;
1359 char *escSpec;
1360 char *sendSpec;
1361 SECStatus rv;
1362
1363 slotID = secmod_FindFreeSlot(mod);
1364 if (slotID == (CK_SLOT_ID) -1) {
1365 return NULL;
1366 }
1367
1368 if (mod->slotCount == 0) {
1369 return NULL;
1370 }
1371
1372 /* just grab the first slot in the module, any present slot should work */
1373 slot = PK11_ReferenceSlot(mod->slots[0]);
1374 if (slot == NULL) {
1375 return NULL;
1376 }
1377
1378 /* we've found the slot, now build the moduleSpec */
1379 escSpec = NSSUTIL_DoubleEscape(moduleSpec, '>', ']');
1380 if (escSpec == NULL) {
1381 PK11_FreeSlot(slot);
1382 return NULL;
1383 }
1384 sendSpec = PR_smprintf("tokens=[0x%x=<%s>]", slotID, escSpec);
1385 PORT_Free(escSpec);
1386
1387 if (sendSpec == NULL) {
1388 /* PR_smprintf does not set SEC_ERROR_NO_MEMORY on failure. */
1389 PK11_FreeSlot(slot);
1390 PORT_SetError(SEC_ERROR_NO_MEMORY);
1391 return NULL;
1392 }
1393 rv = secmod_UserDBOp(slot, CKO_NETSCAPE_NEWSLOT, sendSpec);
1394 PR_smprintf_free(sendSpec);
1395 PK11_FreeSlot(slot);
1396 if (rv != SECSuccess) {
1397 return NULL;
1398 }
1399
1400 slot = SECMOD_FindSlotByID(mod, slotID);
1401 if (slot) {
1402 /* if we are in the delay period for the "isPresent" call, reset
1403 * the delay since we know things have probably changed... */
1404 if (slot->nssToken && slot->nssToken->slot) {
1405 nssSlot_ResetDelay(slot->nssToken->slot);
1406 }
1407 /* force the slot info structures to properly reset */
1408 (void)PK11_IsPresent(slot);
1409 }
1410 return slot;
1411 }
1412
1413 /*
1414 * Open a new database using the softoken. The caller is responsible for making
1415 * sure the module spec is correct and usable. The caller should ask for one
1416 * new database per call if the caller wants to get meaningful information
1417 * about the new database.
1418 *
1419 * moduleSpec is the same data that you would pass to softoken at
1420 * initialization time under the 'tokens' options. For example, if you were
1421 * to specify tokens=<0x4=[configdir='./mybackup' tokenDescription='Backup']>
1422 * You would specify "configdir='./mybackup' tokenDescription='Backup'" as your
1423 * module spec here. The slot ID will be calculated for you by
1424 * SECMOD_OpenUserDB().
1425 *
1426 * Typical parameters here are configdir, tokenDescription and flags.
1427 *
1428 * a Full list is below:
1429 *
1430 *
1431 * configDir - The location of the databases for this token. If configDir is
1432 * not specified, and noCertDB and noKeyDB is not specified, the load
1433 * will fail.
1434 * certPrefix - Cert prefix for this token.
1435 * keyPrefix - Prefix for the key database for this token. (if not specified,
1436 * certPrefix will be used).
1437 * tokenDescription - The label value for this token returned in the
1438 * CK_TOKEN_INFO structure with an internationalize string (UTF8).
1439 * This value will be truncated at 32 bytes (no NULL, partial UTF8
1440 * characters dropped). You should specify a user friendly name here
1441 * as this is the value the token will be referred to in most
1442 * application UI's. You should make sure tokenDescription is unique.
1443 * slotDescription - The slotDescription value for this token returned
1444 * in the CK_SLOT_INFO structure with an internationalize string
1445 * (UTF8). This value will be truncated at 64 bytes (no NULL, partial
1446 * UTF8 characters dropped). This name will not change after the
1447 * database is closed. It should have some number to make this unique.
1448 * minPWLen - minimum password length for this token.
1449 * flags - comma separated list of flag values, parsed case-insensitive.
1450 * Valid flags are:
1451 * readOnly - Databases should be opened read only.
1452 * noCertDB - Don't try to open a certificate database.
1453 * noKeyDB - Don't try to open a key database.
1454 * forceOpen - Don't fail to initialize the token if the
1455 * databases could not be opened.
1456 * passwordRequired - zero length passwords are not acceptable
1457 * (valid only if there is a keyDB).
1458 * optimizeSpace - allocate smaller hash tables and lock tables.
1459 * When this flag is not specified, Softoken will allocate
1460 * large tables to prevent lock contention.
1461 */
1462 PK11SlotInfo *
1463 SECMOD_OpenUserDB(const char *moduleSpec)
1464 {
1465 SECMODModule *mod;
1466
1467 if (moduleSpec == NULL) {
1468 return NULL;
1469 }
1470
1471 /* NOTE: unlike most PK11 function, this does not return a reference
1472 * to the module */
1473 mod = SECMOD_GetInternalModule();
1474 if (!mod) {
1475 /* shouldn't happen */
1476 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1477 return NULL;
1478 }
1479 return SECMOD_OpenNewSlot(mod, moduleSpec);
1480 }
1481
1482
1483 /*
1484 * close an already opened user database. NOTE: the database must be
1485 * in the internal token, and must be one created with SECMOD_OpenUserDB().
1486 * Once the database is closed, the slot will remain as an empty slot
1487 * until it's used again with SECMOD_OpenUserDB() or SECMOD_OpenNewSlot().
1488 */
1489 SECStatus
1490 SECMOD_CloseUserDB(PK11SlotInfo *slot)
1491 {
1492 SECStatus rv;
1493 char *sendSpec;
1494
1495 sendSpec = PR_smprintf("tokens=[0x%x=<>]", slot->slotID);
1496 if (sendSpec == NULL) {
1497 /* PR_smprintf does not set no memory error */
1498 PORT_SetError(SEC_ERROR_NO_MEMORY);
1499 return SECFailure;
1500 }
1501 rv = secmod_UserDBOp(slot, CKO_NETSCAPE_DELSLOT, sendSpec);
1502 PR_smprintf_free(sendSpec);
1503 /* if we are in the delay period for the "isPresent" call, reset
1504 * the delay since we know things have probably changed... */
1505 if (slot->nssToken && slot->nssToken->slot) {
1506 nssSlot_ResetDelay(slot->nssToken->slot);
1507 /* force the slot info structures to properly reset */
1508 (void)PK11_IsPresent(slot);
1509 }
1510 return rv;
1511 }
1512
1513 /*
1514 * Restart PKCS #11 modules after a fork(). See secmod.h for more information.
1515 */
1516 SECStatus
1517 SECMOD_RestartModules(PRBool force)
1518 {
1519 SECMODModuleList *mlp;
1520 SECStatus rrv = SECSuccess;
1521 int lastError = 0;
1522
1523 if (!moduleLock) {
1524 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1525 return SECFailure;
1526 }
1527
1528 /* Only need to restart the PKCS #11 modules that were initialized */
1529 SECMOD_GetReadLock(moduleLock);
1530 for (mlp = modules; mlp != NULL; mlp = mlp->next) {
1531 SECMODModule *mod = mlp->module;
1532 CK_ULONG count;
1533 SECStatus rv;
1534 int i;
1535
1536 /* If the module needs to be reset, do so */
1537 if (force || (PK11_GETTAB(mod)->
1538 C_GetSlotList(CK_FALSE, NULL, &count) != CKR_OK)) {
1539 PRBool alreadyLoaded;
1540 /* first call Finalize. This is not required by PKCS #11, but some
1541 * older modules require it, and it doesn't hurt (compliant modules
1542 * will return CKR_NOT_INITIALIZED */
1543 (void) PK11_GETTAB(mod)->C_Finalize(NULL);
1544 /* now initialize the module, this function reinitializes
1545 * a module in place, preserving existing slots (even if they
1546 * no longer exist) */
1547 rv = secmod_ModuleInit(mod, NULL, &alreadyLoaded);
1548 if (rv != SECSuccess) {
1549 /* save the last error code */
1550 lastError = PORT_GetError();
1551 rrv = rv;
1552 /* couldn't reinit the module, disable all its slots */
1553 for (i=0; i < mod->slotCount; i++) {
1554 mod->slots[i]->disabled = PR_TRUE;
1555 mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1556 }
1557 continue;
1558 }
1559 for (i=0; i < mod->slotCount; i++) {
1560 /* get new token sessions, bump the series up so that
1561 * we refresh other old sessions. This will tell much of
1562 * NSS to flush cached handles it may hold as well */
1563 rv = PK11_InitToken(mod->slots[i],PR_TRUE);
1564 /* PK11_InitToken could fail if the slot isn't present.
1565 * If it is present, though, something is wrong and we should
1566 * disable the slot and let the caller know. */
1567 if (rv != SECSuccess && PK11_IsPresent(mod->slots[i])) {
1568 /* save the last error code */
1569 lastError = PORT_GetError();
1570 rrv = rv;
1571 /* disable the token */
1572 mod->slots[i]->disabled = PR_TRUE;
1573 mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1574 }
1575 }
1576 }
1577 }
1578 SECMOD_ReleaseReadLock(moduleLock);
1579
1580 /*
1581 * on multiple failures, we are only returning the lastError. The caller
1582 * can determine which slots are bad by calling PK11_IsDisabled().
1583 */
1584 if (rrv != SECSuccess) {
1585 /* restore the last error code */
1586 PORT_SetError(lastError);
1587 }
1588
1589 return rrv;
1590 }
OLDNEW
« no previous file with comments | « nss/lib/pk11wrap/pk11slot.c ('k') | nss/lib/pk11wrap/secmod.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698