1c70041dcb
Adds details on how to do signing using sysbuild Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
188 lines
8 KiB
ReStructuredText
188 lines
8 KiB
ReStructuredText
.. _west-sign:
|
|
|
|
Signing Binaries
|
|
################
|
|
|
|
The ``west sign`` :ref:`extension <west-extensions>` command can be used to
|
|
sign a Zephyr application binary for consumption by a bootloader using an
|
|
external tool. In some configurations, ``west sign`` is also used to invoke
|
|
an external, post-processing tool that "stitches" the final components of
|
|
the image together. Run ``west sign -h`` for command line help.
|
|
|
|
MCUboot / imgtool
|
|
*****************
|
|
|
|
The Zephyr build system has special support for signing binaries for use with
|
|
the `MCUboot`_ bootloader using the `imgtool`_ program provided by its
|
|
developers. You can both build and sign this type of application binary in one
|
|
step by setting some Kconfig options. If you do, ``west flash`` will use the
|
|
signed binaries.
|
|
|
|
If you use this feature, you don't need to run ``west sign`` yourself; the
|
|
build system will do it for you.
|
|
|
|
Here is an example workflow, which builds and flashes MCUboot, as well as the
|
|
:ref:`hello_world` application for chain-loading by MCUboot. Run these commands
|
|
from the :file:`zephyrproject` workspace you created in the
|
|
:ref:`getting_started`.
|
|
|
|
.. code-block:: console
|
|
|
|
west build -b YOUR_BOARD bootloader/mcuboot/boot/zephyr -d build-mcuboot
|
|
west build -b YOUR_BOARD zephyr/samples/hello_world -d build-hello-signed -- \
|
|
-DCONFIG_BOOTLOADER_MCUBOOT=y \
|
|
-DCONFIG_MCUBOOT_SIGNATURE_KEY_FILE=\"bootloader/mcuboot/root-rsa-2048.pem\"
|
|
|
|
west flash -d build-mcuboot
|
|
west flash -d build-hello-signed
|
|
|
|
Notes on the above commands:
|
|
|
|
- ``YOUR_BOARD`` should be changed to match your board
|
|
- The ``CONFIG_MCUBOOT_SIGNATURE_KEY_FILE`` value is the insecure default
|
|
provided and used by MCUboot for development and testing
|
|
- You can change the ``hello_world`` application directory to any other
|
|
application that can be loaded by MCUboot, such as the :zephyr:code-sample:`smp-svr` sample.
|
|
|
|
For more information on these and other related configuration options, see:
|
|
|
|
- :kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT`: build the application for loading by
|
|
MCUboot
|
|
- :kconfig:option:`CONFIG_MCUBOOT_SIGNATURE_KEY_FILE`: the key file to use with ``west
|
|
sign``. If you have your own key, change this appropriately
|
|
- :kconfig:option:`CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS`: optional additional command line
|
|
arguments for ``imgtool``
|
|
- :kconfig:option:`CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE`: also generate a confirmed
|
|
image, which may be more useful for flashing in production environments than
|
|
the OTA-able default image
|
|
- On Windows, if you get "Access denied" issues, the recommended fix is
|
|
to run ``pip3 install imgtool``, then retry with a pristine build directory.
|
|
|
|
If your ``west flash`` :ref:`runner <west-runner>` uses an image format
|
|
supported by imgtool, you should see something like this on your device's
|
|
serial console when you run ``west flash -d build-mcuboot``:
|
|
|
|
.. code-block:: none
|
|
|
|
*** Booting Zephyr OS build zephyr-v2.3.0-2310-gcebac69c8ae1 ***
|
|
[00:00:00.004,669] <inf> mcuboot: Starting bootloader
|
|
[00:00:00.011,169] <inf> mcuboot: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
|
|
[00:00:00.021,636] <inf> mcuboot: Boot source: none
|
|
[00:00:00.027,313] <wrn> mcuboot: Failed reading image headers; Image=0
|
|
[00:00:00.035,064] <err> mcuboot: Unable to find bootable image
|
|
|
|
Then, you should see something like this when you run ``west flash -d
|
|
build-hello-signed``:
|
|
|
|
.. code-block:: none
|
|
|
|
*** Booting Zephyr OS build zephyr-v2.3.0-2310-gcebac69c8ae1 ***
|
|
[00:00:00.004,669] <inf> mcuboot: Starting bootloader
|
|
[00:00:00.011,169] <inf> mcuboot: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
|
|
[00:00:00.021,636] <inf> mcuboot: Boot source: none
|
|
[00:00:00.027,374] <inf> mcuboot: Swap type: none
|
|
[00:00:00.115,142] <inf> mcuboot: Bootloader chainload address offset: 0xc000
|
|
[00:00:00.123,168] <inf> mcuboot: Jumping to the first image slot
|
|
*** Booting Zephyr OS build zephyr-v2.3.0-2310-gcebac69c8ae1 ***
|
|
Hello World! nrf52840dk_nrf52840
|
|
|
|
Whether ``west flash`` supports this feature depends on your runner. The
|
|
``nrfjprog`` and ``pyocd`` runners work with the above flow. If your runner
|
|
does not support this flow and you would like it to, please send a patch or
|
|
file an issue for adding support.
|
|
|
|
.. _west-extending-signing:
|
|
|
|
Extending signing externally
|
|
****************************
|
|
|
|
The signing script used when running ``west flash`` can be extended or replaced
|
|
to change features or introduce different signing mechanisms. By default with
|
|
MCUboot enabled, signing is setup by the :file:`cmake/mcuboot.cmake` file in
|
|
Zephyr which adds extra post build commands for generating the signed images.
|
|
The file used for signing can be replaced from a sysbuild scope (if being used)
|
|
or from a zephyr/zephyr module scope, the priority of which is:
|
|
|
|
* Sysbuild
|
|
* Zephyr property
|
|
* Default MCUboot script (if enabled)
|
|
|
|
From sysbuild, ``-D<target>_SIGNING_SCRIPT`` can be used to set a signing script
|
|
for a specific image or ``-DSIGNING_SCRIPT`` can be used to set a signing script
|
|
for all images, for example:
|
|
|
|
.. code-block:: console
|
|
|
|
west build -b <board> <application> -DSIGNING_SCRIPT=<file>
|
|
|
|
The zephyr property method is achieved by adjusting the ``SIGNING_SCRIPT`` property
|
|
on the `zephyr_property_target`, ideally from by a module by using:
|
|
|
|
.. code-block:: cmake
|
|
|
|
if(CONFIG_BOOTLOADER_MCUBOOT)
|
|
set_target_properties(zephyr_property_target PROPERTIES SIGNING_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/custom_signing.cmake)
|
|
endif()
|
|
|
|
This will include the custom signing CMake file instead of the default Zephyr
|
|
one when projects are built with MCUboot signing support enabled. The base
|
|
Zephyr MCUboot signing file can be used as a reference for creating a new
|
|
signing system or extending the default behaviour.
|
|
|
|
.. _MCUboot:
|
|
https://mcuboot.com/
|
|
|
|
.. _imgtool:
|
|
https://pypi.org/project/imgtool/
|
|
|
|
|
|
rimage
|
|
******
|
|
|
|
rimage configuration uses a different approach that does not rely on Kconfig or CMake
|
|
but on :ref:`west config<west-config>` instead, similar to
|
|
:ref:`west-building-cmake-config`.
|
|
|
|
Signing involves a number of "wrapper" scripts stacked on top of each other: ``west
|
|
flash`` invokes ``west build`` which invokes ``cmake`` and ``ninja`` which invokes
|
|
``west sign`` which invokes ``imgtool`` or `rimage`_. As long as the signing
|
|
parameters desired are the default ones and fairly static, these indirections are
|
|
not a problem. On the other hand, passing ``imgtool`` or ``rimage`` options through
|
|
all these layers can causes issues typical when the layers don't abstract
|
|
anything. First, this usually requires boilerplate code in each layer. Quoting
|
|
whitespace or other special characters through all the wrappers can be
|
|
difficult. Reproducing a lower ``west sign`` command to debug some build-time issue
|
|
can be very time-consuming: it requires at least enabling and searching verbose
|
|
build logs to find which exact options were used. Copying these options from the
|
|
build logs can be unreliable: it may produce different results because of subtle
|
|
environment differences. Last and worst: new signing feature and options are
|
|
impossible to use until more boilerplate code has been added in each layer.
|
|
|
|
To avoid these issues, ``rimage`` parameters can bet set in ``west config``
|
|
instead. Here's a ``workspace/.west/config`` example:
|
|
|
|
.. code-block:: ini
|
|
|
|
[sign]
|
|
# Not needed when invoked from CMake
|
|
tool = rimage
|
|
|
|
[rimage]
|
|
# Quoting is optional and works like in Unix shells
|
|
# Not needed when rimage can be found in the default PATH
|
|
path = "/home/me/zworkspace/build-rimage/rimage"
|
|
|
|
# Not needed when using the default development key
|
|
extra-args = -i 4 -k 'keys/key argument with space.pem'
|
|
|
|
In order to support quoting, values are parsed by Python's ``shlex.split()`` like in
|
|
:ref:`west-building-cmake-args`.
|
|
|
|
The ``extra-args`` are passed directly to the ``rimage`` command. The example
|
|
above has the same effect as appending them on command line after ``--`` like this:
|
|
``west sign --tool rimage -- -i 4 -k 'keys/key argument with space.pem'``. In case
|
|
both are used, the command-line arguments go last.
|
|
|
|
.. _rimage:
|
|
https://github.com/thesofproject/rimage
|