Page 1 of 1

encrypt firmware with ESP32

Posted: Mon Jun 29, 2020 7:52 pm
by AlexESP32
Hey guys ;)

As mentioned in the topic I want to encrypt the firmware with the stored nvs data (password, certificates, ...).
Unfortunately I didn't understand the method of the espressif documentation (flash encryption, nvs encrytpion, secure boot).

To encrypt the NVS there are some questions:
Do I really need to adjust the source code or is it possible to do all with python scripts?
I tried this method: ... esp32-4n9k and there is an additional function "nvs_secure_initialize". Do I need this function? Unfortunately this doesnt work in my opinion...

Thank you in advance.

Kind Regards,

Re: encrypt firmware with ESP32

Posted: Wed Jul 01, 2020 10:07 am
by ESP_jakob
Hi Alex,

NVS encryption, flash encryption and secure boot are different things which partially depend on each other. Let's put secure boot aside and try to only do nvs encryption first.

You first need to enable flash encryption, sometimes also called "generic flash encryption". I recommend using a host-generated key for first trials which allows you to re-flash the app as many times as possible, if the settings are correct. You can find instructions here: ... erated-key.
Once have done that and verified that the app is encrypted, e.g. by using the flash encryption example , you can proceed to enabling nvs encryption.

You DO NOT mark the nvs partition itself as encrypted, as nvs encryption works differently than the normal flash encryption.
But you do need little key partition which is encrypted with normal flash encryption. This and the other steps to setup and use an encrypted nvs partition are described here: ... encryption. We don't have an example app for nvs encryption, but you can have a look at the nvs unit tests: ... nvs.c#L346. These unit tests work, I just tested them today. They erase the whole nvs partition before each run, though.

Despite your opinion, you do need to use

Code: Select all

instead of the normal initialization functions ;) . Without it you won't have nvs encryption. The rest of the code, even the de-initialization stays the same though.
You also need to compile in the options for generic flash encryption and nvs flash encryption, as described in the document pages.

Only after succeeding with all this to a satisfiable degree, I recommend you can think about secure boot. After enabling secure boot and flash encryption in release mode, your debugging and re-flashing abilities will be very limited!

Let us know how it goes!

All the Best,

Re: encrypt firmware with ESP32

Posted: Thu Jul 02, 2020 4:58 pm
by AlexESP32
Hey Jakob!

Thank you very much :)

I think I am on the right way:
I can encrypt my partitions with flash encryption and also I got nvs encryption to work.

But there are some more questions:
1. Maybe it is possilbe to explain in short why nvs cannot be encrypted with flash encryption.
In my opinion the encryption works like that:
Take the key and encrypt bootloader, partition table, all application and all partitions which has the addition "encrypted". What are the problems that nvs cannot be encrypted here?

2. What is the method if I want to re-flash the firmware (also the nvs partition) in release mode?
In my opinion I have to encrypt the firmware / partition !at the host! with the key which I have created and then I flash the encrypted firmware. Am I right? What is the command for this?

3. Why Development Mode is not "secure"? In my opinion the only difference between Development Mode and Release Mode is: At Development Mode I can flash the ESP 4x with plain text. At release I can do this only once. Am I right? In this case Development Mode would be secure too.

4. What is this command for: encrypted-flash monitor
In my opinion I use this command if a key is burned and the firmware is encrypted and I want to flash a new encrypted firmware.
But if this is true: Why is there no key required to encrypt this new firmware at the host?
And what is the difference to this command: encrypt_flash_data --keyfile my_flash_encryption_key.bin --address 0x10000 -o build/my-app-encrypted.bin build/my-app.bin
The last command make much more sense in my opinion than this command: encrypted-flash monitor

Thank you very much :) :)

Re: encrypt firmware with ESP32

Posted: Mon Jul 06, 2020 5:44 am
by ESP_jakob
Hi Alex,

Nice to hear your success!

Regarding your questions:
1: NVS relies on the entry state bitmap and the header for each page which are specially tailored to only write 0 bits (this is the way flash writes work) unless the whole page is erased. Hence, this needs to work on the raw flash.

2: You can also trigger the ESP to generate its own key and then encrypt the firmware with that one so that it is never exposed to outside the hardware. In release mode, the encryption happens on the device, right after flashing. This is named "plaintext flashing" in the corresponding sections of the documentation. You can only do this for a very limited number of times (usually 4 on the ESP32). Please refer to the following document: ... figuration.

3. Development is not secure because you can still flash a new image, hence change the code on the device and potentially read plaintext flash data with that code. The plaintext flashes are always limited as described above. If you generated and saved the key outside the ESP, then you can do an unlimited amount of "encrypted flashes" in development mode with the correct settings.

4. This is the command to do the "encrypted flash" with the key saved somewhere on the host. At least after the first flash, it will automatically pick up the correct key file but I'm not familiar with the details. If you only want to flash the app (and not the other partitions), you can also use encrypted-app-flash.


Re: encrypt firmware with ESP32

Posted: Mon Jul 06, 2020 10:51 am
by AlexESP32
Thank you jakob ;)

Now I understand 1. & 4.

But I still don't understand the difference between Release and Development in detail...
1. Can I have unlimited amount of "encrypted flashes" in Release Mode?
2. If the "hacker" can re-flash the firmware at Development Mode with his plaintext firmware he is still not able to read the encrypted partition from my firmware, so why is the development firmware unsecure? Maybe I don't understand a small detail :D... Could you explain this again with maybe some small example please?
3. How is it possible to encrypt the firmware at host side so there is no "plaintext flashing and encryption at first boot at esp". This would make the mass production much faster. Otherwise we must always wait till the encryption is finished :)
4. I want to have the same key for all my ESPs so I can decrypt all the firmwares If I want this.
If I store the key in safe environment and the key won't be stolen the "host generated key mode" is secure. Do you agree with this?

Thank you again ;)

Re: encrypt firmware with ESP32

Posted: Tue Jul 07, 2020 4:24 am
by AlexESP32
5. Is it necessary to encrypt the Ota firmeware at host side too or will this happen automatically at 1. Boot in esp (if download of the new firmware finished)? If the encryption at host side is needed: which command is the preferred one?

Thank you 😉

Re: encrypt firmware with ESP32

Posted: Fri Jul 10, 2020 2:14 pm
by AlexESP32
The questions are still there :(
Additionally there are some more questions:
What exactly is download_dis_decrypt / download_dis_encrypt for? Is it possible to explain the difference in one example when these bits are set and when these bits are not set...

Re: encrypt firmware with ESP32

Posted: Fri Jul 10, 2020 2:43 pm
by usulrasolas
I am going to be working on this in the future myself and am not there in my project.
I specifically am using the esp32-s2 for secure and encrypted features, so I will try and answer what I can from my research.

1) I believe in release mode with a unreadable burned in key, you have a maximum of 3 times of resetting the system to unencrypted. While encrypted, many if not all the uart flash functions are disabled when in release mode with an unreadable burned in key. You may use ota updates still with any encryption mode.
2) In security, it's better to talk in levels than absolutes. The example I can provide to illustrate why it might be less secure than release mode is that if you have everything encrypted and stored, and someone flashes some other firmware to allows them to scrape/view your encrypted data, patterns can be discovered and the process can be reversed with just some long processing times. Say I know a registers approximate location and value, if this is repeating pattern or value ( integer 252525252525 or binary 00000000000000) we can start to reverse engineer the keys with known starting values, drastically reducing calculation time to crack. If you're worried about this level of attack, the solution is to structure any areas with every other 16 bits being filled with a junk value (suggested to use something like system timer).
3&5) These are related and I don't have a definite answer for you. I hope that we can use host-key pre encrypted as it would prevent the unencrypted binaries from being transmitted ota.
4) provided you have a perfectly secure setup and store the key in an offline system or storage, it is close to as secure as the blind burn in key. My personal recommendation would be to use a single host key for a particular release or hardware set/revision to increase the security of host key. This is another area where this is levels of security, and a blind burned key is just always more secure than one that could be downloaded in any format. How can the key get stolen if you don't even know the key? :lol: 8-)