.. _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 `_ (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`.