From d7d5515c67783f711b8d4ade9eaf6c575db557b1 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 13 Jun 2024 16:20:32 +0200 Subject: [PATCH 1/2] Enable trng support for STM32H7 boards --- cores/arduino/WMath.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/cores/arduino/WMath.cpp b/cores/arduino/WMath.cpp index f4ce2b754..9e1c2103a 100644 --- a/cores/arduino/WMath.cpp +++ b/cores/arduino/WMath.cpp @@ -23,10 +23,36 @@ extern "C" { #include "stdlib.h" + #include "hal/trng_api.h" } +#if defined(ARDUINO_PORTENTA_H7_M7) || \ + defined(ARDUINO_NICLA_VISION) || \ + defined(ARDUINO_OPTA) || \ + defined(ARDUINO_GIGA) +#define MBED_TRNG_SUPPORT 1 +static long trng() +{ + trng_t trng_obj; + trng_init(&trng_obj); + long value; + size_t olen; + if (trng_get_bytes(&trng_obj, (uint8_t*)&value, sizeof(value), &olen) != 0) + return -1; + trng_free(&trng_obj); + return value >= 0 ? value : -value; +} +#endif + +#if (MBED_TRNG_SUPPORT == 1) +static bool useTRNG = true; +#endif + void randomSeed(unsigned long seed) { +#if (MBED_TRNG_SUPPORT == 1) + useTRNG = false; +#endif if (seed != 0) { srandom(seed); } @@ -37,6 +63,11 @@ long random(long howbig) if (howbig == 0) { return 0; } +#if (MBED_TRNG_SUPPORT == 1) + if (useTRNG == true) { + return trng() % howbig; + } +#endif return random() % howbig; } @@ -48,3 +79,5 @@ long random(long howsmall, long howbig) long diff = howbig - howsmall; return random(diff) + howsmall; } + +#undef MBED_TRNG_SUPPORT From 447062f89f15733b1b8a664e342a7bafa720b2d1 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 17 Jun 2024 10:46:37 +0200 Subject: [PATCH 2/2] Enable (t)rng support for NANO RP2040 --- cores/arduino/WMath.cpp | 4 +- .../0231-RP2040-add-pico_rand-support.patch | 725 ++++++++++++++++++ 2 files changed, 727 insertions(+), 2 deletions(-) create mode 100644 patches/0231-RP2040-add-pico_rand-support.patch diff --git a/cores/arduino/WMath.cpp b/cores/arduino/WMath.cpp index 9e1c2103a..aec2b4d6d 100644 --- a/cores/arduino/WMath.cpp +++ b/cores/arduino/WMath.cpp @@ -25,8 +25,8 @@ extern "C" { #include "stdlib.h" #include "hal/trng_api.h" } - -#if defined(ARDUINO_PORTENTA_H7_M7) || \ +#if defined(ARDUINO_NANO_RP2040_CONNECT) || \ + defined(ARDUINO_PORTENTA_H7_M7) || \ defined(ARDUINO_NICLA_VISION) || \ defined(ARDUINO_OPTA) || \ defined(ARDUINO_GIGA) diff --git a/patches/0231-RP2040-add-pico_rand-support.patch b/patches/0231-RP2040-add-pico_rand-support.patch new file mode 100644 index 000000000..9afe7ca99 --- /dev/null +++ b/patches/0231-RP2040-add-pico_rand-support.patch @@ -0,0 +1,725 @@ +From ac5c21fad54214e10a3558f29195d7ea70b4ccec Mon Sep 17 00:00:00 2001 +From: pennam +Date: Mon, 17 Jun 2024 10:19:14 +0200 +Subject: [PATCH] RP2040: add pico_rand support + +--- + .../TARGET_RP2040/CMakeLists.txt | 2 + + .../TARGET_RP2040/objects.h | 7 + + .../pico-sdk/rp2_common/CMakeLists.txt | 1 + + .../hardware_sync/include/hardware/sync.h | 5 + + .../pico_platform/include/pico/platform.h | 6 +- + .../rp2_common/pico_rand/CMakeLists.txt | 13 + + .../rp2_common/pico_rand/include/pico/rand.h | 185 +++++++++++ + .../pico-sdk/rp2_common/pico_rand/rand.c | 305 ++++++++++++++++++ + .../TARGET_RP2040/trng_api.c | 64 ++++ + targets/targets.json | 3 +- + 10 files changed, 587 insertions(+), 4 deletions(-) + create mode 100644 targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/CMakeLists.txt + create mode 100644 targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/include/pico/rand.h + create mode 100644 targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/rand.c + create mode 100644 targets/TARGET_RASPBERRYPI/TARGET_RP2040/trng_api.c + +diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/CMakeLists.txt b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/CMakeLists.txt +index 4fadf6091e..4e9bae47ce 100644 +--- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/CMakeLists.txt ++++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/CMakeLists.txt +@@ -36,6 +36,7 @@ target_include_directories(mbed-rp2040 + pico-sdk/common/pico_base/include + pico-sdk/common/pico_binary_info/include + pico-sdk/common/pico_util/include ++ pico-sdk/common/pico_rand/include + pico-sdk/boards/include + pico-sdk/generated + . +@@ -71,6 +72,7 @@ target_sources(mbed-rp2040 + pico-sdk/rp2_common/pico_bootrom/bootrom.c + pico-sdk/rp2_common/pico_runtime/runtime.c + pico-sdk/rp2_common/pico_platform/platform.c ++ pico-sdk/rp2_common/pico_rand/rand.c + pico-sdk/common/pico_sync/mutex.c + pico-sdk/common/pico_time/time.c + pico-sdk/common/pico_sync/lock_core.c +diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/objects.h b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/objects.h +index f5f44a58f4..0231968bb5 100644 +--- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/objects.h ++++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/objects.h +@@ -33,6 +33,7 @@ extern "C" { + #include "pico/assert.h" + #include "pico/time.h" + #include "pico/types.h" ++#include "pico/rand.h" + #include "hardware/pwm.h" + #include "hardware/adc.h" + #include "hardware/resets.h" +@@ -122,6 +123,12 @@ struct flash_s { + uint32_t dummy; + }; + ++#if DEVICE_TRNG ++struct trng_s { ++ uint8_t not_used; ++}; ++#endif ++ + typedef struct gpio_s gpio_t; + typedef struct serial_s serial_t; + +diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/CMakeLists.txt b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/CMakeLists.txt +index 4ca55becba..ec89c3ff71 100644 +--- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/CMakeLists.txt ++++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/CMakeLists.txt +@@ -49,6 +49,7 @@ if (NOT PICO_BARE_METAL) + pico_add_subdirectory(pico_mem_ops) + pico_add_subdirectory(pico_malloc) + pico_add_subdirectory(pico_printf) ++ pico_add_subdirectory(pico_rand) + + pico_add_subdirectory(pico_stdio) + pico_add_subdirectory(pico_stdio_semihosting) +diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_sync/include/hardware/sync.h b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_sync/include/hardware/sync.h +index 8f91d55955..4f076aba02 100644 +--- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_sync/include/hardware/sync.h ++++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_sync/include/hardware/sync.h +@@ -70,6 +70,11 @@ typedef volatile uint32_t spin_lock_t; + #define PICO_SPINLOCK_ID_HARDWARE_CLAIM 11 + #endif + ++// PICO_CONFIG: PICO_SPINLOCK_ID_RAND, Spinlock ID for Random Number Generator, min=0, max=31, default=12, group=hardware_sync ++#ifndef PICO_SPINLOCK_ID_RAND ++#define PICO_SPINLOCK_ID_RAND 12 ++#endif ++ + // PICO_CONFIG: PICO_SPINLOCK_ID_OS1, First Spinlock ID reserved for use by low level OS style software, min=0, max=31, default=14, group=hardware_sync + #ifndef PICO_SPINLOCK_ID_OS1 + #define PICO_SPINLOCK_ID_OS1 14 +diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_platform/include/pico/platform.h b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_platform/include/pico/platform.h +index ee1d360cee..ea16d9734e 100644 +--- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_platform/include/pico/platform.h ++++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_platform/include/pico/platform.h +@@ -151,14 +151,14 @@ extern "C" { + * + * For example a `uint32_t` foo that will retain its value if the program is restarted by reset. + * +- * uint32_t __uninitialized_ram("my_group_name") foo; ++ * uint32_t __uninitialized_ram(foo); + * +- * The section attribute is `.uninitialized_ram.` ++ * The section attribute is `.uninitialized_data.` + * + * \param group a string suffix to use in the section name to distinguish groups that can be linker + * garbage-collected independently + */ +-#define __uninitialized_ram(group) __attribute__((section(".uninitialized_ram." #group))) group ++#define __uninitialized_ram(group) __attribute__((section(".uninitialized_data." #group))) group + + /*! \brief Section attribute macro for placement in flash even in a COPY_TO_RAM binary + * \ingroup pico_platform +diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/CMakeLists.txt b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/CMakeLists.txt +new file mode 100644 +index 0000000000..0e72bb5ab6 +--- /dev/null ++++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/CMakeLists.txt +@@ -0,0 +1,13 @@ ++pico_add_library(pico_rand) ++ ++target_sources(pico_rand INTERFACE ++ ${CMAKE_CURRENT_LIST_DIR}/rand.c ++) ++ ++target_include_directories(pico_rand_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) ++ ++pico_mirrored_target_link_libraries(pico_rand INTERFACE ++ pico_unique_id ++ hardware_clocks ++ hardware_timer ++ hardware_sync) +diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/include/pico/rand.h b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/include/pico/rand.h +new file mode 100644 +index 0000000000..20fc6d6cb1 +--- /dev/null ++++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/include/pico/rand.h +@@ -0,0 +1,185 @@ ++/* ++ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef _PICO_RAND_H ++#define _PICO_RAND_H ++ ++#include "pico.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** \file pico/rand.h ++ * \defgroup pico_rand pico_rand ++ * ++ * Random Number Generator API ++ * ++ * This module generates random numbers at runtime utilizing a number of possible entropy ++ * sources and uses those sources to modify the state of a 128-bit 'Pseudo ++ * Random Number Generator' implemented in software. ++ * ++ * The random numbers (32 to 128 bit) to be supplied are read from the PRNG which is used ++ * to help provide a large number space. ++ * ++ * The following (multiple) sources of entropy are available (of varying quality), each enabled by a #define: ++ * ++ * - The Ring Oscillator (ROSC) (\ref PICO_RAND_ENTROPY_SRC_ROSC == 1): ++ * \ref PICO_RAND_ROSC_BIT_SAMPLE_COUNT bits are gathered from the ring oscillator "random bit" and mixed in each ++ * time. This should not be used if the ROSC is off, or the processor is running from ++ * the ROSC. ++ * \note the maximum throughput of ROSC bit sampling is controlled by PICO_RAND_MIN_ROSC_BIT_SAMPLE_TIME_US which defaults ++ * to 10us, i.e. 100,000 bits per second. ++ * - Time (\ref PICO_RAND_ENTROPY_SRC_TIME == 1): The 64-bit microsecond timer is mixed in each time. ++ * - Bus Performance Counter (\ref PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER == 1): One of the bus fabric's performance ++ * counters is mixed in each time. ++ * ++ * \note All entropy sources are hashed before application to the PRNG state machine. ++ * ++ * The \em first time a random number is requested, the 128-bit PRNG state ++ * must be seeded. Multiple entropy sources are also available for the seeding operation: ++ * ++ * - The Ring Oscillator (ROSC) (\ref PICO_RAND_SEED_ENTROPY_SRC_ROSC == 1): ++ * 64 bits are gathered from the ring oscillator "random bit" and mixed into the seed. ++ * - Time (\ref PICO_RAND_SEED_ENTROPY_SRC_TIME == 1): The 64-bit microsecond timer is mixed into the seed. ++ * - Board Identifier (PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID == 1): The board id via \ref pico_get_unique_board_id ++ * is mixed into the seed. ++ * - RAM hash (\ref PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH (\ref PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH): The hashed contents of a ++ * subset of RAM are mixed in. Initial RAM contents are undefined on power up, so provide a reasonable source of entropy. ++ * By default the last 1K of RAM (which usually contains the core 0 stack) is hashed, which may also provide for differences ++ * after each warm reset. ++ * ++ * With default settings, the seed generation takes approximately 1 millisecond while ++ * subsequent random numbers generally take between 10 and 20 microseconds to generate. ++ * ++ * pico_rand methods may be safely called from either core or from an IRQ, but be careful in the latter case as ++ * the calls may block for a number of microseconds waiting on more entropy. ++ */ ++ ++// --------------- ++// ENTROPY SOURCES ++// --------------- ++ ++// PICO_CONFIG: PICO_RAND_ENTROPY_SRC_ROSC, Enable/disable use of ROSC as an entropy source, type=bool, default=1, group=pico_rand ++#ifndef PICO_RAND_ENTROPY_SRC_ROSC ++#define PICO_RAND_ENTROPY_SRC_ROSC 1 ++#endif ++ ++// PICO_CONFIG: PICO_RAND_ENTROPY_SRC_TIME, Enable/disable use of hardware timestamp as an entropy source, type=bool, default=1, group=pico_rand ++#ifndef PICO_RAND_ENTROPY_SRC_TIME ++#define PICO_RAND_ENTROPY_SRC_TIME 1 ++#endif ++ ++// PICO_CONFIG: PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER, Enable/disable use of a bus performance counter as an entropy source, type=bool, default=1, group=pico_rand ++#ifndef PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER ++#define PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER 1 ++#endif ++ ++// -------------------- ++// SEED ENTROPY SOURCES ++// -------------------- ++ ++// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_ROSC, Enable/disable use of ROSC as an entropy source for the random seed, type=bool, default=1, group=pico_rand ++#ifndef PICO_RAND_SEED_ENTROPY_SRC_ROSC ++#define PICO_RAND_SEED_ENTROPY_SRC_ROSC PICO_RAND_ENTROPY_SRC_ROSC ++#endif ++ ++// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_TIME, Enable/disable use of hardware timestamp as an entropy source for the random seed, type=bool, default=1, group=pico_rand ++#ifndef PICO_RAND_SEED_ENTROPY_SRC_TIME ++#define PICO_RAND_SEED_ENTROPY_SRC_TIME PICO_RAND_ENTROPY_SRC_TIME ++#endif ++ ++// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID, Enable/disable use of board id as part of the random seed, type=bool, default=1, group=pico_rand ++#ifndef PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID ++#define PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID 0 ++#endif ++ ++// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH, Enable/disable use of a RAM hash as an entropy source for the random seed, type=bool, default=1, group=pico_rand ++#ifndef PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH ++#define PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH 1 ++#endif ++ ++// --------------------------------- ++// PICO_RAND_ENTROPY_SRC_ROSC CONFIG ++// --------------------------------- ++ ++// PICO_CONFIG: PICO_RAND_ROSC_BIT_SAMPLE_COUNT, Number of samples to take of the ROSC random bit per random number generation , min=1, max=64, default=1, group=pico_rand ++#ifndef PICO_RAND_ROSC_BIT_SAMPLE_COUNT ++#define PICO_RAND_ROSC_BIT_SAMPLE_COUNT 1 ++#endif ++ ++// PICO_CONFIG: PICO_RAND_MIN_ROSC_BIT_SAMPLE_TIME_US, Define a default minimum time between sampling the ROSC random bit, min=5, max=20, default=10, group=pico_rand ++#ifndef PICO_RAND_MIN_ROSC_BIT_SAMPLE_TIME_US ++// (Arbitrary / tested) minimum time between sampling the ROSC random bit ++#define PICO_RAND_MIN_ROSC_BIT_SAMPLE_TIME_US 10u ++#endif ++ ++// --------------------------------------------- ++// PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER CONFIG ++// --------------------------------------------- ++ ++// PICO_CONFIG: PICO_RAND_BUS_PERF_COUNTER_INDEX, Bus performance counter index to use for sourcing entropy, min=0, max=3, group=pico_rand ++// this is deliberately undefined by default, meaning the code will pick that appears unused ++//#define PICO_RAND_BUS_PERF_COUNTER_INDEX 0 ++ ++// PICO_CONFIG: PICO_RAND_BUS_PERF_COUNTER_EVENT, Bus performance counter event to use for sourcing entropy, default=arbiter_sram5_perf_event_access, group=pico_rand ++#ifndef PICO_RAND_BUS_PERF_COUNTER_EVENT ++#define PICO_RAND_BUS_PERF_COUNTER_EVENT arbiter_sram5_perf_event_access ++#endif ++ ++// ------------------------------------------ ++// PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH CONFIG ++// ------------------------------------------ ++ ++// PICO_CONFIG: PICO_RAND_RAM_HASH_END, end of address in RAM (non-inclusive) to hash during pico_rand seed initialization, default=SRAM_END, group=pico_rand ++#ifndef PICO_RAND_RAM_HASH_END ++#define PICO_RAND_RAM_HASH_END SRAM_END ++#endif ++// PICO_CONFIG: PICO_RAND_RAM_HASH_START, start of address in RAM (inclusive) to hash during pico_rand seed initialization, default=PICO_RAND_RAM_HASH_END - 1024, group=pico_rand ++#ifndef PICO_RAND_RAM_HASH_START ++#define PICO_RAND_RAM_HASH_START (PICO_RAND_RAM_HASH_END - 1024u) ++#endif ++ ++// We provide a maximum of 128 bits entropy in one go ++typedef struct rng_128 { ++ uint64_t r[2]; ++} rng_128_t; ++ ++/*! \brief Get 128-bit random number ++ * \ingroup pico_rand ++ * ++ * This method may be safely called from either core or from an IRQ, but be careful in the latter case as ++ * the call may block for a number of microseconds waiting on more entropy. ++ * ++ * \param rand128 Pointer to storage to accept a 128-bit random number ++ */ ++void get_rand_128(rng_128_t *rand128); ++ ++/*! \brief Get 64-bit random number ++ * \ingroup pico_rand ++ * ++ * This method may be safely called from either core or from an IRQ, but be careful in the latter case as ++ * the call may block for a number of microseconds waiting on more entropy. ++ * ++ * \return 64-bit random number ++ */ ++uint64_t get_rand_64(void); ++ ++/*! \brief Get 32-bit random number ++ * \ingroup pico_rand ++ * ++ * This method may be safely called from either core or from an IRQ, but be careful in the latter case as ++ * the call may block for a number of microseconds waiting on more entropy. ++ * ++ * \return 32-bit random number ++ */ ++uint32_t get_rand_32(void); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/rand.c b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/rand.c +new file mode 100644 +index 0000000000..c73b80321e +--- /dev/null ++++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/rand.c +@@ -0,0 +1,305 @@ ++/* ++ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* xoroshiro128ss(), rotl(): ++ ++ Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) ++ ++ To the extent possible under law, the author has dedicated all copyright ++ and related and neighboring rights to this software to the public domain ++ worldwide. This software is distributed without any warranty. ++ ++ See ++ ++ splitmix64() implementation: ++ ++ Written in 2015 by Sebastiano Vigna (vigna@acm.org) ++ To the extent possible under law, the author has dedicated all copyright ++ and related and neighboring rights to this software to the public domain ++ worldwide. This software is distributed without any warranty. ++ ++ See ++*/ ++ ++#include "pico/rand.h" ++#if PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID ++#include "pico/unique_id.h" ++#endif ++#include "pico/time.h" ++#include "hardware/clocks.h" ++#include "hardware/structs/rosc.h" ++#include "hardware/structs/bus_ctrl.h" ++#include "hardware/sync.h" ++ ++static bool rng_initialised = false; ++ ++// Note: By design, do not initialise any of the variables that hold entropy, ++// they may have useful junk in them, either from power-up or a previous boot. ++static rng_128_t __uninitialized_ram(rng_state); ++#if PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH ++static uint64_t __uninitialized_ram(ram_hash); ++#endif ++ ++#if PICO_RAND_ENTROPY_SRC_ROSC | PICO_RAND_SEED_ENTROPY_SRC_ROSC ++static uint64_t __uninitialized_ram(rosc_samples); ++#endif ++ ++#if PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER ++static uint8_t bus_counter_idx; ++#endif ++ ++/* From the original source: ++ ++ This is a fixed-increment version of Java 8's SplittableRandom generator ++ See http://dx.doi.org/10.1145/2714064.2660195 and ++ http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html ++ ++ It is a very fast generator passing BigCrush, and it can be useful if ++ for some reason you absolutely want 64 bits of state; otherwise, we ++ rather suggest to use a xoroshiro128+ (for moderately parallel ++ computations) or xorshift1024* (for massively parallel computations) ++ generator. ++ ++ Note: This can be called with any value (i.e. including 0) ++*/ ++static __noinline uint64_t splitmix64(uint64_t x) { ++ uint64_t z = x + 0x9E3779B97F4A7C15ull; ++ z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ull; ++ z = (z ^ (z >> 27)) * 0x94D049BB133111EBull; ++ return z ^ (z >> 31); ++} ++ ++/* From the original source: ++ ++ This is xoroshiro128** 1.0, one of our all-purpose, rock-solid, ++ small-state generators. It is extremely (sub-ns) fast and it passes all ++ tests we are aware of, but its state space is large enough only for ++ mild parallelism. ++ ++ For generating just floating-point numbers, xoroshiro128+ is even ++ faster (but it has a very mild bias, see notes in the comments). ++ ++ The state must be seeded so that it is not everywhere zero. If you have ++ a 64-bit seed, we suggest to seed a splitmix64 generator and use its ++ output to fill s. ++*/ ++static inline uint64_t rotl(const uint64_t x, int k) { ++ return (x << k) | (x >> (64 - k)); ++} ++ ++static __noinline uint64_t xoroshiro128ss(rng_128_t *local_rng_state) { ++ const uint64_t s0 = local_rng_state->r[0]; ++ uint64_t s1 = local_rng_state->r[1]; ++ ++ // Because the state is *modified* outside of this function, there is a ++ // 1 in 2^128 chance that it could be all zeroes (which is not allowed). ++ while (s0 == 0 && s1 == 0) { ++ s1 = time_us_64(); // should not be 0, but loop anyway ++ } ++ ++ const uint64_t result = rotl(s0 * 5, 7) * 9; ++ ++ s1 ^= s0; ++ local_rng_state->r[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b ++ local_rng_state->r[1] = rotl(s1, 37); // c ++ ++ return result; ++} ++ ++#if PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH ++static uint64_t sdbm_hash64_sram(uint64_t hash) { ++ // save some time by hashing a word at a time ++ for (uint i = (PICO_RAND_RAM_HASH_START + 3) & ~3; i < PICO_RAND_RAM_HASH_END; i+=4) { ++ uint32_t c = *(uint32_t *) i; ++ hash = (uint64_t) c + (hash << 6) + (hash << 16) - hash; ++ } ++ return hash; ++} ++#endif ++ ++#if PICO_RAND_SEED_ENTROPY_SRC_ROSC | PICO_RAND_ENTROPY_SRC_ROSC ++/* gather an additional n bits of entropy, and shift them into the 64 bit entropy counter */ ++static uint64_t capture_additional_rosc_samples(uint n) { ++ static absolute_time_t next_sample_time; ++ ++ // provide an override if someone really wants it, but disabling ROSC as an entropy source makes more sense ++#if !PICO_RAND_DISABLE_ROSC_CHECK ++ // check that the ROSC is running but that the processors are NOT running from it ++ hard_assert((rosc_hw->status & ROSC_STATUS_ENABLED_BITS) && ++ ((clocks_hw->clk[clk_sys].ctrl & CLOCKS_CLK_SYS_CTRL_AUXSRC_BITS) != (CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC << CLOCKS_CLK_SYS_CTRL_AUXSRC_LSB))); ++#endif ++ ++ bool in_exception = __get_current_exception(); ++ assert(n); // save us having to special case samples for this ++ uint64_t samples = 0; ++ for(uint i=0; irandombit & 1u; ++ // use of relative time to now, rather than offset from before makes things ++ // a bit less predictable at the cost of some speed. ++ next_sample_time = make_timeout_time_us(PICO_RAND_MIN_ROSC_BIT_SAMPLE_TIME_US); ++ bit_done = true; ++ if (i == n - 1) { ++ // samples has our random bits, so let's mix them in now ++ samples = rosc_samples = (rosc_samples << n) | samples; ++ } ++ } ++ spin_unlock(lock, save); ++ } while (!bit_done); ++ } ++ return samples; ++} ++#endif ++ ++static void initialise_rand(void) { ++ rng_128_t local_rng_state = local_rng_state; ++ uint which = 0; ++#if PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH ++ ram_hash = sdbm_hash64_sram(ram_hash); ++ local_rng_state.r[which] ^= splitmix64(ram_hash); ++ which ^= 1; ++#endif ++ ++#if PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID ++ static_assert(PICO_UNIQUE_BOARD_ID_SIZE_BYTES == sizeof(uint64_t), ++ "Code below requires that 'board_id' is 64-bits in size"); ++ ++ // Note! The safety of the length assumption here is protected by a 'static_assert' above ++ union unique_id_u { ++ pico_unique_board_id_t board_id_native; ++ uint64_t board_id_u64; ++ } unique_id; ++ // Note! The safety of the length assumption here is protected by a 'static_assert' above ++ pico_get_unique_board_id(&unique_id.board_id_native); ++ local_rng_state.r[which] ^= splitmix64(unique_id.board_id_u64); ++ which ^= 1; ++#endif ++ ++#if PICO_RAND_SEED_ENTROPY_SRC_ROSC ++ // this is really quite slow (10ms per iteration), and I'm not sure that it adds value over the 64 random bits ++// uint ref_khz = clock_get_hz(clk_ref) / 100; ++// for (int i = 0; i < 5; i++) { ++// // Apply hash of the rosc frequency, limited but still 'extra' entropy ++// uint measurement = frequency_count_raw(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC, ref_khz); ++// local_rng_state.r[which] ^= splitmix64(measurement); ++// (void) xoroshiro128ss(&local_rng_state); //churn to mix seed sources ++// } ++ ++ // Gather a full ROSC sample array with sample bits ++ local_rng_state.r[which] ^= splitmix64(capture_additional_rosc_samples(8 * sizeof(rosc_samples))); ++ which ^= 1; ++#endif ++ ++#if PICO_RAND_SEED_ENTROPY_SRC_TIME ++ // Mix in hashed time. This is [possibly] predictable boot-to-boot ++ // but will vary application-to-application. ++ local_rng_state.r[which] ^= splitmix64(time_us_64()); ++ which ^= 1; ++#endif ++ ++ spin_lock_t *lock = spin_lock_instance(PICO_SPINLOCK_ID_RAND); ++ uint32_t save = spin_lock_blocking(lock); ++ if (!rng_initialised) { ++#if PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER ++#if !PICO_RAND_BUSCTRL_COUNTER_INDEX ++ int idx = -1; ++ for(uint i = 0; i < count_of(bus_ctrl_hw->counter); i++) { ++ if (bus_ctrl_hw->counter[i].sel == BUSCTRL_PERFSEL0_RESET) { ++ idx = (int)i; ++ break; ++ } ++ } ++ hard_assert(idx != -1); ++ bus_counter_idx = (uint8_t)idx; ++#else ++ bus_counter_idx = (uint8_t)PICO_RAND_BUSCTRL_COUNTER_INDEX; ++#endif ++ bus_ctrl_hw->counter[bus_counter_idx].sel = PICO_RAND_BUS_PERF_COUNTER_EVENT; ++#endif ++ (void) xoroshiro128ss(&local_rng_state); ++ rng_state = local_rng_state; ++ rng_initialised = true; ++ } ++ spin_unlock(lock, save); ++} ++ ++uint64_t get_rand_64(void) { ++ if (!rng_initialised) { ++ // Do not provide 'RNs' until the system has been initialised. Note: ++ // The first initialisation can be quite time-consuming depending on ++ // the amount of RAM hashed, see RAM_HASH_START and RAM_HASH_END ++ initialise_rand(); ++ } ++ ++ static volatile uint8_t check_byte; ++ rng_128_t local_rng_state = rng_state; ++ uint8_t local_check_byte = check_byte; ++ // Modify PRNG state with the run-time entropy sources, ++ // hashed to reduce correlation with previous modifications. ++ uint which = 0; ++#if PICO_RAND_ENTROPY_SRC_TIME ++ local_rng_state.r[which] ^= splitmix64(time_us_64()); ++ which ^= 1; ++#endif ++#if PICO_RAND_ENTROPY_SRC_ROSC ++ local_rng_state.r[which] ^= splitmix64(capture_additional_rosc_samples(PICO_RAND_ROSC_BIT_SAMPLE_COUNT)); ++ which ^= 1; ++#endif ++#if PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER ++ uint32_t bus_counter_value = bus_ctrl_hw->counter[bus_counter_idx].value; ++ // counter is saturating, so clear it if it has reached saturation ++ if (bus_counter_value == BUSCTRL_PERFCTR0_BITS) { ++ bus_ctrl_hw->counter[bus_counter_idx].value = 0; ++ } ++ local_rng_state.r[which] ^= splitmix64(bus_counter_value); ++ which ^= 1; ++#endif ++ ++ spin_lock_t *lock = spin_lock_instance(PICO_SPINLOCK_ID_RAND); ++ uint32_t save = spin_lock_blocking(lock); ++ if (local_check_byte != check_byte) { ++ // someone got a random number in the interim, so mix it in ++ local_rng_state.r[0] ^= rng_state.r[0]; ++ local_rng_state.r[1] ^= rng_state.r[1]; ++ } ++ // Generate a 64-bit RN from the modified PRNG state. ++ // Note: This also "churns" the 128-bit state for next time. ++ uint64_t rand64 = xoroshiro128ss(&local_rng_state); ++ rng_state = local_rng_state; ++ check_byte++; ++ spin_unlock(lock, save); ++ ++ return rand64; ++} ++ ++void get_rand_128(rng_128_t *ptr128) { ++ ptr128->r[0] = get_rand_64(); ++ ptr128->r[1] = get_rand_64(); ++} ++ ++uint32_t get_rand_32(void) { ++ return (uint32_t) get_rand_64(); ++} +diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/trng_api.c b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/trng_api.c +new file mode 100644 +index 0000000000..b0886badcc +--- /dev/null ++++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/trng_api.c +@@ -0,0 +1,64 @@ ++/* mbed Microcontroller Library ++ * Copyright (c) 2018 GigaDevice Semiconductor Inc. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++#if DEVICE_TRNG ++ ++#include "trng_api.h" ++ ++/** Initialize the TRNG peripheral ++ * ++ * @param obj The TRNG object ++ */ ++void trng_init(trng_t *obj) ++{ ++ (void)obj; ++} ++ ++/** Deinitialize the TRNG peripheral ++ * ++ * @param obj The TRNG object ++ */ ++void trng_free(trng_t *obj) ++{ ++ (void)obj; ++} ++ ++/** Get random data from TRNG peripheral ++ * ++ * @param obj The TRNG object ++ * @param output The pointer to an output array ++ * @param length The size of output data, to avoid buffer overwrite ++ * @param output_length The length of generated data ++ * @return 0 success, -1 fail ++ */ ++int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length) ++{ ++ (void)obj; ++ *output_length = 0; ++ uint32_t random[16]; ++ ++ while (*output_length < length) { ++ get_rand_128((rng_128_t*)random); ++ for (uint8_t i = 0; (i < 16) && (*output_length < length) ; i++) { ++ *output++ = random[i]; ++ *output_length += 1; ++ random[i] = 0; ++ } ++ } ++ return 0; ++} ++#endif /* DEVICE_TRNG */ +diff --git a/targets/targets.json b/targets/targets.json +index 9a12422336..83fa8c930a 100644 +--- a/targets/targets.json ++++ b/targets/targets.json +@@ -9700,7 +9700,8 @@ + "USTICKER", + "WATCHDOG", + "USBDEVICE", +- "RESET_REASON" ++ "RESET_REASON", ++ "TRNG" + ] + }, + "NANO_RP2040_CONNECT": { +-- +2.43.0 + pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy