Skip to content

Commit e54f3d9

Browse files
committed
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
2 parents 4965665 + 83a179a commit e54f3d9

File tree

13 files changed

+124
-71
lines changed

13 files changed

+124
-71
lines changed

components/bootloader_support/src/bootloader_random.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,23 @@
2323

2424
#ifndef BOOTLOADER_BUILD
2525
#include "esp_system.h"
26-
#endif
2726

27+
void bootloader_fill_random(void *buffer, size_t length)
28+
{
29+
return esp_fill_random(buffer, length);
30+
}
31+
32+
#else
2833
void bootloader_fill_random(void *buffer, size_t length)
2934
{
3035
uint8_t *buffer_bytes = (uint8_t *)buffer;
3136
uint32_t random;
32-
#ifdef BOOTLOADER_BUILD
3337
uint32_t start, now;
34-
#endif
38+
39+
assert(buffer != NULL);
3540

3641
for (int i = 0; i < length; i++) {
3742
if (i == 0 || i % 4 == 0) { /* redundant check is for a compiler warning */
38-
#ifdef BOOTLOADER_BUILD
3943
/* in bootloader with ADC feeding HWRNG, we accumulate 1
4044
bit of entropy per 40 APB cycles (==80 CPU cycles.)
4145
@@ -49,14 +53,12 @@ void bootloader_fill_random(void *buffer, size_t length)
4953
random ^= REG_READ(WDEV_RND_REG);
5054
RSR(CCOUNT, now);
5155
} while(now - start < 80*32*2); /* extra factor of 2 is precautionary */
52-
#else
53-
random = esp_random();
54-
#endif
5556
}
5657

5758
buffer_bytes[i] = random >> ((i % 4) * 8);
5859
}
5960
}
61+
#endif // BOOTLOADER_BUILD
6062

6163
void bootloader_random_enable(void)
6264
{

components/esp32/hw_random.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <stdint.h>
1717
#include <stddef.h>
1818
#include <string.h>
19+
#include <sys/param.h>
1920
#include "esp_attr.h"
2021
#include "esp_clk.h"
2122
#include "soc/wdev_reg.h"
@@ -54,3 +55,16 @@ uint32_t IRAM_ATTR esp_random(void)
5455
last_ccount = ccount;
5556
return result ^ REG_READ(WDEV_RND_REG);
5657
}
58+
59+
void esp_fill_random(void *buf, size_t len)
60+
{
61+
assert(buf != NULL);
62+
uint8_t *buf_bytes = (uint8_t *)buf;
63+
while (len > 0) {
64+
uint32_t word = esp_random();
65+
uint32_t to_copy = MIN(sizeof(word), len);
66+
memcpy(buf_bytes, &word, to_copy);
67+
buf_bytes += to_copy;
68+
len -= to_copy;
69+
}
70+
}

components/esp32/include/esp_system.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,18 +151,31 @@ uint32_t esp_get_minimum_free_heap_size( void );
151151
/**
152152
* @brief Get one random 32-bit word from hardware RNG
153153
*
154-
* The hardware RNG is fully functional whenever an RF subsystem is running (ie Bluetooth or WiFi is enabled). For secure
154+
* The hardware RNG is fully functional whenever an RF subsystem is running (ie Bluetooth or WiFi is enabled). For
155155
* random values, call this function after WiFi or Bluetooth are started.
156156
*
157-
* When the app is running without an RF subsystem enabled, it should be considered a PRNG. To help improve this
158-
* situation, the RNG is pre-seeded with entropy while the IDF bootloader is running. However no new entropy is
159-
* available during the window of time between when the bootloader exits and an RF subsystem starts. It may be possible
160-
* to discern a non-random pattern in a very large amount of output captured during this window of time.
157+
* If the RF subsystem is not used by the program, the function bootloader_random_enable() can be called to enable an
158+
* entropy source. bootloader_random_disable() must be called before RF subsystem or I2S peripheral are used. See these functions'
159+
* documentation for more details.
160+
*
161+
* Any time the app is running without an RF subsystem (or bootloader_random) enabled, RNG hardware should be
162+
* considered a PRNG. A very small amount of entropy is available due to pre-seeding while the IDF
163+
* bootloader is running, but this should not be relied upon for any use.
161164
*
162165
* @return Random value between 0 and UINT32_MAX
163166
*/
164167
uint32_t esp_random(void);
165168

169+
/**
170+
* @brief Fill a buffer with random bytes from hardware RNG
171+
*
172+
* @note This function has the same restrictions regarding available entropy as esp_random()
173+
*
174+
* @param buf Pointer to buffer to fill with random numbers.
175+
* @param len Length of buffer in bytes
176+
*/
177+
void esp_fill_random(void *buf, size_t len);
178+
166179
/**
167180
* @brief Set base MAC address with the MAC address which is stored in BLK3 of EFUSE or
168181
* external storage e.g. flash and EEPROM.

components/esp32/test/test_random.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#include <stdio.h>
2+
#include <string.h>
3+
#include "unity.h"
4+
#include "esp_system.h"
5+
6+
/* Note: these are just sanity tests, not the same as
7+
entropy tests
8+
*/
9+
10+
TEST_CASE("call esp_random()", "[random]")
11+
{
12+
const size_t NUM_RANDOM = 128; /* in most cases this is massive overkill */
13+
14+
uint32_t zeroes = UINT32_MAX;
15+
uint32_t ones = 0;
16+
for (int i = 0; i < NUM_RANDOM - 1; i++) {
17+
uint32_t r = esp_random();
18+
ones |= r;
19+
zeroes &= ~r;
20+
}
21+
22+
/* assuming a 'white' random distribution, we can expect
23+
usually at least one time each bit will be zero and at
24+
least one time each will be one. Statistically this
25+
can still fail, just *very* unlikely to. */
26+
TEST_ASSERT_EQUAL_HEX32(0, zeroes);
27+
TEST_ASSERT_EQUAL_HEX32(UINT32_MAX, ones);
28+
}
29+
30+
TEST_CASE("call esp_fill_random()", "[random]")
31+
{
32+
const size_t NUM_BUF = 200;
33+
const size_t BUF_SZ = 16;
34+
uint8_t buf[NUM_BUF][BUF_SZ];
35+
uint8_t zero_buf[BUF_SZ];
36+
uint8_t one_buf[BUF_SZ];
37+
38+
bzero(buf, sizeof(buf));
39+
bzero(one_buf, sizeof(zero_buf));
40+
memset(zero_buf, 0xFF, sizeof(one_buf));
41+
42+
for (int i = 0; i < NUM_BUF; i++) {
43+
esp_fill_random(buf[i], BUF_SZ);
44+
}
45+
/* No two 128-bit buffers should be the same
46+
(again, statistically this could happen but it's very unlikely) */
47+
for (int i = 0; i < NUM_BUF; i++) {
48+
for (int j = 0; j < NUM_BUF; j++) {
49+
if (i != j) {
50+
TEST_ASSERT_NOT_EQUAL(0, memcmp(buf[i], buf[j], BUF_SZ));
51+
}
52+
}
53+
}
54+
55+
/* Do the same all bits are zero and one at least once test across the buffers */
56+
for (int i = 0; i < NUM_BUF; i++) {
57+
for (int x = 0; x < BUF_SZ; x++) {
58+
zero_buf[x] &= ~buf[i][x];
59+
one_buf[x] |= buf[i][x];
60+
}
61+
}
62+
for (int x = 0; x < BUF_SZ; x++) {
63+
TEST_ASSERT_EQUAL_HEX8(0, zero_buf[x]);
64+
TEST_ASSERT_EQUAL_HEX8(0xFF, one_buf[x]);
65+
}
66+
}
67+

components/fatfs/test/test_fatfs_sdmmc.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,7 @@ TEST_CASE("(SD) write/read speed test", "[fatfs][sd][test_env=UT_T1_SDMODE][time
167167

168168
const size_t buf_size = 16 * 1024;
169169
uint32_t* buf = (uint32_t*) calloc(1, buf_size);
170-
for (size_t i = 0; i < buf_size / 4; ++i) {
171-
buf[i] = esp_random();
172-
}
170+
esp_fill_random(buf, buf_size);
173171
const size_t file_size = 1 * 1024 * 1024;
174172

175173
speed_test(buf, 4 * 1024, file_size, true);

components/fatfs/test/test_fatfs_spiflash.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,7 @@ TEST_CASE("(WL) write/read speed test", "[fatfs][wear_levelling][timeout=60]")
162162

163163
const size_t buf_size = 16 * 1024;
164164
uint32_t* buf = (uint32_t*) calloc(1, buf_size);
165-
for (size_t i = 0; i < buf_size / 4; ++i) {
166-
buf[i] = esp_random();
167-
}
165+
esp_fill_random(buf, buf_size);
168166
const size_t file_size = 256 * 1024;
169167
const char* file = "/spiflash/256k.bin";
170168

components/libsodium/port/randombytes_esp32.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@
1414
#include "randombytes_default.h"
1515
#include "esp_system.h"
1616

17-
static void randombytes_esp32_random_buf(void * const buf, const size_t size)
18-
{
19-
uint8_t *p = (uint8_t *)buf;
20-
for (size_t i = 0; i < size; i++) {
21-
p[i] = esp_random();
22-
}
23-
}
24-
2517
static const char *randombytes_esp32_implementation_name(void)
2618
{
2719
return "esp32";
@@ -39,7 +31,7 @@ const struct randombytes_implementation randombytes_esp32_implementation = {
3931
.random = esp_random,
4032
.stir = NULL,
4133
.uniform = NULL,
42-
.buf = randombytes_esp32_random_buf,
34+
.buf = esp_fill_random,
4335
.close = NULL,
4436
};
4537

components/mbedtls/port/esp_hardware.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@
77
#include <sys/types.h>
88
#include <stdlib.h>
99
#include <stdio.h>
10+
#include <esp_system.h>
1011

11-
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
12+
#ifndef MBEDTLS_ENTROPY_HARDWARE_ALT
13+
#error "MBEDTLS_ENTROPY_HARDWARE_ALT should always be set in ESP-IDF"
14+
#endif
1215

13-
extern int os_get_random(unsigned char *buf, size_t len);
1416
int mbedtls_hardware_poll( void *data,
1517
unsigned char *output, size_t len, size_t *olen )
1618
{
17-
os_get_random(output, len);
19+
esp_fill_random(output, len);
1820
*olen = len;
19-
2021
return 0;
2122
}
22-
#endif
23+
2324

components/newlib/random.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,8 @@ ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
3636
return -1;
3737
}
3838

39-
uint8_t *dst = (uint8_t *) buf;
40-
ssize_t ret = 0;
39+
esp_fill_random(buf, buflen);
4140

42-
while (ret < buflen) {
43-
const uint32_t random = esp_random();
44-
const int needed = buflen - ret;
45-
const int copy_len = MIN(sizeof(random), needed);
46-
memcpy(dst + ret, &random, copy_len);
47-
ret += copy_len;
48-
}
49-
50-
ESP_LOGD(TAG, "getrandom returns %d", ret);
51-
return ret;
41+
ESP_LOGD(TAG, "getrandom returns %d", buflen);
42+
return buflen;
5243
}

components/wpa_supplicant/port/os_xtensa.c

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,9 @@ unsigned long os_random(void)
3939
return esp_random();
4040
}
4141

42-
unsigned long r_rand(void) __attribute__((alias("os_random")));
43-
44-
4542
int os_get_random(unsigned char *buf, size_t len)
4643
{
47-
int i, j;
48-
unsigned long tmp;
49-
50-
for (i = 0; i < ((len + 3) & ~3) / 4; i++) {
51-
tmp = r_rand();
52-
53-
for (j = 0; j < 4; j++) {
54-
if ((i * 4 + j) < len) {
55-
buf[i * 4 + j] = (uint8_t)(tmp >> (j * 8));
56-
} else {
57-
break;
58-
}
59-
}
60-
}
61-
44+
esp_fill_random(buf, len);
6245
return 0;
6346
}
6447

examples/bluetooth/blufi/main/blufi_security.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,7 @@ static struct blufi_security *blufi_sec;
6161

6262
static int myrand( void *rng_state, unsigned char *output, size_t len )
6363
{
64-
size_t i;
65-
66-
for( i = 0; i < len; ++i )
67-
output[i] = esp_random();
68-
64+
esp_fill_random(output, len);
6965
return( 0 );
7066
}
7167

examples/wifi/espnow/main/espnow_example_main.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ int example_espnow_data_parse(uint8_t *data, uint16_t data_len, uint8_t *state,
144144
void example_espnow_data_prepare(example_espnow_send_param_t *send_param)
145145
{
146146
example_espnow_data_t *buf = (example_espnow_data_t *)send_param->buffer;
147-
int i = 0;
148147

149148
assert(send_param->len >= sizeof(example_espnow_data_t));
150149

@@ -153,9 +152,8 @@ void example_espnow_data_prepare(example_espnow_send_param_t *send_param)
153152
buf->seq_num = s_example_espnow_seq[buf->type]++;
154153
buf->crc = 0;
155154
buf->magic = send_param->magic;
156-
for (i = 0; i < send_param->len - sizeof(example_espnow_data_t); i++) {
157-
buf->payload[i] = (uint8_t)esp_random();
158-
}
155+
/* Fill all remaining bytes after the data with random values */
156+
esp_fill_random(buf->payload, send_param->len - sizeof(example_espnow_data_t));
159157
buf->crc = crc16_le(UINT16_MAX, (uint8_t const *)buf, send_param->len);
160158
}
161159

0 commit comments

Comments
 (0)