Skip to content

Commit 678c214

Browse files
authored
Merge pull request #1 from wolfSSL/clean
Refactoring update mechanism
2 parents 281b460 + c521d5c commit 678c214

37 files changed

+906
-3624
lines changed

Makefile

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,12 @@ LSCRIPT:=hal/$(TARGET).ld
1717

1818
OBJS:= \
1919
./hal/$(TARGET).o \
20-
./lib/bootutil/src/loader.o \
21-
./lib/bootutil/src/image_validate.o \
22-
./lib/bootutil/src/bootutil_misc.o \
20+
./src/loader.o \
2321
./src/mem.o \
24-
./src/keys.o \
2522
./src/crypto.o \
2623
./src/wolfboot.o \
27-
./src/main.o \
24+
./src/image.o \
25+
./src/libwolfboot.o \
2826
./lib/wolfssl/wolfcrypt/src/sha256.o \
2927
./lib/wolfssl/wolfcrypt/src/hash.o \
3028
./lib/wolfssl/wolfcrypt/src/wolfmath.o \
@@ -41,12 +39,12 @@ ifeq ($(SIGN),ED25519)
4139
./lib/wolfssl/wolfcrypt/src/ed25519.o \
4240
./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \
4341
./src/ed25519_pub_key.o
44-
CFLAGS+=-DBOOT_SIGN_ED25519
42+
CFLAGS+=-DWOLFBOOT_SIGN_ED25519
4543
endif
4644

4745
ifeq ($(SIGN),EC256)
4846
OBJS+= ./ext/wolfssl/wolfcrypt/src/ecc.o
49-
CFLAGS+=-DBOOT_SIGN_EC256
47+
CFLAGS+=-DWOLFBOOT_SIGN_EC256
5048
endif
5149

5250
ifeq ($(DEBUG),1)
@@ -59,11 +57,6 @@ ifeq ($(VTOR),0)
5957
CFLAGS+=-DNO_VTOR
6058
endif
6159

62-
ifeq ($(SWAP),0)
63-
CFLAGS+=-DWOLFBOOT_OVERWRITE_ONLY
64-
endif
65-
66-
6760
LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=wolfboot.map -ffreestanding -nostartfiles -mcpu=cortex-m3 -mthumb -nostdlib
6861

6962
all: factory.bin
@@ -91,7 +84,6 @@ tools/ed25519/ed25519_sign:
9184
ed25519.der: tools/ed25519/ed25519_sign
9285
tools/ed25519/ed25519_keygen src/ed25519_pub_key.c
9386

94-
9587
factory.bin: $(BOOT_IMG) wolfboot-align.bin tools/ed25519/ed25519_sign ed25519.der
9688
tools/ed25519/ed25519_sign $(BOOT_IMG) ed25519.der 1
9789
cat wolfboot-align.bin $(BOOT_IMG).v1.signed > $@

NOTICE

Lines changed: 0 additions & 22 deletions
This file was deleted.

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, and a modified version of
6-
[mcuboot](https://www.mcuboot.com/)'s *bootutil* library to implement firmware upgrade mechanisms.
5+
relying on wolfCrypt for firmware authentication, providing firmware update mechanisms.
76

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

1211

1312
## Features
1413
- Multi-slot partitioning of the flash device
1514
- Integrity verification of the firmware image(s)
1615
- Authenticity verification of the firmware image(s) using wolfCrypt's Digital Signature Algorithms (DSA)
1716
- 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
1818
- In-place chain-loading of the firmware image in the primary slot
19-
- Copy/swap images from secondary slots into the primary slots to consent firmware upgrade operations
2019

2120
## Components
2221

2322
This repository contains the following components:
24-
- the bootloader
23+
- the wolfBoot bootloader
2524
- Ed25519 key generator and image signing tools
2625
- Baremetal test applications
2726

28-
### The bootloader
27+
### wolfBoot bootloader
2928

30-
The bootloader is a memory-safe standalone bare-metal application, designed to run on a generic 32bit MCU,
31-
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.
3231

33-
The core application depends on the following libraries:
32+
The bootloader consists of the following components:
3433
- wolfCrypt, which is used to verify the Ed25519 signature of the images
35-
- A modified version of mcuboot's bootutil, to handle the firmware image slots and the upgrade state-machine
3634
- 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 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: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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 `STATE_UPDATING`, 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+
### Confirm current image
41+
42+
- `wolfBoot_success()` indicates a successful boot of a new firmware. This can be called by the application
43+
at any time, but it will only be effective to mark the current firmware (in the BOOT partition) with the state
44+
`STATE_SUCCESS`, indicating that no roll-back is required. An application should typically call `wolfBoot_success()`
45+
only after verifying that the basic system features are up and running, including the possibility to retrieve
46+
a new firmware for the next upgrade.
47+
48+
If after an upgrade wolfBoot detects that the active firmware is still in `STATE_TESTING` state, it means that
49+
a successful boot has not been confirmed for the application, and will attempt to revert the update by swapping
50+
the two images again.
51+
52+
For more information about the update process, see [Firmware Update](firmware_update.md)
53+
54+
For the image format, see [Firmware Image](firmware_image.md)
55+
56+

docs/HAL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ In order to run wolfBoot on a target microcontroller, an implementation of the H
44
must be provided.
55

66
The HAL only purposes are allowing write/erase operations from the bootloader
7-
and the application initiating the firmware upgrade through the bootutil library, and
7+
and the application initiating the firmware upgrade through the application library, and
88
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: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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+
![Update and Rollback](png/wolfboot_update_rollback.png)
17+
18+
Applications or OS threads can be linked to the [libwolfboot library](API.md), which exports the API to trigger
19+
the update at the next reboot, and some helper functions to access the flash partition for
20+
erase/write through the target specific [HAL](HAL.md).
21+
22+
## Update procedure description
23+
24+
Using the [API](API.md) provided to the application, wolfBoot offers the possibility to initiate, confirm or
25+
rollback an update.
26+
27+
After storing the new firmware image in the UPDATE partition, the application should initiate the update by calling
28+
`wolfBoot_update()`. By doing so, the UPDATE partition is marked for update. Upon the next reboot, wolfBoot will:
29+
- Validate the new firmware image stored in the UPDATE partition
30+
- Verify the signature attached against a known public key stored in the bootloader image
31+
- Swap the content of the BOOT and the UPDATE partitions
32+
- Mark the new firmware in the BOOT partition as in state `STATE_TESTING`
33+
- Boot into the newly received firmware
34+
35+
### Successful boot
36+
37+
Upon a successful boot, the application should inform the bootloader by calling `wolfBoot_success()`, after verifying that
38+
the system is up and running again. This operation confirms the update to a new firmware.
39+
40+
Failing to set the BOOT partition to `STATE_SUCCESS` before the next reboot triggers a roll-back operation.
41+
Roll-back is initiated by the bootloader by triggering a new update, this time starting from the backup copy of the original
42+
(pre-update) firmware, which is now stored in the UPDATE partition due to the swap occurring earlier.
43+
44+
45+
### Building a new firmware image
46+
47+
Firmware images are position-dependent, and can only boot from the origin of the **BOOT** partition in FLASH.
48+
This design constraint implies that the chosen firmware is always stored in the **BOOT** partition, and wolfBoot
49+
is responsible for pre-validating an update image and copy it to the correct address.
50+
51+
All the firmware images must therefore have their entry point set to the address corresponding to the beginning
52+
of the **BOOT** partition, plus an offset of 256 Bytes to account for the image header.
53+
54+
Once the firmware is compiled and linked, it must be signed using the `ed25519_sign` tool. The tool produces
55+
a signed image that can be transferred to the target using a secure connection, using the same key corresponding
56+
to the public key currently used for verification.
57+
58+
The tool also adds all the required Tags to the image header, containing the signatures and the SHA256 hash of
59+
the firmware.
60+

0 commit comments

Comments
 (0)