mirror of
https://github.com/polhenarejos/pico-keys-sdk
synced 2026-06-10 03:49:05 +02:00
Refactor HWRNG to be less blocking.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
145
src/rng/hwrng.c
145
src/rng/hwrng.c
@@ -71,15 +71,13 @@ static int hwrng_mix_process(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PACK(
|
|
||||||
typedef struct hwrng_buf {
|
typedef struct hwrng_buf {
|
||||||
uint32_t *buf;
|
uint8_t *buf;
|
||||||
uint8_t head;
|
size_t head;
|
||||||
uint8_t tail;
|
size_t tail;
|
||||||
uint8_t size;
|
size_t size;
|
||||||
unsigned int full : 1;
|
size_t count;
|
||||||
unsigned int empty : 1;
|
} hwrng_buf_t;
|
||||||
}) hwrng_buf_t;
|
|
||||||
|
|
||||||
static mutex_t hwrng_mutex;
|
static mutex_t hwrng_mutex;
|
||||||
static bool hwrng_mutex_initialized = false;
|
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->buf = p;
|
||||||
rb->size = size;
|
rb->size = size;
|
||||||
rb->head = rb->tail = 0;
|
rb->head = rb->tail = 0;
|
||||||
rb->full = 0;
|
rb->count = 0;
|
||||||
rb->empty = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hwrng_buf_add(struct hwrng_buf *rb, uint32_t v) {
|
static size_t hwrng_buf_add(struct hwrng_buf *rb, const uint8_t *data, size_t len) {
|
||||||
if (rb->full) {
|
size_t room = rb->size - rb->count;
|
||||||
return;
|
size_t n = len < room ? len : room;
|
||||||
}
|
size_t tail = rb->tail;
|
||||||
|
size_t first = n;
|
||||||
|
|
||||||
uint8_t tail = rb->tail;
|
if (first > rb->size - tail) {
|
||||||
rb->buf[tail] = v;
|
first = rb->size - tail;
|
||||||
tail++;
|
}
|
||||||
if (tail >= rb->size) {
|
if (first) {
|
||||||
tail = 0;
|
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->tail = tail;
|
||||||
rb->full = (rb->tail == rb->head);
|
rb->count += n;
|
||||||
rb->empty = 0;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t hwrng_buf_del(struct hwrng_buf *rb) {
|
static size_t hwrng_buf_del(struct hwrng_buf *rb, uint8_t *data, size_t len) {
|
||||||
uint32_t v = 0;
|
size_t n = len < rb->count ? len : rb->count;
|
||||||
if (rb->empty) {
|
size_t head = rb->head;
|
||||||
return v;
|
size_t first = n;
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t head = rb->head;
|
if (first > rb->size - head) {
|
||||||
v = rb->buf[head];
|
first = rb->size - head;
|
||||||
head++;
|
}
|
||||||
if (head >= rb->size) {
|
if (first) {
|
||||||
head = 0;
|
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;
|
rb->head = head;
|
||||||
if (rb->head == rb->tail) {
|
rb->count -= n;
|
||||||
rb->empty = 1;
|
return n;
|
||||||
}
|
}
|
||||||
rb->full = 0;
|
|
||||||
|
|
||||||
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;
|
static struct hwrng_buf ring_buffer;
|
||||||
@@ -146,24 +165,15 @@ static struct hwrng_buf ring_buffer;
|
|||||||
void *hwrng_task(void) {
|
void *hwrng_task(void) {
|
||||||
struct hwrng_buf *rb = &ring_buffer;
|
struct hwrng_buf *rb = &ring_buffer;
|
||||||
|
|
||||||
int n;
|
|
||||||
|
|
||||||
hwrng_lock();
|
hwrng_lock();
|
||||||
if ((n = hwrng_mix_process())) {
|
if (hwrng_buf_space(rb) >= sizeof(random_word) && hwrng_mix_process()) {
|
||||||
const uint32_t *vp = (const uint32_t *) &random_word;
|
hwrng_buf_add(rb, (const uint8_t *)&random_word, sizeof(random_word));
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
hwrng_buf_add(rb, *vp++);
|
|
||||||
if (rb->full) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
hwrng_unlock();
|
hwrng_unlock();
|
||||||
return NULL;
|
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;
|
struct hwrng_buf *rb = &ring_buffer;
|
||||||
|
|
||||||
mutex_init(&hwrng_mutex);
|
mutex_init(&hwrng_mutex);
|
||||||
@@ -175,28 +185,36 @@ void hwrng_init(uint32_t *buf, uint8_t size) {
|
|||||||
hwrng_mix_init();
|
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) {
|
void hwrng_flush(void) {
|
||||||
struct hwrng_buf *rb = &ring_buffer;
|
struct hwrng_buf *rb = &ring_buffer;
|
||||||
hwrng_lock();
|
hwrng_lock();
|
||||||
while (!rb->empty) {
|
rb->head = 0;
|
||||||
hwrng_buf_del(rb);
|
rb->tail = 0;
|
||||||
}
|
rb->count = 0;
|
||||||
hwrng_unlock();
|
hwrng_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t hwrng_get(void) {
|
uint32_t hwrng_get(void) {
|
||||||
struct hwrng_buf *rb = &ring_buffer;
|
uint32_t v = 0;
|
||||||
uint32_t v;
|
size_t offset = 0;
|
||||||
|
|
||||||
while (true) {
|
while (offset < sizeof(v)) {
|
||||||
hwrng_lock();
|
size_t n = hwrng_read(((uint8_t *)&v) + offset, sizeof(v) - offset);
|
||||||
if (!rb->empty) {
|
if (n == 0) {
|
||||||
v = hwrng_buf_del(rb);
|
hwrng_task();
|
||||||
hwrng_unlock();
|
continue;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
hwrng_unlock();
|
offset += n;
|
||||||
hwrng_task();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
@@ -211,8 +229,9 @@ void hwrng_wait_full(void) {
|
|||||||
#endif
|
#endif
|
||||||
while (true) {
|
while (true) {
|
||||||
hwrng_lock();
|
hwrng_lock();
|
||||||
|
bool full = hwrng_buf_full(rb);
|
||||||
hwrng_unlock();
|
hwrng_unlock();
|
||||||
if (rb->full) {
|
if (full) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
|
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
|
||||||
|
|||||||
@@ -18,11 +18,13 @@
|
|||||||
#ifndef _NEUG_H_
|
#ifndef _NEUG_H_
|
||||||
#define _NEUG_H_
|
#define _NEUG_H_
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
void hwrng_init(uint32_t *buf, uint8_t size);
|
void hwrng_init(uint8_t *buf, size_t size);
|
||||||
uint32_t hwrng_get(void);
|
size_t hwrng_read(uint8_t *buf, size_t len);
|
||||||
void hwrng_flush(void);
|
void hwrng_flush(void);
|
||||||
void hwrng_wait_full(void);
|
void hwrng_wait_full(void);
|
||||||
void *hwrng_task(void);
|
void *hwrng_task(void);
|
||||||
|
uint32_t hwrng_get(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,38 +20,18 @@
|
|||||||
#include "picokeys.h"
|
#include "picokeys.h"
|
||||||
#include "hwrng.h"
|
#include "hwrng.h"
|
||||||
#include "random.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
|
#define RANDOM_BYTES_LENGTH 32
|
||||||
static uint32_t random_word[RANDOM_BYTES_LENGTH / sizeof(uint32_t)];
|
static uint8_t random_pool[256];
|
||||||
static mutex_t random_mutex;
|
|
||||||
static bool random_mutex_initialized = false;
|
|
||||||
|
|
||||||
void random_init(void) {
|
void random_init(void) {
|
||||||
mutex_init(&random_mutex);
|
hwrng_init(random_pool, sizeof(random_pool));
|
||||||
random_mutex_initialized = true;
|
|
||||||
hwrng_init(random_word, RANDOM_BYTES_LENGTH / sizeof(uint32_t));
|
|
||||||
|
|
||||||
for (int i = 0; i < HWRNG_PRE_LOOP; i++) {
|
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
|
* Return pointer to random 32-byte
|
||||||
*/
|
*/
|
||||||
@@ -60,17 +40,9 @@ const uint8_t *random_bytes_get(size_t len) {
|
|||||||
if (len > MAX_RANDOM_BUFFER) {
|
if (len > MAX_RANDOM_BUFFER) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
static uint32_t return_word[MAX_RANDOM_BUFFER / sizeof(uint32_t)];
|
static uint8_t return_word[MAX_RANDOM_BUFFER];
|
||||||
if (random_mutex_initialized) {
|
if (random_fill_buffer(return_word, len) != 0) {
|
||||||
mutex_enter_blocking(&random_mutex);
|
return NULL;
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
return (const uint8_t *) return_word;
|
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) {
|
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;
|
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;
|
int ret = 0;
|
||||||
|
|
||||||
if (random_mutex_initialized) {
|
|
||||||
mutex_enter_blocking(&random_mutex);
|
|
||||||
}
|
|
||||||
while (out_len) {
|
while (out_len) {
|
||||||
if (ctx && ctx->cancel) {
|
if (ctx && ctx->cancel) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
hwrng_wait_full();
|
size_t n = hwrng_read(out, out_len);
|
||||||
|
if (n == 0) {
|
||||||
n = RANDOM_BYTES_LENGTH - index;
|
hwrng_task();
|
||||||
if (n > out_len) {
|
continue;
|
||||||
n = (uint8_t)out_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(out, ((unsigned char *) random_word) + index, n);
|
|
||||||
out += n;
|
out += n;
|
||||||
out_len -= n;
|
out_len -= n;
|
||||||
index += n;
|
if (ctx) {
|
||||||
|
ctx->index = (uint8_t)((ctx->index + n) % RANDOM_BYTES_LENGTH);
|
||||||
if (index >= RANDOM_BYTES_LENGTH) {
|
|
||||||
index = 0;
|
|
||||||
hwrng_flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx) {
|
|
||||||
ctx->index = index;
|
|
||||||
}
|
|
||||||
if (random_mutex_initialized) {
|
|
||||||
mutex_exit(&random_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user