Skip to content

Commit 7cb51a4

Browse files
committed
new design/API: Updated documentation
1 parent 1f196bd commit 7cb51a4

11 files changed

Lines changed: 229 additions & 176 deletions

README.md

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,72 +2,78 @@
22
wolfSSL Secure Bootloader
33

44
wolfBoot is a portable, OS-agnostic, secure bootloader solution for 32-bit microcontrollers,
5-
relying on wolfCrypt for firmware authentication, providing firmware upgrade mechanisms.
5+
relying on wolfCrypt for firmware authentication, providing firmware update mechanisms.
66

77
Due to the minimalist design of the bootloader and the tiny HAL API, wolfBoot is completely independent
88
from any OS or bare-metal application, and can be easily ported and integrated in existing embedded software
9-
projects to provide a secure firmware upgrade mechanism.
9+
projects to provide a secure firmware update mechanism.
1010

1111

1212
## Features
1313
- Multi-slot partitioning of the flash device
1414
- Integrity verification of the firmware image(s)
1515
- Authenticity verification of the firmware image(s) using wolfCrypt's Digital Signature Algorithms (DSA)
1616
- Minimalist hardware abstraction layer (HAL) interface to facilitate portability across different vendors/MCUs
17+
- Copy/swap images from secondary slots into the primary slots to consent firmware update operations
1718
- In-place chain-loading of the firmware image in the primary slot
18-
- Copy/swap images from secondary slots into the primary slots to consent firmware upgrade operations
1919

2020
## Components
2121

2222
This repository contains the following components:
23-
- the bootloader
23+
- the wolfBoot bootloader
2424
- Ed25519 key generator and image signing tools
2525
- Baremetal test applications
2626

27-
### The bootloader
27+
### wolfBoot bootloader
2828

29-
The bootloader is a memory-safe standalone bare-metal application, designed to run on a generic 32bit MCU,
30-
with no dynamic memory allocation mechanism or linkage to any standard C library.
29+
woldBoot is a memory-safe standalone bare-metal application, designed to run on a generic microcontroller,
30+
with no dynamic memory allocation mechanism or linkage to any standard C library.
3131

32-
The core application depends on the following libraries:
32+
The bootloader consists of the following components:
3333
- wolfCrypt, which is used to verify the Ed25519 signature of the images
3434
- A minimalist Hardware Abstraction Layer, with an implementation provided for the supported target, which is in charge for IAP flash access and clock setting on the specific MCU
35-
- The core bootloader
36-
- A small application library to interact with the bootloader
35+
- The core bootloader
36+
- A small application library used by the application to interact with the bootloader [src/libwolfboot.c](src/libwolfboot.c)
3737

38-
The goal of this application is to perform image verification and/or requested firmware upgrade tasks
39-
before chain-loading the actual firmware from a specific location in flash.
40-
41-
Only ARM Cortex-M is supported at this stage. Support for more architectures and
42-
microcontrollers will be added later.
38+
Only ARM Cortex-M boot mechanism is supported at this stage. Support for more architectures and
39+
microcontrollers will be added later. Relocating the interrupt vector can be disabled if needed.
4340

4441
## Integrating wolfBoot in an existing project
4542

46-
Requirements:
43+
### Required steps
4744

4845
- Provide a HAL implementation for the target platform (see [Hardware Abstraction Layer](docs/HAL.md))
4946
- Decide a flash partition strategy and modify `include/target.h` accordingly (see [Flash partitions](docs/flash_partitions.md))
47+
- Change the entry point of the firmware image to account for bootloader presence
48+
- Equip the application with the [wolfBoot library](docs/API.md) to interact with the bootloader
49+
50+
### Examples provided
5051

5152
The following steps are automated in the default `Makefile` target, using the baremetal test
52-
application as an example to create the factory image:
53+
application as an example to create the factory image. By running `make`, the build system will:
5354

5455
- Create a Ed25519 Key-pair using the `ed25519_keygen` tool
5556
- Compile the bootloader. The public key generated in the step above is included in the build
56-
- Compile the firmware image
57+
- Compile the firmware image from the test application in [test\_app](test-app/)
5758
- Re-link the firmware to change the entry-point to the start address of the primary partition
5859
- Sign the firmware image using the `ed25519_sign` tool
5960
- Create a factory image by concatenating the bootloader and the firmware image
60-
- Flash the factory image to the target
61+
62+
The factory image can be flashed to the target device. It contains the bootloader and the signed initial
63+
firmware at the specified address on the flash.
64+
65+
The `ed25519_sign` tool transforms a bootable firmware image to comply with the firmware image format required by the bootloader.
6166

6267
For more detailed information about the firmware image format, see [Firmware image](docs/firmware_image.md)
6368

64-
## Upgrading the firmware
69+
### Upgrading the firmware
6570

6671
- Compile the new firmware image, and link it so that its entry point is at the start address of the primary partition
6772
- Sign the firmware using the `ed25519_sign` tool and the private key generated for the factory image
6873
- Transfer the image using a secure connection, and store it to the secondary firmware slot
69-
- Trigger the image swap using bootutil's `boot_set_pending()` function
74+
- Trigger the image swap using libwolfboot `wolfBoot_update()` function. See [wolfBoot library API](docs/API.md) for a description of the operation
7075
- Reboot to let the bootloader begin the image swap
76+
- Confirm the success of the update using libwolfboot `wolfBoot_success()` function. See [wolfBoot library API](docs/API.md) for a description of the operation
7177

72-
For more detailed information about firmware upgrade procedures, see [Firmware Upgrade](docs/firmware_upgrade.md)
78+
For more detailed information about firmware update implementation, see [Firmware Update](docs/firmware_update.md)
7379

docs/API.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Application interface for interactions with the bootloader
2+
3+
wolfBoot offers a small interface to interact with the images stored in the partition,
4+
explicitly initiate an update and confirm the success of a previously scheduled update.
5+
6+
## Compiling and linking with libwolfboot
7+
8+
An application that requires interactions with wolfBoot must include the header file:
9+
10+
`#include <wolfboot/wolfboot.h>`
11+
12+
Which exports the API function declarations, and the predefined values for the flags
13+
and the tags stored together with the firmware images in the two partitions.
14+
15+
For more information about flash partitions, flags and states see [Flash partitions](flash_partitions.md).
16+
17+
## API
18+
19+
libwolfboot provides low-level access interface to flash partition states. The state
20+
of each partition can be retrieved and altered by the application.
21+
22+
Basic interaction from the application is provided via the two high-level function calls:
23+
24+
`void wolfBoot_update(void)`
25+
26+
and
27+
28+
`void wolfBoot_success(void)`
29+
30+
### Trigger an update
31+
32+
- `wolfBoot_update()` is used to trigger an update upon the next reboot, and it is normally used by
33+
an update application that has retrieved a new version of the running firmware, and has
34+
stored it in the UPDATE partition on the flash. This function will set the state of the UPDATE partition
35+
to `ST_UPDATE`, instructing the bootloader to perform the update upon the next execution (after reboot).
36+
37+
wolfBoot update process consist in swapping the content of the UPDATE and the BOOT partitions, using a temporary
38+
single-block SWAP space.
39+
40+
- `wolfBoot_success()` indicates a successful boot of a new firmware. This can be called by the application
41+
at any time, but it will only be effective to mark the current firmware (in the BOOT partition) with the state
42+
`ST_SUCCESS`, indicating that no roll-back is required. An application should typically call `wolfBoot_success()`
43+
only after verifying that the basic system features are up and running, including the possibility to retrieve
44+
a new firmware for the next upgrade.
45+
46+
If after an upgrade wolfBoot detects that the active firmware is still in `ST_TESTING` state, it means that
47+
a successful boot has not been confirmed for the application, and will attempt to revert the update by swapping
48+
the two images again.
49+
50+
For more information about the update process, see [Firmware Update](firmware_update.md)
51+
52+

docs/HAL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ ensuring that the MCU is running at full speed during boot, to optimize the
99
verification of the signatures.
1010

1111
The implementation of the hardware-specific calls for each platform are grouped in
12-
a single c file in the [hal](hal) directory.
12+
a single c file in the [hal](../hal) directory.
1313

1414
The directory also contains a platform-specific linker script for each supported MCU,
1515
with the same name and the `.ld` extension. This is used to link the bootloader's

docs/firmware_image.md

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ WolfBoot can only chain-load and execute firmware images from a specific entry p
66
which must be specified as the origin of the FLASH memory in the linker script of the embedded
77
application. This correspond to the first partition in the flash memory.
88

9-
Multiple firmware images can be created this way, and stored in different partitions. The bootloader
10-
will take care of moving the selected firmware to the first boot partition before chain-loading the image.
9+
Multiple firmware images can be created this way, and stored in two different partitions. The bootloader
10+
will take care of moving the selected firmware to the first (BOOT) partition before chain-loading the image.
1111

1212
Due to the presence of an image header, the entry point of the application has a fixed additional offset
1313
of 256B from the beginning of the flash partition.
@@ -24,24 +24,48 @@ chain-loading the firmware the interrupt continue to work properly after the boo
2424

2525
*The image header is stored at the beginning of the slot and the actual firmware image starts 256 Bytes after it*
2626

27+
### Image header: Tags
2728

28-
## Firmware trailer
29+
The **image header** is prepended with a single 4-byte magic number, followed by a 4-byte field indicating the
30+
firmware image (excluding the header). All numbers in the header are stored in Little-endian format.
2931

30-
At the end of the actual firmware image, the signing tool stores three trailer "TLV" (type-length-value) records,
31-
respectively containing:
32-
- A hash digest of the firmware, including its firmware header, obtained using SHA-256
33-
- A hash digest of the public key that can be used by the bootloader to verify the authenticity of the firmware. The key must already be stored with the bootloader, and this field is only used as sanity check.
34-
- The signature obtained by signing the hash digest of the firmware with the factory private key
32+
The two fixed fields are followed by one or more tags. Each TAG is structured as follows:
3533

36-
These three fields are required by the bootloader to verify the integrity and the origin of the firmware image.
34+
- 1 Byte indicating the **Type**
35+
- 1 Byte indicating the **size** of the tag, excluding the type and size bytes
36+
- ***N*** bytes of tag content
3737

38-
![Image trailers](png/image_tlv.png)
38+
With the following two exception:
39+
- A '0' in the Type field indicate the end of the Tag. The rest of the header carries no more Tags. The 'end of tags' type has no **size** field.
40+
- A '0xFF' in the Type field indicate a simple padding byte. The 'padding' byte has no **size** field, and the next byte should be processed as **Type** again.
3941

40-
*The trailer of a signed firmware contains a TLV header and three TLV records that are used by the bootloader to verify the image*
42+
Each **Type** has a different meaning, and integrate information about the firmware. The following Tags are mandatory for validating the firmware image:
43+
44+
- A 'version' Tag (type: 0x01, size: 4 Bytes) indicating the version number for the firmware stored in the image
45+
- A 'timestamp' Tag (type: 0x02, size 8 Bytes) indicating the timestamp in unix seconds for the creation of the firmware
46+
- A 'sha256 digest' Tag (type: 0x03, size: 32 Bytes) used for integrity check of the firmware
47+
- A 'firmware signature' Tag (type: 0x20, size: 64 Bytes) used to validate the signature stored with the firmware against a known public key
48+
49+
Optionally, a 'public key hint digest' Tag can be transmitted in the header (type: 0x10, size:32 Bytes). This Tag contains the SHA256 digest of the public key used
50+
by the signing tool. The bootloader may use this field to locate the correct public key in case of multiple keys available.
51+
52+
wolfBoot will, in all cases, refuse to boot an image that cannot be verified and authenticated using the built-in digital signature authentication mechanism.
53+
54+
55+
### Image signing tool
56+
57+
The image signing tool generates the header with all the required Tags for the compiled image, and add them to the output file that can be then
58+
stored on the primary slot on the device, or transmitted later to the device through a secure channel to initiate an update.
59+
60+
### Storing firmware image
61+
62+
Firmware images are stored with their full header at the beginning of any of the partitions on the system.
63+
wolfBoot can only boot images from the BOOT partition, while keeping a second firmware image in the UPDATE partition.
64+
65+
In order to boot a different image, wolfBoot will have to swap the content of the two images.
66+
67+
For more information on how firmware images are stored and managed within the two partitions, see [Flash partitions](flash_partitions.md)
4168

42-
## Image signing tool
4369

44-
The image signing tool generates the header and trailers for the compiled image, and add them to the output file that can be then
45-
stored on the primary slot on the device.
4670

4771

docs/firmware_update.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Firmware update
2+
3+
This section documents the complete firmware update procedure, enabling secure boot
4+
for an existing embedded application.
5+
6+
The steps to follow to complete a firmware update with wolfBoot are:
7+
- Compile the firmware with the correct entry point
8+
- Sign the firmware
9+
- Transfer the image using a secure connection, and store it to the secondary firmware slot
10+
- Trigger the image swap
11+
- Reboot to let the bootloader begin the image swap
12+
13+
At any given time, an application or OS running on a wolfBoot system can receive an updated version of itself,
14+
and store the updated image in the second partition in the FLASH memory.
15+
16+
Applications or OS threads can be linked to the [libwolfboot library](API.md), which exports the API to trigger
17+
the update at the next reboot, and some helper functions to access the flash partition for
18+
erase/write through the target specific [HAL](HAL.md).
19+
20+
## Update procedure description
21+
22+
Using the [API](API.md) provided to the application, wolfBoot offers the possibility to initiate, confirm or
23+
rollback an update.
24+
25+
After storing the new firmware image in the UPDATE partition, the application should initiate the update by calling
26+
`wolfBoot_update()`. By doing so, the UPDATE partition is marked for update. Upon the next reboot, wolfBoot will:
27+
- Validate the new firmware image stored in the UPDATE partition
28+
- Verify the signature attached against a known public key stored in the bootloader image
29+
- Swap the content of the BOOT and the UPDATE partitions
30+
- Mark the new firmware in the BOOT partition as in state `ST_TESTING`
31+
- Boot into the newly received firmware
32+
33+
### Successful boot
34+
35+
Upon a successful boot, the application should inform the bootloader by calling `wolfBoot_success()`, after verifying that
36+
the system is up and running again. This operation confirms the update to a new firmware.
37+
38+
Failing to set the BOOT partition to `ST_SUCCESS` before the next reboot triggers a roll-back operation.
39+
Roll-back is initiated by the bootloader by triggering a new update, this time starting from the backup copy of the original
40+
(pre-update) firmware, which is now stored in the UPDATE partition due to the swap occurring earlier.
41+
42+
43+
### Building a new firmware image
44+
45+
Firmware images are position-dependent, and can only boot from the origin of the **BOOT** partition in FLASH.
46+
This design constraint implies that the chosen firmware is always stored in the **BOOT** partition, and wolfBoot
47+
is responsible for pre-validating an update image and copy it to the correct address.
48+
49+
All the firmware images must therefore have their entry point set to the address corresponding to the beginning
50+
of the **BOOT** partition, plus an offset of 256 Bytes to account for the image header.
51+
52+
Once the firmware is compiled and linked, it must be signed using the `ed25519_sign` tool. The tool produces
53+
a signed image that can be transferred to the target using a secure connection, using the same key corresponding
54+
to the public key currently used for verification.
55+
56+
The tool also adds all the required Tags to the image header, containing the signatures and the SHA256 hash of
57+
the firmware.
58+

0 commit comments

Comments
 (0)