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