Secure Boot & Flash Encryption Using CLI only - Step By Step
Posted: Fri Oct 16, 2020 11:51 pm
Goals here
- Use only CLI command line to generate all necessary files for Secure Boot & Flash Encryption and save to a server before pushing to ESP-32.
- Do this in "reflashable" mode. We will save and secure the necessary files.
I've gotten this far (and am pretty certain this is not yet correct)
Questions
- Is the order correct? For instance, sign first then encrypt?
- I understand that when updating OTA the update is plain text, and it gets automatically encrypted after flashing, correct? Is the same true for the initial non-OTA version? Or does that need to be encrypted as it is below?
- If it's necessary to both sign & encrypt, do you sign and then encrypt, or encrypt and then sign? Below we're signing, then encrypting (and maybe we don't have to encrypt?)
1 Generate Signing Key
espsecure.py generate_signing_key ./secure_boot_signing_key.pem
2 Generate Flash Encryption Key
espsecure.py generate_flash_encryption_key ./flash_encryption_key.bin
3 Extract Public Key
espsecure.py extract_public_key --keyfile ./secure_boot_signing_key.pem ./public_verification_key.bin
4 Digest Private Key
espsecure.py digest_private_key --keyfile ./secure_boot_signing_key.pem --keylen 256 ./secure_boot_private_digest.pem
5 Digest Bootloader
espsecure.py digest_secure_bootloader -k ./secure_boot_private_digest.pem --output ./bootloader_digest.bin /path/to/bootloader_dout_80m.bin
6 Encrypt Bootloader
espsecure.py encrypt_flash_data --keyfile ./flash_encryption_key.bin --address 0x0 --output ./secure_bootloader_encrypted.bin ./bootloader_digest.bin
7 Encrypt Partition
espsecure.py sign_data --version 1 --keyfile ./secure_boot_signing_key.pem --output ./App-esp32.partitions_signed.bin ./App-esp32.partitions.bin
8 Encrypt Partition
espsecure.py encrypt_flash_data --keyfile ./flash_encryption_key.bin --address 0x8000 --output ./App-esp32.partitions_encrypted.bin ./App-esp32.partitions_signed.bin
9 Sign Binary
espsecure.py sign_data --version 1 --keyfile ./secure_boot_signing_key.pem --output ./App-esp32_signed.bin ./App-esp32.bin
10 Encrypt Binary
espsecure.py encrypt_flash_data --keyfile ./flash_encryption_key.bin --address 0x20000 --output ./App-esp32_encrypted.bin ./App-esp32_signed.bin
Next steps / Questions:
- Burn the digested bootloader to the efuse? Or a different item?
- That can be done only once per ESP32 (or 3 times total for some models?)
- Only start from 1 again when flashing a fresh ESP32, correct?
- Subsequent updates would require you to not start at from step 1 but from step 6, using the files generated from 1 - 5?
- Possibly skip steps 8 and 10 (Encryption) because that's handled on the ESP32? Sign but don't encrypt?
- Use only CLI command line to generate all necessary files for Secure Boot & Flash Encryption and save to a server before pushing to ESP-32.
- Do this in "reflashable" mode. We will save and secure the necessary files.
I've gotten this far (and am pretty certain this is not yet correct)
Questions
- Is the order correct? For instance, sign first then encrypt?
- I understand that when updating OTA the update is plain text, and it gets automatically encrypted after flashing, correct? Is the same true for the initial non-OTA version? Or does that need to be encrypted as it is below?
- If it's necessary to both sign & encrypt, do you sign and then encrypt, or encrypt and then sign? Below we're signing, then encrypting (and maybe we don't have to encrypt?)
1 Generate Signing Key
espsecure.py generate_signing_key ./secure_boot_signing_key.pem
2 Generate Flash Encryption Key
espsecure.py generate_flash_encryption_key ./flash_encryption_key.bin
3 Extract Public Key
espsecure.py extract_public_key --keyfile ./secure_boot_signing_key.pem ./public_verification_key.bin
4 Digest Private Key
espsecure.py digest_private_key --keyfile ./secure_boot_signing_key.pem --keylen 256 ./secure_boot_private_digest.pem
5 Digest Bootloader
espsecure.py digest_secure_bootloader -k ./secure_boot_private_digest.pem --output ./bootloader_digest.bin /path/to/bootloader_dout_80m.bin
6 Encrypt Bootloader
espsecure.py encrypt_flash_data --keyfile ./flash_encryption_key.bin --address 0x0 --output ./secure_bootloader_encrypted.bin ./bootloader_digest.bin
7 Encrypt Partition
espsecure.py sign_data --version 1 --keyfile ./secure_boot_signing_key.pem --output ./App-esp32.partitions_signed.bin ./App-esp32.partitions.bin
8 Encrypt Partition
espsecure.py encrypt_flash_data --keyfile ./flash_encryption_key.bin --address 0x8000 --output ./App-esp32.partitions_encrypted.bin ./App-esp32.partitions_signed.bin
9 Sign Binary
espsecure.py sign_data --version 1 --keyfile ./secure_boot_signing_key.pem --output ./App-esp32_signed.bin ./App-esp32.bin
10 Encrypt Binary
espsecure.py encrypt_flash_data --keyfile ./flash_encryption_key.bin --address 0x20000 --output ./App-esp32_encrypted.bin ./App-esp32_signed.bin
Next steps / Questions:
- Burn the digested bootloader to the efuse? Or a different item?
- That can be done only once per ESP32 (or 3 times total for some models?)
- Only start from 1 again when flashing a fresh ESP32, correct?
- Subsequent updates would require you to not start at from step 1 but from step 6, using the files generated from 1 - 5?
- Possibly skip steps 8 and 10 (Encryption) because that's handled on the ESP32? Sign but don't encrypt?