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 "dev3hack.h"
17 #include "utilpars.h"
18 #include "pkcs11uri.h"
19
20 /* these are for displaying error messages */
21
22 static SECMODModuleList *modules = NULL;
23 static SECMODModuleList *modulesDB = NULL;
24 static SECMODModuleList *modulesUnload = NULL;
25 static SECMODModule *internalModule = NULL;
26 static SECMODModule *defaultDBModule = NULL;
27 static SECMODModule *pendingModule = NULL;
28 static SECMODListLock *moduleLock = NULL;
29
30 int secmod_PrivateModuleCount = 0;
31
32 extern const PK11DefaultArrayEntry PK11_DefaultArray[];
33 extern const int num_pk11_default_mechanisms;
34
35 void
SECMOD_Init()36 SECMOD_Init()
37 {
38 /* don't initialize twice */
39 if (moduleLock)
40 return;
41
42 moduleLock = SECMOD_NewListLock();
43 PK11_InitSlotLists();
44 }
45
46 SECStatus
SECMOD_Shutdown()47 SECMOD_Shutdown()
48 {
49 /* destroy the lock */
50 if (moduleLock) {
51 SECMOD_DestroyListLock(moduleLock);
52 moduleLock = NULL;
53 }
54 /* free the internal module */
55 if (internalModule) {
56 SECMOD_DestroyModule(internalModule);
57 internalModule = NULL;
58 }
59
60 /* free the default database module */
61 if (defaultDBModule) {
62 SECMOD_DestroyModule(defaultDBModule);
63 defaultDBModule = NULL;
64 }
65
66 /* destroy the list */
67 if (modules) {
68 SECMOD_DestroyModuleList(modules);
69 modules = NULL;
70 }
71
72 if (modulesDB) {
73 SECMOD_DestroyModuleList(modulesDB);
74 modulesDB = NULL;
75 }
76
77 if (modulesUnload) {
78 SECMOD_DestroyModuleList(modulesUnload);
79 modulesUnload = NULL;
80 }
81
82 /* make all the slots and the lists go away */
83 PK11_DestroySlotLists();
84
85 nss_DumpModuleLog();
86
87 #ifdef DEBUG
88 if (PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) {
89 PORT_Assert(secmod_PrivateModuleCount == 0);
90 }
91 #endif
92 if (secmod_PrivateModuleCount) {
93 PORT_SetError(SEC_ERROR_BUSY);
94 return SECFailure;
95 }
96 return SECSuccess;
97 }
98
99 PRBool
SECMOD_GetSystemFIPSEnabled(void)100 SECMOD_GetSystemFIPSEnabled(void)
101 {
102 #ifdef LINUX
103 #ifndef NSS_FIPS_DISABLED
104 FILE *f;
105 char d;
106 size_t size;
107
108 f = fopen("/proc/sys/crypto/fips_enabled", "r");
109 if (!f) {
110 return PR_FALSE;
111 }
112
113 size = fread(&d, 1, sizeof(d), f);
114 fclose(f);
115 if (size != sizeof(d)) {
116 return PR_FALSE;
117 }
118 if (d == '1') {
119 return PR_TRUE;
120 }
121 #endif
122 #endif
123 return PR_FALSE;
124 }
125
126 /*
127 * retrieve the internal module
128 */
129 SECMODModule *
SECMOD_GetInternalModule(void)130 SECMOD_GetInternalModule(void)
131 {
132 return internalModule;
133 }
134
135 SECStatus
secmod_AddModuleToList(SECMODModuleList ** moduleList,SECMODModule * newModule)136 secmod_AddModuleToList(SECMODModuleList **moduleList, SECMODModule *newModule)
137 {
138 SECMODModuleList *mlp, *newListElement, *last = NULL;
139
140 newListElement = SECMOD_NewModuleListElement();
141 if (newListElement == NULL) {
142 return SECFailure;
143 }
144
145 newListElement->module = SECMOD_ReferenceModule(newModule);
146
147 SECMOD_GetWriteLock(moduleLock);
148 /* Added it to the end (This is very inefficient, but Adding a module
149 * on the fly should happen maybe 2-3 times through the life this program
150 * on a given computer, and this list should be *SHORT*. */
151 for (mlp = *moduleList; mlp != NULL; mlp = mlp->next) {
152 last = mlp;
153 }
154
155 if (last == NULL) {
156 *moduleList = newListElement;
157 } else {
158 SECMOD_AddList(last, newListElement, NULL);
159 }
160 SECMOD_ReleaseWriteLock(moduleLock);
161 return SECSuccess;
162 }
163
164 SECStatus
SECMOD_AddModuleToList(SECMODModule * newModule)165 SECMOD_AddModuleToList(SECMODModule *newModule)
166 {
167 if (newModule->internal && !internalModule) {
168 internalModule = SECMOD_ReferenceModule(newModule);
169 }
170 return secmod_AddModuleToList(&modules, newModule);
171 }
172
173 SECStatus
SECMOD_AddModuleToDBOnlyList(SECMODModule * newModule)174 SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule)
175 {
176 if (defaultDBModule && SECMOD_GetDefaultModDBFlag(newModule)) {
177 SECMOD_DestroyModule(defaultDBModule);
178 defaultDBModule = SECMOD_ReferenceModule(newModule);
179 } else if (defaultDBModule == NULL) {
180 defaultDBModule = SECMOD_ReferenceModule(newModule);
181 }
182 return secmod_AddModuleToList(&modulesDB, newModule);
183 }
184
185 SECStatus
SECMOD_AddModuleToUnloadList(SECMODModule * newModule)186 SECMOD_AddModuleToUnloadList(SECMODModule *newModule)
187 {
188 return secmod_AddModuleToList(&modulesUnload, newModule);
189 }
190
191 /*
192 * get the list of PKCS11 modules that are available.
193 */
194 SECMODModuleList *
SECMOD_GetDefaultModuleList()195 SECMOD_GetDefaultModuleList()
196 {
197 return modules;
198 }
199 SECMODModuleList *
SECMOD_GetDeadModuleList()200 SECMOD_GetDeadModuleList()
201 {
202 return modulesUnload;
203 }
204 SECMODModuleList *
SECMOD_GetDBModuleList()205 SECMOD_GetDBModuleList()
206 {
207 return modulesDB;
208 }
209
210 /*
211 * This lock protects the global module lists.
212 * it also protects changes to the slot array (module->slots[]) and slot count
213 * (module->slotCount) in each module. It is a read/write lock with multiple
214 * readers or one writer. Writes are uncommon.
215 * Because of legacy considerations protection of the slot array and count is
216 * only necessary in applications if the application calls
217 * SECMOD_UpdateSlotList() or SECMOD_WaitForAnyTokenEvent(), though all new
218 * applications are encouraged to acquire this lock when reading the
219 * slot array information directly.
220 */
221 SECMODListLock *
SECMOD_GetDefaultModuleListLock()222 SECMOD_GetDefaultModuleListLock()
223 {
224 return moduleLock;
225 }
226
227 /*
228 * find a module by name, and add a reference to it.
229 * return that module.
230 */
231 SECMODModule *
SECMOD_FindModule(const char * name)232 SECMOD_FindModule(const char *name)
233 {
234 SECMODModuleList *mlp;
235 SECMODModule *module = NULL;
236
237 if (!moduleLock) {
238 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
239 return module;
240 }
241 SECMOD_GetReadLock(moduleLock);
242 for (mlp = modules; mlp != NULL; mlp = mlp->next) {
243 if (PORT_Strcmp(name, mlp->module->commonName) == 0) {
244 module = mlp->module;
245 SECMOD_ReferenceModule(module);
246 break;
247 }
248 }
249 if (module) {
250 goto found;
251 }
252 for (mlp = modulesUnload; mlp != NULL; mlp = mlp->next) {
253 if (PORT_Strcmp(name, mlp->module->commonName) == 0) {
254 module = mlp->module;
255 SECMOD_ReferenceModule(module);
256 break;
257 }
258 }
259
260 found:
261 SECMOD_ReleaseReadLock(moduleLock);
262
263 return module;
264 }
265
266 /*
267 * find a module by ID, and add a reference to it.
268 * return that module.
269 */
270 SECMODModule *
SECMOD_FindModuleByID(SECMODModuleID id)271 SECMOD_FindModuleByID(SECMODModuleID id)
272 {
273 SECMODModuleList *mlp;
274 SECMODModule *module = NULL;
275
276 if (!moduleLock) {
277 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
278 return module;
279 }
280 SECMOD_GetReadLock(moduleLock);
281 for (mlp = modules; mlp != NULL; mlp = mlp->next) {
282 if (id == mlp->module->moduleID) {
283 module = mlp->module;
284 SECMOD_ReferenceModule(module);
285 break;
286 }
287 }
288 SECMOD_ReleaseReadLock(moduleLock);
289 if (module == NULL) {
290 PORT_SetError(SEC_ERROR_NO_MODULE);
291 }
292 return module;
293 }
294
295 /*
296 * find the function pointer.
297 */
298 SECMODModule *
secmod_FindModuleByFuncPtr(void * funcPtr)299 secmod_FindModuleByFuncPtr(void *funcPtr)
300 {
301 SECMODModuleList *mlp;
302 SECMODModule *module = NULL;
303
304 SECMOD_GetReadLock(moduleLock);
305 for (mlp = modules; mlp != NULL; mlp = mlp->next) {
306 /* paranoia, shouldn't ever happen */
307 if (!mlp->module) {
308 continue;
309 }
310 if (funcPtr == mlp->module->functionList) {
311 module = mlp->module;
312 SECMOD_ReferenceModule(module);
313 break;
314 }
315 }
316 SECMOD_ReleaseReadLock(moduleLock);
317 if (module == NULL) {
318 PORT_SetError(SEC_ERROR_NO_MODULE);
319 }
320 return module;
321 }
322
323 /*
324 * Find the Slot based on ID and the module.
325 */
326 PK11SlotInfo *
SECMOD_FindSlotByID(SECMODModule * module,CK_SLOT_ID slotID)327 SECMOD_FindSlotByID(SECMODModule *module, CK_SLOT_ID slotID)
328 {
329 int i;
330 PK11SlotInfo *slot = NULL;
331
332 if (!moduleLock) {
333 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
334 return slot;
335 }
336 SECMOD_GetReadLock(moduleLock);
337 for (i = 0; i < module->slotCount; i++) {
338 PK11SlotInfo *cSlot = module->slots[i];
339
340 if (cSlot->slotID == slotID) {
341 slot = PK11_ReferenceSlot(cSlot);
342 break;
343 }
344 }
345 SECMOD_ReleaseReadLock(moduleLock);
346
347 if (slot == NULL) {
348 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
349 }
350 return slot;
351 }
352
353 /*
354 * lookup the Slot module based on it's module ID and slot ID.
355 */
356 PK11SlotInfo *
SECMOD_LookupSlot(SECMODModuleID moduleID,CK_SLOT_ID slotID)357 SECMOD_LookupSlot(SECMODModuleID moduleID, CK_SLOT_ID slotID)
358 {
359 SECMODModule *module;
360 PK11SlotInfo *slot;
361
362 module = SECMOD_FindModuleByID(moduleID);
363 if (module == NULL)
364 return NULL;
365
366 slot = SECMOD_FindSlotByID(module, slotID);
367 SECMOD_DestroyModule(module);
368 return slot;
369 }
370
371 /*
372 * find a module by name or module pointer and delete it off the module list.
373 * optionally remove it from secmod.db.
374 */
375 SECStatus
SECMOD_DeleteModuleEx(const char * name,SECMODModule * mod,int * type,PRBool permdb)376 SECMOD_DeleteModuleEx(const char *name, SECMODModule *mod,
377 int *type, PRBool permdb)
378 {
379 SECMODModuleList *mlp;
380 SECMODModuleList **mlpp;
381 SECStatus rv = SECFailure;
382
383 if (!moduleLock) {
384 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
385 return rv;
386 }
387
388 *type = SECMOD_EXTERNAL;
389
390 SECMOD_GetWriteLock(moduleLock);
391 for (mlpp = &modules, mlp = modules;
392 mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
393 if ((name && (PORT_Strcmp(name, mlp->module->commonName) == 0)) ||
394 mod == mlp->module) {
395 /* don't delete the internal module */
396 if (!mlp->module->internal) {
397 SECMOD_RemoveList(mlpp, mlp);
398 /* delete it after we release the lock */
399 rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module);
400 } else if (mlp->module->isFIPS) {
401 *type = SECMOD_FIPS;
402 } else {
403 *type = SECMOD_INTERNAL;
404 }
405 break;
406 }
407 }
408 if (mlp) {
409 goto found;
410 }
411 /* not on the internal list, check the unload list */
412 for (mlpp = &modulesUnload, mlp = modulesUnload;
413 mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
414 if ((name && (PORT_Strcmp(name, mlp->module->commonName) == 0)) ||
415 mod == mlp->module) {
416 /* don't delete the internal module */
417 if (!mlp->module->internal) {
418 SECMOD_RemoveList(mlpp, mlp);
419 rv = SECSuccess;
420 } else if (mlp->module->isFIPS) {
421 *type = SECMOD_FIPS;
422 } else {
423 *type = SECMOD_INTERNAL;
424 }
425 break;
426 }
427 }
428 found:
429 SECMOD_ReleaseWriteLock(moduleLock);
430
431 if (rv == SECSuccess) {
432 if (permdb) {
433 SECMOD_DeletePermDB(mlp->module);
434 }
435 SECMOD_DestroyModuleListElement(mlp);
436 }
437 return rv;
438 }
439
440 /*
441 * find a module by name and delete it off the module list
442 */
443 SECStatus
SECMOD_DeleteModule(const char * name,int * type)444 SECMOD_DeleteModule(const char *name, int *type)
445 {
446 return SECMOD_DeleteModuleEx(name, NULL, type, PR_TRUE);
447 }
448
449 /*
450 * find a module by name and delete it off the module list
451 */
452 SECStatus
SECMOD_DeleteInternalModule(const char * name)453 SECMOD_DeleteInternalModule(const char *name)
454 {
455 SECMODModuleList *mlp;
456 SECMODModuleList **mlpp;
457 SECStatus rv = SECFailure;
458
459 if (SECMOD_GetSystemFIPSEnabled() || pendingModule) {
460 PORT_SetError(SEC_ERROR_MODULE_STUCK);
461 return rv;
462 }
463 if (!moduleLock) {
464 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
465 return rv;
466 }
467
468 #ifdef NSS_FIPS_DISABLED
469 PORT_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR);
470 return rv;
471 #endif
472
473 SECMOD_GetWriteLock(moduleLock);
474 for (mlpp = &modules, mlp = modules;
475 mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
476 if (PORT_Strcmp(name, mlp->module->commonName) == 0) {
477 /* don't delete the internal module */
478 if (mlp->module->internal) {
479 SECMOD_RemoveList(mlpp, mlp);
480 rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module);
481 }
482 break;
483 }
484 }
485 SECMOD_ReleaseWriteLock(moduleLock);
486
487 if (rv == SECSuccess) {
488 SECMODModule *newModule, *oldModule;
489
490 if (mlp->module->isFIPS) {
491 newModule = SECMOD_CreateModule(NULL, SECMOD_INT_NAME,
492 NULL, SECMOD_INT_FLAGS);
493 } else {
494 newModule = SECMOD_CreateModule(NULL, SECMOD_FIPS_NAME,
495 NULL, SECMOD_FIPS_FLAGS);
496 }
497 if (newModule) {
498 PK11SlotInfo *slot;
499 newModule->libraryParams =
500 PORT_ArenaStrdup(newModule->arena, mlp->module->libraryParams);
501 /* if an explicit internal key slot has been set, reset it */
502 slot = pk11_SwapInternalKeySlot(NULL);
503 if (slot) {
504 secmod_SetInternalKeySlotFlag(newModule, PR_TRUE);
505 }
506 rv = SECMOD_AddModule(newModule);
507 if (rv != SECSuccess) {
508 /* load failed, restore the internal key slot */
509 pk11_SetInternalKeySlot(slot);
510 SECMOD_DestroyModule(newModule);
511 newModule = NULL;
512 }
513 /* free the old explicit internal key slot, we now have a new one */
514 if (slot) {
515 PK11_FreeSlot(slot);
516 }
517 }
518 if (newModule == NULL) {
519 SECMODModuleList *last = NULL, *mlp2;
520 /* we're in pretty deep trouble if this happens...Security
521 * not going to work well... try to put the old module back on
522 * the list */
523 SECMOD_GetWriteLock(moduleLock);
524 for (mlp2 = modules; mlp2 != NULL; mlp2 = mlp->next) {
525 last = mlp2;
526 }
527
528 if (last == NULL) {
529 modules = mlp;
530 } else {
531 SECMOD_AddList(last, mlp, NULL);
532 }
533 SECMOD_ReleaseWriteLock(moduleLock);
534 return SECFailure;
535 }
536 pendingModule = oldModule = internalModule;
537 internalModule = NULL;
538 SECMOD_DestroyModule(oldModule);
539 SECMOD_DeletePermDB(mlp->module);
540 SECMOD_DestroyModuleListElement(mlp);
541 internalModule = newModule; /* adopt the module */
542 }
543 return rv;
544 }
545
546 SECStatus
SECMOD_AddModule(SECMODModule * newModule)547 SECMOD_AddModule(SECMODModule *newModule)
548 {
549 SECStatus rv;
550 SECMODModule *oldModule;
551
552 /* Test if a module w/ the same name already exists */
553 /* and return SECWouldBlock if so. */
554 /* We should probably add a new return value such as */
555 /* SECDublicateModule, but to minimize ripples, I'll */
556 /* give SECWouldBlock a new meaning */
557 if ((oldModule = SECMOD_FindModule(newModule->commonName)) != NULL) {
558 SECMOD_DestroyModule(oldModule);
559 return SECWouldBlock;
560 /* module already exists. */
561 }
562
563 rv = secmod_LoadPKCS11Module(newModule, NULL);
564 if (rv != SECSuccess) {
565 return rv;
566 }
567
568 if (newModule->parent == NULL) {
569 newModule->parent = SECMOD_ReferenceModule(defaultDBModule);
570 }
571
572 SECMOD_AddPermDB(newModule);
573 SECMOD_AddModuleToList(newModule);
574
575 rv = STAN_AddModuleToDefaultTrustDomain(newModule);
576
577 return rv;
578 }
579
580 PK11SlotInfo *
SECMOD_FindSlot(SECMODModule * module,const char * name)581 SECMOD_FindSlot(SECMODModule *module, const char *name)
582 {
583 int i;
584 char *string;
585 PK11SlotInfo *retSlot = NULL;
586
587 if (!moduleLock) {
588 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
589 return retSlot;
590 }
591 SECMOD_GetReadLock(moduleLock);
592 for (i = 0; i < module->slotCount; i++) {
593 PK11SlotInfo *slot = module->slots[i];
594
595 if (PK11_IsPresent(slot)) {
596 string = PK11_GetTokenName(slot);
597 } else {
598 string = PK11_GetSlotName(slot);
599 }
600 if (PORT_Strcmp(name, string) == 0) {
601 retSlot = PK11_ReferenceSlot(slot);
602 break;
603 }
604 }
605 SECMOD_ReleaseReadLock(moduleLock);
606
607 if (retSlot == NULL) {
608 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
609 }
610 return retSlot;
611 }
612
613 SECStatus
PK11_GetModInfo(SECMODModule * mod,CK_INFO * info)614 PK11_GetModInfo(SECMODModule *mod, CK_INFO *info)
615 {
616 CK_RV crv;
617
618 if (mod->functionList == NULL)
619 return SECFailure;
620 crv = PK11_GETTAB(mod)->C_GetInfo(info);
621 if (crv != CKR_OK) {
622 PORT_SetError(PK11_MapError(crv));
623 }
624 return (crv == CKR_OK) ? SECSuccess : SECFailure;
625 }
626
627 char *
PK11_GetModuleURI(SECMODModule * mod)628 PK11_GetModuleURI(SECMODModule *mod)
629 {
630 CK_INFO info;
631 PK11URI *uri;
632 char *ret = NULL;
633 PK11URIAttribute attrs[3];
634 size_t nattrs = 0;
635 char libraryManufacturer[32 + 1], libraryDescription[32 + 1], libraryVersion[8];
636
637 if (PK11_GetModInfo(mod, &info) == SECFailure) {
638 return NULL;
639 }
640
641 PK11_MakeString(NULL, libraryManufacturer, (char *)info.manufacturerID,
642 sizeof(info.manufacturerID));
643 if (*libraryManufacturer != '\0') {
644 attrs[nattrs].name = PK11URI_PATTR_LIBRARY_MANUFACTURER;
645 attrs[nattrs].value = libraryManufacturer;
646 nattrs++;
647 }
648
649 PK11_MakeString(NULL, libraryDescription, (char *)info.libraryDescription,
650 sizeof(info.libraryDescription));
651 if (*libraryDescription != '\0') {
652 attrs[nattrs].name = PK11URI_PATTR_LIBRARY_DESCRIPTION;
653 attrs[nattrs].value = libraryDescription;
654 nattrs++;
655 }
656
657 PR_snprintf(libraryVersion, sizeof(libraryVersion), "%d.%d",
658 info.libraryVersion.major, info.libraryVersion.minor);
659 attrs[nattrs].name = PK11URI_PATTR_LIBRARY_VERSION;
660 attrs[nattrs].value = libraryVersion;
661 nattrs++;
662
663 uri = PK11URI_CreateURI(attrs, nattrs, NULL, 0);
664 if (uri == NULL) {
665 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
666 return NULL;
667 }
668
669 ret = PK11URI_FormatURI(NULL, uri);
670 PK11URI_DestroyURI(uri);
671 if (ret == NULL) {
672 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
673 return NULL;
674 }
675
676 return ret;
677 }
678
679 /* Determine if we have the FIP's module loaded as the default
680 * module to trigger other bogus FIPS requirements in PKCS #12 and
681 * SSL
682 */
683 PRBool
PK11_IsFIPS(void)684 PK11_IsFIPS(void)
685 {
686 SECMODModule *mod = SECMOD_GetInternalModule();
687
688 if (mod && mod->internal) {
689 return mod->isFIPS;
690 }
691
692 return PR_FALSE;
693 }
694
695 /* combines NewModule() & AddModule */
696 /* give a string for the module name & the full-path for the dll, */
697 /* installs the PKCS11 module & update registry */
698 SECStatus
SECMOD_AddNewModuleEx(const char * moduleName,const char * dllPath,unsigned long defaultMechanismFlags,unsigned long cipherEnableFlags,char * modparms,char * nssparms)699 SECMOD_AddNewModuleEx(const char *moduleName, const char *dllPath,
700 unsigned long defaultMechanismFlags,
701 unsigned long cipherEnableFlags,
702 char *modparms, char *nssparms)
703 {
704 SECMODModule *module;
705 SECStatus result = SECFailure;
706 int s, i;
707 PK11SlotInfo *slot;
708
709 PR_SetErrorText(0, NULL);
710 if (!moduleLock) {
711 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
712 return result;
713 }
714
715 module = SECMOD_CreateModule(dllPath, moduleName, modparms, nssparms);
716
717 if (module == NULL) {
718 return result;
719 }
720
721 if (module->dllName != NULL) {
722 if (module->dllName[0] != 0) {
723 result = SECMOD_AddModule(module);
724 if (result == SECSuccess) {
725 /* turn on SSL cipher enable flags */
726 module->ssl[0] = cipherEnableFlags;
727
728 SECMOD_GetReadLock(moduleLock);
729 /* check each slot to turn on appropriate mechanisms */
730 for (s = 0; s < module->slotCount; s++) {
731 slot = (module->slots)[s];
732 /* for each possible mechanism */
733 for (i = 0; i < num_pk11_default_mechanisms; i++) {
734 /* we are told to turn it on by default ? */
735 PRBool add =
736 (PK11_DefaultArray[i].flag & defaultMechanismFlags) ? PR_TRUE : PR_FALSE;
737 result = PK11_UpdateSlotAttribute(slot,
738 &(PK11_DefaultArray[i]), add);
739 if (result != SECSuccess) {
740 SECMOD_ReleaseReadLock(moduleLock);
741 SECMOD_DestroyModule(module);
742 return result;
743 }
744 } /* for each mechanism */
745 /* disable each slot if the defaultFlags say so */
746 if (defaultMechanismFlags & PK11_DISABLE_FLAG) {
747 PK11_UserDisableSlot(slot);
748 }
749 } /* for each slot of this module */
750 SECMOD_ReleaseReadLock(moduleLock);
751
752 /* delete and re-add module in order to save changes
753 * to the module */
754 result = SECMOD_UpdateModule(module);
755 }
756 }
757 }
758 SECMOD_DestroyModule(module);
759 return result;
760 }
761
762 SECStatus
SECMOD_AddNewModule(const char * moduleName,const char * dllPath,unsigned long defaultMechanismFlags,unsigned long cipherEnableFlags)763 SECMOD_AddNewModule(const char *moduleName, const char *dllPath,
764 unsigned long defaultMechanismFlags,
765 unsigned long cipherEnableFlags)
766 {
767 return SECMOD_AddNewModuleEx(moduleName, dllPath, defaultMechanismFlags,
768 cipherEnableFlags,
769 NULL, NULL); /* don't pass module or nss params */
770 }
771
772 SECStatus
SECMOD_UpdateModule(SECMODModule * module)773 SECMOD_UpdateModule(SECMODModule *module)
774 {
775 SECStatus result;
776
777 result = SECMOD_DeletePermDB(module);
778
779 if (result == SECSuccess) {
780 result = SECMOD_AddPermDB(module);
781 }
782 return result;
783 }
784
785 /* Public & Internal(Security Library) representation of
786 * encryption mechanism flags conversion */
787
788 /* Currently, the only difference is that internal representation
789 * puts RANDOM_FLAG at bit 31 (Most-significant bit), but
790 * public representation puts this bit at bit 28
791 */
792 unsigned long
SECMOD_PubMechFlagstoInternal(unsigned long publicFlags)793 SECMOD_PubMechFlagstoInternal(unsigned long publicFlags)
794 {
795 unsigned long internalFlags = publicFlags;
796
797 if (publicFlags & PUBLIC_MECH_RANDOM_FLAG) {
798 internalFlags &= ~PUBLIC_MECH_RANDOM_FLAG;
799 internalFlags |= SECMOD_RANDOM_FLAG;
800 }
801 return internalFlags;
802 }
803
804 unsigned long
SECMOD_InternaltoPubMechFlags(unsigned long internalFlags)805 SECMOD_InternaltoPubMechFlags(unsigned long internalFlags)
806 {
807 unsigned long publicFlags = internalFlags;
808
809 if (internalFlags & SECMOD_RANDOM_FLAG) {
810 publicFlags &= ~SECMOD_RANDOM_FLAG;
811 publicFlags |= PUBLIC_MECH_RANDOM_FLAG;
812 }
813 return publicFlags;
814 }
815
816 /* Public & Internal(Security Library) representation of */
817 /* cipher flags conversion */
818 /* Note: currently they are just stubs */
819 unsigned long
SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags)820 SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags)
821 {
822 return publicFlags;
823 }
824
825 unsigned long
SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags)826 SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags)
827 {
828 return internalFlags;
829 }
830
831 /* Funtion reports true if module of modType is installed/configured */
832 PRBool
SECMOD_IsModulePresent(unsigned long int pubCipherEnableFlags)833 SECMOD_IsModulePresent(unsigned long int pubCipherEnableFlags)
834 {
835 PRBool result = PR_FALSE;
836 SECMODModuleList *mods;
837
838 if (!moduleLock) {
839 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
840 return result;
841 }
842 SECMOD_GetReadLock(moduleLock);
843 mods = SECMOD_GetDefaultModuleList();
844 for (; mods != NULL; mods = mods->next) {
845 if (mods->module->ssl[0] &
846 SECMOD_PubCipherFlagstoInternal(pubCipherEnableFlags)) {
847 result = PR_TRUE;
848 }
849 }
850
851 SECMOD_ReleaseReadLock(moduleLock);
852 return result;
853 }
854
855 /* create a new ModuleListElement */
856 SECMODModuleList *
SECMOD_NewModuleListElement(void)857 SECMOD_NewModuleListElement(void)
858 {
859 SECMODModuleList *newModList;
860
861 newModList = (SECMODModuleList *)PORT_Alloc(sizeof(SECMODModuleList));
862 if (newModList) {
863 newModList->next = NULL;
864 newModList->module = NULL;
865 }
866 return newModList;
867 }
868
869 /*
870 * make a new reference to a module so It doesn't go away on us
871 */
872 SECMODModule *
SECMOD_ReferenceModule(SECMODModule * module)873 SECMOD_ReferenceModule(SECMODModule *module)
874 {
875 PZ_Lock(module->refLock);
876 PORT_Assert(module->refCount > 0);
877
878 module->refCount++;
879 PZ_Unlock(module->refLock);
880 return module;
881 }
882
883 /* destroy an existing module */
884 void
SECMOD_DestroyModule(SECMODModule * module)885 SECMOD_DestroyModule(SECMODModule *module)
886 {
887 PRBool willfree = PR_FALSE;
888 int slotCount;
889 int i;
890
891 PZ_Lock(module->refLock);
892 if (module->refCount-- == 1) {
893 willfree = PR_TRUE;
894 }
895 PORT_Assert(willfree || (module->refCount > 0));
896 PZ_Unlock(module->refLock);
897
898 if (!willfree) {
899 return;
900 }
901
902 if (module->parent != NULL) {
903 SECMODModule *parent = module->parent;
904 /* paranoia, don't loop forever if the modules are looped */
905 module->parent = NULL;
906 SECMOD_DestroyModule(parent);
907 }
908
909 /* slots can't really disappear until our module starts freeing them,
910 * so this check is safe */
911 slotCount = module->slotCount;
912 if (slotCount == 0) {
913 SECMOD_SlotDestroyModule(module, PR_FALSE);
914 return;
915 }
916
917 /* now free all out slots, when they are done, they will cause the
918 * module to disappear altogether */
919 for (i = 0; i < slotCount; i++) {
920 if (!module->slots[i]->disabled) {
921 PK11_ClearSlotList(module->slots[i]);
922 }
923 PK11_FreeSlot(module->slots[i]);
924 }
925 /* WARNING: once the last slot has been freed is it possible (even likely)
926 * that module is no more... touching it now is a good way to go south */
927 }
928
929 /* we can only get here if we've destroyed the module, or some one has
930 * erroneously freed a slot that wasn't referenced. */
931 void
SECMOD_SlotDestroyModule(SECMODModule * module,PRBool fromSlot)932 SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot)
933 {
934 PRBool willfree = PR_FALSE;
935 if (fromSlot) {
936 PORT_Assert(module->refCount == 0);
937 PZ_Lock(module->refLock);
938 if (module->slotCount-- == 1) {
939 willfree = PR_TRUE;
940 }
941 PORT_Assert(willfree || (module->slotCount > 0));
942 PZ_Unlock(module->refLock);
943 if (!willfree)
944 return;
945 }
946
947 if (module == pendingModule) {
948 pendingModule = NULL;
949 }
950
951 if (module->loaded) {
952 SECMOD_UnloadModule(module);
953 }
954 PZ_DestroyLock(module->refLock);
955 PORT_FreeArena(module->arena, PR_FALSE);
956 secmod_PrivateModuleCount--;
957 }
958
959 /* destroy a list element
960 * this destroys a single element, and returns the next element
961 * on the chain. It makes it easy to implement for loops to delete
962 * the chain. It also make deleting a single element easy */
963 SECMODModuleList *
SECMOD_DestroyModuleListElement(SECMODModuleList * element)964 SECMOD_DestroyModuleListElement(SECMODModuleList *element)
965 {
966 SECMODModuleList *next = element->next;
967
968 if (element->module) {
969 SECMOD_DestroyModule(element->module);
970 element->module = NULL;
971 }
972 PORT_Free(element);
973 return next;
974 }
975
976 /*
977 * Destroy an entire module list
978 */
979 void
SECMOD_DestroyModuleList(SECMODModuleList * list)980 SECMOD_DestroyModuleList(SECMODModuleList *list)
981 {
982 SECMODModuleList *lp;
983
984 for (lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp))
985 ;
986 }
987
988 PRBool
SECMOD_CanDeleteInternalModule(void)989 SECMOD_CanDeleteInternalModule(void)
990 {
991 #ifdef NSS_FIPS_DISABLED
992 return PR_FALSE;
993 #else
994 return (PRBool)((pendingModule == NULL) && !SECMOD_GetSystemFIPSEnabled());
995 #endif
996 }
997
998 /*
999 * check to see if the module has added new slots. PKCS 11 v2.20 allows for
1000 * modules to add new slots, but never remove them. Slots cannot be added
1001 * between a call to C_GetSlotLlist(Flag, NULL, &count) and the subsequent
1002 * C_GetSlotList(flag, &data, &count) so that the array doesn't accidently
1003 * grow on the caller. It is permissible for the slots to increase between
1004 * successive calls with NULL to get the size.
1005 */
1006 SECStatus
SECMOD_UpdateSlotList(SECMODModule * mod)1007 SECMOD_UpdateSlotList(SECMODModule *mod)
1008 {
1009 CK_RV crv;
1010 CK_ULONG count;
1011 CK_ULONG i, oldCount;
1012 PRBool freeRef = PR_FALSE;
1013 void *mark = NULL;
1014 CK_ULONG *slotIDs = NULL;
1015 PK11SlotInfo **newSlots = NULL;
1016 PK11SlotInfo **oldSlots = NULL;
1017
1018 if (!moduleLock) {
1019 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1020 return SECFailure;
1021 }
1022
1023 /* C_GetSlotList is not a session function, make sure
1024 * calls are serialized */
1025 PZ_Lock(mod->refLock);
1026 freeRef = PR_TRUE;
1027 /* see if the number of slots have changed */
1028 crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, NULL, &count);
1029 if (crv != CKR_OK) {
1030 PORT_SetError(PK11_MapError(crv));
1031 goto loser;
1032 }
1033 /* nothing new, blow out early, we want this function to be quick
1034 * and cheap in the normal case */
1035 if (count == mod->slotCount) {
1036 PZ_Unlock(mod->refLock);
1037 return SECSuccess;
1038 }
1039 if (count < (CK_ULONG)mod->slotCount) {
1040 /* shouldn't happen with a properly functioning PKCS #11 module */
1041 PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
1042 goto loser;
1043 }
1044
1045 /* get the new slot list */
1046 slotIDs = PORT_NewArray(CK_SLOT_ID, count);
1047 if (slotIDs == NULL) {
1048 goto loser;
1049 }
1050
1051 crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, slotIDs, &count);
1052 if (crv != CKR_OK) {
1053 PORT_SetError(PK11_MapError(crv));
1054 goto loser;
1055 }
1056 freeRef = PR_FALSE;
1057 PZ_Unlock(mod->refLock);
1058 mark = PORT_ArenaMark(mod->arena);
1059 if (mark == NULL) {
1060 goto loser;
1061 }
1062 newSlots = PORT_ArenaZNewArray(mod->arena, PK11SlotInfo *, count);
1063
1064 /* walk down the new slot ID list returned from the module. We keep
1065 * the old slots which match a returned ID, and we initialize the new
1066 * slots. */
1067 for (i = 0; i < count; i++) {
1068 PK11SlotInfo *slot = SECMOD_FindSlotByID(mod, slotIDs[i]);
1069
1070 if (!slot) {
1071 /* we have a new slot create a new slot data structure */
1072 slot = PK11_NewSlotInfo(mod);
1073 if (!slot) {
1074 goto loser;
1075 }
1076 PK11_InitSlot(mod, slotIDs[i], slot);
1077 STAN_InitTokenForSlotInfo(NULL, slot);
1078 }
1079 newSlots[i] = slot;
1080 }
1081 STAN_ResetTokenInterator(NULL);
1082 PORT_Free(slotIDs);
1083 slotIDs = NULL;
1084 PORT_ArenaUnmark(mod->arena, mark);
1085
1086 /* until this point we're still using the old slot list. Now we update
1087 * module slot list. We update the slots (array) first then the count,
1088 * since we've already guarrenteed that count has increased (just in case
1089 * someone is looking at the slots field of module without holding the
1090 * moduleLock */
1091 SECMOD_GetWriteLock(moduleLock);
1092 oldCount = mod->slotCount;
1093 oldSlots = mod->slots;
1094 mod->slots = newSlots; /* typical arena 'leak'... old mod->slots is
1095 * allocated out of the module arena and won't
1096 * be freed until the module is freed */
1097 mod->slotCount = count;
1098 SECMOD_ReleaseWriteLock(moduleLock);
1099 /* free our old references before forgetting about oldSlot*/
1100 for (i = 0; i < oldCount; i++) {
1101 PK11_FreeSlot(oldSlots[i]);
1102 }
1103 return SECSuccess;
1104
1105 loser:
1106 if (freeRef) {
1107 PZ_Unlock(mod->refLock);
1108 }
1109 if (slotIDs) {
1110 PORT_Free(slotIDs);
1111 }
1112 /* free all the slots we allocated. newSlots are part of the
1113 * mod arena. NOTE: the newSlots array contain both new and old
1114 * slots, but we kept a reference to the old slots when we built the new
1115 * array, so we need to free all the slots in newSlots array. */
1116 if (newSlots) {
1117 for (i = 0; i < count; i++) {
1118 if (newSlots[i] == NULL) {
1119 break; /* hit the last one */
1120 }
1121 PK11_FreeSlot(newSlots[i]);
1122 }
1123 }
1124 /* must come after freeing newSlots */
1125 if (mark) {
1126 PORT_ArenaRelease(mod->arena, mark);
1127 }
1128 return SECFailure;
1129 }
1130
1131 /*
1132 * this handles modules that do not support C_WaitForSlotEvent().
1133 * The internal flags are stored. Note that C_WaitForSlotEvent() does not
1134 * have a timeout, so we don't have one for handleWaitForSlotEvent() either.
1135 */
1136 PK11SlotInfo *
secmod_HandleWaitForSlotEvent(SECMODModule * mod,unsigned long flags,PRIntervalTime latency)1137 secmod_HandleWaitForSlotEvent(SECMODModule *mod, unsigned long flags,
1138 PRIntervalTime latency)
1139 {
1140 PRBool removableSlotsFound = PR_FALSE;
1141 int i;
1142 int error = SEC_ERROR_NO_EVENT;
1143
1144 if (!moduleLock) {
1145 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1146 return NULL;
1147 }
1148 PZ_Lock(mod->refLock);
1149 if (mod->evControlMask & SECMOD_END_WAIT) {
1150 mod->evControlMask &= ~SECMOD_END_WAIT;
1151 PZ_Unlock(mod->refLock);
1152 PORT_SetError(SEC_ERROR_NO_EVENT);
1153 return NULL;
1154 }
1155 mod->evControlMask |= SECMOD_WAIT_SIMULATED_EVENT;
1156 while (mod->evControlMask & SECMOD_WAIT_SIMULATED_EVENT) {
1157 PZ_Unlock(mod->refLock);
1158 /* now is a good time to see if new slots have been added */
1159 SECMOD_UpdateSlotList(mod);
1160
1161 /* loop through all the slots on a module */
1162 SECMOD_GetReadLock(moduleLock);
1163 for (i = 0; i < mod->slotCount; i++) {
1164 PK11SlotInfo *slot = mod->slots[i];
1165 PRUint16 series;
1166 PRBool present;
1167
1168 /* perm modules do not change */
1169 if (slot->isPerm) {
1170 continue;
1171 }
1172 removableSlotsFound = PR_TRUE;
1173 /* simulate the PKCS #11 module flags. are the flags different
1174 * from the last time we called? */
1175 series = slot->series;
1176 present = PK11_IsPresent(slot);
1177 if ((slot->flagSeries != series) || (slot->flagState != present)) {
1178 slot->flagState = present;
1179 slot->flagSeries = series;
1180 SECMOD_ReleaseReadLock(moduleLock);
1181 PZ_Lock(mod->refLock);
1182 mod->evControlMask &= ~SECMOD_END_WAIT;
1183 PZ_Unlock(mod->refLock);
1184 return PK11_ReferenceSlot(slot);
1185 }
1186 }
1187 SECMOD_ReleaseReadLock(moduleLock);
1188 /* if everything was perm modules, don't lock up forever */
1189 if ((mod->slotCount != 0) && !removableSlotsFound) {
1190 error = SEC_ERROR_NO_SLOT_SELECTED;
1191 PZ_Lock(mod->refLock);
1192 break;
1193 }
1194 if (flags & CKF_DONT_BLOCK) {
1195 PZ_Lock(mod->refLock);
1196 break;
1197 }
1198 PR_Sleep(latency);
1199 PZ_Lock(mod->refLock);
1200 }
1201 mod->evControlMask &= ~SECMOD_END_WAIT;
1202 PZ_Unlock(mod->refLock);
1203 PORT_SetError(error);
1204 return NULL;
1205 }
1206
1207 /*
1208 * this function waits for a token event on any slot of a given module
1209 * This function should not be called from more than one thread of the
1210 * same process (though other threads can make other library calls
1211 * on this module while this call is blocked).
1212 */
1213 PK11SlotInfo *
SECMOD_WaitForAnyTokenEvent(SECMODModule * mod,unsigned long flags,PRIntervalTime latency)1214 SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags,
1215 PRIntervalTime latency)
1216 {
1217 CK_SLOT_ID id;
1218 CK_RV crv;
1219 PK11SlotInfo *slot;
1220
1221 if (!pk11_getFinalizeModulesOption() ||
1222 ((mod->cryptokiVersion.major == 2) &&
1223 (mod->cryptokiVersion.minor < 1))) {
1224 /* if we are sharing the module with other software in our
1225 * address space, we can't reliably use C_WaitForSlotEvent(),
1226 * and if the module is version 2.0, C_WaitForSlotEvent() doesn't
1227 * exist */
1228 return secmod_HandleWaitForSlotEvent(mod, flags, latency);
1229 }
1230 /* first the the PKCS #11 call */
1231 PZ_Lock(mod->refLock);
1232 if (mod->evControlMask & SECMOD_END_WAIT) {
1233 goto end_wait;
1234 }
1235 mod->evControlMask |= SECMOD_WAIT_PKCS11_EVENT;
1236 PZ_Unlock(mod->refLock);
1237 crv = PK11_GETTAB(mod)->C_WaitForSlotEvent(flags, &id, NULL);
1238 PZ_Lock(mod->refLock);
1239 mod->evControlMask &= ~SECMOD_WAIT_PKCS11_EVENT;
1240 /* if we are in end wait, short circuit now, don't even risk
1241 * going into secmod_HandleWaitForSlotEvent */
1242 if (mod->evControlMask & SECMOD_END_WAIT) {
1243 goto end_wait;
1244 }
1245 PZ_Unlock(mod->refLock);
1246 if (crv == CKR_FUNCTION_NOT_SUPPORTED) {
1247 /* module doesn't support that call, simulate it */
1248 return secmod_HandleWaitForSlotEvent(mod, flags, latency);
1249 }
1250 if (crv != CKR_OK) {
1251 /* we can get this error if finalize was called while we were
1252 * still running. This is the only way to force a C_WaitForSlotEvent()
1253 * to return in PKCS #11. In this case, just return that there
1254 * was no event. */
1255 if (crv == CKR_CRYPTOKI_NOT_INITIALIZED) {
1256 PORT_SetError(SEC_ERROR_NO_EVENT);
1257 } else {
1258 PORT_SetError(PK11_MapError(crv));
1259 }
1260 return NULL;
1261 }
1262 slot = SECMOD_FindSlotByID(mod, id);
1263 if (slot == NULL) {
1264 /* possibly a new slot that was added? */
1265 SECMOD_UpdateSlotList(mod);
1266 slot = SECMOD_FindSlotByID(mod, id);
1267 }
1268 /* if we are in the delay period for the "isPresent" call, reset
1269 * the delay since we know things have probably changed... */
1270 if (slot) {
1271 NSSToken *nssToken = PK11Slot_GetNSSToken(slot);
1272 if (nssToken) {
1273 if (nssToken->slot) {
1274 nssSlot_ResetDelay(nssToken->slot);
1275 }
1276 (void)nssToken_Destroy(nssToken);
1277 }
1278 }
1279 return slot;
1280
1281 /* must be called with the lock on. */
1282 end_wait:
1283 mod->evControlMask &= ~SECMOD_END_WAIT;
1284 PZ_Unlock(mod->refLock);
1285 PORT_SetError(SEC_ERROR_NO_EVENT);
1286 return NULL;
1287 }
1288
1289 /*
1290 * This function "wakes up" WaitForAnyTokenEvent. It's a pretty drastic
1291 * function, possibly bringing down the pkcs #11 module in question. This
1292 * should be OK because 1) it does reinitialize, and 2) it should only be
1293 * called when we are on our way to tear the whole system down anyway.
1294 */
1295 SECStatus
SECMOD_CancelWait(SECMODModule * mod)1296 SECMOD_CancelWait(SECMODModule *mod)
1297 {
1298 unsigned long controlMask;
1299 SECStatus rv = SECSuccess;
1300 CK_RV crv;
1301
1302 PZ_Lock(mod->refLock);
1303 mod->evControlMask |= SECMOD_END_WAIT;
1304 controlMask = mod->evControlMask;
1305 if (controlMask & SECMOD_WAIT_PKCS11_EVENT) {
1306 if (!pk11_getFinalizeModulesOption()) {
1307 /* can't get here unless pk11_getFinalizeModulesOption is set */
1308 PORT_Assert(0);
1309 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1310 rv = SECFailure;
1311 goto loser;
1312 }
1313 /* NOTE: this call will drop all transient keys, in progress
1314 * operations, and any authentication. This is the only documented
1315 * way to get WaitForSlotEvent to return. Also note: for non-thread
1316 * safe tokens, we need to hold the module lock, this is not yet at
1317 * system shutdown/startup time, so we need to protect these calls */
1318 crv = PK11_GETTAB(mod)->C_Finalize(NULL);
1319 /* ok, we slammed the module down, now we need to reinit it in case
1320 * we intend to use it again */
1321 if (CKR_OK == crv) {
1322 PRBool alreadyLoaded;
1323 secmod_ModuleInit(mod, NULL, &alreadyLoaded);
1324 } else {
1325 /* Finalized failed for some reason, notify the application
1326 * so maybe it has a prayer of recovering... */
1327 PORT_SetError(PK11_MapError(crv));
1328 rv = SECFailure;
1329 }
1330 } else if (controlMask & SECMOD_WAIT_SIMULATED_EVENT) {
1331 mod->evControlMask &= ~SECMOD_WAIT_SIMULATED_EVENT;
1332 /* Simulated events will eventually timeout
1333 * and wake up in the loop */
1334 }
1335 loser:
1336 PZ_Unlock(mod->refLock);
1337 return rv;
1338 }
1339
1340 /*
1341 * check to see if the module has removable slots that we may need to
1342 * watch for.
1343 */
1344 PRBool
SECMOD_HasRemovableSlots(SECMODModule * mod)1345 SECMOD_HasRemovableSlots(SECMODModule *mod)
1346 {
1347 int i;
1348 PRBool ret = PR_FALSE;
1349
1350 if (!moduleLock) {
1351 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1352 return ret;
1353 }
1354 SECMOD_GetReadLock(moduleLock);
1355 for (i = 0; i < mod->slotCount; i++) {
1356 PK11SlotInfo *slot = mod->slots[i];
1357 /* perm modules are not inserted or removed */
1358 if (slot->isPerm) {
1359 continue;
1360 }
1361 ret = PR_TRUE;
1362 break;
1363 }
1364 if (mod->slotCount == 0) {
1365 ret = PR_TRUE;
1366 }
1367 SECMOD_ReleaseReadLock(moduleLock);
1368 return ret;
1369 }
1370
1371 /*
1372 * helper function to actually create and destroy user defined slots
1373 */
1374 static SECStatus
secmod_UserDBOp(PK11SlotInfo * slot,CK_OBJECT_CLASS objClass,const char * sendSpec)1375 secmod_UserDBOp(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass,
1376 const char *sendSpec)
1377 {
1378 CK_OBJECT_HANDLE dummy;
1379 CK_ATTRIBUTE template[2];
1380 CK_ATTRIBUTE *attrs = template;
1381 CK_RV crv;
1382
1383 PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass));
1384 attrs++;
1385 PK11_SETATTRS(attrs, CKA_NSS_MODULE_SPEC, (unsigned char *)sendSpec,
1386 strlen(sendSpec) + 1);
1387 attrs++;
1388
1389 PORT_Assert(attrs - template <= 2);
1390
1391 PK11_EnterSlotMonitor(slot);
1392 crv = PK11_CreateNewObject(slot, slot->session,
1393 template, attrs - template, PR_FALSE, &dummy);
1394 PK11_ExitSlotMonitor(slot);
1395
1396 if (crv != CKR_OK) {
1397 PORT_SetError(PK11_MapError(crv));
1398 return SECFailure;
1399 }
1400 return SECMOD_UpdateSlotList(slot->module);
1401 }
1402
1403 /*
1404 * return true if the selected slot ID is not present or doesn't exist
1405 */
1406 static PRBool
secmod_SlotIsEmpty(SECMODModule * mod,CK_SLOT_ID slotID)1407 secmod_SlotIsEmpty(SECMODModule *mod, CK_SLOT_ID slotID)
1408 {
1409 PK11SlotInfo *slot = SECMOD_LookupSlot(mod->moduleID, slotID);
1410 if (slot) {
1411 PRBool present = PK11_IsPresent(slot);
1412 PK11_FreeSlot(slot);
1413 if (present) {
1414 return PR_FALSE;
1415 }
1416 }
1417 /* it doesn't exist or isn't present, it's available */
1418 return PR_TRUE;
1419 }
1420
1421 /*
1422 * Find an unused slot id in module.
1423 */
1424 static CK_SLOT_ID
secmod_FindFreeSlot(SECMODModule * mod)1425 secmod_FindFreeSlot(SECMODModule *mod)
1426 {
1427 CK_SLOT_ID i, minSlotID, maxSlotID;
1428
1429 /* look for a free slot id on the internal module */
1430 if (mod->internal && mod->isFIPS) {
1431 minSlotID = SFTK_MIN_FIPS_USER_SLOT_ID;
1432 maxSlotID = SFTK_MAX_FIPS_USER_SLOT_ID;
1433 } else {
1434 minSlotID = SFTK_MIN_USER_SLOT_ID;
1435 maxSlotID = SFTK_MAX_USER_SLOT_ID;
1436 }
1437 for (i = minSlotID; i < maxSlotID; i++) {
1438 if (secmod_SlotIsEmpty(mod, i)) {
1439 return i;
1440 }
1441 }
1442 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
1443 return (CK_SLOT_ID)-1;
1444 }
1445
1446 /*
1447 * Attempt to open a new slot.
1448 *
1449 * This works the same os OpenUserDB except it can be called against
1450 * any module that understands the softoken protocol for opening new
1451 * slots, not just the softoken itself. If the selected module does not
1452 * understand the protocol, C_CreateObject will fail with
1453 * CKR_INVALID_ATTRIBUTE, and SECMOD_OpenNewSlot will return NULL and set
1454 * SEC_ERROR_BAD_DATA.
1455 *
1456 * NewSlots can be closed with SECMOD_CloseUserDB();
1457 *
1458 * Modulespec is module dependent.
1459 */
1460 PK11SlotInfo *
SECMOD_OpenNewSlot(SECMODModule * mod,const char * moduleSpec)1461 SECMOD_OpenNewSlot(SECMODModule *mod, const char *moduleSpec)
1462 {
1463 CK_SLOT_ID slotID = 0;
1464 PK11SlotInfo *slot;
1465 char *escSpec;
1466 char *sendSpec;
1467 SECStatus rv;
1468
1469 slotID = secmod_FindFreeSlot(mod);
1470 if (slotID == (CK_SLOT_ID)-1) {
1471 return NULL;
1472 }
1473
1474 if (mod->slotCount == 0) {
1475 return NULL;
1476 }
1477
1478 /* just grab the first slot in the module, any present slot should work */
1479 slot = PK11_ReferenceSlot(mod->slots[0]);
1480 if (slot == NULL) {
1481 return NULL;
1482 }
1483
1484 /* we've found the slot, now build the moduleSpec */
1485 escSpec = NSSUTIL_DoubleEscape(moduleSpec, '>', ']');
1486 if (escSpec == NULL) {
1487 PK11_FreeSlot(slot);
1488 return NULL;
1489 }
1490 sendSpec = PR_smprintf("tokens=[0x%x=<%s>]", slotID, escSpec);
1491 PORT_Free(escSpec);
1492
1493 if (sendSpec == NULL) {
1494 /* PR_smprintf does not set SEC_ERROR_NO_MEMORY on failure. */
1495 PK11_FreeSlot(slot);
1496 PORT_SetError(SEC_ERROR_NO_MEMORY);
1497 return NULL;
1498 }
1499 rv = secmod_UserDBOp(slot, CKO_NSS_NEWSLOT, sendSpec);
1500 PR_smprintf_free(sendSpec);
1501 PK11_FreeSlot(slot);
1502 if (rv != SECSuccess) {
1503 return NULL;
1504 }
1505
1506 slot = SECMOD_FindSlotByID(mod, slotID);
1507 if (slot) {
1508 /* if we are in the delay period for the "isPresent" call, reset
1509 * the delay since we know things have probably changed... */
1510 NSSToken *nssToken = PK11Slot_GetNSSToken(slot);
1511 if (nssToken) {
1512 if (nssToken->slot) {
1513 nssSlot_ResetDelay(nssToken->slot);
1514 }
1515 (void)nssToken_Destroy(nssToken);
1516 }
1517 /* force the slot info structures to properly reset */
1518 (void)PK11_IsPresent(slot);
1519 }
1520 return slot;
1521 }
1522
1523 /*
1524 * given a module spec, find the slot in the module for it.
1525 */
1526 PK11SlotInfo *
secmod_FindSlotFromModuleSpec(const char * moduleSpec,SECMODModule * module)1527 secmod_FindSlotFromModuleSpec(const char *moduleSpec, SECMODModule *module)
1528 {
1529 CK_SLOT_ID slot_id = secmod_GetSlotIDFromModuleSpec(moduleSpec, module);
1530 if (slot_id == -1) {
1531 return NULL;
1532 }
1533
1534 return SECMOD_FindSlotByID(module, slot_id);
1535 }
1536
1537 /*
1538 * Open a new database using the softoken. The caller is responsible for making
1539 * sure the module spec is correct and usable. The caller should ask for one
1540 * new database per call if the caller wants to get meaningful information
1541 * about the new database.
1542 *
1543 * moduleSpec is the same data that you would pass to softoken at
1544 * initialization time under the 'tokens' options. For example, if you were
1545 * to specify tokens=<0x4=[configdir='./mybackup' tokenDescription='Backup']>
1546 * You would specify "configdir='./mybackup' tokenDescription='Backup'" as your
1547 * module spec here. The slot ID will be calculated for you by
1548 * SECMOD_OpenUserDB().
1549 *
1550 * Typical parameters here are configdir, tokenDescription and flags.
1551 *
1552 * a Full list is below:
1553 *
1554 *
1555 * configDir - The location of the databases for this token. If configDir is
1556 * not specified, and noCertDB and noKeyDB is not specified, the load
1557 * will fail.
1558 * certPrefix - Cert prefix for this token.
1559 * keyPrefix - Prefix for the key database for this token. (if not specified,
1560 * certPrefix will be used).
1561 * tokenDescription - The label value for this token returned in the
1562 * CK_TOKEN_INFO structure with an internationalize string (UTF8).
1563 * This value will be truncated at 32 bytes (no NULL, partial UTF8
1564 * characters dropped). You should specify a user friendly name here
1565 * as this is the value the token will be referred to in most
1566 * application UI's. You should make sure tokenDescription is unique.
1567 * slotDescription - The slotDescription value for this token returned
1568 * in the CK_SLOT_INFO structure with an internationalize string
1569 * (UTF8). This value will be truncated at 64 bytes (no NULL, partial
1570 * UTF8 characters dropped). This name will not change after the
1571 * database is closed. It should have some number to make this unique.
1572 * minPWLen - minimum password length for this token.
1573 * flags - comma separated list of flag values, parsed case-insensitive.
1574 * Valid flags are:
1575 * readOnly - Databases should be opened read only.
1576 * noCertDB - Don't try to open a certificate database.
1577 * noKeyDB - Don't try to open a key database.
1578 * forceOpen - Don't fail to initialize the token if the
1579 * databases could not be opened.
1580 * passwordRequired - zero length passwords are not acceptable
1581 * (valid only if there is a keyDB).
1582 * optimizeSpace - allocate smaller hash tables and lock tables.
1583 * When this flag is not specified, Softoken will allocate
1584 * large tables to prevent lock contention.
1585 */
1586 PK11SlotInfo *
SECMOD_OpenUserDB(const char * moduleSpec)1587 SECMOD_OpenUserDB(const char *moduleSpec)
1588 {
1589 SECMODModule *mod;
1590 SECMODConfigList *conflist = NULL;
1591 int count = 0;
1592
1593 if (moduleSpec == NULL) {
1594 return NULL;
1595 }
1596
1597 /* NOTE: unlike most PK11 function, this does not return a reference
1598 * to the module */
1599 mod = SECMOD_GetInternalModule();
1600 if (!mod) {
1601 /* shouldn't happen */
1602 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1603 return NULL;
1604 }
1605
1606 /* make sure we don't open the same database twice. We only understand
1607 * the moduleSpec for internal databases well enough to do this, so only
1608 * do this in OpenUserDB */
1609 conflist = secmod_GetConfigList(mod->isFIPS, mod->libraryParams, &count);
1610 if (conflist) {
1611 PK11SlotInfo *slot = NULL;
1612 if (secmod_MatchConfigList(moduleSpec, conflist, count)) {
1613 slot = secmod_FindSlotFromModuleSpec(moduleSpec, mod);
1614 }
1615 secmod_FreeConfigList(conflist, count);
1616 if (slot) {
1617 return slot;
1618 }
1619 }
1620 return SECMOD_OpenNewSlot(mod, moduleSpec);
1621 }
1622
1623 /*
1624 * close an already opened user database. NOTE: the database must be
1625 * in the internal token, and must be one created with SECMOD_OpenUserDB().
1626 * Once the database is closed, the slot will remain as an empty slot
1627 * until it's used again with SECMOD_OpenUserDB() or SECMOD_OpenNewSlot().
1628 */
1629 SECStatus
SECMOD_CloseUserDB(PK11SlotInfo * slot)1630 SECMOD_CloseUserDB(PK11SlotInfo *slot)
1631 {
1632 SECStatus rv;
1633 char *sendSpec;
1634
1635 sendSpec = PR_smprintf("tokens=[0x%x=<>]", slot->slotID);
1636 if (sendSpec == NULL) {
1637 /* PR_smprintf does not set no memory error */
1638 PORT_SetError(SEC_ERROR_NO_MEMORY);
1639 return SECFailure;
1640 }
1641 rv = secmod_UserDBOp(slot, CKO_NSS_DELSLOT, sendSpec);
1642 PR_smprintf_free(sendSpec);
1643 /* if we are in the delay period for the "isPresent" call, reset
1644 * the delay since we know things have probably changed... */
1645 NSSToken *nssToken = PK11Slot_GetNSSToken(slot);
1646 if (nssToken) {
1647 if (nssToken->slot) {
1648 nssSlot_ResetDelay(nssToken->slot);
1649 }
1650 (void)nssToken_Destroy(nssToken);
1651 /* force the slot info structures to properly reset */
1652 (void)PK11_IsPresent(slot);
1653 }
1654 return rv;
1655 }
1656
1657 /*
1658 * Restart PKCS #11 modules after a fork(). See secmod.h for more information.
1659 */
1660 SECStatus
SECMOD_RestartModules(PRBool force)1661 SECMOD_RestartModules(PRBool force)
1662 {
1663 SECMODModuleList *mlp;
1664 SECStatus rrv = SECSuccess;
1665 int lastError = 0;
1666
1667 if (!moduleLock) {
1668 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1669 return SECFailure;
1670 }
1671
1672 /* Only need to restart the PKCS #11 modules that were initialized */
1673 SECMOD_GetReadLock(moduleLock);
1674 for (mlp = modules; mlp != NULL; mlp = mlp->next) {
1675 SECMODModule *mod = mlp->module;
1676 CK_ULONG count;
1677 SECStatus rv;
1678 int i;
1679
1680 /* If the module needs to be reset, do so */
1681 if (force || (PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, NULL, &count) != CKR_OK)) {
1682 PRBool alreadyLoaded;
1683 /* first call Finalize. This is not required by PKCS #11, but some
1684 * older modules require it, and it doesn't hurt (compliant modules
1685 * will return CKR_NOT_INITIALIZED */
1686 (void)PK11_GETTAB(mod)->C_Finalize(NULL);
1687 /* now initialize the module, this function reinitializes
1688 * a module in place, preserving existing slots (even if they
1689 * no longer exist) */
1690 rv = secmod_ModuleInit(mod, NULL, &alreadyLoaded);
1691 if (rv != SECSuccess) {
1692 /* save the last error code */
1693 lastError = PORT_GetError();
1694 rrv = rv;
1695 /* couldn't reinit the module, disable all its slots */
1696 for (i = 0; i < mod->slotCount; i++) {
1697 mod->slots[i]->disabled = PR_TRUE;
1698 mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1699 }
1700 continue;
1701 }
1702 for (i = 0; i < mod->slotCount; i++) {
1703 /* get new token sessions, bump the series up so that
1704 * we refresh other old sessions. This will tell much of
1705 * NSS to flush cached handles it may hold as well */
1706 rv = PK11_InitToken(mod->slots[i], PR_TRUE);
1707 /* PK11_InitToken could fail if the slot isn't present.
1708 * If it is present, though, something is wrong and we should
1709 * disable the slot and let the caller know. */
1710 if (rv != SECSuccess && PK11_IsPresent(mod->slots[i])) {
1711 /* save the last error code */
1712 lastError = PORT_GetError();
1713 rrv = rv;
1714 /* disable the token */
1715 mod->slots[i]->disabled = PR_TRUE;
1716 mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1717 }
1718 }
1719 }
1720 }
1721 SECMOD_ReleaseReadLock(moduleLock);
1722
1723 /*
1724 * on multiple failures, we are only returning the lastError. The caller
1725 * can determine which slots are bad by calling PK11_IsDisabled().
1726 */
1727 if (rrv != SECSuccess) {
1728 /* restore the last error code */
1729 PORT_SetError(lastError);
1730 }
1731
1732 return rrv;
1733 }
1734