1 /*
2 * (C) 2019 Jack Lloyd
3 *
4 * Botan is released under the Simplified BSD License (see license.txt)
5 */
6 
7 #include <botan/sodium.h>
8 #include <botan/chacha.h>
9 #include <botan/mem_ops.h>
10 #include <botan/system_rng.h>
11 #include <botan/internal/os_utils.h>
12 #include <botan/internal/ct_utils.h>
13 #include <botan/loadstor.h>
14 
15 namespace Botan {
16 
randombytes_buf(void * buf,size_t len)17 void Sodium::randombytes_buf(void* buf, size_t len)
18    {
19    system_rng().randomize(static_cast<uint8_t*>(buf), len);
20    }
21 
randombytes_uniform(uint32_t upper_bound)22 uint32_t Sodium::randombytes_uniform(uint32_t upper_bound)
23    {
24    if(upper_bound <= 1)
25       return 0;
26 
27    // Not completely uniform
28    uint64_t x;
29    randombytes_buf(&x, sizeof(x));
30    return x % upper_bound;
31    }
32 
randombytes_buf_deterministic(void * buf,size_t size,const uint8_t seed[randombytes_SEEDBYTES])33 void Sodium::randombytes_buf_deterministic(void* buf, size_t size, const uint8_t seed[randombytes_SEEDBYTES])
34    {
35    const unsigned char nonce[12] = {
36       'L', 'i', 'b', 's', 'o', 'd', 'i', 'u', 'm', 'D', 'R', 'G'
37    };
38 
39    ChaCha chacha(20);
40    chacha.set_key(seed, randombytes_SEEDBYTES);
41    chacha.set_iv(nonce, sizeof(nonce));
42    chacha.write_keystream(static_cast<uint8_t*>(buf), size);
43    }
44 
crypto_verify_16(const uint8_t x[16],const uint8_t y[16])45 int Sodium::crypto_verify_16(const uint8_t x[16], const uint8_t y[16])
46    {
47    return same_mem(x, y, 16);
48    }
49 
crypto_verify_32(const uint8_t x[32],const uint8_t y[32])50 int Sodium::crypto_verify_32(const uint8_t x[32], const uint8_t y[32])
51    {
52    return same_mem(x, y, 32);
53    }
54 
crypto_verify_64(const uint8_t x[64],const uint8_t y[64])55 int Sodium::crypto_verify_64(const uint8_t x[64], const uint8_t y[64])
56    {
57    return same_mem(x, y, 64);
58    }
59 
sodium_memzero(void * ptr,size_t len)60 void Sodium::sodium_memzero(void* ptr, size_t len)
61    {
62    secure_scrub_memory(ptr, len);
63    }
64 
sodium_memcmp(const void * x,const void * y,size_t len)65 int Sodium::sodium_memcmp(const void* x, const void* y, size_t len)
66    {
67    const bool same = constant_time_compare(static_cast<const uint8_t*>(x), static_cast<const uint8_t*>(y), len);
68    return same ? 0 : -1;
69    }
70 
sodium_compare(const uint8_t x[],const uint8_t y[],size_t len)71 int Sodium::sodium_compare(const uint8_t x[], const uint8_t y[], size_t len)
72    {
73    const uint8_t LT = static_cast<uint8_t>(-1);
74    const uint8_t EQ = 0;
75    const uint8_t GT = 1;
76 
77    uint8_t result = EQ; // until found otherwise
78 
79    for(size_t i = 0; i != len; ++i)
80       {
81       const auto is_eq = CT::Mask<uint8_t>::is_equal(x[i], y[i]);
82       const auto is_lt = CT::Mask<uint8_t>::is_lt(x[i], y[i]);
83       result = is_eq.select(result, is_lt.select(LT, GT));
84       }
85 
86    return static_cast<int8_t>(result);
87    }
88 
sodium_is_zero(const uint8_t b[],size_t len)89 int Sodium::sodium_is_zero(const uint8_t b[], size_t len)
90    {
91    uint8_t sum = 0;
92    for(size_t i = 0; i != len; ++i)
93       sum |= b[i];
94    return static_cast<int>(CT::Mask<uint8_t>::expand(sum).if_not_set_return(1));
95    }
96 
sodium_increment(uint8_t b[],size_t len)97 void Sodium::sodium_increment(uint8_t b[], size_t len)
98    {
99    uint8_t carry = 1;
100    for(size_t i = 0; i != len; ++i)
101       {
102       b[i] += carry;
103       carry &= (b[i] == 0);
104       }
105    }
106 
sodium_add(uint8_t a[],const uint8_t b[],size_t len)107 void Sodium::sodium_add(uint8_t a[], const uint8_t b[], size_t len)
108    {
109    uint8_t carry = 0;
110    for(size_t i = 0; i != len; ++i)
111       {
112       a[i] += b[i] + carry;
113       carry = (a[i] < b[i]);
114       }
115    }
116 
sodium_malloc(size_t size)117 void* Sodium::sodium_malloc(size_t size)
118    {
119    const uint64_t len = size;
120 
121    if(size + sizeof(len) < size)
122       return nullptr;
123 
124    uint8_t* p = static_cast<uint8_t*>(std::calloc(size + sizeof(len), 1));
125    store_le(len, p);
126    return p + 8;
127    }
128 
sodium_free(void * ptr)129 void Sodium::sodium_free(void* ptr)
130    {
131    if(ptr == nullptr)
132       return;
133 
134    uint8_t* p = static_cast<uint8_t*>(ptr) - 8;
135    const uint64_t len = load_le<uint64_t>(p, 0);
136    secure_scrub_memory(ptr, static_cast<size_t>(len));
137    std::free(p);
138    }
139 
sodium_allocarray(size_t count,size_t size)140 void* Sodium::sodium_allocarray(size_t count, size_t size)
141    {
142    const size_t bytes = count * size;
143    if(bytes < count || bytes < size)
144       return nullptr;
145    return sodium_malloc(bytes);
146    }
147 
sodium_mprotect_noaccess(void * ptr)148 int Sodium::sodium_mprotect_noaccess(void* ptr)
149    {
150    OS::page_prohibit_access(ptr);
151    return 0;
152    }
153 
sodium_mprotect_readwrite(void * ptr)154 int Sodium::sodium_mprotect_readwrite(void* ptr)
155    {
156    OS::page_allow_access(ptr);
157    return 0;
158    }
159 
160 }
161