tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

stubs.c (23025B)


      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 /*
      6 * Allow freebl and softoken to be loaded without util or NSPR.
      7 *
      8 * These symbols are overridden once real NSPR, and libutil are attached.
      9 */
     10 #define _GNU_SOURCE 1
     11 #include <stdlib.h>
     12 #include <stdio.h>
     13 #include <stdarg.h>
     14 #include <fcntl.h>
     15 #include <time.h>
     16 #include <unistd.h>
     17 #include <sys/time.h>
     18 #include <dlfcn.h>
     19 #include <prio.h>
     20 #include <prlink.h>
     21 #include <prlog.h>
     22 #include <prthread.h>
     23 #include <plstr.h>
     24 #include <prinit.h>
     25 #include <prlock.h>
     26 #include <prmem.h>
     27 #include <prerror.h>
     28 #include <prmon.h>
     29 #include <pratom.h>
     30 #include <prsystem.h>
     31 #include <prinrval.h>
     32 #include <prtime.h>
     33 #include <prcvar.h>
     34 #include <secasn1.h>
     35 #include <secdig.h>
     36 #include <secport.h>
     37 #include <secitem.h>
     38 #include <blapi.h>
     39 #include <assert.h>
     40 #include <private/pprio.h>
     41 
     42 /* Android API < 21 doesn't define RTLD_NOLOAD */
     43 #ifndef RTLD_NOLOAD
     44 #define RTLD_NOLOAD 0
     45 #endif
     46 
     47 #define FREEBL_NO_WEAK 1
     48 
     49 #define WEAK __attribute__((weak))
     50 
     51 #ifdef FREEBL_NO_WEAK
     52 
     53 /*
     54 * This uses function pointers.
     55 *
     56 * CONS:  A separate function is needed to
     57 * fill in the function pointers.
     58 *
     59 * PROS: it works on all platforms.
     60 *  it allows for dynamically finding nspr and libutil, even once
     61 *  softoken is loaded and running. (NOTE: this may be a problem if
     62 *  we switch between the stubs and real NSPR on the fly. NSPR will
     63 *  do bad things if passed an _FakeArena to free or allocate from).
     64 */
     65 #define STUB_DECLARE(ret, fn, args) \
     66    typedef ret(*type_##fn) args;   \
     67    static type_##fn ptr_##fn = NULL
     68 
     69 #define STUB_SAFE_CALL0(fn) \
     70    if (ptr_##fn) {         \
     71        return ptr_##fn();  \
     72    }
     73 #define STUB_SAFE_CALL1(fn, a1) \
     74    if (ptr_##fn) {             \
     75        return ptr_##fn(a1);    \
     76    }
     77 #define STUB_SAFE_CALL2(fn, a1, a2) \
     78    if (ptr_##fn) {                 \
     79        return ptr_##fn(a1, a2);    \
     80    }
     81 #define STUB_SAFE_CALL3(fn, a1, a2, a3) \
     82    if (ptr_##fn) {                     \
     83        return ptr_##fn(a1, a2, a3);    \
     84    }
     85 #define STUB_SAFE_CALL4(fn, a1, a2, a3, a4) \
     86    if (ptr_##fn) {                         \
     87        return ptr_##fn(a1, a2, a3, a4);    \
     88    }
     89 #define STUB_SAFE_CALL5(fn, a1, a2, a3, a4, a5) \
     90    if (ptr_##fn) {                             \
     91        return ptr_##fn(a1, a2, a3, a4, a5);    \
     92    }
     93 #define STUB_SAFE_CALL6(fn, a1, a2, a3, a4, a5, a6) \
     94    if (ptr_##fn) {                                 \
     95        return ptr_##fn(a1, a2, a3, a4, a5, a6);    \
     96    }
     97 
     98 #define STUB_FETCH_FUNCTION(fn)            \
     99    ptr_##fn = (type_##fn)dlsym(lib, #fn); \
    100    if (ptr_##fn == NULL) {                \
    101        return SECFailure;                 \
    102    }
    103 
    104 #else
    105 /*
    106 * this uses the loader weak attribute. it works automatically, but once
    107 * freebl is loaded, the symbols are 'fixed' (later loading of NSPR or
    108 * libutil will not resolve these symbols).
    109 */
    110 
    111 #define STUB_DECLARE(ret, fn, args) \
    112    WEAK extern ret fn args
    113 
    114 #define STUB_SAFE_CALL0(fn) \
    115    if (fn) {               \
    116        return fn();        \
    117    }
    118 #define STUB_SAFE_CALL1(fn, a1) \
    119    if (fn) {                   \
    120        return fn(a1);          \
    121    }
    122 #define STUB_SAFE_CALL2(fn, a1, a2) \
    123    if (fn) {                       \
    124        return fn(a1, a2);          \
    125    }
    126 #define STUB_SAFE_CALL3(fn, a1, a2, a3) \
    127    if (fn) {                           \
    128        return fn(a1, a2, a3);          \
    129    }
    130 #define STUB_SAFE_CALL4(fn, a1, a2, a3, a4) \
    131    if (fn) {                               \
    132        return fn(a1, a2, a3, a4);          \
    133    }
    134 #define STUB_SAFE_CALL6(fn, a1, a2, a3, a4, a5, a6) \
    135    if (fn) {                                       \
    136        return fn(a1, a2, a3, a4, a5, a6);          \
    137    }
    138 #endif
    139 
    140 STUB_DECLARE(void *, PORT_Alloc_Util, (size_t len));
    141 STUB_DECLARE(void *, PORT_ArenaAlloc_Util, (PLArenaPool * arena, size_t size));
    142 STUB_DECLARE(void *, PORT_ArenaZAlloc_Util, (PLArenaPool * arena, size_t size));
    143 STUB_DECLARE(void, PORT_Free_Util, (void *ptr));
    144 STUB_DECLARE(void, PORT_FreeArena_Util, (PLArenaPool * arena, PRBool zero));
    145 STUB_DECLARE(int, PORT_GetError_Util, (void));
    146 STUB_DECLARE(PLArenaPool *, PORT_NewArena_Util, (unsigned long chunksize));
    147 STUB_DECLARE(void, PORT_SafeZero, (void *p, size_t n));
    148 STUB_DECLARE(void, PORT_SetError_Util, (int value));
    149 STUB_DECLARE(void *, PORT_ZAlloc_Util, (size_t len));
    150 STUB_DECLARE(void *, PORT_ZAllocAligned_Util, (size_t bytes, size_t alignment, void **mem));
    151 STUB_DECLARE(void *, PORT_ZAllocAlignedOffset_Util, (size_t bytes, size_t alignment, size_t offset));
    152 STUB_DECLARE(void, PORT_ZFree_Util, (void *ptr, size_t len));
    153 
    154 STUB_DECLARE(void, PR_Assert, (const char *s, const char *file, PRIntn ln));
    155 STUB_DECLARE(PRStatus, PR_Access, (const char *name, PRAccessHow how));
    156 STUB_DECLARE(PRStatus, PR_CallOnce, (PRCallOnceType * once, PRCallOnceFN func));
    157 STUB_DECLARE(PRStatus, PR_Close, (PRFileDesc * fd));
    158 STUB_DECLARE(void, PR_DestroyLock, (PRLock * lock));
    159 STUB_DECLARE(void, PR_DestroyCondVar, (PRCondVar * cvar));
    160 STUB_DECLARE(void, PR_Free, (void *ptr));
    161 STUB_DECLARE(char *, PR_GetLibraryFilePathname, (const char *name, PRFuncPtr addr));
    162 STUB_DECLARE(PRFileDesc *, PR_ImportPipe, (PROsfd osfd));
    163 STUB_DECLARE(void, PR_Lock, (PRLock * lock));
    164 STUB_DECLARE(PRCondVar *, PR_NewCondVar, (PRLock * lock));
    165 STUB_DECLARE(PRLock *, PR_NewLock, (void));
    166 STUB_DECLARE(PRStatus, PR_NotifyCondVar, (PRCondVar * cvar));
    167 STUB_DECLARE(PRStatus, PR_NotifyAllCondVar, (PRCondVar * cvar));
    168 STUB_DECLARE(PRFileDesc *, PR_Open, (const char *name, PRIntn flags, PRIntn mode));
    169 STUB_DECLARE(PRInt32, PR_Read, (PRFileDesc * fd, void *buf, PRInt32 amount));
    170 STUB_DECLARE(PROffset32, PR_Seek, (PRFileDesc * fd, PROffset32 offset, PRSeekWhence whence));
    171 STUB_DECLARE(PRStatus, PR_Sleep, (PRIntervalTime ticks));
    172 STUB_DECLARE(PRStatus, PR_Unlock, (PRLock * lock));
    173 STUB_DECLARE(PRStatus, PR_WaitCondVar, (PRCondVar * cvar, PRIntervalTime timeout));
    174 STUB_DECLARE(char *, PR_GetEnvSecure, (const char *));
    175 
    176 STUB_DECLARE(SECItem *, SECITEM_AllocItem_Util, (PLArenaPool * arena, SECItem *item, unsigned int len));
    177 STUB_DECLARE(SECComparison, SECITEM_CompareItem_Util, (const SECItem *a, const SECItem *b));
    178 STUB_DECLARE(PRBool, SECITEM_ItemsAreEqual_Util, (const SECItem *a, const SECItem *b));
    179 STUB_DECLARE(SECStatus, SECITEM_CopyItem_Util, (PLArenaPool * arena, SECItem *to, const SECItem *from));
    180 STUB_DECLARE(void, SECITEM_FreeItem_Util, (SECItem * zap, PRBool freeit));
    181 STUB_DECLARE(void, SECITEM_ZfreeItem_Util, (SECItem * zap, PRBool freeit));
    182 STUB_DECLARE(SECOidTag, SECOID_FindOIDTag_Util, (const SECItem *oid));
    183 STUB_DECLARE(int, NSS_SecureMemcmp, (const void *a, const void *b, size_t n));
    184 STUB_DECLARE(unsigned int, NSS_SecureMemcmpZero, (const void *mem, size_t n));
    185 STUB_DECLARE(void, NSS_SecureSelect, (void *dest, const void *src0, const void *src1, size_t n, unsigned char b));
    186 #ifndef NSS_FIPS_DISABLED
    187 STUB_DECLARE(PRBool, NSS_GetSystemFIPSEnabled, (void));
    188 #endif
    189 
    190 #define PORT_ZNew_stub(type) (type *)PORT_ZAlloc_stub(sizeof(type))
    191 #define PORT_New_stub(type) (type *)PORT_Alloc_stub(sizeof(type))
    192 #define PORT_ZNewArray_stub(type, num) \
    193    (type *)PORT_ZAlloc_stub(sizeof(type) * (num))
    194 #define PORT_ZNewAligned_stub(type, alignment, mem) \
    195    (type *)PORT_ZAllocAlignedOffset_stub(sizeof(type), alignment, offsetof(type, mem))
    196 
    197 /*
    198 * NOTE: in order to support hashing only the memory allocation stubs,
    199 * the get library name stubs, and the file io stubs are needed (the latter
    200 * two are for the library verification). The remaining stubs are simply to
    201 * compile. Attempts to use the library for other operations without NSPR
    202 * will most likely fail.
    203 */
    204 
    205 /* memory */
    206 extern void *
    207 PORT_Alloc_stub(size_t len)
    208 {
    209    STUB_SAFE_CALL1(PORT_Alloc_Util, len);
    210    return malloc(len);
    211 }
    212 
    213 extern void
    214 PORT_Free_stub(void *ptr)
    215 {
    216    STUB_SAFE_CALL1(PORT_Free_Util, ptr);
    217    return free(ptr);
    218 }
    219 
    220 extern void *
    221 PORT_ZAlloc_stub(size_t len)
    222 {
    223    STUB_SAFE_CALL1(PORT_ZAlloc_Util, len);
    224    void *ptr = malloc(len);
    225    if (ptr) {
    226        memset(ptr, 0, len);
    227    }
    228    return ptr;
    229 }
    230 
    231 /* aligned_alloc is C11. This is an alternative to get aligned memory. */
    232 extern void *
    233 PORT_ZAllocAligned_stub(size_t bytes, size_t alignment, void **mem)
    234 {
    235    STUB_SAFE_CALL3(PORT_ZAllocAligned_Util, bytes, alignment, mem);
    236 
    237    /* This only works if alignement is a power of 2. */
    238    if ((alignment == 0) || (alignment & (alignment - 1))) {
    239        return NULL;
    240    }
    241 
    242    size_t x = alignment - 1;
    243    size_t len = (bytes ? bytes : 1) + x;
    244 
    245    if (!mem) {
    246        return NULL;
    247    }
    248 
    249    /* Always allocate a non-zero amount of bytes */
    250    *mem = malloc(len);
    251    if (!*mem) {
    252        return NULL;
    253    }
    254 
    255    memset(*mem, 0, len);
    256 
    257    /* We're pretty sure this is non-zero, but let's assure scan-build too. */
    258    void *ret = (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x);
    259    assert(ret);
    260 
    261    return ret;
    262 }
    263 
    264 extern void *
    265 PORT_ZAllocAlignedOffset_stub(size_t size, size_t alignment, size_t offset)
    266 {
    267    STUB_SAFE_CALL3(PORT_ZAllocAlignedOffset_Util, size, alignment, offset);
    268    if (offset > size) {
    269        return NULL;
    270    }
    271 
    272    void *mem = NULL;
    273    void *v = PORT_ZAllocAligned_stub(size, alignment, &mem);
    274    if (!v) {
    275        return NULL;
    276    }
    277 
    278    *((void **)((uintptr_t)v + offset)) = mem;
    279    return v;
    280 }
    281 
    282 extern void
    283 PORT_ZFree_stub(void *ptr, size_t len)
    284 {
    285    STUB_SAFE_CALL2(PORT_ZFree_Util, ptr, len);
    286    memset(ptr, 0, len);
    287    return free(ptr);
    288 }
    289 
    290 extern void
    291 PR_Free_stub(void *ptr)
    292 {
    293    STUB_SAFE_CALL1(PR_Free, ptr);
    294    return free(ptr);
    295 }
    296 
    297 /* we have defensive returns after abort(), which is marked noreturn on some
    298 * platforms, making the compiler legitimately complain. */
    299 #ifdef __clang__
    300 #pragma clang diagnostic push
    301 #pragma clang diagnostic ignored "-Wunreachable-code-return"
    302 #endif
    303 
    304 /*
    305 * arenas
    306 *
    307 */
    308 extern PLArenaPool *
    309 PORT_NewArena_stub(unsigned long chunksize)
    310 {
    311    STUB_SAFE_CALL1(PORT_NewArena_Util, chunksize);
    312    abort();
    313    return NULL;
    314 }
    315 
    316 extern void *
    317 PORT_ArenaAlloc_stub(PLArenaPool *arena, size_t size)
    318 {
    319 
    320    STUB_SAFE_CALL2(PORT_ArenaZAlloc_Util, arena, size);
    321    abort();
    322    return NULL;
    323 }
    324 
    325 extern void *
    326 PORT_ArenaZAlloc_stub(PLArenaPool *arena, size_t size)
    327 {
    328 
    329    STUB_SAFE_CALL2(PORT_ArenaZAlloc_Util, arena, size);
    330    abort();
    331    return NULL;
    332 }
    333 
    334 extern void
    335 PORT_FreeArena_stub(PLArenaPool *arena, PRBool zero)
    336 {
    337 
    338    STUB_SAFE_CALL2(PORT_FreeArena_Util, arena, zero);
    339    abort();
    340 }
    341 
    342 /* io */
    343 extern PRFileDesc *
    344 PR_Open_stub(const char *name, PRIntn flags, PRIntn mode)
    345 {
    346    int *lfd = NULL;
    347    int fd;
    348    int lflags = 0;
    349 
    350    STUB_SAFE_CALL3(PR_Open, name, flags, mode);
    351 
    352    if (flags & PR_RDWR) {
    353        lflags = O_RDWR;
    354    } else if (flags & PR_WRONLY) {
    355        lflags = O_WRONLY;
    356    } else {
    357        lflags = O_RDONLY;
    358    }
    359 
    360    if (flags & PR_EXCL)
    361        lflags |= O_EXCL;
    362    if (flags & PR_APPEND)
    363        lflags |= O_APPEND;
    364    if (flags & PR_TRUNCATE)
    365        lflags |= O_TRUNC;
    366 
    367    fd = open(name, lflags, mode);
    368    if (fd >= 0) {
    369        lfd = PORT_New_stub(int);
    370        if (lfd != NULL) {
    371            *lfd = fd;
    372        } else {
    373            close(fd);
    374        }
    375    }
    376    return (PRFileDesc *)lfd;
    377 }
    378 
    379 extern PRFileDesc *
    380 PR_ImportPipe_stub(PROsfd fd)
    381 {
    382    int *lfd = NULL;
    383 
    384    STUB_SAFE_CALL1(PR_ImportPipe, fd);
    385 
    386    lfd = PORT_New_stub(int);
    387    if (lfd != NULL) {
    388        *lfd = fd;
    389    }
    390    return (PRFileDesc *)lfd;
    391 }
    392 
    393 extern PRStatus
    394 PR_Close_stub(PRFileDesc *fd)
    395 {
    396    int *lfd;
    397    STUB_SAFE_CALL1(PR_Close, fd);
    398 
    399    lfd = (int *)fd;
    400    close(*lfd);
    401    PORT_Free_stub(lfd);
    402 
    403    return PR_SUCCESS;
    404 }
    405 
    406 extern PRInt32
    407 PR_Read_stub(PRFileDesc *fd, void *buf, PRInt32 amount)
    408 {
    409    int *lfd;
    410    STUB_SAFE_CALL3(PR_Read, fd, buf, amount);
    411 
    412    lfd = (int *)fd;
    413    return read(*lfd, buf, amount);
    414 }
    415 
    416 extern PROffset32
    417 PR_Seek_stub(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
    418 {
    419    int *lfd;
    420    int lwhence = SEEK_SET;
    421    STUB_SAFE_CALL3(PR_Seek, fd, offset, whence);
    422    lfd = (int *)fd;
    423    switch (whence) {
    424        case PR_SEEK_CUR:
    425            lwhence = SEEK_CUR;
    426            break;
    427        case PR_SEEK_END:
    428            lwhence = SEEK_END;
    429            break;
    430        case PR_SEEK_SET:
    431            break;
    432    }
    433 
    434    return lseek(*lfd, offset, lwhence);
    435 }
    436 
    437 PRStatus
    438 PR_Access_stub(const char *name, PRAccessHow how)
    439 {
    440    int mode = F_OK;
    441    int rv;
    442    STUB_SAFE_CALL2(PR_Access, name, how);
    443    switch (how) {
    444        case PR_ACCESS_WRITE_OK:
    445            mode = W_OK;
    446            break;
    447        case PR_ACCESS_READ_OK:
    448            mode = R_OK;
    449            break;
    450        /* assume F_OK for all others */
    451        default:
    452            break;
    453    }
    454    rv = access(name, mode);
    455    if (rv == 0) {
    456        return PR_SUCCESS;
    457    }
    458    return PR_FAILURE;
    459 }
    460 
    461 /*
    462 * library
    463 */
    464 extern char *
    465 PR_GetLibraryFilePathname_stub(const char *name, PRFuncPtr addr)
    466 {
    467    Dl_info dli;
    468    char *result;
    469 
    470    STUB_SAFE_CALL2(PR_GetLibraryFilePathname, name, addr);
    471 
    472    if (dladdr((void *)addr, &dli) == 0) {
    473        return NULL;
    474    }
    475    result = PORT_Alloc_stub(strlen(dli.dli_fname) + 1);
    476    if (result != NULL) {
    477        strcpy(result, dli.dli_fname);
    478    }
    479    return result;
    480 }
    481 
    482 #include <errno.h>
    483 
    484 /* errors */
    485 extern int
    486 PORT_GetError_stub(void)
    487 {
    488    STUB_SAFE_CALL0(PORT_GetError_Util);
    489    return errno;
    490 }
    491 
    492 extern void
    493 PORT_SafeZero_stub(void *p, size_t n)
    494 {
    495    STUB_SAFE_CALL2(PORT_SafeZero, p, n);
    496    /* just use a generic call in the case where we are running
    497     * standalone freebl */
    498    if (p != NULL) {
    499        volatile unsigned char *__vl = (unsigned char *)p;
    500        size_t __nl = n;
    501        while (__nl--)
    502            *__vl++ = 0;
    503    }
    504 }
    505 
    506 extern void
    507 PORT_SetError_stub(int value)
    508 {
    509    STUB_SAFE_CALL1(PORT_SetError_Util, value);
    510    errno = value;
    511 }
    512 
    513 /* misc */
    514 extern void
    515 PR_Assert_stub(const char *s, const char *file, PRIntn ln)
    516 {
    517    STUB_SAFE_CALL3(PR_Assert, s, file, ln);
    518    fprintf(stderr, "%s line %d: %s\n", file, ln, s);
    519    abort();
    520 }
    521 
    522 /* time */
    523 extern PRStatus
    524 PR_Sleep_stub(PRIntervalTime ticks)
    525 {
    526    STUB_SAFE_CALL1(PR_Sleep, ticks);
    527    usleep(ticks * 1000);
    528    return PR_SUCCESS;
    529 }
    530 
    531 /* locking */
    532 extern PRLock *
    533 PR_NewLock_stub(void)
    534 {
    535    STUB_SAFE_CALL0(PR_NewLock);
    536    abort();
    537    return NULL;
    538 }
    539 
    540 extern PRStatus
    541 PR_Unlock_stub(PRLock *lock)
    542 {
    543    STUB_SAFE_CALL1(PR_Unlock, lock);
    544    abort();
    545    return PR_FAILURE;
    546 }
    547 
    548 extern void
    549 PR_Lock_stub(PRLock *lock)
    550 {
    551    STUB_SAFE_CALL1(PR_Lock, lock);
    552    abort();
    553    return;
    554 }
    555 
    556 extern void
    557 PR_DestroyLock_stub(PRLock *lock)
    558 {
    559    STUB_SAFE_CALL1(PR_DestroyLock, lock);
    560    abort();
    561    return;
    562 }
    563 
    564 extern PRCondVar *
    565 PR_NewCondVar_stub(PRLock *lock)
    566 {
    567    STUB_SAFE_CALL1(PR_NewCondVar, lock);
    568    abort();
    569    return NULL;
    570 }
    571 
    572 extern PRStatus
    573 PR_NotifyCondVar_stub(PRCondVar *cvar)
    574 {
    575    STUB_SAFE_CALL1(PR_NotifyCondVar, cvar);
    576    abort();
    577    return PR_FAILURE;
    578 }
    579 
    580 extern PRStatus
    581 PR_NotifyAllCondVar_stub(PRCondVar *cvar)
    582 {
    583    STUB_SAFE_CALL1(PR_NotifyAllCondVar, cvar);
    584    abort();
    585    return PR_FAILURE;
    586 }
    587 
    588 extern PRStatus
    589 PR_WaitCondVar_stub(PRCondVar *cvar, PRIntervalTime timeout)
    590 {
    591    STUB_SAFE_CALL2(PR_WaitCondVar, cvar, timeout);
    592    abort();
    593    return PR_FAILURE;
    594 }
    595 
    596 extern char *
    597 PR_GetEnvSecure_stub(const char *var)
    598 {
    599    STUB_SAFE_CALL1(PR_GetEnvSecure, var);
    600 #ifdef __USE_GNU
    601    return secure_getenv(var);
    602 #else
    603    return getenv(var);
    604 #endif
    605 }
    606 
    607 extern void
    608 PR_DestroyCondVar_stub(PRCondVar *cvar)
    609 {
    610    STUB_SAFE_CALL1(PR_DestroyCondVar, cvar);
    611    abort();
    612    return;
    613 }
    614 
    615 /*
    616 * NOTE: this presupposes GCC 4.1
    617 */
    618 extern PRStatus
    619 PR_CallOnce_stub(PRCallOnceType *once, PRCallOnceFN func)
    620 {
    621    STUB_SAFE_CALL2(PR_CallOnce, once, func);
    622    abort();
    623    return PR_FAILURE;
    624 }
    625 
    626 /*
    627 * SECITEMS implement Item Utilities
    628 */
    629 extern void
    630 SECITEM_FreeItem_stub(SECItem *zap, PRBool freeit)
    631 {
    632    STUB_SAFE_CALL2(SECITEM_FreeItem_Util, zap, freeit);
    633    abort();
    634 }
    635 
    636 extern SECItem *
    637 SECITEM_AllocItem_stub(PLArenaPool *arena, SECItem *item, unsigned int len)
    638 {
    639    STUB_SAFE_CALL3(SECITEM_AllocItem_Util, arena, item, len);
    640    abort();
    641    return NULL;
    642 }
    643 
    644 extern SECComparison
    645 SECITEM_CompareItem_stub(const SECItem *a, const SECItem *b)
    646 {
    647    STUB_SAFE_CALL2(SECITEM_CompareItem_Util, a, b);
    648    abort();
    649    return SECEqual;
    650 }
    651 
    652 extern PRBool
    653 SECITEM_ItemsAreEqual_stub(const SECItem *a, const SECItem *b)
    654 {
    655    STUB_SAFE_CALL2(SECITEM_ItemsAreEqual_Util, a, b);
    656    /* two nulls are equal */
    657    if (!a && !b) {
    658        return PR_TRUE;
    659    }
    660    /* only one NULL is not equal */
    661    if (!a || !b) {
    662        return PR_FALSE;
    663    }
    664    /* we know both secitems have been set, now make sure the lengths
    665     * are equal */
    666    if (a->len != b->len) {
    667        return PR_FALSE;
    668    }
    669    /* lengths are equal, safe to verify the data */
    670    if (PORT_Memcmp(a->data, b->data, b->len) != 0) {
    671        return PR_FALSE;
    672    }
    673    return PR_TRUE;
    674 }
    675 
    676 extern SECStatus
    677 SECITEM_CopyItem_stub(PLArenaPool *arena, SECItem *to, const SECItem *from)
    678 {
    679    STUB_SAFE_CALL3(SECITEM_CopyItem_Util, arena, to, from);
    680    abort();
    681    return SECFailure;
    682 }
    683 
    684 extern SECOidTag
    685 SECOID_FindOIDTag_stub(const SECItem *oid)
    686 {
    687    STUB_SAFE_CALL1(SECOID_FindOIDTag_Util, oid);
    688    abort();
    689    return SEC_OID_UNKNOWN;
    690 }
    691 
    692 #ifdef __clang__
    693 #pragma clang diagnostic pop
    694 #endif
    695 
    696 extern void
    697 SECITEM_ZfreeItem_stub(SECItem *zap, PRBool freeit)
    698 {
    699    STUB_SAFE_CALL2(SECITEM_ZfreeItem_Util, zap, freeit);
    700    if (zap) {
    701        if (zap->data) {
    702            PORT_Memset(zap->data, 0, zap->len);
    703            PORT_Free_stub(zap->data);
    704        }
    705        PORT_Memset(zap, 0, sizeof(SECItem));
    706        if (freeit) {
    707            PORT_Free_stub(zap);
    708        }
    709    }
    710 }
    711 
    712 extern int
    713 NSS_SecureMemcmp_stub(const void *a, const void *b, size_t n)
    714 {
    715    STUB_SAFE_CALL3(NSS_SecureMemcmp, a, b, n);
    716    abort();
    717 }
    718 
    719 extern unsigned int
    720 NSS_SecureMemcmpZero_stub(const void *mem, size_t n)
    721 {
    722    STUB_SAFE_CALL2(NSS_SecureMemcmpZero, mem, n);
    723    abort();
    724 }
    725 
    726 extern void
    727 NSS_SecureSelect_stub(void *dest, const void *src0, const void *src1, size_t n, unsigned char b)
    728 {
    729    STUB_SAFE_CALL5(NSS_SecureSelect, dest, src0, src1, n, b);
    730    abort();
    731 }
    732 
    733 #ifndef NSS_FIPS_DISABLED
    734 PRBool
    735 NSS_GetSystemFIPSEnabled_stub(void)
    736 {
    737    STUB_SAFE_CALL0(NSS_GetSystemFIPSEnabled);
    738    const char *env;
    739 
    740    /* The environment variable is active for all platforms */
    741    env = PR_GetEnvSecure_stub("NSS_FIPS");
    742    /* we generally accept y, Y, 1, FIPS, TRUE, and ON as turning on FIPS
    743     * mode. Anything else is considered 'off' */
    744    if (env && (*env == 'y' || *env == '1' || *env == 'Y' ||
    745                (strcasecmp(env, "fips") == 0) ||
    746                (strcasecmp(env, "true") == 0) ||
    747                (strcasecmp(env, "on") == 0))) {
    748        return PR_TRUE;
    749    }
    750 
    751 /* currently only Linux has a system FIPS indicator. Add others here
    752 * as they become available/known */
    753 #ifdef LINUX
    754    {
    755        FILE *f;
    756        char d;
    757        size_t size;
    758        f = fopen("/proc/sys/crypto/fips_enabled", "r");
    759        if (!f)
    760            return PR_FALSE;
    761 
    762        size = fread(&d, 1, 1, f);
    763        fclose(f);
    764        if (size != 1)
    765            return PR_FALSE;
    766        if (d == '1')
    767            return PR_TRUE;
    768    }
    769 #endif /* LINUX */
    770    return PR_FALSE;
    771 }
    772 #endif /* NSS_FIPS_DISABLED = 0 */
    773 
    774 #ifdef FREEBL_NO_WEAK
    775 
    776 static const char *nsprLibName = SHLIB_PREFIX "nspr4." SHLIB_SUFFIX;
    777 static const char *nssutilLibName = SHLIB_PREFIX "nssutil3." SHLIB_SUFFIX;
    778 
    779 static SECStatus
    780 freebl_InitNSPR(void *lib)
    781 {
    782    STUB_FETCH_FUNCTION(PR_Free);
    783    STUB_FETCH_FUNCTION(PR_Open);
    784    STUB_FETCH_FUNCTION(PR_ImportPipe);
    785    STUB_FETCH_FUNCTION(PR_Close);
    786    STUB_FETCH_FUNCTION(PR_Read);
    787    STUB_FETCH_FUNCTION(PR_Seek);
    788    STUB_FETCH_FUNCTION(PR_GetLibraryFilePathname);
    789    STUB_FETCH_FUNCTION(PR_Assert);
    790    STUB_FETCH_FUNCTION(PR_Access);
    791    STUB_FETCH_FUNCTION(PR_Sleep);
    792    STUB_FETCH_FUNCTION(PR_CallOnce);
    793    STUB_FETCH_FUNCTION(PR_NewCondVar);
    794    STUB_FETCH_FUNCTION(PR_NotifyCondVar);
    795    STUB_FETCH_FUNCTION(PR_NotifyAllCondVar);
    796    STUB_FETCH_FUNCTION(PR_WaitCondVar);
    797    STUB_FETCH_FUNCTION(PR_DestroyCondVar);
    798    STUB_FETCH_FUNCTION(PR_NewLock);
    799    STUB_FETCH_FUNCTION(PR_Unlock);
    800    STUB_FETCH_FUNCTION(PR_Lock);
    801    STUB_FETCH_FUNCTION(PR_DestroyLock);
    802    STUB_FETCH_FUNCTION(PR_GetEnvSecure);
    803    return SECSuccess;
    804 }
    805 
    806 static SECStatus
    807 freebl_InitNSSUtil(void *lib)
    808 {
    809    STUB_FETCH_FUNCTION(PORT_Alloc_Util);
    810    STUB_FETCH_FUNCTION(PORT_Free_Util);
    811    STUB_FETCH_FUNCTION(PORT_ZAlloc_Util);
    812    STUB_FETCH_FUNCTION(PORT_ZFree_Util);
    813    STUB_FETCH_FUNCTION(PORT_NewArena_Util);
    814    STUB_FETCH_FUNCTION(PORT_ArenaAlloc_Util);
    815    STUB_FETCH_FUNCTION(PORT_ArenaZAlloc_Util);
    816    STUB_FETCH_FUNCTION(PORT_FreeArena_Util);
    817    STUB_FETCH_FUNCTION(PORT_GetError_Util);
    818    STUB_FETCH_FUNCTION(PORT_SetError_Util);
    819    STUB_FETCH_FUNCTION(SECITEM_FreeItem_Util);
    820    STUB_FETCH_FUNCTION(SECITEM_AllocItem_Util);
    821    STUB_FETCH_FUNCTION(SECITEM_CompareItem_Util);
    822    STUB_FETCH_FUNCTION(SECITEM_CopyItem_Util);
    823    STUB_FETCH_FUNCTION(SECITEM_ZfreeItem_Util);
    824    STUB_FETCH_FUNCTION(SECOID_FindOIDTag_Util);
    825    STUB_FETCH_FUNCTION(NSS_SecureMemcmp);
    826    STUB_FETCH_FUNCTION(NSS_SecureMemcmpZero);
    827    STUB_FETCH_FUNCTION(NSS_SecureSelect);
    828    return SECSuccess;
    829 }
    830 
    831 /*
    832 * fetch the library if it's loaded. For NSS it should already be loaded
    833 */
    834 #define freebl_getLibrary(libName) \
    835    dlopen(libName, RTLD_LAZY | RTLD_NOLOAD)
    836 
    837 #define freebl_releaseLibrary(lib) \
    838    if (lib)                       \
    839    dlclose(lib)
    840 
    841 static void *FREEBLnsprGlobalLib = NULL;
    842 static void *FREEBLnssutilGlobalLib = NULL;
    843 
    844 void __attribute((destructor)) FREEBL_unload()
    845 {
    846    freebl_releaseLibrary(FREEBLnsprGlobalLib);
    847    freebl_releaseLibrary(FREEBLnssutilGlobalLib);
    848 }
    849 #endif
    850 
    851 /*
    852 * load the symbols from the real libraries if available.
    853 *
    854 * if force is set, explicitly load the libraries if they are not already
    855 * loaded. If we could not use the real libraries, return failure.
    856 */
    857 extern SECStatus
    858 FREEBL_InitStubs()
    859 {
    860    SECStatus rv = SECSuccess;
    861 #ifdef FREEBL_NO_WEAK
    862    void *nspr = NULL;
    863    void *nssutil = NULL;
    864 
    865    /* NSPR should be first */
    866    if (!FREEBLnsprGlobalLib) {
    867        nspr = freebl_getLibrary(nsprLibName);
    868        if (!nspr) {
    869            return SECFailure;
    870        }
    871        rv = freebl_InitNSPR(nspr);
    872        if (rv != SECSuccess) {
    873            freebl_releaseLibrary(nspr);
    874            return rv;
    875        }
    876        FREEBLnsprGlobalLib = nspr; /* adopt */
    877    }
    878    /* now load NSSUTIL */
    879    if (!FREEBLnssutilGlobalLib) {
    880        nssutil = freebl_getLibrary(nssutilLibName);
    881        if (!nssutil) {
    882            return SECFailure;
    883        }
    884        rv = freebl_InitNSSUtil(nssutil);
    885        if (rv != SECSuccess) {
    886            freebl_releaseLibrary(nssutil);
    887            return rv;
    888        }
    889        FREEBLnssutilGlobalLib = nssutil; /* adopt */
    890    }
    891 #endif
    892 
    893    return rv;
    894 }