This patch adds the capability to check image dependencies in case
of multi-image boot. The dependencies are described with a new type
of TLV in the manifest.
Change-Id: If45f81a00d4324c881634f50156f9939e1bf8707
Signed-off-by: David Vincze <david.vincze@arm.com>
This patch adds the capability to handle multiple firmware images,
to update them independently. Also update the design documentation.
It separates the completion of aborted image swap operations and the
update of images even more as these should be happening at different
stages of the boot process according to the design proposal of
the multiple image support:
https://github.com/JuulLabs-OSS/mcuboot/pull/317.
Change-Id: I7eb5f632298bb08c805bfaee0359703b2ae19e9d
Signed-off-by: David Vincze <david.vincze@arm.com>
This patch introduces the BOOT_IMAGE_NUMBER macro and current_image
variable to support multiple updatable images and the associated
extended flash layout.
The FLASH_AREA_IMAGE_* object-like macros are replaced with
function-like ones and therefore some functions have been updated,
because the labels of a switch statement and the initialization
values of objects with static storage duration have to be constant
expressions.
Change-Id: Ib7b26ec3c94233e52db4f97825ddb6a3e55bb1d3
Signed-off-by: David Vincze <david.vincze@arm.com>
Overload the swap_type field in image trailer to store as an addition
the image sequence number. It indicates which image's swap was
interrupted. It is required by multi image boot to determine which
image the trailer belongs to if boot status is found on scratch area
when the swap operation is resumed.
Change-Id: I6820fd8277931aff4f0db408376eae8b42a030ed
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
Signed-off-by: David Vincze <david.vincze@arm.com>
When HW / OS provides an always enabled watchdog, this macro can
optionally be implemented to avoid resets which are expected to
occur under normal conditions when swapping very large images or
running on slower devices.
Signed-off-by: Fabio Utzig <utzig@apache.org>
There is a bug in split_go that never opens the loader image flash
area, but opens the app/split image flash arta twice. This prevents
split_image_check from passing and the app from ever loading.
Signed-off-by: Alvaro Prieto <source@alvaroprieto.com>
mbedTLS made sha256 functions that do not return errors deprecated. This
updates to use the new functions avoiding the extra functions calls, and
breakage when the deprecated calls are effectively removed.
Signed-off-by: Fabio Utzig <utzig@apache.org>
This fixes#480.
When mcuboot rewrites image trailers during a swap, some information is
lost. If a reset occurs before the swap completes, mcuboot may not be
able to determine what which swap type to resume upon startup.
Specifically, if a "revert" swap gets interupted, mcuboot will perform
an extraneous swap on the subsequent boot. See
https://github.com/JuulLabs-OSS/mcuboot/issues/480 for details.
This commit adds an additional field to the image trailer: `swap-type`.
The new trailer structure is illustrated below:
```
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ ~
~ Swap status (BOOT_MAX_IMG_SECTORS * min-write-size * 3) ~
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ Encryption key 0 (16 octets) [*] ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ Encryption key 1 (16 octets) [*] ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Swap size | 0xff padding (4 octets) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Swap type | 0xff padding (7 octets) ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Copy done | 0xff padding (7 octets) ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Image OK | 0xff padding (7 octets) ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ MAGIC (16 octets) ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```
The `swap-type` field contains one of the `BOOT_SWAP_TYPE_[...]` constants.
Every time a trailer is written, this field is written along with it.
When resuming an interrupted swap, mcuboot uses this field alone to
determine the type of swap being resumed. For new swap operations
(non-resume case), this field is not read at all; instead, mcuboot
consults the `boot_swap_tables` array to determine the swap operation to
perform (as it did prior to this commit).
Some additional changes were necessary to make all the simulated unit
tests pass:
* Before initiating a new swap operation, always write the image trailer
to the scratch area. This step allows mcuboot to persist the
`swap-type` field somewhere before erasing the trailer in the primary
slot. If a reset occurs immediately after the erase, mcuboot recovers
by using the trailer in the scratch area.
* Related to the above: if the scratch area is being used to hold status
bytes (because there are no spare sectors in the primary slot), erase
the scratch area immediately after the trailer gets written to the
primary slot. This eliminates ambiguity regarding the location of the
current trailer in case a reset occurs shortly afterwards.
Signed-off-by: Christopher Collins <ccollins@apache.org>
Prior to this change, the scratch image trailer had a different format
from a slot image trailer. Specifically:
1. The scratch trailer only contained a single set of status entries
(three bytes); the slot trailer contained `BOOT_STATUS_MAX_ENTRIES`
sets of status entries.
2. The scratch trailer did not contain the `copy_done` field.
This inconsistency required some extra conditional logic in the trailer
handling code. It is simpler to just use the same trailer format
everywhere.
This commit removes this inconsistency. Now, the scratch trailer
structure is identical to that of the slot trailer.
Signed-off-by: Christopher Collins <ccollins@apache.org>
In addition to the binary capability flags, add a query function that
returns the number of images MCUboot has been configured to support.
Signed-off-by: David Brown <david.brown@linaro.org>
The change
boot: bootutil: Simplify check for crypto backends to reduce complexity
Adding multiple crypto backends will grow quadraticly. This change will
ensure that the growth will be linear and generate less complexity.
unfortunately is not legal C. It can be fixed by eliminating the
intermediate macro, so that the `defined` keywords are within the `#if`.
Signed-off-by: David Brown <david.brown@linaro.org>
mcuboot tests are done under sim and there is no need to maintain
separate tests just for Mynewt. Especially that those no longer
compile nor are maintained.
Also Mynewt code will rather depend on release and not master so
there is no need to run those on Mynewt anyway.
Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
Adding multiple crypto backends will grow quadraticly. This change will
ensure that the growth will be linear and generate less complexity.
Signed-off-by: Sigvart Hovland <sigvart.m@gmail.com>
The bootutil unit tests fail to build with the following error:
Testing package @mcuboot/boot/bootutil/test
Unsatisfied APIs detected:
* log, required by: sys/log/modlog
This commit adds a `sys/log/stub` dependency to the bootutil unit test
package.
NOTE: This unit test package still fails to build because the code is
out of date. This commit just fixes one of several issues.
Signed-off-by: Christopher Collins <ccollins@apache.org>
This change only affects the Mynewt port.
Prior to this commit, the `FLASH_AREA_IMAGE_{PRIMARY,SECONDARY}` macros
were private to the bootutil package (defined in `bootutil_priv.h`).
Some other packages require these symbols (e.g., the boot_serial unit
tests), so they should be made public.
This commit moves these definitions into the public `bootutil.h` header.
Signed-off-by: Christopher Collins <ccollins@apache.org>
boot_enc_valid() is supposed to return boolena so
changed it return type in order to reflect this.
Signed-off-by: Andrzej Puzdrowski <andrzej.puzdrowski@nordicsemi.no>
enc_state table was indexed with assumption that
image flash area are subsequent and increasing numbers.
It might not be true while building zephyr.
Patch introduce flash_area_id_to_image_slot() implementation for
the zephyr port and uses it to assign proper slot number.
This API is already available in MyNewt.
Signed-off-by: Andrzej Puzdrowski <andrzej.puzdrowski@nordicsemi.no>
This change replaces the slot 0/1 terminology with primary/secondary
slot and replaces FLASH_AREA_IMAGE_0/1 with
FLASH_AREA_IMAGE_PRIMARY/SECONDARY. This naming convention may be more
understandable, fits better to MCUs with multiple images and it is an
architecture agnostic alternative as well.
Change-Id: I655a585f6ae023852c671ee6635399efe25209c9
Signed-off-by: David Vincze <david.vincze@arm.com>
Signed-off-by: David Brown <david.brown@linaro.org>
This change affects the "set pending" operation. That is, the operation
that configures mcuboot to temporarily swap images on the next boot.
PRIOR TO COMMIT:
If the slot 1 trailer contained an invalid 128-bit magic number, an
assertion would fail, causing a crash.
AFTER COMMIT:
If corruption is detected in the slot 1 trailer, the entire image slot
is erased, and the "set pending" operation fails with a `BOOT_EBADIMAGE`
status.
RATIONALE:
mcuboot cannot meaningfully recover from data corruption. The only
recourse is to erase the bad data so that future upgrades can be
performed. I was tempted to add a build-time setting to control whether
the image slot gets erased when corruption is detected, but I dont think this
freedom justifies the cost of extra config. A device with a corrupt
image slot can no longer be upgraded, so the only reason someone would
want to preserve the corrupt data would be for debugging.
Signed-off-by: Christopher Collins <ccollins@apache.org>
Previously it was assumed that the trailer would fit one sector. While
this works for most devices, some which happen to have lots of sectors
end up using lots of space for their swap status area. The same issue
could also happen if sectors are small (less than 2K/4K, for example).
This fixes the issue by checking the trailer size and erasing all
sectors that encompass it.
Signed-off-by: Fabio Utzig <utzig@apache.org>
While loading a new EC point, when it was smaller than the expected
number of bytes, a zero padding was being written beyond the end of the
buffer instead of at the initial position.
While this has been working before, it broke when images were signed using
the ring API.
Signed-off-by: Fabio Utzig <utzig@apache.org>
The old log subsystem has been deprecated in Zephyr.
Migrate to the new subsystem to avoid compilation warnings.
In-place log processing is selected as it is required as MCUBoot is
one thread application.
Signed-off-by: Emanuele Di Santo <emdi@nordicsemi.no>
Signed-off-by: Andrzej Puzdrowski <andrzej.puzdrowski@nordicsemi.no>
Remove unnused BOOT_LOG_LEVEL macros.
These are not honored, nor usable since they are supposed to be
defined before including the header in which they are defined.
Signed-off-by: Emanuele Di Santo <emdi@nordicsemi.no>
The mcuboot_logging.h header includes the header for the log subystem,
which needs to be included regardless of whether logging is enabled
for logging macros to compile correctly.
Signed-off-by: Emanuele Di Santo <emdi@nordicsemi.no>
As reported by issue #384, some #ifdefery was wrongly done, which broke
overwrite-only mode under Zephyr.
Signed-off-by: Fabio Utzig <utzig@apache.org>
Mynewt builds require the `mcuboot_config.h` file to translate syscfg
setting names to MCUboot setting names. This change fixes a build error
that occurs when MCUboot is built with mbedTLS support:
Error: In file included from keys/bootkeys/src/bootkeys.c:2:0:
repos/mcuboot/boot/bootutil/include/bootutil/enc_key.h:29:10: fatal error: tinycrypt/aes.h: No such file or directory
#include "tinycrypt/aes.h"
^~~~~~~~~~~~~~~~~
Signed-off-by: Christopher Collins <ccollins@apache.org>
This implements AES key unwrapping following RFC-3394 section 2.2.2
using tinycrypt for AES-128 decryption. It is enabled when ECDSA was
chosen as the signature algorithm.
Signed-off-by: Fabio Utzig <utzig@apache.org>
This adds a new option that allows copying slot0, from the contents
of slot1, if slot0 is found out to be erased and not validated, and
the contents of slot1 are validated.
This mechanism basically enables a device to "bootstrap" from the
contents of an external flash that has a valid image, given that the
only flashed thing in the internal flash is the bootloader.
Signed-off-by: Fabio Utzig <utzig@apache.org>
This adds bootutil support for slots on different flash devices
the happen to have different sector sizes.
It consists basically in relaxing the `boot_slots_compatible` to
allow swaps as long as the sectors that are required to fit both
images are able to fit inside scratch and both slot's sectors have
sizes that are multiple of each other.
This is now tested on the simulator and was tested in a Nordic's
pca10056 using slot0 in internal flash, and slot1 in the external
QSPI flash, configured with 4K, 8K and 16K sized sectors (the HW
is 4KB but Mynewt allows emulating multiples of that!)
Signed-off-by: Fabio Utzig <utzig@apache.org>
Encrypted images were known to be failing when the header size was larger
than 256 bytes because of incorrect handling of blocks sent to decryption
and hashing routines. An assert was previously added to check the header
and read block sizes matched to avoid incurring into the know error, but
it was incorrectly enabled also for non-encrypted images.
Now the handling of the header, which is not encrypted, is correctly
separated from the handling of the remaining image, when encryption is
used, to avoid ever sending header data into the decryption routines.
Signed-off-by: Fabio Utzig <utzig@apache.org>
This allows storing encrypted images in slot1, that are automatically
decrypted when copying to slot0 and re-encrypted when copying from slot0
to slot1.
The encryption works by applying AES-CTR-128 on the image blocks
(excluding the header and TLVs) using a random key. This random key
is itself encrypted using either RSA-OAEP-2048 or AES-KW-128 (AES keywrap
as defined by RFC3394), and appended to the image as newly defined TLVs.
AES-CTR-128 was chosen primarily for having stream cipher proporties,
which basically means that any block being encrypted/decrypted does not
depend on any other previous blocks results.
The TLV adds about 256 bytes to the image in RSA-OAEP-2048 mode, and 24
bytes in AES-KW-128 mode. Resulting sizes for a Mynewt generated mcuboot
(frdm-k64f):
- swap mode and no signing: 12KB
- adding encryption with RSA-OAEP-2048: 28KB
- adding encryption with AES-KW-128: 20KB
Some extra comments:
- AES-KW-128 requires a fairly new mbedtls with nist_kw support.
- An alternative methods which could be added later are ECIES.
- Key-wrapping seems easy enough to implement using just standard
AES-ECB mode that it should be straight-forward to also add support to
tinycrypt.
Signed-off-by: Fabio Utzig <utzig@apache.org>
Mynewt has recently added an encrypted flash layer driver, that runs
transparently on any flash, handling reads and writes, and bypassing
other flash operations to the HW driver. As a result of this change,
checking for erased data cannot be done by read + compare to erased_val
but need to be routed to an empty check on the lower level. To do this
Mynewt added a new flash_map function called "flash_area_read_is_empty"
which checks for erased blocks (and reads/decrypts the data as well).
This commit uses `flash_area_read_is_empty` to determine if magic,
flags and swap status are erased. For Zephyr/sim commits were added
previously that mimic this functionality by simply doing the
read/compare.
Signed-off-by: Fabio Utzig <utzig@apache.org>