bootloader_random.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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 * 16) // Keep the byte sampling frequency in the ~62KHz range which has been
  24. // tested.
  25. #else
  26. #define RNG_CPU_WAIT_CYCLE_NUM (80 * 32 * 2) /* extra factor of 2 is precautionary */
  27. #endif
  28. #else
  29. #define RNG_CPU_WAIT_CYCLE_NUM (80 * 23) /* 45 KHz reading frequency is the maximum we have tested so far on S3 */
  30. #endif
  31. #if defined CONFIG_IDF_TARGET_ESP32H2
  32. // TODO: temporary definition until IDF-6270 is implemented
  33. #include "soc/lp_timer_reg.h"
  34. static inline uint32_t lp_timer_hal_get_cycle_count(void)
  35. {
  36. REG_SET_BIT(LP_TIMER_UPDATE_REG, LP_TIMER_MAIN_TIMER_UPDATE);
  37. uint32_t lo = REG_GET_FIELD(LP_TIMER_MAIN_BUF0_LOW_REG, LP_TIMER_MAIN_TIMER_BUF0_LOW);
  38. return lo;
  39. }
  40. #endif
  41. __attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length)
  42. {
  43. uint8_t *buffer_bytes = (uint8_t *)buffer;
  44. uint32_t random;
  45. uint32_t start, now;
  46. assert(buffer != NULL);
  47. for (size_t i = 0; i < length; i++) {
  48. #if (defined CONFIG_IDF_TARGET_ESP32C6 || defined CONFIG_IDF_TARGET_ESP32H2)
  49. random = REG_READ(WDEV_RND_REG);
  50. start = esp_cpu_get_cycle_count();
  51. do {
  52. random ^= REG_READ(WDEV_RND_REG);
  53. now = esp_cpu_get_cycle_count();
  54. } while (now - start < RNG_CPU_WAIT_CYCLE_NUM);
  55. // XOR the RT slow clock, which is asynchronous, to add some entropy and improve
  56. // the distribution
  57. uint32_t current_rtc_timer_counter = (lp_timer_hal_get_cycle_count() & 0xFF);
  58. random = random ^ current_rtc_timer_counter;
  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. To avoid reading the entire RNG hardware state out
  65. as-is, we repeatedly read the RNG register and XOR all
  66. values.
  67. */
  68. random = REG_READ(WDEV_RND_REG);
  69. start = esp_cpu_get_cycle_count();
  70. do {
  71. random ^= REG_READ(WDEV_RND_REG);
  72. now = esp_cpu_get_cycle_count();
  73. } while (now - start < RNG_CPU_WAIT_CYCLE_NUM);
  74. }
  75. buffer_bytes[i] = random >> ((i % 4) * 8);
  76. #endif
  77. }
  78. }
  79. #ifndef CONFIG_IDF_ENV_FPGA
  80. #else // CONFIG_IDF_ENV_FPGA
  81. #include "esp_log.h"
  82. static void s_non_functional(const char *func)
  83. {
  84. ESP_EARLY_LOGW("rand", "%s non-functional for FPGA builds", func);
  85. }
  86. void bootloader_random_enable()
  87. {
  88. s_non_functional(__func__);
  89. }
  90. void bootloader_random_disable()
  91. {
  92. s_non_functional(__func__);
  93. }
  94. #endif // CONFIG_IDF_ENV_FPGA
  95. #endif // BOOTLOADER_BUILD