Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync with wolfboot/docs #158

Merged
merged 3 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions wolfBoot/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@ SOURCES = chapter01.md \
chapter06.md \
chapter07.md \
chapter08.md
APPENDIX= appendix01.md \
appendix02.md \
appendix03.md \
appendix04.md \
appendix05.md \
appendix06.md \
appendix07.md \
appendix08.md \
appendix09.md \
appendix10.md \
appendix11.md \
appendix12.md \
appendix13.md

ifeq ($(DOC_LANG),JA)
PDF = wolfBoot-Manual-jp.pdf
Expand Down
15 changes: 14 additions & 1 deletion wolfBoot/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ site_name: wolfBoot Manual
site_url: https://wolfssl.com/
docs_dir: build/html/
site_dir: html/
copyright: wolfSSL Inc. 2021
copyright: wolfSSL Inc. 2024
nav:
- "1. Introduction": index.md
- "2. Compiling wolfBoot": chapter02.md
Expand All @@ -12,6 +12,19 @@ nav:
- "6. wolfBoot Features": chapter06.md
- "7. Integrating wolfBoot in an existing project": chapter07.md
- "8. Troubleshooting": chapter08.md
- "A. ATA Security": appendix01.md
- "B. Signing firmware using Microsoft Azure Key Vault": appendix02.md
- "C. Using One-Time Programmable (OTP) flash area for keystore": appendix03.md
- "D. KeyStore structure: support for multiple public keys": appendix04.md
- "E. Build wolfBoot as Library": appendix05.md
- "F. wolfBoot Loaders / Updaters": appendix06.md
- "G. Measured Boot using wolfBoot": appendix07.md
- "H. Post-Quantum Signatures": appendix08.md
- "I. Remote External flash memory support via UART": appendix09.md
- "J. Renesas wolfBoot": appendix10.md
- "K. wolfBoot Key Tools": appendix11.md
- "L. wolfCrypt in TrustZone-M secure domain": appendix12.md
- "M. wolfBoot TPM support": appendix13.md
theme:
name: null
custom_dir: ../mkdocs-material/material
Expand Down
44 changes: 44 additions & 0 deletions wolfBoot/src/appendix01.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# ATA Security

## Introduction
This document provides an overview of how wolfBoot can leaverage the ATA security features to lock or unlock ATA drive.
The ATA drive may be locked either by using a hardcoded password or by using a secret that is sealed in the TPM.

## Table of Contents
- [ATA Security](#ata-security)
- [Introduction](#introduction)
- [Table of Contents](#table-of-contents)
- [Unlocking the Disk with a Hardcoded Password](#unlocking-the-disk-with-a-hardcoded-password)
- [Unlocking the Disk with a TPM-Sealed Secret](#unlocking-the-disk-with-a-tpm-sealed-secret)
- [Disabling the password](#disabling-the-password)

## Unlocking the Disk with a Hardcoded Password
To unlock the disk using a hardcoded password, use the following options in your .config file:
```
DISK_LOCK=1
DISK_LOCK_PASSWORD=hardcoded_password
```
If the ATA disk has no password set, the disk will be locked with the password provided at the first boot.

## Unlocking the Disk with a TPM-Sealed Secret
wolfBoot allows to seal secret safely in the TPM in a way that it can be unsealed only under specific conditions. Please refer to [Appendix M](appendix13.md) and [Appendix G](appendix07.md)for more information.
If the options `WOLFBOOT_TPM_SEAL` and `DISK_LOCK` are enabled, wolfBoot will use a TPM sealed secret as the password to unlock the disk. The following options controls the sealing and unsealing of the secret:

| Option | Description |
|-----------|----------|
| WOLFBOOT_TPM_SEAL_KEY_ID| The key ID to use for sign the policy |
| ATA_UNLOCK_DISK_KEY_NV_INDEX | The NV index to store the sealed secret. |
| WOLFBOOT_DEBUG_REMOVE_SEALED_ON_ERROR| In case of error, delete the secret and panic() |

In case there are no secret sealed at `ATA_UNLOCK_DISK_KEY_NV_INDEX`, a new random secret will be created and sealed at that index.
In case the ATA drive is not locked, it will be locked at the first boot with the secret sealed in the TPM.

## Disabling the password

If you need to disable the password, a master password should be already set on the device. Then you can use the following options to compile wolfBoot so that it will disable the password from the drive and panic:

```
WOLFBOOT_ATA_DISABLE_USER_PASSWORD=1
ATA_MASTER_PASSWORD=the_master_password
```

109 changes: 109 additions & 0 deletions wolfBoot/src/appendix02.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Signing firmware using Microsoft Azure Key Vault

Microsoft offers secure key management and provisioning tools, using keys stored
in HSMs. This mechanisms helps to centralize key management for several purposes,
including the support for signing payloads using the managed keys, which can be
used in combination with wolfBoot for provisioning public keys in a fleet of
devices.


## Preparing the keystore

wolfBoot can import public keys in the keystore using the `keygen` command line
tool provided. `keygen` supports both raw ECC keys and ASN.1 format (.der).

Azure allows to download the public keys in ASN.1 format to provision the device.
To retrieve each public key to use for firmware authentication in wolfBoot, use:

```sh
az keyvault key download --vault-name <vault-name> -n test-signing-key-1 -e DER -f public-key-1.der
```

A keystore can now be created importing the public keys and with `keygen`'s `-i`
(import) option. The option may be repeated multiple times to add more keys to
the keystore.

```sh
./tools/keytools/keygen --ecc256 -i public-key-1.der [-i public-key-2.der ...]
```

## Signing the firmware image for wolfBoot

The signing operation using any external HSM is performed through three-steps,
as described in the relevant section in [Appendix B](appendix02.md).
In this section we describe the procedure to sign the firmware image using Azure key vault.


### Obtaining the SHA256 digest

Step 1 consists in calling the `./sign` tool with the extra `--sha-only` argument,
to generate the digest to sign. The public key associated to the selected signing
key in the vault needs to be provided:

```sh
./tools/keytools/sign --ecc256 --sha-only --sha256 test-app/image.bin public-key-1.der 1
```

To fit in a https REST request, the digest obtained must be encoded using base64:

```sh
DIGEST=$(cat test-app/image_v1_digest.bin | base64url_encode)
```

The variable `DIGEST` now contains a printable encoding of the key, which can be
attached to the request.

### HTTPS request for signing the digest with the Key Vault


To prepare the request, first get an access token from the vault and store it in a variable:

```sh
ACCESS_TOKEN=$(az account get-access-token --resource "https://vault.azure.net" --query "accessToken" -o tsv)
```

Use the URL associated to the selected key vault:

```sh
KEY_IDENTIFIER="https://<vault-name>.vault.azure.net/keys/test-signing-key"
```

Perform the request using cURL, and store the result in a variable:

```sh
SIGNING_RESULT=$(curl -X POST \
-s "${KEY_IDENTIFIER}/sign?api-version=7.4" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type:application/json" \
-H "Accept:application/json" \
-d "{\"alg\":\"ES256\",\"value\":\"${DIGEST}\"}")
echo $SIGNING_RESULT
```

The field `.value` in the result contains the (base64 encoded) signature.
To extract the signature from the response, you can use a JSON parser:

```sh
SIGNATURE=$(jq -jn "$SIGNING_RESULT|.value")
```

The signature can now be decoded from base64 into a binary, so the
`sign` tool can incorporate the signature into the manifest header.

```sh
echo $SIGNATURE| base64url_decode > test-app/image_v1_digest.sig
```

### Final step: create the signed firmware image

The 'third step' in the HSM three-steps procedure requires the `--manual-sign` option and the
signature obtained through the Azure REST API.


```
./tools/keytools/sign --ecc256 --sha256 --manual-sign test-app/image.bin test-signin-key_pub.der 1 test-app/image_v1_digest.sig
```

The resulting binary file `image_v1_signed.bin` will now contain a signed firmware
image that can be authenticated and staged by wolfBoot.

191 changes: 191 additions & 0 deletions wolfBoot/src/appendix03.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# 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>
```
Loading
Loading