mirror of
https://github.com/sascha-hemi/pycom-documentation.git
synced 2026-03-21 05:06:35 +01:00
104 lines
5.0 KiB
Markdown
104 lines
5.0 KiB
Markdown
# SecureBoot and Encryption
|
|
|
|
## Summary
|
|
|
|
In order to encrypt your firmware, you will need to build it from source. Our firmware source code can be found [here](https://github.com/pycom/pycom-micropython-sigfox/), along with instructions on how to build it. Below you will find specific instructions on how generate keys, build and flash encrypted firmware.
|
|
|
|
1. Obtain keys \(for Secure Boot and Flash Encryption\)
|
|
2. Flash keys and parameters in `efuses`
|
|
3. Compile bootloader and application with `make SECURE=on`
|
|
4. Flash: bootloader-digest at address `0x0` and encrypted; all the others \(partitions and application\) encrypted, too.
|
|
|
|
## Prerequisites
|
|
|
|
Firstly you will need to setup the tool chain and download the source code. detailed instructions on how to achieve this can be found [here](https://github.com/pycom/pycom-micropython-sigfox/blob/master/README.md#the-esp32-version_). Once you have complete this, you will need to open a terminal in the `esp32` folder of the firmware source code repo.
|
|
|
|
Next you will need keys for Flash Encryption and Secure Boot; they can be generated randomly with the following commands:
|
|
|
|
```bash
|
|
python $IDF_PATH/components/esptool_py/esptool/espsecure.py generate_flash_encryption_key flash_encryption_key.bin
|
|
python $IDF_PATH/components/esptool_py/esptool/espsecure.py generate_signing_key secure_boot_signing_key.pem
|
|
```
|
|
|
|
The Secure Boot key `secure_boot_signing_key.pem` has to be transformed into `secure-bootloader-key.bin`, to be burnt into efuses. This can be done in 2 ways:
|
|
|
|
```bash
|
|
python $IDF_PATH/components/esptool_py/esptool/espsecure.py extract_public_key --keyfile secure_boot_signing_key.pem signature_verification_key.bin
|
|
```
|
|
|
|
or, as an artifact of the make build process, on the same directory level as Makefile
|
|
|
|
```bash
|
|
make BOARD=GPY SECURE=on TARGET=boot
|
|
```
|
|
|
|
To flash the keys \(`flash_encryption_key.bin` and `secure-bootloader-key.bin`\) into the efuses \(write and read protected\) run the following commands \(ignoring the lines that start with `#`\):
|
|
|
|
_**Note: Irreversible operations**_
|
|
|
|
```bash
|
|
# Burning Encryption Key
|
|
python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/ttyUSB0 burn_key flash_encryption flash_encryption_key.bin
|
|
# Burning Secure Boot Key
|
|
python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/ttyUSB0 burn_key secure_boot secure-bootloader-key.bin
|
|
# Enabling Flash Encryption mechanism
|
|
python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/ttyUSB0 burn_efuse FLASH_CRYPT_CNT
|
|
# Configuring Flash Encryption to use all address bits together with Encryption key (max value 0x0F)
|
|
python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/ttyUSB0 burn_efuse FLASH_CRYPT_CONFIG 0x0F
|
|
# Enabling Secure Boot mechanism
|
|
python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/ttyUSB0 burn_efuse ABS_DONE_0
|
|
```
|
|
|
|
**If the keys are not written in efuse, before flashing the bootloader, then random keys will be generated by the ESP32, they can never be read nor re-written, so bootloader can never be updated. Even more, the application can be re-flashed \(by USB\) just 3 more times.**
|
|
|
|
## Makefile options
|
|
|
|
```bash
|
|
make BOARD=GPY SECURE=on SECURE_KEY=secure_boot_signing_key.pem ENCRYPT_KEY=flash_encryption_key.bin TARGET=[boot|app]
|
|
```
|
|
|
|
* `SECURE=on` is the main flag; it's not optional
|
|
* if `SECURE=on` the following defaults are set:
|
|
* encryption is enable
|
|
* `secure_boot_signing_key.pem` is the secure boot key, located relatively to Makefile
|
|
* `flash_encryption_key.bin` is the flash encryption key, located relatively to Makefile
|
|
|
|
For flashing the bootloader digest and the encrypted versions of all binaries:
|
|
|
|
```bash
|
|
make BOARD=GPY SECURE=on flash
|
|
```
|
|
|
|
## Flashing
|
|
|
|
For flashing the `bootloader-reflash-digest.bin` has to be written at address 0x0, instead of the `bootloader.bin` \(at address `0x1000`\).
|
|
|
|
Build is done using `SECURE=on` option; additionally, all the binaries are pre-encrypted.
|
|
|
|
```bash
|
|
make BOARD=GPY clean
|
|
make BOARD=GPY SECURE=on TARGET=boot
|
|
make BOARD=GPY SECURE=on TARGET=app
|
|
make BOARD=GPY SECURE=on flash
|
|
```
|
|
|
|
Manual flash command:
|
|
|
|
```bash
|
|
python $IDF_PATH/components/esptool_py/esptool/esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before no_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0x0 build/GPY/release/bootloader/bootloader-reflash-digest.bin_enc 0x8000 build/GPY/release/lib/partitions.bin_enc 0x10000 build/GPY/release/gpy.bin_enc_0x10000
|
|
```
|
|
|
|
## OTA update
|
|
|
|
The OTA should be done using the pre-encrypted application image.
|
|
|
|
Because the encryption is done based on the physical flash address, there are 2 application binaries generated:
|
|
|
|
* `gpy.bin_enc_0x10000` which has to be written at default factory address: `0x10000`
|
|
* `gpy.bin_enc_0x1A0000` which has to be written at the `ota_0` partition address \(`0x1A0000`\)
|
|
|
|
{% hint style="info" %}
|
|
Hint: on MicroPython interface, the method `pycom.ota_slot()` responds with the address of the next OTA partition available \(either `0x10000` or `0x1A0000`\).
|
|
{% endhint %}
|
|
|