binman: Add support for externally encrypted blobs

This adds a new etype encrypted.

It creates a new cipher node in the related image similar to the
cipher node used by u-boot, see boot/image-cipher.c.

Signed-off-by: Christian Taedcke <christian.taedcke@weidmueller.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Christian Taedcke 2023-07-17 09:05:52 +02:00 committed by Simon Glass
parent df11aa7d74
commit 473e5206f0
2 changed files with 224 additions and 0 deletions

View file

@ -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

View file

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