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
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.
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 ***** */
38 static const char CVS_ID
[] = "@(#) $RCSfile: devmod.c,v $ $Revision: 1.7 $ $Date: 2005/01/20 02:25:47 $";
43 #endif /* NSSCKEPV_H */
51 #endif /* CKHELPER_H */
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
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 */
70 struct nssDeviceBaseStr base
;
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. */
108 nss_ck_CreateMutex(CK_VOID_PTR_PTR pMutex
)
110 CK_VOID_PTR mutex
= (CK_VOID_PTR
)PZ_NewLock(nssILockOther
);
112 *pMutex
= (CK_VOID_PTR
)mutex
;
115 return CKR_HOST_MEMORY
;
119 nss_ck_DestroyMutex(CK_VOID_PTR mutex
)
121 PZ_DestroyLock((PZLock
*)mutex
);
126 nss_ck_LockMutex(CK_VOID_PTR mutex
)
128 PZ_Lock((PZLock
*)mutex
);
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 */
154 /* load all slots in a module. */
156 module_load_slots(NSSModule
*mod
)
158 CK_ULONG i
, ulNumSlots
;
160 nssArenaMark
*mark
= NULL
;
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? */
170 /* Alloc memory for the array of slot ID's */
171 slotIDs
= nss_ZNEWARRAY(NULL
, CK_SLOT_ID
, ulNumSlots
);
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? */
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 */
186 slots
= nss_ZNEWARRAY(mod
->base
.arena
, NSSSlot
*, ulNumSlots
);
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
) {
200 mod
->numSlots
= ulNumSlots
;
204 nssArena_Release(mod
->base
.arena
, mark
);
206 nss_ZFreeIf(slotIDs
);
210 NSS_IMPLEMENT PRStatus
215 PRLibrary
*library
= NULL
;
216 CK_C_GetFunctionList epv
;
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
;
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? */
233 /* Use NSPR to load the library */
234 library
= PR_LoadLibrary(mod
->libraryName
);
236 /* what's the error to set? */
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");
255 /* Load the cryptoki entry point vector (function list) */
256 ckrv
= (*epv
)((CK_FUNCTION_LIST_PTR
*)&mod
->epv
);
257 if (ckrv
!= CKR_OK
) {
260 /* Initialize the module */
261 if (mod
->libraryParams
) {
262 s_ck_initialize_args
.LibraryParameters
= (void *)mod
->libraryParams
;
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
) {
277 /* TODO: check the version # using C_GetInfo */
278 ckrv
= CKAPI(mod
->epv
)->C_GetInfo(&mod
->info
);
279 if (ckrv
!= CKR_OK
) {
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
) {
287 /* Module has successfully loaded */
288 mod
->isLoaded
= PR_TRUE
;
292 PR_UnloadLibrary(library
);
294 /* clear all values set above, they are invalid now */
300 NSS_IMPLEMENT PRStatus
305 PRStatus nssrv
= PR_SUCCESS
;
307 (void)CKAPI(mod
->epv
)->C_Finalize(NULL
);
308 nssrv
= PR_UnloadLibrary(mod
->library
);
310 /* Free the slots, yes? */
313 mod
->isLoaded
= PR_FALSE
;
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
*
330 arena
= NSSArena_Create();
332 return (NSSModule
*)NULL
;
334 rvMod
= nss_ZNEW(arena
, NSSModule
);
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
343 rvMod
->base
.name
= nssUTF8_Duplicate(moduleOpt
, arena
);
344 if (!rvMod
->base
.name
) {
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
) {
356 rvMod
->base
.arena
= arena
;
357 rvMod
->base
.refCount
= 1;
358 rvMod
->base
.lock
= PZ_NewLock(nssNSSILockOther
);
359 if (!rvMod
->base
.lock
) {
362 /* everything else is 0/NULL at this point. */
365 nssArena_Destroy(arena
);
366 return (NSSModule
*)NULL
;
370 nssCryptokiArgs_ParseNextPair (
384 PRStatus nssrv
= PR_SUCCESS
;
386 PRBool done
= PR_FALSE
;
387 NSSUTF8
*mark
, *last
;
388 last
= mark
= slotFlags
;
390 while (*mark
&& *mark
!= ',') ++mark
;
391 if (!*mark
) done
= PR_TRUE
;
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
;
434 parse_slot_parameters (
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
,
447 &remainder
, tmparena
);
448 if (nssrv
!= PR_SUCCESS
) break;
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;
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,...?
466 get_slot_number(NSSUTF8
* snString
)
468 /* XXX super big hack */
469 return atoi(&snString
[strlen(snString
)-1]);
473 parse_module_slot_parameters (
478 PRStatus nssrv
= PR_SUCCESS
;
479 NSSUTF8
*current
, *remainder
;
480 NSSUTF8
*attrib
, *value
;
483 tmparena
= nssArena_Create();
487 current
= slotParams
;
488 while (nssrv
== PR_SUCCESS
) {
489 nssrv
= nssCryptokiArgs_ParseNextPair(current
,
491 &remainder
, tmparena
);
492 if (nssrv
!= PR_SUCCESS
) break;
494 slotNum
= get_slot_number(attrib
);
495 if (slotNum
< 0 || slotNum
> mod
->numSlots
) {
498 nssrv
= parse_slot_parameters(mod
->slots
[slotNum
],
500 if (nssrv
!= PR_SUCCESS
) break;
502 if (*remainder
== '\0') break;
514 PRStatus nssrv
= PR_SUCCESS
;
515 PRBool done
= PR_FALSE
;
516 NSSUTF8
*mark
, *last
;
517 last
= mark
= nssFlags
;
519 while (*mark
&& *mark
!= ',') ++mark
;
520 if (!*mark
) done
= PR_TRUE
;
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
;
540 parse_nss_parameters (
547 PRStatus nssrv
= PR_SUCCESS
;
548 NSSUTF8
*current
, *remainder
;
549 NSSUTF8
*attrib
, *value
;
551 while (nssrv
== PR_SUCCESS
) {
552 nssrv
= nssCryptokiArgs_ParseNextPair(current
,
554 &remainder
, tmparena
);
555 if (nssrv
!= PR_SUCCESS
) break;
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;
577 parse_module_parameters (
579 NSSUTF8
*moduleParams
,
583 PRStatus nssrv
= PR_SUCCESS
;
584 NSSUTF8
*current
, *remainder
;
585 NSSUTF8
*attrib
, *value
;
586 NSSArena
*arena
= mod
->base
.arena
;
588 current
= moduleParams
;
589 tmparena
= nssArena_Create();
593 while (nssrv
== PR_SUCCESS
) {
594 nssrv
= nssCryptokiArgs_ParseNextPair(current
,
596 &remainder
, tmparena
);
597 if (nssrv
!= PR_SUCCESS
) break;
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;
612 nssArena_Destroy(tmparena
);
621 SECMODModuleDBFunc func
= (SECMODModuleDBFunc
)mod
->moduleDBFunc
;
623 return (*func
)(SECMOD_MODULE_DB_FUNCTION_FIND
,
630 /* XXX continue working on */
631 NSS_IMPLEMENT NSSModule
*
632 nssModule_CreateFromSpec (
635 PRBool loadSubModules
639 NSSModule
*thisModule
;
641 NSSUTF8
*slotParams
= NULL
;
642 arena
= nssArena_Create();
646 thisModule
= nss_ZNEW(arena
, NSSModule
);
650 thisModule
->base
.lock
= PZ_NewLock(nssILockOther
);
651 if (!thisModule
->base
.lock
) {
654 PR_AtomicIncrement(&thisModule
->base
.refCount
);
655 thisModule
->base
.arena
= arena
;
656 thisModule
->base
.lock
= PZ_NewLock(nssNSSILockOther
);
657 if (!thisModule
->base
.lock
) {
660 nssrv
= parse_module_parameters(thisModule
, moduleSpec
, &slotParams
);
661 if (nssrv
!= PR_SUCCESS
) {
664 nssrv
= nssModule_Load(thisModule
);
665 if (nssrv
!= PR_SUCCESS
) {
669 nssrv
= parse_module_slot_parameters(thisModule
, slotParams
);
670 nss_ZFreeIf(slotParams
);
671 if (nssrv
!= PR_SUCCESS
) {
675 if (loadSubModules
&& NSSMODULE_IS_MODULE_DB(thisModule
)) {
676 NSSUTF8
**moduleSpecs
;
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
++) {
683 /* load the child recursively */
684 child
= nssModule_CreateFromSpec(*index
, thisModule
, PR_TRUE
);
686 /* when children fail, does the parent? */
690 if (NSSMODULE_IS_CRITICAL(child
) && !child
->isLoaded
) {
692 nssModule_Destroy(child
);
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
) {
707 if (thisModule
->base
.lock
) {
708 PZ_DestroyLock(thisModule
->base
.lock
);
710 nssArena_Destroy(arena
);
711 return (NSSModule
*)NULL
;
714 NSS_IMPLEMENT PRStatus
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
);
725 numSlots
= mod
->numSlots
;
726 for (i
=0; i
<numSlots
; i
++) {
727 nssSlot_Destroy(mod
->slots
[i
]);
734 NSS_IMPLEMENT PRStatus
735 nssModule_DestroyFromSlot (
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
]) {
750 (void)nssModule_Unload(mod
);
751 return nssArena_Destroy(mod
->base
.arena
);
756 NSS_IMPLEMENT NSSModule
*
761 PR_AtomicIncrement(&mod
->base
.refCount
);
765 NSS_IMPLEMENT NSSUTF8
*
770 return mod
->base
.name
;
774 nssModule_IsThreadSafe (
778 return NSSMODULE_IS_THREADSAFE(module
);
782 nssModule_IsInternal (
786 return NSSMODULE_IS_INTERNAL(mod
);
790 nssModule_IsModuleDBOnly (
794 return NSSMODULE_IS_MODULE_DB_ONLY(mod
);
798 nssModule_GetCryptokiEPV (
805 NSS_IMPLEMENT NSSSlot
**
812 rvSlots
= nss_ZNEWARRAY(NULL
, NSSSlot
*, mod
->numSlots
+ 1);
814 for (i
=0; i
<mod
->numSlots
; i
++) {
815 rvSlots
[i
] = nssSlot_AddRef(mod
->slots
[i
]);
821 NSS_IMPLEMENT NSSSlot
*
822 nssModule_FindSlotByName (
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
) {
841 return (NSSSlot
*)NULL
;
844 NSS_IMPLEMENT NSSToken
*
845 nssModule_FindTokenByName (
854 for (i
=0; i
<mod
->numSlots
; i
++) {
855 tok
= nssSlot_GetToken(mod
->slots
[i
]);
857 name
= nssToken_GetName(tok
);
858 if (nssUTF8_Equal(name
, tokenName
, &nssrv
)) {
861 if (nssrv
!= PR_SUCCESS
) {
866 return (NSSToken
*)NULL
;
869 NSS_IMPLEMENT PRInt32
870 nssModule_GetCertOrder (
877 #endif /* PURE_STAN_BUILD */