aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/compat/sodium/sodium_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/compat/sodium/sodium_utils.cpp')
-rw-r--r--src/lib/compat/sodium/sodium_utils.cpp160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/lib/compat/sodium/sodium_utils.cpp b/src/lib/compat/sodium/sodium_utils.cpp
new file mode 100644
index 000000000..208355583
--- /dev/null
+++ b/src/lib/compat/sodium/sodium_utils.cpp
@@ -0,0 +1,160 @@
+/*
+* (C) 2019 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/sodium.h>
+#include <botan/chacha.h>
+#include <botan/mem_ops.h>
+#include <botan/system_rng.h>
+#include <botan/internal/os_utils.h>
+#include <botan/internal/ct_utils.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+void Sodium::randombytes_buf(void* buf, size_t len)
+ {
+ system_rng().randomize(static_cast<uint8_t*>(buf), len);
+ }
+
+uint32_t Sodium::randombytes_uniform(uint32_t upper_bound)
+ {
+ if(upper_bound <= 1)
+ return 0;
+
+ // Not completely uniform
+ uint64_t x;
+ randombytes_buf(&x, sizeof(x));
+ return x % upper_bound;
+ }
+
+void Sodium::randombytes_buf_deterministic(void* buf, size_t size, const uint8_t seed[randombytes_SEEDBYTES])
+ {
+ const unsigned char nonce[12] = {
+ 'L', 'i', 'b', 's', 'o', 'd', 'i', 'u', 'm', 'D', 'R', 'G'
+ };
+
+ ChaCha chacha(20);
+ chacha.set_key(seed, randombytes_SEEDBYTES);
+ chacha.set_iv(nonce, sizeof(nonce));
+ chacha.write_keystream(static_cast<uint8_t*>(buf), size);
+ }
+
+int Sodium::crypto_verify_16(const uint8_t* x, const uint8_t* y)
+ {
+ return same_mem(x, y, 16);
+ }
+
+int Sodium::crypto_verify_32(const uint8_t* x, const uint8_t* y)
+ {
+ return same_mem(x, y, 32);
+ }
+
+int Sodium::crypto_verify_64(const uint8_t* x, const uint8_t* y)
+ {
+ return same_mem(x, y, 64);
+ }
+
+void Sodium::sodium_memzero(void* ptr, size_t len)
+ {
+ secure_scrub_memory(ptr, len);
+ }
+
+int Sodium::sodium_memcmp(const void* x, const void* y, size_t len)
+ {
+ const bool same = constant_time_compare(static_cast<const uint8_t*>(x), static_cast<const uint8_t*>(y), len);
+ return same ? 0 : -1;
+ }
+
+int Sodium::sodium_compare(const uint8_t x[], const uint8_t y[], size_t len)
+ {
+ const uint8_t LT = static_cast<uint8_t>(-1);
+ const uint8_t EQ = 0;
+ const uint8_t GT = 1;
+
+ uint8_t result = EQ; // until found otherwise
+
+ for(size_t i = 0; i != len; ++i)
+ {
+ const auto is_eq = CT::Mask<uint8_t>::is_equal(x[i], y[i]);
+ const auto is_lt = CT::Mask<uint8_t>::is_lt(x[i], y[i]);
+ result = is_eq.select(result, is_lt.select(LT, GT));
+ }
+
+ return static_cast<int8_t>(result);
+ }
+
+int Sodium::sodium_is_zero(const uint8_t b[], size_t len)
+ {
+ uint8_t sum = 0;
+ for(size_t i = 0; i != len; ++i)
+ sum |= b[i];
+ return static_cast<int>(CT::Mask<uint8_t>::expand(sum).if_not_set_return(1));
+ }
+
+void Sodium::sodium_increment(uint8_t b[], size_t len)
+ {
+ uint8_t carry = 1;
+ for(size_t i = 0; i != len; ++i)
+ {
+ b[i] += carry;
+ carry &= (b[i] == 0);
+ }
+ }
+
+void Sodium::sodium_add(uint8_t a[], const uint8_t b[], size_t len)
+ {
+ uint8_t carry = 0;
+ for(size_t i = 0; i != len; ++i)
+ {
+ a[i] += b[i] + carry;
+ carry = (a[i] < b[i]);
+ }
+ }
+
+void* Sodium::sodium_malloc(size_t size)
+ {
+ const uint64_t len = size;
+
+ if(size + sizeof(len) < size)
+ return nullptr;
+
+ uint8_t* p = static_cast<uint8_t*>(std::calloc(size + sizeof(len), 1));
+ store_le(len, p);
+ return p + 8;
+ }
+
+void Sodium::sodium_free(void* ptr)
+ {
+ if(ptr == nullptr)
+ return;
+
+ uint8_t* p = static_cast<uint8_t*>(ptr) - 8;
+ const uint64_t len = load_le<uint64_t>(p, 0);
+ secure_scrub_memory(ptr, len);
+ std::free(p);
+ }
+
+void* Sodium::sodium_allocarray(size_t count, size_t size)
+ {
+ const size_t bytes = count * size;
+ if(bytes < count || bytes < size)
+ return nullptr;
+ return sodium_malloc(bytes);
+ }
+
+int Sodium::sodium_mprotect_noaccess(void* ptr)
+ {
+ OS::page_prohibit_access(ptr);
+ return 0;
+ }
+
+int Sodium::sodium_mprotect_readwrite(void* ptr)
+ {
+ OS::page_allow_access(ptr);
+ return 0;
+ }
+
+}