utils.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  1. #ifndef __STDC_WANT_LIB_EXT1__
  2. # define __STDC_WANT_LIB_EXT1__ 1
  3. #endif
  4. #include <assert.h>
  5. #include <errno.h>
  6. #include <limits.h>
  7. #include <stddef.h>
  8. #include <stdint.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #ifndef __wasm__
  12. # include <signal.h>
  13. #endif
  14. #ifdef HAVE_SYS_MMAN_H
  15. # include <sys/mman.h>
  16. #endif
  17. #ifdef _WIN32
  18. # include <windows.h>
  19. # include <wincrypt.h>
  20. #else
  21. # include <unistd.h>
  22. #endif
  23. #ifndef HAVE_C_VARARRAYS
  24. # ifdef HAVE_ALLOCA_H
  25. # include <alloca.h>
  26. # elif !defined(alloca)
  27. # if defined(__clang__) || defined(__GNUC__)
  28. # define alloca __builtin_alloca
  29. # elif defined _AIX
  30. # define alloca __alloca
  31. # elif defined _MSC_VER
  32. # include <malloc.h>
  33. # define alloca _alloca
  34. # else
  35. # include <stddef.h>
  36. # ifdef __cplusplus
  37. extern "C"
  38. # endif
  39. void *alloca (size_t);
  40. # endif
  41. # endif
  42. #endif
  43. #include "core.h"
  44. #include "randombytes.h"
  45. #include "utils.h"
  46. #ifndef ENOSYS
  47. # define ENOSYS ENXIO
  48. #endif
  49. #if defined(_WIN32) && \
  50. (!defined(WINAPI_FAMILY) || WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
  51. # define WINAPI_DESKTOP
  52. #endif
  53. #define CANARY_SIZE 16U
  54. #define GARBAGE_VALUE 0xdb
  55. #ifndef MAP_NOCORE
  56. # ifdef MAP_CONCEAL
  57. # define MAP_NOCORE MAP_CONCEAL
  58. # else
  59. # define MAP_NOCORE 0
  60. # endif
  61. #endif
  62. #if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
  63. # define MAP_ANON MAP_ANONYMOUS
  64. #endif
  65. #if defined(WINAPI_DESKTOP) || (defined(MAP_ANON) && defined(HAVE_MMAP)) || \
  66. defined(HAVE_POSIX_MEMALIGN)
  67. # define HAVE_ALIGNED_MALLOC
  68. #endif
  69. #if defined(HAVE_MPROTECT) && \
  70. !(defined(PROT_NONE) && defined(PROT_READ) && defined(PROT_WRITE))
  71. # undef HAVE_MPROTECT
  72. #endif
  73. #if defined(HAVE_ALIGNED_MALLOC) && \
  74. (defined(WINAPI_DESKTOP) || defined(HAVE_MPROTECT))
  75. # define HAVE_PAGE_PROTECTION
  76. #endif
  77. #if !defined(MADV_DODUMP) && defined(MADV_CORE)
  78. # define MADV_DODUMP MADV_CORE
  79. # define MADV_DONTDUMP MADV_NOCORE
  80. #endif
  81. #ifndef DEFAULT_PAGE_SIZE
  82. # ifdef PAGE_SIZE
  83. # define DEFAULT_PAGE_SIZE PAGE_SIZE
  84. # else
  85. # define DEFAULT_PAGE_SIZE 0x10000
  86. # endif
  87. #endif
  88. static size_t page_size = DEFAULT_PAGE_SIZE;
  89. static unsigned char canary[CANARY_SIZE];
  90. /* LCOV_EXCL_START */
  91. #ifdef HAVE_WEAK_SYMBOLS
  92. __attribute__((weak)) void
  93. _sodium_dummy_symbol_to_prevent_memzero_lto(void *const pnt,
  94. const size_t len);
  95. __attribute__((weak)) void
  96. _sodium_dummy_symbol_to_prevent_memzero_lto(void *const pnt,
  97. const size_t len)
  98. {
  99. (void) pnt; /* LCOV_EXCL_LINE */
  100. (void) len; /* LCOV_EXCL_LINE */
  101. }
  102. #endif
  103. /* LCOV_EXCL_STOP */
  104. void
  105. sodium_memzero(void * const pnt, const size_t len)
  106. {
  107. #ifdef _WIN32
  108. SecureZeroMemory(pnt, len);
  109. #elif defined(HAVE_MEMSET_S)
  110. if (len > 0U && memset_s(pnt, (rsize_t) len, 0, (rsize_t) len) != 0) {
  111. sodium_misuse(); /* LCOV_EXCL_LINE */
  112. }
  113. #elif defined(HAVE_EXPLICIT_BZERO)
  114. explicit_bzero(pnt, len);
  115. #elif defined(HAVE_EXPLICIT_MEMSET)
  116. explicit_memset(pnt, 0, len);
  117. #elif HAVE_WEAK_SYMBOLS
  118. if (len > 0U) {
  119. memset(pnt, 0, len);
  120. _sodium_dummy_symbol_to_prevent_memzero_lto(pnt, len);
  121. }
  122. # ifdef HAVE_INLINE_ASM
  123. __asm__ __volatile__ ("" : : "r"(pnt) : "memory");
  124. # endif
  125. #else
  126. volatile unsigned char *volatile pnt_ =
  127. (volatile unsigned char *volatile) pnt;
  128. size_t i = (size_t) 0U;
  129. while (i < len) {
  130. pnt_[i++] = 0U;
  131. }
  132. #endif
  133. }
  134. void
  135. sodium_stackzero(const size_t len)
  136. {
  137. #ifdef HAVE_C_VARARRAYS
  138. unsigned char fodder[len];
  139. sodium_memzero(fodder, len);
  140. #elif HAVE_ALLOCA
  141. sodium_memzero(alloca(len), len);
  142. #endif
  143. }
  144. #ifdef HAVE_WEAK_SYMBOLS
  145. __attribute__((weak)) void
  146. _sodium_dummy_symbol_to_prevent_memcmp_lto(const unsigned char *b1,
  147. const unsigned char *b2,
  148. const size_t len);
  149. __attribute__((weak)) void
  150. _sodium_dummy_symbol_to_prevent_memcmp_lto(const unsigned char *b1,
  151. const unsigned char *b2,
  152. const size_t len)
  153. {
  154. (void) b1;
  155. (void) b2;
  156. (void) len;
  157. }
  158. #endif
  159. int
  160. sodium_memcmp(const void *const b1_, const void *const b2_, size_t len)
  161. {
  162. #ifdef HAVE_WEAK_SYMBOLS
  163. const unsigned char *b1 = (const unsigned char *) b1_;
  164. const unsigned char *b2 = (const unsigned char *) b2_;
  165. #else
  166. const volatile unsigned char *volatile b1 =
  167. (const volatile unsigned char *volatile) b1_;
  168. const volatile unsigned char *volatile b2 =
  169. (const volatile unsigned char *volatile) b2_;
  170. #endif
  171. size_t i;
  172. volatile unsigned char d = 0U;
  173. #if HAVE_WEAK_SYMBOLS
  174. _sodium_dummy_symbol_to_prevent_memcmp_lto(b1, b2, len);
  175. #endif
  176. for (i = 0U; i < len; i++) {
  177. d |= b1[i] ^ b2[i];
  178. }
  179. return (1 & ((d - 1) >> 8)) - 1;
  180. }
  181. #ifdef HAVE_WEAK_SYMBOLS
  182. __attribute__((weak)) void
  183. _sodium_dummy_symbol_to_prevent_compare_lto(const unsigned char *b1,
  184. const unsigned char *b2,
  185. const size_t len);
  186. __attribute__((weak)) void
  187. _sodium_dummy_symbol_to_prevent_compare_lto(const unsigned char *b1,
  188. const unsigned char *b2,
  189. const size_t len)
  190. {
  191. (void) b1;
  192. (void) b2;
  193. (void) len;
  194. }
  195. #endif
  196. int
  197. sodium_compare(const unsigned char *b1_, const unsigned char *b2_, size_t len)
  198. {
  199. #ifdef HAVE_WEAK_SYMBOLS
  200. const unsigned char *b1 = b1_;
  201. const unsigned char *b2 = b2_;
  202. #else
  203. const volatile unsigned char *volatile b1 =
  204. (const volatile unsigned char *volatile) b1_;
  205. const volatile unsigned char *volatile b2 =
  206. (const volatile unsigned char *volatile) b2_;
  207. #endif
  208. size_t i;
  209. volatile unsigned char gt = 0U;
  210. volatile unsigned char eq = 1U;
  211. uint16_t x1, x2;
  212. #if HAVE_WEAK_SYMBOLS
  213. _sodium_dummy_symbol_to_prevent_compare_lto(b1, b2, len);
  214. #endif
  215. i = len;
  216. while (i != 0U) {
  217. i--;
  218. x1 = b1[i];
  219. x2 = b2[i];
  220. gt |= ((x2 - x1) >> 8) & eq;
  221. eq &= ((x2 ^ x1) - 1) >> 8;
  222. }
  223. return (int) (gt + gt + eq) - 1;
  224. }
  225. int
  226. sodium_is_zero(const unsigned char *n, const size_t nlen)
  227. {
  228. size_t i;
  229. volatile unsigned char d = 0U;
  230. for (i = 0U; i < nlen; i++) {
  231. d |= n[i];
  232. }
  233. return 1 & ((d - 1) >> 8);
  234. }
  235. void
  236. sodium_increment(unsigned char *n, const size_t nlen)
  237. {
  238. size_t i = 0U;
  239. uint_fast16_t c = 1U;
  240. #ifdef HAVE_AMD64_ASM
  241. uint64_t t64, t64_2;
  242. uint32_t t32;
  243. if (nlen == 12U) {
  244. __asm__ __volatile__(
  245. "xorq %[t64], %[t64] \n"
  246. "xorl %[t32], %[t32] \n"
  247. "stc \n"
  248. "adcq %[t64], (%[out]) \n"
  249. "adcl %[t32], 8(%[out]) \n"
  250. : [t64] "=&r"(t64), [t32] "=&r"(t32)
  251. : [out] "D"(n)
  252. : "memory", "flags", "cc");
  253. return;
  254. } else if (nlen == 24U) {
  255. __asm__ __volatile__(
  256. "movq $1, %[t64] \n"
  257. "xorq %[t64_2], %[t64_2] \n"
  258. "addq %[t64], (%[out]) \n"
  259. "adcq %[t64_2], 8(%[out]) \n"
  260. "adcq %[t64_2], 16(%[out]) \n"
  261. : [t64] "=&r"(t64), [t64_2] "=&r"(t64_2)
  262. : [out] "D"(n)
  263. : "memory", "flags", "cc");
  264. return;
  265. } else if (nlen == 8U) {
  266. __asm__ __volatile__("incq (%[out]) \n"
  267. :
  268. : [out] "D"(n)
  269. : "memory", "flags", "cc");
  270. return;
  271. }
  272. #endif
  273. for (; i < nlen; i++) {
  274. c += (uint_fast16_t) n[i];
  275. n[i] = (unsigned char) c;
  276. c >>= 8;
  277. }
  278. }
  279. void
  280. sodium_add(unsigned char *a, const unsigned char *b, const size_t len)
  281. {
  282. size_t i;
  283. uint_fast16_t c = 0U;
  284. #ifdef HAVE_AMD64_ASM
  285. uint64_t t64, t64_2, t64_3;
  286. uint32_t t32;
  287. if (len == 12U) {
  288. __asm__ __volatile__(
  289. "movq (%[in]), %[t64] \n"
  290. "movl 8(%[in]), %[t32] \n"
  291. "addq %[t64], (%[out]) \n"
  292. "adcl %[t32], 8(%[out]) \n"
  293. : [t64] "=&r"(t64), [t32] "=&r"(t32)
  294. : [in] "S"(b), [out] "D"(a)
  295. : "memory", "flags", "cc");
  296. return;
  297. } else if (len == 24U) {
  298. __asm__ __volatile__(
  299. "movq (%[in]), %[t64] \n"
  300. "movq 8(%[in]), %[t64_2] \n"
  301. "movq 16(%[in]), %[t64_3] \n"
  302. "addq %[t64], (%[out]) \n"
  303. "adcq %[t64_2], 8(%[out]) \n"
  304. "adcq %[t64_3], 16(%[out]) \n"
  305. : [t64] "=&r"(t64), [t64_2] "=&r"(t64_2), [t64_3] "=&r"(t64_3)
  306. : [in] "S"(b), [out] "D"(a)
  307. : "memory", "flags", "cc");
  308. return;
  309. } else if (len == 8U) {
  310. __asm__ __volatile__(
  311. "movq (%[in]), %[t64] \n"
  312. "addq %[t64], (%[out]) \n"
  313. : [t64] "=&r"(t64)
  314. : [in] "S"(b), [out] "D"(a)
  315. : "memory", "flags", "cc");
  316. return;
  317. }
  318. #endif
  319. for (i = 0U; i < len; i++) {
  320. c += (uint_fast16_t) a[i] + (uint_fast16_t) b[i];
  321. a[i] = (unsigned char) c;
  322. c >>= 8;
  323. }
  324. }
  325. void
  326. sodium_sub(unsigned char *a, const unsigned char *b, const size_t len)
  327. {
  328. uint_fast16_t c = 0U;
  329. size_t i;
  330. #ifdef HAVE_AMD64_ASM
  331. uint64_t t64_1, t64_2, t64_3, t64_4;
  332. uint64_t t64_5, t64_6, t64_7, t64_8;
  333. uint32_t t32;
  334. if (len == 64U) {
  335. __asm__ __volatile__(
  336. "movq (%[in]), %[t64_1] \n"
  337. "movq 8(%[in]), %[t64_2] \n"
  338. "movq 16(%[in]), %[t64_3] \n"
  339. "movq 24(%[in]), %[t64_4] \n"
  340. "movq 32(%[in]), %[t64_5] \n"
  341. "movq 40(%[in]), %[t64_6] \n"
  342. "movq 48(%[in]), %[t64_7] \n"
  343. "movq 56(%[in]), %[t64_8] \n"
  344. "subq %[t64_1], (%[out]) \n"
  345. "sbbq %[t64_2], 8(%[out]) \n"
  346. "sbbq %[t64_3], 16(%[out]) \n"
  347. "sbbq %[t64_4], 24(%[out]) \n"
  348. "sbbq %[t64_5], 32(%[out]) \n"
  349. "sbbq %[t64_6], 40(%[out]) \n"
  350. "sbbq %[t64_7], 48(%[out]) \n"
  351. "sbbq %[t64_8], 56(%[out]) \n"
  352. : [t64_1] "=&r"(t64_1), [t64_2] "=&r"(t64_2), [t64_3] "=&r"(t64_3), [t64_4] "=&r"(t64_4),
  353. [t64_5] "=&r"(t64_5), [t64_6] "=&r"(t64_6), [t64_7] "=&r"(t64_7), [t64_8] "=&r"(t64_8)
  354. : [in] "S"(b), [out] "D"(a)
  355. : "memory", "flags", "cc");
  356. return;
  357. }
  358. #endif
  359. for (i = 0U; i < len; i++) {
  360. c = (uint_fast16_t) a[i] - (uint_fast16_t) b[i] - c;
  361. a[i] = (unsigned char) c;
  362. c = (c >> 8) & 1U;
  363. }
  364. }
  365. int
  366. _sodium_alloc_init(void)
  367. {
  368. #ifdef HAVE_ALIGNED_MALLOC
  369. # if defined(_SC_PAGESIZE)
  370. long page_size_ = sysconf(_SC_PAGESIZE);
  371. if (page_size_ > 0L) {
  372. page_size = (size_t) page_size_;
  373. }
  374. # elif defined(WINAPI_DESKTOP)
  375. SYSTEM_INFO si;
  376. GetSystemInfo(&si);
  377. page_size = (size_t) si.dwPageSize;
  378. # else
  379. # warning Unknown page size
  380. # endif
  381. if (page_size < CANARY_SIZE || page_size < sizeof(size_t)) {
  382. sodium_misuse(); /* LCOV_EXCL_LINE */
  383. }
  384. #endif
  385. randombytes_buf(canary, sizeof canary);
  386. return 0;
  387. }
  388. int
  389. sodium_mlock(void *const addr, const size_t len)
  390. {
  391. #if defined(MADV_DONTDUMP) && defined(HAVE_MADVISE)
  392. (void) madvise(addr, len, MADV_DONTDUMP);
  393. #endif
  394. #ifdef HAVE_MLOCK
  395. return mlock(addr, len);
  396. #elif defined(WINAPI_DESKTOP)
  397. return -(VirtualLock(addr, len) == 0);
  398. #else
  399. errno = ENOSYS;
  400. return -1;
  401. #endif
  402. }
  403. int
  404. sodium_munlock(void *const addr, const size_t len)
  405. {
  406. sodium_memzero(addr, len);
  407. #if defined(MADV_DODUMP) && defined(HAVE_MADVISE)
  408. (void) madvise(addr, len, MADV_DODUMP);
  409. #endif
  410. #ifdef HAVE_MLOCK
  411. return munlock(addr, len);
  412. #elif defined(WINAPI_DESKTOP)
  413. return -(VirtualUnlock(addr, len) == 0);
  414. #else
  415. errno = ENOSYS;
  416. return -1;
  417. #endif
  418. }
  419. static int
  420. _mprotect_noaccess(void *ptr, size_t size)
  421. {
  422. #ifdef HAVE_MPROTECT
  423. return mprotect(ptr, size, PROT_NONE);
  424. #elif defined(WINAPI_DESKTOP)
  425. DWORD old;
  426. return -(VirtualProtect(ptr, size, PAGE_NOACCESS, &old) == 0);
  427. #else
  428. errno = ENOSYS;
  429. return -1;
  430. #endif
  431. }
  432. static int
  433. _mprotect_readonly(void *ptr, size_t size)
  434. {
  435. #ifdef HAVE_MPROTECT
  436. return mprotect(ptr, size, PROT_READ);
  437. #elif defined(WINAPI_DESKTOP)
  438. DWORD old;
  439. return -(VirtualProtect(ptr, size, PAGE_READONLY, &old) == 0);
  440. #else
  441. errno = ENOSYS;
  442. return -1;
  443. #endif
  444. }
  445. static int
  446. _mprotect_readwrite(void *ptr, size_t size)
  447. {
  448. #ifdef HAVE_MPROTECT
  449. return mprotect(ptr, size, PROT_READ | PROT_WRITE);
  450. #elif defined(WINAPI_DESKTOP)
  451. DWORD old;
  452. return -(VirtualProtect(ptr, size, PAGE_READWRITE, &old) == 0);
  453. #else
  454. errno = ENOSYS;
  455. return -1;
  456. #endif
  457. }
  458. #ifdef HAVE_ALIGNED_MALLOC
  459. __attribute__((noreturn)) static void
  460. _out_of_bounds(void)
  461. {
  462. # ifndef __wasm__
  463. # ifdef SIGSEGV
  464. raise(SIGSEGV);
  465. # elif defined(SIGKILL)
  466. raise(SIGKILL);
  467. # endif
  468. # endif
  469. abort(); /* not something we want any higher-level API to catch */
  470. } /* LCOV_EXCL_LINE */
  471. static inline size_t
  472. _page_round(const size_t size)
  473. {
  474. const size_t page_mask = page_size - 1U;
  475. return (size + page_mask) & ~page_mask;
  476. }
  477. static __attribute__((malloc)) unsigned char *
  478. _alloc_aligned(const size_t size)
  479. {
  480. void *ptr;
  481. # if defined(MAP_ANON) && defined(HAVE_MMAP)
  482. if ((ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
  483. MAP_ANON | MAP_PRIVATE | MAP_NOCORE, -1, 0)) ==
  484. MAP_FAILED) {
  485. ptr = NULL; /* LCOV_EXCL_LINE */
  486. } /* LCOV_EXCL_LINE */
  487. # elif defined(HAVE_POSIX_MEMALIGN)
  488. if (posix_memalign(&ptr, page_size, size) != 0) {
  489. ptr = NULL; /* LCOV_EXCL_LINE */
  490. } /* LCOV_EXCL_LINE */
  491. # elif defined(WINAPI_DESKTOP)
  492. ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  493. # else
  494. # error Bug
  495. # endif
  496. return (unsigned char *) ptr;
  497. }
  498. static void
  499. _free_aligned(unsigned char *const ptr, const size_t size)
  500. {
  501. # if defined(MAP_ANON) && defined(HAVE_MMAP)
  502. (void) munmap(ptr, size);
  503. # elif defined(HAVE_POSIX_MEMALIGN)
  504. free(ptr);
  505. # elif defined(WINAPI_DESKTOP)
  506. VirtualFree(ptr, 0U, MEM_RELEASE);
  507. # else
  508. # error Bug
  509. #endif
  510. }
  511. static unsigned char *
  512. _unprotected_ptr_from_user_ptr(void *const ptr)
  513. {
  514. uintptr_t unprotected_ptr_u;
  515. unsigned char *canary_ptr;
  516. size_t page_mask;
  517. canary_ptr = ((unsigned char *) ptr) - sizeof canary;
  518. page_mask = page_size - 1U;
  519. unprotected_ptr_u = ((uintptr_t) canary_ptr & (uintptr_t) ~page_mask);
  520. if (unprotected_ptr_u <= page_size * 2U) {
  521. sodium_misuse(); /* LCOV_EXCL_LINE */
  522. }
  523. return (unsigned char *) unprotected_ptr_u;
  524. }
  525. #endif /* HAVE_ALIGNED_MALLOC */
  526. #ifndef HAVE_ALIGNED_MALLOC
  527. static __attribute__((malloc)) void *
  528. _sodium_malloc(const size_t size)
  529. {
  530. return malloc(size > (size_t) 0U ? size : (size_t) 1U);
  531. }
  532. #else
  533. static __attribute__((malloc)) void *
  534. _sodium_malloc(const size_t size)
  535. {
  536. void *user_ptr;
  537. unsigned char *base_ptr;
  538. unsigned char *canary_ptr;
  539. unsigned char *unprotected_ptr;
  540. size_t size_with_canary;
  541. size_t total_size;
  542. size_t unprotected_size;
  543. if (size >= (size_t) SIZE_MAX - page_size * 4U) {
  544. errno = ENOMEM;
  545. return NULL;
  546. }
  547. if (page_size <= sizeof canary || page_size < sizeof unprotected_size) {
  548. sodium_misuse(); /* LCOV_EXCL_LINE */
  549. }
  550. size_with_canary = (sizeof canary) + size;
  551. unprotected_size = _page_round(size_with_canary);
  552. total_size = page_size + page_size + unprotected_size + page_size;
  553. if ((base_ptr = _alloc_aligned(total_size)) == NULL) {
  554. return NULL; /* LCOV_EXCL_LINE */
  555. }
  556. unprotected_ptr = base_ptr + page_size * 2U;
  557. _mprotect_noaccess(base_ptr + page_size, page_size);
  558. # ifndef HAVE_PAGE_PROTECTION
  559. memcpy(unprotected_ptr + unprotected_size, canary, sizeof canary);
  560. # endif
  561. _mprotect_noaccess(unprotected_ptr + unprotected_size, page_size);
  562. sodium_mlock(unprotected_ptr, unprotected_size);
  563. canary_ptr =
  564. unprotected_ptr + _page_round(size_with_canary) - size_with_canary;
  565. user_ptr = canary_ptr + sizeof canary;
  566. memcpy(canary_ptr, canary, sizeof canary);
  567. memcpy(base_ptr, &unprotected_size, sizeof unprotected_size);
  568. _mprotect_readonly(base_ptr, page_size);
  569. assert(_unprotected_ptr_from_user_ptr(user_ptr) == unprotected_ptr);
  570. return user_ptr;
  571. }
  572. #endif /* !HAVE_ALIGNED_MALLOC */
  573. __attribute__((malloc)) void *
  574. sodium_malloc(const size_t size)
  575. {
  576. void *ptr;
  577. if ((ptr = _sodium_malloc(size)) == NULL) {
  578. return NULL;
  579. }
  580. memset(ptr, (int) GARBAGE_VALUE, size);
  581. return ptr;
  582. }
  583. __attribute__((malloc)) void *
  584. sodium_allocarray(size_t count, size_t size)
  585. {
  586. if (count > (size_t) 0U && size >= (size_t) SIZE_MAX / count) {
  587. errno = ENOMEM;
  588. return NULL;
  589. }
  590. return sodium_malloc(count * size);
  591. }
  592. #ifndef HAVE_ALIGNED_MALLOC
  593. void
  594. sodium_free(void *ptr)
  595. {
  596. free(ptr);
  597. }
  598. #else
  599. void
  600. sodium_free(void *ptr)
  601. {
  602. unsigned char *base_ptr;
  603. unsigned char *canary_ptr;
  604. unsigned char *unprotected_ptr;
  605. size_t total_size;
  606. size_t unprotected_size;
  607. if (ptr == NULL) {
  608. return;
  609. }
  610. canary_ptr = ((unsigned char *) ptr) - sizeof canary;
  611. unprotected_ptr = _unprotected_ptr_from_user_ptr(ptr);
  612. base_ptr = unprotected_ptr - page_size * 2U;
  613. memcpy(&unprotected_size, base_ptr, sizeof unprotected_size);
  614. total_size = page_size + page_size + unprotected_size + page_size;
  615. _mprotect_readwrite(base_ptr, total_size);
  616. if (sodium_memcmp(canary_ptr, canary, sizeof canary) != 0) {
  617. _out_of_bounds();
  618. }
  619. # ifndef HAVE_PAGE_PROTECTION
  620. if (sodium_memcmp(unprotected_ptr + unprotected_size, canary,
  621. sizeof canary) != 0) {
  622. _out_of_bounds();
  623. }
  624. # endif
  625. sodium_munlock(unprotected_ptr, unprotected_size);
  626. _free_aligned(base_ptr, total_size);
  627. }
  628. #endif /* HAVE_ALIGNED_MALLOC */
  629. #ifndef HAVE_PAGE_PROTECTION
  630. static int
  631. _sodium_mprotect(void *ptr, int (*cb)(void *ptr, size_t size))
  632. {
  633. (void) ptr;
  634. (void) cb;
  635. errno = ENOSYS;
  636. return -1;
  637. }
  638. #else
  639. static int
  640. _sodium_mprotect(void *ptr, int (*cb)(void *ptr, size_t size))
  641. {
  642. unsigned char *base_ptr;
  643. unsigned char *unprotected_ptr;
  644. size_t unprotected_size;
  645. unprotected_ptr = _unprotected_ptr_from_user_ptr(ptr);
  646. base_ptr = unprotected_ptr - page_size * 2U;
  647. memcpy(&unprotected_size, base_ptr, sizeof unprotected_size);
  648. return cb(unprotected_ptr, unprotected_size);
  649. }
  650. #endif
  651. int
  652. sodium_mprotect_noaccess(void *ptr)
  653. {
  654. return _sodium_mprotect(ptr, _mprotect_noaccess);
  655. }
  656. int
  657. sodium_mprotect_readonly(void *ptr)
  658. {
  659. return _sodium_mprotect(ptr, _mprotect_readonly);
  660. }
  661. int
  662. sodium_mprotect_readwrite(void *ptr)
  663. {
  664. return _sodium_mprotect(ptr, _mprotect_readwrite);
  665. }
  666. int
  667. sodium_pad(size_t *padded_buflen_p, unsigned char *buf,
  668. size_t unpadded_buflen, size_t blocksize, size_t max_buflen)
  669. {
  670. unsigned char *tail;
  671. size_t i;
  672. size_t xpadlen;
  673. size_t xpadded_len;
  674. volatile unsigned char mask;
  675. unsigned char barrier_mask;
  676. if (blocksize <= 0U) {
  677. return -1;
  678. }
  679. xpadlen = blocksize - 1U;
  680. if ((blocksize & (blocksize - 1U)) == 0U) {
  681. xpadlen -= unpadded_buflen & (blocksize - 1U);
  682. } else {
  683. xpadlen -= unpadded_buflen % blocksize;
  684. }
  685. if ((size_t) SIZE_MAX - unpadded_buflen <= xpadlen) {
  686. sodium_misuse();
  687. }
  688. xpadded_len = unpadded_buflen + xpadlen;
  689. if (xpadded_len >= max_buflen) {
  690. return -1;
  691. }
  692. tail = &buf[xpadded_len];
  693. if (padded_buflen_p != NULL) {
  694. *padded_buflen_p = xpadded_len + 1U;
  695. }
  696. mask = 0U;
  697. for (i = 0; i < blocksize; i++) {
  698. barrier_mask = (unsigned char) (((i ^ xpadlen) - 1U)
  699. >> ((sizeof(size_t) - 1) * CHAR_BIT));
  700. *(tail - i) = ((*(tail - i)) & mask) | (0x80 & barrier_mask);
  701. mask |= barrier_mask;
  702. }
  703. return 0;
  704. }
  705. int
  706. sodium_unpad(size_t *unpadded_buflen_p, const unsigned char *buf,
  707. size_t padded_buflen, size_t blocksize)
  708. {
  709. const unsigned char *tail;
  710. unsigned char acc = 0U;
  711. unsigned char c;
  712. unsigned char valid = 0U;
  713. volatile size_t pad_len = 0U;
  714. size_t i;
  715. size_t is_barrier;
  716. if (padded_buflen < blocksize || blocksize <= 0U) {
  717. return -1;
  718. }
  719. tail = &buf[padded_buflen - 1U];
  720. for (i = 0U; i < blocksize; i++) {
  721. c = *(tail - i);
  722. is_barrier =
  723. (( (acc - 1U) & (pad_len - 1U) & ((c ^ 0x80) - 1U) ) >> 8) & 1U;
  724. acc |= c;
  725. pad_len |= i & (1U + ~is_barrier);
  726. valid |= (unsigned char) is_barrier;
  727. }
  728. *unpadded_buflen_p = padded_buflen - 1U - pad_len;
  729. return (int) (valid - 1U);
  730. }