stm32/rng: Use SysTick+RTC+unique-id to seed pRNG for MCUs without RNG.

The same seed will only occur if the board is the same, the RTC has the
same time (eg freshly powered up) and the first call to this function (eg
via an "import random") is done at exactly the same time since reset.

Signed-off-by: Damien George <damien@micropython.org>
bound-method-equality
Damien George 2020-10-20 14:17:46 +11:00
parent 59019d7f75
commit 3e455e9792
1 changed files with 13 additions and 2 deletions

View File

@ -24,6 +24,7 @@
* THE SOFTWARE.
*/
#include "rtc.h"
#include "rng.h"
#if MICROPY_HW_ENABLE_RNG
@ -63,16 +64,26 @@ MP_DEFINE_CONST_FUN_OBJ_0(pyb_rng_get_obj, pyb_rng_get);
#else // MICROPY_HW_ENABLE_RNG
// For MCUs that don't have an RNG we still need to provide a rng_get() function,
// eg for lwIP. A pseudo-RNG is not really ideal but we go with it for now. We
// eg for lwIP and random.seed(). A pseudo-RNG is not really ideal but we go with
// it for now, seeding with numbers which will be somewhat different each time. We
// don't want to use urandom's pRNG because then the user won't see a reproducible
// random stream.
// Yasmarang random number generator by Ilya Levin
// http://www.literatecode.com/yasmarang
STATIC uint32_t pyb_rng_yasmarang(void) {
static uint32_t pad = 0xeda4baba, n = 69, d = 233;
static bool seeded = false;
static uint32_t pad = 0, n = 0, d = 0;
static uint8_t dat = 0;
if (!seeded) {
seeded = true;
rtc_init_finalise();
pad = *(uint32_t *)MP_HAL_UNIQUE_ID_ADDRESS ^ SysTick->VAL;
n = RTC->TR;
d = RTC->SSR;
}
pad += dat + d * n;
pad = (pad << 3) + (pad >> 29);
n = pad | 2;