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 }