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 30static 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 44static void 45randombytes_init_if_needed(void) 46{ 47 if (implementation == NULL) { 48 implementation = RANDOMBYTES_DEFAULT_IMPLEMENTATION; 49 randombytes_stir(); 50 } 51} 52 53int 54randombytes_set_implementation(randombytes_implementation *impl) 55{ 56 implementation = impl; 57 58 return 0; 59} 60 61const char * 62randombytes_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 72uint32_t 73randombytes_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 85void 86randombytes_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 124uint32_t 125randombytes_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 149void 150randombytes_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 167void 168randombytes_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 186size_t 187randombytes_seedbytes(void) 188{ 189 return randombytes_SEEDBYTES; 190} 191 192int 193randombytes_close(void) 194{ 195 if (implementation != NULL && implementation->close != NULL) { 196 return implementation->close(); 197 } 198 return 0; 199} 200 201void 202randombytes(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