bootloader_random.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. #if defined CONFIG_IDF_TARGET_ESP32C6
  11. #include "hal/lp_timer_hal.h"
  12. #endif
  13. #ifndef BOOTLOADER_BUILD
  14. #include "esp_random.h"
  15. #include "esp_private/periph_ctrl.h"
  16. __attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length)
  17. {
  18. return esp_fill_random(buffer, length);
  19. }
  20. #else
  21. #if !defined CONFIG_IDF_TARGET_ESP32S3
  22. #if (defined CONFIG_IDF_TARGET_ESP32C6 || defined CONFIG_IDF_TARGET_ESP32H2)
  23. #define RNG_CPU_WAIT_CYCLE_NUM (80 * 12) // higher frequency because we are reading bytes instead of words
  24. #else
  25. #define RNG_CPU_WAIT_CYCLE_NUM (80 * 32 * 2) /* extra factor of 2 is precautionary */
  26. #endif
  27. #else
  28. #define RNG_CPU_WAIT_CYCLE_NUM (80 * 23) /* 45 KHz reading frequency is the maximum we have tested so far on S3 */
  29. #endif
  30. #if defined CONFIG_IDF_TARGET_ESP32H2
  31. // TODO: temporary definition until IDF-6270 is implemented
  32. #include "soc/lp_timer_reg.h"
  33. static inline uint32_t lp_timer_hal_get_cycle_count(void)
  34. {
  35. REG_SET_BIT(LP_TIMER_UPDATE_REG, LP_TIMER_MAIN_TIMER_UPDATE);
  36. uint32_t lo = REG_GET_FIELD(LP_TIMER_MAIN_BUF0_LOW_REG, LP_TIMER_MAIN_TIMER_BUF0_LOW);
  37. return lo;
  38. }
  39. #endif
  40. __attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length)
  41. {
  42. uint8_t *buffer_bytes = (uint8_t *)buffer;
  43. uint32_t random;
  44. uint32_t start, now;
  45. assert(buffer != NULL);
  46. for (size_t i = 0; i < length; i++) {
  47. #if (defined CONFIG_IDF_TARGET_ESP32C6 || defined CONFIG_IDF_TARGET_ESP32H2)
  48. random = REG_READ(WDEV_RND_REG);
  49. start = esp_cpu_get_cycle_count();
  50. do {
  51. random ^= REG_READ(WDEV_RND_REG);
  52. now = esp_cpu_get_cycle_count();
  53. } while (now - start < RNG_CPU_WAIT_CYCLE_NUM);
  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. buffer_bytes[i] = random & 0xFF;
  59. #else
  60. if (i == 0 || i % 4 == 0) { /* redundant check is for a compiler warning */
  61. /* in bootloader with ADC feeding HWRNG, we accumulate 1
  62. bit of entropy per 40 APB cycles (==80 CPU cycles.)
  63. To avoid reading the entire RNG hardware state out
  64. as-is, we repeatedly read the RNG register and XOR all
  65. values.
  66. */
  67. random = REG_READ(WDEV_RND_REG);
  68. start = esp_cpu_get_cycle_count();
  69. do {
  70. random ^= REG_READ(WDEV_RND_REG);
  71. now = esp_cpu_get_cycle_count();
  72. } while (now - start < RNG_CPU_WAIT_CYCLE_NUM);
  73. }
  74. buffer_bytes[i] = random >> ((i % 4) * 8);
  75. #endif
  76. }
  77. }
  78. #ifndef CONFIG_IDF_ENV_FPGA
  79. #else // CONFIG_IDF_ENV_FPGA
  80. #include "esp_log.h"
  81. static void s_non_functional(const char *func)
  82. {
  83. ESP_EARLY_LOGW("rand", "%s non-functional for FPGA builds", func);
  84. }
  85. void bootloader_random_enable()
  86. {
  87. s_non_functional(__func__);
  88. }
  89. void bootloader_random_disable()
  90. {
  91. s_non_functional(__func__);
  92. }
  93. #endif // CONFIG_IDF_ENV_FPGA
  94. #endif // BOOTLOADER_BUILD