Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / dev / devmod.c
blobf071ec95539a4613ad4dbad86ecfe9ea31f47e00
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 #ifdef DEBUG
38 static const char CVS_ID[] = "@(#) $RCSfile: devmod.c,v $ $Revision: 1.7 $ $Date: 2005/01/20 02:25:47 $";
39 #endif /* DEBUG */
41 #ifndef NSSCKEPV_H
42 #include "nssckepv.h"
43 #endif /* NSSCKEPV_H */
45 #ifndef DEVM_H
46 #include "devm.h"
47 #endif /* DEVM_H */
49 #ifndef CKHELPER_H
50 #include "ckhelper.h"
51 #endif /* CKHELPER_H */
53 #ifdef PURE_STAN_CODE
55 extern void FC_GetFunctionList(void);
56 extern void NSC_GetFunctionList(void);
57 extern void NSC_ModuleDBFunc(void);
59 /* The list of boolean flags used to describe properties of a
60 * module.
62 #define NSSMODULE_FLAGS_NOT_THREADSAFE 0x0001 /* isThreadSafe */
63 #define NSSMODULE_FLAGS_INTERNAL 0x0002 /* isInternal */
64 #define NSSMODULE_FLAGS_FIPS 0x0004 /* isFIPS */
65 #define NSSMODULE_FLAGS_MODULE_DB 0x0008 /* isModuleDB */
66 #define NSSMODULE_FLAGS_MODULE_DB_ONLY 0x0010 /* moduleDBOnly */
67 #define NSSMODULE_FLAGS_CRITICAL 0x0020 /* isCritical */
69 struct NSSModuleStr {
70 struct nssDeviceBaseStr base;
71 NSSUTF8 *libraryName;
72 PRLibrary *library;
73 char *libraryParams;
74 void *moduleDBFunc;
75 void *epv;
76 CK_INFO info;
77 NSSSlot **slots;
78 PRUint32 numSlots;
79 PRBool isLoaded;
80 struct {
81 PRInt32 trust;
82 PRInt32 cipher;
83 PRInt32 certStorage;
84 } order;
87 #define NSSMODULE_IS_THREADSAFE(module) \
88 (!(module->base.flags & NSSMODULE_FLAGS_NOT_THREADSAFE))
90 #define NSSMODULE_IS_INTERNAL(module) \
91 (module->base.flags & NSSMODULE_FLAGS_INTERNAL)
93 #define NSSMODULE_IS_FIPS(module) \
94 (module->base.flags & NSSMODULE_FLAGS_FIPS)
96 #define NSSMODULE_IS_MODULE_DB(module) \
97 (module->base.flags & NSSMODULE_FLAGS_MODULE_DB)
99 #define NSSMODULE_IS_MODULE_DB_ONLY(module) \
100 (module->base.flags & NSSMODULE_FLAGS_MODULE_DB_ONLY)
102 #define NSSMODULE_IS_CRITICAL(module) \
103 (module->base.flags & NSSMODULE_FLAGS_CRITICAL)
105 /* Threading callbacks for C_Initialize. Use NSPR threads. */
107 CK_RV PR_CALLBACK
108 nss_ck_CreateMutex(CK_VOID_PTR_PTR pMutex)
110 CK_VOID_PTR mutex = (CK_VOID_PTR)PZ_NewLock(nssILockOther);
111 if (mutex != NULL) {
112 *pMutex = (CK_VOID_PTR)mutex;
113 return CKR_OK;
115 return CKR_HOST_MEMORY;
118 CK_RV PR_CALLBACK
119 nss_ck_DestroyMutex(CK_VOID_PTR mutex)
121 PZ_DestroyLock((PZLock *)mutex);
122 return CKR_OK;
125 CK_RV PR_CALLBACK
126 nss_ck_LockMutex(CK_VOID_PTR mutex)
128 PZ_Lock((PZLock *)mutex);
129 return CKR_OK;
132 CK_RV PR_CALLBACK
133 nss_ck_UnlockMutex(CK_VOID_PTR mutex)
135 return (PZ_Unlock((PZLock *)mutex) == PR_SUCCESS) ?
136 CKR_OK : CKR_MUTEX_NOT_LOCKED;
139 /* Default callback args to C_Initialize */
140 /* XXX not const because we are modifying the pReserved argument in order
141 * to use the libraryParams extension.
143 static CK_C_INITIALIZE_ARGS
144 s_ck_initialize_args = {
145 nss_ck_CreateMutex, /* CreateMutex */
146 nss_ck_DestroyMutex, /* DestroyMutex */
147 nss_ck_LockMutex, /* LockMutex */
148 nss_ck_UnlockMutex, /* UnlockMutex */
149 CKF_LIBRARY_CANT_CREATE_OS_THREADS |
150 CKF_OS_LOCKING_OK, /* flags */
151 NULL /* pReserved */
154 /* load all slots in a module. */
155 static PRStatus
156 module_load_slots(NSSModule *mod)
158 CK_ULONG i, ulNumSlots;
159 CK_SLOT_ID *slotIDs;
160 nssArenaMark *mark = NULL;
161 NSSSlot **slots;
162 PRStatus nssrv;
163 CK_RV ckrv;
164 /* Get the number of slots */
165 ckrv = CKAPI(mod->epv)->C_GetSlotList(CK_FALSE, NULL, &ulNumSlots);
166 if (ckrv != CKR_OK) {
167 /* what is the error? */
168 return PR_FAILURE;
170 /* Alloc memory for the array of slot ID's */
171 slotIDs = nss_ZNEWARRAY(NULL, CK_SLOT_ID, ulNumSlots);
172 if (!slotIDs) {
173 goto loser;
175 /* Get the actual slot list */
176 ckrv = CKAPI(mod->epv)->C_GetSlotList(CK_FALSE, slotIDs, &ulNumSlots);
177 if (ckrv != CKR_OK) {
178 /* what is the error? */
179 goto loser;
181 /* Alloc memory for the array of slots, in the module's arena */
182 mark = nssArena_Mark(mod->base.arena); /* why mark? it'll be destroyed */
183 if (!mark) {
184 return PR_FAILURE;
186 slots = nss_ZNEWARRAY(mod->base.arena, NSSSlot *, ulNumSlots);
187 if (!slots) {
188 goto loser;
190 /* Initialize each slot */
191 for (i=0; i<ulNumSlots; i++) {
192 slots[i] = nssSlot_Create(slotIDs[i], mod);
194 nss_ZFreeIf(slotIDs);
195 nssrv = nssArena_Unmark(mod->base.arena, mark);
196 if (nssrv != PR_SUCCESS) {
197 goto loser;
199 mod->slots = slots;
200 mod->numSlots = ulNumSlots;
201 return PR_SUCCESS;
202 loser:
203 if (mark) {
204 nssArena_Release(mod->base.arena, mark);
206 nss_ZFreeIf(slotIDs);
207 return PR_FAILURE;
210 NSS_IMPLEMENT PRStatus
211 nssModule_Load (
212 NSSModule *mod
215 PRLibrary *library = NULL;
216 CK_C_GetFunctionList epv;
217 CK_RV ckrv;
218 if (NSSMODULE_IS_INTERNAL(mod)) {
219 /* internal, statically get the C_GetFunctionList function */
220 if (NSSMODULE_IS_FIPS(mod)) {
221 epv = (CK_C_GetFunctionList) FC_GetFunctionList;
222 } else {
223 epv = (CK_C_GetFunctionList) NSC_GetFunctionList;
225 if (NSSMODULE_IS_MODULE_DB(mod)) {
226 mod->moduleDBFunc = (void *) NSC_ModuleDBFunc;
228 if (NSSMODULE_IS_MODULE_DB_ONLY(mod)) {
229 mod->isLoaded = PR_TRUE; /* XXX needed? */
230 return PR_SUCCESS;
232 } else {
233 /* Use NSPR to load the library */
234 library = PR_LoadLibrary(mod->libraryName);
235 if (!library) {
236 /* what's the error to set? */
237 return PR_FAILURE;
239 mod->library = library;
240 /* Skip if only getting the db loader function */
241 if (!NSSMODULE_IS_MODULE_DB_ONLY(mod)) {
242 /* Load the cryptoki entry point function */
243 epv = (CK_C_GetFunctionList)PR_FindSymbol(library,
244 "C_GetFunctionList");
246 /* Load the module database loader function */
247 if (NSSMODULE_IS_MODULE_DB(mod)) {
248 mod->moduleDBFunc = (void *)PR_FindSymbol(library,
249 "NSS_ReturnModuleSpecData");
252 if (epv == NULL) {
253 goto loser;
255 /* Load the cryptoki entry point vector (function list) */
256 ckrv = (*epv)((CK_FUNCTION_LIST_PTR *)&mod->epv);
257 if (ckrv != CKR_OK) {
258 goto loser;
260 /* Initialize the module */
261 if (mod->libraryParams) {
262 s_ck_initialize_args.LibraryParameters = (void *)mod->libraryParams;
263 } else {
264 s_ck_initialize_args.LibraryParameters = NULL;
266 ckrv = CKAPI(mod->epv)->C_Initialize(&s_ck_initialize_args);
267 if (ckrv != CKR_OK) {
268 /* Apparently the token is not thread safe. Retry without
269 * threading parameters.
271 mod->base.flags |= NSSMODULE_FLAGS_NOT_THREADSAFE;
272 ckrv = CKAPI(mod->epv)->C_Initialize((CK_VOID_PTR)NULL);
273 if (ckrv != CKR_OK) {
274 goto loser;
277 /* TODO: check the version # using C_GetInfo */
278 ckrv = CKAPI(mod->epv)->C_GetInfo(&mod->info);
279 if (ckrv != CKR_OK) {
280 goto loser;
282 /* TODO: if the name is not set, get it from info.libraryDescription */
283 /* Now load the slots */
284 if (module_load_slots(mod) != PR_SUCCESS) {
285 goto loser;
287 /* Module has successfully loaded */
288 mod->isLoaded = PR_TRUE;
289 return PR_SUCCESS;
290 loser:
291 if (library) {
292 PR_UnloadLibrary(library);
294 /* clear all values set above, they are invalid now */
295 mod->library = NULL;
296 mod->epv = NULL;
297 return PR_FAILURE;
300 NSS_IMPLEMENT PRStatus
301 nssModule_Unload (
302 NSSModule *mod
305 PRStatus nssrv = PR_SUCCESS;
306 if (mod->library) {
307 (void)CKAPI(mod->epv)->C_Finalize(NULL);
308 nssrv = PR_UnloadLibrary(mod->library);
310 /* Free the slots, yes? */
311 mod->library = NULL;
312 mod->epv = NULL;
313 mod->isLoaded = PR_FALSE;
314 return nssrv;
317 /* Alloc memory for a module. Copy in the module name and library path
318 * if provided. XXX use the opaque arg also, right?
320 NSS_IMPLEMENT NSSModule *
321 nssModule_Create (
322 NSSUTF8 *moduleOpt,
323 NSSUTF8 *uriOpt,
324 NSSUTF8 *opaqueOpt,
325 void *reserved
328 NSSArena *arena;
329 NSSModule *rvMod;
330 arena = NSSArena_Create();
331 if(!arena) {
332 return (NSSModule *)NULL;
334 rvMod = nss_ZNEW(arena, NSSModule);
335 if (!rvMod) {
336 goto loser;
338 if (moduleOpt) {
339 /* XXX making the gross assumption this is just the module name */
340 /* if the name is a duplicate, should that be tested here? or
341 * wait for Load?
343 rvMod->base.name = nssUTF8_Duplicate(moduleOpt, arena);
344 if (!rvMod->base.name) {
345 goto loser;
348 if (uriOpt) {
349 /* Load the module from a URI. */
350 /* XXX at this time - only file URI (even worse, no file:// for now) */
351 rvMod->libraryName = nssUTF8_Duplicate(uriOpt, arena);
352 if (!rvMod->libraryName) {
353 goto loser;
356 rvMod->base.arena = arena;
357 rvMod->base.refCount = 1;
358 rvMod->base.lock = PZ_NewLock(nssNSSILockOther);
359 if (!rvMod->base.lock) {
360 goto loser;
362 /* everything else is 0/NULL at this point. */
363 return rvMod;
364 loser:
365 nssArena_Destroy(arena);
366 return (NSSModule *)NULL;
369 NSS_EXTERN PRStatus
370 nssCryptokiArgs_ParseNextPair (
371 NSSUTF8 *start,
372 NSSUTF8 **attrib,
373 NSSUTF8 **value,
374 NSSUTF8 **remainder,
375 NSSArena *arenaOpt
378 static PRStatus
379 parse_slot_flags (
380 NSSSlot *slot,
381 NSSUTF8 *slotFlags
384 PRStatus nssrv = PR_SUCCESS;
385 #if 0
386 PRBool done = PR_FALSE;
387 NSSUTF8 *mark, *last;
388 last = mark = slotFlags;
389 while (PR_TRUE) {
390 while (*mark && *mark != ',') ++mark;
391 if (!*mark) done = PR_TRUE;
392 *mark = '\0';
393 if (nssUTF8_Equal(last, "RANDOM", &nssrv)) {
394 slot->base.flags |= NSSSLOT_FLAGS_HAS_RANDOM;
395 } else if (nssUTF8_Equal(last, "RSA", &nssrv)) {
396 slot->base.flags |= NSSSLOT_FLAGS_RSA;
397 } else if (nssUTF8_Equal(last, "DSA", &nssrv)) {
398 slot->base.flags |= NSSSLOT_FLAGS_DSA;
399 } else if (nssUTF8_Equal(last, "DH", &nssrv)) {
400 slot->base.flags |= NSSSLOT_FLAGS_DH;
401 } else if (nssUTF8_Equal(last, "RC2", &nssrv)) {
402 slot->base.flags |= NSSSLOT_FLAGS_RC2;
403 } else if (nssUTF8_Equal(last, "RC4", &nssrv)) {
404 slot->base.flags |= NSSSLOT_FLAGS_RC4;
405 } else if (nssUTF8_Equal(last, "RC5", &nssrv)) {
406 slot->base.flags |= NSSSLOT_FLAGS_RC5;
407 } else if (nssUTF8_Equal(last, "DES", &nssrv)) {
408 slot->base.flags |= NSSSLOT_FLAGS_DES;
409 } else if (nssUTF8_Equal(last, "AES", &nssrv)) {
410 slot->base.flags |= NSSSLOT_FLAGS_AES;
411 } else if (nssUTF8_Equal(last, "SHA1", &nssrv)) {
412 slot->base.flags |= NSSSLOT_FLAGS_SHA1;
413 } else if (nssUTF8_Equal(last, "MD2", &nssrv)) {
414 slot->base.flags |= NSSSLOT_FLAGS_MD2;
415 } else if (nssUTF8_Equal(last, "MD5", &nssrv)) {
416 slot->base.flags |= NSSSLOT_FLAGS_MD5;
417 } else if (nssUTF8_Equal(last, "SSL", &nssrv)) {
418 slot->base.flags |= NSSSLOT_FLAGS_SSL;
419 } else if (nssUTF8_Equal(last, "TLS", &nssrv)) {
420 slot->base.flags |= NSSSLOT_FLAGS_TLS;
421 } else if (nssUTF8_Equal(last, "PublicCerts", &nssrv)) {
422 slot->base.flags |= NSSSLOT_FLAGS_FRIENDLY;
423 } else {
424 return PR_FAILURE;
426 if (done) break;
427 last = ++mark;
429 #endif
430 return nssrv;
433 static PRStatus
434 parse_slot_parameters (
435 NSSSlot *slot,
436 NSSUTF8 *slotParams,
437 NSSArena *tmparena
440 PRStatus nssrv = PR_SUCCESS;
441 NSSUTF8 *current, *remainder;
442 NSSUTF8 *attrib, *value;
443 current = slotParams;
444 while (nssrv == PR_SUCCESS) {
445 nssrv = nssCryptokiArgs_ParseNextPair(current,
446 &attrib, &value,
447 &remainder, tmparena);
448 if (nssrv != PR_SUCCESS) break;
449 if (value) {
450 if (nssUTF8_Equal(attrib, "slotFlags", &nssrv)) {
451 nssrv = parse_slot_flags(slot, value);
452 } else if (nssUTF8_Equal(attrib, "askpw", &nssrv)) {
453 } else if (nssUTF8_Equal(attrib, "timeout", &nssrv)) {
456 if (*remainder == '\0') break;
457 current = remainder;
459 return nssrv;
462 /* softoken seems to use "0x0000001", but no standard yet... perhaps this
463 * should store the number as an ID, in case the input isn't 1,2,3,...?
465 static PRIntn
466 get_slot_number(NSSUTF8* snString)
468 /* XXX super big hack */
469 return atoi(&snString[strlen(snString)-1]);
472 static PRStatus
473 parse_module_slot_parameters (
474 NSSModule *mod,
475 NSSUTF8 *slotParams
478 PRStatus nssrv = PR_SUCCESS;
479 NSSUTF8 *current, *remainder;
480 NSSUTF8 *attrib, *value;
481 NSSArena *tmparena;
482 PRIntn slotNum;
483 tmparena = nssArena_Create();
484 if (!tmparena) {
485 return PR_FAILURE;
487 current = slotParams;
488 while (nssrv == PR_SUCCESS) {
489 nssrv = nssCryptokiArgs_ParseNextPair(current,
490 &attrib, &value,
491 &remainder, tmparena);
492 if (nssrv != PR_SUCCESS) break;
493 if (value) {
494 slotNum = get_slot_number(attrib);
495 if (slotNum < 0 || slotNum > mod->numSlots) {
496 return PR_FAILURE;
498 nssrv = parse_slot_parameters(mod->slots[slotNum],
499 value, tmparena);
500 if (nssrv != PR_SUCCESS) break;
502 if (*remainder == '\0') break;
503 current = remainder;
505 return nssrv;
508 static PRStatus
509 parse_nss_flags (
510 NSSModule *mod,
511 NSSUTF8 *nssFlags
514 PRStatus nssrv = PR_SUCCESS;
515 PRBool done = PR_FALSE;
516 NSSUTF8 *mark, *last;
517 last = mark = nssFlags;
518 while (PR_TRUE) {
519 while (*mark && *mark != ',') ++mark;
520 if (!*mark) done = PR_TRUE;
521 *mark = '\0';
522 if (nssUTF8_Equal(last, "internal", &nssrv)) {
523 mod->base.flags |= NSSMODULE_FLAGS_INTERNAL;
524 } else if (nssUTF8_Equal(last, "moduleDB", &nssrv)) {
525 mod->base.flags |= NSSMODULE_FLAGS_MODULE_DB;
526 } else if (nssUTF8_Equal(last, "moduleDBOnly", &nssrv)) {
527 mod->base.flags |= NSSMODULE_FLAGS_MODULE_DB_ONLY;
528 } else if (nssUTF8_Equal(last, "critical", &nssrv)) {
529 mod->base.flags |= NSSMODULE_FLAGS_CRITICAL;
530 } else {
531 return PR_FAILURE;
533 if (done) break;
534 last = ++mark;
536 return nssrv;
539 static PRStatus
540 parse_nss_parameters (
541 NSSModule *mod,
542 NSSUTF8 *nssParams,
543 NSSArena *tmparena,
544 NSSUTF8 **slotParams
547 PRStatus nssrv = PR_SUCCESS;
548 NSSUTF8 *current, *remainder;
549 NSSUTF8 *attrib, *value;
550 current = nssParams;
551 while (nssrv == PR_SUCCESS) {
552 nssrv = nssCryptokiArgs_ParseNextPair(current,
553 &attrib, &value,
554 &remainder, tmparena);
555 if (nssrv != PR_SUCCESS) break;
556 if (value) {
557 if (nssUTF8_Equal(attrib, "flags", &nssrv) ||
558 nssUTF8_Equal(attrib, "Flags", &nssrv)) {
559 nssrv = parse_nss_flags(mod, value);
560 } else if (nssUTF8_Equal(attrib, "trustOrder", &nssrv)) {
561 mod->order.trust = atoi(value);
562 } else if (nssUTF8_Equal(attrib, "cipherOrder", &nssrv)) {
563 mod->order.cipher = atoi(value);
564 } else if (nssUTF8_Equal(attrib, "ciphers", &nssrv)) {
565 } else if (nssUTF8_Equal(attrib, "slotParams", &nssrv)) {
566 /* slotParams doesn't get an arena, it is handled separately */
567 *slotParams = nssUTF8_Duplicate(value, NULL);
570 if (*remainder == '\0') break;
571 current = remainder;
573 return nssrv;
576 static PRStatus
577 parse_module_parameters (
578 NSSModule *mod,
579 NSSUTF8 *moduleParams,
580 NSSUTF8 **slotParams
583 PRStatus nssrv = PR_SUCCESS;
584 NSSUTF8 *current, *remainder;
585 NSSUTF8 *attrib, *value;
586 NSSArena *arena = mod->base.arena;
587 NSSArena *tmparena;
588 current = moduleParams;
589 tmparena = nssArena_Create();
590 if (!tmparena) {
591 return PR_FAILURE;
593 while (nssrv == PR_SUCCESS) {
594 nssrv = nssCryptokiArgs_ParseNextPair(current,
595 &attrib, &value,
596 &remainder, tmparena);
597 if (nssrv != PR_SUCCESS) break;
598 if (value) {
599 if (nssUTF8_Equal(attrib, "name", &nssrv)) {
600 mod->base.name = nssUTF8_Duplicate(value, arena);
601 } else if (nssUTF8_Equal(attrib, "library", &nssrv)) {
602 mod->libraryName = nssUTF8_Duplicate(value, arena);
603 } else if (nssUTF8_Equal(attrib, "parameters", &nssrv)) {
604 mod->libraryParams = nssUTF8_Duplicate(value, arena);
605 } else if (nssUTF8_Equal(attrib, "NSS", &nssrv)) {
606 parse_nss_parameters(mod, value, tmparena, slotParams);
609 if (*remainder == '\0') break;
610 current = remainder;
612 nssArena_Destroy(tmparena);
613 return nssrv;
616 static NSSUTF8 **
617 get_module_specs (
618 NSSModule *mod
621 SECMODModuleDBFunc func = (SECMODModuleDBFunc)mod->moduleDBFunc;
622 if (func) {
623 return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND,
624 mod->libraryParams,
625 NULL);
627 return NULL;
630 /* XXX continue working on */
631 NSS_IMPLEMENT NSSModule *
632 nssModule_CreateFromSpec (
633 NSSUTF8 *moduleSpec,
634 NSSModule *parent,
635 PRBool loadSubModules
638 PRStatus nssrv;
639 NSSModule *thisModule;
640 NSSArena *arena;
641 NSSUTF8 *slotParams = NULL;
642 arena = nssArena_Create();
643 if (!arena) {
644 return NULL;
646 thisModule = nss_ZNEW(arena, NSSModule);
647 if (!thisModule) {
648 goto loser;
650 thisModule->base.lock = PZ_NewLock(nssILockOther);
651 if (!thisModule->base.lock) {
652 goto loser;
654 PR_AtomicIncrement(&thisModule->base.refCount);
655 thisModule->base.arena = arena;
656 thisModule->base.lock = PZ_NewLock(nssNSSILockOther);
657 if (!thisModule->base.lock) {
658 goto loser;
660 nssrv = parse_module_parameters(thisModule, moduleSpec, &slotParams);
661 if (nssrv != PR_SUCCESS) {
662 goto loser;
664 nssrv = nssModule_Load(thisModule);
665 if (nssrv != PR_SUCCESS) {
666 goto loser;
668 if (slotParams) {
669 nssrv = parse_module_slot_parameters(thisModule, slotParams);
670 nss_ZFreeIf(slotParams);
671 if (nssrv != PR_SUCCESS) {
672 goto loser;
675 if (loadSubModules && NSSMODULE_IS_MODULE_DB(thisModule)) {
676 NSSUTF8 **moduleSpecs;
677 NSSUTF8 **index;
678 /* get the array of sub modules one level below this module */
679 moduleSpecs = get_module_specs(thisModule);
680 /* iterate over the array */
681 for (index = moduleSpecs; index && *index; index++) {
682 NSSModule *child;
683 /* load the child recursively */
684 child = nssModule_CreateFromSpec(*index, thisModule, PR_TRUE);
685 if (!child) {
686 /* when children fail, does the parent? */
687 nssrv = PR_FAILURE;
688 break;
690 if (NSSMODULE_IS_CRITICAL(child) && !child->isLoaded) {
691 nssrv = PR_FAILURE;
692 nssModule_Destroy(child);
693 break;
695 nssModule_Destroy(child);
696 /*nss_ZFreeIf(*index);*/
698 /*nss_ZFreeIf(moduleSpecs);*/
700 /* The global list inherits the reference */
701 nssrv = nssGlobalModuleList_Add(thisModule);
702 if (nssrv != PR_SUCCESS) {
703 goto loser;
705 return thisModule;
706 loser:
707 if (thisModule->base.lock) {
708 PZ_DestroyLock(thisModule->base.lock);
710 nssArena_Destroy(arena);
711 return (NSSModule *)NULL;
714 NSS_IMPLEMENT PRStatus
715 nssModule_Destroy (
716 NSSModule *mod
719 PRUint32 i, numSlots;
720 if (PR_AtomicDecrement(&mod->base.refCount) == 0) {
721 if (mod->numSlots == 0) {
722 (void)nssModule_Unload(mod);
723 return nssArena_Destroy(mod->base.arena);
724 } else {
725 numSlots = mod->numSlots;
726 for (i=0; i<numSlots; i++) {
727 nssSlot_Destroy(mod->slots[i]);
731 return PR_SUCCESS;
734 NSS_IMPLEMENT PRStatus
735 nssModule_DestroyFromSlot (
736 NSSModule *mod,
737 NSSSlot *slot
740 PRUint32 i, numSlots = 0;
741 PR_ASSERT(mod->base.refCount == 0);
742 for (i=0; i<mod->numSlots; i++) {
743 if (mod->slots[i] == slot) {
744 mod->slots[i] = NULL;
745 } else if (mod->slots[i]) {
746 numSlots++;
749 if (numSlots == 0) {
750 (void)nssModule_Unload(mod);
751 return nssArena_Destroy(mod->base.arena);
753 return PR_SUCCESS;
756 NSS_IMPLEMENT NSSModule *
757 nssModule_AddRef (
758 NSSModule *mod
761 PR_AtomicIncrement(&mod->base.refCount);
762 return mod;
765 NSS_IMPLEMENT NSSUTF8 *
766 nssModule_GetName (
767 NSSModule *mod
770 return mod->base.name;
773 NSS_IMPLEMENT PRBool
774 nssModule_IsThreadSafe (
775 NSSModule *module
778 return NSSMODULE_IS_THREADSAFE(module);
781 NSS_IMPLEMENT PRBool
782 nssModule_IsInternal (
783 NSSModule *mod
786 return NSSMODULE_IS_INTERNAL(mod);
789 NSS_IMPLEMENT PRBool
790 nssModule_IsModuleDBOnly (
791 NSSModule *mod
794 return NSSMODULE_IS_MODULE_DB_ONLY(mod);
797 NSS_IMPLEMENT void *
798 nssModule_GetCryptokiEPV (
799 NSSModule *mod
802 return mod->epv;
805 NSS_IMPLEMENT NSSSlot **
806 nssModule_GetSlots (
807 NSSModule *mod
810 PRUint32 i;
811 NSSSlot **rvSlots;
812 rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, mod->numSlots + 1);
813 if (rvSlots) {
814 for (i=0; i<mod->numSlots; i++) {
815 rvSlots[i] = nssSlot_AddRef(mod->slots[i]);
818 return rvSlots;
821 NSS_IMPLEMENT NSSSlot *
822 nssModule_FindSlotByName (
823 NSSModule *mod,
824 NSSUTF8 *slotName
827 PRUint32 i;
828 PRStatus nssrv;
829 NSSSlot *slot;
830 NSSUTF8 *name;
831 for (i=0; i<mod->numSlots; i++) {
832 slot = mod->slots[i];
833 name = nssSlot_GetName(slot);
834 if (nssUTF8_Equal(name, slotName, &nssrv)) {
835 return nssSlot_AddRef(slot);
837 if (nssrv != PR_SUCCESS) {
838 break;
841 return (NSSSlot *)NULL;
844 NSS_IMPLEMENT NSSToken *
845 nssModule_FindTokenByName (
846 NSSModule *mod,
847 NSSUTF8 *tokenName
850 PRUint32 i;
851 PRStatus nssrv;
852 NSSToken *tok;
853 NSSUTF8 *name;
854 for (i=0; i<mod->numSlots; i++) {
855 tok = nssSlot_GetToken(mod->slots[i]);
856 if (tok) {
857 name = nssToken_GetName(tok);
858 if (nssUTF8_Equal(name, tokenName, &nssrv)) {
859 return tok;
861 if (nssrv != PR_SUCCESS) {
862 break;
866 return (NSSToken *)NULL;
869 NSS_IMPLEMENT PRInt32
870 nssModule_GetCertOrder (
871 NSSModule *module
874 return 1; /* XXX */
877 #endif /* PURE_STAN_BUILD */