|
|
@@ -6,345 +6,21 @@ static TLS struct {
|
|
|
} hydro_random_context;
|
|
|
|
|
|
#if defined(AVR) && !defined(__unix__)
|
|
|
-#include <Arduino.h>
|
|
|
-
|
|
|
-static bool
|
|
|
-hydro_random_rbit(uint16_t x)
|
|
|
-{
|
|
|
- uint8_t x8;
|
|
|
-
|
|
|
- x8 = ((uint8_t)(x >> 8)) ^ (uint8_t) x;
|
|
|
- x8 = (x8 >> 4) ^ (x8 & 0xf);
|
|
|
- x8 = (x8 >> 2) ^ (x8 & 0x3);
|
|
|
- x8 = (x8 >> 1) ^ x8;
|
|
|
-
|
|
|
- return (bool) (x8 & 1);
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-hydro_random_init(void)
|
|
|
-{
|
|
|
- const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
|
|
|
- hydro_hash_state st;
|
|
|
- uint16_t ebits = 0;
|
|
|
- uint16_t tc;
|
|
|
- bool a, b;
|
|
|
-
|
|
|
- cli();
|
|
|
- MCUSR = 0;
|
|
|
- WDTCSR |= _BV(WDCE) | _BV(WDE);
|
|
|
- WDTCSR = _BV(WDIE);
|
|
|
- sei();
|
|
|
-
|
|
|
- hydro_hash_init(&st, ctx, NULL);
|
|
|
-
|
|
|
- while (ebits < 256) {
|
|
|
- delay(1);
|
|
|
- tc = TCNT1;
|
|
|
- hydro_hash_update(&st, (const uint8_t *) &tc, sizeof tc);
|
|
|
- a = hydro_random_rbit(tc);
|
|
|
- delay(1);
|
|
|
- tc = TCNT1;
|
|
|
- b = hydro_random_rbit(tc);
|
|
|
- hydro_hash_update(&st, (const uint8_t *) &tc, sizeof tc);
|
|
|
- if (a == b) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- hydro_hash_update(&st, (const uint8_t *) &b, sizeof b);
|
|
|
- ebits++;
|
|
|
- }
|
|
|
-
|
|
|
- cli();
|
|
|
- MCUSR = 0;
|
|
|
- WDTCSR |= _BV(WDCE) | _BV(WDE);
|
|
|
- WDTCSR = 0;
|
|
|
- sei();
|
|
|
-
|
|
|
- hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
|
|
|
- hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-ISR(WDT_vect) {}
|
|
|
-
|
|
|
+# include "random/avr.h"
|
|
|
#elif (defined(ESP32) || defined(ESP8266)) && !defined(__unix__)
|
|
|
-
|
|
|
-// Important: RF *must* be activated on ESP board
|
|
|
-// https://techtutorialsx.com/2017/12/22/esp32-arduino-random-number-generation/
|
|
|
-
|
|
|
-#include <esp_system.h>
|
|
|
-
|
|
|
-static int
|
|
|
-hydro_random_init(void)
|
|
|
-{
|
|
|
- const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
|
|
|
- hydro_hash_state st;
|
|
|
- uint16_t ebits = 0;
|
|
|
-
|
|
|
- hydro_hash_init(&st, ctx, NULL);
|
|
|
-
|
|
|
- while (ebits < 256) {
|
|
|
- uint32_t r = esp_random();
|
|
|
-
|
|
|
- delay(10);
|
|
|
- hydro_hash_update(&st, (const uint32_t *) &r, sizeof r);
|
|
|
- ebits += 32;
|
|
|
- }
|
|
|
-
|
|
|
- hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
|
|
|
- hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
+# include "random/esp32.h"
|
|
|
#elif defined(PARTICLE) && defined(PLATFORM_ID) && PLATFORM_ID > 2 && !defined(__unix__)
|
|
|
-
|
|
|
-// Note: All particle platforms except for the Spark Core have a HW RNG. Only allow building on
|
|
|
-// supported platforms for now. PLATFORM_ID definitions:
|
|
|
-// https://github.com/particle-iot/device-os/blob/mesh-develop/hal/shared/platforms.h
|
|
|
-
|
|
|
-#include "Particle.h"
|
|
|
-
|
|
|
-static int
|
|
|
-hydro_random_init(void)
|
|
|
-{
|
|
|
- const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
|
|
|
- hydro_hash_state st;
|
|
|
- uint16_t ebits = 0;
|
|
|
-
|
|
|
- hydro_hash_init(&st, ctx, NULL);
|
|
|
-
|
|
|
- while (ebits < 256) {
|
|
|
- uint32_t r = HAL_RNG_GetRandomNumber();
|
|
|
- hydro_hash_update(&st, (const uint32_t *) &r, sizeof r);
|
|
|
- ebits += 32;
|
|
|
- }
|
|
|
-
|
|
|
- hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
|
|
|
- hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
+# include "random/particle.h"
|
|
|
#elif (defined(NRF52832_XXAA) || defined(NRF52832_XXAB)) && !defined(__unix__)
|
|
|
-
|
|
|
-// Important: The SoftDevice *must* be activated to enable reading from the RNG
|
|
|
-// http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Frng.html
|
|
|
-
|
|
|
-#include <nrf_soc.h>
|
|
|
-
|
|
|
-static int
|
|
|
-hydro_random_init(void)
|
|
|
-{
|
|
|
- const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
|
|
|
- hydro_hash_state st;
|
|
|
- const uint8_t total_bytes = 32;
|
|
|
- uint8_t remaining_bytes = total_bytes;
|
|
|
- uint8_t available_bytes;
|
|
|
- uint8_t rand_buffer[32];
|
|
|
-
|
|
|
- hydro_hash_init(&st, ctx, NULL);
|
|
|
-
|
|
|
- for (;;) {
|
|
|
- if (sd_rand_application_bytes_available_get(&available_bytes) != NRF_SUCCESS) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if (available_bytes > 0) {
|
|
|
- if (available_bytes > remaining_bytes) {
|
|
|
- available_bytes = remaining_bytes;
|
|
|
- }
|
|
|
- if (sd_rand_application_vector_get(rand_buffer, available_bytes) != NRF_SUCCESS) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- hydro_hash_update(&st, rand_buffer, total_bytes);
|
|
|
- remaining_bytes -= available_bytes;
|
|
|
- }
|
|
|
- if (remaining_bytes <= 0) {
|
|
|
- break;
|
|
|
- }
|
|
|
- delay(10);
|
|
|
- }
|
|
|
- hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
|
|
|
- hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
+# include "random/nrf52832.h"
|
|
|
#elif defined(_WIN32)
|
|
|
-
|
|
|
-#include <windows.h>
|
|
|
-#define RtlGenRandom SystemFunction036
|
|
|
-#if defined(__cplusplus)
|
|
|
-extern "C"
|
|
|
-#endif
|
|
|
- BOOLEAN NTAPI
|
|
|
- RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
|
|
|
-#pragma comment(lib, "advapi32.lib")
|
|
|
-
|
|
|
-static int
|
|
|
-hydro_random_init(void)
|
|
|
-{
|
|
|
- if (!RtlGenRandom((PVOID) hydro_random_context.state,
|
|
|
- (ULONG) sizeof hydro_random_context.state)) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
+# include "random/windows.h"
|
|
|
#elif defined(__wasi__)
|
|
|
-
|
|
|
-#include <unistd.h>
|
|
|
-
|
|
|
-static int
|
|
|
-hydro_random_init(void)
|
|
|
-{
|
|
|
- if (getentropy(hydro_random_context.state, sizeof hydro_random_context.state) != 0) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
+# include "random/wasi.h"
|
|
|
#elif defined(__unix__)
|
|
|
-
|
|
|
-#include <errno.h>
|
|
|
-#include <fcntl.h>
|
|
|
-#ifdef __linux__
|
|
|
-#include <poll.h>
|
|
|
-#endif
|
|
|
-#include <sys/types.h>
|
|
|
-#include <unistd.h>
|
|
|
-
|
|
|
-#ifdef __linux__
|
|
|
-static int
|
|
|
-hydro_random_block_on_dev_random(void)
|
|
|
-{
|
|
|
- struct pollfd pfd;
|
|
|
- int fd;
|
|
|
- int pret;
|
|
|
-
|
|
|
- fd = open("/dev/random", O_RDONLY);
|
|
|
- if (fd == -1) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- pfd.fd = fd;
|
|
|
- pfd.events = POLLIN;
|
|
|
- pfd.revents = 0;
|
|
|
- do {
|
|
|
- pret = poll(&pfd, 1, -1);
|
|
|
- } while (pret < 0 && (errno == EINTR || errno == EAGAIN));
|
|
|
- if (pret != 1) {
|
|
|
- (void) close(fd);
|
|
|
- errno = EIO;
|
|
|
- return -1;
|
|
|
- }
|
|
|
- return close(fd);
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-static ssize_t
|
|
|
-hydro_random_safe_read(const int fd, void *const buf_, size_t len)
|
|
|
-{
|
|
|
- unsigned char *buf = (unsigned char *) buf_;
|
|
|
- ssize_t readnb;
|
|
|
-
|
|
|
- do {
|
|
|
- while ((readnb = read(fd, buf, len)) < (ssize_t) 0 && (errno == EINTR || errno == EAGAIN)) {
|
|
|
- }
|
|
|
- if (readnb < (ssize_t) 0) {
|
|
|
- return readnb;
|
|
|
- }
|
|
|
- if (readnb == (ssize_t) 0) {
|
|
|
- break;
|
|
|
- }
|
|
|
- len -= (size_t) readnb;
|
|
|
- buf += readnb;
|
|
|
- } while (len > (ssize_t) 0);
|
|
|
-
|
|
|
- return (ssize_t)(buf - (unsigned char *) buf_);
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-hydro_random_init(void)
|
|
|
-{
|
|
|
- uint8_t tmp[gimli_BLOCKBYTES + 8];
|
|
|
- int fd;
|
|
|
- int ret = -1;
|
|
|
-
|
|
|
-#ifdef __linux__
|
|
|
- if (hydro_random_block_on_dev_random() != 0) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
-#endif
|
|
|
- do {
|
|
|
- fd = open("/dev/urandom", O_RDONLY);
|
|
|
- if (fd == -1 && errno != EINTR) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- } while (fd == -1);
|
|
|
- if (hydro_random_safe_read(fd, tmp, sizeof tmp) == (ssize_t) sizeof tmp) {
|
|
|
- memcpy(hydro_random_context.state, tmp, gimli_BLOCKBYTES);
|
|
|
- memcpy(&hydro_random_context.counter, tmp + gimli_BLOCKBYTES, 8);
|
|
|
- hydro_memzero(tmp, sizeof tmp);
|
|
|
- ret = 0;
|
|
|
- }
|
|
|
- ret |= close(fd);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
+# include "random/unix.h"
|
|
|
#elif defined(TARGET_LIKE_MBED)
|
|
|
-
|
|
|
-#include <mbedtls/ctr_drbg.h>
|
|
|
-#include <mbedtls/entropy.h>
|
|
|
-
|
|
|
-#if defined(MBEDTLS_ENTROPY_C)
|
|
|
-
|
|
|
-static int
|
|
|
-hydro_random_init(void)
|
|
|
-{
|
|
|
- mbedtls_entropy_context entropy;
|
|
|
- uint16_t pos = 0;
|
|
|
-
|
|
|
- mbedtls_entropy_init(&entropy);
|
|
|
-
|
|
|
- // Pull data directly out of the entropy pool for the state, as it's small enough.
|
|
|
- if (mbedtls_entropy_func(&entropy, (uint8_t *) &hydro_random_context.counter,
|
|
|
- sizeof hydro_random_context.counter) != 0) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- // mbedtls_entropy_func can't provide more than MBEDTLS_ENTROPY_BLOCK_SIZE in one go.
|
|
|
- // This constant depends of mbedTLS configuration (whether the PRNG is backed by SHA256/SHA512
|
|
|
- // at this time) Therefore, if necessary, we get entropy multiple times.
|
|
|
-
|
|
|
- do {
|
|
|
- const uint8_t dataLeftToConsume = gimli_BLOCKBYTES - pos;
|
|
|
- const uint8_t currentChunkSize = (dataLeftToConsume > MBEDTLS_ENTROPY_BLOCK_SIZE)
|
|
|
- ? MBEDTLS_ENTROPY_BLOCK_SIZE
|
|
|
- : dataLeftToConsume;
|
|
|
-
|
|
|
- // Forces mbedTLS to fetch fresh entropy, then get some to feed libhydrogen.
|
|
|
- if (mbedtls_entropy_gather(&entropy) != 0 ||
|
|
|
- mbedtls_entropy_func(&entropy, &hydro_random_context.state[pos], currentChunkSize) !=
|
|
|
- 0) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- pos += MBEDTLS_ENTROPY_BLOCK_SIZE;
|
|
|
- } while (pos < gimli_BLOCKBYTES);
|
|
|
-
|
|
|
- mbedtls_entropy_free(&entropy);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-#else
|
|
|
-#error Need an entropy source
|
|
|
-#endif
|
|
|
-
|
|
|
+# include "random/mbed.h"
|
|
|
#else
|
|
|
#error Unsupported platform
|
|
|
#endif
|