1 2 #include <assert.h> 3 #include <limits.h> 4 #include <stdint.h> 5 #include <stdlib.h> 6 7 #include <sys/types.h> 8 9 #ifdef __EMSCRIPTEN__ 10 # include <emscripten.h> 11 #endif 12 13 #include "core.h" 14 #include "crypto_stream_chacha20.h" 15 #include "randombytes.h" 16 #ifdef RANDOMBYTES_DEFAULT_IMPLEMENTATION 17 # include "randombytes_default.h" 18 #else 19 # ifdef __native_client__ 20 # include "randombytes_nativeclient.h" 21 # else 22 # include "randombytes_sysrandom.h" 23 # endif 24 #endif 25 #include "private/common.h" 26 27 /* C++Builder defines a "random" macro */ 28 #undef random 29 30 static const randombytes_implementation *implementation; 31 32 #ifndef RANDOMBYTES_DEFAULT_IMPLEMENTATION 33 # ifdef __EMSCRIPTEN__ 34 # define RANDOMBYTES_DEFAULT_IMPLEMENTATION NULL 35 # else 36 # ifdef __native_client__ 37 # define RANDOMBYTES_DEFAULT_IMPLEMENTATION &randombytes_nativeclient_implementation; 38 # else 39 # define RANDOMBYTES_DEFAULT_IMPLEMENTATION &randombytes_sysrandom_implementation; 40 # endif 41 # endif 42 #endif 43 44 static void 45 randombytes_init_if_needed(void) 46 { 47 if (implementation == NULL) { 48 implementation = RANDOMBYTES_DEFAULT_IMPLEMENTATION; 49 randombytes_stir(); 50 } 51 } 52 53 int 54 randombytes_set_implementation(randombytes_implementation *impl) 55 { 56 implementation = impl; 57 58 return 0; 59 } 60 61 const char * 62 randombytes_implementation_name(void) 63 { 64 #ifndef __EMSCRIPTEN__ 65 randombytes_init_if_needed(); 66 return implementation->implementation_name(); 67 #else 68 return "js"; 69 #endif 70 } 71 72 uint32_t 73 randombytes_random(void) 74 { 75 #ifndef __EMSCRIPTEN__ 76 randombytes_init_if_needed(); 77 return implementation->random(); 78 #else 79 return EM_ASM_INT_V({ 80 return Module.getRandomValue(); 81 }); 82 #endif 83 } 84 85 void 86 randombytes_stir(void) 87 { 88 #ifndef __EMSCRIPTEN__ 89 randombytes_init_if_needed(); 90 if (implementation->stir != NULL) { 91 implementation->stir(); 92 } 93 #else 94 EM_ASM({ 95 if (Module.getRandomValue === undefined) { 96 try { 97 var window_ = 'object' === typeof window ? window : self; 98 var crypto_ = typeof window_.crypto !== 'undefined' ? window_.crypto : window_.msCrypto; 99 var randomValuesStandard = function() { 100 var buf = new Uint32Array(1); 101 crypto_.getRandomValues(buf); 102 return buf[0] >>> 0; 103 }; 104 randomValuesStandard(); 105 Module.getRandomValue = randomValuesStandard; 106 } catch (e) { 107 try { 108 var crypto = require('crypto'); 109 var randomValueNodeJS = function() { 110 var buf = crypto['randomBytes'](4); 111 return (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]) >>> 0; 112 }; 113 randomValueNodeJS(); 114 Module.getRandomValue = randomValueNodeJS; 115 } catch (e) { 116 throw 'No secure random number generator found'; 117 } 118 } 119 } 120 }); 121 #endif 122 } 123 124 uint32_t 125 randombytes_uniform(const uint32_t upper_bound) 126 { 127 uint32_t min; 128 uint32_t r; 129 130 #ifndef __EMSCRIPTEN__ 131 randombytes_init_if_needed(); 132 if (implementation->uniform != NULL) { 133 return implementation->uniform(upper_bound); 134 } 135 #endif 136 if (upper_bound < 2) { 137 return 0; 138 } 139 min = (1U + ~upper_bound) % upper_bound; /* = 2**32 mod upper_bound */ 140 do { 141 r = randombytes_random(); 142 } while (r < min); 143 /* r is now clamped to a set whose size mod upper_bound == 0 144 * the worst case (2**31+1) requires ~ 2 attempts */ 145 146 return r % upper_bound; 147 } 148 149 void 150 randombytes_buf(void * const buf, const size_t size) 151 { 152 #ifndef __EMSCRIPTEN__ 153 randombytes_init_if_needed(); 154 if (size > (size_t) 0U) { 155 implementation->buf(buf, size); 156 } 157 #else 158 unsigned char *p = (unsigned char *) buf; 159 size_t i; 160 161 for (i = (size_t) 0U; i < size; i++) { 162 p[i] = (unsigned char) randombytes_random(); 163 } 164 #endif 165 } 166 167 void 168 randombytes_buf_deterministic(void * const buf, const size_t size, 169 const unsigned char seed[randombytes_SEEDBYTES]) 170 { 171 static const unsigned char nonce[crypto_stream_chacha20_ietf_NONCEBYTES] = { 172 'L', 'i', 'b', 's', 'o', 'd', 'i', 'u', 'm', 'D', 'R', 'G' 173 }; 174 175 COMPILER_ASSERT(randombytes_SEEDBYTES == crypto_stream_chacha20_ietf_KEYBYTES); 176 #if SIZE_MAX > 0x4000000000ULL 177 COMPILER_ASSERT(randombytes_BYTES_MAX <= 0x4000000000ULL); 178 if (size > 0x4000000000ULL) { 179 sodium_misuse(); 180 } 181 #endif 182 crypto_stream_chacha20_ietf((unsigned char *) buf, (unsigned long long) size, 183 nonce, seed); 184 } 185 186 size_t 187 randombytes_seedbytes(void) 188 { 189 return randombytes_SEEDBYTES; 190 } 191 192 int 193 randombytes_close(void) 194 { 195 if (implementation != NULL && implementation->close != NULL) { 196 return implementation->close(); 197 } 198 return 0; 199 } 200 201 void 202 randombytes(unsigned char * const buf, const unsigned long long buf_len) 203 { 204 assert(buf_len <= SIZE_MAX); 205 randombytes_buf(buf, (size_t) buf_len); 206 } 207