Keep both image areas and the scratch area open while we are
bootloading. This fixes up a hack and will make it easier to use
flash_area_get_sectors() later.
Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
Add abstractions for calculating the starting offset of a sector from
the beginning of its image, and the starting offset of an image slot
from the beginning of its flash device.
Using this tweaks a check in boot_swap_sectors(), but doesn't change
its outcome.
Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
Add an abstraction for initializing bootloader state for a particular
flash area.
For now, we preserve some existing hacky behavior related to the
scratch area. This will get cleaned up more later in the series.
Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
Taking the opportunity to move some signed integers over to unsigned
size_t as we go. (Depending on compiler settings, signed / unsigned
comparisons can generate warnings, so it's nice to use the signedness
we mean when possible).
Having boot_img_set_num_sectors() is just an intermediate step; this
gets cleaned up as we go forward.
Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
This begins some preparatory work to using flash_area_get_sectors() in
loader.c. Subsequent commits will add and use additional accessors for
the contents of this struct.
Making the struct contents opaque will allow it to contain struct
flash_area or struct flash_sector values in its sectors field. This
will allow use of either flash_area_get_sectors() or the
now-deprecated flash_area_to_sectors().
Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
Allow the size of bignums in mbed TLS to be configured larger than
needed for RSA2048. This will waste memory holding the large numbers,
but will still work.
The PKCS#1 standards, which define RSA signatures, are currently at
version 2.2. Starting in v2.1, the standard defines a new signature
method RSA-PSS, which has a stronger security proof than the signature
method used in earlier versions. The standard recommends that RSA-PSS
be used in new designs, instead of the older algorithm.
This patch implements RSA-PSS verification for a specific set of
parameters:
- RSA-2048
- SHA256 for both the message digest and the internal hash
- 32-byte salt
- 2047 bit message
Although RSA-PSS supports other parameters, due to size constraints,
this verificatino code only supports these specific parameters, and
signatures with other parameters will be considered invalid.
To encourage the use of the more secure algorithm, the default build
configuration is RSA-PSS. BOOTUTIL_RSA_PKCS1_15 needs to be defined in
order to support the older signature algorithm.
Remove most of mynewt specific stuff to a separate port package. This
should make mcuboot less "mynewt'y" and slightly easier to port to.
- Mynewt specific stuff moved to boot/mynewt.
- Sample app moved from apps/boot to boot/mynewt.
- Use MYNEWT_VAL macro only on mynewt port.
- BOOTUTIL_* and MYNEWT_VAL() usage moved to MCUBOOT_ defines.
Before this patch, the swapping would process all sectors in a slot
not matter what the size of the binary firmware was. This changes the
swap process to swap only sectors that are in use by firmware.
Also, if the last slot sector, which stores the trailer, is actually not
in use by the binary firmware, now trailer is never written to scratch.
`use_scratch` temp variable was added to boot_status struct to control
this (this var is never written to disk).
Random other small refactorings were applied.
Before this change, trailer was handled as part of the binary image,
which during a swap was just copied around together with the image.
This had issues if some fault happened while the trailer copy was
underway.
This patch changes how trailer is handled by making by non-copying.
The trailer is now updated step-by-step based on the current status.
Magic, copy_done and image_ok are also handled by writing them
individually, not by copying.
The trailer on scratch area was reduced to include at most swap state for
one sector, since it is only used temporarily while erasing the last
sector of the slot that stores the final trailer.
Many other small fixes were applied.
In order to allow messages to be printed, set the compiled level to
INFO. This allows messages at this level to be printed without having
to recompile.
Change the C logging code, when in the simulator, to query what the rust
logging level is set to. This allows the level of logging from the C
code to be set through the environment. For example
RUST_LOG=bootsim=info cargo run --release runall
will enable logging at the "info" level for all of the C code as well as
the simulator code. The C code's logging can be selected specifically
by using bootsim::api instead of just bootsim in the above.
Add a configuration option "BOOTUTIL_OVERWRITE_ONLY" that avoids using
the image swap code. Instead, when an upgrade is detected in slot 1, it
is copied directly onto slot 0. As long as the image in slot 1 is
valid, this should work robustly (it will redo it if power is lost
during the upgrade).
This doesn't protect against the case of deploying an image that fails
to boot on some devices. But, the behavior is similar to the swap
upgrade approach when the slot 1 image is marked initially as "image
ok", but without the complexity (or need of a swap partition) of the
swap code.
Add a simple function to query the bootloader for capabilities.
Ultimately, this API should be available to the running app, but the
simulator can use this to determine what to test.
Instead of a separate invocation of printf to print the trailing
newline, use some modern cpp trickery to expand the format string
explicitly. The ## will remove the preceding comma of the argument list
if empty.
Add logging support for when running in the simulator. Log messages are
still based on compile-time determinations, and log using printf.
Based on a patch from Marti Bolivar <marti.bolivar@linaro.org>.
When building with ECDSA P-256 as the signature algorithm, we are still
bringing in SHA256 and some ASN.1 code from mbed TLS. Fix part of this
by wrapping the hash functions with general routines (inline functions)
allowing to select between mbed TLS and Tinycrypt for the
implementation.
Update the Zephyr config files so that the Tinycrypt version is used
when building the ECDSA P-256 signing variant.
There are some problems with how mbed TLS is configured in Zephyr.
First, include the makefile stub in the Makefile that uses these
defines. This makes sure the right definitions get made so that our
custom config gets used for all compiled files, rather than a mixed set.
Also, fix up the wrappers on the custom configs so that each is
different, making it easier to detect if multiple configs are being
included.
Lastly, only include the right header in the image validation. The mbed
TLS includes don't seem to want to allow both RSA and ECDSA to be used
(due to the key size), and including the wrong header results in a
compilation error.
Previously, the return of boot_swap_sectors() was discarded. If a flash
operation failed, this information was lost.
Now, boot_swap_sectors() returns void. Rather than returning a result,
success is asserted for all flash operations during function execution
(boot_copy_sector() and boot_erase_sector()).
commit d930ec69c8
Author: David Brown <david.brown@linaro.org>
Date: Wed Dec 14 07:59:48 2016 -0700
Validate slot zero before booting
adds a feature to validate slot 0 before booting it. However, there
is an error in the logic, and if the magic number is written to an
invalid value, but not all 0xFF, it will consider any image to be
valid.
Fix this logic so that slot zero is always validated.
Use the bootutil_log.h APIs to log the boot source chosen by the
loader, as well as the image trailer state that led it to its
conclusion.
Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
This patch adds platform-independent logging to bootutil.
When bootutil is compiled as part of an application, the
application environment can provide logging hooks using this
file. Initially, hooks for Zephyr are provided. When built for
simulation or unit testing, the logging macros produce no
code (the ignore.h used by mynewt is used to avoid unused
variable warnings in this case).
Before including this file, users may define BOOT_LOG_LEVEL. If
they do, it must be one of BOOT_LOG_LEVEL_OFF,
BOOT_LOG_LEVEL_ERROR, ..., BOOT_LOG_LEVEL_DEBUG. This determines
the log level for the current translation unit. If they do not, a
default log level is determined in a target-specific way.
After including bootutil_log.h, the macros BOOT_LOG_ERR(),
BOOT_LOG_WRN(), etc. may be used to log messages. These take
printf-like arguments.
Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
Make it clear in the top-level Makefile how to configure mcuboot for
Zephyr for a particular signing algorithm. Currently supported, are the
RSA signatures, and ECDSA with the P-256 curve. These configuration
lines will select the code built in the bootloader, as well as which
public key gets included with the image.
This also adds a demo public key for the P-256 signatures.
Instead of just checking the upgrade image signature, check the
signature on each boot. This helps to prevent rogue images being flash
by a means other than the upgrade process.
This feature is controlled by whether BOOTUTIL_VALIDATE_SLOT0 is
defined.
The ECDSA signature is written as two DER-encoded INTEGERS. Although
the values are always 256 bits, the encoding ends up being variable
length, because the encoding is signed, and therefore needs an extra
zero byte to keep the number positive. This means that the length can
vary by up to two bytes.
The 'newt' tool handles this for signature by allowing space for the
largest encoding, and padding with one or two zeros. However, the
bootutil image check code insists that the length is exact, resulting in
a decoding error on about 3/4 signatures.
Fix this by only verifying that we have at least enough payload to hold
the signature. There are later checks that will fail if the integers
themselves are too large.
Some flash devices not only require writes to occur on an `align` byte
boundary, but also require that the writes be done in chunks of this
size as well. Enhance the sections that write status bytes to write
more than a single status byte.
This reverts commit 920fc16b89.
The boot loader records its current state in the form of a pair of image
trailers, each located at the end of the corresponding image slot. If
an image is so big that it extends into the trailer space of a slot, the
boot loader would read the end of the image and interpet it as the start
of a trailer. The fix was to determine the size of each image upfront
by reading their headers, and only attempt to read an image's trailer if
the image is small enough that it doesn't extend into the trailer space.
If an image is too big to allow for a trailer, the boot loader fails
over to its "rescue mode": just boot into whatever is in slot 0.
The problem arises when the boot loader reads the image headers. There
are certain points during a swap when an image header is not in the
expected location. That is, if the device reboots at the wrong time
during an image swap, the boot loader will fail to read the image
headers when it comes up.
The image sectors are swapped in reverse order. When a swap is
performed, the final sectors of each slot are swapped first, and the
first sectors (containing the image headers) get swapped last. During
the final swap operation, there are two points at which the image
headers are not in the expected place:
1. slot 1 erased; header 1 in scratch area.
2. slot 0 erased; header 0 in scratch area.
In each case, the image header is not actually missing. Rather, the
boot loader is just looking in the wrong place. It should be looking in
the scratch area, not the start of the image slot.
The fix is to revert the original commit. Now, the boot loader won't
fail when an image header read fails. It is the user's responsibility
to ensure an image isn't too big.
The previous commit for this ticket left the code in a working state.
However, it was not possible for image management to distinguish between
the test and permanent states.
Now, these two states are indicated by the addition of a new swap type:
BOOT_SWAP_TYPE_PERMANENT.
Currently, to permanently run the alternate image, the boot loader
requires the following sequence:
1. image test <slot-01-hash>
2. reboot
3. image confirm
The new feature is to remove the need for the third step. The user
should be able to permanently switch images with this sequence:
1. image confirm <slot-01-hash>
2. reboot