Page 1 of 1

ESP32C3 Flash Encryption only works the first time, but not on repeat uploads

Posted: Tue Jul 01, 2025 6:49 pm
by BenKrug
Hello everyone, I'm working on an ESP32C3 project where I need to encrypt the firmware and be able to upload the firmware any number of times after Flash encryption has been enabled, on top of that ideally the firmware should already be encrypted when I upload it. On the ESP32 this all works as expected, but with the ESP32C3 I've tried and tried again with multiple ESPs and I've only managed ot make it work the first time when the ESP is clean. I'm not managing to get it to work on repeat uploads, I've tried doing it with esptool with pre encrypted binaries, plain text binaries, having the --encrypt option alongside the command, --encrypt-files, I have the boot mode as Development for now, but I think the one I need to use is Release, but not even with Development I'm managing to get something that works, and I'm stumped, I've been working on this for days to no avail, all I get is a loop of error messages saying "invalid header: 0x93c07c2c"(sometimes the specific hex is different, but I don't know if there's any meaning to it.

I also have a custom partition table file, that looks like this:

# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, factory, 0x10000, 0x200000, encrypted
spiffs, data, spiffs, 0x210000,0x1F0000,
I've also tested it without the encrypted flag on the app0 section and it didn't work as well.

I'm doing all this one Platformio with Arduino and ESP-IDF working together, so I can configure things via Menuconfig, with the pertinent sections of it looking like the following:
Captura de tela 2025-07-01 150921.png
Captura de tela 2025-07-01 150921.png (23.73 KiB) Viewed 66 times
Captura de tela 2025-07-01 151025.png
Captura de tela 2025-07-01 151025.png (12.27 KiB) Viewed 66 times
I tested the usage mode both in Development *and* in Release, and both had the same issues.
To start the encryption process, I use the following command:

Code: Select all

.\env\scripts\python.exe -m espefuse --port COM82 --do-not-confirm --baud 115200 burn_key BLOCK_KEY0 key.bin XTS_AES_128_KEY
When I want to upload the code pre-encrypted, I use these commands to encrypt the firmware files:

Code: Select all

.\env\scripts\python.exe -m espsecure encrypt_flash_data -x --keyfile key.bin --address 0x1000 -o enc\bootloader.bin .pio\build\esp32dev\bootloader.bin

.\env\scripts\python.exe -m espsecure encrypt_flash_data -x --keyfile key.bin --address 0x8000 -o enc\partitions.bin .pio\build\esp32dev\partitions.bin

.\env\scripts\python.exe -m espsecure encrypt_flash_data -x --keyfile key.bin --address 0x10000 -o enc\firmware.bin .pio\build\esp32dev\firmware.bin
Then to upload the code I do this:

Code: Select all

.\env\scripts\python.exe -m esptool --chip esp32c3 --baud 230400 COM82 --before default_reset --after hard_reset write_flash --flash_mode qio --flash_freq 80m --flash_size detect 0x1000 enc\bootloader.bin 0x8000 enc\partitions.bin 0x10000 enc\firmware.bin
I've also tried uploading the plain text code via Platformio's builtin upload feature with the same results.

I'm honestly out of ideas at the moment, so any help is very appreciated, thank you very much in advance to anyone that takes the time to help me out

Re: ESP32C3 Flash Encryption only works the first time, but not on repeat uploads

Posted: Thu Jul 03, 2025 12:13 pm
by BenKrug
UPDATE: So in the end my mistake was a couple of things all initially rooted in putting the wrong bootloader position in my command and then also not using the correct combination of commands, efuse configs and binary files.
- I had the bootloader position as 0x1000 when it was supposed to be 0x0000
- My second mistake was that when my device was in development mode I just needed to send the code with plaintext binaries with the "--encrypt" flag in the upload command , like this:

```
.\env\scripts\python.exe -m esptool --chip esp32c3 --baud 230400 COM82 --before default_reset --after hard_reset write_flash --flash_mode qio --flash_freq 80m --flash_size detect --encrypt 0x0000 enc\bootloader.bin 0x8000 enc\partitions.bin 0x10000 enc\firmware.bin
```
Fixing this then made the Development mode encryption work

- My third mistake was that the device I had put into Release mode had the keys mixed up from one of my tests of generating a new key(that was one of the tests I made when I was skidding in the mud lol), so when I pre-encrypted the files, obviously the ESP couldn't decrypt them, after I got a fresh ESP and used my original key, I got Release mode to work almost immediately, meaning my actual only mistake was having the bootloader wrong originally and then changing around things and losing track of them

Hopefully this is can be useful to someone else, granted I don't think anyone else will be as much of a buffoon as I was in this one.