1 /*
2 * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "sdkconfig.h"
7 #include "bootloader_random.h"
8 #include "esp_cpu.h"
9 #include "soc/wdev_reg.h"
10
11 #if SOC_LP_TIMER_SUPPORTED
12 #include "hal/lp_timer_hal.h"
13 #endif
14
15 #ifndef BOOTLOADER_BUILD
16 #include "esp_random.h"
17 #include "esp_private/periph_ctrl.h"
18
bootloader_fill_random(void * buffer,size_t length)19 __attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length)
20 {
21 return esp_fill_random(buffer, length);
22 }
23
24 #else
25
26 #if !defined CONFIG_IDF_TARGET_ESP32S3
27 #if (defined CONFIG_IDF_TARGET_ESP32C6 || defined CONFIG_IDF_TARGET_ESP32H2)
28 #define RNG_CPU_WAIT_CYCLE_NUM (80 * 16) // Keep the byte sampling frequency in the ~62KHz range which has been
29 // tested.
30 #else
31 #define RNG_CPU_WAIT_CYCLE_NUM (80 * 32 * 2) /* extra factor of 2 is precautionary */
32 #endif
33 #else
34 #define RNG_CPU_WAIT_CYCLE_NUM (80 * 23) /* 45 KHz reading frequency is the maximum we have tested so far on S3 */
35 #endif
36
bootloader_fill_random(void * buffer,size_t length)37 __attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length)
38 {
39 uint8_t *buffer_bytes = (uint8_t *)buffer;
40 uint32_t random;
41 uint32_t start, now;
42
43 assert(buffer != NULL);
44
45 for (size_t i = 0; i < length; i++) {
46 #if SOC_LP_TIMER_SUPPORTED
47 random = REG_READ(WDEV_RND_REG);
48 start = esp_cpu_get_cycle_count();
49 do {
50 random ^= REG_READ(WDEV_RND_REG);
51 now = esp_cpu_get_cycle_count();
52 } while (now - start < RNG_CPU_WAIT_CYCLE_NUM);
53
54 // XOR the RT slow clock, which is asynchronous, to add some entropy and improve
55 // the distribution
56 uint32_t current_rtc_timer_counter = (lp_timer_hal_get_cycle_count() & 0xFF);
57 random = random ^ current_rtc_timer_counter;
58
59 buffer_bytes[i] = random & 0xFF;
60 #else
61 if (i == 0 || i % 4 == 0) { /* redundant check is for a compiler warning */
62 /* in bootloader with ADC feeding HWRNG, we accumulate 1
63 bit of entropy per 40 APB cycles (==80 CPU cycles.)
64
65 To avoid reading the entire RNG hardware state out
66 as-is, we repeatedly read the RNG register and XOR all
67 values.
68 */
69 random = REG_READ(WDEV_RND_REG);
70 start = esp_cpu_get_cycle_count();
71 do {
72 random ^= REG_READ(WDEV_RND_REG);
73 now = esp_cpu_get_cycle_count();
74 } while (now - start < RNG_CPU_WAIT_CYCLE_NUM);
75 }
76 buffer_bytes[i] = random >> ((i % 4) * 8);
77 #endif
78 }
79 }
80
81 #ifndef CONFIG_IDF_ENV_FPGA
82
83 #else // CONFIG_IDF_ENV_FPGA
84 #include "esp_log.h"
85
s_non_functional(const char * func)86 static void s_non_functional(const char *func)
87 {
88 ESP_EARLY_LOGW("rand", "%s non-functional for FPGA builds", func);
89 }
90
bootloader_random_enable()91 void bootloader_random_enable()
92 {
93 s_non_functional(__func__);
94 }
95
bootloader_random_disable()96 void bootloader_random_disable()
97 {
98 s_non_functional(__func__);
99 }
100
101 #endif // CONFIG_IDF_ENV_FPGA
102
103 #endif // BOOTLOADER_BUILD
104