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