Skip to content

Commit d117855

Browse files
committed
Add PKCS#7 certificate-chain validation
Add support for PKCS#7/CMS SignedData signatures as an alternative to direct key-based verification. This enables a chain-of-trust model similar to UEFI Secure Boot and is Authenticode-compatible. This adds a new optional 'format' property in the signature node, which can be used to select 'direct' (default, existing behavior) or 'pkcs7', as well as an integer 'generation' for revocation For pkcs7 format, the certificate chain is embedded in the SignedData structure. Validation must include verification of the certificate chain verification up to trusted root, checking of the validity period and generation-based revocation. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com>
1 parent 1be2a60 commit d117855

File tree

2 files changed

+145
-7
lines changed

2 files changed

+145
-7
lines changed

source/chapter2-source-file-format.rst

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ Mandatory nodes
148148
Contains a set of available configuration nodes and
149149
defines a default configuration.
150150

151-
152151
'/images' node
153152
--------------
154153

@@ -645,13 +644,24 @@ not* be specified in a configuration node.
645644
Configuration-signature nodes
646645
-----------------------------
647646

648-
::
647+
Direct format (default)::
649648

650649
o signature-1
651650
|- algo = "algorithm name"
652651
|- key-name-hint = "key name"
653652
|- sign-images = "path1", "path2";
654-
|- value = [hash or checksum value]
653+
|- value = [signature value]
654+
|- hashed-strings = <0 len>
655+
656+
PKCS#7 format::
657+
658+
o signature-1
659+
|- algo = "algorithm name"
660+
|- format = "pkcs7"
661+
|- compatible = "vendor,product-signing"
662+
|- generation = <1>
663+
|- sign-images = "path1", "path2";
664+
|- value = [PKCS#7 SignedData]
655665
|- hashed-strings = <0 len>
656666

657667

@@ -661,11 +671,40 @@ Mandatory properties
661671
algo
662672
See `FIT Algorithm`_.
663673

674+
Optional properties
675+
~~~~~~~~~~~~~~~~~~~
676+
677+
format
678+
Signature format. Supported values:
679+
680+
=========== ==============================================================
681+
Format Meaning
682+
=========== ==============================================================
683+
direct Direct signature verification (default). The public key is
684+
stored in the bootloader.
685+
pkcs7 PKCS#7/CMS SignedData structure (Authenticode-compatible).
686+
The certificate chain is embedded in the ``value`` property.
687+
=========== ==============================================================
688+
689+
compatible
690+
Identifies the signing authority for generation-based revocation.
691+
The bootloader maintains a minimum acceptable generation per compatible
692+
string, allowing different signing authorities to manage revocation
693+
independently.
694+
See :ref:`certificate_revocation`.
695+
696+
generation
697+
Integer generation number for revocation purposes.
698+
The bootloader maintains a minimum acceptable generation per ``compatible``
699+
value; signatures with a generation below this minimum are rejected.
700+
See :ref:`certificate_revocation`.
701+
664702
key-name-hint
665-
Name of key to use for signing. The keys will normally be in
666-
a single directory (parameter -k to mkimage). For a given key <name>, its
667-
private key is stored in <name>.key and the certificate is stored in
668-
<name>.crt.
703+
Hint for the bootloader indicating which key to use for verification.
704+
The keys will normally be in a single directory (parameter -k to mkimage).
705+
For a given key <name>, its private key is stored in <name>.key and the
706+
certificate is stored in <name>.crt.
707+
This is optional; the bootloader may locate the key through other means.
669708

670709
The following properties are added as part of signing, and are mandatory:
671710

source/chapter3-usage.rst

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

255+
.. _certificate_chain_validation:
256+
257+
Certificate chain validation
258+
----------------------------
259+
260+
FIT supports certificate chain validation as an alternative to direct public
261+
key verification.
262+
This enables a chain-of-trust model similar to Authenticode with UEFI Secure
263+
Boot.
264+
265+
When the signature's ``format`` property is ``pkcs7``, the ``value`` property
266+
contains a PKCS#7/CMS SignedData structure (as used by Authenticode).
267+
The certificate chain is embedded within the SignedData.
268+
269+
Validation proceeds as follows:
270+
271+
#. Parse the PKCS#7 SignedData structure from the ``value`` property
272+
#. Extract the signing certificate and any intermediate certificates
273+
#. Verify the signature using the signing certificate's public key
274+
#. Walk the certificate chain, verifying each certificate's signature against
275+
its issuer's public key
276+
#. Verify the root certificate is trusted by checking its hash against the
277+
bootloader's trust store
278+
#. Verify each certificate's validity period (NotBefore/NotAfter) against
279+
the current time, if a reliable time source is available
280+
#. Verify each certificate includes the Code Signing Extended Key Usage (EKU)
281+
extension (OID ``1.3.6.1.5.5.7.3.3``)
282+
#. Check the signature's ``generation`` property against the bootloader's
283+
minimum acceptable generation (see :ref:`certificate_revocation`)
284+
285+
If any step fails, the signature must be rejected.
286+
287+
This format enables compatibility with existing Authenticode tooling and
288+
workflows.
289+
290+
Trust anchors
291+
~~~~~~~~~~~~~
292+
293+
The bootloader stores trusted root CA certificate hashes in the same secure
294+
storage used for direct public keys (e.g., UEFI secure variables or U-Boot's
295+
control FDT). A root certificate is trusted if its SHA-256 hash matches one in
296+
the trust store.
297+
298+
Extended Key Usage
299+
~~~~~~~~~~~~~~~~~~
300+
301+
Certificates used for FIT signing must include the Code Signing EKU extension
302+
(OID ``1.3.6.1.5.5.7.3.3``, id-kp-codeSigning).
303+
This is the same OID used by Authenticode and UEFI Secure Boot.
304+
It prevents certificates issued for other purposes (e.g., TLS, email) from
305+
being misused to sign firmware images.
306+
307+
Intermediate CA certificates in the chain should include the
308+
``anyExtendedKeyUsage`` OID or the Code Signing OID.
309+
310+
.. _certificate_revocation:
311+
312+
Certificate revocation
313+
----------------------
314+
315+
FIT uses generation-based revocation for simplicity.
316+
317+
The signature node includes:
318+
319+
- ``compatible``: identifies the signing authority (e.g.,
320+
``"vendor,product-signing"``)
321+
- ``generation``: integer generation number
322+
323+
The bootloader maintains a minimum acceptable generation per ``compatible``
324+
value in secure storage.
325+
This allows different signing authorities to manage revocation independently;
326+
one vendor can revoke old signatures without affecting another vendor's
327+
signatures.
328+
329+
During validation, the bootloader:
330+
331+
#. Looks up the minimum generation for the signature's ``compatible`` value
332+
#. Rejects the signature if its ``generation`` is less than the stored minimum
333+
334+
To revoke, the system administrator increments the minimum generation for a
335+
specific ``compatible`` value in the bootloader's secure storage;
336+
all signatures with that ``compatible`` and lower generation numbers become
337+
invalid.
338+
339+
This approach has several advantages:
340+
341+
- Simple to implement (integer comparison per signing authority)
342+
- No need to track individual revoked certificate serial numbers
343+
- No network access required (unlike OCSP)
344+
- Deterministic and fast
345+
- Multiple signing authorities can coexist
346+
347+
To revoke and re-issue:
348+
349+
#. Issue new signatures with a higher generation number
350+
#. Update the FIT with new signatures
351+
#. Increment the bootloader's minimum generation for that ``compatible`` value
352+
#. All older signatures from that authority are now rejected
353+
255354
.. sectionauthor:: Simon Glass <sjg@chromium.org>

0 commit comments

Comments
 (0)