Page 1 of 1

ESP32 UART Encrypted Firmware Update

Posted: Wed Apr 26, 2023 8:27 am
by mckey128
Hallo everyone,

I am trying to figure out how to securely update the application via UART of my ESP32S3 module.
I've been reading almost all documents around but one way or the other I am always missing a part of it.

1. I am not not using an OTA update. I have no space left in the external flash as my app itself is around 4MB then I need to add NVS and Filesystem (SPIFFS in my case). All have to be updated at the same time. Any succestion about OTA is not fitting my case.

2. I need to disable the JTag to prevent attaker to hook up on it and sniff my code. So I will do a soft-disable, the reason of a soft-disable is because I'd like to debug the module just in case and I can use a UART Command to revert the JTag lock. Does it make any sense?

3. I need to flash the encrypted binary of my application. In this case I was thinking about encrypting the whole flash (I use always the same key for all modules to make a global update) and then flash it using the UART.

Now... I was rading this doc https://docs.espressif.com/projects/esp ... via-serial but it all looks a bit confusing an it is not really providing me with a clear procedure about how to do it.
I am particular the who documentation about flash update along with eFuses is really misleading. There are tons of possible combinations between secure-boot, flash encryption, Jtag disabling, UART disabling and on and on which is making me miss the focus of goal.

I've been tring to ask to people at Espressif but none came back with a clear procudere throwing me back to well-known docs.

I am open to any advice, please HELP.

Re: ESP32 UART Encrypted Firmware Update

Posted: Tue May 02, 2023 12:43 pm
by ESP_flying_raijin
Hi mckey128

The way you can flash the encrypted binary on esp32s3 module would depend on the eFuse configuration set for your module.
If the Flash encryption is enabled for the Release mode then I think you need to opt for method 1 as follows

Method 1 - External encryption and flashing
https://docs.espressif.com/projects/esp ... ing-files
In this case the plaintext aes-xts key ( 256 bit or 512 bit) needs to be known to the host. The host would take the key and un-encrypted binary and generate an encrypted binary using espsecure.py utility. This encrypted binary can then be directly flashed on the chip using the write_flash command. In ESP32S3 the UART ROM DL mode can be safely set to Secure ROM DL mode which allows limited operations for UART ROM DL mode. the write_flash operation is supported so you can write the binary on the flash. As the binary is encrypted on host hence we would just write the binary as it is.

Method 2 - Encryption on esp32 device when it is in ROM DL mode
In above case when I say that Flash Encryption is enabled in Release mode. I particularly mean the state of the eFuse with name DIS_DOWNLOAD_MANUAL_ENCRYPT and the status of ENABLE_SECURITY_DOWNLOAD and DIS_DOWNLOAD_MODE.
By default when Flash encryption is enabled in release mode the eFuse `DIS_DOWNLOAD_MANUAL_ENCRYPT` and ENABLE_SECURITY_DOWNLOAD is set to 1. Due to this we are unable to perform encryption operation in the UART ROM download mode.
Alternatively, when Flash encryption is enabled in development mode the eFuses ENABLE_SECURITY_DOWNLOAD and DIS_DOWNLOAD_MANUAL_ENCRYPT are not set. Hence the ROM bootloader can perform the encryption operation in the UART ROM download mode to allow following.
In this case we need to only have the plaintext firmware. The flash encryption key that is burned in the eFuse does not need to be known.
We shall just write the flash and provide `--encrypt` option. The ROM bootloader takes the plaintext binary from esptool and encrypts the binary before writing to the flash. It users the flash encryption key burned in the eFuse hence the key does not need to be known outside of the device and each device can have unique Flash encryption key. This would however add timing overhead because encryption happens on esp32 device with limited resource. More details about this operation can be found here https://docs.espressif.com/projects/esp ... protection


in your case as you mentioned the flash encryption is is common for all the devices, the Method 1 is more suitable for you as you can simple perform the encryption outside which is very fast ( uses host machine resources for encryption which have not limits) and just write the flash on the chip. Just to note here, as you require the ability to write flash on the chip, you must disable the UART ROM DL mode by setting the eFuse DIS_DOWNLOAD_MODE. This is done automatically when you the option https://docs.espressif.com/projects/esp ... om-dl-mode is set to permanently disable the UART ROM DL mode.


I would recommend using unique flash encryption keys for each device. This would definitely complicate the key management process in your case as you may have to manage unique key for each device but I think that would greatly reduce the attach surface. Otherwise the plaintext aes-xts key is becomes highly critical and vulnerable.

I would recommend you to enable secure OTA by efficiently managing the flash on your chip or increasing the flash size in order to reduce the key management overhead. Also I think updating each device through UART would need physical access to each device, I am not sure if it is suitable for on-field devices.

Please let me know if you want me to elaborate on any point.

Thanks,
Aditya