From 6f06dcaee57cc6f36a4121b4797942200b2d7281 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Wed, 17 Mar 2021 07:57:27 +0100 Subject: [PATCH] rp2/moduos: Implement uos.urandom(). The implementation samples rosc.randombits at a frequency lower than the oscillator frequency. This gives better random values. In addition, for an 8-bit value 8 samples are taken and fed through a 8-bit CRC, distributing the sampling over the byte. The resulting sampling rate is about 120k/sec. The RNG does not include testing of error conditions, like the ROSC being in sync with the sampling or completely failing. Making the interim value static causes it to perform a little bit better in short sync or drop-out situations. The output of uos.urandom() performs well with the NIST800-22 test suite. In my trial it passed all tests of the sts 2.1.2 test suite. I also ran a test of the random data with the Common Criteria test suite AIS 31, and it passed all tests too. --- ports/rp2/main.c | 16 ++++++++++++++-- ports/rp2/moduos.c | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/ports/rp2/main.c b/ports/rp2/main.c index 64218f97c5..8fddeaa560 100644 --- a/ports/rp2/main.c +++ b/ports/rp2/main.c @@ -30,6 +30,7 @@ #include "py/runtime.h" #include "py/gc.h" #include "py/mperrno.h" +#include "py/mphal.h" #include "py/stackctrl.h" #include "lib/mp-readline/readline.h" #include "lib/utils/gchelper.h" @@ -168,10 +169,21 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c } #endif +#define POLY (0xD5) + +uint8_t rosc_random_u8(size_t cycles) { + static uint8_t r; + for (size_t i = 0; i < cycles; ++i) { + r = ((r << 1) | rosc_hw->randombit) ^ (r & 0x80 ? POLY : 0); + mp_hal_delay_us_fast(1); + } + return r; +} + uint32_t rosc_random_u32(void) { uint32_t value = 0; - for (size_t i = 0; i < 32; ++i) { - value = value << 1 | rosc_hw->randombit; + for (size_t i = 0; i < 4; ++i) { + value = value << 8 | rosc_random_u8(32); } return value; } diff --git a/ports/rp2/moduos.c b/ports/rp2/moduos.c index 7ee662b5a4..02f34eb960 100644 --- a/ports/rp2/moduos.c +++ b/ports/rp2/moduos.c @@ -31,6 +31,8 @@ #include "extmod/vfs_lfs.h" #include "genhdr/mpversion.h" +uint8_t rosc_random_u8(size_t cycles); + STATIC const qstr os_uname_info_fields[] = { MP_QSTR_sysname, MP_QSTR_nodename, MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine @@ -57,10 +59,22 @@ STATIC mp_obj_t os_uname(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); +STATIC mp_obj_t os_urandom(mp_obj_t num) { + mp_int_t n = mp_obj_get_int(num); + vstr_t vstr; + vstr_init_len(&vstr, n); + for (int i = 0; i < n; i++) { + vstr.buf[i] = rosc_random_u8(8); + } + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); + STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, + { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) }, #if MICROPY_VFS { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },