mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-25 01:37:22 +00:00
Merge branch 'bugfix/bootloader_random_in_app' into 'master'
esp32: Allow bootloader_random.h use in app, add esp_fill_random() function See merge request idf/esp-idf!3124
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_attr.h"
|
||||
#include "esp_clk.h"
|
||||
#include "soc/wdev_reg.h"
|
||||
@@ -54,3 +55,16 @@ uint32_t IRAM_ATTR esp_random(void)
|
||||
last_ccount = ccount;
|
||||
return result ^ REG_READ(WDEV_RND_REG);
|
||||
}
|
||||
|
||||
void esp_fill_random(void *buf, size_t len)
|
||||
{
|
||||
assert(buf != NULL);
|
||||
uint8_t *buf_bytes = (uint8_t *)buf;
|
||||
while (len > 0) {
|
||||
uint32_t word = esp_random();
|
||||
uint32_t to_copy = MIN(sizeof(word), len);
|
||||
memcpy(buf_bytes, &word, to_copy);
|
||||
buf_bytes += to_copy;
|
||||
len -= to_copy;
|
||||
}
|
||||
}
|
||||
|
@@ -151,18 +151,31 @@ uint32_t esp_get_minimum_free_heap_size( void );
|
||||
/**
|
||||
* @brief Get one random 32-bit word from hardware RNG
|
||||
*
|
||||
* The hardware RNG is fully functional whenever an RF subsystem is running (ie Bluetooth or WiFi is enabled). For secure
|
||||
* The hardware RNG is fully functional whenever an RF subsystem is running (ie Bluetooth or WiFi is enabled). For
|
||||
* random values, call this function after WiFi or Bluetooth are started.
|
||||
*
|
||||
* When the app is running without an RF subsystem enabled, it should be considered a PRNG. To help improve this
|
||||
* situation, the RNG is pre-seeded with entropy while the IDF bootloader is running. However no new entropy is
|
||||
* available during the window of time between when the bootloader exits and an RF subsystem starts. It may be possible
|
||||
* to discern a non-random pattern in a very large amount of output captured during this window of time.
|
||||
* If the RF subsystem is not used by the program, the function bootloader_random_enable() can be called to enable an
|
||||
* entropy source. bootloader_random_disable() must be called before RF subsystem or I2S peripheral are used. See these functions'
|
||||
* documentation for more details.
|
||||
*
|
||||
* Any time the app is running without an RF subsystem (or bootloader_random) enabled, RNG hardware should be
|
||||
* considered a PRNG. A very small amount of entropy is available due to pre-seeding while the IDF
|
||||
* bootloader is running, but this should not be relied upon for any use.
|
||||
*
|
||||
* @return Random value between 0 and UINT32_MAX
|
||||
*/
|
||||
uint32_t esp_random(void);
|
||||
|
||||
/**
|
||||
* @brief Fill a buffer with random bytes from hardware RNG
|
||||
*
|
||||
* @note This function has the same restrictions regarding available entropy as esp_random()
|
||||
*
|
||||
* @param buf Pointer to buffer to fill with random numbers.
|
||||
* @param len Length of buffer in bytes
|
||||
*/
|
||||
void esp_fill_random(void *buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Set base MAC address with the MAC address which is stored in BLK3 of EFUSE or
|
||||
* external storage e.g. flash and EEPROM.
|
||||
|
67
components/esp32/test/test_random.c
Normal file
67
components/esp32/test/test_random.c
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
/* Note: these are just sanity tests, not the same as
|
||||
entropy tests
|
||||
*/
|
||||
|
||||
TEST_CASE("call esp_random()", "[random]")
|
||||
{
|
||||
const size_t NUM_RANDOM = 128; /* in most cases this is massive overkill */
|
||||
|
||||
uint32_t zeroes = UINT32_MAX;
|
||||
uint32_t ones = 0;
|
||||
for (int i = 0; i < NUM_RANDOM - 1; i++) {
|
||||
uint32_t r = esp_random();
|
||||
ones |= r;
|
||||
zeroes &= ~r;
|
||||
}
|
||||
|
||||
/* assuming a 'white' random distribution, we can expect
|
||||
usually at least one time each bit will be zero and at
|
||||
least one time each will be one. Statistically this
|
||||
can still fail, just *very* unlikely to. */
|
||||
TEST_ASSERT_EQUAL_HEX32(0, zeroes);
|
||||
TEST_ASSERT_EQUAL_HEX32(UINT32_MAX, ones);
|
||||
}
|
||||
|
||||
TEST_CASE("call esp_fill_random()", "[random]")
|
||||
{
|
||||
const size_t NUM_BUF = 200;
|
||||
const size_t BUF_SZ = 16;
|
||||
uint8_t buf[NUM_BUF][BUF_SZ];
|
||||
uint8_t zero_buf[BUF_SZ];
|
||||
uint8_t one_buf[BUF_SZ];
|
||||
|
||||
bzero(buf, sizeof(buf));
|
||||
bzero(one_buf, sizeof(zero_buf));
|
||||
memset(zero_buf, 0xFF, sizeof(one_buf));
|
||||
|
||||
for (int i = 0; i < NUM_BUF; i++) {
|
||||
esp_fill_random(buf[i], BUF_SZ);
|
||||
}
|
||||
/* No two 128-bit buffers should be the same
|
||||
(again, statistically this could happen but it's very unlikely) */
|
||||
for (int i = 0; i < NUM_BUF; i++) {
|
||||
for (int j = 0; j < NUM_BUF; j++) {
|
||||
if (i != j) {
|
||||
TEST_ASSERT_NOT_EQUAL(0, memcmp(buf[i], buf[j], BUF_SZ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the same all bits are zero and one at least once test across the buffers */
|
||||
for (int i = 0; i < NUM_BUF; i++) {
|
||||
for (int x = 0; x < BUF_SZ; x++) {
|
||||
zero_buf[x] &= ~buf[i][x];
|
||||
one_buf[x] |= buf[i][x];
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < BUF_SZ; x++) {
|
||||
TEST_ASSERT_EQUAL_HEX8(0, zero_buf[x]);
|
||||
TEST_ASSERT_EQUAL_HEX8(0xFF, one_buf[x]);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user