summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/freebl/stubs.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/freebl/stubs.c')
-rw-r--r--security/nss/lib/freebl/stubs.c711
1 files changed, 711 insertions, 0 deletions
diff --git a/security/nss/lib/freebl/stubs.c b/security/nss/lib/freebl/stubs.c
new file mode 100644
index 000000000..8e0784935
--- /dev/null
+++ b/security/nss/lib/freebl/stubs.c
@@ -0,0 +1,711 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Allow freebl and softoken to be loaded without util or NSPR.
+ *
+ * These symbols are overridden once real NSPR, and libutil are attached.
+ */
+#define _GNU_SOURCE 1
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <dlfcn.h>
+#include <prio.h>
+#include <prlink.h>
+#include <prlog.h>
+#include <prthread.h>
+#include <plstr.h>
+#include <prinit.h>
+#include <prlock.h>
+#include <prmem.h>
+#include <prerror.h>
+#include <prmon.h>
+#include <pratom.h>
+#include <prsystem.h>
+#include <prinrval.h>
+#include <prtime.h>
+#include <prcvar.h>
+#include <secasn1.h>
+#include <secdig.h>
+#include <secport.h>
+#include <secitem.h>
+#include <blapi.h>
+#include <private/pprio.h>
+
+#define FREEBL_NO_WEAK 1
+
+#define WEAK __attribute__((weak))
+
+#ifdef FREEBL_NO_WEAK
+
+/*
+ * This uses function pointers.
+ *
+ * CONS: A separate function is needed to
+ * fill in the function pointers.
+ *
+ * PROS: it works on all platforms.
+ * it allows for dynamically finding nspr and libutil, even once
+ * softoken is loaded and running. (NOTE: this may be a problem if
+ * we switch between the stubs and real NSPR on the fly. NSPR will
+ * do bad things if passed an _FakeArena to free or allocate from).
+ */
+#define STUB_DECLARE(ret, fn, args) \
+ typedef ret(*type_##fn) args; \
+ static type_##fn ptr_##fn = NULL
+
+#define STUB_SAFE_CALL0(fn) \
+ if (ptr_##fn) { \
+ return ptr_##fn(); \
+ }
+#define STUB_SAFE_CALL1(fn, a1) \
+ if (ptr_##fn) { \
+ return ptr_##fn(a1); \
+ }
+#define STUB_SAFE_CALL2(fn, a1, a2) \
+ if (ptr_##fn) { \
+ return ptr_##fn(a1, a2); \
+ }
+#define STUB_SAFE_CALL3(fn, a1, a2, a3) \
+ if (ptr_##fn) { \
+ return ptr_##fn(a1, a2, a3); \
+ }
+#define STUB_SAFE_CALL4(fn, a1, a2, a3, a4) \
+ if (ptr_##fn) { \
+ return ptr_##fn(a1, a2, a3, a4); \
+ }
+#define STUB_SAFE_CALL6(fn, a1, a2, a3, a4, a5, a6) \
+ if (ptr_##fn) { \
+ return ptr_##fn(a1, a2, a3, a4, a5, a6); \
+ }
+
+#define STUB_FETCH_FUNCTION(fn) \
+ ptr_##fn = (type_##fn)dlsym(lib, #fn); \
+ if (ptr_##fn == NULL) { \
+ return SECFailure; \
+ }
+
+#else
+/*
+ * this uses the loader weak attribute. it works automatically, but once
+ * freebl is loaded, the symbols are 'fixed' (later loading of NSPR or
+ * libutil will not resolve these symbols).
+ */
+
+#define STUB_DECLARE(ret, fn, args) \
+ WEAK extern ret fn args
+
+#define STUB_SAFE_CALL0(fn) \
+ if (fn) { \
+ return fn(); \
+ }
+#define STUB_SAFE_CALL1(fn, a1) \
+ if (fn) { \
+ return fn(a1); \
+ }
+#define STUB_SAFE_CALL2(fn, a1, a2) \
+ if (fn) { \
+ return fn(a1, a2); \
+ }
+#define STUB_SAFE_CALL3(fn, a1, a2, a3) \
+ if (fn) { \
+ return fn(a1, a2, a3); \
+ }
+#define STUB_SAFE_CALL4(fn, a1, a2, a3, a4) \
+ if (fn) { \
+ return fn(a1, a2, a3, a4); \
+ }
+#define STUB_SAFE_CALL6(fn, a1, a2, a3, a4, a5, a6) \
+ if (fn) { \
+ return fn(a1, a2, a3, a4, a5, a6); \
+ }
+#endif
+
+STUB_DECLARE(void *, PORT_Alloc_Util, (size_t len));
+STUB_DECLARE(void *, PORT_ArenaAlloc_Util, (PLArenaPool * arena, size_t size));
+STUB_DECLARE(void *, PORT_ArenaZAlloc_Util, (PLArenaPool * arena, size_t size));
+STUB_DECLARE(void, PORT_Free_Util, (void *ptr));
+STUB_DECLARE(void, PORT_FreeArena_Util, (PLArenaPool * arena, PRBool zero));
+STUB_DECLARE(int, PORT_GetError_Util, (void));
+STUB_DECLARE(PLArenaPool *, PORT_NewArena_Util, (unsigned long chunksize));
+STUB_DECLARE(void, PORT_SetError_Util, (int value));
+STUB_DECLARE(void *, PORT_ZAlloc_Util, (size_t len));
+STUB_DECLARE(void, PORT_ZFree_Util, (void *ptr, size_t len));
+
+STUB_DECLARE(void, PR_Assert, (const char *s, const char *file, PRIntn ln));
+STUB_DECLARE(PRStatus, PR_Access, (const char *name, PRAccessHow how));
+STUB_DECLARE(PRStatus, PR_CallOnce, (PRCallOnceType * once, PRCallOnceFN func));
+STUB_DECLARE(PRStatus, PR_Close, (PRFileDesc * fd));
+STUB_DECLARE(void, PR_DestroyLock, (PRLock * lock));
+STUB_DECLARE(void, PR_DestroyCondVar, (PRCondVar * cvar));
+STUB_DECLARE(void, PR_Free, (void *ptr));
+STUB_DECLARE(char *, PR_GetLibraryFilePathname, (const char *name,
+ PRFuncPtr addr));
+STUB_DECLARE(PRFileDesc *, PR_ImportPipe, (PROsfd osfd));
+STUB_DECLARE(void, PR_Lock, (PRLock * lock));
+STUB_DECLARE(PRCondVar *, PR_NewCondVar, (PRLock * lock));
+STUB_DECLARE(PRLock *, PR_NewLock, (void));
+STUB_DECLARE(PRStatus, PR_NotifyCondVar, (PRCondVar * cvar));
+STUB_DECLARE(PRStatus, PR_NotifyAllCondVar, (PRCondVar * cvar));
+STUB_DECLARE(PRFileDesc *, PR_Open, (const char *name, PRIntn flags,
+ PRIntn mode));
+STUB_DECLARE(PRInt32, PR_Read, (PRFileDesc * fd, void *buf, PRInt32 amount));
+STUB_DECLARE(PROffset32, PR_Seek, (PRFileDesc * fd, PROffset32 offset,
+ PRSeekWhence whence));
+STUB_DECLARE(PRStatus, PR_Sleep, (PRIntervalTime ticks));
+STUB_DECLARE(PRStatus, PR_Unlock, (PRLock * lock));
+STUB_DECLARE(PRStatus, PR_WaitCondVar, (PRCondVar * cvar,
+ PRIntervalTime timeout));
+STUB_DECLARE(char *, PR_GetEnvSecure, (const char *));
+
+STUB_DECLARE(SECItem *, SECITEM_AllocItem_Util, (PLArenaPool * arena,
+ SECItem *item, unsigned int len));
+STUB_DECLARE(SECComparison, SECITEM_CompareItem_Util, (const SECItem *a,
+ const SECItem *b));
+STUB_DECLARE(SECStatus, SECITEM_CopyItem_Util, (PLArenaPool * arena,
+ SECItem *to, const SECItem *from));
+STUB_DECLARE(void, SECITEM_FreeItem_Util, (SECItem * zap, PRBool freeit));
+STUB_DECLARE(void, SECITEM_ZfreeItem_Util, (SECItem * zap, PRBool freeit));
+STUB_DECLARE(SECOidTag, SECOID_FindOIDTag_Util, (const SECItem *oid));
+STUB_DECLARE(int, NSS_SecureMemcmp, (const void *a, const void *b, size_t n));
+
+#define PORT_ZNew_stub(type) (type *)PORT_ZAlloc_stub(sizeof(type))
+#define PORT_New_stub(type) (type *)PORT_Alloc_stub(sizeof(type))
+#define PORT_ZNewArray_stub(type, num) \
+ (type *)PORT_ZAlloc_stub(sizeof(type) * (num))
+
+/*
+ * NOTE: in order to support hashing only the memory allocation stubs,
+ * the get library name stubs, and the file io stubs are needed (the latter
+ * two are for the library verification). The remaining stubs are simply to
+ * compile. Attempts to use the library for other operations without NSPR
+ * will most likely fail.
+ */
+
+/* memory */
+extern void *
+PORT_Alloc_stub(size_t len)
+{
+ STUB_SAFE_CALL1(PORT_Alloc_Util, len);
+ return malloc(len);
+}
+
+extern void
+PORT_Free_stub(void *ptr)
+{
+ STUB_SAFE_CALL1(PORT_Free_Util, ptr);
+ return free(ptr);
+}
+
+extern void *
+PORT_ZAlloc_stub(size_t len)
+{
+ STUB_SAFE_CALL1(PORT_ZAlloc_Util, len);
+ void *ptr = malloc(len);
+ if (ptr) {
+ memset(ptr, 0, len);
+ }
+ return ptr;
+}
+
+extern void
+PORT_ZFree_stub(void *ptr, size_t len)
+{
+ STUB_SAFE_CALL2(PORT_ZFree_Util, ptr, len);
+ memset(ptr, 0, len);
+ return free(ptr);
+}
+
+extern void
+PR_Free_stub(void *ptr)
+{
+ STUB_SAFE_CALL1(PR_Free, ptr);
+ return free(ptr);
+}
+
+/*
+ * arenas
+ *
+ */
+extern PLArenaPool *
+PORT_NewArena_stub(unsigned long chunksize)
+{
+ STUB_SAFE_CALL1(PORT_NewArena_Util, chunksize);
+ abort();
+ return NULL;
+}
+
+extern void *
+PORT_ArenaAlloc_stub(PLArenaPool *arena, size_t size)
+{
+
+ STUB_SAFE_CALL2(PORT_ArenaZAlloc_Util, arena, size);
+ abort();
+ return NULL;
+}
+
+extern void *
+PORT_ArenaZAlloc_stub(PLArenaPool *arena, size_t size)
+{
+
+ STUB_SAFE_CALL2(PORT_ArenaZAlloc_Util, arena, size);
+ abort();
+ return NULL;
+}
+
+extern void
+PORT_FreeArena_stub(PLArenaPool *arena, PRBool zero)
+{
+
+ STUB_SAFE_CALL2(PORT_FreeArena_Util, arena, zero);
+ abort();
+}
+
+/* io */
+extern PRFileDesc *
+PR_Open_stub(const char *name, PRIntn flags, PRIntn mode)
+{
+ int *lfd = NULL;
+ int fd;
+ int lflags = 0;
+
+ STUB_SAFE_CALL3(PR_Open, name, flags, mode);
+
+ if (flags & PR_RDWR) {
+ lflags = O_RDWR;
+ } else if (flags & PR_WRONLY) {
+ lflags = O_WRONLY;
+ } else {
+ lflags = O_RDONLY;
+ }
+
+ if (flags & PR_EXCL)
+ lflags |= O_EXCL;
+ if (flags & PR_APPEND)
+ lflags |= O_APPEND;
+ if (flags & PR_TRUNCATE)
+ lflags |= O_TRUNC;
+
+ fd = open(name, lflags, mode);
+ if (fd >= 0) {
+ lfd = PORT_New_stub(int);
+ if (lfd != NULL) {
+ *lfd = fd;
+ } else {
+ close(fd);
+ }
+ }
+ return (PRFileDesc *)lfd;
+}
+
+extern PRFileDesc *
+PR_ImportPipe_stub(PROsfd fd)
+{
+ int *lfd = NULL;
+
+ STUB_SAFE_CALL1(PR_ImportPipe, fd);
+
+ lfd = PORT_New_stub(int);
+ if (lfd != NULL) {
+ *lfd = fd;
+ }
+ return (PRFileDesc *)lfd;
+}
+
+extern PRStatus
+PR_Close_stub(PRFileDesc *fd)
+{
+ int *lfd;
+ STUB_SAFE_CALL1(PR_Close, fd);
+
+ lfd = (int *)fd;
+ close(*lfd);
+ PORT_Free_stub(lfd);
+
+ return PR_SUCCESS;
+}
+
+extern PRInt32
+PR_Read_stub(PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+ int *lfd;
+ STUB_SAFE_CALL3(PR_Read, fd, buf, amount);
+
+ lfd = (int *)fd;
+ return read(*lfd, buf, amount);
+}
+
+extern PROffset32
+PR_Seek_stub(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
+{
+ int *lfd;
+ int lwhence = SEEK_SET;
+ STUB_SAFE_CALL3(PR_Seek, fd, offset, whence);
+ lfd = (int *)fd;
+ switch (whence) {
+ case PR_SEEK_CUR:
+ lwhence = SEEK_CUR;
+ break;
+ case PR_SEEK_END:
+ lwhence = SEEK_END;
+ break;
+ case PR_SEEK_SET:
+ break;
+ }
+
+ return lseek(*lfd, offset, lwhence);
+}
+
+PRStatus
+PR_Access_stub(const char *name, PRAccessHow how)
+{
+ int mode = F_OK;
+ int rv;
+ STUB_SAFE_CALL2(PR_Access, name, how);
+ switch (how) {
+ case PR_ACCESS_WRITE_OK:
+ mode = W_OK;
+ break;
+ case PR_ACCESS_READ_OK:
+ mode = R_OK;
+ break;
+ /* assume F_OK for all others */
+ default:
+ break;
+ }
+ rv = access(name, mode);
+ if (rv == 0) {
+ return PR_SUCCESS;
+ }
+ return PR_FAILURE;
+}
+
+/*
+ * library
+ */
+extern char *
+PR_GetLibraryFilePathname_stub(const char *name, PRFuncPtr addr)
+{
+ Dl_info dli;
+ char *result;
+
+ STUB_SAFE_CALL2(PR_GetLibraryFilePathname, name, addr);
+
+ if (dladdr((void *)addr, &dli) == 0) {
+ return NULL;
+ }
+ result = PORT_Alloc_stub(strlen(dli.dli_fname) + 1);
+ if (result != NULL) {
+ strcpy(result, dli.dli_fname);
+ }
+ return result;
+}
+
+#include <errno.h>
+
+/* errors */
+extern int
+PORT_GetError_stub(void)
+{
+ STUB_SAFE_CALL0(PORT_GetError_Util);
+ return errno;
+}
+
+extern void
+PORT_SetError_stub(int value)
+{
+ STUB_SAFE_CALL1(PORT_SetError_Util, value);
+ errno = value;
+}
+
+/* misc */
+extern void
+PR_Assert_stub(const char *s, const char *file, PRIntn ln)
+{
+ STUB_SAFE_CALL3(PR_Assert, s, file, ln);
+ fprintf(stderr, "%s line %d: %s\n", file, ln, s);
+ abort();
+}
+
+/* time */
+extern PRStatus
+PR_Sleep_stub(PRIntervalTime ticks)
+{
+ STUB_SAFE_CALL1(PR_Sleep, ticks);
+ usleep(ticks * 1000);
+ return PR_SUCCESS;
+}
+
+/* locking */
+extern PRLock *
+PR_NewLock_stub(void)
+{
+ STUB_SAFE_CALL0(PR_NewLock);
+ abort();
+ return NULL;
+}
+
+extern PRStatus
+PR_Unlock_stub(PRLock *lock)
+{
+ STUB_SAFE_CALL1(PR_Unlock, lock);
+ abort();
+ return PR_FAILURE;
+}
+
+extern void
+PR_Lock_stub(PRLock *lock)
+{
+ STUB_SAFE_CALL1(PR_Lock, lock);
+ abort();
+ return;
+}
+
+extern void
+PR_DestroyLock_stub(PRLock *lock)
+{
+ STUB_SAFE_CALL1(PR_DestroyLock, lock);
+ abort();
+ return;
+}
+
+extern PRCondVar *
+PR_NewCondVar_stub(PRLock *lock)
+{
+ STUB_SAFE_CALL1(PR_NewCondVar, lock);
+ abort();
+ return NULL;
+}
+
+extern PRStatus
+PR_NotifyCondVar_stub(PRCondVar *cvar)
+{
+ STUB_SAFE_CALL1(PR_NotifyCondVar, cvar);
+ abort();
+ return PR_FAILURE;
+}
+
+extern PRStatus
+PR_NotifyAllCondVar_stub(PRCondVar *cvar)
+{
+ STUB_SAFE_CALL1(PR_NotifyAllCondVar, cvar);
+ abort();
+ return PR_FAILURE;
+}
+
+extern PRStatus
+PR_WaitCondVar_stub(PRCondVar *cvar, PRIntervalTime timeout)
+{
+ STUB_SAFE_CALL2(PR_WaitCondVar, cvar, timeout);
+ abort();
+ return PR_FAILURE;
+}
+
+extern char *
+PR_GetEnvSecure_stub(const char *var)
+{
+ STUB_SAFE_CALL1(PR_GetEnvSecure, var);
+ abort();
+ return NULL;
+}
+
+extern void
+PR_DestroyCondVar_stub(PRCondVar *cvar)
+{
+ STUB_SAFE_CALL1(PR_DestroyCondVar, cvar);
+ abort();
+ return;
+}
+
+/*
+ * NOTE: this presupposes GCC 4.1
+ */
+extern PRStatus
+PR_CallOnce_stub(PRCallOnceType *once, PRCallOnceFN func)
+{
+ STUB_SAFE_CALL2(PR_CallOnce, once, func);
+ abort();
+ return PR_FAILURE;
+}
+
+/*
+ * SECITEMS implement Item Utilities
+ */
+extern void
+SECITEM_FreeItem_stub(SECItem *zap, PRBool freeit)
+{
+ STUB_SAFE_CALL2(SECITEM_FreeItem_Util, zap, freeit);
+ abort();
+}
+
+extern SECItem *
+SECITEM_AllocItem_stub(PLArenaPool *arena, SECItem *item, unsigned int len)
+{
+ STUB_SAFE_CALL3(SECITEM_AllocItem_Util, arena, item, len);
+ abort();
+ return NULL;
+}
+
+extern SECComparison
+SECITEM_CompareItem_stub(const SECItem *a, const SECItem *b)
+{
+ STUB_SAFE_CALL2(SECITEM_CompareItem_Util, a, b);
+ abort();
+ return SECEqual;
+}
+
+extern SECStatus
+SECITEM_CopyItem_stub(PLArenaPool *arena, SECItem *to, const SECItem *from)
+{
+ STUB_SAFE_CALL3(SECITEM_CopyItem_Util, arena, to, from);
+ abort();
+ return SECFailure;
+}
+
+extern SECOidTag
+SECOID_FindOIDTag_stub(const SECItem *oid)
+{
+ STUB_SAFE_CALL1(SECOID_FindOIDTag_Util, oid);
+ abort();
+ return SEC_OID_UNKNOWN;
+}
+
+extern void
+SECITEM_ZfreeItem_stub(SECItem *zap, PRBool freeit)
+{
+ STUB_SAFE_CALL2(SECITEM_ZfreeItem_Util, zap, freeit);
+ abort();
+}
+
+extern int
+NSS_SecureMemcmp_stub(const void *a, const void *b, size_t n)
+{
+ STUB_SAFE_CALL3(NSS_SecureMemcmp, a, b, n);
+ abort();
+}
+
+#ifdef FREEBL_NO_WEAK
+
+static const char *nsprLibName = SHLIB_PREFIX "nspr4." SHLIB_SUFFIX;
+static const char *nssutilLibName = SHLIB_PREFIX "nssutil3." SHLIB_SUFFIX;
+
+static SECStatus
+freebl_InitNSPR(void *lib)
+{
+ STUB_FETCH_FUNCTION(PR_Free);
+ STUB_FETCH_FUNCTION(PR_Open);
+ STUB_FETCH_FUNCTION(PR_ImportPipe);
+ STUB_FETCH_FUNCTION(PR_Close);
+ STUB_FETCH_FUNCTION(PR_Read);
+ STUB_FETCH_FUNCTION(PR_Seek);
+ STUB_FETCH_FUNCTION(PR_GetLibraryFilePathname);
+ STUB_FETCH_FUNCTION(PR_Assert);
+ STUB_FETCH_FUNCTION(PR_Access);
+ STUB_FETCH_FUNCTION(PR_Sleep);
+ STUB_FETCH_FUNCTION(PR_CallOnce);
+ STUB_FETCH_FUNCTION(PR_NewCondVar);
+ STUB_FETCH_FUNCTION(PR_NotifyCondVar);
+ STUB_FETCH_FUNCTION(PR_NotifyAllCondVar);
+ STUB_FETCH_FUNCTION(PR_WaitCondVar);
+ STUB_FETCH_FUNCTION(PR_DestroyCondVar);
+ STUB_FETCH_FUNCTION(PR_NewLock);
+ STUB_FETCH_FUNCTION(PR_Unlock);
+ STUB_FETCH_FUNCTION(PR_Lock);
+ STUB_FETCH_FUNCTION(PR_DestroyLock);
+ STUB_FETCH_FUNCTION(PR_GetEnvSecure);
+ return SECSuccess;
+}
+
+static SECStatus
+freebl_InitNSSUtil(void *lib)
+{
+ STUB_FETCH_FUNCTION(PORT_Alloc_Util);
+ STUB_FETCH_FUNCTION(PORT_Free_Util);
+ STUB_FETCH_FUNCTION(PORT_ZAlloc_Util);
+ STUB_FETCH_FUNCTION(PORT_ZFree_Util);
+ STUB_FETCH_FUNCTION(PORT_NewArena_Util);
+ STUB_FETCH_FUNCTION(PORT_ArenaAlloc_Util);
+ STUB_FETCH_FUNCTION(PORT_ArenaZAlloc_Util);
+ STUB_FETCH_FUNCTION(PORT_FreeArena_Util);
+ STUB_FETCH_FUNCTION(PORT_GetError_Util);
+ STUB_FETCH_FUNCTION(PORT_SetError_Util);
+ STUB_FETCH_FUNCTION(SECITEM_FreeItem_Util);
+ STUB_FETCH_FUNCTION(SECITEM_AllocItem_Util);
+ STUB_FETCH_FUNCTION(SECITEM_CompareItem_Util);
+ STUB_FETCH_FUNCTION(SECITEM_CopyItem_Util);
+ STUB_FETCH_FUNCTION(SECITEM_ZfreeItem_Util);
+ STUB_FETCH_FUNCTION(SECOID_FindOIDTag_Util);
+ STUB_FETCH_FUNCTION(NSS_SecureMemcmp);
+ return SECSuccess;
+}
+
+/*
+ * fetch the library if it's loaded. For NSS it should already be loaded
+ */
+#define freebl_getLibrary(libName) \
+ dlopen(libName, RTLD_LAZY | RTLD_NOLOAD)
+
+#define freebl_releaseLibrary(lib) \
+ if (lib) \
+ dlclose(lib)
+
+static void *FREEBLnsprGlobalLib = NULL;
+static void *FREEBLnssutilGlobalLib = NULL;
+
+void __attribute((destructor)) FREEBL_unload()
+{
+ freebl_releaseLibrary(FREEBLnsprGlobalLib);
+ freebl_releaseLibrary(FREEBLnssutilGlobalLib);
+}
+#endif
+
+/*
+ * load the symbols from the real libraries if available.
+ *
+ * if force is set, explicitly load the libraries if they are not already
+ * loaded. If we could not use the real libraries, return failure.
+ */
+extern SECStatus
+FREEBL_InitStubs()
+{
+ SECStatus rv = SECSuccess;
+#ifdef FREEBL_NO_WEAK
+ void *nspr = NULL;
+ void *nssutil = NULL;
+
+ /* NSPR should be first */
+ if (!FREEBLnsprGlobalLib) {
+ nspr = freebl_getLibrary(nsprLibName);
+ if (!nspr) {
+ return SECFailure;
+ }
+ rv = freebl_InitNSPR(nspr);
+ if (rv != SECSuccess) {
+ freebl_releaseLibrary(nspr);
+ return rv;
+ }
+ FREEBLnsprGlobalLib = nspr; /* adopt */
+ }
+ /* now load NSSUTIL */
+ if (!FREEBLnssutilGlobalLib) {
+ nssutil = freebl_getLibrary(nssutilLibName);
+ if (!nssutil) {
+ return SECFailure;
+ }
+ rv = freebl_InitNSSUtil(nssutil);
+ if (rv != SECSuccess) {
+ freebl_releaseLibrary(nssutil);
+ return rv;
+ }
+ FREEBLnssutilGlobalLib = nssutil; /* adopt */
+ }
+#endif
+
+ return rv;
+}