Skip to content

Commit 8415194

Browse files
committed
chapter7: Document the security architecture and hash contents
The security chapter currently gives only a brief overview. Expand it with two new sections: Architecture: describe the two-level scheme (image hashing plus configuration signing), explain why configuration signing prevents mix-and-match attacks, and outline the verification procedure. Hash contents: define exactly which bytes are included when computing a configuration signature hash, covering the FDT structure-block token rules (including the exclusion of data, data-size, data-position and data-offset properties), the strings-block region, and image hashing. Co-developed-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 72c0bfc commit 8415194

File tree

1 file changed

+156
-0
lines changed

1 file changed

+156
-0
lines changed

source/chapter7-security.rst

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,160 @@ For more information on FIT security, see
2323
The mechanism is also widely covered in conference talks, some of which are
2424
listed at `elinux.org <https://elinux.org/Boot_Loaders#U-Boot>`_.
2525

26+
Architecture
27+
------------
28+
29+
FIT security uses a two-level scheme: image hashing and configuration signing.
30+
31+
Image hashing
32+
~~~~~~~~~~~~~
33+
34+
Each image node contains one or more hash sub-nodes. Each hash sub-node holds
35+
the algorithm name (e.g. ``sha256``) and the resulting digest of the image
36+
data. The hash covers the image content only, so the loader can verify that the
37+
image data has not been modified after the hash was computed.
38+
39+
Hashing alone does not provide authentication, since an attacker who can modify
40+
the image data can also replace the hash. Authentication comes from the
41+
configuration signature, described next.
42+
43+
Configuration signing
44+
~~~~~~~~~~~~~~~~~~~~~
45+
46+
Each configuration node may contain one or more signature sub-nodes. A
47+
configuration signature covers:
48+
49+
- the configuration node itself (including its references to images),
50+
- each image node referenced by the configuration,
51+
- the hash sub-nodes of those images, and
52+
- the root (``/``) node of the FIT.
53+
54+
Because the signature covers the hash sub-nodes, the image data is
55+
transitively protected: any change to the image data invalidates the hash,
56+
and any change to the hash invalidates the configuration signature.
57+
58+
This design means that image data is protected without being directly included
59+
in the configuration signature. The ``data`` property (and related properties
60+
``data-size``, ``data-position`` and ``data-offset``) of image nodes are
61+
explicitly excluded from the signed region, since image-data integrity is already
62+
guaranteed by the image hash.
63+
64+
This two-level design has an important consequence: the same image can appear
65+
in multiple configurations, each with its own signature, without duplicating
66+
the image data or requiring it to be signed multiple times.
67+
68+
Configuration signing compared to image signing
69+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
70+
71+
Signing each image independently is vulnerable to a mix-and-match attack, where
72+
an attacker combines legitimately signed images into a configuration that was
73+
never intended. For example, an attacker could pair a signed kernel with a
74+
different signed devicetree to change the system's behaviour, even though both
75+
images carry valid signatures.
76+
77+
Configuration signing prevents this, because the signature binds a specific
78+
set of images together. A loader that verifies the configuration signature
79+
knows that this exact combination of images was approved by the signer.
80+
81+
Verification procedure
82+
~~~~~~~~~~~~~~~~~~~~~~
83+
84+
The bootloader verifies a configuration as follows:
85+
86+
#. Locate the configuration's signature node and verify the signature against
87+
a trusted public key.
88+
#. The signature covers certain FDT nodes and a region of the string table
89+
(see :ref:`hash_contents` below). Rebuild the list of nodes that should
90+
have been signed (the root node, the configuration node, each referenced
91+
image node and its hash sub-nodes) and verify that the hash of those nodes
92+
matches the signature.
93+
#. For each image referenced by the configuration, compute the hash of the
94+
image data and compare it against the ``value`` in the image's hash
95+
sub-node. This step may be deferred until the image is actually loaded,
96+
which can be some time after the configuration is selected.
97+
98+
If any step fails, the configuration must be rejected.
99+
100+
.. _hash_contents:
101+
102+
Hash contents
103+
-------------
104+
105+
This section defines exactly which bytes are included when computing the hash
106+
for a signature. A FIT is a flattened devicetree (FDT), so the hash operates
107+
on the FDT binary structure as defined in the Devicetree Specification
108+
[dtspec]_.
109+
110+
The input to the hash is the concatenation of two regions: a set of nodes from
111+
the FDT structure block, followed by a region of the FDT strings block.
112+
113+
Structure block
114+
~~~~~~~~~~~~~~~
115+
116+
The signer and verifier each construct a **node list**: the set of FDT nodes
117+
whose content is included in the hash. For a configuration signature this list
118+
contains:
119+
120+
- the root (``/``) node,
121+
- the configuration node (e.g. ``/configurations/conf-1``),
122+
- each image node referenced by the configuration
123+
(e.g. ``/images/kernel``, ``/images/fdt-1``),
124+
- the hash sub-nodes of those image nodes
125+
(e.g. ``/images/kernel/hash-1``, ``/images/fdt-1/hash-1``), and
126+
- any cipher sub-nodes of those image nodes (e.g. ``/images/kernel/cipher-1``).
127+
128+
The signer walks the FDT structure block sequentially and includes or excludes
129+
each token according to the following rules:
130+
131+
``FDT_BEGIN_NODE``
132+
The token and the node's unit name are included if the node or its parent
133+
is in the node list.
134+
135+
``FDT_END_NODE``
136+
Included under the same condition as ``FDT_BEGIN_NODE``.
137+
138+
``FDT_PROP``
139+
The token, the property length word, the string-table offset word, and the
140+
property data are all included if the containing node is in the node list
141+
**and** the property name is not one of the excluded properties: ``data``,
142+
``data-size``, ``data-position`` and ``data-offset``. These are excluded
143+
because image-data integrity is covered by image hashes instead.
144+
145+
``FDT_NOP``
146+
Included if the containing node is in the node list.
147+
148+
``FDT_END``
149+
Always included.
150+
151+
Note that the "or its parent" condition in the ``FDT_BEGIN_NODE`` and
152+
``FDT_END_NODE`` rules means that sub-nodes of listed nodes contribute their
153+
structural tokens to the hash, even though they are not themselves in the node
154+
list. For example, the signature sub-nodes of the configuration node have their
155+
``FDT_BEGIN_NODE`` and ``FDT_END_NODE`` tokens included, but their properties
156+
are excluded (since ``FDT_PROP`` requires the node itself to be in the list).
157+
158+
All included bytes are fed into the hash in the order they appear in the
159+
structure block. Padding bytes that are part of the FDT token alignment are
160+
included as they appear.
161+
162+
Strings block
163+
~~~~~~~~~~~~~
164+
165+
The ``hashed-strings`` property in the signature node records the start offset
166+
and size of the region of the FDT strings block that is hashed. The start is
167+
normally 0 (the beginning of the strings block). Only property names that
168+
are referenced by the signed nodes need to appear in this region; the signer
169+
must ensure that the region is large enough to cover them.
170+
171+
After hashing the structure-block regions, the hash algorithm continues with
172+
the strings-block region to produce the final digest.
173+
174+
Image hashing
175+
~~~~~~~~~~~~~
176+
177+
For image hash nodes (``/images/image-name/hash-1``), the hash is computed
178+
over the image's ``data`` property value only (i.e. the raw image content,
179+
not any FDT metadata). The algorithm is given by the hash node's ``algo``
180+
property and the resulting digest is stored in its ``value`` property.
181+
26182
.. sectionauthor:: Simon Glass <sjg@chromium.org>

0 commit comments

Comments
 (0)