| # 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) |