dualcone 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,281 @@
1
+ #define hydro_pwhash_ENC_ALGBYTES 1
2
+ #define hydro_pwhash_HASH_ALGBYTES 1
3
+ #define hydro_pwhash_THREADSBYTES 1
4
+ #define hydro_pwhash_OPSLIMITBYTES 8
5
+ #define hydro_pwhash_MEMLIMITBYTES 8
6
+ #define hydro_pwhash_HASHBYTES 32
7
+ #define hydro_pwhash_SALTBYTES 16
8
+ #define hydro_pwhash_PARAMSBYTES \
9
+ (hydro_pwhash_HASH_ALGBYTES + hydro_pwhash_THREADSBYTES + hydro_pwhash_OPSLIMITBYTES + \
10
+ hydro_pwhash_MEMLIMITBYTES + hydro_pwhash_SALTBYTES + hydro_pwhash_HASHBYTES)
11
+ #define hydro_pwhash_ENC_ALG 0x01
12
+ #define hydro_pwhash_HASH_ALG 0x01
13
+ #define hydro_pwhash_CONTEXT "hydro_pw"
14
+
15
+ static int
16
+ _hydro_pwhash_hash(uint8_t out[hydro_random_SEEDBYTES], size_t h_len,
17
+ const uint8_t salt[hydro_pwhash_SALTBYTES], const char *passwd,
18
+ size_t passwd_len, const char ctx[hydro_pwhash_CONTEXTBYTES],
19
+ const uint8_t master_key[hydro_pwhash_MASTERKEYBYTES], uint64_t opslimit,
20
+ size_t memlimit, uint8_t threads)
21
+ {
22
+ _hydro_attr_aligned_(16) uint8_t state[gimli_BLOCKBYTES];
23
+ hydro_hash_state h_st;
24
+ uint8_t tmp64_u8[8];
25
+ uint64_t i;
26
+ uint8_t tmp8;
27
+
28
+ COMPILER_ASSERT(hydro_pwhash_MASTERKEYBYTES >= hydro_hash_KEYBYTES);
29
+ hydro_hash_init(&h_st, ctx, master_key);
30
+
31
+ STORE64_LE(tmp64_u8, (uint64_t) passwd_len);
32
+ hydro_hash_update(&h_st, tmp64_u8, sizeof tmp64_u8);
33
+ hydro_hash_update(&h_st, passwd, passwd_len);
34
+
35
+ hydro_hash_update(&h_st, salt, hydro_pwhash_SALTBYTES);
36
+
37
+ tmp8 = hydro_pwhash_HASH_ALG;
38
+ hydro_hash_update(&h_st, &tmp8, 1);
39
+
40
+ hydro_hash_update(&h_st, &threads, 1);
41
+
42
+ STORE64_LE(tmp64_u8, (uint64_t) memlimit);
43
+ hydro_hash_update(&h_st, tmp64_u8, sizeof tmp64_u8);
44
+
45
+ STORE64_LE(tmp64_u8, (uint64_t) h_len);
46
+ hydro_hash_update(&h_st, tmp64_u8, sizeof tmp64_u8);
47
+
48
+ hydro_hash_final(&h_st, (uint8_t *) (void *) &state, sizeof state);
49
+
50
+ gimli_core_u8(state, 1);
51
+ COMPILER_ASSERT(gimli_RATE >= 8);
52
+ for (i = 0; i < opslimit; i++) {
53
+ mem_zero(state, gimli_RATE);
54
+ STORE64_LE(state, i);
55
+ gimli_core_u8(state, 0);
56
+ }
57
+ mem_zero(state, gimli_RATE);
58
+
59
+ COMPILER_ASSERT(hydro_random_SEEDBYTES == gimli_CAPACITY);
60
+ memcpy(out, state + gimli_RATE, hydro_random_SEEDBYTES);
61
+ hydro_memzero(state, sizeof state);
62
+
63
+ return 0;
64
+ }
65
+
66
+ void
67
+ hydro_pwhash_keygen(uint8_t master_key[hydro_pwhash_MASTERKEYBYTES])
68
+ {
69
+ hydro_random_buf(master_key, hydro_pwhash_MASTERKEYBYTES);
70
+ }
71
+
72
+ int
73
+ hydro_pwhash_deterministic(uint8_t *h, size_t h_len, const char *passwd, size_t passwd_len,
74
+ const char ctx[hydro_pwhash_CONTEXTBYTES],
75
+ const uint8_t master_key[hydro_pwhash_MASTERKEYBYTES], uint64_t opslimit,
76
+ size_t memlimit, uint8_t threads)
77
+ {
78
+ uint8_t seed[hydro_random_SEEDBYTES];
79
+
80
+ COMPILER_ASSERT(sizeof zero >= hydro_pwhash_SALTBYTES);
81
+ COMPILER_ASSERT(sizeof zero >= hydro_pwhash_MASTERKEYBYTES);
82
+
83
+ (void) memlimit;
84
+ if (_hydro_pwhash_hash(seed, h_len, zero, passwd, passwd_len, ctx, master_key, opslimit,
85
+ memlimit, threads) != 0) {
86
+ return -1;
87
+ }
88
+ hydro_random_buf_deterministic(h, h_len, seed);
89
+ hydro_memzero(seed, sizeof seed);
90
+
91
+ return 0;
92
+ }
93
+
94
+ int
95
+ hydro_pwhash_create(uint8_t stored[hydro_pwhash_STOREDBYTES], const char *passwd, size_t passwd_len,
96
+ const uint8_t master_key[hydro_pwhash_MASTERKEYBYTES], uint64_t opslimit,
97
+ size_t memlimit, uint8_t threads)
98
+ {
99
+ uint8_t *const enc_alg = &stored[0];
100
+ uint8_t *const secretbox = &enc_alg[hydro_pwhash_ENC_ALGBYTES];
101
+ uint8_t *const hash_alg = &secretbox[hydro_secretbox_HEADERBYTES];
102
+ uint8_t *const threads_u8 = &hash_alg[hydro_pwhash_HASH_ALGBYTES];
103
+ uint8_t *const opslimit_u8 = &threads_u8[hydro_pwhash_THREADSBYTES];
104
+ uint8_t *const memlimit_u8 = &opslimit_u8[hydro_pwhash_OPSLIMITBYTES];
105
+ uint8_t *const salt = &memlimit_u8[hydro_pwhash_MEMLIMITBYTES];
106
+ uint8_t *const h = &salt[hydro_pwhash_SALTBYTES];
107
+
108
+ COMPILER_ASSERT(hydro_pwhash_STOREDBYTES >= hydro_pwhash_ENC_ALGBYTES +
109
+ hydro_secretbox_HEADERBYTES +
110
+ hydro_pwhash_PARAMSBYTES);
111
+ (void) memlimit;
112
+ mem_zero(stored, hydro_pwhash_STOREDBYTES);
113
+ *enc_alg = hydro_pwhash_ENC_ALG;
114
+ *hash_alg = hydro_pwhash_HASH_ALG;
115
+ *threads_u8 = threads;
116
+ STORE64_LE(opslimit_u8, opslimit);
117
+ STORE64_LE(memlimit_u8, (uint64_t) memlimit);
118
+ hydro_random_buf(salt, hydro_pwhash_SALTBYTES);
119
+
120
+ COMPILER_ASSERT(sizeof zero >= hydro_pwhash_MASTERKEYBYTES);
121
+ if (_hydro_pwhash_hash(h, hydro_pwhash_HASHBYTES, salt, passwd, passwd_len,
122
+ hydro_pwhash_CONTEXT, zero, opslimit, memlimit, threads) != 0) {
123
+ return -1;
124
+ }
125
+ COMPILER_ASSERT(hydro_pwhash_MASTERKEYBYTES == hydro_secretbox_KEYBYTES);
126
+
127
+ return hydro_secretbox_encrypt(secretbox, hash_alg, hydro_pwhash_PARAMSBYTES,
128
+ (uint64_t) *enc_alg, hydro_pwhash_CONTEXT, master_key);
129
+ }
130
+
131
+ static int
132
+ _hydro_pwhash_verify(uint8_t computed_h[hydro_pwhash_HASHBYTES],
133
+ const uint8_t stored[hydro_pwhash_STOREDBYTES], const char *passwd,
134
+ size_t passwd_len, const uint8_t master_key[hydro_pwhash_MASTERKEYBYTES],
135
+ uint64_t opslimit_max, size_t memlimit_max, uint8_t threads_max)
136
+ {
137
+ const uint8_t *const enc_alg = &stored[0];
138
+ const uint8_t *const secretbox = &enc_alg[hydro_pwhash_ENC_ALGBYTES];
139
+
140
+ uint8_t params[hydro_pwhash_PARAMSBYTES];
141
+ uint8_t *const hash_alg = &params[0];
142
+ uint8_t *const threads_u8 = &hash_alg[hydro_pwhash_HASH_ALGBYTES];
143
+ uint8_t *const opslimit_u8 = &threads_u8[hydro_pwhash_THREADSBYTES];
144
+ uint8_t *const memlimit_u8 = &opslimit_u8[hydro_pwhash_OPSLIMITBYTES];
145
+ uint8_t *const salt = &memlimit_u8[hydro_pwhash_MEMLIMITBYTES];
146
+ uint8_t *const h = &salt[hydro_pwhash_SALTBYTES];
147
+
148
+ uint64_t opslimit;
149
+ size_t memlimit;
150
+ uint8_t threads;
151
+
152
+ (void) memlimit;
153
+ if (*enc_alg != hydro_pwhash_ENC_ALG) {
154
+ return -1;
155
+ }
156
+ if (hydro_secretbox_decrypt(params, secretbox,
157
+ hydro_secretbox_HEADERBYTES + hydro_pwhash_PARAMSBYTES,
158
+ (uint64_t) *enc_alg, hydro_pwhash_CONTEXT, master_key) != 0) {
159
+ return -1;
160
+ }
161
+ if (*hash_alg != hydro_pwhash_HASH_ALG || (opslimit = LOAD64_LE(opslimit_u8)) > opslimit_max ||
162
+ (memlimit = (size_t) LOAD64_LE(memlimit_u8)) > memlimit_max ||
163
+ (threads = *threads_u8) > threads_max) {
164
+ return -1;
165
+ }
166
+ if (_hydro_pwhash_hash(computed_h, hydro_pwhash_HASHBYTES, salt, passwd, passwd_len,
167
+ hydro_pwhash_CONTEXT, zero, opslimit, memlimit, threads) == 0 &&
168
+ hydro_equal(computed_h, h, hydro_pwhash_HASHBYTES) == 1) {
169
+ return 0;
170
+ }
171
+ return -1;
172
+ }
173
+
174
+ int
175
+ hydro_pwhash_verify(const uint8_t stored[hydro_pwhash_STOREDBYTES], const char *passwd,
176
+ size_t passwd_len, const uint8_t master_key[hydro_pwhash_MASTERKEYBYTES],
177
+ uint64_t opslimit_max, size_t memlimit_max, uint8_t threads_max)
178
+ {
179
+ uint8_t computed_h[hydro_pwhash_HASHBYTES];
180
+ int ret;
181
+
182
+ ret = _hydro_pwhash_verify(computed_h, stored, passwd, passwd_len, master_key, opslimit_max,
183
+ memlimit_max, threads_max);
184
+ hydro_memzero(computed_h, sizeof computed_h);
185
+
186
+ return ret;
187
+ }
188
+
189
+ int
190
+ hydro_pwhash_derive_static_key(uint8_t *static_key, size_t static_key_len,
191
+ const uint8_t stored[hydro_pwhash_STOREDBYTES], const char *passwd,
192
+ size_t passwd_len, const char ctx[hydro_pwhash_CONTEXTBYTES],
193
+ const uint8_t master_key[hydro_pwhash_MASTERKEYBYTES],
194
+ uint64_t opslimit_max, size_t memlimit_max, uint8_t threads_max)
195
+ {
196
+ uint8_t computed_h[hydro_pwhash_HASHBYTES];
197
+
198
+ if (_hydro_pwhash_verify(computed_h, stored, passwd, passwd_len, master_key, opslimit_max,
199
+ memlimit_max, threads_max) != 0) {
200
+ hydro_memzero(computed_h, sizeof computed_h);
201
+ return -1;
202
+ }
203
+ COMPILER_ASSERT(hydro_kdf_CONTEXTBYTES <= hydro_pwhash_CONTEXTBYTES);
204
+ COMPILER_ASSERT(hydro_kdf_KEYBYTES <= hydro_pwhash_HASHBYTES);
205
+ hydro_kdf_derive_from_key(static_key, static_key_len, 0, ctx, computed_h);
206
+ hydro_memzero(computed_h, sizeof computed_h);
207
+
208
+ return 0;
209
+ }
210
+
211
+ int
212
+ hydro_pwhash_reencrypt(uint8_t stored[hydro_pwhash_STOREDBYTES],
213
+ const uint8_t master_key[hydro_pwhash_MASTERKEYBYTES],
214
+ const uint8_t new_master_key[hydro_pwhash_MASTERKEYBYTES])
215
+ {
216
+ uint8_t *const enc_alg = &stored[0];
217
+ uint8_t *const secretbox = &enc_alg[hydro_pwhash_ENC_ALGBYTES];
218
+ uint8_t *const params = &secretbox[hydro_secretbox_HEADERBYTES];
219
+
220
+ if (*enc_alg != hydro_pwhash_ENC_ALG) {
221
+ return -1;
222
+ }
223
+ if (hydro_secretbox_decrypt(secretbox, secretbox,
224
+ hydro_secretbox_HEADERBYTES + hydro_pwhash_PARAMSBYTES,
225
+ (uint64_t) *enc_alg, hydro_pwhash_CONTEXT, master_key) != 0) {
226
+ return -1;
227
+ }
228
+ memmove(params, secretbox, hydro_pwhash_PARAMSBYTES);
229
+ return hydro_secretbox_encrypt(secretbox, params, hydro_pwhash_PARAMSBYTES, (uint64_t) *enc_alg,
230
+ hydro_pwhash_CONTEXT, new_master_key);
231
+ }
232
+
233
+ int
234
+ hydro_pwhash_upgrade(uint8_t stored[hydro_pwhash_STOREDBYTES],
235
+ const uint8_t master_key[hydro_pwhash_MASTERKEYBYTES], uint64_t opslimit,
236
+ size_t memlimit, uint8_t threads)
237
+ {
238
+ uint8_t *const enc_alg = &stored[0];
239
+ uint8_t *const secretbox = &enc_alg[hydro_pwhash_ENC_ALGBYTES];
240
+ uint8_t *const params = &secretbox[hydro_secretbox_HEADERBYTES];
241
+ uint8_t *const hash_alg = &params[0];
242
+ uint8_t *const threads_u8 = &hash_alg[hydro_pwhash_HASH_ALGBYTES];
243
+ uint8_t *const opslimit_u8 = &threads_u8[hydro_pwhash_THREADSBYTES];
244
+ uint8_t *const memlimit_u8 = &opslimit_u8[hydro_pwhash_OPSLIMITBYTES];
245
+ uint8_t *const salt = &memlimit_u8[hydro_pwhash_MEMLIMITBYTES];
246
+ uint8_t *const h = &salt[hydro_pwhash_SALTBYTES];
247
+
248
+ _hydro_attr_aligned_(16) uint8_t state[gimli_BLOCKBYTES];
249
+ uint64_t i;
250
+ uint64_t opslimit_prev;
251
+
252
+ if (*enc_alg != hydro_pwhash_ENC_ALG) {
253
+ return -1;
254
+ }
255
+ if (hydro_secretbox_decrypt(secretbox, secretbox,
256
+ hydro_secretbox_HEADERBYTES + hydro_pwhash_PARAMSBYTES,
257
+ (uint64_t) *enc_alg, hydro_pwhash_CONTEXT, master_key) != 0) {
258
+ return -1;
259
+ }
260
+ memmove(params, secretbox, hydro_pwhash_PARAMSBYTES);
261
+ opslimit_prev = LOAD64_LE(opslimit_u8);
262
+ if (*hash_alg != hydro_pwhash_HASH_ALG) {
263
+ mem_zero(stored, hydro_pwhash_STOREDBYTES);
264
+ return -1;
265
+ }
266
+ COMPILER_ASSERT(hydro_random_SEEDBYTES == gimli_CAPACITY);
267
+ memcpy(state + gimli_RATE, h, hydro_random_SEEDBYTES);
268
+ for (i = opslimit_prev; i < opslimit; i++) {
269
+ mem_zero(state, gimli_RATE);
270
+ STORE64_LE(state, i);
271
+ gimli_core_u8(state, 0);
272
+ }
273
+ mem_zero(state, gimli_RATE);
274
+ memcpy(h, state + gimli_RATE, hydro_random_SEEDBYTES);
275
+ *threads_u8 = threads;
276
+ STORE64_LE(opslimit_u8, opslimit);
277
+ STORE64_LE(memlimit_u8, (uint64_t) memlimit);
278
+
279
+ return hydro_secretbox_encrypt(secretbox, params, hydro_pwhash_PARAMSBYTES, (uint64_t) *enc_alg,
280
+ hydro_pwhash_CONTEXT, master_key);
281
+ }
@@ -0,0 +1,465 @@
1
+ static TLS struct {
2
+ _hydro_attr_aligned_(16) uint8_t state[gimli_BLOCKBYTES];
3
+ uint64_t counter;
4
+ uint8_t initialized;
5
+ uint8_t available;
6
+ } hydro_random_context;
7
+
8
+ #if defined(AVR) && !defined(__unix__)
9
+ #include <Arduino.h>
10
+
11
+ static bool
12
+ hydro_random_rbit(uint16_t x)
13
+ {
14
+ uint8_t x8;
15
+
16
+ x8 = ((uint8_t)(x >> 8)) ^ (uint8_t) x;
17
+ x8 = (x8 >> 4) ^ (x8 & 0xf);
18
+ x8 = (x8 >> 2) ^ (x8 & 0x3);
19
+ x8 = (x8 >> 1) ^ x8;
20
+
21
+ return (bool) (x8 & 1);
22
+ }
23
+
24
+ static int
25
+ hydro_random_init(void)
26
+ {
27
+ const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
28
+ hydro_hash_state st;
29
+ uint16_t ebits = 0;
30
+ uint16_t tc;
31
+ bool a, b;
32
+
33
+ cli();
34
+ MCUSR = 0;
35
+ WDTCSR |= _BV(WDCE) | _BV(WDE);
36
+ WDTCSR = _BV(WDIE);
37
+ sei();
38
+
39
+ hydro_hash_init(&st, ctx, NULL);
40
+
41
+ while (ebits < 256) {
42
+ delay(1);
43
+ tc = TCNT1;
44
+ hydro_hash_update(&st, (const uint8_t *) &tc, sizeof tc);
45
+ a = hydro_random_rbit(tc);
46
+ delay(1);
47
+ tc = TCNT1;
48
+ b = hydro_random_rbit(tc);
49
+ hydro_hash_update(&st, (const uint8_t *) &tc, sizeof tc);
50
+ if (a == b) {
51
+ continue;
52
+ }
53
+ hydro_hash_update(&st, (const uint8_t *) &b, sizeof b);
54
+ ebits++;
55
+ }
56
+
57
+ cli();
58
+ MCUSR = 0;
59
+ WDTCSR |= _BV(WDCE) | _BV(WDE);
60
+ WDTCSR = 0;
61
+ sei();
62
+
63
+ hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
64
+ hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
65
+
66
+ return 0;
67
+ }
68
+
69
+ ISR(WDT_vect) {}
70
+
71
+ #elif (defined(ESP32) || defined(ESP8266)) && !defined(__unix__)
72
+
73
+ // Important: RF *must* be activated on ESP board
74
+ // https://techtutorialsx.com/2017/12/22/esp32-arduino-random-number-generation/
75
+
76
+ #include <esp_system.h>
77
+
78
+ static int
79
+ hydro_random_init(void)
80
+ {
81
+ const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
82
+ hydro_hash_state st;
83
+ uint16_t ebits = 0;
84
+
85
+ hydro_hash_init(&st, ctx, NULL);
86
+
87
+ while (ebits < 256) {
88
+ uint32_t r = esp_random();
89
+
90
+ delay(10);
91
+ hydro_hash_update(&st, (const uint32_t *) &r, sizeof r);
92
+ ebits += 32;
93
+ }
94
+
95
+ hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
96
+ hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
97
+
98
+ return 0;
99
+ }
100
+
101
+ #elif defined(PARTICLE) && defined(PLATFORM_ID) && PLATFORM_ID > 2 && !defined(__unix__)
102
+
103
+ // Note: All particle platforms except for the Spark Core have a HW RNG. Only allow building on
104
+ // supported platforms for now. PLATFORM_ID definitions:
105
+ // https://github.com/particle-iot/device-os/blob/mesh-develop/hal/shared/platforms.h
106
+
107
+ #include "Particle.h"
108
+
109
+ static int
110
+ hydro_random_init(void)
111
+ {
112
+ const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
113
+ hydro_hash_state st;
114
+ uint16_t ebits = 0;
115
+
116
+ hydro_hash_init(&st, ctx, NULL);
117
+
118
+ while (ebits < 256) {
119
+ uint32_t r = HAL_RNG_GetRandomNumber();
120
+ hydro_hash_update(&st, (const uint32_t *) &r, sizeof r);
121
+ ebits += 32;
122
+ }
123
+
124
+ hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
125
+ hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
126
+
127
+ return 0;
128
+ }
129
+
130
+ #elif (defined(NRF52832_XXAA) || defined(NRF52832_XXAB)) && !defined(__unix__)
131
+
132
+ // Important: The SoftDevice *must* be activated to enable reading from the RNG
133
+ // http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Frng.html
134
+
135
+ #include <nrf_soc.h>
136
+
137
+ static int
138
+ hydro_random_init(void)
139
+ {
140
+ const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
141
+ hydro_hash_state st;
142
+ const uint8_t total_bytes = 32;
143
+ uint8_t remaining_bytes = total_bytes;
144
+ uint8_t available_bytes;
145
+ uint8_t rand_buffer[32];
146
+
147
+ hydro_hash_init(&st, ctx, NULL);
148
+
149
+ for (;;) {
150
+ if (sd_rand_application_bytes_available_get(&available_bytes) != NRF_SUCCESS) {
151
+ return -1;
152
+ }
153
+ if (available_bytes > 0) {
154
+ if (available_bytes > remaining_bytes) {
155
+ available_bytes = remaining_bytes;
156
+ }
157
+ if (sd_rand_application_vector_get(rand_buffer, available_bytes) != NRF_SUCCESS) {
158
+ return -1;
159
+ }
160
+ hydro_hash_update(&st, rand_buffer, total_bytes);
161
+ remaining_bytes -= available_bytes;
162
+ }
163
+ if (remaining_bytes <= 0) {
164
+ break;
165
+ }
166
+ delay(10);
167
+ }
168
+ hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
169
+ hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
170
+
171
+ return 0;
172
+ }
173
+
174
+ #elif defined(_WIN32)
175
+
176
+ #include <windows.h>
177
+ #define RtlGenRandom SystemFunction036
178
+ #if defined(__cplusplus)
179
+ extern "C"
180
+ #endif
181
+ BOOLEAN NTAPI
182
+ RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
183
+ #pragma comment(lib, "advapi32.lib")
184
+
185
+ static int
186
+ hydro_random_init(void)
187
+ {
188
+ if (!RtlGenRandom((PVOID) hydro_random_context.state,
189
+ (ULONG) sizeof hydro_random_context.state)) {
190
+ return -1;
191
+ }
192
+ hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
193
+
194
+ return 0;
195
+ }
196
+
197
+ #elif defined(__wasi__)
198
+
199
+ #include <unistd.h>
200
+
201
+ static int
202
+ hydro_random_init(void)
203
+ {
204
+ if (getentropy(hydro_random_context.state, sizeof hydro_random_context.state) != 0) {
205
+ return -1;
206
+ }
207
+ hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
208
+
209
+ return 0;
210
+ }
211
+
212
+ #elif defined(__unix__)
213
+
214
+ #include <errno.h>
215
+ #include <fcntl.h>
216
+ #ifdef __linux__
217
+ #include <poll.h>
218
+ #endif
219
+ #include <sys/types.h>
220
+ #include <unistd.h>
221
+
222
+ #ifdef __linux__
223
+ static int
224
+ hydro_random_block_on_dev_random(void)
225
+ {
226
+ struct pollfd pfd;
227
+ int fd;
228
+ int pret;
229
+
230
+ fd = open("/dev/random", O_RDONLY);
231
+ if (fd == -1) {
232
+ return 0;
233
+ }
234
+ pfd.fd = fd;
235
+ pfd.events = POLLIN;
236
+ pfd.revents = 0;
237
+ do {
238
+ pret = poll(&pfd, 1, -1);
239
+ } while (pret < 0 && (errno == EINTR || errno == EAGAIN));
240
+ if (pret != 1) {
241
+ (void) close(fd);
242
+ errno = EIO;
243
+ return -1;
244
+ }
245
+ return close(fd);
246
+ }
247
+ #endif
248
+
249
+ static ssize_t
250
+ hydro_random_safe_read(const int fd, void *const buf_, size_t len)
251
+ {
252
+ unsigned char *buf = (unsigned char *) buf_;
253
+ ssize_t readnb;
254
+
255
+ do {
256
+ while ((readnb = read(fd, buf, len)) < (ssize_t) 0 && (errno == EINTR || errno == EAGAIN)) {
257
+ }
258
+ if (readnb < (ssize_t) 0) {
259
+ return readnb;
260
+ }
261
+ if (readnb == (ssize_t) 0) {
262
+ break;
263
+ }
264
+ len -= (size_t) readnb;
265
+ buf += readnb;
266
+ } while (len > (ssize_t) 0);
267
+
268
+ return (ssize_t)(buf - (unsigned char *) buf_);
269
+ }
270
+
271
+ static int
272
+ hydro_random_init(void)
273
+ {
274
+ uint8_t tmp[gimli_BLOCKBYTES + 8];
275
+ int fd;
276
+ int ret = -1;
277
+
278
+ #ifdef __linux__
279
+ if (hydro_random_block_on_dev_random() != 0) {
280
+ return -1;
281
+ }
282
+ #endif
283
+ do {
284
+ fd = open("/dev/urandom", O_RDONLY);
285
+ if (fd == -1 && errno != EINTR) {
286
+ return -1;
287
+ }
288
+ } while (fd == -1);
289
+ if (hydro_random_safe_read(fd, tmp, sizeof tmp) == (ssize_t) sizeof tmp) {
290
+ memcpy(hydro_random_context.state, tmp, gimli_BLOCKBYTES);
291
+ memcpy(&hydro_random_context.counter, tmp + gimli_BLOCKBYTES, 8);
292
+ hydro_memzero(tmp, sizeof tmp);
293
+ ret = 0;
294
+ }
295
+ ret |= close(fd);
296
+
297
+ return ret;
298
+ }
299
+
300
+ #elif defined(TARGET_LIKE_MBED)
301
+
302
+ #include <mbedtls/ctr_drbg.h>
303
+ #include <mbedtls/entropy.h>
304
+
305
+ #if defined(MBEDTLS_ENTROPY_C)
306
+
307
+ static int
308
+ hydro_random_init(void)
309
+ {
310
+ mbedtls_entropy_context entropy;
311
+ uint16_t pos = 0;
312
+
313
+ mbedtls_entropy_init(&entropy);
314
+
315
+ // Pull data directly out of the entropy pool for the state, as it's small enough.
316
+ if (mbedtls_entropy_func(&entropy, (uint8_t *) &hydro_random_context.counter,
317
+ sizeof hydro_random_context.counter) != 0) {
318
+ return -1;
319
+ }
320
+ // mbedtls_entropy_func can't provide more than MBEDTLS_ENTROPY_BLOCK_SIZE in one go.
321
+ // This constant depends of mbedTLS configuration (whether the PRNG is backed by SHA256/SHA512
322
+ // at this time) Therefore, if necessary, we get entropy multiple times.
323
+
324
+ do {
325
+ const uint8_t dataLeftToConsume = gimli_BLOCKBYTES - pos;
326
+ const uint8_t currentChunkSize = (dataLeftToConsume > MBEDTLS_ENTROPY_BLOCK_SIZE)
327
+ ? MBEDTLS_ENTROPY_BLOCK_SIZE
328
+ : dataLeftToConsume;
329
+
330
+ // Forces mbedTLS to fetch fresh entropy, then get some to feed libhydrogen.
331
+ if (mbedtls_entropy_gather(&entropy) != 0 ||
332
+ mbedtls_entropy_func(&entropy, &hydro_random_context.state[pos], currentChunkSize) !=
333
+ 0) {
334
+ return -1;
335
+ }
336
+ pos += MBEDTLS_ENTROPY_BLOCK_SIZE;
337
+ } while (pos < gimli_BLOCKBYTES);
338
+
339
+ mbedtls_entropy_free(&entropy);
340
+
341
+ return 0;
342
+ }
343
+
344
+ #else
345
+ #error Need an entropy source
346
+ #endif
347
+
348
+ #else
349
+ #error Unsupported platform
350
+ #endif
351
+
352
+ static void
353
+ hydro_random_check_initialized(void)
354
+ {
355
+ if (hydro_random_context.initialized == 0) {
356
+ if (hydro_random_init() != 0) {
357
+ abort();
358
+ }
359
+ gimli_core_u8(hydro_random_context.state, 0);
360
+ hydro_random_ratchet();
361
+ hydro_random_context.initialized = 1;
362
+ }
363
+ }
364
+
365
+ void
366
+ hydro_random_ratchet(void)
367
+ {
368
+ mem_zero(hydro_random_context.state, gimli_RATE);
369
+ STORE64_LE(hydro_random_context.state, hydro_random_context.counter);
370
+ hydro_random_context.counter++;
371
+ gimli_core_u8(hydro_random_context.state, 0);
372
+ hydro_random_context.available = gimli_RATE;
373
+ }
374
+
375
+ uint32_t
376
+ hydro_random_u32(void)
377
+ {
378
+ uint32_t v;
379
+
380
+ hydro_random_check_initialized();
381
+ if (hydro_random_context.available < 4) {
382
+ hydro_random_ratchet();
383
+ }
384
+ memcpy(&v, &hydro_random_context.state[gimli_RATE - hydro_random_context.available], 4);
385
+ hydro_random_context.available -= 4;
386
+
387
+ return v;
388
+ }
389
+
390
+ uint32_t
391
+ hydro_random_uniform(const uint32_t upper_bound)
392
+ {
393
+ uint32_t min;
394
+ uint32_t r;
395
+
396
+ if (upper_bound < 2U) {
397
+ return 0;
398
+ }
399
+ min = (1U + ~upper_bound) % upper_bound; /* = 2**32 mod upper_bound */
400
+ do {
401
+ r = hydro_random_u32();
402
+ } while (r < min);
403
+ /* r is now clamped to a set whose size mod upper_bound == 0
404
+ * the worst case (2**31+1) requires 2 attempts on average */
405
+
406
+ return r % upper_bound;
407
+ }
408
+
409
+ void
410
+ hydro_random_buf(void *out, size_t out_len)
411
+ {
412
+ uint8_t *p = (uint8_t *) out;
413
+ size_t i;
414
+ size_t leftover;
415
+
416
+ hydro_random_check_initialized();
417
+ for (i = 0; i < out_len / gimli_RATE; i++) {
418
+ gimli_core_u8(hydro_random_context.state, 0);
419
+ memcpy(p + i * gimli_RATE, hydro_random_context.state, gimli_RATE);
420
+ }
421
+ leftover = out_len % gimli_RATE;
422
+ if (leftover != 0) {
423
+ gimli_core_u8(hydro_random_context.state, 0);
424
+ mem_cpy(p + i * gimli_RATE, hydro_random_context.state, leftover);
425
+ }
426
+ hydro_random_ratchet();
427
+ }
428
+
429
+ void
430
+ hydro_random_buf_deterministic(void *out, size_t out_len,
431
+ const uint8_t seed[hydro_random_SEEDBYTES])
432
+ {
433
+ static const uint8_t prefix[] = { 7, 'd', 'r', 'b', 'g', '2', '5', '6' };
434
+ _hydro_attr_aligned_(16) uint8_t state[gimli_BLOCKBYTES];
435
+ uint8_t * p = (uint8_t *) out;
436
+ size_t i;
437
+ size_t leftover;
438
+
439
+ mem_zero(state, gimli_BLOCKBYTES);
440
+ COMPILER_ASSERT(sizeof prefix + 8 <= gimli_RATE);
441
+ memcpy(state, prefix, sizeof prefix);
442
+ STORE64_LE(state + sizeof prefix, (uint64_t) out_len);
443
+ gimli_core_u8(state, 1);
444
+ COMPILER_ASSERT(hydro_random_SEEDBYTES == gimli_RATE * 2);
445
+ mem_xor(state, seed, gimli_RATE);
446
+ gimli_core_u8(state, 2);
447
+ mem_xor(state, seed + gimli_RATE, gimli_RATE);
448
+ gimli_core_u8(state, 2);
449
+ for (i = 0; i < out_len / gimli_RATE; i++) {
450
+ gimli_core_u8(state, 0);
451
+ memcpy(p + i * gimli_RATE, state, gimli_RATE);
452
+ }
453
+ leftover = out_len % gimli_RATE;
454
+ if (leftover != 0) {
455
+ gimli_core_u8(state, 0);
456
+ mem_cpy(p + i * gimli_RATE, state, leftover);
457
+ }
458
+ }
459
+
460
+ void
461
+ hydro_random_reseed(void)
462
+ {
463
+ hydro_random_context.initialized = 0;
464
+ hydro_random_check_initialized();
465
+ }