espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.54k stars 7.26k forks source link

Secure boot seems not checking signature for partition app (IDFGH-12220) #13273

Closed GuillaumeHupi closed 7 months ago

GuillaumeHupi commented 7 months ago

Answers checklist.

General issue report

Hello,

I want to enable secure boot V2 and flash encryption on my esp32-s3 board. So I have followed this guide https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/security/host-based-security-workflows.html.

I'm not using the last esp-idf version because I need to use arduino component and it was not yet working with the last version. So I use v5.1.2.

I followed all the steps of the guide to implement the flash encryption and the secure boot. Since I'm in development, I just didn't followed the last step for secure boot and flash encryption which consists of burning security efuses.

Flash encryption seems to work perfectly. Since if I upload files without encryption or encrypted with a wrong key, I got errors in logs. And if files are well encrypted, it works perfectly.

But regarding secure boot, I'm not sure it is working as expected. If I upload a bootloder wich is not signed, I got errors on boot which is normal. If the bootloader is signed, it works like a charm. So secure boot seems to work for the bootloader. But for the application partition, the code is running weather the firmware is signed or not. So the secure boot seems not be working for application partition. I also tried to make ota update, I got the exact same result.

I checked on the web and it seems that when secure boot in bootloader is enabled in menuconfig, it also enables it for app partition by default, am I wrong ?

The process I use to build all the partitions is :

  1. Build the program with the build button in vscode with esp-idf extension
  2. Sign firmware and bootloader with espsecure
  3. Encrypt firmware, bootloader and partition table with espsecure
  4. Upload all the partitions with esptool

If I skip step 2 for firmware, it works perfectly while it shouldn't, isn't it ? I precise that the "sign binaries during build" option in menu config is unchecked.

So I don't understand why the esp32 is not checking if app partition is signed or not while secure boot is activated and working for the bootloader partition.

mahavirj commented 7 months ago

@GuillaumeHupi

Have you enabled CONFIG_SECURE_BOOT or CONFIG_SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT while building the bootloader? If not, then bootloader will not verify the application signature. This is highlighted in the Step 5 here.

It will help if you could share your sdkconfig here.

GuillaumeHupi commented 7 months ago

I'm so stupid! I used the menuconfig button on vscode and checked "Enable hardware Secure Boot in bootloader". But I thought it was automatically saved since there was no save button. But after reloading the menuconfig page, the modifications I made were deleted. But this time a save button appeared. So this time I made the modifications and pressed the save button made a new build, signed and encrypted files and it worked as expected. Thanks for the hint @mahavirj !

Now I got an other problem. I was able to use the OTA. But after enabling secure boot, the bootloader was bigger so I had to modify a bit the addresses in the partition table to increase the bootloader partition. And now because of secure boot, I have to upload manually individual partition (signed and encrypted for some of them) with --no-stub and --force arguments. This is not really a problem. So I was able to upload the new bootloader, the new partition table, the new firmware and the new spiffs partition. And all of them are working perfectly. But for the OTA, I got the error "E (165) boot: ota data partition invalid, falling back to factory". Wich is logical since I modified the otadata offset when I increased the bootloader partition size. So I try to find a way to reinitialize the otadata partition, but I don't know how. I can't use the vscode flash button since the activation of secure boot. So I have to do it manually. I think I found the otadata bin file which is automatically generated during build. Is it "ota_data_initial.bin" ? I tried upload it at the right offset with esptool.py -p /dev/tty.usbserial-0001 -b 460800 --before default_reset --no-stub --after hard_reset --chip esp32-S3 write_flash --flash_mode dio --flash_size 8MB --flash_freq 40m 0x160000 build/ota_data_initial.bin --force

But it didn't work, I got exactly the same error on boot. I also tried to encrypt the partition before uploading but i got the same problem. So I don't know how to restore the otadata partition at its default state.

My partition table is : `# ESP-IDF Partition Table

Name, Type, SubType, Offset, Size, Flags

nvs, data, nvs, 0xb000, 0x4000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 0x150000, otadata, data, ota, 0x160000, 0x2000, ota_0, app, ota_0, 0x170000, 0x150000, encrypted ota_1, app, ota_1, 0x2C0000, 0x150000, encrypted storage, data, spiffs, 0x410000, 0x100000,`

mahavirj commented 7 months ago

@GuillaumeHupi

I also tried to encrypt the partition before uploading but i got the same problem. So I don't know how to restore the otadata partition at its default state.

Yes, otadata partition must be written in an encrypted manner. What command you used to encrypt the ota_data_initial.bin file?

But after enabling secure boot, the bootloader was bigger so I had to modify a bit the addresses in the partition table to increase the bootloader partition

Did you also rebuild bootloader, application with updated partition table offset?

Can you please share:

GuillaumeHupi commented 7 months ago

Yes, otadata partition must be written in an encrypted manner. What command you used to encrypt the ota_data_initial.bin file?

I used those commands to encrypt and upload the partition. (Did the same for other partitions + signing command for app and bootloader) :


espsecure.py encrypt_flash_data --aes_xts --keyfile my_flash_encryption_key.bin --address 0x160000 --output ota-enc.bin build/ota_data_initial.bin

esptool.py -p /dev/tty.usbserial-0001 -b 460800 --before default_reset --no-stub --after hard_reset --chip esp32-S3 write_flash --flash_mode dio --flash_size 8MB --flash_freq 40m 0x160000 ota-enc.bin --force


> Did you also rebuild bootloader, application with updated partition table offset?

Yes I rebuilt and uploaded all of them.

> Can you please share:
> 
> * Device efuse summary
> * console log for the failure case

Here are the console logs : 

SP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x29 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 Valid secure boot key blocks: 0 secure boot verification succeeded load:0x3fce3980,len:0x31f8 load:0x403c9700,len:0x4 load:0x403c9704,len:0xc00 load:0x403cc700,len:0x4d20 entry 0x403c9908 I (69) boot: ESP-IDF v5.1.2-dirty 2nd stage bootloader I (69) boot: compile time Feb 28 2024 09:54:51 I (70) boot: Multicore bootloader I (73) boot: chip revision: v0.1 I (77) boot.esp32s3: Boot SPI Speed : 80MHz I (82) boot.esp32s3: SPI Mode : DIO I (86) boot.esp32s3: SPI Flash Size : 8MB I (91) boot: Enabling RNG early entropy source... I (97) boot: Partition Table: I (100) boot: ## Label Usage Type ST Offset Length I (107) boot: 0 nvs WiFi data 01 02 0000b000 00004000 I (115) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (123) boot: 2 factory factory app 00 00 00010000 00150000 I (130) boot: 3 otadata OTA data 01 00 00160000 00002000 I (138) boot: 4 ota_0 OTA app 00 10 00170000 00150000 I (145) boot: 5 ota_1 OTA app 00 11 002c0000 00150000 I (153) boot: 6 storage Unknown data 01 82 00410000 00100000 I (160) boot: End of partition table E (165) boot: ota data partition invalid, falling back to factory I (171) esp_image: segment 0: paddr=00010020 vaddr=3c0a0020 size=25e0ch (155148) map I (211) esp_image: segment 1: paddr=00035e34 vaddr=3fc96d00 size=0469ch ( 18076) load I (215) esp_image: segment 2: paddr=0003a4d8 vaddr=40374000 size=05b40h ( 23360) load I (222) esp_image: segment 3: paddr=00040020 vaddr=42000020 size=93f24h (605988) map I (346) esp_image: segment 4: paddr=000d3f4c vaddr=40379b40 size=0d114h ( 53524) load I (359) esp_image: segment 5: paddr=000e1068 vaddr=00000000 size=0ef68h ( 61288) I (371) esp_image: Verifying image signature... I (372) secure_boot_v2: Verifying with RSA-PSS... I (375) secure_boot_v2: Signature verified successfully! I (384) boot: Loaded app from partition at offset 0x10000 I (384) secure_boot_v2: enabling secure boot v2... I (388) secure_boot_v2: secure boot v2 is already enabled, continuing.. I (395) boot: Disabling RNG early entropy source... I (412) cpu_start: Multicore app I (413) cpu_start: Pro cpu up. I (413) cpu_start: Starting app cpu, entry point is 0x403754a8 0x403754a8: call_start_cpu1 at /Users/guillaumecostes/esp/v5.1.2/esp-idf/components/esp_system/port/cpu_start.c:157

I (0) cpu_start: App cpu up. I (431) cpu_start: Pro cpu start user code I (431) cpu_start: cpu freq: 160000000 Hz I (431) cpu_start: Application information: I (434) cpu_start: Project name: template_project I (440) cpu_start: App version: 1 I (444) cpu_start: Compile time: Feb 28 2024 09:54:47 I (450) cpu_start: ELF file SHA256: 3d38bf975f532a01... I (456) cpu_start: ESP-IDF: v5.1.2-dirty I (461) cpu_start: Min chip rev: v0.0 I (466) cpu_start: Max chip rev: v0.99 I (471) cpu_start: Chip rev: v0.1 I (476) heap_init: Initializing. RAM available for dynamic allocation: I (483) heap_init: At 3FCA3290 len 00046480 (281 KiB): DRAM I (489) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM I (496) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM I (502) heap_init: At 600FE010 len 00001FD8 (7 KiB): RTCRAM I (509) spi_flash: detected chip: gd I (513) spi_flash: flash io: dio I (517) sleep: Configure to isolate all GPIO pins in sleep state I (523) sleep: Enable automatic switching of GPIO sleep configuration I (531) app_start: Starting scheduler on CPU0 I (535) app_start: Starting scheduler on CPU1 I (535) main_task: Started on CPU0 I (545) main_task: Calling app_main()


I (745) gpio: GPIO[0]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 Wifi & OTA task starting! I (775) pp: pp rom version: e7ae62f I (775) net80211: net80211 rom version: e7ae62f I (805) wifi:wifi driver task: 3fcaf284, prio:23, stack:6656, core=0 I (815) wifi:wifi firmware version: 91b9630 I (815) wifi:wifi certification version: v7.0 I (815) wifi:config NVS flash: enabled I (815) wifi:config nano formating: disabled I (815) wifi:Init data frame dynamic rx buffer num: 32 I (825) wifi:Init static rx mgmt buffer num: 5 I (825) wifi:Init management short buffer num: 32 I (835) wifi:Init dynamic tx buffer num: 32 I (835) wifi:Init static tx FG buffer num: 2 I (835) wifi:Init static rx buffer size: 1600 I (845) wifi:Init static rx buffer num: 10 I (845) wifi:Init dynamic rx buffer num: 32 I (875) wifi_init: rx ba win: 6 I (875) wifi_init: tcpip mbox: 32 I (875) wifi_init: udp mbox: 6 I (875) wifi_init: tcp mbox: 6 I (875) wifi_init: tcp tx win: 5744 I (875) wifi_init: tcp rx win: 5744 I (885) wifi_init: tcp mss: 1440 I (885) wifi_init: WiFi IRAM OP enabled I (895) wifi_init: WiFi RX IRAM OP enabled Unhandled WIFI_PROV_EVENT event: 0 Already provisioned, starting Wi-Fi STA Unhandled WIFI_PROV_EVENT event: 6 I (945) phy_init: phy_version 620,ec7ec30,Sep 5 2023,13:49:13 I (975) wifi:mode : sta (f4:12:fa:67:15:98) I (975) wifi:enable tsf

And for the efuses summary, how to get it when secure boot is enabled ? I got this error : 

espefuse.py --port /dev/tty.usbserial-0001 summary

espefuse.py v4.7.0 Connecting.... Detecting chip type... ESP32-S3

A fatal error occurred: Secure Download Mode is enabled. The tool can not read eFuses.

mahavirj commented 7 months ago

@GuillaumeHupi

E (165) boot: ota data partition invalid, falling back to factory

This looks good, since the initially otadata partition is all empty the default boot partition is factory. You need to activate different partition from the factory firmware using esp_ota_set_boot_partition to switch to either ota_0 or ota_1. Please consult https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/partition-tables.html for more information.

And for the efuses summary, how to get it when secure boot is enabled ? I got this error :

You can get minimal summary using esptool.py get_security_info once secure DL mode is enabled. Please see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/security/security.html#uart-download-mode

GuillaumeHupi commented 7 months ago

Oh Ok thank you, I thought the ota problem came from there. But I had other errors during ota process. It was related to httpd task stack overflow. But i fixed this problem and now it with working just fine.

The Security informations are :

Security Information:
=====================
Flags: 0x00000035 (0b110101)
Key Purposes: (4, 9, 0, 0, 0, 0, 12)
Chip ID: 9
API Version: 0
Secure Boot: Enabled
Secure Boot Key Revocation Status:

        Secure Boot Key1 is Revoked

        Secure Boot Key2 is Revoked

Flash Encryption: Enabled
SPI Boot Crypt Count (SPI_BOOT_CRYPT_CNT): 0x1

I have 1 last questions : By default spiffs is not encrypted, if I add the "encrypted" flag in the partition table, what is the process to read and write inside the spiffs ? Is the process transparent (no changes in use compared to unencrypted) or are there special functions to call in the main ?

mahavirj commented 7 months ago

@GuillaumeHupi

Unfortunately flash encryption is not supported with SPIFFS (https://github.com/espressif/esp-idf/issues/11048#issuecomment-1482332552). Please consider using FATFS or NVS for storage purpose.

GuillaumeHupi commented 7 months ago

Oh OK. Thanks for the tips and for problem solving ! Have a good day.