From b11026689724830fcfcb5060df2c5a17cb4dbc65 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 14 Feb 2023 10:02:22 +0100 Subject: [PATCH] samd/moduos: Add uos.urandom() using the phase-jitter rng. This RNG passes many of the Diehard tests and also the AIS31 test suite. The RNG is quite slow, delivering 200bytes/s. Tested on boards with and without a crystal. --- ports/samd/mcu/samd21/mpconfigmcu.h | 5 +++-- ports/samd/moduos.c | 20 ++++++++++++++++++-- ports/samd/samd_isr.c | 9 +-------- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h index 150a378a3e..db4e58753c 100644 --- a/ports/samd/mcu/samd21/mpconfigmcu.h +++ b/ports/samd/mcu/samd21/mpconfigmcu.h @@ -22,8 +22,8 @@ #define MICROPY_PY_CMATH (0) #endif -#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32()) -unsigned long trng_random_u32(void); +#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32(300)) +unsigned long trng_random_u32(int delay); #define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages; @@ -36,6 +36,7 @@ unsigned long trng_random_u32(void); #define MICROPY_PY_MACHINE_RTC (1) #endif #endif +#define MICROPY_PY_UOS_URANDOM (1) #ifndef MICROPY_PY_MACHINE_PIN_BOARD_CPU #define MICROPY_PY_MACHINE_PIN_BOARD_CPU (1) diff --git a/ports/samd/moduos.c b/ports/samd/moduos.c index e0237fd88f..3404919d24 100644 --- a/ports/samd/moduos.c +++ b/ports/samd/moduos.c @@ -52,6 +52,23 @@ uint32_t trng_random_u32(void) { return REG_TRNG_DATA; } +#define TRNG_RANDOM_U32 trng_random_u32() +#endif // defined(MCU_SAMD51) + +#if defined(MCU_SAMD21) +extern volatile uint32_t rng_state; + +uint32_t trng_random_u32(int delay) { + mp_hal_delay_ms(delay); // wait a few cycles + uint32_t upper = rng_state; + mp_hal_delay_ms(delay); // wait again a few cycles + return (upper & 0xffff0000) | (rng_state >> 16); +} + +#define trng_start() +#define TRNG_RANDOM_U32 trng_random_u32(10) +#endif + #if MICROPY_PY_UOS_URANDOM STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { mp_int_t n = mp_obj_get_int(num); @@ -62,7 +79,7 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { trng_start(); for (int i = 0; i < n; i++) { if ((i % 4) == 0) { - rngval = trng_random_u32(); + rngval = TRNG_RANDOM_U32; } vstr.buf[i] = rngval & 0xff; rngval >>= 8; @@ -72,7 +89,6 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom); #endif // MICROPY_PY_UOS_URANDOM -#endif // defined(MCU_SAMD51) #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream) { diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index 838800bdbb..a12140313b 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -96,7 +96,7 @@ void Default_Handler(void) { void SysTick_Handler(void) { #if defined(MCU_SAMD21) // Use the phase jitter between the clocks to get some entropy - // and accumulate the random number register. + // and accumulate the random number register with a "spiced" LCG. rng_state = (rng_state * 32310901 + 1) ^ (REG_TC4_COUNT32_COUNT >> 1); #endif @@ -108,13 +108,6 @@ void SysTick_Handler(void) { } } -#if defined(MCU_SAMD21) -uint32_t trng_random_u32(void) { - mp_hal_delay_ms(320); // wait for ten cycles of the rng_seed register - return rng_state; -} -#endif - void us_timer_IRQ(void) { #if defined(MCU_SAMD21) if (TC4->COUNT32.INTFLAG.reg & TC_INTFLAG_OVF) {