Skip to content

Commit dfbe975

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 dfbe975

File tree

2 files changed

+140
-2
lines changed

2 files changed

+140
-2
lines changed

source/chapter2-source-file-format.rst

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,13 +645,24 @@ not* be specified in a configuration node.
645645
Configuration-signature nodes
646646
-----------------------------
647647

648-
::
648+
Direct format (default)::
649649

650650
o signature-1
651651
|- algo = "algorithm name"
652652
|- key-name-hint = "key name"
653653
|- sign-images = "path1", "path2";
654-
|- value = [hash or checksum value]
654+
|- value = [signature value]
655+
|- hashed-strings = <0 len>
656+
657+
PKCS#7 format::
658+
659+
o signature-1
660+
|- algo = "algorithm name"
661+
|- format = "pkcs7"
662+
|- compatible = "vendor,product-signing"
663+
|- generation = <1>
664+
|- sign-images = "path1", "path2";
665+
|- value = [PKCS#7 SignedData]
655666
|- hashed-strings = <0 len>
656667

657668

@@ -661,6 +672,34 @@ Mandatory properties
661672
algo
662673
See `FIT Algorithm`_.
663674

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

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)