pw_software_update: Design#

pw_software_update: Secure software delivery

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.

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.

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.

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#

flowchart LR A[(Incoming bundle)] --> |UpdateBundleAccessor| B[/Verified target files/]

The 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, BundledUpdateService orchestrates an update session end-to-end. It drives the backend via a BundledUpdateBackend interface.

BundledUpdateService is invoked via pw_rpc after an incoming bundle is staged via pw_transfer.

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.

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.

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 pw_software_update: CLI reference.