/** * Copyright (C) 2017 Kaspar Schleiser * 2019 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /** * @ingroup sys_random * @{ * @file * * @brief PRNG seeding * * @author Kaspar Schleiser * @author Hauke Petersen * @} */ #include #include #include "log.h" #include "random.h" #include "bitarithm.h" #ifdef MODULE_PUF_SRAM #include "puf_sram.h" #endif #ifdef MODULE_PERIPH_HWRNG #include "periph/hwrng.h" #endif #ifdef MODULE_PERIPH_CPUID #include "luid.h" #endif #define ENABLE_DEBUG 0 #include "debug.h" void auto_init_random(void) { uint32_t seed; #ifdef MODULE_PUF_SRAM /* TODO: hand state to application? */ if (puf_sram_state) { LOG_WARNING("random: PUF SEED not fresh\n"); } seed = puf_sram_seed; #elif defined (MODULE_PERIPH_HWRNG) hwrng_read(&seed, 4); #elif defined (MODULE_PERIPH_CPUID) luid_get(&seed, 4); #else LOG_WARNING("random: NO SEED AVAILABLE!\n"); seed = RANDOM_SEED_DEFAULT; #endif DEBUG("random: using seed value %u\n", (unsigned)seed); random_init(seed); } void random_bytes(void *target, size_t n) { uint32_t random; uint8_t *dst = target; uint8_t *random_pos = (uint8_t*)&random; unsigned _n = 0; while (n--) { if (! (_n++ & 0x3)) { random = random_uint32(); random_pos = (uint8_t *) &random; } *dst++ = *random_pos++; } } uint32_t random_uint32_range(uint32_t a, uint32_t b) { assert(a < b); uint32_t divisor, rand_val, range = b - a; uint8_t range_msb = bitarithm_msb(range); /* check if range is a power of two */ if (!(range & (range - 1))) { divisor = (1 << range_msb) - 1; } else if (range_msb < 31) { /* leftshift for next power of two interval */ divisor = (1 << (range_msb + 1)) -1; } else { /* disable modulo operation in loop below */ divisor = UINT32_MAX; } /* get random numbers until value is smaller than range */ do { rand_val = (random_uint32() & divisor); } while (rand_val >= range); /* return random in range [a,b] */ return (rand_val + a); }