Flash Encryption (Development) and Secure Boot

neptunes
Posts: 1
Joined: Thu Nov 20, 2025 4:38 pm

Flash Encryption (Development) and Secure Boot

Postby neptunes » Thu Nov 20, 2025 4:58 pm

Issue
The initial issue is that changing SPI_BOOT_CRYPT_CNT from 0b001 -> 0b011 changing my device from normal operation to getting
invalid header: 0xeecc68ce
which is quite unexpected since values 1 and 3 should have the same behavior.

This error generally means the
bootloader partition is re-flashed with a plaintext second stage bootloader image
instead of the encrypted binary

https://docs.espressif.com/projects/esp ... e-failures

Now when trying to flash again via
esptool write-flash --encrypt ..
I get
Warning: Security features enabled, so not changing any flash settings.
and
Cannot verify written data if encrypted or in secure download mode.
which makes me think something is changed internally where I can no longer use the --encrypt flag.

Prior to changing SPI_BOOT_CRYPT_CNT from 1 to 3, flash encryption (from what I could tell) and secure boot were working together.

Background

I am working with the esp32-s3. My intent is to protect firmware (keys, IP) and nvs (user data) while making my device as user friendly as possible.

Thus I am using flash encryption and secure boot. My flash encryption I have been using has been in development mode as I don't see a reason to use release mode and I would like the esp to internally handle keys for encryption (as I believe it does for dev mode). I do know SPI_BOOT_CRYPT_CNT then must be burned to 3 in order to secure device flash which is the step that caused my issue.

Nespressif
Posts: 89
Joined: Tue Sep 12, 2017 11:25 am

Re: Flash Encryption (Development) and Secure Boot

Postby Nespressif » Fri Nov 21, 2025 7:48 am

Issue
The initial issue is that changing SPI_BOOT_CRYPT_CNT from 0b001 -> 0b011 changing my device from normal operation to getting
invalid header: 0xeecc68ce
which is quite unexpected since values 1 and 3 should have the same behavior.
Hello, flash encryption is active when the number of CNT bits is odd, 0000001 active, 0000011 inactive. It is not the decimal value, but rather the number of bits. If it is even, you must burn another one until you get 111 to make it active again.

A
number that indicating whether the contents of flash have been encrypted.

If an odd number of bits are set (e.g., 0b0000001 or 0b0000111), this indicates the contents of flash are encrypted. The contents will need to be transparently decrypted when read.

If an even number of bits are set (e.g., 0b0000000 or 0b0000011), this indicates the contents of flash are unencrypted (i.e., plain text).

Burn CNT with 7 to set it back to odd 0x0000111 and use these commands to flash, as I imagine the encryption key will have been generated internally in the chip.

Re-flashing Updated Partitions
If you update your application code (done in plaintext) and want to re-flash it, you will need to encrypt it before flashing. To encrypt the application and flash it in one step, run:

idf.py encrypted-app-flash monitor
If all partitions needs to be updated in encrypted format, run:

idf.py encrypted-flash monitor

To flash after activating FE and SB, you must use --force, although it is necessary to understand how everything works so as not to block the device. However, as long as you keep DOWNLOAD_ROM_MODE_UART enabled, you will always have room to test.

My recommendation is that you enable FE and SBv2 security features externally, following the workflows outlined in the security guide documentation, but always leaving the burning of security efuses for last. You can also use scripts, which the AI quickly generates to automate the process.

regards

Who is online

Users browsing this forum: Baidu [Spider], Bytespider and 12 guests