OTA update with secure boot and encryption

dmlee05a
Posts: 17
Joined: Thu Jul 06, 2017 4:00 pm

OTA update with secure boot and encryption

Postby dmlee05a » Sat Jun 30, 2018 2:12 am

I have successfully done OTA updates many times without using encryption and secure boot. I'm now trying to do an OTA update on a device that has both encryption enabled and secure boot. It fails with an error message:
E (3909293) esp_image: image at 0x150000 has invalid magic byte
W (3909293) esp_image: image at 0x150000 has invalid SPI mode 173

The original flashed image and the new image were both signed with the same key. The differences in the code are not huge, but they have different names, eg, test_version vs production_version. Not sure that should make a difference. Partitions tables are identical (shown below). Should both images be created with encryption and secure boot? Or should the second image be unsigned without secure boot? What is the correct process to achieve what I am trying to do? Thanks.

# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x140000,
app1, app, ota_1, 0x150000,0x140000,
eeprom, data, 0x99, 0x290000,0x1000,
spiffs, data, spiffs, 0x291000,0x16F000,

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: OTA update with secure boot and encryption

Postby ESP_Angus » Mon Jul 02, 2018 12:55 am

Hi dmlee,

The image will need to be signed, but doesn't need to be encrypted outside of the device - ie the .bin file will be plaintext when received by the ESP32, and then it will be encrypted transparently when written to the flash. (Note that the default output of the build process will be a signed plaintext .bin file, so it's likely this is what you have already.)

The error you're seeing suggests that esp_image_verify() is reading garbage from the app partition at 0x150000 - so either the image written there has been double-encrypted (was encrypted when download by the OTA function, and then encrypted again), or it has been written in plaintext when it should have been written encrypted. Or possibly it wasn't written at all and the flash contains all 0xFF, which is being converted to garbage on decryption.

Are you using the app_update component (ie calling esp_ota_write()?) Do you have any log output from earlier in the OTA process itself? What ESP-IDF version are you using?

Thanks,

Angus

dmlee05a
Posts: 17
Joined: Thu Jul 06, 2017 4:00 pm

Re: OTA update with secure boot and encryption

Postby dmlee05a » Mon Jul 02, 2018 8:07 pm

Angus,
Thanks for the help, I really appreciate it. To answer your questions (1) I'm using arduino libraries, so the esp_ota_write function is way down in the code from where I'm working. I think the Update library does use it. (2) During the attempt to update, the code reports that 890532 bytes were expected and 890532 were written successfully. (3) I updated the idf in on Jan. 29 and git tells me I'm using v3.0-dev-1678-gdaa8cfa8.

When I tried to update using the exact same file that was initially flashed, I get a slightly different errror message:
E (471146) esp_image: image at 0x150000 has invalid magic byte
W (471146) esp_image: image at 0x150000 has invalid SPI mode 186
W (471156) esp_image: image at 0x150000 has invalid SPI size 10

I used the flash commands that the idf printed out for the bootloader and app.
Could this be a cause of the problem: the flashing was done by a script that (a) flashed the bootloader (without reset after), then (b) flashed the app (which did a hard reset after), then (c) 10 seconds later used esptool.py to read the MAC address. Perhaps the device was encrypting when the read_MAC happened? However, the app functions perfectly fine.

I also assume (maybe incorrectly) that the app was flashed in ota_0 at 0x140000,and the update is flashing at 0x150000. They should be completely independent, right? I could flash totally different data in ota_1 as long as it fits in the partition, correct? Any chance the digest is too large to fit?

BTW, I copied the app directory to a different location and rebuilt it. The binaries are identical to the original build. I also have a couple of units with secure boot, but not encrypted, and they update fine.

Thanks again.


ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: OTA update with secure boot and encryption

Postby ESP_Angus » Tue Jul 03, 2018 12:01 am

Hi dmlee,

WiFive has hit the nail on the head. Arduino Updater doesn't actually use the app_update component to write the image, so doesn't support encrypted flash.

This may be something that can be implemented in the medium term (please consider opening a feature request on the arduino-esp32 repo on Github). However in the short term the best thing you can do is refactor to call app_update OTA functions directly.

Angus

dmlee05a
Posts: 17
Joined: Thu Jul 06, 2017 4:00 pm

Re: OTA update with secure boot and encryption

Postby dmlee05a » Tue Jul 03, 2018 12:38 am

Many thanks, guys... I'll stop pulling my hair out now.

snahmad75
Posts: 445
Joined: Wed Jan 24, 2018 6:32 pm

Re: OTA update with secure boot and encryption

Postby snahmad75 » Fri Nov 23, 2018 12:33 pm

Hi,

I enabled secure boot. and upload signed bins via flash. It works good. then over OTA. I used unsigned bin. OTA still works.

I am not using make menuconfig to enable secure boot. I am using

These comands.

Code: Select all

partitions="partitions.bin"
firmware="W2K1-BootLoader-Release.bin"
port="COM184"
baud="921600"
secure_boot_key="secure_boot_key.bin"
secure_sign_key="signing_key.pem"

echo "create secure bootloader"
/c/Work/library/esp32/esp-idf/components/esptool_py/esptool/espsecure.py digest_secure_bootloader --keyfile $secure_boot_key --output ./build/secure_bootloader.bin ./build/bootloader/bootloader.bin

echo "sign partitions"
/c/Work/library/esp32/esp-idf/components/esptool_py/esptool/espsecure.py sign_data --keyfile $secure_sign_key --output ./build/signed_$partitions ./build/$partitions

echo "sign firmware"
/c/Work/library/esp32/esp-idf/components/esptool_py/esptool/espsecure.py sign_data --keyfile $secure_sign_key --output ./build/signed_$firmware ./build/$firmware



echo "burn secure boot key"
/c/Work/library/esp32/esp-idf/components/esptool_py/esptool/espefuse.py --port $port burn_key secure_boot $secure_boot_key --no-protect-key

echo "Enable secure boot"
/c/Work/library/esp32/esp-idf/components/esptool_py/esptool/espefuse.py --port $port burn_efuse ABS_DONE_0 1

echo "Upload signed bins"
/c/Work/library/esp32/esp-idf/components/esptool_py/esptool/esptool.py --port $port --baud $baud write_flash 0x0000 ./build/secure_bootloader.bin 0x8000 ./build/signed_$partitions 0x10000 ./build/$firmware

I am confused. need help. I am expecting only signed bin over OTA should work not unsigned.

Thanks,
Naeem

Who is online

Users browsing this forum: Gilbert and 121 guests