Page 1 of 1

ESP32 Secure Bootloader

Posted: Thu Apr 04, 2019 10:42 pm
by applecrusher
I am currently trying to use secure bootloader for the ESP32.


I currently in the hello world app and I am trying to implement secure boot. I am currently using these two links, https://docs.pycom.io/advance/encryption.html, and https://docs.espressif.com/projects/esp ... oject.html to help me through the process, and I have all the esp32 tool chain and download the source code. However, I am having tremendous difficulty transforming the secure_boot_signing_key.pem has to be transformed into secure-bootloader-key.bin, or producing that particular file. I am not quite sure what they mean.

I have done the command

Code: Select all

python $IDF_PATH/components/esptool_py/esptool/espsecure.py generate_signing_key secure_boot_signing_key.pem
And then the command

Code: Select all

python $IDF_PATH/components/esptool_py/esptool/espsecure.py extract_public_key --keyfile secure_boot_signing_key.pem signature_verification_key.bin
The last command just extracts the public key. If you look at both the espressif documentation and the pycom documentation, this just extracts a 64 bit key, which I thought would have been the secure bootloader key, but the secure bootloader key is just a 32 bit key. So how do I create a secure bootloader key?

I tried the build command

Code: Select all

make BOARD=GPY SECURE=on TARGET=boot
and this does not produce a secure bootloader key either. I would appreciate any help in creating a secure boot loader with the hello world app. Thank you.

Re: ESP32 Secure Bootloader

Posted: Fri Apr 05, 2019 12:15 am
by ESP_Angus
applecrusher wrote:
Thu Apr 04, 2019 10:42 pm
The last command just extracts the public key. If you look at both the espressif documentation and the pycom documentation, this just extracts a 64 bit key, which I thought would have been the secure bootloader key, but the secure bootloader key is just a 32 bit key. So how do I create a secure bootloader key?
It's a bit confusing, as hardware secure boot on the ESP32 is a two stage process (a summary of the full process is here).

The first boot stage is when the ROM loads the bootloader.bin from the flash. This uses a "digest" of the bootloader (stored in flash at offset 0x0) which is generated from a 32 byte (256 bit) secure bootloader key which is stored in efuse and not readable by software. This digest can be generated beforehand ("reflashable" mode) or generated by the device on first boot ("one-time flash" mode).

The second boot stage is when the IDF bootloader verifies the app. This part uses an ECDSA signature appended to the app .bin file. This signature is created using the private key of an Elliptic Curve key pair (secure_boot_signing_key.pem). The IDF bootloader itself contains just the public key data from this EC key pair as 64 bytes of raw binary data (signature_verification_key.bin), which is enough for it to verify the signature. Storing only the public key means that even if an attacker gets a copy of bootloader.bin, they can't generate any new signatures.

Going back to the first boot stage, in "one-time flash" mode the key stored in efuse is generated from the hardware random number generator and no copy is ever available elsewhere. This means the IDF bootloader can only be flashed once (but the IDF bootloader can still boot any app which is signed correctly).

In "reflashable" mode, you keep a copy of the key which is in efuse so it's possible to generate new secure boot digests, in order to update the bootloader. One option here would be to generate a random 32 byte key and burn this to efuse. However then you would need to keep two secrets - secure_boot_signing_key.pem and this 32 byte random key. To reduce the number of secret files, the ESP-IDF build system has a step where it takes the SHA-256 digest of secure_boot_signing_key.pem and this can be used as the secure boot key in efuse. This means you only need to keep one file secret - secure_boot_signing_key.pem - for both things.

In IDF build system, this step is done automatically. If you're using PyCom's tools then it might not be automatic, but you can do it as follows:

Code: Select all

espsecure.py digest_private_key --keyfile secure_boot_signing_key.pem secure-bootloader-key.bin
Then burn secure-booloader-key key to efuse:

Code: Select all

espefuse.py burn_key secure_boot secure-bootloader-key.bin
Then, if secure boot is already enabled and you want to reflash bootloader.bin:

Code: Select all

espsecure.py digest_secure_bootloader --keyfile secure-bootloader-key.bin --output bootloader-digest.bin bootloader.bin
esptool.py write_flash 0x0 bootloader-digest.bin
(See also here)

If using the ESP-IDF build system then all of these steps are built-in, so the build system will produce secure-bootloader-key.bin file, print the correct burn_key command to run, generate a bootloader digest, etc.

Re: ESP32 Secure Bootloader

Posted: Fri Oct 16, 2020 6:13 pm
by Munque
In "reflashable" mode, you keep a copy of the key which is in efuse so it's possible to generate new secure boot digests, in order to update the bootloader.
Under what circumstances do you 'generate new secure boot digests'?
Is that something you must do if you want to flash updated code to the esp32?

Re: ESP32 Secure Bootloader

Posted: Wed Oct 21, 2020 9:15 am
by ESP_Angus
Munque wrote:
Fri Oct 16, 2020 6:13 pm
In "reflashable" mode, you keep a copy of the key which is in efuse so it's possible to generate new secure boot digests, in order to update the bootloader.
Under what circumstances do you 'generate new secure boot digests'?
Is that something you must do if you want to flash updated code to the esp32?
With Secure Boot V1, it's necessary to generate a new secure boot digest from the bootloader in order to update the bootloader only. The app doesn't use a digest (it uses a digital signature) and signing can be done automatically via the build system. Usually in an ESP32 production system the bootloader is never updated, just the app.

With Secure Boot V2 both the bootloader and the app have a digital signature, and no "secure boot digest" is needed for anything.

Re: ESP32 Secure Bootloader

Posted: Sun Feb 28, 2021 6:00 pm
by kristaps_r
I am havin problems with extracting public key from Secure Boot V2 pem file.
Mys steps :
espsecure.py generate_signing_key --version 2 key.pem
espsecure.py extract_public_key --version 2 --keyfile key.pem key.bin

Code: Select all

espsecure.py v3.1-dev
Traceback (most recent call last):
  File "...\esp-idf\components\esptool_py\esptool\espsecure.py", line 828, in <module>
    _main()
  File "...\esp-idf\components\esptool_py\esptool\espsecure.py", line 821, in _main
    main()
  File "...\esp-idf\components\esptool_py\esptool\espsecure.py", line 816, in main
    operation_func(args)
  File "...\esp-idf\components\esptool_py\esptool\espsecure.py", line 458, in extract_public_key
    sk = _load_sbv2_rsa_signing_key(args.keyfile)
  File "...\esp-idf\components\esptool_py\esptool\espsecure.py", line 175, in _load_sbv2_rsa_signing_key
    sk = serialization.load_pem_private_key(keydata, password=None, backend=default_backend())
  File "...\.espressif\python_env\idf4.2_py3.8_env\lib\site-packages\cryptography\hazmat\primitives\serialization\base.py", line 20, in load_pem_private_key
    return backend.load_pem_private_key(data, password)
  File "...\.espressif\python_env\idf4.2_py3.8_env\lib\site-packages\cryptography\hazmat\backends\openssl\backend.py", line 1217, in load_pem_private_key
    return self._load_key(
  File "...\.espressif\python_env\idf4.2_py3.8_env\lib\site-packages\cryptography\hazmat\backends\openssl\backend.py", line 1416, in _load_key
    mem_bio = self._bytes_to_bio(data)
  File "...\.espressif\python_env\idf4.2_py3.8_env\lib\site-packages\cryptography\hazmat\backends\openssl\backend.py", line 636, in _bytes_to_bio
    data_ptr = self._ffi.from_buffer(data)
TypeError: a bytes-like object is required, not '_io.BufferedReader'
I get the key.pem file but can'get the bin file.
Can someone explain where could be the problem?

Re: ESP32 Secure Bootloader

Posted: Sat Apr 13, 2024 11:01 pm
by ChrisAlfred
I know this is late, but my guess is that you are starting with a public PEM rather than the required private PEM.