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