diff options
Diffstat (limited to 'tools/binman')
34 files changed, 748 insertions, 37 deletions
diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst index c30e7eb..20ee243 100644 --- a/tools/binman/bintools.rst +++ b/tools/binman/bintools.rst @@ -155,6 +155,17 @@ Support is provided for fetching this on Debian-like systems, using apt. +Bintool: openssl: openssl tool +------------------------------ + +This bintool supports creating new openssl certificates. + +It also supports fetching a binary openssl + +Documentation about openssl is at https://www.openssl.org/ + + + Bintool: xz: Compression/decompression using the xz algorithm ------------------------------------------------------------- @@ -183,3 +194,25 @@ Documentation is available via:: +Bintool: fdt_add_pubkey: Add public key to device tree +------------------------------------------------------ + +This bintool supports running `fdt_add_pubkey` in order to add a public +key coming from a certificate to a device-tree. + +Normally signing is done using `mkimage` in context of `binman sign`. However, +in this process the public key is not added to the stage before u-boot proper. +Using `fdt_add_pubkey` the key can be injected to the SPL independent of +`mkimage` + + + +Bintool: bootgen: Sign ZynqMP FSBL image +--------------------------------------------- + +This bintool supports running `bootgen` in order to sign a SPL for ZynqMP +devices. + +The bintool automatically creates an appropriate input image file (.bif) for +bootgen based on the passed arguments. The output is a bootable, +authenticated `boot.bin` file. diff --git a/tools/binman/btool/fdt_add_pubkey.py b/tools/binman/btool/fdt_add_pubkey.py new file mode 100644 index 0000000..a507742 --- /dev/null +++ b/tools/binman/btool/fdt_add_pubkey.py @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (C) 2023 Weidmüller Interface GmbH & Co. KG +# Lukas Funke <lukas.funke@weidmueller.com> +# +"""Bintool implementation for fdt_add_pubkey""" + +from binman import bintool + +class Bintoolfdt_add_pubkey(bintool.Bintool): + """Add public key to control dtb (spl or u-boot proper) + + This bintool supports running `fdt_add_pubkey`. + + Normally mkimage adds signature information to the control dtb. However + binman images are built independent from each other. Thus it is required + to add the public key separately from mkimage. + """ + def __init__(self, name): + super().__init__(name, 'Generate image for U-Boot') + + # pylint: disable=R0913 + def run(self, input_fname, keydir, keyname, required, algo): + """Run fdt_add_pubkey + + Args: + input_fname (str): dtb file to sign + keydir (str): Directory with public key. Optional parameter, + default value: '.' (current directory) + keyname (str): Public key name. Optional parameter, + default value: key + required (str): If present this indicates that the key must be + verified for the image / configuration to be considered valid. + algo (str): Cryptographic algorithm. Optional parameter, + default value: sha1,rsa2048 + """ + args = [] + if algo: + args += ['-a', algo] + if keydir: + args += ['-k', keydir] + if keyname: + args += ['-n', keyname] + if required: + args += ['-r', required] + + args += [ input_fname ] + + return self.run_cmd(*args) + + def fetch(self, method): + """Fetch handler for fdt_add_pubkey + + This installs fdt_add_pubkey using the apt utility. + + Args: + method (FETCH_...): Method to use + + Returns: + True if the file was fetched and now installed, None if a method + other than FETCH_BIN was requested + + Raises: + Valuerror: Fetching could not be completed + """ + if method != bintool.FETCH_BIN: + return None + return self.apt_install('u-boot-tools') diff --git a/tools/binman/control.py b/tools/binman/control.py index 25e6681..d1ee1d6 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -308,8 +308,8 @@ def BeforeReplace(image, allow_resize): image: Image to prepare """ state.PrepareFromLoadedData(image) - image.LoadData() image.CollectBintools() + image.LoadData(decomp=False) # If repacking, drop the old offset/size values except for the original # ones, so we are only left with the constraints. diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index 1621ff3..f237693 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -468,6 +468,92 @@ updating the EC on startup via software sync. +.. _etype_encrypted: + +Entry: encrypted: Externally built encrypted binary blob +-------------------------------------------------------- + +This entry provides the functionality to include information about how to +decrypt an encrypted binary. This information is added to the +resulting device tree by adding a new cipher node in the entry's parent +node (i.e. the binary). + +The key that must be used to decrypt the binary is either directly embedded +in the device tree or indirectly by specifying a key source. The key source +can be used as an id of a key that is stored in an external device. + +Using an embedded key +~~~~~~~~~~~~~~~~~~~~~ + +This is an example using an embedded key:: + + blob-ext { + filename = "encrypted-blob.bin"; + }; + + encrypted { + algo = "aes256-gcm"; + iv-filename = "encrypted-blob.bin.iv"; + key-filename = "encrypted-blob.bin.key"; + }; + +This entry generates the following device tree structure form the example +above:: + + data = [...] + cipher { + algo = "aes256-gcm"; + key = <0x...>; + iv = <0x...>; + }; + +The data property is generated by the blob-ext etype, the cipher node and +its content is generated by this etype. + +Using an external key +~~~~~~~~~~~~~~~~~~~~~ + +Instead of embedding the key itself into the device tree, it is also +possible to address an externally stored key by specifying a 'key-source' +instead of the 'key':: + + blob-ext { + filename = "encrypted-blob.bin"; + }; + + encrypted { + algo = "aes256-gcm"; + iv-filename = "encrypted-blob.bin.iv"; + key-source = "external-key-id"; + }; + +This entry generates the following device tree structure form the example +above:: + + data = [...] + cipher { + algo = "aes256-gcm"; + key-source = "external-key-id"; + iv = <0x...>; + }; + +Properties +~~~~~~~~~~ + +Properties / Entry arguments: + - algo: The encryption algorithm. Currently no algorithm is supported + out-of-the-box. Certain algorithms will be added in future + patches. + - iv-filename: The name of the file containing the initialization + vector (in short iv). See + https://en.wikipedia.org/wiki/Initialization_vector + - key-filename: The name of the file containing the key. Either + key-filename or key-source must be provided. + - key-source: The key that should be used. Either key-filename or + key-source must be provided. + + + .. _etype_fdtmap: Entry: fdtmap: An entry which contains an FDT map @@ -2031,6 +2117,45 @@ binman uses that to look up symbols to write into the SPL binary. +.. _etype_u_boot_spl_pubkey_dtb: + +Entry: u-boot-spl-pubkey-dtb: U-Boot SPL device tree including public key +------------------------------------------------------------------------- + +Properties / Entry arguments: + - key-name-hint: Public key name without extension (.crt). + Default is determined by underlying + bintool (fdt_add_pubkey), usually 'key'. + - algo: (Optional) Algorithm used for signing. Default is determined by + underlying bintool (fdt_add_pubkey), usually 'sha1,rsa2048' + - required: (Optional) If present this indicates that the key must be + verified for the image / configuration to be + considered valid + +The following example shows an image containing an SPL which +is packed together with the dtb. Binman will add a signature +node to the dtb. + +Example node:: + + image { + ... + spl { + filename = "spl.bin" + + u-boot-spl-nodtb { + }; + u-boot-spl-pubkey-dtb { + algo = "sha384,rsa4096"; + required = "conf"; + key-name-hint = "dev"; + }; + }; + ... + } + + + .. _etype_u_boot_spl_with_ucode_ptr: Entry: u-boot-spl-with-ucode-ptr: U-Boot SPL with embedded microcode pointer diff --git a/tools/binman/etype/blob_dtb.py b/tools/binman/etype/blob_dtb.py index 6a3fbc4..d543de9 100644 --- a/tools/binman/etype/blob_dtb.py +++ b/tools/binman/etype/blob_dtb.py @@ -38,7 +38,7 @@ class Entry_blob_dtb(Entry_blob): self.Raise("Invalid prepend in '%s': '%s'" % (self._node.name, self.prepend)) - def ObtainContents(self): + def ObtainContents(self, fake_size=0): """Get the device-tree from the list held by the 'state' module""" self._filename = self.GetDefaultFilename() self._pathname, _ = state.GetFdtContents(self.GetFdtEtype()) diff --git a/tools/binman/etype/encrypted.py b/tools/binman/etype/encrypted.py new file mode 100644 index 0000000..53d0e76 --- /dev/null +++ b/tools/binman/etype/encrypted.py @@ -0,0 +1,138 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2023 Weidmüller Interface GmbH & Co. KG +# Written by Christian Taedcke <christian.taedcke@weidmueller.com> +# +# Entry-type module for cipher information of encrypted blobs/binaries +# + +from binman.etype.collection import Entry +from dtoc import fdt_util +from u_boot_pylib import tools + +# This is imported if needed +state = None + + +class Entry_encrypted(Entry): + """Externally built encrypted binary blob + + This entry provides the functionality to include information about how to + decrypt an encrypted binary. This information is added to the + resulting device tree by adding a new cipher node in the entry's parent + node (i.e. the binary). + + The key that must be used to decrypt the binary is either directly embedded + in the device tree or indirectly by specifying a key source. The key source + can be used as an id of a key that is stored in an external device. + + Using an embedded key + ~~~~~~~~~~~~~~~~~~~~~ + + This is an example using an embedded key:: + + blob-ext { + filename = "encrypted-blob.bin"; + }; + + encrypted { + algo = "aes256-gcm"; + iv-filename = "encrypted-blob.bin.iv"; + key-filename = "encrypted-blob.bin.key"; + }; + + This entry generates the following device tree structure form the example + above:: + + data = [...] + cipher { + algo = "aes256-gcm"; + key = <0x...>; + iv = <0x...>; + }; + + The data property is generated by the blob-ext etype, the cipher node and + its content is generated by this etype. + + Using an external key + ~~~~~~~~~~~~~~~~~~~~~ + + Instead of embedding the key itself into the device tree, it is also + possible to address an externally stored key by specifying a 'key-source' + instead of the 'key':: + + blob-ext { + filename = "encrypted-blob.bin"; + }; + + encrypted { + algo = "aes256-gcm"; + iv-filename = "encrypted-blob.bin.iv"; + key-source = "external-key-id"; + }; + + This entry generates the following device tree structure form the example + above:: + + data = [...] + cipher { + algo = "aes256-gcm"; + key-source = "external-key-id"; + iv = <0x...>; + }; + + Properties + ~~~~~~~~~~ + + Properties / Entry arguments: + - algo: The encryption algorithm. Currently no algorithm is supported + out-of-the-box. Certain algorithms will be added in future + patches. + - iv-filename: The name of the file containing the initialization + vector (in short iv). See + https://en.wikipedia.org/wiki/Initialization_vector + - key-filename: The name of the file containing the key. Either + key-filename or key-source must be provided. + - key-source: The key that should be used. Either key-filename or + key-source must be provided. + """ + + def __init__(self, section, etype, node): + # Put this here to allow entry-docs and help to work without libfdt + global state + from binman import state + + super().__init__(section, etype, node) + self.required_props = ['algo', 'iv-filename'] + self._algo = None + self._iv_filename = None + self._key_name_hint = None + self._key_filename = None + + def ReadNode(self): + super().ReadNode() + + self._algo = fdt_util.GetString(self._node, 'algo') + self._iv_filename = fdt_util.GetString(self._node, 'iv-filename') + self._key_filename = fdt_util.GetString(self._node, 'key-filename') + self._key_source = fdt_util.GetString(self._node, 'key-source') + + if self._key_filename is None and self._key_source is None: + self.Raise("Provide either 'key-filename' or 'key-source'") + + def gen_entries(self): + super().gen_entries() + + iv_filename = tools.get_input_filename(self._iv_filename) + iv = tools.read_file(iv_filename, binary=True) + + cipher_node = state.AddSubnode(self._node.parent, "cipher") + cipher_node.AddString("algo", self._algo) + cipher_node.AddData("iv", iv) + + if self._key_filename: + key_filename = tools.get_input_filename(self._key_filename) + key = tools.read_file(key_filename, binary=True) + cipher_node.AddData("key", key) + + if self._key_source: + cipher_node.AddString("key-source", self._key_source) diff --git a/tools/binman/etype/pre_load.py b/tools/binman/etype/pre_load.py index bd3545b..2e4c723 100644 --- a/tools/binman/etype/pre_load.py +++ b/tools/binman/etype/pre_load.py @@ -81,7 +81,8 @@ class Entry_pre_load(Entry_collection): def ReadNode(self): super().ReadNode() - self.key_path, = self.GetEntryArgsOrProps([EntryArg('pre-load-key-path', str)]) + self.key_path, = self.GetEntryArgsOrProps( + [EntryArg('pre-load-key-path', str)]) if self.key_path is None: self.key_path = '' @@ -98,8 +99,7 @@ class Entry_pre_load(Entry_collection): self.Raise(sign_name + " is not supported") # Read the key - with open(key_name, 'rb') as pem: - key = RSA.import_key(pem.read()) + key = RSA.import_key(tools.read_file(key_name)) # Check if the key has the expected size if key.size_in_bytes() != RSAS[sign_name]: diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index 7c4d312..fb49e85 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -179,7 +179,7 @@ class Entry_section(Entry): Returns: bool: True if the node is a special one, else False """ - start_list = ('hash', 'signature', 'template') + start_list = ('cipher', 'hash', 'signature', 'template') return any(node.name.startswith(name) for name in start_list) def ReadNode(self): diff --git a/tools/binman/etype/u_boot_spl_pubkey_dtb.py b/tools/binman/etype/u_boot_spl_pubkey_dtb.py new file mode 100644 index 0000000..cb19606 --- /dev/null +++ b/tools/binman/etype/u_boot_spl_pubkey_dtb.py @@ -0,0 +1,112 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2023 Weidmueller GmbH +# Written by Lukas Funke <lukas.funke@weidmueller.com> +# +# Entry-type module for 'u-boot-spl-pubkey.dtb' +# + +import tempfile +import os + +from binman.etype.blob_dtb import Entry_blob_dtb + +from dtoc import fdt_util + +from u_boot_pylib import tools + +# This is imported if needed +state = None + +# pylint: disable=C0103 +class Entry_u_boot_spl_pubkey_dtb(Entry_blob_dtb): + """U-Boot SPL device tree including public key + + Properties / Entry arguments: + - key-name-hint: Public key name without extension (.crt). + Default is determined by underlying + bintool (fdt_add_pubkey), usually 'key'. + - algo: (Optional) Algorithm used for signing. Default is determined by + underlying bintool (fdt_add_pubkey), usually 'sha1,rsa2048' + - required: (Optional) If present this indicates that the key must be + verified for the image / configuration to be + considered valid + + The following example shows an image containing an SPL which + is packed together with the dtb. Binman will add a signature + node to the dtb. + + Example node:: + + image { + ... + spl { + filename = "spl.bin" + + u-boot-spl-nodtb { + }; + u-boot-spl-pubkey-dtb { + algo = "sha384,rsa4096"; + required = "conf"; + key-name-hint = "dev"; + }; + }; + ... + } + """ + + def __init__(self, section, etype, node): + # Put this here to allow entry-docs and help to work without libfdt + global state + from binman import state + + super().__init__(section, etype, node) + self.required_props = ['key-name-hint'] + self.fdt_add_pubkey = None + self._algo = fdt_util.GetString(self._node, 'algo') + self._required = fdt_util.GetString(self._node, 'required') + self._key_name_hint = fdt_util.GetString(self._node, 'key-name-hint') + + def ObtainContents(self, fake_size=0): + """Add public key to SPL dtb + + Add public key which is pointed out by + 'key-name-hint' to node 'signature' in the spl-dtb + + This is equivalent to the '-K' option of 'mkimage' + + Args: + fake_size (int): unused + """ + + # We don't pass fake_size upwards because this is currently + # not supported by the blob type + super().ObtainContents() + + with tempfile.NamedTemporaryFile(prefix=os.path.basename( + self.GetFdtEtype()), + dir=tools.get_output_dir())\ + as pubkey_tdb: + tools.write_file(pubkey_tdb.name, self.GetData()) + keyname = tools.get_input_filename(self._key_name_hint + ".crt") + self.fdt_add_pubkey.run(pubkey_tdb.name, + os.path.dirname(keyname), + self._key_name_hint, + self._required, self._algo) + dtb = tools.read_file(pubkey_tdb.name) + self.SetContents(dtb) + state.UpdateFdtContents(self.GetFdtEtype(), dtb) + + return True + + # pylint: disable=R0201,C0116 + def GetDefaultFilename(self): + return 'spl/u-boot-spl-pubkey.dtb' + + # pylint: disable=R0201,C0116 + def GetFdtEtype(self): + return 'u-boot-spl-dtb' + + # pylint: disable=R0201,C0116 + def AddBintools(self, btools): + super().AddBintools(btools) + self.fdt_add_pubkey = self.AddBintool(btools, 'fdt_add_pubkey') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 3e8091e..1cfa349 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -94,6 +94,8 @@ ROCKCHIP_TPL_DATA = b'rockchip-tpl' TEST_FDT1_DATA = b'fdt1' TEST_FDT2_DATA = b'test-fdt2' ENV_DATA = b'var1=1\nvar2="2"' +ENCRYPTED_IV_DATA = b'123456' +ENCRYPTED_KEY_DATA = b'abcde' PRE_LOAD_MAGIC = b'UBSH' PRE_LOAD_VERSION = 0x11223344.to_bytes(4, 'big') PRE_LOAD_HDR_SIZE = 0x00001000.to_bytes(4, 'big') @@ -232,6 +234,10 @@ class TestFunctional(unittest.TestCase): # Newer OP_TEE file in v1 binary format cls.make_tee_bin('tee.bin') + # test files for encrypted tests + TestFunctional._MakeInputFile('encrypted-file.iv', ENCRYPTED_IV_DATA) + TestFunctional._MakeInputFile('encrypted-file.key', ENCRYPTED_KEY_DATA) + cls.comp_bintools = {} for name in COMP_BINTOOLS: cls.comp_bintools[name] = bintool.Bintool.create(name) @@ -648,6 +654,16 @@ class TestFunctional(unittest.TestCase): tools.read_file(cls.ElfTestFile(src_fname))) @classmethod + def _SetupPmuFwlElf(cls, src_fname='bss_data'): + """Set up an ELF file with a '_dt_ucode_base_size' symbol + + Args: + Filename of ELF file to use as VPL + """ + TestFunctional._MakeInputFile('pmu-firmware.elf', + tools.read_file(cls.ElfTestFile(src_fname))) + + @classmethod def _SetupDescriptor(cls): with open(cls.TestFile('descriptor.bin'), 'rb') as fd: TestFunctional._MakeInputFile('descriptor.bin', fd.read()) @@ -5647,41 +5663,61 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testPreLoad(self): """Test an image with a pre-load header""" entry_args = { - 'pre-load-key-path': '.', + 'pre-load-key-path': os.path.join(self._binman_dir, 'test'), } - data, _, _, _ = self._DoReadFileDtb('230_pre_load.dts', - entry_args=entry_args) - 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)]) - data = self._DoReadFile('230_pre_load.dts') + data = self._DoReadFileDtb( + '230_pre_load.dts', entry_args=entry_args, + extra_indirs=[os.path.join(self._binman_dir, 'test')])[0] 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)]) + def testPreLoadNoKey(self): + """Test an image with a pre-load heade0r with missing key""" + with self.assertRaises(FileNotFoundError) as exc: + self._DoReadFile('230_pre_load.dts') + self.assertIn("No such file or directory: 'dev.key'", + str(exc.exception)) + def testPreLoadPkcs(self): """Test an image with a pre-load header with padding pkcs""" - data = self._DoReadFile('231_pre_load_pkcs.dts') + entry_args = { + 'pre-load-key-path': os.path.join(self._binman_dir, 'test'), + } + data = self._DoReadFileDtb('231_pre_load_pkcs.dts', + entry_args=entry_args)[0] 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)]) def testPreLoadPss(self): """Test an image with a pre-load header with padding pss""" - data = self._DoReadFile('232_pre_load_pss.dts') + entry_args = { + 'pre-load-key-path': os.path.join(self._binman_dir, 'test'), + } + data = self._DoReadFileDtb('232_pre_load_pss.dts', + entry_args=entry_args)[0] 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)]) def testPreLoadInvalidPadding(self): """Test an image with a pre-load header with an invalid padding""" + entry_args = { + 'pre-load-key-path': os.path.join(self._binman_dir, 'test'), + } with self.assertRaises(ValueError) as e: - data = self._DoReadFile('233_pre_load_invalid_padding.dts') + self._DoReadFileDtb('233_pre_load_invalid_padding.dts', + entry_args=entry_args) def testPreLoadInvalidSha(self): """Test an image with a pre-load header with an invalid hash""" + entry_args = { + 'pre-load-key-path': os.path.join(self._binman_dir, 'test'), + } with self.assertRaises(ValueError) as e: - data = self._DoReadFile('234_pre_load_invalid_sha.dts') + self._DoReadFileDtb('234_pre_load_invalid_sha.dts', + entry_args=entry_args) def testPreLoadInvalidAlgo(self): """Test an image with a pre-load header with an invalid algo""" @@ -5690,8 +5726,12 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testPreLoadInvalidKey(self): """Test an image with a pre-load header with an invalid key""" + entry_args = { + 'pre-load-key-path': os.path.join(self._binman_dir, 'test'), + } with self.assertRaises(ValueError) as e: - data = self._DoReadFile('236_pre_load_invalid_key.dts') + data = self._DoReadFileDtb('236_pre_load_invalid_key.dts', + entry_args=entry_args) def _CheckSafeUniqueNames(self, *images): """Check all entries of given images for unsafe unique names""" @@ -6659,18 +6699,18 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testPackRockchipTpl(self): """Test that an image with a Rockchip TPL binary can be created""" - data = self._DoReadFile('277_rockchip_tpl.dts') + data = self._DoReadFile('291_rockchip_tpl.dts') self.assertEqual(ROCKCHIP_TPL_DATA, data[:len(ROCKCHIP_TPL_DATA)]) def testMkimageMissingBlobMultiple(self): """Test missing blob with mkimage entry and multiple-data-files""" with test_util.capture_sys_output() as (stdout, stderr): - self._DoTestFile('278_mkimage_missing_multiple.dts', allow_missing=True) + self._DoTestFile('292_mkimage_missing_multiple.dts', allow_missing=True) err = stderr.getvalue() self.assertIn("is missing external blobs and is non-functional", err) with self.assertRaises(ValueError) as e: - self._DoTestFile('278_mkimage_missing_multiple.dts', allow_missing=False) + self._DoTestFile('292_mkimage_missing_multiple.dts', allow_missing=False) self.assertIn("not found in input path", str(e.exception)) def _PrepareSignEnv(self, dts='280_fit_sign.dts'): @@ -6906,19 +6946,19 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testTIBoardConfig(self): """Test that a schema validated board config file can be generated""" - data = self._DoReadFile('277_ti_board_cfg.dts') + data = self._DoReadFile('293_ti_board_cfg.dts') self.assertEqual(TI_BOARD_CONFIG_DATA, data) def testTIBoardConfigCombined(self): """Test that a schema validated combined board config file can be generated""" - data = self._DoReadFile('278_ti_board_cfg_combined.dts') + data = self._DoReadFile('294_ti_board_cfg_combined.dts') configlen_noheader = TI_BOARD_CONFIG_DATA * 4 self.assertGreater(data, configlen_noheader) def testTIBoardConfigNoDataType(self): """Test that error is thrown when data type is not supported""" with self.assertRaises(ValueError) as e: - data = self._DoReadFile('279_ti_board_cfg_no_type.dts') + data = self._DoReadFile('295_ti_board_cfg_no_type.dts') self.assertIn("Schema validation error", str(e.exception)) def testPackTiSecure(self): @@ -6927,7 +6967,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap entry_args = { 'keyfile': keyfile, } - data = self._DoReadFileDtb('279_ti_secure.dts', + data = self._DoReadFileDtb('296_ti_secure.dts', entry_args=entry_args)[0] self.assertGreater(len(data), len(TI_UNSECURE_DATA)) @@ -6939,7 +6979,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap 'keyfile': keyfile, } with test_util.capture_sys_output() as (_, stderr): - self._DoTestFile('279_ti_secure.dts', + self._DoTestFile('296_ti_secure.dts', force_missing_bintools='openssl', entry_args=entry_args) err = stderr.getvalue() @@ -6951,11 +6991,11 @@ fdt fdtmap Extract the devicetree blob from the fdtmap entry_args = { 'keyfile': keyfile, } - data = self._DoReadFileDtb('280_ti_secure_rom.dts', + data = self._DoReadFileDtb('297_ti_secure_rom.dts', entry_args=entry_args)[0] - data_a = self._DoReadFileDtb('288_ti_secure_rom_a.dts', + data_a = self._DoReadFileDtb('299_ti_secure_rom_a.dts', entry_args=entry_args)[0] - data_b = self._DoReadFileDtb('289_ti_secure_rom_b.dts', + data_b = self._DoReadFileDtb('300_ti_secure_rom_b.dts', entry_args=entry_args)[0] self.assertGreater(len(data), len(TI_UNSECURE_DATA)) self.assertGreater(len(data_a), len(TI_UNSECURE_DATA)) @@ -6967,9 +7007,85 @@ fdt fdtmap Extract the devicetree blob from the fdtmap entry_args = { 'keyfile': keyfile, } - data = self._DoReadFileDtb('281_ti_secure_rom_combined.dts', + data = self._DoReadFileDtb('298_ti_secure_rom_combined.dts', entry_args=entry_args)[0] self.assertGreater(len(data), len(TI_UNSECURE_DATA)) + def testEncryptedNoAlgo(self): + """Test encrypted node with missing required properties""" + with self.assertRaises(ValueError) as e: + self._DoReadFileDtb('301_encrypted_no_algo.dts') + self.assertIn( + "Node '/binman/fit/images/u-boot/encrypted': 'encrypted' entry is missing properties: algo iv-filename", + str(e.exception)) + + def testEncryptedInvalidIvfile(self): + """Test encrypted node with invalid iv file""" + with self.assertRaises(ValueError) as e: + self._DoReadFileDtb('302_encrypted_invalid_iv_file.dts') + self.assertIn("Filename 'invalid-iv-file' not found in input path", + str(e.exception)) + + def testEncryptedMissingKey(self): + """Test encrypted node with missing key properties""" + with self.assertRaises(ValueError) as e: + self._DoReadFileDtb('303_encrypted_missing_key.dts') + self.assertIn( + "Node '/binman/fit/images/u-boot/encrypted': Provide either 'key-filename' or 'key-source'", + str(e.exception)) + + def testEncryptedKeySource(self): + """Test encrypted node with key-source property""" + data = self._DoReadFileDtb('304_encrypted_key_source.dts')[0] + + dtb = fdt.Fdt.FromData(data) + dtb.Scan() + + node = dtb.GetNode('/images/u-boot/cipher') + self.assertEqual('algo-name', node.props['algo'].value) + self.assertEqual('key-source-value', node.props['key-source'].value) + self.assertEqual(ENCRYPTED_IV_DATA, + tools.to_bytes(''.join(node.props['iv'].value))) + self.assertNotIn('key', node.props) + + def testEncryptedKeyFile(self): + """Test encrypted node with key-filename property""" + data = self._DoReadFileDtb('305_encrypted_key_file.dts')[0] + + dtb = fdt.Fdt.FromData(data) + dtb.Scan() + + node = dtb.GetNode('/images/u-boot/cipher') + self.assertEqual('algo-name', node.props['algo'].value) + self.assertEqual(ENCRYPTED_IV_DATA, + tools.to_bytes(''.join(node.props['iv'].value))) + self.assertEqual(ENCRYPTED_KEY_DATA, + tools.to_bytes(''.join(node.props['key'].value))) + self.assertNotIn('key-source', node.props) + + + def testSplPubkeyDtb(self): + """Test u_boot_spl_pubkey_dtb etype""" + data = tools.read_file(self.TestFile("key.pem")) + self._MakeInputFile("key.crt", data) + self._DoReadFileRealDtb('306_spl_pubkey_dtb.dts') + image = control.images['image'] + entries = image.GetEntries() + dtb_entry = entries['u-boot-spl-pubkey-dtb'] + dtb_data = dtb_entry.GetData() + dtb = fdt.Fdt.FromData(dtb_data) + dtb.Scan() + + signature_node = dtb.GetNode('/signature') + self.assertIsNotNone(signature_node) + key_node = signature_node.FindNode("key-key") + self.assertIsNotNone(key_node) + self.assertEqual(fdt_util.GetString(key_node, "required"), + "conf") + self.assertEqual(fdt_util.GetString(key_node, "algo"), + "sha384,rsa4096") + self.assertEqual(fdt_util.GetString(key_node, "key-name-hint"), + "key") + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/230_pre_load.dts b/tools/binman/test/230_pre_load.dts index c0c2472..e6d9ef4 100644 --- a/tools/binman/test/230_pre_load.dts +++ b/tools/binman/test/230_pre_load.dts @@ -10,7 +10,7 @@ pre-load { content = <&image>; algo-name = "sha256,rsa2048"; - key-name = "tools/binman/test/230_dev.key"; + key-name = "dev.key"; header-size = <4096>; version = <0x11223344>; }; diff --git a/tools/binman/test/231_pre_load_pkcs.dts b/tools/binman/test/231_pre_load_pkcs.dts index 530638c..66268cd 100644 --- a/tools/binman/test/231_pre_load_pkcs.dts +++ b/tools/binman/test/231_pre_load_pkcs.dts @@ -11,7 +11,7 @@ content = <&image>; algo-name = "sha256,rsa2048"; padding-name = "pkcs-1.5"; - key-name = "tools/binman/test/230_dev.key"; + key-name = "dev.key"; header-size = <4096>; version = <0x11223344>; }; diff --git a/tools/binman/test/232_pre_load_pss.dts b/tools/binman/test/232_pre_load_pss.dts index 371e0fd..3008d3f 100644 --- a/tools/binman/test/232_pre_load_pss.dts +++ b/tools/binman/test/232_pre_load_pss.dts @@ -11,7 +11,7 @@ content = <&image>; algo-name = "sha256,rsa2048"; padding-name = "pss"; - key-name = "tools/binman/test/230_dev.key"; + key-name = "dev.key"; header-size = <4096>; version = <0x11223344>; }; diff --git a/tools/binman/test/233_pre_load_invalid_padding.dts b/tools/binman/test/233_pre_load_invalid_padding.dts index 9cb4cb5..bbe2d1b 100644 --- a/tools/binman/test/233_pre_load_invalid_padding.dts +++ b/tools/binman/test/233_pre_load_invalid_padding.dts @@ -11,7 +11,7 @@ content = <&image>; algo-name = "sha256,rsa2048"; padding-name = "padding"; - key-name = "tools/binman/test/230_dev.key"; + key-name = "dev.key"; header-size = <4096>; version = <1>; }; diff --git a/tools/binman/test/234_pre_load_invalid_sha.dts b/tools/binman/test/234_pre_load_invalid_sha.dts index 8ded98d..29afd2e 100644 --- a/tools/binman/test/234_pre_load_invalid_sha.dts +++ b/tools/binman/test/234_pre_load_invalid_sha.dts @@ -11,7 +11,7 @@ content = <&image>; algo-name = "sha2560,rsa2048"; padding-name = "pkcs-1.5"; - key-name = "tools/binman/test/230_dev.key"; + key-name = "dev.key"; header-size = <4096>; version = <1>; }; diff --git a/tools/binman/test/235_pre_load_invalid_algo.dts b/tools/binman/test/235_pre_load_invalid_algo.dts index 145286c..d6f6dd2 100644 --- a/tools/binman/test/235_pre_load_invalid_algo.dts +++ b/tools/binman/test/235_pre_load_invalid_algo.dts @@ -11,7 +11,7 @@ content = <&image>; algo-name = "sha256,rsa20480"; padding-name = "pkcs-1.5"; - key-name = "tools/binman/test/230_dev.key"; + key-name = "dev.key"; header-size = <4096>; version = <1>; }; diff --git a/tools/binman/test/236_pre_load_invalid_key.dts b/tools/binman/test/236_pre_load_invalid_key.dts index df858c3..f93bc97 100644 --- a/tools/binman/test/236_pre_load_invalid_key.dts +++ b/tools/binman/test/236_pre_load_invalid_key.dts @@ -11,7 +11,7 @@ content = <&image>; algo-name = "sha256,rsa4096"; padding-name = "pkcs-1.5"; - key-name = "tools/binman/test/230_dev.key"; + key-name = "dev.key"; header-size = <4096>; version = <1>; }; diff --git a/tools/binman/test/277_rockchip_tpl.dts b/tools/binman/test/291_rockchip_tpl.dts index 269f56e..269f56e 100644 --- a/tools/binman/test/277_rockchip_tpl.dts +++ b/tools/binman/test/291_rockchip_tpl.dts diff --git a/tools/binman/test/278_mkimage_missing_multiple.dts b/tools/binman/test/292_mkimage_missing_multiple.dts index f84aea4..f84aea4 100644 --- a/tools/binman/test/278_mkimage_missing_multiple.dts +++ b/tools/binman/test/292_mkimage_missing_multiple.dts diff --git a/tools/binman/test/277_ti_board_cfg.dts b/tools/binman/test/293_ti_board_cfg.dts index cda024c..cda024c 100644 --- a/tools/binman/test/277_ti_board_cfg.dts +++ b/tools/binman/test/293_ti_board_cfg.dts diff --git a/tools/binman/test/278_ti_board_cfg_combined.dts b/tools/binman/test/294_ti_board_cfg_combined.dts index 95ef449..95ef449 100644 --- a/tools/binman/test/278_ti_board_cfg_combined.dts +++ b/tools/binman/test/294_ti_board_cfg_combined.dts diff --git a/tools/binman/test/279_ti_board_cfg_no_type.dts b/tools/binman/test/295_ti_board_cfg_no_type.dts index 584b7ac..584b7ac 100644 --- a/tools/binman/test/279_ti_board_cfg_no_type.dts +++ b/tools/binman/test/295_ti_board_cfg_no_type.dts diff --git a/tools/binman/test/279_ti_secure.dts b/tools/binman/test/296_ti_secure.dts index 941d0ab..941d0ab 100644 --- a/tools/binman/test/279_ti_secure.dts +++ b/tools/binman/test/296_ti_secure.dts diff --git a/tools/binman/test/280_ti_secure_rom.dts b/tools/binman/test/297_ti_secure_rom.dts index d131376..d131376 100644 --- a/tools/binman/test/280_ti_secure_rom.dts +++ b/tools/binman/test/297_ti_secure_rom.dts diff --git a/tools/binman/test/281_ti_secure_rom_combined.dts b/tools/binman/test/298_ti_secure_rom_combined.dts index bf87273..bf87273 100644 --- a/tools/binman/test/281_ti_secure_rom_combined.dts +++ b/tools/binman/test/298_ti_secure_rom_combined.dts diff --git a/tools/binman/test/288_ti_secure_rom_a.dts b/tools/binman/test/299_ti_secure_rom_a.dts index 887138f..887138f 100644 --- a/tools/binman/test/288_ti_secure_rom_a.dts +++ b/tools/binman/test/299_ti_secure_rom_a.dts diff --git a/tools/binman/test/289_ti_secure_rom_b.dts b/tools/binman/test/300_ti_secure_rom_b.dts index c6d6182..c6d6182 100644 --- a/tools/binman/test/289_ti_secure_rom_b.dts +++ b/tools/binman/test/300_ti_secure_rom_b.dts diff --git a/tools/binman/test/301_encrypted_no_algo.dts b/tools/binman/test/301_encrypted_no_algo.dts new file mode 100644 index 0000000..03f7ffe --- /dev/null +++ b/tools/binman/test/301_encrypted_no_algo.dts @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0+ +/dts-v1/; + +/ { + binman { + fit { + images { + u-boot { + encrypted { + }; + }; + }; + }; + }; +}; diff --git a/tools/binman/test/302_encrypted_invalid_iv_file.dts b/tools/binman/test/302_encrypted_invalid_iv_file.dts new file mode 100644 index 0000000..388a0a6 --- /dev/null +++ b/tools/binman/test/302_encrypted_invalid_iv_file.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ +/dts-v1/; + +/ { + binman { + fit { + images { + u-boot { + encrypted { + algo = "some-algo"; + key-source = "key"; + iv-filename = "invalid-iv-file"; + }; + }; + }; + }; + }; +}; diff --git a/tools/binman/test/303_encrypted_missing_key.dts b/tools/binman/test/303_encrypted_missing_key.dts new file mode 100644 index 0000000..d1daaa0 --- /dev/null +++ b/tools/binman/test/303_encrypted_missing_key.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + fit { + description = "test desc"; + + images { + u-boot { + encrypted { + algo = "algo-name"; + iv-filename = "encrypted-file.iv"; + }; + }; + }; + }; + }; +}; diff --git a/tools/binman/test/304_encrypted_key_source.dts b/tools/binman/test/304_encrypted_key_source.dts new file mode 100644 index 0000000..884ec50 --- /dev/null +++ b/tools/binman/test/304_encrypted_key_source.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + fit { + description = "test desc"; + + images { + u-boot { + encrypted { + algo = "algo-name"; + key-source = "key-source-value"; + iv-filename = "encrypted-file.iv"; + }; + }; + }; + }; + }; +}; diff --git a/tools/binman/test/305_encrypted_key_file.dts b/tools/binman/test/305_encrypted_key_file.dts new file mode 100644 index 0000000..efd7ee5 --- /dev/null +++ b/tools/binman/test/305_encrypted_key_file.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + fit { + description = "test desc"; + + images { + u-boot { + encrypted { + algo = "algo-name"; + iv-filename = "encrypted-file.iv"; + key-filename = "encrypted-file.key"; + }; + }; + }; + }; + }; +}; diff --git a/tools/binman/test/306_spl_pubkey_dtb.dts b/tools/binman/test/306_spl_pubkey_dtb.dts new file mode 100644 index 0000000..3256ff9 --- /dev/null +++ b/tools/binman/test/306_spl_pubkey_dtb.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + u-boot-spl-pubkey-dtb { + algo = "sha384,rsa4096"; + required = "conf"; + key-name-hint = "key"; + }; + }; +}; diff --git a/tools/binman/test/230_dev.key b/tools/binman/test/dev.key index b36bad2..b36bad2 100644 --- a/tools/binman/test/230_dev.key +++ b/tools/binman/test/dev.key |