mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-02 09:46:37 +03:00
Merge patch series "binman: Fix preload signing with encrypted FIT"
Yan WANG <yan.wang@softathome.com> says: This series improves the reliability and efficiency of binman preload header generation and test it against an encrypted FIT image signed with a preload header. When a preload header references other entries (e.g. an encrypted FIT) through the collection etype, the referenced entries may be rebuilt multiple times during binman processing. This becomes problematic when the referenced entry produces non-deterministic output, such as FIT encryption using random IVs or timestamps, since rebuilding the entry changes the data. This series ensures that referenced entries are built only once and that preload signing is performed after all data is collected. It also avoids unnecessary repacking or repeated signing operations by the preload. The changes include: * generate preload header placeholders in ObtainContents() and sign data only once in ProcessContentsUpdate() * mark referenced entries as build_done in the collection etype to avoid rebuilding data * add a functional test for signing an encrypted FIT with a preload header Link: https://lore.kernel.org/r/20260417083050.499955-1-yan.wang@softathome.com
This commit is contained in:
@@ -45,12 +45,17 @@ class Entry_collection(Entry):
|
||||
self.Info('Getting contents, required=%s' % required)
|
||||
data = bytearray()
|
||||
for entry_phandle in self.content:
|
||||
entry_data = self.section.GetContentsByPhandle(entry_phandle, self,
|
||||
required)
|
||||
entry, entry_data = self.section.GetContentsByPhandle(
|
||||
entry_phandle, self, required)
|
||||
if not required and entry_data is None:
|
||||
self.Info('Contents not available yet')
|
||||
# Data not available yet
|
||||
return None
|
||||
|
||||
# Mark referenced entries as build_done to avoid rebuilding
|
||||
if required:
|
||||
entry.mark_build_done()
|
||||
|
||||
data += entry_data
|
||||
|
||||
self.Info('Returning contents size %x' % len(data))
|
||||
|
||||
@@ -152,14 +152,11 @@ class Entry_pre_load(Entry_collection):
|
||||
return data + pad
|
||||
|
||||
def ObtainContents(self):
|
||||
"""Obtain a placeholder for the header contents"""
|
||||
# wait that the image is available
|
||||
self.image = self.GetContents(False)
|
||||
if self.image is None:
|
||||
return False
|
||||
self.SetContents(self._CreateHeader())
|
||||
"""Create a placeholder for the header"""
|
||||
self.SetContents(tools.get_bytes(0, self.header_size))
|
||||
return True
|
||||
|
||||
def ProcessContents(self):
|
||||
self.image = self.GetContents(True)
|
||||
data = self._CreateHeader()
|
||||
return self.ProcessContentsUpdate(data)
|
||||
|
||||
@@ -557,7 +557,8 @@ class Entry_section(Entry):
|
||||
return None
|
||||
|
||||
Returns:
|
||||
data from associated entry (as a string), or None if not found
|
||||
tuple: (entry, data) where entry is the Entry object and data is
|
||||
from that entry (as a string), or (entry, None) if data not found
|
||||
"""
|
||||
node = self._node.GetFdt().LookupPhandle(phandle)
|
||||
if not node:
|
||||
@@ -565,7 +566,7 @@ class Entry_section(Entry):
|
||||
entry = self.FindEntryByNode(node)
|
||||
if not entry:
|
||||
source_entry.Raise("Cannot find entry for node '%s'" % node.name)
|
||||
return entry.GetData(required)
|
||||
return entry, entry.GetData(required)
|
||||
|
||||
def LookupEntry(self, entries, sym_name, msg):
|
||||
"""Look up the entry for a binman symbol
|
||||
|
||||
@@ -5895,6 +5895,27 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
|
||||
data = self._DoReadFileDtb('security/pre_load_invalid_key.dts',
|
||||
entry_args=entry_args)
|
||||
|
||||
def testPreLoadEncryptedFit(self):
|
||||
"""Test an encrypted FIT image with a pre-load header"""
|
||||
entry_args = {
|
||||
'pre-load-key-path': os.path.join(self._binman_dir, 'test'),
|
||||
}
|
||||
data = tools.read_file(self.TestFile("fit/aes256.bin"))
|
||||
self._MakeInputFile("keys/aes256.bin", data)
|
||||
|
||||
keys_subdir = os.path.join(self._indir, "keys")
|
||||
data = self._DoReadFileDtb(
|
||||
'security/pre_load_fit_encrypted.dts', entry_args=entry_args,
|
||||
extra_indirs=[keys_subdir])[0]
|
||||
|
||||
image_fname = tools.get_output_filename('image.bin')
|
||||
is_signed = self._CheckPreload(image_fname, self.TestFile("dev.key"))
|
||||
|
||||
self.assertEqual(PRE_LOAD_MAGIC, data[:len(PRE_LOAD_MAGIC)])
|
||||
self.assertEqual(PRE_LOAD_VERSION, data[4:4 + len(PRE_LOAD_VERSION)])
|
||||
self.assertEqual(PRE_LOAD_HDR_SIZE, data[8:8 + len(PRE_LOAD_HDR_SIZE)])
|
||||
self.assertEqual(is_signed, True)
|
||||
|
||||
def _CheckSafeUniqueNames(self, *images):
|
||||
"""Check all entries of given images for unsafe unique names"""
|
||||
for image in images:
|
||||
|
||||
63
tools/binman/test/security/pre_load_fit_encrypted.dts
Normal file
63
tools/binman/test/security/pre_load_fit_encrypted.dts
Normal file
@@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
pre-load {
|
||||
content = <&image>;
|
||||
algo-name = "sha256,rsa2048";
|
||||
key-name = "dev.key";
|
||||
header-size = <4096>;
|
||||
version = <0x11223344>;
|
||||
};
|
||||
|
||||
image: fit {
|
||||
fit,encrypt;
|
||||
description = "Test a FIT with encrypted data and signed with a preload";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
u-boot {
|
||||
description = "U-Boot";
|
||||
type = "firmware";
|
||||
arch = "arm64";
|
||||
os = "U-Boot";
|
||||
compression = "none";
|
||||
load = <00000000>;
|
||||
entry = <00000000>;
|
||||
cipher {
|
||||
algo = "aes256";
|
||||
key-name-hint = "aes256";
|
||||
};
|
||||
u-boot-nodtb {
|
||||
};
|
||||
};
|
||||
fdt-1 {
|
||||
description = "Flattened Device Tree blob";
|
||||
type = "flat_dt";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
cipher {
|
||||
algo = "aes256";
|
||||
key-name-hint = "aes256";
|
||||
};
|
||||
u-boot-dtb {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
description = "Boot U-Boot with FDT blob";
|
||||
firmware = "u-boot";
|
||||
fdt = "fdt-1";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user