utils.c 20 KB

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