| .. _module-pw_software_update-design: |
| |
| -------------------------- |
| pw_software_update: Design |
| -------------------------- |
| .. pigweed-module-subpage:: |
| :name: pw_software_update |
| :tagline: Secure software delivery |
| :nav: |
| getting started: module-pw_software_update-get-started |
| design: module-pw_software_update-design |
| guides: module-pw_software_update-guides |
| cli: module-pw_software_update-cli |
| |
| 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:: |
| |
| / |
| ├── 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:: python |
| |
| 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:: bash |
| |
| 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`. |