Infineon: Switch to 1.9.0 code base, add xmc7000 family support, refactor memory layer
diff --git a/docs/CNAME b/docs/CNAME
new file mode 100644
index 0000000..64ca4fe
--- /dev/null
+++ b/docs/CNAME
@@ -0,0 +1 @@
+docs.mcuboot.com
\ No newline at end of file
diff --git a/docs/PORTING.md b/docs/PORTING.md
index 2df9b49..4804096 100644
--- a/docs/PORTING.md
+++ b/docs/PORTING.md
@@ -1,20 +1,20 @@
-# Porting How-To
+# Porting how-to
This document describes the requirements and necessary steps required to port
-`mcuboot` to a new target `OS`.
+`MCUboot` to a new target `OS`.
# Requirements
-* `mcuboot` requires a configuration file, which can be included as
+* `MCUboot` requires a configuration file, which can be included as
mcuboot_config/mcuboot_config.h, which configures various options
(that begin with MCUBOOT_).
-* `mcuboot` requires that the target provides a `flash` API with ability to
+* `MCUboot` requires that the target provides a `flash` API with ability to
get the flash's minimum write size, and read/write/erase individual sectors.
-* `mcuboot` doesn't bundle a cryptographic library, which means the target
+* `MCUboot` doesn't bundle a cryptographic library, which means the target
OS must already have it bundled. The supported libraries at the moment are
- either `mbed TLS` or the set `tinycrypt` + `mbed TLS` (where `mbed TLS` is
+ either `Mbed TLS` or the set `tinycrypt` + `Mbed TLS` (where `Mbed TLS` is
used to provide functionality not existing in `tinycrypt`).
# Steps to port
@@ -70,20 +70,20 @@
## Flash Map
The bootloader requires to be able to address flash regions where the code
-for mcuboot and images of applications are stored, in system-agnostic way.
-For that purpose the mcuboot uses ID, which is integer (uint8_t) number
+for MCUboot and images of applications are stored, in system-agnostic way.
+For that purpose the MCUboot uses ID, which is integer (uint8_t) number
that should uniquely identify each flash region.
Such flash regions are served by object of `const struct flash_area` type while
layout of these objects is gathered under `flash_map`.
-The common code of mcuboot, that is non-system specific, does not directly
+The common code of MCUboot, that is non-system specific, does not directly
access contents of that object and never modifies it, instead it calls
`flash_area_` API to perform any actions on that object.
This way systems are free to implement internal logic of flash map or define
`struct flash_area` as they wish; the only restriction is that ID should be
uniquely tied to region characterized by device, offset and size.
-Changes to common mcuboot code should not affect system specific internals
-of flash map, on the other side system specific code, within mcuboot, is
+Changes to common MCUboot code should not affect system specific internals
+of flash map, on the other side system specific code, within MCUboot, is
is not restricted from directly accessing `struct flash_area` elements.
@@ -98,7 +98,7 @@
};
```
The above example of structure hold all information that is currently required
-by mcuboot, although the mcuboot will not be trying to access them directly,
+by MCUboot, although the MCUboot will not be trying to access them directly,
instead a system is required to provide following mandatory getter functions:
```c
@@ -114,7 +114,7 @@
```
-The mcuboot common code uses following defines that should be defined by system
+The MCUboot common code uses following defines that should be defined by system
specific header files and are used to identify destination of flash area by ID:
```c
@@ -141,50 +141,55 @@
```c
/*< Opens the area for use. id is one of the `fa_id`s */
-int flash_area_open(uint8_t id, const struct flash_area **);
-void flash_area_close(const struct flash_area *);
+int flash_area_open(uint8_t id, const struct flash_area **);
+void flash_area_close(const struct flash_area *);
/*< Reads `len` bytes of flash memory at `off` to the buffer at `dst` */
-int flash_area_read(const struct flash_area *, uint32_t off, void *dst,
- uint32_t len);
+int flash_area_read(const struct flash_area *, uint32_t off, void *dst,
+ uint32_t len);
/*< Writes `len` bytes of flash memory at `off` from the buffer at `src` */
-int flash_area_write(const struct flash_area *, uint32_t off,
- const void *src, uint32_t len);
+int flash_area_write(const struct flash_area *, uint32_t off,
+ const void *src, uint32_t len);
/*< Erases `len` bytes of flash memory at `off` */
-int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len);
+int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len);
/*< Returns this `flash_area`s alignment */
-uint8_t flash_area_align(const struct flash_area *);
+uint32_t flash_area_align(const struct flash_area *);
/*< What is value is read from erased flash bytes. */
-uint8_t flash_area_erased_val(const struct flash_area *);
+uint8_t flash_area_erased_val(const struct flash_area *);
/*< Given flash area ID, return info about sectors within the area. */
-int flash_area_get_sectors(int fa_id, uint32_t *count,
- struct flash_sector *sectors);
+int flash_area_get_sectors(int fa_id, uint32_t *count,
+ struct flash_sector *sectors);
/*< Returns the `fa_id` for slot, where slot is 0 (primary) or 1 (secondary).
`image_index` (0 or 1) is the index of the image. Image index is
relevant only when multi-image support support is enabled */
-int flash_area_id_from_multi_image_slot(int image_index, int slot);
+int flash_area_id_from_multi_image_slot(int image_index, int slot);
/*< Returns the slot (0 for primary or 1 for secondary), for the supplied
`image_index` and `area_id`. `area_id` is unique and is represented by
`fa_id` in the `flash_area` struct. */
-int flash_area_id_to_multi_image_slot(int image_index, int area_id);
+int flash_area_id_to_multi_image_slot(int image_index, int area_id);
```
-**Note:** As of writing, it is possible that mcuboot will open a flash area multiple times simultaneously (through nested calls to `flash_area_open`). As a result, mcuboot may call `flash_area_close` on a flash area that is still opened by another part of mcuboot. As a workaround when porting, it may be necessary to implement a counter of the number of times a given flash area has been opened by mcuboot. The `flash_area_close` implementation should only fully deinitialize the underlying flash area when the open counter is decremented to 0. See [this GitHub PR](https://github.com/mcu-tools/mcuboot/pull/894/) for a more detailed discussion.
+---
+***Note***
-## Memory management for mbed TLS
+*As of writing, it is possible that MCUboot will open a flash area multiple times simultaneously (through nested calls to `flash_area_open`). As a result, MCUboot may call `flash_area_close` on a flash area that is still opened by another part of MCUboot. As a workaround when porting, it may be necessary to implement a counter of the number of times a given flash area has been opened by MCUboot. The `flash_area_close` implementation should only fully deinitialize the underlying flash area when the open counter is decremented to 0. See [this GitHub PR](https://github.com/mcu-tools/mcuboot/pull/894/) for a more detailed discussion.*
-`mbed TLS` employs dynamic allocation of memory, making use of the pair
-`calloc/free`. If `mbed TLS` is to be used for crypto, your target RTOS
+---
+
+## Memory management for Mbed TLS
+
+`Mbed TLS` employs dynamic allocation of memory, making use of the pair
+`calloc/free`. If `Mbed TLS` is to be used for crypto, your target RTOS
needs to provide this pair of function.
To configure the what functions are called when allocating/deallocating
-memory `mbed TLS` uses the following call:
+memory `Mbed TLS` uses the following call:
```
int mbedtls_platform_set_calloc_free (void *(*calloc_func)(size_t, size_t),
void (*free_func)(void *));
```
-For reference see [mbed TLS platform.h](https://tls.mbed.org/api/platform_8h.html).
+For reference see [Mbed TLS platform.h](https://tls.mbed.org/api/platform_8h.html).
If your system already provides functions with compatible signatures, those can
be used directly here, otherwise create new functions that glue to your
`calloc/free` implementations.
diff --git a/docs/SECURITY.md b/docs/SECURITY.md
index aa50858..9eac59f 100644
--- a/docs/SECURITY.md
+++ b/docs/SECURITY.md
@@ -1,49 +1,54 @@
-# MCUboot project security policy
-
-## Reporting Security Issues
+# Project security policy
The MCUboot team takes security, vulnerabilities, and weaknesses
seriously.
-Security issues should be sent to the current maintainers of the
-project:
+## Reporting security issues
+
+You should report security issues either using our page at [Hackerone]
+(https://hackerone.com/mcuboot?type=team) or contacting directly the
+current maintainers of the project:
- David Brown: davidb@davidb.org or david.brown@linaro.org
- Fabio Utzig: utzig@apache.org
-If you wish to send encrypted email, you may use these PGP keys:
+If you wish to send an encrypted email, you may use these PGP keys:
+```
pub rsa4096 2011-10-14 [SC]
DAFD760825AE2636AEA9CB19E6BA9F5C5E54DF82
uid [ultimate] David Brown <davidb@davidb.org>
uid [ultimate] David Brown <david.brown@linaro.org>
sub rsa4096 2011-10-14 [E]
+```
and
+```
pub rsa4096 2017-07-28 [SC]
126087C7E725625BC7E89CC7537097EDFD4A7339
uid [ unknown] Fabio Utzig <utzig@apache.org>
uid [ unknown] Fabio Utzig <utzig@utzig.org>
sub rsa4096 2017-07-28 [E]
+```
Please include the word "SECURITY" as well as "MCUboot" in the subject
-of any messages.
+of any message.
-We will make our best effort to respond within a timely manner. Most
+We will make our best effort to respond in a timely manner. Most
vulnerabilities found within published code will undergo an embargo of
90 days to allow time fixes to be developed and deployed.
-## Vulnerability Advisories
+## Vulnerability advisories
Vulnerability reports and published fixes will be reported as follows:
-- Issues will be entered into Github's [Security Advisory
- system](https://github.com/mcu-tools/mcuboot/security/advisories), with
+- Issues will be entered into MCUboot's [security advisory
+ system](https://github.com/mcu-tools/mcuboot/security/advisories) on GitHub, with
the interested parties (including the reporter) added as viewers.
- The release notes will contain a reference to any allocated CVE(s).
-- When any embargo is lifted, the Security Advisory page will be made
+- When the embargo is lifted, the security advisory page will be made
public, and the public CVE database will be updated with all
relevant information.
diff --git a/docs/SubmittingPatches.md b/docs/SubmittingPatches.md
index 55b9230..13c46b0 100644
--- a/docs/SubmittingPatches.md
+++ b/docs/SubmittingPatches.md
@@ -1,33 +1,38 @@
-# Submitting Patches
+# Patch submission
-Development on mcuboot primarily takes place in github, at:
-https://github.com/mcu-tools/mcuboot
+The development of MCUboot takes place in the [MCUboot GitHub
+repository](https://github.com/mcu-tools/mcuboot).
-Changes should be submitted via github pull requests. Each commit
-should have a Signed-off-by line for the author (and the committer, if
-that is different). It is not necessary (or possible) to get a
-Signed-off-by from Github itself, even though some commits may be
-generated by that tool.
+To submit patches, use GitHub pull requests.
-The Signed-off-by line should be at the end of the commit text, in the
-last blank-line-separated section. There can be multiple lines in
-this section (the format being roughly like RFC-2822). Currently
-supported trailer lines are:
+Each commit has to have, in the commit message, a "Signed-off-by" line
+that mentions the author (and the committer, if that is different). You
+must add this line at the end of the commit text, separated by a blank
+line. You can also add a line linking the commit to a specific GitHub
+issue, as this section supports multiple lines, similarly to RFC-2822.
- Signed-off-by: Developer Name <devname@example.com>
+The supported trailer lines are structured as follows:
-which indicates that the signer agrees to the Developer Certificate of
-Origin below, and
+- A line that indicates that the signer agrees to the "Developer
+Certificate of Origin" located at the bottom of this page:
- JIRA: MCUB-1234
+ ```
+ Signed-off-by: Developer Name <devname@example.com>
+ ```
-which associates this commit with a particular JIRA ticket. You can
-put more than one JIRA ticket, by separating them with a comma and a
-space. JIRA is quite flexible about where the indicators go, but
-putting them in a trailer with a common format will make them easier
-to find later.
+- A line that links this commit to specific GitHub issues, if present:
-# Developer Certificate of Origin
+ ```
+ Keyword #GH_issue_number
+ ```
+
+ For more details about linking a GitHub pull request to a GitHub issue,
+ see this [link]
+ (https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
+
+## Developer certificate of origin
+
+The following is the "Developer Certificate of Origin":
```
Developer Certificate of Origin
diff --git a/docs/design.md b/docs/design.md
index e5e94b3..548580b 100755
--- a/docs/design.md
+++ b/docs/design.md
@@ -25,30 +25,30 @@
- under the License.
-->
-# Boot Loader
+# Bootloader
## [Summary](#summary)
-mcuboot comprises two packages:
+MCUboot comprises two packages:
* The bootutil library (boot/bootutil)
* The boot application (each port has its own at boot/<port>)
-The bootutil library performs most of the functions of a boot loader. In
+The bootutil library performs most of the functions of a bootloader. In
particular, the piece that is missing is the final step of actually jumping to
the main image. This last step is instead implemented by the boot application.
-Boot loader functionality is separated in this manner to enable unit testing of
-the boot loader. A library can be unit tested, but an application can't.
+Bootloader functionality is separated in this manner to enable unit testing of
+the bootloader. A library can be unit tested, but an application can't.
Therefore, functionality is delegated to the bootutil library when possible.
## [Limitations](#limitations)
-The boot loader currently only supports images with the following
+The bootloader currently only supports images with the following
characteristics:
* Built to run from flash.
* Built to run from a fixed location (i.e., not position-independent).
-## [Image Format](#image-format)
+## [Image format](#image-format)
The following definitions describe the image format.
@@ -134,7 +134,7 @@
offset of the image itself. This field provides for backwards compatibility in
case of changes to the format of the image header.
-## [Flash Map](#flash-map)
+## [Flash map](#flash-map)
A device's flash is partitioned according to its _flash map_. At a high
level, the flash map maps numeric IDs to _flash areas_. A flash area is a
@@ -142,19 +142,19 @@
1. An area can be fully erased without affecting any other areas.
2. A write to one area does not restrict writes to other areas.
-The boot loader uses the following flash area IDs:
+The bootloader uses the following flash area IDs:
```c
/* Independent from multiple image boot */
#define FLASH_AREA_BOOTLOADER 0
#define FLASH_AREA_IMAGE_SCRATCH 3
```
```c
-/* If the boot loader is working with the first image */
+/* If the bootloader is working with the first image */
#define FLASH_AREA_IMAGE_PRIMARY 1
#define FLASH_AREA_IMAGE_SECONDARY 2
```
```c
-/* If the boot loader is working with the second image */
+/* If the bootloader is working with the second image */
#define FLASH_AREA_IMAGE_PRIMARY 5
#define FLASH_AREA_IMAGE_SECONDARY 6
```
@@ -165,22 +165,25 @@
based on the number of the active image (on which the bootloader is currently
working).
-## [Image Slots](#image-slots)
+## [Image slots](#image-slots)
A portion of the flash memory can be partitioned into multiple image areas, each
contains two image slots: a primary slot and a secondary slot.
-Normally, the boot loader will only run an image from the primary slot, so
+Normally, the bootloader will only run an image from the primary slot, so
images must be built such that they can run from that fixed location in flash
(the exception to this is the [direct-xip](#direct-xip) and the
-[ram-load](#ram-load) upgrade mode). If the boot loader needs to run the
+[ram-load](#ram-load) upgrade mode). If the bootloader needs to run the
image resident in the secondary slot, it must copy its contents into the primary
slot before doing so, either by swapping the two images or by overwriting the
contents of the primary slot. The bootloader supports either swap- or
overwrite-based image upgrades, but must be configured at build time to choose
one of these two strategies.
-In addition to the slots of image areas, the boot loader requires a scratch
-area to allow for reliable image swapping. The scratch area must have a size
+### [Swap using scratch](#image-swap-using-scratch)
+
+When swap-using-scratch algorithm is used, in addition to the slots of
+image areas, the bootloader requires a scratch area to allow for reliable
+image swapping. The scratch area must have a size
that is enough to store at least the largest sector that is going to be swapped.
Many devices have small equally sized flash sectors, eg 4K, while others have
variable sized sectors where the largest sectors might be 128K or 256K, so the
@@ -220,6 +223,59 @@
manufacturer's specified number of erase cycles. In general, using a ratio that
allows hundreds to thousands of field upgrades in production is recommended.
+swap-using scratch algorithm assumes that the primary and the secondary image
+slot areas sizes are equal.
+The maximum image size available for the application
+will be:
+```
+maximum-image-size = image-slot-size - image-trailer-size
+```
+
+Where:
+ `image-slot-size` is the size of the image slot.
+ `image-trailer-size` is the size of the image trailer.
+
+### [Swap without using scratch](#image-swap-no-scratch)
+
+This algorithm is an alternative to the swap-using-scratch algorithm.
+It uses an additional sector in the primary slot to make swap possible.
+The algorithm works as follows:
+
+ 1. Moves all sectors of the primary slot up by one sector.
+ Beginning from N=0:
+ 2. Copies the N-th sector from the secondary slot to the N-th sector of the
+ primary slot.
+ 3. Copies the (N+1)-th sector from the primary slot to the N-th sector of the
+ secondary slot.
+ 4. Repeats steps 2. and 3. until all the slots' sectors are swapped.
+
+This algorithm is designed so that the higher sector of the primary slot is
+used only for allowing sectors to move up. Therefore the most
+memory-size-effective slot layout is when the primary slot is exactly one sector
+larger than the secondary slot, although same-sized slots are allowed as well.
+The algorithm is limited to support sectors of the same
+sector layout. All slot's sectors should be of the same size.
+
+When using this algorithm the maximum image size available for the application
+will be:
+```
+maximum-image-size = (N-1) * slot-sector-size - image-trailer-sectors-size
+```
+
+Where:
+ `N` is the number of sectors in the primary slot.
+ `image-trailer-sectors-size` is the size of the image trailer rounded up to
+ the total size of sectors its occupied. For instance if the image-trailer-size
+ is equal to 1056 B and the sector size is equal to 1024 B, then
+ `image-trailer-sectors-size` will be equal to 2048 B.
+
+The algorithm does two erase cycles on the primary slot and one on the secondary
+slot during each swap. Assuming that receiving a new image by the DFU
+application requires 1 erase cycle on the secondary slot, this should result in
+leveling the flash wear between the slots.
+
+The algorithm is enabled using the `MCUBOOT_SWAP_USING_MOVE` option.
+
### [Equal slots (direct-xip)](#direct-xip)
When the direct-xip mode is enabled the active image flag is "moved" between the
@@ -251,7 +307,7 @@
reason, the rest of the document describes its behavior when configured to swap
images during an upgrade.
-### [RAM Loading](#ram-load)
+### [RAM loading](#ram-load)
In ram-load mode the slots are equal. Like the direct-xip mode, this mode
also selects the newest image by reading the image version numbers in the image
@@ -293,34 +349,34 @@
the provided address and then decrypted. Finally, the decrypted image is
authenticated in RAM and executed.
-## [Boot Swap Types](#boot-swap-types)
+## [Boot swap types](#boot-swap-types)
When the device first boots under normal circumstances, there is an up-to-date
-firmware image in each primary slot, which mcuboot can validate and then
+firmware image in each primary slot, which MCUboot can validate and then
chain-load. In this case, no image swaps are necessary. During device upgrades,
however, new candidate image(s) is present in the secondary slot(s), which
-mcuboot must swap into the primary slot(s) before booting as discussed above.
+MCUboot must swap into the primary slot(s) before booting as discussed above.
Upgrading an old image with a new one by swapping can be a two-step process. In
-this process, mcuboot performs a "test" swap of image data in flash and boots
+this process, MCUboot performs a "test" swap of image data in flash and boots
the new image or it will be executed during operation. The new image can then
-update the contents of flash at runtime to mark itself "OK", and mcuboot will
+update the contents of flash at runtime to mark itself "OK", and MCUboot will
then still choose to run it during the next boot. When this happens, the swap is
-made "permanent". If this doesn't happen, mcuboot will perform a "revert" swap
+made "permanent". If this doesn't happen, MCUboot will perform a "revert" swap
during the next boot by swapping the image(s) back into its original location(s)
, and attempting to boot the old image(s).
Depending on the use case, the first swap can also be made permanent directly.
-In this case, mcuboot will never attempt to revert the images on the next reset.
+In this case, MCUboot will never attempt to revert the images on the next reset.
Test swaps are supported to provide a rollback mechanism to prevent devices
from becoming "bricked" by bad firmware. If the device crashes immediately
-upon booting a new (bad) image, mcuboot will revert to the old (working) image
+upon booting a new (bad) image, MCUboot will revert to the old (working) image
at the next device reset, rather than booting the bad image again. This allows
device firmware to make test swaps permanent only after performing a self-test
routine.
-On startup, mcuboot inspects the contents of flash to decide for each images
+On startup, MCUboot inspects the contents of flash to decide for each images
which of these "swap types" to perform; this decision determines how it
proceeds.
@@ -345,7 +401,7 @@
- `BOOT_SWAP_TYPE_PANIC`: Swapping encountered an unrecoverable error.
The "swap type" is a high-level representation of the outcome of the
-boot. Subsequent sections describe how mcuboot determines the swap type from
+boot. Subsequent sections describe how MCUboot determines the swap type from
the bit-level contents of flash.
### [Revert mechanism in direct-xip mode](#direct-xip-revert)
@@ -375,7 +431,7 @@
- Proceed to step 3.
3. Proceed to image validation ...
-## [Image Trailer](#image-trailer)
+## [Image trailer](#image-trailer)
For the bootloader to be able to determine the current state and what actions
should be taken during the current boot operation, it uses metadata stored in
@@ -396,16 +452,28 @@
| Encryption key 0 (16 octets) [*] |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0xff padding as needed |
+ | (BOOT_MAX_ALIGN minus 16 octets from Encryption key 0) [*] |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Encryption key 1 (16 octets) [*] |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0xff padding as needed |
+ | (BOOT_MAX_ALIGN minus 16 octets from Encryption key 1) [*] |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Swap size (4 octets) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Swap info | 0xff padding (7 octets) |
+ | 0xff padding as needed |
+ | (BOOT_MAX_ALIGN minus 4 octets from Swap size) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Copy done | 0xff padding (7 octets) |
+ | Swap info | 0xff padding (BOOT_MAX_ALIGN minus 1 octet) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Image OK | 0xff padding (7 octets) |
+ | Copy done | 0xff padding (BOOT_MAX_ALIGN minus 1 octet) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Image OK | 0xff padding (BOOT_MAX_ALIGN minus 1 octet) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0xff padding as needed |
+ | (BOOT_MAX_ALIGN minus 16 octets from MAGIC) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAGIC (16 octets) |
| |
@@ -417,10 +485,15 @@
The offset immediately following such a record represents the start of the next
flash area.
-Note: "min-write-size" is a property of the flash hardware. If the hardware
-allows individual bytes to be written at arbitrary addresses, then
-min-write-size is 1. If the hardware only allows writes at even addresses,
-then min-write-size is 2, and so on.
+---
+***Note***
+
+*"min-write-size" is a property of the flash hardware. If the hardware*
+*allows individual bytes to be written at arbitrary addresses, then*
+*min-write-size is 1. If the hardware only allows writes at even addresses,*
+*then min-write-size is 2, and so on.*
+
+---
An image trailer contains the following fields:
@@ -438,7 +511,7 @@
sector. The swap status field can thus used to resume a swap operation if the
bootloader is halted while a swap operation is ongoing and later reset. The
`BOOT_MAX_IMG_SECTORS` value is the configurable maximum number of sectors
-mcuboot supports for each image; its value defaults to 128, but allows for
+MCUboot supports for each image; its value defaults to 128, but allows for
either decreasing this size, to limit RAM usage, or to increase it in devices
that have massive amounts of Flash or very small sized sectors and thus require
a bigger configuration to allow for the handling of all slot's sectors.
@@ -456,7 +529,7 @@
4. Swap info: A single byte which encodes the following information:
- Swap type: Stored in bits 0-3. Indicating the type of swap operation in
- progress. When mcuboot resumes an interrupted swap, it uses this field to
+ progress. When MCUboot resumes an interrupted swap, it uses this field to
determine the type of operation to perform. This field contains one of the
following values in the table below.
- Image number: Stored in bits 4-7. It has always 0 value at single image
@@ -479,26 +552,67 @@
6. Image OK: A single byte indicating whether the image in this slot has been
confirmed as good by the user (0x01=confirmed; 0xff=not confirmed).
-7. MAGIC: The following 16 bytes, written in host-byte-order:
+7. MAGIC: A 16-byte field identifying the image trailer layout. It may assume
+ distinct values depending on the maximum supported write alignment
+ (`BOOT_MAX_ALIGN`) of the image, as defined by the following construct:
``` c
- const uint32_t boot_img_magic[4] = {
- 0xf395c277,
- 0x7fefd260,
- 0x0f505235,
- 0x8079b62c,
+union boot_img_magic_t
+{
+ struct {
+ uint16_t align;
+ uint8_t magic[14];
};
+ uint8_t val[16];
+};
+```
+ If `BOOT_MAX_ALIGN` is **8 bytes**, then MAGIC contains the following 16 bytes:
+
+``` c
+const union boot_img_magic_t boot_img_magic = {
+ .val = {
+ 0x77, 0xc2, 0x95, 0xf3,
+ 0x60, 0xd2, 0xef, 0x7f,
+ 0x35, 0x52, 0x50, 0x0f,
+ 0x2c, 0xb6, 0x79, 0x80
+ }
+};
```
-## [IMAGE TRAILERS](#image-trailers)
+ In case `BOOT_MAX_ALIGN` is defined to any value different than **8**, then the maximum
+ supported write alignment value is encoded in the MAGIC field, followed by a fixed
+ 14-byte pattern:
-At startup, the boot loader determines the boot swap type by inspecting the
+``` c
+const union boot_img_magic_t boot_img_magic = {
+ .align = BOOT_MAX_ALIGN,
+ .magic = {
+ 0x2d, 0xe1,
+ 0x5d, 0x29, 0x41, 0x0b,
+ 0x8d, 0x77, 0x67, 0x9c,
+ 0x11, 0x0f, 0x1f, 0x8a
+ }
+};
+```
+
+---
+***Note***
+Be aware that the image trailers make the ending area of the image slot
+unavailable for carrying the image data. In particular, the swap status size
+could be huge. For example, for 128 slot sectors with a 4-byte alignment,
+it would become 1536 B.
+
+---
+
+## [Image trailers](#image-trailers)
+
+At startup, the bootloader determines the boot swap type by inspecting the
image trailers. When using the term "image trailers" what is meant is the
aggregate information provided by both image slot's trailers.
### [New swaps (non-resumes)](#new-swaps-non-resumes)
-For new swaps, mcuboot must inspect a collection of fields to determine which
+For new swaps, MCUboot must inspect a collection of fields to determine which
swap operation to perform.
The image trailers records are structured around the limitations imposed by
@@ -507,9 +621,14 @@
image trailers. It is better to map all the possible trailer states to the swap
types described above via a set of tables. These tables are reproduced below.
-Note: An important caveat about the tables described below is that they must
-be evaluated in the order presented here. Lower state numbers must have a
-higher priority when testing the image trailers.
+---
+***Note***
+
+*An important caveat about the tables described below is that they must*
+*be evaluated in the order presented here. Lower state numbers must have a*
+*higher priority when testing the image trailers.*
+
+---
```
State I
@@ -545,9 +664,9 @@
-------------------------------------------------'
```
-Any of the above three states results in mcuboot attempting to swap images.
+Any of the above three states results in MCUboot attempting to swap images.
-Otherwise, mcuboot does not attempt to swap images, resulting in one of the
+Otherwise, MCUboot does not attempt to swap images, resulting in one of the
other three swap types, as illustrated by State IV.
```
@@ -564,30 +683,35 @@
-------------------------------------------------'
```
-In State IV, when no errors occur, mcuboot will attempt to boot the contents of
+In State IV, when no errors occur, MCUboot will attempt to boot the contents of
the primary slot directly, and the result is `BOOT_SWAP_TYPE_NONE`. If the image
in the primary slot is not valid, the result is `BOOT_SWAP_TYPE_FAIL`. If a
fatal error occurs during boot, the result is `BOOT_SWAP_TYPE_PANIC`. If the
-result is either `BOOT_SWAP_TYPE_FAIL` or `BOOT_SWAP_TYPE_PANIC`, mcuboot hangs
+result is either `BOOT_SWAP_TYPE_FAIL` or `BOOT_SWAP_TYPE_PANIC`, MCUboot hangs
rather than booting an invalid or compromised image.
-Note: An important caveat to the above is the result when a swap is requested
- and the image in the secondary slot fails to validate, due to a hashing or
- signing error. This state behaves as State IV with the extra action of
- marking the image in the primary slot as "OK", to prevent further attempts
- to swap.
+---
+***Note***
+
+*An important caveat to the above is the result when a swap is requested*
+*and the image in the secondary slot fails to validate, due to a hashing or*
+*signing error. This state behaves as State IV with the extra action of*
+*marking the image in the primary slot as "OK", to prevent further attempts*
+*to swap.*
+
+---
### [Resumed swaps](#resumed-swaps)
-If mcuboot determines that it is resuming an interrupted swap (i.e., a reset
+If MCUboot determines that it is resuming an interrupted swap (i.e., a reset
occurred mid-swap), it fully determines the operation to resume by reading the
`swap info` field from the active trailer and extracting the swap type from bits
0-3. The set of tables in the previous section are not necessary in the resume
case.
-## [High-Level Operation](#high-level-operation)
+## [High-level operation](#high-level-operation)
-With the terms defined, we can now explore the boot loader's operation. First,
+With the terms defined, we can now explore the bootloader's operation. First,
a high-level overview of the boot process is presented. Then, the following
sections describe each step of the process in more detail.
@@ -613,15 +737,15 @@
3. Boot into image in primary slot.
-### [Multiple Image Boot](#multiple-image-boot)
+### [Multiple image boot](#multiple-image-boot)
-When the flash contains multiple executable images the boot loader's operation
+When the flash contains multiple executable images the bootloader's operation
is a bit more complex but similar to the previously described procedure with
one image. Every image can be updated independently therefore the flash is
partitioned further to arrange two slots for each image.
```
+--------------------+
-| MCUBoot |
+| MCUboot |
+--------------------+
~~~~~ <- memory might be not contiguous
+--------------------+
@@ -642,7 +766,7 @@
| Scratch |
+--------------------+
```
-MCUBoot is also capable of handling dependencies between images. For example
+MCUboot is also capable of handling dependencies between images. For example
if an image needs to be reverted it might be necessary to revert another one too
(e.g. due to API incompatibilities) or simply to prevent from being updated
because of an unsatisfied dependency. Therefore all aborted swaps have to be
@@ -705,9 +829,9 @@
+ Boot into image in the primary slot of the 0th image position\
(other image in the boot chain is started by another image).
-### [Multiple Image Boot for RAM loading and direct-xip](#multiple-image-boot-for-ram-loading-and-direct-xip)
+### [Multiple image boot for RAM loading and direct-xip](#multiple-image-boot-for-ram-loading-and-direct-xip)
-The operation of the boot loader is different when the ram-load or the
+The operation of the bootloader is different when the ram-load or the
direct-xip strategy is chosen. The flash map is very similar to the swap
strategy but there is no need for Scratch area.
@@ -740,20 +864,20 @@
+ Boot the loaded slot of image 0.
-## [Image Swapping](#image-swapping)
+## [Image swapping](#image-swapping)
-The boot loader swaps the contents of the two image slots for two reasons:
+The bootloader swaps the contents of the two image slots for two reasons:
* User has issued a "set pending" operation; the image in the secondary slot
should be run once (state I) or repeatedly (state II), depending on
whether a permanent swap was specified.
- * Test image rebooted without being confirmed; the boot loader should
+ * Test image rebooted without being confirmed; the bootloader should
revert to the original image currently in the secondary slot (state III).
If the image trailers indicates that the image in the secondary slot should be
-run, the boot loader needs to copy it to the primary slot. The image currently
+run, the bootloader needs to copy it to the primary slot. The image currently
in the primary slot also needs to be retained in flash so that it can be used
-later. Furthermore, both images need to be recoverable if the boot loader
+later. Furthermore, both images need to be recoverable if the bootloader
resets in the middle of the swap operation. The two images are swapped
according to the following procedure:
@@ -798,13 +922,21 @@
unwritten, the user can test the image in the secondary slot
(i.e., transition to state I).
-Note1: If the region being copied contains the last sector, then swap status is
-temporarily maintained on scratch for the duration of this operation, always
-using the primary slot's area otherwise.
+---
+***Note***
-Note2: The bootloader tries to copy only used sectors (based on largest image
-installed on any of the slots), minimizing the amount of sectors copied and
-reducing the amount of time required for a swap operation.
+*If the region being copied contains the last sector, then swap status is*
+*temporarily maintained on scratch for the duration of this operation, always*
+*using the primary slot's area otherwise.*
+
+---
+***Note***
+
+*The bootloader tries to copy only used sectors (based on largest image*
+*installed on any of the slots), minimizing the amount of sectors copied and*
+*reducing the amount of time required for a swap operation.*
+
+---
The particulars of step 3 vary depending on whether an image is being tested,
permanently used, reverted or a validation failure of the secondary slot
@@ -836,9 +968,9 @@
After completing the operations as described above the image in the primary slot
should be booted.
-## [Swap Status](#swap-status)
+## [Swap status](#swap-status)
-The swap status region allows the boot loader to recover in case it restarts in
+The swap status region allows the bootloader to recover in case it restarts in
the middle of an image swap operation. The swap status region consists of a
series of single-byte records. These records are written independently, and
therefore must be padded according to the minimum write size imposed by the
@@ -884,11 +1016,11 @@
3. primary slot: image 1, secondary slot: image 0, scratch: N/A (s->0)
```
-Each time a sector index transitions to a new state, the boot loader writes a
-record to the swap status region. Logically, the boot loader only needs one
+Each time a sector index transitions to a new state, the bootloader writes a
+record to the swap status region. Logically, the bootloader only needs one
record per sector index to keep track of the current swap state. However, due
to limitations imposed by flash hardware, a record cannot be overwritten when
-an index's state changes. To solve this problem, the boot loader uses three
+an index's state changes. To solve this problem, the bootloader uses three
records per sector index rather than just one.
Each sector-state pair is represented as a set of three records. The record
@@ -914,12 +1046,17 @@
sector index that gets swapped is 63, which corresponds to the exact halfway
point within the region.
-Note: since the scratch area only ever needs to record swapping of the last
-sector, it uses at most min-write-size * 3 bytes for its own status area.
+---
+***Note***
-## [Reset Recovery](#reset-recovery)
+*Since the scratch area only ever needs to record swapping of the last*
+*sector, it uses at most min-write-size * 3 bytes for its own status area.*
-If the boot loader resets in the middle of a swap operation, the two images may
+---
+
+## [Reset recovery](#reset-recovery)
+
+If the bootloader resets in the middle of a swap operation, the two images may
be discontiguous in flash. Bootutil recovers from this condition by using the
image trailers to determine how the image parts are distributed in flash.
@@ -973,7 +1110,7 @@
-----------------------------------------------------------------------'
```
-If the swap status region indicates that the images are not contiguous, mcuboot
+If the swap status region indicates that the images are not contiguous, MCUboot
determines the type of swap operation that was interrupted by reading the `swap
info` field in the active image trailer and extracting the swap type from bits
0-3 then resumes the operation. In other words, it applies the procedure defined
@@ -983,18 +1120,18 @@
at step e or step h in the area-swap procedure, depending on whether the part
belongs to image 0 or image 1.
-After the swap operation has been completed, the boot loader proceeds as though
+After the swap operation has been completed, the bootloader proceeds as though
it had just been started.
-## [Integrity Check](#integrity-check)
+## [Integrity check](#integrity-check)
An image is checked for integrity immediately before it gets copied into the
-primary slot. If the boot loader doesn't perform an image swap, then it can
+primary slot. If the bootloader doesn't perform an image swap, then it can
perform an optional integrity check of the image in the primary slot if
`MCUBOOT_VALIDATE_PRIMARY_SLOT` is set, otherwise it doesn't perform an
integrity check.
-During the integrity check, the boot loader verifies the following aspects of
+During the integrity check, the bootloader verifies the following aspects of
an image:
* 32-bit magic number must be correct (`IMAGE_MAGIC`).
@@ -1010,39 +1147,53 @@
keys will then be iterated over looking for the matching key, which then
will then be used to verify the image contents.
+For low performance MCU's where the validation is a heavy process at boot
+(~1-2 seconds on a arm-cortex-M0), the `MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE`
+could be used. This option will cache the validation result as described above
+into the magic area of the primary slot. The next boot, the validation will be
+skipped if the previous validation was succesfull. This option is reducing the
+security level since if an attacker could modify the contents of the flash after
+a good image has been validated, the attacker could run his own image without
+running validation again. Enabling this option should be done with care.
+
## [Security](#security)
As indicated above, the final step of the integrity check is signature
-verification. The boot loader can have one or more public keys embedded in it
-at build time. During signature verification, the boot loader verifies that an
+verification. The bootloader can have one or more public keys embedded in it
+at build time. During signature verification, the bootloader verifies that an
image was signed with a private key that corresponds to the embedded KEYHASH
TLV.
-For information on embedding public keys in the boot loader, as well as
+For information on embedding public keys in the bootloader, as well as
producing signed images, see: [signed_images](signed_images.md).
If you want to enable and use encrypted images, see:
[encrypted_images](encrypted_images.md).
-Note: Image encryption is not supported when the direct-xip upgrade strategy
-is selected.
+---
+***Note***
-### [Using Hardware Keys for Verification](#hw-key-support)
+*Image encryption is not supported when the direct-xip upgrade strategy*
+*is selected.*
+
+---
+
+### [Using hardware keys for verification](#hw-key-support)
By default, the whole public key is embedded in the bootloader code and its
hash is added to the image manifest as a KEYHASH TLV entry. As an alternative
the bootloader can be made independent of the keys by setting the
`MCUBOOT_HW_KEY` option. In this case the hash of the public key must be
-provisioned to the target device and mcuboot must be able to retrieve the
+provisioned to the target device and MCUboot must be able to retrieve the
key-hash from there. For this reason the target must provide a definition
for the `boot_retrieve_public_key_hash()` function which is declared in
`boot/bootutil/include/bootutil/sign_key.h`. It is also required to use
the `full` option for the `--public-key-format` imgtool argument in order to
add the whole public key (PUBKEY TLV) to the image manifest instead of its
hash (KEYHASH TLV). During boot the public key is validated before using it for
-signature verification, mcuboot calculates the hash of the public key from the
+signature verification, MCUboot calculates the hash of the public key from the
TLV area and compares it with the key-hash that was retrieved from the device.
-This way mcuboot is independent from the public key(s). The key(s) can be
+This way MCUboot is independent from the public key(s). The key(s) can be
provisioned any time and by different parties.
## [Protected TLVs](#protected-tlvs)
@@ -1082,9 +1233,9 @@
+---------------------+
```
-## [Dependency Check](#dependency-check)
+## [Dependency check](#dependency-check)
-MCUBoot can handle multiple firmware images. It is possible to update them
+MCUboot can handle multiple firmware images. It is possible to update them
independently but in many cases it can be desired to be able to describe
dependencies between the images (e.g. to ensure API compliance and avoid
interoperability issues).
@@ -1095,7 +1246,7 @@
images then there can be maximum one entry which reflects to the other image.
At the phase of dependency check all aborted swaps are finalized if there were
-any. During the dependency check the boot loader verifies whether the image
+any. During the dependency check the bootloader verifies whether the image
dependencies are all satisfied. If at least one of the dependencies of an image
is not fulfilled then the swap type of that image has to be modified
accordingly and the dependency check needs to be restarted. This way the number
@@ -1106,14 +1257,14 @@
For more information on adding dependency entries to an image,
see: [imgtool](imgtool.md).
-## [Downgrade Prevention](#downgrade-prevention)
+## [Downgrade prevention](#downgrade-prevention)
Downgrade prevention is a feature which enforces that the new image must have a
higher version/security counter number than the image it is replacing, thus
preventing the malicious downgrading of the device to an older and possibly
vulnerable version of its firmware.
-### [SW Based Downgrade Prevention](#sw-downgrade-prevention)
+### [Software-based downgrade prevention](#sw-downgrade-prevention)
During the software based downgrade prevention the image version numbers are
compared. This feature is enabled with the `MCUBOOT_DOWNGRADE_PREVENTION`
@@ -1121,7 +1272,7 @@
overwrite-based image update strategy is used (i.e. `MCUBOOT_OVERWRITE_ONLY`
is set).
-### [HW Based Downgrade Prevention](#hw-downgrade-prevention)
+### [Hardware-based downgrade prevention](#hw-downgrade-prevention)
Each signed image can contain a security counter in its protected TLV area, which
can be added to the image using the `-s` option of the [imgtool](imgtool.md) script.
@@ -1142,7 +1293,7 @@
## [Measured boot and data sharing](#boot-data-sharing)
-MCUBoot defines a mechanism for sharing boot status information (also known as
+MCUboot defines a mechanism for sharing boot status information (also known as
measured boot) and an interface for sharing application specific information
with the runtime software. If any of these are enabled the target must provide
a shared data area between the bootloader and runtime firmware and define the
@@ -1198,7 +1349,7 @@
will be the value of the "Software type" attribute in the generated BOOT_RECORD
TLV. The target must also define the `MAX_BOOT_RECORD_SZ` macro which indicates
the maximum size of the CBOR encoded boot record in bytes.
-During boot, MCUBoot will look for these TLVs (in case of multiple images) in
+During boot, MCUboot will look for these TLVs (in case of multiple images) in
the manifests of the active images (the latest and validated) and copy the CBOR
encoded binary data to the shared data area. Preserving all these image
attributes from the boot stage for use by later runtime services (such as an
diff --git a/docs/ecdsa.md b/docs/ecdsa.md
index e60c7aa..50ca961 100644
--- a/docs/ecdsa.md
+++ b/docs/ecdsa.md
@@ -1,90 +1,94 @@
# ECDSA signature format
-When ECDSA SECP256R1 (EC256) signature support was added to MCUboot, a
+When the ECDSA SECP256R1 (EC256) signature support was added to MCUboot, a
shortcut was taken, and these signatures were padded to make them
-always a fixed length. Unfortunately, this padding was done in a way
-that is not easily reversible. Some crypto libraries are fairly
-strict about the formatting of the ECDSA signature (specifically, mbed
-TLS). This currently means that the ECDSA SECP224R1 (EC) signature
+always a fixed length. Unfortunately, this padding was done in a way
+that is not easily reversible. Some crypto libraries (specifically, Mbed
+TLS) are fairly strict about the formatting of the ECDSA signature.
+This currently means that the ECDSA SECP224R1 (EC) signature
checking code will fail to boot about 1 out of every 256 images,
because the signature itself will end in a 0x00 byte, and the code
will remove too much data, invalidating the signature.
-There are a couple of ways to fix this:
+There are two ways to fix this:
- 1. Use a reversible padding scheme. This will work, but requires
- at least one pad byte always be added (to set the length). This
- padding would be somewhat incompatible across versions (older
- EC256 would work, newer mcuboot code would reject old
- signatures. EC code would only reliably work in the new
- combination).
+ - Use a reversible padding scheme. This solution requires
+ at least one pad byte to always be added (to set the length). This
+ padding would be somewhat incompatible across versions (older
+ EC256 would work, while newer MCUboot code would reject old
+ signatures. The EC code would work reliably only in the new
+ combination).
- 2. Remove the padding entirely. Depending on which tool, this will
- require some rethinking of how TLV generation is implemented so
- that the length does not need to be known until the signature is
- generated. These tools are all written in higher-level
- languages and this change should not be difficult.
+ - Remove the padding entirely. Depending on the tool used, this solution
+ requires some rethinking of how TLV generation is implemented so
+ that the length does not need to be known until the signature is
+ generated. These tools are usually written in higher-level
+ languages, so this change should not be difficult.
- However, this will also break compatibility with older versions,
- specifically in that images generated with newer tools will not
- work with older versions of MCUboot.
+ However, this will also break compatibility with older versions,
+ because images generated with newer tools will not
+ work with older versions of MCUboot.
-This document proposes a multi-stage approach, to give a transition
-period.
+This document proposes a multi-stage approach to give a transition
+period:
- - First, add a `--no-pad-sig` argument to the sign command in
- `imgtool.py`. Without this, the images will be padded with the
- existing scheme, and with the argument, the ecdsa will be encoded
- without any padding. The `--pad-sig` argument will also be
- accepted, but this will initially be the default.
+ 1. Add a `--no-pad-sig` argument to the sign command in
+ `imgtool.py`.
- - MCUboot will be modified to allow unpadded signatures right away.
- The existing EC256 implementations will still work (with or
- without padding), and the existing EC implementation will begin
- accepting padded and unpadded signatures.
+ Without this argument, the images are padded with the
+ existing scheme. With this argument, the ECDSA is encoded
+ without any padding. The `--pad-sig` argument is also
+ accepted, but it is already the default.
- - An mbed TLS implementation of EC256 can be added, but will require
- the `--no-pad-sig` signature to be able to boot all generated
- images (without the argument 3 of out 4 images generated will have
- padding, and be considered invalid).
+ 2. MCUboot will be modified to allow unpadded signatures right away.
+ The existing EC256 implementations will still work (with or
+ without padding), and the existing EC implementation will be able
+ to accept padded and unpadded signatures.
-After one or more MCUboot release cycles, and announcements over
+ 3. An Mbed TLS implementation of EC256 can be added, but it will require
+ the `--no-pad-sig` signature to be able to boot all generated
+ images. Without the argument, 3 out of 4 images generated will have
+ padding and will be considered invalid.
+
+After one or more MCUboot release cycles and announcements in the
relevant channels, the arguments to `imgtool.py` will change:
- - `--no-pad-sig` will still be accepted, but have no effect.
+ - `--no-pad-sig` will still be accepted but will have no effect.
- `--pad-sig` will now bring back the old padding behavior.
-This will require a change to any scripts that are relying on a
-default, but not specifying a specific version of imgtool.
+This will require an update to any scripts that will rely on the default
+behavior, but will not specify a specific version of imgtool.
The signature generation in the simulator can be changed at the same
-time the boot code begins to accept unpadded signatures. The sim is
-always run out of the same tree as the mcuboot code, so there should
+time the boot code begins to accept unpadded signatures. The simulator is
+always run out of the same tree as the MCUboot code, so there should
not be any compatibility issues.
## Background
ECDSA signatures are encoded as ASN.1, notably with the signature
-itself being encoded as:
+itself encoded as follows:
+```
ECDSA-Sig-Value ::= SEQUENCE {
r INTEGER,
s INTEGER
}
+```
-where both `r` and `s` are 256-bit numbers. Because these are
+Both `r` and `s` are 256-bit numbers. Because these are
unsigned numbers that are being encoded in ASN.1 as signed values, if
-the high bit of the number is set, the DER encoded representation will
-require 33 bytes instead of 32. This means that the length of the
-signature will vary by a couple of bytes, depending on whether one of
-both of these numbers has the high bit set.
+the high bit of the number is set, the DER-encoded representation will
+require 33 bytes instead of 32. This means that the length of the
+signature will vary by a couple of bytes, depending on whether one or
+both of these numbers have the high bit set.
-Originally, MCUboot added padding to the entire signature, and just
-removed any trailing 0 bytes from the data block. This would be fine 255/256
-times, when the last byte of the signature was non-zero, but if the
-signature ended in a zero, it would remove too many bytes, and the
-signature would be considered invalid.
+Originally, MCUboot added padding to the entire signature and just
+removed any trailing 0 bytes from the data block. This turned out to be fine 255 out of 256
+times, each time the last byte of the signature was non-zero, but if the
+signature ended in a zero, MCUboot would remove too many bytes and render the
+signature invalid.
-The correct approach here is to accept that ECDSA signatures are
-variable length, and make sure that we can handle them as such.
+The correct approach here is to accept that ECDSA signatures are of
+variable length, and to make sure that we can handle them as such.
diff --git a/docs/encrypted_images.md b/docs/encrypted_images.md
index 838f493..6ce52f1 100644
--- a/docs/encrypted_images.md
+++ b/docs/encrypted_images.md
@@ -24,7 +24,7 @@
## [Rationale](#rationale)
To provide confidentiality of image data while in transport to the
-device or while residing on an external flash, `MCUBoot` has support
+device or while residing on an external flash, `MCUboot` has support
for encrypting/decrypting images on-the-fly while upgrading.
The image header needs to flag this image as `ENCRYPTED` (0x04) and
@@ -84,7 +84,7 @@
ECIES follows a well defined protocol to generate an encryption key. There are
multiple standards which differ only on which building blocks are used; for
-MCUBoot we settled on some primitives that are easily found on our crypto
+MCUboot we settled on some primitives that are easily found on our crypto
libraries. The whole key encryption can be summarized as:
* Generate a new private key and derive the public key; when using ECIES-P256
@@ -112,7 +112,7 @@
## [Upgrade process](#upgrade-process)
-When starting a new upgrade process, `MCUBoot` checks that the image in the
+When starting a new upgrade process, `MCUboot` checks that the image in the
`secondary slot` has the `ENCRYPTED` flag set and has the required TLV with the
encrypted key. It then uses its internal private/secret key to decrypt
the TLV containing the key. Given that no errors are found, it will then
@@ -132,8 +132,13 @@
sectors are re-encrypted when copying from the `primary slot` to
the `secondary slot`.
-PS: Each encrypted image must have its own key TLV that should be unique
-and used only for this particular image.
+---
+***Note***
+
+*Each encrypted image must have its own key TLV that should be unique*
+*and used only for this particular image.*
+
+---
Also when swap method is employed, the sizes of both images are saved to
the status area just before starting the upgrade process, because it
diff --git a/docs/imgtool.md b/docs/imgtool.md
index 97f3272..9d50e67 100644
--- a/docs/imgtool.md
+++ b/docs/imgtool.md
@@ -18,7 +18,7 @@
./scripts/imgtool.py keygen -k filename.pem -t rsa-2048
or use rsa-3072, ecdsa-p256, or ed25519 for the type. The key type used
-should match what mcuboot is configured to verify.
+should match what MCUboot is configured to verify.
This key file is what is used to sign images, this file should be
protected, and not widely distributed.
@@ -29,7 +29,7 @@
## [Incorporating the public key into the code](#incorporating-the-public-key-into-the-code)
-There is a development key distributed with mcuboot that can be used
+There is a development key distributed with MCUboot that can be used
for testing. Since this private key is widely distributed, it should
never be used for production. Once you have generated a production
key, as described above, you should replace the public key in the
@@ -68,7 +68,7 @@
it from the image version.
-d, --dependencies TEXT
--pad-sig Add 0-2 bytes of padding to ECDSA signature
- (for mcuboot <1.5)
+ (for MCUboot <1.5)
-H, --header-size INTEGER [required]
--pad-header Add --header-size zeroed bytes at the
beginning of the image
diff --git a/docs/index.md b/docs/index.md
index c892c57..02b7d09 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,82 +1,92 @@
# MCUboot
+MCUboot is a secure bootloader for 32-bits microcontrollers.
+
## Overview
-MCUboot is a secure bootloader for 32-bit MCUs. The goal of MCUboot is to
-define a common infrastructure for the bootloader, system flash layout on
-microcontroller systems, and to provide a secure bootloader that enables
-easy software upgrade.
+MCUboot defines a common infrastructure for the bootloader and the system flash
+layout on microcontroller systems, and provides a secure bootloader that
+enables easy software upgrade.
-MCUboot is operating system and hardware independent and relies on
-hardware porting layers from the operating system it works with. Currently
-MCUboot works with both the Apache Mynewt, and Zephyr operating systems, but
-more ports are planned in the future. RIOT is currently supported as a boot
-target with a complete port planned.
+MCUboot is not dependent on any specific operating system and hardware and
+relies on hardware porting layers from the operating system it works with.
+Currently MCUboot works with the following operating systems and SoCs:
+- [Zephyr](https://www.zephyrproject.org/)
+- [Apache Mynewt](https://mynewt.apache.org/)
+- [Apache NuttX](https://nuttx.apache.org/)
+- [RIOT](https://www.riot-os.org/)
+- [Mbed OS](https://os.mbed.com/)
+- [Espressif IDF](https://idf.espressif.com/)
+- [Cypress/Infineon](https://www.cypress.com/)
-MCUboot is an open governance project. See the [membership
+RIOT is supported only as a boot target. We will accept any new port
+contributed by the community once it is good enough.
+
+MCUboot is an open governance project. See the [membership
list](https://github.com/mcu-tools/mcuboot/wiki/Members) for current
members, and the
-[charter](https://github.com/mcu-tools/mcuboot/wiki/MCUboot-Project-Charter)
+[project charter](https://github.com/mcu-tools/mcuboot/wiki/MCUboot-Project-Charter)
for more details.
-## Contents
+## Documentation
+
+The MCUboot documentation is composed of the following pages:
- General - this document
- [Release notes](release-notes.md)
- [Bootloader design](design.md)
- [Encrypted images](encrypted_images.md)
- [imgtool](imgtool.md) - image signing and key management
-- [ecdsa](ecdsa.md) - Information about ECDSA signature formats
+- [ECDSA](ecdsa.md) - information about ECDSA signature formats
- Usage instructions:
- [Zephyr](readme-zephyr.md)
- - [Mynewt](readme-mynewt.md)
+ - [Apache Mynewt](readme-mynewt.md)
+ - [Apache NuttX](readme-nuttx.md)
- [RIOT](readme-riot.md)
- - [Mbed-OS](readme-mbed.md)
-- [Patch submission](SubmittingPatches.md) - information
- on how to contribute to mcuboot
+ - [Mbed OS](readme-mbed.md)
+ - [Espressif IDF](readme-espressif.md)
+ - [Cypress/Infineon](../boot/cypress/readme.md)
+ - [Simulator](../sim/README.rst)
- Testing
- - [Zephyr](testplan-zephyr.md) test plan
- - [mynewt](testplan-mynewt.md) test plan
+ - [Zephyr](testplan-zephyr.md) - Zephyr test plan
+ - [Apache Mynewt](testplan-mynewt.md) - Apache Mynewt test plan
- [Release process](release.md)
+- [Project security policy](SECURITY.md)
+- [Patch submission](SubmittingPatches.md) - information
+ on how to contribute to MCUboot
-There is also a document about [signed images](signed_images.md) that is out
-of date. You should use `imgtool.py` instead of these documents.
+The documentation page about [signed images](signed_images.md) is currently
+outdated. Follow the instructions in [imgtool](imgtool.md) instead.
## Roadmap
-The issues being planned and worked on are tracked using GitHub issues. To participate
-please visit:
+The issues being planned and worked on are tracked using GitHub issues. To
+give your input, visit [MCUboot GitHub
+Issues](https://github.com/mcu-tools/mcuboot/issues).
-[MCUboot Issues](https://github.com/mcu-tools/mcuboot/issues)
+## Source files
-~~Issues were previously tracked on [MCUboot JIRA](https://runtimeco.atlassian.net/projects/MCUB/summary)
-, but it is now deprecated.~~
+You can find additional documentation on the bootloader in the source files.
+For more information, use the following links:
+- [boot/bootutil](https://github.com/mcu-tools/mcuboot/tree/main/boot/bootutil) - The core of the bootloader itself.
+- [boot/boot\_serial](https://github.com/mcu-tools/mcuboot/tree/main/boot/boot_serial) - Support for serial upgrade within the bootloader itself.
+- [boot/zephyr](https://github.com/mcu-tools/mcuboot/tree/main/boot/zephyr) - Port of the bootloader to Zephyr.
+- [boot/mynewt](https://github.com/mcu-tools/mcuboot/tree/main/boot/mynewt) - Bootloader application for Apache Mynewt.
+- [boot/nuttx](https://github.com/mcu-tools/mcuboot/tree/main/boot/nuttx) - Bootloader application and port of MCUboot interfaces for Apache NuttX.
+- [boot/mbed](https://github.com/mcu-tools/mcuboot/tree/main/boot/mbed) - Port of the bootloader to Mbed OS.
+- [boot/espressif](https://github.com/mcu-tools/mcuboot/tree/main/boot/espressif) - Bootloader application and MCUboot port for Espressif SoCs.
+- [boot/cypress](https://github.com/mcu-tools/mcuboot/tree/main/boot/cypress) - Bootloader application and MCUboot port for Cypress/Infineon SoCs.
+- [imgtool](https://github.com/mcu-tools/mcuboot/tree/main/scripts/imgtool.py) - A tool to securely sign firmware images for booting by MCUboot.
+- [sim](https://github.com/mcu-tools/mcuboot/tree/main/sim) - A bootloader simulator for testing and regression.
-## Browsing
+## Joining the project
-Information and documentation on the bootloader is stored within the source.
+Developers are welcome!
-~~It was previously also documented on confluence: [Confluence page](https://runtimeco.atlassian.net/wiki/discover/all-updates)
-, but it is now deprecated and not currently maintained~~
-
-For more information in the source, here are some pointers:
-
-- [boot/bootutil](https://github.com/mcu-tools/mcuboot/tree/main/boot/bootutil): The core of the bootloader itself.
-- [boot/boot\_serial](https://github.com/mcu-tools/mcuboot/tree/main/boot/boot_serial): Support for serial upgrade within the bootloader itself.
-- [boot/zephyr](https://github.com/mcu-tools/mcuboot/tree/main/boot/zephyr): Port of the bootloader to Zephyr
-- [boot/mynewt](https://github.com/mcu-tools/mcuboot/tree/main/boot/mynewt): Mynewt bootloader app
-- [boot/mbed](https://github.com/mcu-tools/mcuboot/tree/main/boot/mbed): Port of the bootloader to Mbed-OS
-- [imgtool](https://github.com/mcu-tools/mcuboot/tree/main/scripts/imgtool.py): A tool to securely sign firmware images for booting by MCUboot.
-- [sim](https://github.com/mcu-tools/mcuboot/tree/main/sim): A bootloader simulator for testing and regression
-
-## Joining
-
-Developers welcome!
+Use the following links to join or see more about the project:
* [Our developer mailing list](https://groups.io/g/MCUBoot)
-* [Our Slack channel](https://mcuboot.slack.com/)<br />
- Get your invite [here!](https://join.slack.com/t/mcuboot/shared_invite/MjE2NDcwMTQ2MTYyLTE1MDA4MTIzNTAtYzgyZTU0NjFkMg)
-* [Our IRC channel](http://irc.freenode.net), channel #mcuboot ([IRC
- link](irc://chat.freenode.net/#mcuboot)
+* [Our Slack channel](https://mcuboot.slack.com/) <br />
+ Get [your invite](https://join.slack.com/t/mcuboot/shared_invite/MjE2NDcwMTQ2MTYyLTE1MDA4MTIzNTAtYzgyZTU0NjFkMg)
* [Current members](https://github.com/mcu-tools/mcuboot/wiki/Members)
* [Project charter](https://github.com/mcu-tools/mcuboot/wiki/MCUboot-Project-Charter)
diff --git a/docs/readme-espressif.md b/docs/readme-espressif.md
index fa72fb3..2e9c277 100644
--- a/docs/readme-espressif.md
+++ b/docs/readme-espressif.md
@@ -1,25 +1,24 @@
-# Building and using MCUboot with Espressif's chips
+# [Building and using MCUboot with Espressif's chips](#building-and-using-mcuboot-with-espressifs-chips)
The Espressif port is build on top of ESP-IDF HAL, therefore it is required in order to build MCUboot for Espressif SoCs.
Documentation about the MCUboot bootloader design, operation and features can be found in the [design document](design.md).
-## SoC support availability
+## [SoC support availability](#soc-support-availability)
The current port is available for use in the following SoCs within the OSes:
-- ESP32
- - Zephyr RTOS - _WIP_
- - NuttX
-- ESP32-S2
- - Zephyr RTOS - _WIP_
- - NuttX - _WIP_
-## Installing Requirements and Dependencies
+| | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 |
+| :-----: | :-----: | :-----: | :-----: | :-----: |
+| Zephyr | Supported | Supported | Supported | WIP |
+| NuttX | Supported | Supported | Supported | WIP |
+
+## [Installing requirements and dependencies](#installing-requirements-and-dependencies)
1. Install additional packages required for development with MCUboot:
```
- cd ~/mcuboot # or to your directory where mcuboot is cloned
+ cd ~/mcuboot # or to your directory where MCUboot is cloned
pip3 install --user -r scripts/requirements.txt
```
@@ -29,7 +28,7 @@
git submodule update --init --recursive --checkout boot/espressif/hal/esp-idf
```
-3. Next, get the mbedtls submodule required by MCUboot.
+3. Next, get the Mbed TLS submodule required by MCUboot.
```
git submodule update --init --recursive ext/mbedtls
```
@@ -42,29 +41,353 @@
cd ../..
```
-## Building the bootloader itself
+## [Building the bootloader itself](#building-the-bootloader-itself)
The MCUboot Espressif port bootloader is built using the toolchain and tools provided by ESP-IDF. Additional configuration related to MCUboot features and slot partitioning may be made using the `bootloader.conf`.
-**Note:** Replace `<target>` with the target ESP32 family (like `esp32`, `esp32s2` and others).
+---
+***Note***
+
+*Replace `<TARGET>` with the target ESP32 family (like `esp32`, `esp32s2` and others).*
+
+---
1. Compile and generate the ELF:
```
-cmake -DCMAKE_TOOLCHAIN_FILE=tools/toolchain-<target>.cmake -DMCUBOOT_TARGET=<target> -B build -GNinja
+cmake -DCMAKE_TOOLCHAIN_FILE=tools/toolchain-<TARGET>.cmake -DMCUBOOT_TARGET=<TARGET> -B build -GNinja
cmake --build build/
```
2. Convert the ELF to the final bootloader image, ready to be flashed:
```
-esptool.py --chip <target> elf2image --flash_mode dio --flash_freq 40m -o build/mcuboot_<target>.bin build/mcuboot_<target>.elf
+esptool.py --chip <TARGET> elf2image --flash_mode dio --flash_freq 40m --flash_size <FLASH_SIZE> -o build/mcuboot_<TARGET>.bin build/mcuboot_<TARGET>.elf
```
-3. Flash MCUboot in your board:
+3. Flash MCUboot in your device:
```
-esptool.py -p <PORT> -b <BAUD> --before default_reset --after hard_reset --chip <target> write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 build/mcuboot_<target>.bin
+esptool.py -p <PORT> -b <BAUD> --before default_reset --after hard_reset --chip <TARGET> write_flash --flash_mode dio --flash_size <FLASH_SIZE> --flash_freq 40m <BOOTLOADER_FLASH_OFFSET> build/mcuboot_<TARGET>.bin
+```
+---
+***Note***
+You may adjust the port `<PORT>` (like `/dev/ttyUSB0`) and baud rate `<BAUD>` (like `2000000`) according to the connection with your board.
+You can also skip `<PORT>` and `<BAUD>` parameters so that esptool tries to automatically detect it.
+
+*`<FLASH_SIZE>` can be found using the command below:*
+```
+esptool.py -p <PORT> -b <BAUD> flash_id
+```
+The output contains device information and its flash size:
+```
+Detected flash size: 4MB
```
-You may adjust the port `<PORT>` (like `/dev/ttyUSB0`) and baud rate `<BAUD>` (like `2000000`) according to the connection with your board.
+
+*`<BOOTLOADER_FLASH_OFFSET>` value must follow one of the addresses below:*
+| ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 |
+| :-----: | :-----: | :-----: | :-----: |
+| 0x1000 | 0x1000 | 0x0000 | 0x0000 |
+
+---
+
+## [Signing and flashing an application](#signing-and-flashing-an-application)
+
+1. Images can be regularly signed with the `scripts/imgtool.py` script:
+
+```
+imgtool.py sign --align 4 -v 0 -H 32 --pad-header -S <SLOT_SIZE> <BIN_IN> <SIGNED_BIN>
+```
+
+---
+
+***Note***
+`<SLOT_SIZE>` is the size of the slot to be used.
+Default slot0 size is `0x100000`, but it can change as per application flash partitions.
+
+For Zephyr images, `--pad-header` is not needed as it already has the padding for MCUboot header.
+
+---
+
+:warning: ***ATTENTION***
+
+*This is the basic signing needed for adding MCUboot headers and trailers.
+For signing with a crypto key and guarantee the authenticity of the image being booted, see the section [MCUboot image signature verification](#mcuboot-image-signature-verification) below.*
+
+---
+
+2. Flash the signed application:
+
+```
+esptool.py -p <PORT> -b <BAUD> --before default_reset --after hard_reset --chip <TARGET> write_flash --flash_mode dio --flash_size <FLASH_SIZE> --flash_freq 40m <SLOT_OFFSET> <SIGNED_BIN>
+```
+
+# [Security Chain on Espressif port](#security-chain-on-espressif-port)
+
+[MCUboot encrypted images](encrypted_images.md) do not provide full code confidentiality when only external storage is available (see [Threat model](encrypted_images.md#threat-model)) since by MCUboot design the image in Primary Slot, from where the image is executed, is stored plaintext.
+Espressif chips have off-chip flash memory, so to ensure a security chain along with MCUboot image signature verification, the hardware-assisted Secure Boot and Flash Encryption were made available on the MCUboot Espressif port.
+
+## [MCUboot image signature verification](#mcuboot-image-signature-verification)
+
+The image that MCUboot is booting can be signed with 4 types of keys: RSA-2048, RSA-3072, EC256 and ED25519. In order to enable the feature, the **bootloader** must be compiled with the following configurations:
+
+---
+***Note***
+*It is strongly recommended to generate a new signing key using `imgtool` instead of use the existent samples.*
+
+---
+
+#### For EC256 algorithm use
+```
+CONFIG_ESP_SIGN_EC256=y
+
+# Use Tinycrypt lib for EC256 or ED25519 signing
+CONFIG_ESP_USE_TINYCRYPT=y
+
+CONFIG_ESP_SIGN_KEY_FILE=<YOUR_SIGNING_KEY.pem>
+```
+
+#### For ED25519 algorithm use
+```
+CONFIG_ESP_SIGN_ED25519=y
+
+# Use Tinycrypt lib for EC256 or ED25519 signing
+CONFIG_ESP_USE_TINYCRYPT=y
+
+CONFIG_ESP_SIGN_KEY_FILE=<YOUR_SIGNING_KEY.pem>
+```
+
+#### For RSA (2048 or 3072) algorithm use
+```
+CONFIG_ESP_SIGN_RSA=y
+# RSA_LEN is 2048 or 3072
+CONFIG_ESP_SIGN_RSA_LEN=<RSA_LEN>
+
+# Use Mbed TLS lib for RSA image signing
+CONFIG_ESP_USE_MBEDTLS=y
+
+CONFIG_ESP_SIGN_KEY_FILE=<YOUR_SIGNING_KEY.pem>
+```
+
+Notice that the public key will be embedded in the bootloader code, since the hardware key storage is not supported by Espressif port.
+
+### [Signing the image](#signing-the-image)
+
+Now you need to sign the **image binary**, use the `imgtool` with `-k` parameter:
+
+```
+imgtool.py sign -k <YOUR_SIGNING_KEY.pem> --pad --pad-sig --align 4 -v 0 -H 32 --pad-header -S 0x00100000 <BIN_IN> <BIN_OUT>
+```
+If signing a Zephyr image, the `--pad-header` is not needed, as it already have the padding for MCUboot header.
+
+
+## [Secure Boot](#secure-boot)
+
+The Secure Boot implementation is based on [IDF's Secure Boot V2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/security/secure-boot-v2.html), is hardware-assisted and RSA based, and has the role for ensuring that only authorized code will be executed on the device. This is done through bootloader signature checking by the ROM bootloader. \
+***Note***: ROM bootloader is the First Stage Bootloader, while the Espressif MCUboot port is the Second Stage Bootloader.
+
+### [Building bootloader with Secure Boot](#building-bootloader-with-secure-boot)
+
+In order to build the bootloader with the feature on, the following configurations must be enabled:
+```
+CONFIG_SECURE_BOOT=1
+CONFIG_SECURE_BOOT_V2_ENABLED=1
+CONFIG_SECURE_SIGNED_ON_BOOT=1
+CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1
+CONFIG_SECURE_BOOT_SUPPORTS_RSA=1
+```
+
+---
+:warning: ***ATTENTION***
+
+*On development phase is recommended add the following configuration in order to keep the debugging enabled and also to avoid any unrecoverable/permanent state change:*
+```
+CONFIG_SECURE_BOOT_ALLOW_JTAG=1
+CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=1
+
+# Options for enabling eFuse emulation in Flash
+CONFIG_EFUSE_VIRTUAL=1
+CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH=1
+```
+
+---
+
+Once the **bootloader image** is built, the resulting binary file is required to be signed with `espsecure.py` tool.
+
+First create a signing key:
+```
+espsecure.py generate_signing_key --version 2 <BOOTLOADER_SIGNING_KEY.pem>
+```
+
+Then sign the bootloader image:
+```
+espsecure.py sign_data --version 2 --keyfile <BOOTLOADER_SIGNING_KEY.pem> -o <BOOTLOADER_BIN_OUT> <BOOTLOADER_BIN_IN>
+```
+
+---
+:warning: ***ATTENTION***
+
+*Once the bootloader is flashed and the device resets, the **first boot will enable Secure Boot** and the bootloader and key **no longer can be modified**. So **ENSURE** that both bootloader and key are correct and you did not forget anything before flashing.*
+
+---
+
+Flash the bootloader as following, with `--after no_reset` flag, so you can reset the device only when assured:
+```
+esptool.py -p <PORT> -b 2000000 --after no_reset --chip <ESP_CHIP> write_flash --flash_mode dio --flash_size <FLASH_SIZE> --flash_freq 40m <BOOTLOADER_FLASH_OFFSET> <SIGNED_BOOTLOADER_BIN>
+```
+
+### [Secure Boot Process](#secure-boot-process)
+
+Secure boot uses a signature block appended to the bootloader image in order to verify the authenticity. The signature block contains the RSA-3072 signature of that image and the RSA-3072 public key.
+
+On its **first boot** the Secure Boot is not enabled on the device eFuses yet, neither the key nor digests. So the first boot will have the following process:
+
+1. On startup, since it is the first boot, the ROM bootloader will not verify the bootloader image (the Secure Boot bit in the eFuse is disabled) yet, so it proceeds to execute it (our MCUboot bootloader port).
+2. Bootloader calculates the SHA-256 hash digest of the public key and writes the result to eFuse.
+3. Bootloader validates the application images and prepare the booting process (MCUboot phase).
+4. Bootloader burns eFuse to enable Secure Boot V2.
+5. Bootloader proceeds to load the Primary image.
+
+After that the Secure Boot feature is permanently enabled and on every next boot the ROM bootloader will verify the MCUboot bootloader image.
+The process of an usual boot:
+
+1. On startup, the ROM bootloader checks the Secure Boot enable bit in the eFuse. If it is enabled, the boot will proceed as following.
+2. ROM bootloader verifies the bootloader's signature block integrity (magic number and CRC). Interrupt boot if it fails.
+3. ROM bootloader verifies the bootloader image, interrupt boot if any step fails.: \
+3.1. Compare the SHA-256 hash digest of the public key embedded in the bootloader’s signature block with the digest saved in the eFuses. \
+3.2. Generate the application image digest and match it with the image digest in the signature block. \
+3.3. Use the public key to verify the signature of the bootloader image, using RSA-PSS with the image digest calculated from previous step for comparison.
+4. ROM bootloader executes the bootloader image.
+5. Bootloader does the usual verification (MCUboot phase).
+6. Proceeds to boot the Primary image.
+
+## [Flash Encryption](#flash-encryption)
+
+The Espressif Flash Encryption is hardware-assisted, transparent to the MCUboot process and is an additional security measure beyond MCUboot existent features.
+The Flash Encryption implementation is also based on [IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/security/flash-encryption.html) and is intended for encrypting off-chip flash memory contents, so it is protected against physical reading.
+
+When enabling the Flash Encryption, the user can encrypt the content either using a **device generated key** (remains unknown and unreadable) or a **host generated key** (owner is responsible for keeping the key private and safe). After the flash encryption gets enabled through eFuse burning on the device, all read and write operations are decrypted/encrypted in runtime.
+
+### [Building bootloader with Flash Encryption](#building-bootloader-with-flash-encryption)
+
+In order to build the bootloader with the feature on, the following configurations must be enabled:
+
+For **release mode**:
+```
+CONFIG_SECURE_FLASH_ENC_ENABLED=1
+CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE=1
+```
+
+For **development mode**:
+```
+CONFIG_SECURE_FLASH_ENC_ENABLED=1
+CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=1
+```
+:warning: ***ATTENTION***
+
+*On development phase is strongly recommended adding the following configuration in order to keep the debugging enabled and also to avoid any unrecoverable/permanent state change:*
+```
+CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=1
+CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=1
+CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=1
+CONFIG_SECURE_BOOT_ALLOW_JTAG=1
+
+# Options for enabling eFuse emulation in Flash
+CONFIG_EFUSE_VIRTUAL=1
+CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH=1
+```
+
+---
+:warning: ***ATTENTION***
+
+*Unless the recommended flags for **DEVELOPMENT MODE** were enabled, the actions made by Flash Encryption process are **PERMANENT**.* \
+*Once the bootloader is flashed and the device resets, the **first boot will enable Flash Encryption, encrypt the flash content including bootloader and image slots, burn the eFuses that no longer can be modified** and if device generated the key **it will not be recoverable**.* \
+*When on **RELEASE MODE**, **ENSURE** that the application with an update agent is flashed before reset the device.*
+
+---
+
+### [Signing the image when working with Flash Encryption](#signing-the-image-when-working-with-flash-encryption)
+
+When enabling flash encryption, it is required to signed the image using 32-byte alignment: `--align 32 --max-align 32`.
+
+Command example:
+```
+imgtool.py sign -k <YOUR_SIGNING_KEY.pem> --pad --pad-sig --align 32 --max-align 32 -v 0 -H 32 --pad-header -S <SLOT_SIZE> <BIN_IN> <BIN_OUT>
+```
+
+### [Device generated key](#device-generated-key)
+
+First ensure that the application image is able to perform encrypted read and write operations to the SPI Flash.
+Flash the bootloader and application normally:
+
+```
+esptool.py -p <PORT> -b 2000000 --after no_reset --chip <ESP_CHIP> write_flash --flash_mode dio --flash_size <FLASH_SIZE> --flash_freq 40m <BOOTLOADER_FLASH_OFFSET> <BOOTLOADER_BIN>
+```
+```
+esptool.py -p <PORT> -b 2000000 --after no_reset --chip <ESP_CHIP> write_flash --flash_mode dio --flash_size <FLASH_SIZE> --flash_freq 40m <PRIMARY_SLOT_FLASH_OFFSET> <APPLICATION_BIN>
+```
+
+On the **first boot**, the bootloader will:
+1. Generate Flash Encryption key and write to eFuse.
+2. Encrypt flash in-place including bootloader, image primary/secondary slot and scratch.
+3. Burn eFuse to enable Flash Encryption.
+4. Reset system to ensure Flash Encryption cache resets properly.
+
+### [Host generated key](#host-generated-key)
+
+First ensure that the application image is able to perform encrypted read and write operations to the SPI Flash.
+Before flashing, generate the encryption key using `espsecure.py` tool:
+```
+espsecure.py generate_flash_encryption_key <FLASH_ENCRYPTION_KEY.bin>
+```
+
+Burn the key into the device's eFuse, this action can be done **only once**:
+
+---
+:warning: ***ATTENTION***
+
+*eFuse emulation in Flash configuration options do not have any effect, so if the key burning command is used, it will actually burn the physical eFuse.*
+
+---
+
+- ESP32
+```
+espefuse.py --port PORT burn_key flash_encryption <FLASH_ENCRYPTION_KEY.bin>
+```
+
+- ESP32S2, ESP32C3 and ESP32S3
+```
+espefuse.py --port PORT burn_key BLOCK <FLASH_ENCRYPTION_KEY.bin> <KEYPURPOSE>
+```
+
+BLOCK is a free keyblock between BLOCK_KEY0 and BLOCK_KEY5. And KEYPURPOSE is either XTS_AES_128_KEY, XTS_AES_256_KEY_1, XTS_AES_256_KEY_2 (AES XTS 256 is available only in ESP32S2).
+
+Now, similar as the Device generated key, the bootloader and application can be flashed plaintext. The **first boot** will encrypt the flash content using the host key burned in the eFuse instead of generate a new one.
+
+Flashing the bootloader and application:
+
+```
+esptool.py -p <PORT> -b 2000000 --after no_reset --chip <ESP_CHIP> write_flash --flash_mode dio --flash_size <FLASH_SIZE> --flash_freq 40m <BOOTLOADER_FLASH_OFFSET> <BOOTLOADER_BIN>
+```
+```
+esptool.py -p <PORT> -b 2000000 --after no_reset --chip <ESP_CHIP> write_flash --flash_mode dio --flash_size <FLASH_SIZE> --flash_freq 40m <PRIMARY_SLOT_FLASH_OFFSET> <APPLICATION_BIN>
+```
+
+On the **first boot**, the bootloader will:
+1. Encrypt flash in-place including bootloader, image primary/secondary slot and scratch using the written key.
+2. Burn eFuse to enable Flash Encryption.
+3. Reset system to ensure Flash Encryption cache resets properly.
+
+## [Security Chain scheme](#security-chain-scheme)
+
+Using the 3 features, Secure Boot, Image signature verification and Flash Encryption, a Security Chain can be established so only trusted code is executed, and also the code and content residing in the off-chip flash are protected against undesirable reading.
+
+The overall final process when all features are enabled:
+1. ROM bootloader validates the MCUboot bootloader using RSA signature verification.
+2. MCUboot bootloader validates the image using the chosen algorithm EC256/RSA/ED25519. It also validates an upcoming image when updating.
+3. Flash Encryption guarantees that code and data are not exposed.
+
+### [Size Limitation](#size-limitation)
+
+When all 3 features are enable at same time, the bootloader size may exceed the fixed limit for the ROM bootloader checking on the Espressif chips **depending on which algorithm** was chosen for MCUboot image signing. The issue https://github.com/mcu-tools/mcuboot/issues/1262 was created to track this limitation.
\ No newline at end of file
diff --git a/docs/readme-riot.md b/docs/readme-riot.md
index 9bb1b9b..3aba53b 100644
--- a/docs/readme-riot.md
+++ b/docs/readme-riot.md
@@ -15,7 +15,7 @@
In the next version, it is planned to compile MCUboot using RIOT,
which should be able to boot any of the supported OS images.
-## Building Applications for the bootloader
+## Building applications for the bootloader
A compatible MCUboot image can be compiled by typing: `make mcuboot`.
diff --git a/docs/readme-zephyr.md b/docs/readme-zephyr.md
index 26bc519..ea18fe9 100644
--- a/docs/readme-zephyr.md
+++ b/docs/readme-zephyr.md
@@ -30,12 +30,12 @@
`boards/arm/frdm_k64f/frdm_k64f.dts`. Make sure the labels in your board's
`.dts` file match the ones used there.
-## Installing Requirements and Dependencies
+## Installing requirements and dependencies
-Install additional packages required for development with mcuboot:
+Install additional packages required for development with MCUboot:
```
- cd ~/mcuboot # or to your directory where mcuboot is cloned
+ cd ~/mcuboot # or to your directory where MCUboot is cloned
pip3 install --user -r scripts/requirements.txt
```
@@ -71,10 +71,10 @@
system `flash` target to flash these binaries, usually by running
`make flash` (or `ninja flash`, etc.) from the build directory. Depending
on the target and flash tool used, this might erase the whole of the flash
-memory (mass erase) or only the sectors where the boot loader resides prior to
+memory (mass erase) or only the sectors where the bootloader resides prior to
programming the bootloader image itself.
-## Building Applications for the bootloader
+## Building applications for the bootloader
In addition to flash partitions in DTS, some additional configuration
is required to build applications for MCUboot.
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 885fe31..43af557 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -1,8 +1,40 @@
-# MCUboot Release Notes
+# MCUboot release notes
- Table of Contents
{:toc}
+## Version 1.9.0
+
+The 1.9.0 release of MCUboot contains various bug fixes, improves
+support on some recent targets, and adds support for devices with a
+write alignment larger than 8.
+
+This change introduces a potentially incompatible change to the format
+of the image trailer. If `BOOT_MAX_ALIGN` is kept at 8, the trailer
+format does not change. However, to support larger write alignments,
+this value can be increased, which will result in a different magic
+number value. These targets were previously unsupported in MCUboot,
+so this change should not affect any existing targets. The change has
+been tested with a `BOOT_MAX_ALIGN` up to 32 bytes.
+
+### About this release
+
+- Add native flash encryption to Espressif targets
+- Numerous documentation improvements
+- Increase coverage of large images in the simulator
+- Add stm32 watchdog support
+- Add support for the `mimxrt685_evk` board
+- Add support for "partial multi-image booting"
+- Add support for clear image generation with encryption capability to
+ imgtool
+- Fix Zephyr when `CONFIG_BOOT_ENCRYPTION_KEY_FILE` is not defined
+- Remove zephyr example test running in shell. The Go version is
+ primary and much more featureful.
+- imgtool: make `--max-align` default reasonable in most cases.
+- Implement the mcumgr echo command in serial boot mode
+
+### Security fixes
+
## Version 1.8.0
The 1.8.0 release of MCUboot contains numerous fixes, and adds support
@@ -20,8 +52,8 @@
brought in for another reason.
- Add simulator support for testing direct-XIP and ramload.
- Support Mbed TLS 3.0. Updates the submodule for Mbed TLS to 3.0.
-- Enable direct-xip mode in mbed-os port.
-- extract `bootutil_public` library, a common interface for mcuboot
+- Enable direct-xip mode in Mbed-OS port.
+- extract `bootutil_public` library, a common interface for MCUboot
and the application.
- Allow to boot primary image if secondary one is unreachable.
- Add AES256 image encryption support.
@@ -43,7 +75,7 @@
## Version 1.7.0
-The 1.7.0 release of MCUBoot adds support for the Mbed-OS platform,
+The 1.7.0 release of MCUboot adds support for the Mbed-OS platform,
Equal slots (direct-xip) upgrade mode, RAM loading upgrade mode,
hardening against hardware level fault injection and timing attacks
and single image mode.
@@ -52,7 +84,7 @@
### About this release
- Initial support for the Mbed-OS platform.
-- Added possibility to enter deep sleep mode after mcuboot app execution
+- Added possibility to enter deep sleep mode after MCUboot app execution
for cypress platform.
- Added hardening against hardware level fault injection and timing attacks.
- Introduced Abstract crypto primitives to simplify porting.
@@ -62,7 +94,7 @@
- Fixed boostrapping in swap-move mode.
- Fixed issue causing that interrupted swap-move operation might brick device
if the primary image was padded.
-- Abstracting mcuboot crypto functions for cleaner porting
+- Abstracting MCUboot crypto functions for cleaner porting
- Droped flash_area_read_is_empty() porting API.
- boot/zephyr: Added watchdog feed on nRF devices.
See `CONFIG_BOOT_WATCHDOG_FEED` option.
@@ -75,7 +107,7 @@
- imgtool: added possibility to set confirm flag for hex files as well.
- imgtool: Print image digest during verify.
-### Zephyr-RTOS Compatibility
+### Zephyr-RTOS compatibility
This release of MCUboot works with the Zephyr "main" at the time of the
release. It was tested as of has 7a3b253ce. This version of MCUboot also
@@ -111,7 +143,7 @@
2.9.10 has an infinite loop in a certain end-of-file situation." Fix
by updating a dependency in documentation generation.
-### Zephyr-RTOS Compatibility
+### Zephyr-RTOS compatibility
This release of MCUboot works the Zephyr "main" at the time of the
release. It was tested as of has 1a89ca1238. When Zephyr v2.3.0 is
@@ -134,7 +166,7 @@
should work with no changes for little-endian targets, but will
break compatibility with big-endian targets.
- A benchmark framework was added to Zephyr
-- ed25519 signature validation can now build without using mbedTLS
+- ed25519 signature validation can now build without using Mbed TLS
by relying on a bundled tinycrypt based sha-512 implementation.
- imgtool was updated to correctly detect trailer overruns by image.
- Encrypted image TLVs can be saved in swap metadata during a swap
@@ -169,8 +201,8 @@
- Numerous code cleanups and refactorings
- Documentation updates for multi-image features
- Update imgtool.py to support the new features
-- Updated the mbed TLS submodule to current stable version 2.16.3
-- Moved the mbed TLS submodule from within sim/mcuboot-sys to ext.
+- Updated the Mbed TLS submodule to current stable version 2.16.3
+- Moved the Mbed TLS submodule from within sim/mcuboot-sys to ext.
This will make it easier for other board supports to use this code.
- Added some additional overflow and bound checks to data in the image
header, and TLV data.
@@ -236,7 +268,7 @@
The 1.2.0 release of MCUboot brings a lot of fixes/updates, where much of the
changes were on the boot serial functionality and imgtool utility. There are
-no breaking changes in MCUBoot functionality, but some of the CLI parameters
+no breaking changes in MCUboot functionality, but some of the CLI parameters
in imgtool were changed (either removed or added or updated).
### About this release
@@ -281,8 +313,8 @@
of ecdsa (secp256r1) was added
- imgtool: removed PKCS1.5 support, added support for password
protected keys
-- tinycrypt 0.2.8 and the mbed-tls ASN1 parser are now bundled with
- mcuboot (eg secp256r1 is now free of external dependencies!)
+- tinycrypt 0.2.8 and the Mbed TLS ASN1 parser are now bundled with
+ MCUboot (eg secp256r1 is now free of external dependencies!)
- Overwrite-only mode was updated to erase/copy only sectors that
actually store firmware
- A lot of small code and documentation fixes and updates.
@@ -358,12 +390,12 @@
- An overwrite only which upgrades slot 0 with the image in slot 1.
- A swapping upgrade which enables image test, allowing for rollback to a
previous known good image.
-- Supports both mbed-TLS and tinycrypt as backend crypto libraries. One of them
+- Supports both Mbed TLS and tinycrypt as backend crypto libraries. One of them
must be defined and the chosen signing algorithm will require a particular
library according to this list:
- - RSA 2048 needs mbed TLS
- - ECDSA secp224r1 needs mbed TLS
- - ECDSA secp256r1 needs tinycrypt as well as the ASN.1 code from mbed TLS
+ - RSA 2048 needs Mbed TLS
+ - ECDSA secp224r1 needs Mbed TLS
+ - ECDSA secp256r1 needs tinycrypt as well as the ASN.1 code from Mbed TLS
(so still needs that present).
### Known issues
diff --git a/docs/release.md b/docs/release.md
index 90c32b5..170c9b8 100644
--- a/docs/release.md
+++ b/docs/release.md
@@ -1,91 +1,94 @@
-# Release Process
+# Release process
-The following documents the release process used with mcuboot.
+This page describes the release process used with MCUboot.
## Version numbering
MCUboot uses [semantic versioning][semver], where version numbers
-follow a MAJOR.MINOR.PATCH format with the following guidelines on
-incremeting the numbers:
+follow a `MAJOR.MINOR.PATCH` format with the following guidelines on
+incrementing the numbers:
-1. MAJOR version when you make incompatible API changes,
-2. MINOR version when you add functionality in a backwards-compatible
- manner, and
-3. PATCH version when you make backwards-compatible bug fixes.
+1. MAJOR version when there are incompatible API changes.
+2. MINOR version when new functionalities were added in a
+ backward-compatible manner.
+3. PATCH version when there are backward-compatible bug fixes.
-We add pre-release tags of the format MAJOR.MINOR.PATCH-rc1.
+We add pre-release tags using the format `MAJOR.MINOR.PATCH-rc1`.
-We mark in documentation an MCUBoot development version using
-the format MAJOR.MINOR.PATCH-dev.
+In the documentation, we mark an MCUBoot development version using the
+format `MAJOR.MINOR.PATCH-dev`.
-## Release Notes
+## Release notes
-Before making a release, be sure to update the `docs/release-notes.md`
-to describe the release. This should be a high-level description of
+Before making a release, update the `docs/release-notes.md` file
+to describe the release. This should be a high-level description of
the changes, not a list of the git commits.
-## Release Candidates
+## Release candidates
-Prior to each release, tags are made (see below) for at least one
-release candidate (a.b.c-rc1, followed by a.b.c-rc2, etc, followed by
-the official a.b.c release). The intent is to freeze the code for a
-time, and allow testing to happen.
+Before each release, tags are made (see below) for at least one
+release candidate (a.b.c-rc1, followed by a.b.c-rc2 and the subsequent
+release candidates, followed by the official a.b.c release). The intent
+is to freeze the code and allow testing.
-During the time between rc1 and the final release, the only changes
-that should be merged into main are those to fix bugs found in the
-rc and Mynewt metadata as described in the next section.
+During the time between the rc1 and the final release, the only changes
+that should be merged into the main branch are those to fix bugs found
+in the RC and in the Mynewt metadata, as described in the next section.
-## imgtool release
+## Imgtool release
-imgtool is released through pypi.org (The Python package index) and
-requires that its version to be updated by editing
+imgtool is released through pypi.org (The Python package index).
+It requires its version to be updated by editing
`scripts/imgtool/__init__.py` and modifying the exported version:
+```
+imgtool_version = "A.B.CrcN"
+```
-`imgtool_version = "A.B.CrcN"`
+This version should match the current release number of MCUboot. The
+suffix `rcN` (with no dash) is accepted only for the pre-release versions
+under test, while numbers are accepted only for the final releases.
-This version should match the current release number of MCUboot; `rcN`
-(with no dash!) is accepted for pre-release version under test, and
-numbers only for final releases. For more info see:
-
-https://www.python.org/dev/peps/pep-0440/#pre-releases
+For more information, see [this
+link](https://www.python.org/dev/peps/pep-0440/#pre-releases).
## Mynewt release information
-On Mynewt, `newt` always fetches a versioned MCUBoot release, so after
-the rc step is finished, the release needs to be exported by modifying
+On Mynewt, `newt` always fetches a versioned MCUboot release, so after
+the RC step is finished, the release needs to be exported by modifying
`repository.yml` in the root directory; it must be updated with the
new release version, including updates to the pseudo keys
(`*-(latest|dev)`).
-## Tagging and Release
+## Tagging and release
To make a release, make sure your local repo is on the tip version by
-fetching from origin. Typically, the releaser should create a branch
+fetching from origin. Typically, the releaser should create a branch
named after the particular release.
Create a commit on top of the branch that modifies the version number
in the top-level `README.md`, and create a commit, with just this
-change, with a commit text similar to “Bump to version
-a.b.c”. Having the version bump helps to make the releases
+change, with a commit text similar to "Bump to version a.b.c".
+Having the version bump helps to make the releases
easier to find, as each release has a commit associated with it, and
not just a tag pointing to another commit.
-Once this is done, the release should create a signed tag:
+Once this is done, the release should create a signed tag with the
+appropriate tag name:
``` bash
git tag -s va.b.c-rcn
```
-with the appropriate tag name. The releaser will need to make sure
-that git is configured to use the proper signing key, and that the
-public key is signed by enough parties to be trusted.
+The releaser will need to make sure that git is configured to use the
+proper signing key, and that the public key is signed by enough parties to
+be trusted.
-At this point, the tag can be pushed to github to make the actual
-release happen:
+At this point, the tag can be pushed to GitHub to make the actual release
+happen:
``` bash
git push origin HEAD:refs/heads/main
git push origin va.b.c-rcn
```
-## Branching after a Release
+## Branching after a release
After the final (non-`rc`) a.b.0 release is made, a new branch must
be created and pushed:
@@ -97,12 +100,13 @@
```
This branch will be used to generate new incremental `PATCH` releases
-for bug fixes or required minor updates (eg, new `imgtool` features).
+for bug fixes or required minor updates (for example, new `imgtool` features).
## Post release actions
-Mark the MCUBoot version as a development version. The version number used
-should be specified for the next expected release.
+Mark the MCUboot version as a development version.
+
+The version number used should be specified for the next expected release.
It should be larger than the last release version by incrementing the MAJOR or
the MINOR number. It is not necessary to define the next version precisely as
the next release version might still be different as it might be needed to do:
@@ -111,5 +115,4 @@
- a MINOR release while a MAJOR release was expected
- a MAJOR release while a MINOR release was expected
-
[semver]: http://semver.org/
diff --git a/docs/signed_images.md b/docs/signed_images.md
index 22a6836..c1edcfb 100644
--- a/docs/signed_images.md
+++ b/docs/signed_images.md
@@ -91,7 +91,7 @@
const int bootutil_key_cnt = sizeof(bootutil_keys) / sizeof(bootutil_keys[0]);
-## Building bootloader
+## Building the bootloader
Enable the BOOTUTIL_SIGN_RSA syscfg setting in your app or target syscfg.yml
file
diff --git a/docs/testplan-mynewt.md b/docs/testplan-mynewt.md
index 5a227b9..402a493 100644
--- a/docs/testplan-mynewt.md
+++ b/docs/testplan-mynewt.md
@@ -1,4 +1,4 @@
-## mcuboot test plan
+## MCUboot test plan
The current target for running the tests is the Freedom K64F board.
@@ -12,7 +12,7 @@
key_<sign-algo>.pem, key_<sign-algo>_2.pem. And a keys file with the C public
key data for key_<sign-algo>.pem.
-Build and load mcuboot:
+Build and load MCUboot:
* `newt build k64f_boot_<sign-algo>`
* `newt load k64f_boot_<sign-algo>`
@@ -22,11 +22,16 @@
* `newt create-image k64f_blinky 1.0.1 key_<sign-algo>.pem`
* `newt load k64f_blinky`
-NOTE: If testing RSA/PSS `newt create-image` needs to be passed in the extra
-flag `--rsa-pss` eg:
+---
+***Note***
+
+*If testing RSA/PSS `newt create-image` needs to be passed in the extra*
+*flag `--rsa-pss` eg:*
`newt create-image k64f_blinky 1.0.1 key_rsa.pem --rsa-pss`
+---
+
Build and load image in slot 1 with no signing, signed with
key_<sign-algo>_2.pem and signed with key_<sign-algo>.pem. Mark each one as
test image and check that swap only happens for image signed with
@@ -41,7 +46,7 @@
FIXME: this is currently not functional, skip this section!
-Build and load mcuboot:
+Build and load MCUboot:
* `newt build k64f_boot_rsa_ec`
* `newt load k64f_boot_rsa_ec`
@@ -68,7 +73,7 @@
### Overwrite only functionality
-Build/load mcuboot:
+Build/load MCUboot:
* `newt build k64f_boot_rsa_noswap`
* `newt load k64f_boot_rsa_noswap`
@@ -92,7 +97,7 @@
### Validate slot 0 option
-Build/load mcuboot:
+Build/load MCUboot:
* `newt build k64f_boot_rsa_validate0`
* `newt load k64f_boot_rsa_validate0`
@@ -120,7 +125,7 @@
DISCLAIMER: be careful with copy/paste of commands, this test uses another
target/app!
-Build/load mcuboot:
+Build/load MCUboot:
* `newt build k64f_boot_rsa`
* `newt load k64f_boot_rsa`
diff --git a/docs/testplan-zephyr.md b/docs/testplan-zephyr.md
index bd5b34b..9b70151 100644
--- a/docs/testplan-zephyr.md
+++ b/docs/testplan-zephyr.md
@@ -1,6 +1,6 @@
-# Zephyr Test Plan
+# Zephyr test plan
-The following roughly describes how mcuboot is tested on Zephyr. The
+The following roughly describes how MCUboot is tested on Zephyr. The
testing is done with the code in `samples/zephyr`. These examples
were written using the FRDM-K64F, but other boards should be similar.
At this time, however, the partitions are hardcoded in the Makefile