blob: 45c99be6316c07c8ccee7c0c613a3946042c2ace [file] [log] [blame]
.. _module-pw_software_update-design:
--------------------------
pw_software_update: Design
--------------------------
.. pigweed-module-subpage::
:name: pw_software_update
This page explains the security framing, bundle format and update workflows of
``pw_software_update``.
Embedded TUF
------------
At the heart, the ``pw_software_update`` module leverages
`The Update Framework <https://theupdateframework.io/>`_ (TUF),
an industry-leading software update security framework that is open, flexible,
and offers a balanced security and privacy treatment.
The ``pw_software_update`` module implements the following building blocks
around TUF.
.. mermaid::
flowchart LR
A[/Source/] --> |Build| B[/Target files/]
B --> |Assemble & Sign| C[(Update bundle)]
C --> |Publish| D[(Available updates)]
D --> |OTA| E[Device]
Update bundles
^^^^^^^^^^^^^^
Update bundles represent software releases packaged ready for delivery. A bundle
is essentially an archived folder matching the following structure:
.. code-block:: text
/
├── root_metadata
├── targets_metadata
└── targets
├── release_notes.txt
├── manifest.txt
├── rtos.bin
└── app.bin
Bundles are encoded as serialized "protocol buffers".
Key structure
^^^^^^^^^^^^^
As an optimization and trade-off for embedded projects, ``pw_software_update``
only supports the "root" and "targets" roles, as represented by
``root_metadata`` and ``targets_metadata``.
.. mermaid::
flowchart LR
A[Verified boot] --> |Embed & Verify| B[/Root key/]
B --> |Delegate & Rotate| C[/Targets key/]
C --> |Sign| D[/Target files/]
The "root" role delegates the "targets" role to directly authorize each release.
The "root" role can regularly rotate the "targets" role, in effect revoking
older versions once a new release is available.
The "root" role is the "root of trust" for software update and tied into
verified boot. Due to security risks, ``pw_software_update`` does not use
persistent metadata caches that are not covered by verified boot.
Signing service
^^^^^^^^^^^^^^^
Production signing keys MUST be kept secure and clean. That means we must
carefully control access, log usage details, and revoke the key if it was
(accidentally) used to sign a "questionable" build.
This is easier with a signing server built around a key management service.
.. mermaid::
sequenceDiagram
actor Releaser
Releaser->>Signer: Sign my bundle with my key, please.
activate Signer
Signer->>Signer: Check permission.
Signer->>Signer: Validate & sign bundle.
Signer->>Signer: Log action. Email alerts.
Signer-->>Releaser: Done!
deactivate Signer
We don't yet have a public-facing service. External users should source their
own solution.
Bundle verification
^^^^^^^^^^^^^^^^^^^
.. mermaid::
flowchart LR
A[(Incoming bundle)] --> |UpdateBundleAccessor| B[/Verified target files/]
The :cpp:type:`UpdateBundleAccessor` decodes, verifies, and exposes the target
files from an incoming bundle. This class hides the details of the bundle
format and verification flow from callers.
Update workflow
^^^^^^^^^^^^^^^
On the device side, :cpp:type:`BundledUpdateService` orchestrates an update
session end-to-end. It drives the backend via a :cpp:type:`BundledUpdateBackend`
interface.
:cpp:type:`BundledUpdateService` is invoked via :ref:`module-pw_rpc` after an
incoming bundle is staged via :ref:`module-pw_transfer`.
.. mermaid::
stateDiagram-v2
direction LR
[*] --> Inactive
Inactive --> Transferring: Start()
Inactive --> Finished: Start() error
Transferring --> Transferring: GetStatus()
Transferring --> Transferred
Transferring --> Aborting: Abort()
Transferring --> Finished: Transfer error
Transferred --> Transferred: GetStatus()
Transferred --> Verifying: Verify()
Transferred --> Verifying: Apply()
Transferred --> Aborting: Abort()
Verifying --> Verifying: GetStatus()
Verifying --> Verified
Verifying --> Aborting: Abort()
Verified --> Verified: GetStatus()
Verified --> Applying: Apply()
Verified --> Aborting: Abort()
Applying --> Applying: GetStatus()
Applying --> Finished: Apply() OK
Applying --> Finished: Apply() error
Aborting --> Aborting: GetStatus()
Aborting --> Finished: Abort() OK
Aborting --> Finished: Abort() error
Finished --> Finished: GetStatus()
Finished --> Inactive: Reset()
Finished --> Finished: Reset() error
Tooling
^^^^^^^
``pw_software_update`` provides the following tooling support for development
and integration.
The python package
~~~~~~~~~~~~~~~~~~
``pw_software_update`` comes with a python package of the same name, providing
the following functionalities.
- Local signing key generation for development.
- TUF root metadata generation and signing.
- Bundle generation, signing, and verification.
- Signing server integration.
A typical use of the package is for build system integration.
.. code-block:: text
Help on package pw_software_update:
NAME
pw_software_update - pw_software_update
PACKAGE CONTENTS
bundled_update_pb2
cli
dev_sign
generate_test_bundle
keys
metadata
remote_sign
root_metadata
tuf_pb2
update_bundle
update_bundle_pb2
verify
The command line utility
~~~~~~~~~~~~~~~~~~~~~~~~
The ``pw update ...`` CLI (Command Line Interface) is a user-friendly interface
to the ``pw_software_update`` python package.
You can use the CLI to quickly learn and prototype a software update system
based on ``pw_software_update`` on your development PC before productionizing
one. In the future you will be able to use the CLI to update a reference
target.
.. code-block:: text
usage: pw update [sub-commands]
sub-commands:
generate-key
create-root-metadata
sign-root-metadata
inspect-root-metadata
create-empty-bundle
add-root-metadata-to-bundle
add-file-to-bundle
sign-bundle
inspect-bundle
options:
-h, --help show this help message and exit
To learn more, see :ref:`module-pw_software_update-cli`.