summaryrefslogtreecommitdiff
path: root/src/libsodium/sodium
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsodium/sodium')
-rw-r--r--src/libsodium/sodium/compat.c361
-rw-r--r--src/libsodium/sodium/core.c4
-rw-r--r--src/libsodium/sodium/runtime.c6
-rw-r--r--src/libsodium/sodium/utils.c340
4 files changed, 313 insertions, 398 deletions
diff --git a/src/libsodium/sodium/compat.c b/src/libsodium/sodium/compat.c
deleted file mode 100644
index ece2dbc..0000000
--- a/src/libsodium/sodium/compat.c
+++ /dev/null
@@ -1,361 +0,0 @@
-
-#include "crypto_auth_hmacsha256.h"
-#include "crypto_auth_hmacsha512256.h"
-#include "crypto_box_curve25519xsalsa20poly1305.h"
-#include "crypto_hash_sha256.h"
-#include "crypto_hash_sha512.h"
-#include "crypto_onetimeauth_poly1305.h"
-#include "crypto_pwhash_scryptsalsa208sha256.h"
-#include "crypto_scalarmult_curve25519.h"
-#include "crypto_secretbox_xsalsa20poly1305.h"
-#include "crypto_sign_ed25519.h"
-#include "crypto_stream_salsa20.h"
-#include "crypto_stream_xsalsa20.h"
-#include "crypto_verify_16.h"
-#include "crypto_verify_32.h"
-#include "export.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#undef crypto_pwhash_scryptxsalsa208sha256_saltbytes
-SODIUM_EXPORT size_t
-crypto_pwhash_scryptxsalsa208sha256_saltbytes(void)
-{
- return crypto_pwhash_scryptsalsa208sha256_saltbytes();
-}
-
-#undef crypto_pwhash_scryptxsalsa208sha256_strbytes
-SODIUM_EXPORT size_t
-crypto_pwhash_scryptxsalsa208sha256_strbytes(void)
-{
- return crypto_pwhash_scryptsalsa208sha256_strbytes();
-}
-
-#undef crypto_pwhash_scryptxsalsa208sha256
-SODIUM_EXPORT int
-crypto_pwhash_scryptxsalsa208sha256(unsigned char * const out,
- unsigned long long outlen,
- const char * const passwd,
- unsigned long long passwdlen,
- const unsigned char * const salt,
- unsigned long long opslimit,
- size_t memlimit)
-{
- return crypto_pwhash_scryptsalsa208sha256(out, outlen, passwd, passwdlen,
- salt, opslimit, memlimit);
-}
-
-#undef crypto_pwhash_scryptxsalsa208sha256_str
-SODIUM_EXPORT int
-crypto_pwhash_scryptxsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
- const char * const passwd,
- unsigned long long passwdlen,
- unsigned long long opslimit,
- size_t memlimit)
-{
- return crypto_pwhash_scryptsalsa208sha256_str(out, passwd, passwdlen,
- opslimit, memlimit);
-}
-
-#undef crypto_pwhash_scryptxsalsa208sha256_str_verify
-SODIUM_EXPORT int
-crypto_pwhash_scryptxsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
- const char * const passwd,
- unsigned long long passwdlen)
-{
- return crypto_pwhash_scryptsalsa208sha256_str_verify(str,
- passwd, passwdlen);
-}
-
-#ifdef EXPORT_ORIGINAL_IMPLEMENTATIONS
-
-#undef crypto_hash_sha256_ref
-SODIUM_EXPORT int
-crypto_hash_sha256_ref(unsigned char *out, const unsigned char *in,
- unsigned long long inlen)
-{
- return crypto_hash_sha256(out, in, inlen);
-}
-
-#undef crypto_hash_sha512_ref
-SODIUM_EXPORT int
-crypto_hash_sha512_ref(unsigned char *out, const unsigned char *in,
- unsigned long long inlen)
-{
- return crypto_hash_sha512(out, in, inlen);
-}
-
-#undef crypto_auth_hmacsha256_ref
-SODIUM_EXPORT int
-crypto_auth_hmacsha256_ref(unsigned char *out, const unsigned char *in,
- unsigned long long inlen, const unsigned char *k)
-{
- return crypto_auth_hmacsha256(out, in, inlen, k);
-}
-
-#undef crypto_auth_hmacsha256_ref_verify
-SODIUM_EXPORT int
-crypto_auth_hmacsha256_ref_verify(const unsigned char *h,
- const unsigned char *in,
- unsigned long long inlen,
- const unsigned char *k)
-{
- return crypto_auth_hmacsha256_verify(h, in, inlen, k);
-}
-
-#undef crypto_auth_hmacsha512256_ref
-SODIUM_EXPORT int
-crypto_auth_hmacsha512256_ref(unsigned char *out, const unsigned char *in,
- unsigned long long inlen, const unsigned char *k)
-{
- return crypto_auth_hmacsha512256(out, in, inlen, k);
-}
-
-#undef crypto_auth_hmacsha512256_ref_verify
-SODIUM_EXPORT int
-crypto_auth_hmacsha512256_ref_verify(const unsigned char *h,
- const unsigned char *in,
- unsigned long long inlen,
- const unsigned char *k)
-{
- return crypto_auth_hmacsha512256_verify(h, in, inlen, k);
-}
-
-#undef crypto_box_curve25519xsalsa20poly1305_ref_keypair
-SODIUM_EXPORT int
-crypto_box_curve25519xsalsa20poly1305_ref_keypair(unsigned char *pk,
- unsigned char *sk)
-{
- return crypto_box_curve25519xsalsa20poly1305_keypair(pk, sk);
-}
-
-#undef crypto_box_curve25519xsalsa20poly1305_ref_beforenm
-SODIUM_EXPORT int
-crypto_box_curve25519xsalsa20poly1305_ref_beforenm(unsigned char *k,
- const unsigned char *pk,
- const unsigned char *sk)
-{
- return crypto_box_curve25519xsalsa20poly1305_beforenm(k, pk, sk);
-}
-
-#undef crypto_box_curve25519xsalsa20poly1305_ref_afternm
-SODIUM_EXPORT int
-crypto_box_curve25519xsalsa20poly1305_ref_afternm(unsigned char *c,
- const unsigned char *m,
- unsigned long long mlen,
- const unsigned char *n,
- const unsigned char *k)
-{
- return crypto_box_curve25519xsalsa20poly1305_afternm(c, m, mlen, n, k);
-}
-
-#undef crypto_box_curve25519xsalsa20poly1305_ref_open_afternm
-SODIUM_EXPORT int
-crypto_box_curve25519xsalsa20poly1305_ref_open_afternm(unsigned char *m,
- const unsigned char *c,
- unsigned long long clen,
- const unsigned char *n,
- const unsigned char *k)
-{
- return crypto_box_curve25519xsalsa20poly1305_open_afternm(m, c, clen, n, k);
-}
-
-#undef crypto_box_curve25519xsalsa20poly1305_ref
-SODIUM_EXPORT int
-crypto_box_curve25519xsalsa20poly1305_ref(unsigned char *c,
- const unsigned char *m,
- unsigned long long mlen,
- const unsigned char *n,
- const unsigned char *pk,
- const unsigned char *sk)
-{
- return crypto_box_curve25519xsalsa20poly1305(c, m, mlen, n, pk, sk);
-}
-
-#undef crypto_box_curve25519xsalsa20poly1305_ref_open
-SODIUM_EXPORT int
-crypto_box_curve25519xsalsa20poly1305_ref_open(unsigned char *m,
- const unsigned char *c,
- unsigned long long clen,
- const unsigned char *n,
- const unsigned char *pk,
- const unsigned char *sk)
-{
- return crypto_box_curve25519xsalsa20poly1305_open(m, c, clen, n, pk, sk);
-}
-
-#undef crypto_scalarmult_curve25519_ref_base
-SODIUM_EXPORT int
-crypto_scalarmult_curve25519_ref_base(unsigned char *q, const unsigned char *n)
-{
- return crypto_scalarmult_curve25519_base(q, n);
-}
-
-#undef crypto_scalarmult_curve25519_ref
-SODIUM_EXPORT int
-crypto_scalarmult_curve25519_ref(unsigned char *q, const unsigned char *n,
- const unsigned char *p)
-{
- return crypto_scalarmult_curve25519(q, n, p);
-}
-
-#undef crypto_scalarmult_curve25519_donna_c64_base
-SODIUM_EXPORT int
-crypto_scalarmult_curve25519_donna_c64_base(unsigned char *q, const unsigned char *n)
-{
- return crypto_scalarmult_curve25519_base(q, n);
-}
-
-#undef crypto_scalarmult_curve25519_donna_c64
-SODIUM_EXPORT int
-crypto_scalarmult_curve25519_donna_c64(unsigned char *q, const unsigned char *n,
- const unsigned char *p)
-{
- return crypto_scalarmult_curve25519(q, n, p);
-}
-
-#undef crypto_secretbox_xsalsa20poly1305_ref
-SODIUM_EXPORT int
-crypto_secretbox_xsalsa20poly1305_ref(unsigned char *c,
- const unsigned char *m,
- unsigned long long mlen,
- const unsigned char *n,
- const unsigned char *k)
-{
- return crypto_secretbox_xsalsa20poly1305(c, m, mlen, n, k);
-}
-
-#undef crypto_secretbox_xsalsa20poly1305_ref_open
-SODIUM_EXPORT int
-crypto_secretbox_xsalsa20poly1305_ref_open(unsigned char *m,
- const unsigned char *c,
- unsigned long long clen,
- const unsigned char *n,
- const unsigned char *k)
-{
- return crypto_secretbox_xsalsa20poly1305_open(m, c, clen, n, k);
-}
-
-#undef crypto_sign_ed25519_ref_seed_keypair
-SODIUM_EXPORT int
-crypto_sign_ed25519_ref_seed_keypair(unsigned char *pk, unsigned char *sk,
- const unsigned char *seed)
-{
- return crypto_sign_ed25519_seed_keypair(pk, sk, seed);
-}
-
-#undef crypto_sign_ed25519_ref_keypair
-SODIUM_EXPORT int
-crypto_sign_ed25519_ref_keypair(unsigned char *pk, unsigned char *sk)
-{
- return crypto_sign_ed25519_keypair(pk, sk);
-}
-
-#undef crypto_sign_ed25519_ref
-SODIUM_EXPORT int
-crypto_sign_ed25519_ref(unsigned char *sm, unsigned long long *smlen,
- const unsigned char *m, unsigned long long mlen,
- const unsigned char *sk)
-{
- return crypto_sign_ed25519(sm, smlen, m, mlen, sk);
-}
-
-#undef crypto_sign_ed25519_ref_open
-SODIUM_EXPORT int
-crypto_sign_ed25519_ref_open(unsigned char *m, unsigned long long *mlen,
- const unsigned char *sm, unsigned long long smlen,
- const unsigned char *pk)
-{
- return crypto_sign_ed25519_open(m, mlen, sm, smlen, pk);
-}
-
-#undef crypto_stream_xsalsa20_ref
-SODIUM_EXPORT int
-crypto_stream_xsalsa20_ref(unsigned char *c, unsigned long long clen,
- const unsigned char *n, const unsigned char *k)
-{
- return crypto_stream_xsalsa20(c, clen, n, k);
-}
-
-#undef crypto_stream_xsalsa20_ref_xor
-SODIUM_EXPORT int
-crypto_stream_xsalsa20_ref_xor(unsigned char *c, const unsigned char *m,
- unsigned long long mlen, const unsigned char *n,
- const unsigned char *k)
-{
- return crypto_stream_xsalsa20_xor(c, m, mlen, n, k);
-}
-
-#undef crypto_verify_16_ref
-SODIUM_EXPORT int
-crypto_verify_16_ref(const unsigned char *x, const unsigned char *y)
-{
- return crypto_verify_16(x, y);
-}
-
-#undef crypto_verify_32_ref
-SODIUM_EXPORT int
-crypto_verify_32_ref(const unsigned char *x, const unsigned char *y)
-{
- return crypto_verify_32(x, y);
-}
-
-#undef crypto_onetimeauth_poly1305_ref
-SODIUM_EXPORT int
-crypto_onetimeauth_poly1305_ref(unsigned char *out,
- const unsigned char *in,
- unsigned long long inlen,
- const unsigned char *k)
-{
- return crypto_onetimeauth_poly1305(out, in, inlen, k);
-}
-
-#undef crypto_stream_salsa20_amd64_xmm6
-SODIUM_EXPORT int
-crypto_stream_salsa20_amd64_xmm6(unsigned char *c,
- unsigned long long clen,
- const unsigned char *n,
- const unsigned char *k)
-{
- return crypto_stream_salsa20(c, clen, n, k);
-}
-
-#undef crypto_stream_salsa20_ref
-SODIUM_EXPORT int
-crypto_stream_salsa20_ref(unsigned char *c,
- unsigned long long clen,
- const unsigned char *n,
- const unsigned char *k)
-{
- return crypto_stream_salsa20(c, clen, n, k);
-}
-
-#undef crypto_stream_salsa20_amd64_xmm6_xor
-SODIUM_EXPORT int
-crypto_stream_salsa20_amd64_xmm6_xor(unsigned char *c,
- const unsigned char *m,
- unsigned long long mlen,
- const unsigned char *n,
- const unsigned char *k)
-{
- return crypto_stream_salsa20_xor(c, m, mlen, n, k);
-}
-
-#undef crypto_stream_salsa20_ref_xor
-SODIUM_EXPORT int
-crypto_stream_salsa20_ref_xor(unsigned char *c,
- const unsigned char *m,
- unsigned long long mlen,
- const unsigned char *n,
- const unsigned char *k)
-{
- return crypto_stream_salsa20_xor(c, m, mlen, n, k);
-}
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/libsodium/sodium/core.c b/src/libsodium/sodium/core.c
index 652f31e..367f275 100644
--- a/src/libsodium/sodium/core.c
+++ b/src/libsodium/sodium/core.c
@@ -3,6 +3,7 @@
#include "crypto_onetimeauth.h"
#include "randombytes.h"
#include "runtime.h"
+#include "utils.h"
static int initialized;
@@ -14,9 +15,10 @@ sodium_init(void)
}
sodium_runtime_get_cpu_features();
if (crypto_onetimeauth_pick_best_implementation() == NULL) {
- return -1;
+ return -1; /* LCOV_EXCL_LINE */
}
randombytes_stir();
+ _sodium_alloc_init();
initialized = 1;
return 0;
diff --git a/src/libsodium/sodium/runtime.c b/src/libsodium/sodium/runtime.c
index 52b3707..3e424a0 100644
--- a/src/libsodium/sodium/runtime.c
+++ b/src/libsodium/sodium/runtime.c
@@ -44,7 +44,7 @@ static void
_cpuid(unsigned int cpu_info[4U], const unsigned int cpu_info_type)
{
#ifdef _MSC_VER
- __cpuidex((int *) cpu_info, cpu_info_type, 0);
+ __cpuid((int *) cpu_info, cpu_info_type);
#elif defined(HAVE_CPUID)
cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0;
# ifdef __i386__
@@ -56,7 +56,7 @@ _cpuid(unsigned int cpu_info[4U], const unsigned int cpu_info_type)
"=&r" (cpu_info[0]), "=&r" (cpu_info[1]) :
"i" (0x200000));
if (((cpu_info[0] ^ cpu_info[1]) & 0x200000) == 0x0) {
- return;
+ return; /* LCOV_EXCL_LINE */
}
# endif
# ifdef __i386__
@@ -88,7 +88,7 @@ _sodium_runtime_intel_cpu_features(CPUFeatures * const cpu_features)
_cpuid(cpu_info, 0x0);
if ((id = cpu_info[0]) == 0U) {
- return -1;
+ return -1; /* LCOV_EXCL_LINE */
}
_cpuid(cpu_info, 0x00000001);
#ifndef HAVE_EMMINTRIN_H
diff --git a/src/libsodium/sodium/utils.c b/src/libsodium/sodium/utils.c
index eff9d0c..e51ae6b 100644
--- a/src/libsodium/sodium/utils.c
+++ b/src/libsodium/sodium/utils.c
@@ -1,8 +1,10 @@
#ifndef __STDC_WANT_LIB_EXT1__
# define __STDC_WANT_LIB_EXT1__ 1
#endif
+#include <assert.h>
#include <errno.h>
#include <limits.h>
+#include <signal.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
@@ -17,8 +19,32 @@
#ifdef _WIN32
# include <windows.h>
# include <wincrypt.h>
+#else
+# include <unistd.h>
+#endif
+
+#define CANARY_SIZE 16U
+#define GARBAGE_VALUE 0xd0
+
+#ifndef MAP_NOCORE
+# define MAP_NOCORE 0
+#endif
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+#endif
+#if defined(_WIN32) || defined(MAP_ANON) || defined(HAVE_POSIX_MEMALIGN)
+# define HAVE_ALIGNED_MALLOC
+#endif
+#if defined(HAVE_MPROTECT) && !(defined(PROT_NONE) && defined(PROT_READ) && defined(PROT_WRITE))
+# undef HAVE_MPROTECT
+#endif
+#if defined(HAVE_ALIGNED_MALLOC) && (defined(_WIN32) || defined(HAVE_MPROTECT))
+# define HAVE_PAGE_PROTECTION
#endif
+static size_t page_size;
+static unsigned char canary[CANARY_SIZE];
+
#ifdef HAVE_WEAK_SYMBOLS
__attribute__((weak)) void
__sodium_dummy_symbol_to_prevent_lto(void * const pnt, const size_t len)
@@ -31,11 +57,11 @@ __sodium_dummy_symbol_to_prevent_lto(void * const pnt, const size_t len)
void
sodium_memzero(void * const pnt, const size_t len)
{
-#ifdef HAVE_SECUREZEROMEMORY
+#ifdef _WIN32
SecureZeroMemory(pnt, len);
#elif defined(HAVE_MEMSET_S)
if (memset_s(pnt, (rsize_t) len, 0, (rsize_t) len) != 0) {
- abort();
+ abort(); /* LCOV_EXCL_LINE */
}
#elif defined(HAVE_EXPLICIT_BZERO)
explicit_bzero(pnt, len);
@@ -66,34 +92,6 @@ sodium_memcmp(const void * const b1_, const void * const b2_, size_t len)
return (int) ((1 & ((d - 1) >> 8)) - 1);
}
-unsigned char *
-_sodium_alignedcalloc(unsigned char ** const unaligned_p, const size_t len)
-{
- unsigned char *aligned;
- unsigned char *unaligned;
- size_t i;
-
- if (SIZE_MAX - (size_t) 256U < len ||
- (unaligned = (unsigned char *) malloc(len + (size_t) 256U)) == NULL) {
- *unaligned_p = NULL;
- return NULL;
- }
- *unaligned_p = unaligned;
-#ifdef HAVE_ARC4RANDOM_BUF
- (void) i;
- arc4random_buf(unaligned, len + (size_t) 256U);
-#else
- for (i = (size_t) 0U; i < len + (size_t) 256U; ++i) {
- unaligned[i] = (unsigned char) rand();
- }
-#endif
- aligned = unaligned + 64;
- aligned += (ptrdiff_t) 63 & (-(ptrdiff_t) aligned);
- memset(aligned, 0, len);
-
- return aligned;
-}
-
char *
sodium_bin2hex(char * const hex, const size_t hex_maxlen,
const unsigned char * const bin, const size_t bin_len)
@@ -106,7 +104,7 @@ sodium_bin2hex(char * const hex, const size_t hex_maxlen,
size_t j = (size_t) 0U;
if (bin_len >= SIZE_MAX / 2 || hex_maxlen < bin_len * 2U) {
- abort();
+ abort(); /* LCOV_EXCL_LINE */
}
while (i < bin_len) {
hex[j++] = hexdigits[bin[i] >> 4];
@@ -178,7 +176,7 @@ sodium_mlock(void * const addr, const size_t len)
#endif
#ifdef HAVE_MLOCK
return mlock(addr, len);
-#elif defined(HAVE_VIRTUALLOCK)
+#elif defined(_WIN32)
return -(VirtualLock(addr, len) == 0);
#else
errno = ENOSYS;
@@ -195,10 +193,286 @@ sodium_munlock(void * const addr, const size_t len)
#endif
#ifdef HAVE_MLOCK
return munlock(addr, len);
-#elif defined(HAVE_VIRTUALLOCK)
+#elif defined(_WIN32)
return -(VirtualUnlock(addr, len) == 0);
#else
errno = ENOSYS;
return -1;
#endif
}
+
+int
+_sodium_alloc_init(void)
+{
+#if defined(_SC_PAGESIZE)
+ long page_size_ = sysconf(_SC_PAGESIZE);
+ if (page_size_ > 0L) {
+ page_size = (size_t) page_size_;
+ }
+#elif defined(_WIN32)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ page_size = (size_t) si.dwPageSize;
+#endif
+ if (page_size < CANARY_SIZE) {
+ abort(); /* LCOV_EXCL_LINE */
+ }
+ randombytes_buf(canary, sizeof canary);
+
+ return 0;
+}
+
+static inline size_t
+_page_round(const size_t size)
+{
+ const size_t page_mask = page_size - 1U;
+
+ return (size + page_mask) & ~page_mask;
+}
+
+static int
+_mprotect_noaccess(void *ptr, size_t size)
+{
+#if defined(HAVE_MPROTECT) && defined(HAVE_PAGE_PROTECTION)
+ return mprotect(ptr, size, PROT_NONE);
+#elif defined(_WIN32)
+ {
+ DWORD old;
+ return -(VirtualProtect(ptr, size, PAGE_NOACCESS, &old) == 0);
+ }
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static int
+_mprotect_readonly(void *ptr, size_t size)
+{
+#if defined(HAVE_MPROTECT) && defined(HAVE_PAGE_PROTECTION)
+ return mprotect(ptr, size, PROT_READ);
+#elif defined(_WIN32)
+ {
+ DWORD old;
+ return -(VirtualProtect(ptr, size, PAGE_READONLY, &old) == 0);
+ }
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static int
+_mprotect_readwrite(void *ptr, size_t size)
+{
+#if defined(HAVE_MPROTECT) && defined(HAVE_PAGE_PROTECTION)
+ return mprotect(ptr, size, PROT_READ | PROT_WRITE);
+#elif defined(_WIN32)
+ {
+ DWORD old;
+ return -(VirtualProtect(ptr, size, PAGE_READWRITE, &old) == 0);
+ }
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static void
+_out_of_bounds(void)
+{
+#ifdef SIGSEGV
+ raise(SIGSEGV);
+#elif defined(SIGKILL)
+ raise(SIGKILL);
+#endif
+ abort();
+} /* LCOV_EXCL_LINE */
+
+static __attribute__((malloc)) unsigned char *
+_alloc_aligned(const size_t size)
+{
+ void *ptr;
+
+#ifdef MAP_ANON
+ if ((ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE, -1, 0)) == MAP_FAILED) {
+ ptr = NULL; /* LCOV_EXCL_LINE */
+ } /* LCOV_EXCL_LINE */
+#elif defined(HAVE_POSIX_MEMALIGN)
+ if (posix_memalign(&ptr, page_size, size) != 0) {
+ ptr = NULL; /* LCOV_EXCL_LINE */
+ } /* LCOV_EXCL_LINE */
+#elif defined(_WIN32)
+ ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+#elif !defined(HAVE_ALIGNED_MALLOC)
+ ptr = malloc(size);
+#else
+# error Bug
+#endif
+ return (unsigned char *) ptr;
+}
+
+static void
+_free_aligned(unsigned char * const ptr, const size_t size)
+{
+#ifdef MAP_ANON
+ (void) munmap(ptr, size);
+#elif defined(HAVE_POSIX_MEMALIGN)
+ free(ptr);
+#elif defined(_WIN32)
+ VirtualFree(ptr, 0U, MEM_RELEASE);
+#else
+ free(ptr);
+#endif
+}
+
+static unsigned char *
+_unprotected_ptr_from_user_ptr(const void *ptr)
+{
+ uintptr_t unprotected_ptr_u;
+ unsigned char *canary_ptr;
+ size_t page_mask;
+
+ canary_ptr = ((unsigned char *) ptr) - sizeof canary;
+ page_mask = page_size - 1U;
+ unprotected_ptr_u = ((uintptr_t) canary_ptr & (uintptr_t) ~page_mask);
+ if (unprotected_ptr_u <= page_size * 2U) {
+ abort(); /* LCOV_EXCL_LINE */
+ }
+ return (unsigned char *) unprotected_ptr_u;
+}
+
+static __attribute__((malloc)) void *
+_sodium_malloc(const size_t size)
+{
+ void *user_ptr;
+ unsigned char *base_ptr;
+ unsigned char *canary_ptr;
+ unsigned char *unprotected_ptr;
+ size_t page_mask;
+ size_t size_with_canary;
+ size_t total_size;
+ size_t unprotected_size;
+
+ if (size >= SIZE_MAX - page_size * 4U) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ if (page_size <= sizeof canary || page_size < sizeof unprotected_size) {
+ abort(); /* LCOV_EXCL_LINE */
+ }
+ size_with_canary = (sizeof canary) + size;
+ unprotected_size = _page_round(size_with_canary);
+ total_size = page_size + page_size + unprotected_size + page_size;
+ if ((base_ptr = _alloc_aligned(total_size)) == NULL) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ unprotected_ptr = base_ptr + page_size * 2U;
+ _mprotect_noaccess(base_ptr + page_size, page_size);
+#ifndef HAVE_PAGE_PROTECTION
+ memcpy(unprotected_ptr + unprotected_size, canary, sizeof canary);
+#endif
+ _mprotect_noaccess(unprotected_ptr + unprotected_size, page_size);
+ sodium_mlock(unprotected_ptr, unprotected_size);
+ page_mask = page_size - 1U;
+ canary_ptr = unprotected_ptr + _page_round(size_with_canary) -
+ size_with_canary;
+ user_ptr = canary_ptr + sizeof canary;
+ memcpy(canary_ptr, canary, sizeof canary);
+ memcpy(base_ptr, &unprotected_size, sizeof unprotected_size);
+ _mprotect_readonly(base_ptr, page_size);
+ assert(_unprotected_ptr_from_user_ptr(user_ptr) == unprotected_ptr);
+
+ return user_ptr;
+}
+
+__attribute__((malloc)) void *
+sodium_malloc(const size_t size)
+{
+ void *ptr;
+
+ if ((ptr = _sodium_malloc(size)) == NULL) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ memset(ptr, (int) GARBAGE_VALUE, size);
+
+ return ptr;
+}
+
+__attribute__((malloc)) void *
+sodium_allocarray(size_t count, size_t size)
+{
+ size_t total_size;
+
+ if (size >= SIZE_MAX / count) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ total_size = count * size;
+
+ return sodium_malloc(total_size);
+}
+
+void
+sodium_free(void *ptr)
+{
+ unsigned char *base_ptr;
+ unsigned char *canary_ptr;
+ unsigned char *unprotected_ptr;
+ size_t total_size;
+ size_t unprotected_size;
+
+ if (ptr == NULL) {
+ return;
+ }
+ canary_ptr = ((unsigned char *) ptr) - sizeof canary;
+ if (sodium_memcmp(canary_ptr, canary, sizeof canary) != 0) {
+ _out_of_bounds();
+ }
+ unprotected_ptr = _unprotected_ptr_from_user_ptr(ptr);
+ base_ptr = unprotected_ptr - page_size * 2U;
+ memcpy(&unprotected_size, base_ptr, sizeof unprotected_size);
+ total_size = page_size + page_size + unprotected_size + page_size;
+ _mprotect_readwrite(base_ptr, total_size);
+#ifndef HAVE_PAGE_PROTECTION
+ if (sodium_memcmp(unprotected_ptr + unprotected_size,
+ canary, sizeof canary) != 0) {
+ _out_of_bounds();
+ }
+#endif
+ sodium_munlock(unprotected_ptr, unprotected_size);
+ _free_aligned(base_ptr, total_size);
+}
+
+static int
+_sodium_mprotect(void *ptr, int (*cb)(void *ptr, size_t size))
+{
+ unsigned char *base_ptr;
+ unsigned char *unprotected_ptr;
+ size_t unprotected_size;
+
+ unprotected_ptr = _unprotected_ptr_from_user_ptr(ptr);
+ base_ptr = unprotected_ptr - page_size * 2U;
+ memcpy(&unprotected_size, base_ptr, sizeof unprotected_size);
+
+ return cb(unprotected_ptr, unprotected_size);
+}
+
+int
+sodium_mprotect_noaccess(void *ptr)
+{
+ return _sodium_mprotect(ptr, _mprotect_noaccess);
+}
+
+int
+sodium_mprotect_readonly(void *ptr)
+{
+ return _sodium_mprotect(ptr, _mprotect_readonly);
+}
+
+int
+sodium_mprotect_readwrite(void *ptr)
+{
+ return _sodium_mprotect(ptr, _mprotect_readwrite);
+}