Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 1 | /* |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 2 | * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
| 6 | |
| 7 | #include <bootutil/bootutil.h> |
Gustavo Henrique Nihei | d985d22 | 2021-11-12 14:21:12 -0300 | [diff] [blame] | 8 | #include <bootutil/bootutil_log.h> |
| 9 | #include <bootutil/fault_injection_hardening.h> |
Shubham Kulkarni | 8787bb0 | 2021-07-20 11:46:03 +0530 | [diff] [blame] | 10 | #include <bootutil/image.h> |
| 11 | |
Gustavo Henrique Nihei | d985d22 | 2021-11-12 14:21:12 -0300 | [diff] [blame] | 12 | #include "bootloader_init.h" |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 13 | #include "bootloader_utility.h" |
| 14 | #include "bootloader_random.h" |
Almir Okato | db2024e | 2023-08-24 15:40:26 -0300 | [diff] [blame] | 15 | #include "bootloader_soc.h" |
Shubham Kulkarni | 8787bb0 | 2021-07-20 11:46:03 +0530 | [diff] [blame] | 16 | |
Almir Okato | 54ef484 | 2023-03-07 17:56:53 -0300 | [diff] [blame] | 17 | #include "esp_assert.h" |
| 18 | |
Almir Okato | e8cbc0d | 2022-06-13 10:45:39 -0300 | [diff] [blame] | 19 | #ifdef CONFIG_MCUBOOT_SERIAL |
| 20 | #include "boot_serial/boot_serial.h" |
| 21 | #include "serial_adapter/serial_adapter.h" |
| 22 | |
| 23 | const struct boot_uart_funcs boot_funcs = { |
| 24 | .read = console_read, |
| 25 | .write = console_write |
| 26 | }; |
| 27 | #endif |
| 28 | |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 29 | #if defined(CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH) || defined(CONFIG_SECURE_BOOT) |
| 30 | #include "esp_efuse.h" |
| 31 | #endif |
| 32 | #ifdef CONFIG_SECURE_BOOT |
| 33 | #include "esp_secure_boot.h" |
| 34 | #endif |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 35 | #ifdef CONFIG_SECURE_FLASH_ENC_ENABLED |
| 36 | #include "esp_flash_encrypt.h" |
| 37 | #endif |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 38 | |
Gustavo Henrique Nihei | d985d22 | 2021-11-12 14:21:12 -0300 | [diff] [blame] | 39 | #include "esp_loader.h" |
| 40 | #include "os/os_malloc.h" |
Shubham Kulkarni | 8787bb0 | 2021-07-20 11:46:03 +0530 | [diff] [blame] | 41 | |
Almir Okato | a1d641d | 2022-02-21 19:31:46 -0300 | [diff] [blame] | 42 | #define IMAGE_INDEX_0 0 |
| 43 | #define IMAGE_INDEX_1 1 |
| 44 | |
| 45 | #define PRIMARY_SLOT 0 |
| 46 | #define SECONDARY_SLOT 1 |
| 47 | |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 48 | #ifdef CONFIG_SECURE_BOOT |
| 49 | extern esp_err_t check_and_generate_secure_boot_keys(void); |
| 50 | #endif |
| 51 | |
Shubham Kulkarni | 8787bb0 | 2021-07-20 11:46:03 +0530 | [diff] [blame] | 52 | void do_boot(struct boot_rsp *rsp) |
| 53 | { |
Gustavo Henrique Nihei | d985d22 | 2021-11-12 14:21:12 -0300 | [diff] [blame] | 54 | BOOT_LOG_INF("br_image_off = 0x%x", rsp->br_image_off); |
| 55 | BOOT_LOG_INF("ih_hdr_size = 0x%x", rsp->br_hdr->ih_hdr_size); |
Almir Okato | a1d641d | 2022-02-21 19:31:46 -0300 | [diff] [blame] | 56 | int slot = (rsp->br_image_off == CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS) ? PRIMARY_SLOT : SECONDARY_SLOT; |
Almir Okato | c4b3058 | 2022-05-06 14:59:43 -0300 | [diff] [blame] | 57 | start_cpu0_image(IMAGE_INDEX_0, slot, rsp->br_hdr->ih_hdr_size); |
Shubham Kulkarni | 8787bb0 | 2021-07-20 11:46:03 +0530 | [diff] [blame] | 58 | } |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 59 | |
Almir Okato | a1d641d | 2022-02-21 19:31:46 -0300 | [diff] [blame] | 60 | #ifdef CONFIG_ESP_MULTI_PROCESSOR_BOOT |
| 61 | int read_image_header(uint32_t img_index, uint32_t slot, struct image_header *img_header) |
| 62 | { |
| 63 | const struct flash_area *fap; |
| 64 | int area_id; |
| 65 | int rc = 0; |
| 66 | |
| 67 | area_id = flash_area_id_from_multi_image_slot(img_index, slot); |
| 68 | rc = flash_area_open(area_id, &fap); |
| 69 | if (rc != 0) { |
| 70 | rc = BOOT_EFLASH; |
| 71 | goto done; |
| 72 | } |
| 73 | |
| 74 | if (flash_area_read(fap, 0, img_header, sizeof(struct image_header))) { |
| 75 | rc = BOOT_EFLASH; |
| 76 | goto done; |
| 77 | } |
| 78 | |
| 79 | BOOT_LOG_INF("Image offset = 0x%x", fap->fa_off); |
| 80 | BOOT_LOG_INF("Image header size = 0x%x", img_header->ih_hdr_size); |
| 81 | |
| 82 | done: |
| 83 | flash_area_close(fap); |
| 84 | return rc; |
| 85 | } |
| 86 | |
| 87 | void do_boot_appcpu(uint32_t img_index, uint32_t slot) |
| 88 | { |
Almir Okato | a1d641d | 2022-02-21 19:31:46 -0300 | [diff] [blame] | 89 | struct image_header img_header; |
| 90 | |
| 91 | if (read_image_header(img_index, slot, &img_header) != 0) { |
| 92 | FIH_PANIC; |
| 93 | } |
| 94 | |
Almir Okato | c4b3058 | 2022-05-06 14:59:43 -0300 | [diff] [blame] | 95 | start_cpu1_image(img_index, slot, img_header.ih_hdr_size); |
Almir Okato | a1d641d | 2022-02-21 19:31:46 -0300 | [diff] [blame] | 96 | } |
| 97 | #endif |
| 98 | |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 99 | int main() |
| 100 | { |
Almir Okato | fa173df | 2022-04-19 01:10:30 -0300 | [diff] [blame] | 101 | if (bootloader_init() != ESP_OK) { |
| 102 | FIH_PANIC; |
| 103 | } |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 104 | |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 105 | /* Rough steps for a first boot when Secure Boot and/or Flash Encryption are still disabled on device: |
| 106 | * Secure Boot: |
| 107 | * 1) Calculate the SHA-256 hash digest of the public key and write to EFUSE. |
| 108 | * 2) Validate the application images and prepare the booting process. |
| 109 | * 3) Burn EFUSE to enable Secure Boot V2 (ABS_DONE_0). |
| 110 | * Flash Encryption: |
| 111 | * 4) Generate Flash Encryption key and write to EFUSE. |
| 112 | * 5) Encrypt flash in-place including bootloader, image primary/secondary slot and scratch. |
| 113 | * 6) Burn EFUSE to enable Flash Encryption. |
| 114 | * 7) Reset system to ensure Flash Encryption cache resets properly. |
| 115 | */ |
| 116 | |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 117 | #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH |
| 118 | BOOT_LOG_WRN("eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!"); |
| 119 | esp_efuse_init_virtual_mode_in_flash(CONFIG_EFUSE_VIRTUAL_OFFSET, CONFIG_EFUSE_VIRTUAL_SIZE); |
Shubham Kulkarni | 8787bb0 | 2021-07-20 11:46:03 +0530 | [diff] [blame] | 120 | #endif |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 121 | |
Almir Okato | db2024e | 2023-08-24 15:40:26 -0300 | [diff] [blame] | 122 | #if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_FLASH_ENC_ENABLED) |
| 123 | esp_err_t err; |
| 124 | #endif |
| 125 | |
| 126 | #ifdef CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER |
| 127 | if (esp_secure_boot_enabled() ^ esp_flash_encrypt_initialized_once()) { |
| 128 | BOOT_LOG_ERR("Secure Boot and Flash Encryption cannot be enabled separately, only together (their keys go into one eFuse key block)"); |
| 129 | FIH_PANIC; |
| 130 | } |
| 131 | |
| 132 | if (!esp_secure_boot_enabled() || !esp_flash_encryption_enabled()) { |
| 133 | esp_efuse_batch_write_begin(); |
| 134 | } |
| 135 | #endif // CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER |
| 136 | |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 137 | #ifdef CONFIG_SECURE_BOOT |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 138 | /* Steps 1 (see above for full description): |
| 139 | * 1) Compute digest of the public key. |
| 140 | */ |
| 141 | |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 142 | BOOT_LOG_INF("enabling secure boot v2..."); |
| 143 | |
| 144 | bool sb_hw_enabled = esp_secure_boot_enabled(); |
| 145 | |
| 146 | if (sb_hw_enabled) { |
| 147 | BOOT_LOG_INF("secure boot v2 is already enabled, continuing.."); |
| 148 | } else { |
| 149 | esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */ |
| 150 | |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 151 | err = check_and_generate_secure_boot_keys(); |
| 152 | if (err != ESP_OK) { |
| 153 | esp_efuse_batch_write_cancel(); |
| 154 | FIH_PANIC; |
| 155 | } |
| 156 | } |
| 157 | #endif |
| 158 | |
Almir Okato | eb6b7bf | 2021-09-07 17:06:35 -0300 | [diff] [blame] | 159 | os_heap_init(); |
| 160 | |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 161 | struct boot_rsp rsp; |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 162 | |
Michael Grand | 5047f03 | 2022-11-24 16:49:56 +0100 | [diff] [blame] | 163 | FIH_DECLARE(fih_rc, FIH_FAILURE); |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 164 | |
Almir Okato | e8cbc0d | 2022-06-13 10:45:39 -0300 | [diff] [blame] | 165 | #ifdef CONFIG_MCUBOOT_SERIAL |
| 166 | boot_console_init(); |
| 167 | if (boot_serial_detect_pin()) { |
| 168 | BOOT_LOG_INF("Enter the serial recovery mode"); |
| 169 | boot_serial_start(&boot_funcs); |
| 170 | } |
| 171 | #endif |
| 172 | |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 173 | /* Step 2 (see above for full description): |
| 174 | * 2) MCUboot validates the application images and prepares the booting process. |
| 175 | */ |
| 176 | |
Almir Okato | a1d641d | 2022-02-21 19:31:46 -0300 | [diff] [blame] | 177 | /* MCUboot's boot_go validates and checks all images for update and returns |
| 178 | * the load information for booting the main image |
| 179 | */ |
Shubham Kulkarni | 8787bb0 | 2021-07-20 11:46:03 +0530 | [diff] [blame] | 180 | FIH_CALL(boot_go, fih_rc, &rsp); |
Michael Grand | 5047f03 | 2022-11-24 16:49:56 +0100 | [diff] [blame] | 181 | if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { |
Gustavo Henrique Nihei | d985d22 | 2021-11-12 14:21:12 -0300 | [diff] [blame] | 182 | BOOT_LOG_ERR("Unable to find bootable image"); |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 183 | #ifdef CONFIG_SECURE_BOOT |
| 184 | esp_efuse_batch_write_cancel(); |
| 185 | #endif |
Shubham Kulkarni | 8787bb0 | 2021-07-20 11:46:03 +0530 | [diff] [blame] | 186 | FIH_PANIC; |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 187 | } |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 188 | |
| 189 | #ifdef CONFIG_SECURE_BOOT |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 190 | /* Step 3 (see above for full description): |
| 191 | * 3) Burn EFUSE to enable Secure Boot V2. |
| 192 | */ |
| 193 | |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 194 | if (!sb_hw_enabled) { |
| 195 | BOOT_LOG_INF("blowing secure boot efuse..."); |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 196 | err = esp_secure_boot_enable_secure_features(); |
| 197 | if (err != ESP_OK) { |
| 198 | esp_efuse_batch_write_cancel(); |
| 199 | FIH_PANIC; |
| 200 | } |
| 201 | |
| 202 | err = esp_efuse_batch_write_commit(); |
| 203 | if (err != ESP_OK) { |
| 204 | BOOT_LOG_ERR("Error programming security eFuses (err=0x%x).", err); |
| 205 | FIH_PANIC; |
| 206 | } |
| 207 | |
| 208 | #ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE |
| 209 | assert(esp_efuse_read_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE)); |
| 210 | #endif |
| 211 | |
Almir Okato | db2024e | 2023-08-24 15:40:26 -0300 | [diff] [blame] | 212 | #ifndef CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 213 | assert(esp_secure_boot_enabled()); |
| 214 | BOOT_LOG_INF("Secure boot permanently enabled"); |
Almir Okato | db2024e | 2023-08-24 15:40:26 -0300 | [diff] [blame] | 215 | #endif |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 216 | } |
| 217 | #endif |
| 218 | |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 219 | #ifdef CONFIG_SECURE_FLASH_ENC_ENABLED |
| 220 | /* Step 4, 5 & 6 (see above for full description): |
| 221 | * 4) Generate Flash Encryption key and write to EFUSE. |
| 222 | * 5) Encrypt flash in-place including bootloader, image primary/secondary slot and scratch. |
| 223 | * 6) Burn EFUSE to enable flash encryption |
| 224 | */ |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 225 | BOOT_LOG_INF("Checking flash encryption..."); |
Almir Okato | db2024e | 2023-08-24 15:40:26 -0300 | [diff] [blame] | 226 | bool flash_encryption_enabled = esp_flash_encrypt_state(); |
| 227 | if (!flash_encryption_enabled) { |
| 228 | #ifdef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED |
| 229 | BOOT_LOG_ERR("flash encryption is not enabled, and SECURE_FLASH_REQUIRE_ALREADY_ENABLED is set, refusing to boot."); |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 230 | FIH_PANIC; |
Almir Okato | db2024e | 2023-08-24 15:40:26 -0300 | [diff] [blame] | 231 | #endif // CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED |
| 232 | |
| 233 | if (esp_flash_encrypt_is_write_protected(true)) { |
| 234 | FIH_PANIC; |
| 235 | } |
| 236 | |
| 237 | err = esp_flash_encrypt_init(); |
| 238 | if (err != ESP_OK) { |
| 239 | BOOT_LOG_ERR("Initialization of Flash Encryption key failed (%d)", err); |
| 240 | FIH_PANIC; |
| 241 | } |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 242 | } |
| 243 | |
Almir Okato | db2024e | 2023-08-24 15:40:26 -0300 | [diff] [blame] | 244 | if (!flash_encryption_enabled) { |
| 245 | err = esp_flash_encrypt_contents(); |
| 246 | if (err != ESP_OK) { |
| 247 | BOOT_LOG_ERR("Encryption flash contents failed (%d)", err); |
| 248 | FIH_PANIC; |
| 249 | } |
| 250 | |
| 251 | err = esp_flash_encrypt_enable(); |
| 252 | if (err != ESP_OK) { |
| 253 | BOOT_LOG_ERR("Enabling of Flash encryption failed (%d)", err); |
| 254 | FIH_PANIC; |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | #ifdef CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER |
| 259 | if (!esp_secure_boot_enabled() || !flash_encryption_enabled) { |
| 260 | err = esp_efuse_batch_write_commit(); |
| 261 | if (err != ESP_OK) { |
| 262 | BOOT_LOG_ERR("Error programming eFuses (err=0x%x).", err); |
| 263 | FIH_PANIC; |
| 264 | } |
| 265 | assert(esp_secure_boot_enabled()); |
| 266 | BOOT_LOG_INF("Secure boot permanently enabled"); |
| 267 | } |
| 268 | #endif // CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER |
| 269 | |
Almir Okato | 14763b1 | 2021-11-25 00:45:26 -0300 | [diff] [blame] | 270 | /* Step 7 (see above for full description): |
| 271 | * 7) Reset system to ensure flash encryption cache resets properly. |
| 272 | */ |
| 273 | if (!flash_encryption_enabled && esp_flash_encryption_enabled()) { |
| 274 | BOOT_LOG_INF("Resetting with flash encryption enabled..."); |
| 275 | bootloader_reset(); |
| 276 | } |
| 277 | #endif |
| 278 | |
| 279 | BOOT_LOG_INF("Disabling RNG early entropy source..."); |
| 280 | bootloader_random_disable(); |
| 281 | |
Almir Okato | db2024e | 2023-08-24 15:40:26 -0300 | [diff] [blame] | 282 | /* Disable glitch reset after all the security checks are completed. |
| 283 | * Glitch detection can be falsely triggered by EMI interference (high RF TX power, etc) |
| 284 | * and to avoid such false alarms, disable it. |
| 285 | */ |
| 286 | bootloader_ana_clock_glitch_reset_config(false); |
| 287 | |
Almir Okato | a1d641d | 2022-02-21 19:31:46 -0300 | [diff] [blame] | 288 | #ifdef CONFIG_ESP_MULTI_PROCESSOR_BOOT |
| 289 | /* Multi image independent boot |
| 290 | * Boot on the second processor happens before the image0 boot |
| 291 | */ |
| 292 | do_boot_appcpu(IMAGE_INDEX_1, PRIMARY_SLOT); |
| 293 | #endif |
| 294 | |
Shubham Kulkarni | 8787bb0 | 2021-07-20 11:46:03 +0530 | [diff] [blame] | 295 | do_boot(&rsp); |
Gustavo Henrique Nihei | 523ef3f | 2021-11-12 17:53:18 -0300 | [diff] [blame] | 296 | |
Shubham Kulkarni | 052561d | 2021-07-20 11:42:44 +0530 | [diff] [blame] | 297 | while(1); |
| 298 | } |