1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
|
.. _module-pw_software_update-design:
--------------------------
pw_software_update: Design
--------------------------
.. pigweed-module-subpage::
:name: pw_software_update
:tagline: 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 <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`.
|