mirror of https://github.com/wolfSSL/wolfBoot.git
192 lines
8.6 KiB
Markdown
192 lines
8.6 KiB
Markdown
# Using One-Time Programmable (OTP) flash area for keystore
|
||
|
||
Some microcontrollers provide a special area in flash memory that can
|
||
only be written once and cannot be erased.
|
||
|
||
This feature comes particularly handy when you want to store the public keys required
|
||
to authenticate the firmware update images, which has exactly the same requirements. A public
|
||
key is a cryptographic key that can be freely distributed and is used to verify the signature
|
||
of the firmware update image. By storing the public keys in the OTP area, you can ensure that
|
||
they are immutable and cannot be tampered with.
|
||
|
||
## Compiling wolfBoot to access OTP as keystore
|
||
|
||
To use the OTP area as a keystore, you need to compile wolfBoot with the `FLASH_OTP_KEYSTORE`
|
||
option enabled. This option is disabled by default, which means that the keystore is incorporated into
|
||
the wolfBoot binary itself.
|
||
|
||
When wolfBoot uses the OTP area as a keystore, it reads the public keys from the OTP area at runtime.
|
||
The public keys are stored in the OTP area, after an initial 16-byte header that contains the number of
|
||
keys stored, the size of each key, and other information.
|
||
|
||
In order for wolfBoot to start authenticating the firmware images at boot and upon update, the public keys
|
||
must be provisioned to the OTP area in a separate step, as described in the next sections.
|
||
|
||
Depending on the target device, you can either prepare a binary image of the OTP area content, or use `otp-keystore-primer` firmware to directly provision the keys on the target.
|
||
|
||
## Creating an image of the OTP area content
|
||
|
||
It is possible to create a binary image of the content for the OTP area. The resulting file (otp.bin) can be manually provisioned using any external tool that allows writing to the target OTP area.
|
||
|
||
To compile the otp-keystore-gen tool using the current keystore content:
|
||
|
||
```sh
|
||
make otpgen
|
||
```
|
||
|
||
And then, to create the image file `otp.bin`:
|
||
|
||
|
||
```sh
|
||
./tools/keytools/otp/otp-keystore-gen
|
||
```
|
||
|
||
|
||
## Directly provisioning the public keys to the OTP area (primer)
|
||
|
||
After enabling the `FLASH_OTP_KEYSTORE` option in your `.config` file, when you compile wolfBoot by running "make",
|
||
an additional application called `otp-keystore-primer` is generated under `tools/keytools/otp`. This application is used to
|
||
provision the public keys to the OTP area. By flashing this application to the microcontroller, the public keys contained
|
||
in your keystore (previously generated by `keygen`) are written to the OTP area.
|
||
|
||
The `otp-keystore-primer` application is generated with the public keys embedded in it. The keys are retrieved from the `keystore.c` file,
|
||
generated by the `keygen` command. The `otp-keystore-primer` application reads the public keys from the `keystore.c` file and writes them to the OTP area.
|
||
|
||
After generating a new `keystore.c` with the `keygen` application, you can generate the `otp-keystore-primer` application again, by running `make otp`.
|
||
|
||
> [!WARNING]
|
||
> The `otp-keystore-primer` application is a one-time use application. Once the application runs on your target, the public keys are written to the OTP area,
|
||
> and it will be impossible to erase them. Therefore, it is important to ensure that the public keys are correct before provisioning them to the OTP area,
|
||
> and that the associated private keys are stored securely. Accidentally losing the private keys will render the public keys stored in the OTP area useless.
|
||
|
||
> [!CAUTION]
|
||
> ** Be very careful when using the `otp-keystore-primer` application. Use it at your own risk. **
|
||
|
||
|
||
## Examples
|
||
|
||
### STM32H5 OTP KeyStore
|
||
|
||
Example for NULCLEO-STM32H563ZI with TrustZone (via PKCS11), DualBank and signing with PQ LMS:
|
||
|
||
1) Setup the configuration and key tools:
|
||
|
||
```sh
|
||
cp config/examples/stm32h5-tz-dualbank-otp-lms.config .config
|
||
make include/target.h
|
||
make keytools
|
||
```
|
||
|
||
2) Generate key(s) to write to OTP
|
||
|
||
- `./examples/keytools/keygen --lms -g 1.key -g 2.key -g 3.key -g 4.key -g 5.key`
|
||
|
||
3) Backup the generated keys and `src/keystore.c`
|
||
- Save to safe place outside of the wolfBoot tree
|
||
|
||
4) Set the signing key to use
|
||
|
||
- Copy one of the generated keys to `wolfboot_signing_private_key.der`
|
||
- `cp 1.key wolfboot_signing_private_key.der`
|
||
|
||
5) Setup the OTP keystore
|
||
|
||
Flash the OTP keystore primer:
|
||
- Run `make otp`
|
||
- Flash `./tools/keytools/otp/otp-keystore-primer.bin` to `0x08000000`
|
||
- Disconnect the tool and hit reset button
|
||
- The primer will run and flash keystore.c to OTP and enable write protection on those blocks
|
||
|
||
OR
|
||
|
||
Generate OTP (otp.bin) and flash using external tool
|
||
- Run `make otpgen`
|
||
- Run `./tools/keytools/otp/otp-keystore-gen` to generate an otp.bin file
|
||
- Program otp.bin to `0x08FFF000` using external tool like STM32CubeProgrammer
|
||
|
||
6) Verify OTP keystore
|
||
- Read memory at address `0x08FFF000` (should start with ASCII "WOLFBOOT")
|
||
- Typically use STM32CubeProgrammer for this
|
||
|
||
7) Setup the option bytes
|
||
- User Configuration 2 -> TrustZone Enable (TZEN=0xB4)
|
||
- Bank1 - Flash Watermark area (SECWM1_START=0x00, SECWM1_END=0x1F)
|
||
- Bank2 - Flash Watermark area (SECWM2_START=0x00, SECWM2_END=0x1F)
|
||
|
||
8) Mass erase the device
|
||
- STM32CubeProgrammer -> Full chip erase
|
||
|
||
9) Build wolfBoot and test application using `make`
|
||
|
||
10) Flash wolfBoot and test-app
|
||
|
||
- Flash `wolfboot.bin` at `0x0C000000`
|
||
- Flash `test-app/image_v1_signed.bin` at `0x08040000`
|
||
|
||
11) Disconnect and reboot, the red LED should turn on.
|
||
|
||
12) Connect to USB UART on NUCLEO board for console
|
||
|
||
Explore the command line (run help)
|
||
|
||
```sh
|
||
========================
|
||
STM32H5 wolfBoot demo Application
|
||
Copyright 2024 wolfSSL Inc
|
||
GPL v3
|
||
Version : 0x1
|
||
========================
|
||
|
||
cmd> help
|
||
help : shows this help message
|
||
info : display information about the system and partitions
|
||
success : confirm a successful update
|
||
pkcs11 : enable and test crypto calls with PKCS11 in secure mode
|
||
random : generate a random number
|
||
timestamp : print the current timestamp
|
||
benchmark : run the wolfCrypt benchmark
|
||
test : run the wolfCrypt test
|
||
update : update the firmware via XMODEM
|
||
reboot : reboot the system
|
||
```
|
||
|
||
13) Test Update
|
||
|
||
- Sign a new version of the firmware: `./tools/keytools/sign --lms test-app/image.bin wolfboot_signing_private_key.der 2`
|
||
- Run "update" command on the shell and wait for xmodem transfer
|
||
- Use serial terminal that supports xmodem like "minicom" or "CoolTerm".
|
||
* Run `minicom` on `/dev/ttyACM0` and start file transfer using "CTRL+A; S"
|
||
* Select xmodem then navigate to the new signed firmware file `test-app/image_v2_signed.bin`
|
||
- During the transfer, the yellow LED will flash.
|
||
- The green LED is dim because it's sync with the UART RX
|
||
- At the end of the transfer, the new image will be in the update partition.
|
||
- Reset board to install new firmware and confirm new version number.
|
||
|
||
Example update output:
|
||
|
||
```sh
|
||
cmd> update
|
||
Erasing update partition...Done.
|
||
Waiting for XMODEM transfer...
|
||
.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
||
|
||
|
||
|
||
|
||
End of transfer. ret: 0
|
||
New firmware version: 0x2
|
||
Triggering update...
|
||
Update completed successfully.
|
||
|
||
cmd> reboot
|
||
|
||
========================
|
||
STM32H5 wolfBoot demo Application
|
||
Copyright 2024 wolfSSL Inc
|
||
GPL v3
|
||
Version : 0x2
|
||
========================
|
||
|
||
cmd>
|
||
```
|