
From: Christian Taedcke christian.taedcke@weidmueller.com
This adds a new etype encrypted that is derived from collection.
It creates a new cipher node in the related image similar to the cipher node used by u-boot, see boot/image-cipher.c. Optionally it creates a global /cipher node containing a key and iv using the same nameing convention as used in boot/image-cipher.c.
Signed-off-by: Christian Taedcke christian.taedcke@weidmueller.com ---
tools/binman/etype/encrypted.py | 98 +++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tools/binman/etype/encrypted.py
diff --git a/tools/binman/etype/encrypted.py b/tools/binman/etype/encrypted.py new file mode 100644 index 0000000000..005ae56acf --- /dev/null +++ b/tools/binman/etype/encrypted.py @@ -0,0 +1,98 @@ +# 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/images +# + +from binman.etype.collection import Entry_collection +from dtoc import fdt_util +from u_boot_pylib import tools + +# This is imported if needed +state = None + + +class Entry_encrypted(Entry_collection): + """Externally built encrypted binary blob + + If the file providing this blob is missing, binman can optionally ignore it + and produce a broken image with a warning. + + In addition to the inherited 'collection' for Properties / Entry arguments: + - algo: The encryption algorithm + - iv-name-hint: The name hint for the iv + - key-name-hint: The name hint for the key + - iv-filename: The name of the file containing the iv + - key-filename: The name of the file containing the key + + This entry creates a cipher node in the entries' parent node (i.e. the + image). Optionally it also creates a cipher node in the root of the device + tree containg key and iv information. + """ + + 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) + # The property key-filename is not required, because some implementations use keys that + # are not embedded in the device tree, but e.g. in the device itself + self.required_props = ['algo', 'key-name-hint', 'iv-filename'] + self._algo = fdt_util.GetString(self._node, 'algo') + self._iv_name_hint = fdt_util.GetString(self._node, 'iv-name-hint') + self._key_name_hint = fdt_util.GetString(self._node, 'key-name-hint') + self._filename_iv = fdt_util.GetString(self._node, 'iv-filename') + self._filename_key = fdt_util.GetString(self._node, 'key-filename') + + def ReadNode(self): + super().ReadNode() + + iv_filename = tools.get_input_filename(self._filename_iv) + self._iv = tools.read_file(iv_filename, binary=True) + + self._key = None + if self._filename_key: + key_filename = tools.get_input_filename(self._filename_key) + self._key = tools.read_file(key_filename, binary=True) + + def gen_entries(self): + super().gen_entries() + + cipher_node = state.AddSubnode(self._node.parent, "cipher") + cipher_node.AddString("algo", self._algo) + cipher_node.AddString("key-name-hint", self._key_name_hint) + if self._iv_name_hint: + cipher_node.AddString("iv-name-hint", self._iv_name_hint) + else: + cipher_node.AddData("iv", self._iv) + + if self._key or self._iv_name_hint: + # add cipher node in root + root_node = self._node.parent.parent.parent + name = "cipher" + cipher_node = root_node.FindNode(name) + if not cipher_node: + cipher_node = state.AddSubnode(root_node, name) + key_node_name = ( + f"key-{self._algo}-{self._key_name_hint}-{self._iv_name_hint}" + if self._iv_name_hint + else f"key-{self._algo}-{self._key_name_hint}" + ) + key_node = cipher_node.FindNode(key_node_name) + if not key_node: + key_node = state.AddSubnode(cipher_node, key_node_name) + if self._key: + key_node.AddData("key", self._key) + if self._iv_name_hint: + key_node.AddData("iv", self._iv) + + def ObtainContents(self): + # ensure that linked content is not added to the device tree again from this entry + self.SetContents(b'') + return True + + def ProcessContents(self): + # ensure that linked content is not added to the device tree again from this entry + return self.ProcessContentsUpdate(b'')