diff --git a/src/rng/hwrng.c b/src/rng/hwrng.c index 79f2b5f..c443fc4 100644 --- a/src/rng/hwrng.c +++ b/src/rng/hwrng.c @@ -71,15 +71,13 @@ static int hwrng_mix_process(void) { return 0; } -PACK( typedef struct hwrng_buf { - uint32_t *buf; - uint8_t head; - uint8_t tail; - uint8_t size; - unsigned int full : 1; - unsigned int empty : 1; -}) hwrng_buf_t; + uint8_t *buf; + size_t head; + size_t tail; + size_t size; + size_t count; +} hwrng_buf_t; static mutex_t hwrng_mutex; static bool hwrng_mutex_initialized = false; @@ -96,49 +94,70 @@ static inline void hwrng_unlock(void) { } } -static void hwrng_buf_init(struct hwrng_buf *rb, uint32_t *p, uint8_t size) { +static void hwrng_buf_init(struct hwrng_buf *rb, uint8_t *p, size_t size) { rb->buf = p; rb->size = size; rb->head = rb->tail = 0; - rb->full = 0; - rb->empty = 1; + rb->count = 0; } -static void hwrng_buf_add(struct hwrng_buf *rb, uint32_t v) { - if (rb->full) { - return; - } +static size_t hwrng_buf_add(struct hwrng_buf *rb, const uint8_t *data, size_t len) { + size_t room = rb->size - rb->count; + size_t n = len < room ? len : room; + size_t tail = rb->tail; + size_t first = n; - uint8_t tail = rb->tail; - rb->buf[tail] = v; - tail++; - if (tail >= rb->size) { - tail = 0; + if (first > rb->size - tail) { + first = rb->size - tail; + } + if (first) { + memcpy(rb->buf + tail, data, first); + tail += first; + if (tail >= rb->size) { + tail = 0; + } + } + if (n > first) { + size_t second = n - first; + memcpy(rb->buf + tail, data + first, second); + tail += second; } rb->tail = tail; - rb->full = (rb->tail == rb->head); - rb->empty = 0; + rb->count += n; + return n; } -static uint32_t hwrng_buf_del(struct hwrng_buf *rb) { - uint32_t v = 0; - if (rb->empty) { - return v; - } +static size_t hwrng_buf_del(struct hwrng_buf *rb, uint8_t *data, size_t len) { + size_t n = len < rb->count ? len : rb->count; + size_t head = rb->head; + size_t first = n; - uint8_t head = rb->head; - v = rb->buf[head]; - head++; - if (head >= rb->size) { - head = 0; + if (first > rb->size - head) { + first = rb->size - head; + } + if (first) { + memcpy(data, rb->buf + head, first); + head += first; + if (head >= rb->size) { + head = 0; + } + } + if (n > first) { + size_t second = n - first; + memcpy(data + first, rb->buf + head, second); + head += second; } rb->head = head; - if (rb->head == rb->tail) { - rb->empty = 1; - } - rb->full = 0; + rb->count -= n; + return n; +} - return v; +static inline size_t hwrng_buf_space(const struct hwrng_buf *rb) { + return rb->size - rb->count; +} + +static inline bool hwrng_buf_full(const struct hwrng_buf *rb) { + return rb->count == rb->size; } static struct hwrng_buf ring_buffer; @@ -146,24 +165,15 @@ static struct hwrng_buf ring_buffer; void *hwrng_task(void) { struct hwrng_buf *rb = &ring_buffer; - int n; - hwrng_lock(); - if ((n = hwrng_mix_process())) { - const uint32_t *vp = (const uint32_t *) &random_word; - - for (int i = 0; i < n; i++) { - hwrng_buf_add(rb, *vp++); - if (rb->full) { - break; - } - } + if (hwrng_buf_space(rb) >= sizeof(random_word) && hwrng_mix_process()) { + hwrng_buf_add(rb, (const uint8_t *)&random_word, sizeof(random_word)); } hwrng_unlock(); return NULL; } -void hwrng_init(uint32_t *buf, uint8_t size) { +void hwrng_init(uint8_t *buf, size_t size) { struct hwrng_buf *rb = &ring_buffer; mutex_init(&hwrng_mutex); @@ -175,28 +185,36 @@ void hwrng_init(uint32_t *buf, uint8_t size) { hwrng_mix_init(); } +size_t hwrng_read(uint8_t *buf, size_t len) { + struct hwrng_buf *rb = &ring_buffer; + size_t n; + + hwrng_lock(); + n = hwrng_buf_del(rb, buf, len); + hwrng_unlock(); + return n; +} + void hwrng_flush(void) { struct hwrng_buf *rb = &ring_buffer; hwrng_lock(); - while (!rb->empty) { - hwrng_buf_del(rb); - } + rb->head = 0; + rb->tail = 0; + rb->count = 0; hwrng_unlock(); } uint32_t hwrng_get(void) { - struct hwrng_buf *rb = &ring_buffer; - uint32_t v; + uint32_t v = 0; + size_t offset = 0; - while (true) { - hwrng_lock(); - if (!rb->empty) { - v = hwrng_buf_del(rb); - hwrng_unlock(); - break; + while (offset < sizeof(v)) { + size_t n = hwrng_read(((uint8_t *)&v) + offset, sizeof(v) - offset); + if (n == 0) { + hwrng_task(); + continue; } - hwrng_unlock(); - hwrng_task(); + offset += n; } return v; @@ -211,8 +229,9 @@ void hwrng_wait_full(void) { #endif while (true) { hwrng_lock(); + bool full = hwrng_buf_full(rb); hwrng_unlock(); - if (rb->full) { + if (full) { break; } #if defined(PICO_PLATFORM) || defined(ESP_PLATFORM) diff --git a/src/rng/hwrng.h b/src/rng/hwrng.h index 6a0bfcd..f19683a 100644 --- a/src/rng/hwrng.h +++ b/src/rng/hwrng.h @@ -18,11 +18,13 @@ #ifndef _NEUG_H_ #define _NEUG_H_ #include +#include -void hwrng_init(uint32_t *buf, uint8_t size); -uint32_t hwrng_get(void); +void hwrng_init(uint8_t *buf, size_t size); +size_t hwrng_read(uint8_t *buf, size_t len); void hwrng_flush(void); void hwrng_wait_full(void); void *hwrng_task(void); +uint32_t hwrng_get(void); #endif diff --git a/src/rng/random.c b/src/rng/random.c index 939f38b..930b6f4 100644 --- a/src/rng/random.c +++ b/src/rng/random.c @@ -20,38 +20,18 @@ #include "picokeys.h" #include "hwrng.h" #include "random.h" -#if defined(PICO_PLATFORM) -#include "pico/mutex.h" -#elif defined(ESP_PLATFORM) -#include "compat/esp_compat.h" -#else -#include "compat/queue.h" -#endif #define RANDOM_BYTES_LENGTH 32 -static uint32_t random_word[RANDOM_BYTES_LENGTH / sizeof(uint32_t)]; -static mutex_t random_mutex; -static bool random_mutex_initialized = false; +static uint8_t random_pool[256]; void random_init(void) { - mutex_init(&random_mutex); - random_mutex_initialized = true; - hwrng_init(random_word, RANDOM_BYTES_LENGTH / sizeof(uint32_t)); + hwrng_init(random_pool, sizeof(random_pool)); for (int i = 0; i < HWRNG_PRE_LOOP; i++) { - hwrng_get(); + hwrng_task(); } } -/* - * Free pointer to random 32-byte - */ -static void random_bytes_free(const uint8_t *p) { - (void) p; - memset(random_word, 0, RANDOM_BYTES_LENGTH); - hwrng_flush(); -} - /* * Return pointer to random 32-byte */ @@ -60,17 +40,9 @@ const uint8_t *random_bytes_get(size_t len) { if (len > MAX_RANDOM_BUFFER) { return NULL; } - static uint32_t return_word[MAX_RANDOM_BUFFER / sizeof(uint32_t)]; - if (random_mutex_initialized) { - mutex_enter_blocking(&random_mutex); - } - for (size_t ix = 0; ix < len; ix += RANDOM_BYTES_LENGTH) { - hwrng_wait_full(); - memcpy(return_word + ix / sizeof(uint32_t), random_word, RANDOM_BYTES_LENGTH); - random_bytes_free((const uint8_t *) random_word); - } - if (random_mutex_initialized) { - mutex_exit(&random_mutex); + static uint8_t return_word[MAX_RANDOM_BUFFER]; + if (random_fill_buffer(return_word, len) != 0) { + return NULL; } return (const uint8_t *) return_word; } @@ -80,43 +52,25 @@ const uint8_t *random_bytes_get(size_t len) { */ int random_fill_iterator(void *arg, unsigned char *out, size_t out_len) { random_fill_iterator_ctx_t *ctx = (random_fill_iterator_ctx_t *) arg; - uint8_t index = ctx ? ctx->index : 0; - uint8_t n; int ret = 0; - if (random_mutex_initialized) { - mutex_enter_blocking(&random_mutex); - } while (out_len) { if (ctx && ctx->cancel) { ret = -1; break; } - hwrng_wait_full(); - - n = RANDOM_BYTES_LENGTH - index; - if (n > out_len) { - n = (uint8_t)out_len; + size_t n = hwrng_read(out, out_len); + if (n == 0) { + hwrng_task(); + continue; } - - memcpy(out, ((unsigned char *) random_word) + index, n); out += n; out_len -= n; - index += n; - - if (index >= RANDOM_BYTES_LENGTH) { - index = 0; - hwrng_flush(); + if (ctx) { + ctx->index = (uint8_t)((ctx->index + n) % RANDOM_BYTES_LENGTH); } } - if (ctx) { - ctx->index = index; - } - if (random_mutex_initialized) { - mutex_exit(&random_mutex); - } - return ret; }