summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2022-03-31 14:12:30 -0400
committerTom Rini <[email protected]>2022-03-31 14:12:30 -0400
commit52d8100b1d60b656e3e311e3312fed43d388088a (patch)
treecb370025bcc386ef741cce94bda1b4dd58fe2d76 /tools
parent23e354f82c04a1c070ca59907abc6b042761b0e7 (diff)
parent7bebc11c42351c8f0364f0e3eb922f5af7b6e826 (diff)
Merge branch '2022-03-31-image-add-a-stage-pre-load' into next
To quote the author: This series adds a stage pre-load before launching an image. This stage is used to read a header before the image and this header contains the signature of the full image. So u-boot may check the full image before using any data of the image. The support of this header is added to binman, and a command verify checks the signature of a blob and set the u-boot env variable "loadaddr_verified" to the beginning of the "real" image. The support of this header is only added to binman, but it may also be added to mkimage.
Diffstat (limited to 'tools')
-rw-r--r--tools/binman/entries.rst38
-rw-r--r--tools/binman/etype/pre_load.py162
-rw-r--r--tools/binman/ftest.py51
-rw-r--r--tools/binman/test/225_dev.key28
-rw-r--r--tools/binman/test/225_pre_load.dts22
-rw-r--r--tools/binman/test/226_pre_load_pkcs.dts23
-rw-r--r--tools/binman/test/227_pre_load_pss.dts23
-rw-r--r--tools/binman/test/228_pre_load_invalid_padding.dts23
-rw-r--r--tools/binman/test/229_pre_load_invalid_sha.dts23
-rw-r--r--tools/binman/test/230_pre_load_invalid_algo.dts23
-rw-r--r--tools/binman/test/231_pre_load_invalid_key.dts23
-rw-r--r--tools/fit_image.c3
-rw-r--r--tools/image-host.c114
13 files changed, 556 insertions, 0 deletions
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index be8de5560c4..ae4305c99e4 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -1155,6 +1155,44 @@ placed at offset 'RESET_VECTOR_ADDRESS - 0xffc'.
+Entry: pre-load: Pre load image header
+--------------------------------------
+
+Properties / Entry arguments:
+ - key-path: Path of the directory that store key (provided by the environment variable KEY_PATH)
+ - content: List of phandles to entries to sign
+ - algo-name: Hash and signature algo to use for the signature
+ - padding-name: Name of the padding (pkcs-1.5 or pss)
+ - key-name: Filename of the private key to sign
+ - header-size: Total size of the header
+ - version: Version of the header
+
+This entry creates a pre-load header that contains a global
+image signature.
+
+For example, this creates an image with a pre-load header and a binary::
+
+ binman {
+ image2 {
+ filename = "sandbox.bin";
+
+ pre-load {
+ content = <&image>;
+ algo-name = "sha256,rsa2048";
+ padding-name = "pss";
+ key-name = "private.pem";
+ header-size = <4096>;
+ version = <1>;
+ };
+
+ image: blob-ext {
+ filename = "sandbox.itb";
+ };
+ };
+ };
+
+
+
Entry: scp: System Control Processor (SCP) firmware blob
--------------------------------------------------------
diff --git a/tools/binman/etype/pre_load.py b/tools/binman/etype/pre_load.py
new file mode 100644
index 00000000000..245ee755259
--- /dev/null
+++ b/tools/binman/etype/pre_load.py
@@ -0,0 +1,162 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2022 Softathome
+# Written by Philippe Reynes <[email protected]>
+#
+# Entry-type for the global header
+#
+
+import os
+import struct
+from dtoc import fdt_util
+from patman import tools
+
+from binman.entry import Entry
+from binman.etype.collection import Entry_collection
+from binman.entry import EntryArg
+
+from Cryptodome.Hash import SHA256, SHA384, SHA512
+from Cryptodome.PublicKey import RSA
+from Cryptodome.Signature import pkcs1_15
+from Cryptodome.Signature import pss
+
+PRE_LOAD_MAGIC = b'UBSH'
+
+RSAS = {
+ 'rsa1024': 1024 / 8,
+ 'rsa2048': 2048 / 8,
+ 'rsa4096': 4096 / 8
+}
+
+SHAS = {
+ 'sha256': SHA256,
+ 'sha384': SHA384,
+ 'sha512': SHA512
+}
+
+class Entry_pre_load(Entry_collection):
+ """Pre load image header
+
+ Properties / Entry arguments:
+ - pre-load-key-path: Path of the directory that store key (provided by the environment variable PRE_LOAD_KEY_PATH)
+ - content: List of phandles to entries to sign
+ - algo-name: Hash and signature algo to use for the signature
+ - padding-name: Name of the padding (pkcs-1.5 or pss)
+ - key-name: Filename of the private key to sign
+ - header-size: Total size of the header
+ - version: Version of the header
+
+ This entry creates a pre-load header that contains a global
+ image signature.
+
+ For example, this creates an image with a pre-load header and a binary::
+
+ binman {
+ image2 {
+ filename = "sandbox.bin";
+
+ pre-load {
+ content = <&image>;
+ algo-name = "sha256,rsa2048";
+ padding-name = "pss";
+ key-name = "private.pem";
+ header-size = <4096>;
+ version = <1>;
+ };
+
+ image: blob-ext {
+ filename = "sandbox.itb";
+ };
+ };
+ };
+ """
+
+ def __init__(self, section, etype, node):
+ super().__init__(section, etype, node)
+ self.algo_name = fdt_util.GetString(self._node, 'algo-name')
+ self.padding_name = fdt_util.GetString(self._node, 'padding-name')
+ self.key_name = fdt_util.GetString(self._node, 'key-name')
+ self.header_size = fdt_util.GetInt(self._node, 'header-size')
+ self.version = fdt_util.GetInt(self._node, 'version')
+
+ def ReadNode(self):
+ super().ReadNode()
+ self.key_path, = self.GetEntryArgsOrProps([EntryArg('pre-load-key-path', str)])
+ if self.key_path is None:
+ self.key_path = ''
+
+ def _CreateHeader(self):
+ """Create a pre load header"""
+ hash_name, sign_name = self.algo_name.split(',')
+ padding_name = self.padding_name
+ key_name = os.path.join(self.key_path, self.key_name)
+
+ # Check hash and signature name/type
+ if hash_name not in SHAS:
+ self.Raise(hash_name + " is not supported")
+ if sign_name not in RSAS:
+ self.Raise(sign_name + " is not supported")
+
+ # Read the key
+ with open(key_name, 'rb') as pem:
+ key = RSA.import_key(pem.read())
+
+ # Check if the key has the expected size
+ if key.size_in_bytes() != RSAS[sign_name]:
+ self.Raise("The key " + self.key_name + " don't have the expected size")
+
+ # Compute the hash
+ hash_image = SHAS[hash_name].new()
+ hash_image.update(self.image)
+
+ # Compute the signature
+ if padding_name is None:
+ padding_name = "pkcs-1.5"
+ if padding_name == "pss":
+ salt_len = key.size_in_bytes() - hash_image.digest_size - 2
+ padding = pss
+ padding_args = {'salt_bytes': salt_len}
+ elif padding_name == "pkcs-1.5":
+ padding = pkcs1_15
+ padding_args = {}
+ else:
+ self.Raise(padding_name + " is not supported")
+
+ sig = padding.new(key, **padding_args).sign(hash_image)
+
+ hash_sig = SHA256.new()
+ hash_sig.update(sig)
+
+ version = self.version
+ header_size = self.header_size
+ image_size = len(self.image)
+ ofs_img_sig = 64 + len(sig)
+ flags = 0
+ reserved0 = 0
+ reserved1 = 0
+
+ first_header = struct.pack('>4sIIIIIII32s', PRE_LOAD_MAGIC,
+ version, header_size, image_size,
+ ofs_img_sig, flags, reserved0,
+ reserved1, hash_sig.digest())
+
+ hash_first_header = SHAS[hash_name].new()
+ hash_first_header.update(first_header)
+ sig_first_header = padding.new(key, **padding_args).sign(hash_first_header)
+
+ data = first_header + sig_first_header + sig
+ pad = bytearray(self.header_size - len(data))
+
+ return data + pad
+
+ def ObtainContents(self):
+ """Obtain a placeholder for the header contents"""
+ # wait that the image is available
+ self.image = self.GetContents(False)
+ if self.image is None:
+ return False
+ self.SetContents(self._CreateHeader())
+ return True
+
+ def ProcessContents(self):
+ data = self._CreateHeader()
+ return self.ProcessContentsUpdate(data)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 876953f1132..4ce181a0666 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -91,6 +91,9 @@ SCP_DATA = b'scp'
TEST_FDT1_DATA = b'fdt1'
TEST_FDT2_DATA = b'test-fdt2'
ENV_DATA = b'var1=1\nvar2="2"'
+PRE_LOAD_MAGIC = b'UBSH'
+PRE_LOAD_VERSION = 0x11223344.to_bytes(4, 'big')
+PRE_LOAD_HDR_SIZE = 0x00001000.to_bytes(4, 'big')
# Subdirectory of the input dir to use to put test FDTs
TEST_FDT_SUBDIR = 'fdts'
@@ -5471,6 +5474,54 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
err,
"Image '.*' is missing external blobs and is non-functional: .*")
+ def testPreLoad(self):
+ """Test an image with a pre-load header"""
+ entry_args = {
+ 'pre-load-key-path': '.',
+ }
+ data, _, _, _ = self._DoReadFileDtb('225_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('225_pre_load.dts')
+ 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 testPreLoadPkcs(self):
+ """Test an image with a pre-load header with padding pkcs"""
+ data = self._DoReadFile('226_pre_load_pkcs.dts')
+ 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('227_pre_load_pss.dts')
+ 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"""
+ with self.assertRaises(ValueError) as e:
+ data = self._DoReadFile('228_pre_load_invalid_padding.dts')
+
+ def testPreLoadInvalidSha(self):
+ """Test an image with a pre-load header with an invalid hash"""
+ with self.assertRaises(ValueError) as e:
+ data = self._DoReadFile('229_pre_load_invalid_sha.dts')
+
+ def testPreLoadInvalidAlgo(self):
+ """Test an image with a pre-load header with an invalid algo"""
+ with self.assertRaises(ValueError) as e:
+ data = self._DoReadFile('230_pre_load_invalid_algo.dts')
+
+ def testPreLoadInvalidKey(self):
+ """Test an image with a pre-load header with an invalid key"""
+ with self.assertRaises(ValueError) as e:
+ data = self._DoReadFile('231_pre_load_invalid_key.dts')
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/225_dev.key b/tools/binman/test/225_dev.key
new file mode 100644
index 00000000000..b36bad2cfb3
--- /dev/null
+++ b/tools/binman/test/225_dev.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDYngNWUvXYRXX/
+WEUI7k164fcpv1srXz+u+5Y3Yhouw3kPs+ffvYyHAPfjF7aUIAgezKk/4o7AvsxE
+Rdih3T+0deAd/q/yuqN4Adzt6ImnsO/EqdtYl3Yh+Vck9xWhLd3SAw1++GfSmNMT
+gxlcc/z6z+bIh2tJNtPtRSNNHMmvYYOkBmkfwcjbMXD+fe4vBwYjVrIize+l7Yuv
+1qN2nFlq56pFi8Lj5vOvFyNhZHRvwcpWdUdkx39beNUfwrGhgewOeWngTcY75n7S
+FY45TBR1G2PR90CQvyDinCi9Mm0u5s+1WASQWPblovfD6CPbHQu4GZm+FAs7yUvr
+hA7VCyNxAgMBAAECggEAUbq0uaJNfc8faTtNuMPo2d9eGRNI+8FRTt0/3R+Xj2NT
+TvhrGUD0P4++96Df012OkshXZ3I8uD6E5ZGQ3emTeqwq5kZM7oE64jGZwO3G2k1o
++cO4reFfwgvItHrBX3HlyrI6KljhG1Vr9mW1cOuWXK+KfMiTUylrpo86dYLSGeg3
+7ZlsOPArr4eof/A0iPryQZX6X5POf7k/e9qRFYsOkoRQO8pBL3J4rIKwBl3uBN3K
++FY40vCkd8JyTo2DNfHeIe1XYA9fG2ahjD2qMsw10TUsRRMd5yhonEcJ7VzGzy8m
+MnuMDAr7CwbbLkKi4UfZUl6YDkojqerwLOrxikBqkQKBgQD6sS6asDgwiq5MtstE
+4/PxMrVEsCdkrU+jjQN749qIt/41a6lbp0Pr6aUKKKGs0QbcnCtlpp7qmhvymBcW
+hlqxk2wokKMChv4WLXjZS3DGcOdMglc81y2F+252bToN8vwUfm6DPp9/GKtejA0a
+GP57GeHxoVO7vfDX1F/vZRogRQKBgQDdNCLWOlGWvnKjfgNZHgX+Ou6ZgTSAzy+/
+hRsZPlY5nwO5iD7YkIKvqBdOmfyjlUpHWk2uAcT9pfgzYygvyBRaoQhAYBGkHItt
+slaMxnLd+09wWufoCbgJvFn+wVQxBLcA5PXB98ws0Dq8ZYuo6AOuoRivsSO4lblK
+MW0guBJXPQKBgQDGjf0ukbH/aGfC5Oi8SJvWhuYhYC/jQo2YKUEAKCjXLnuOThZW
+PHXEbUrFcAcVfH0l0B9jJIQrpiHKlAF9Wq6MhQoeWuhxQQAQCrXzzRemZJgd9gIo
+cvlgbBNCgyJ/F9vmU3kuRDRJkv1wJhbee7tbPtXA7pkGUttl5pSRZI87zQKBgQC/
+0ZkwCox72xTQP9MpcYai6nnDta5Q0NnIC+Xu4wakmwcA2WweIlqhdnMXnyLcu/YY
+n+9iqHgpuMXd0eukW62C1cexA13o4TPrYU36b5BmfKprdPlLVzo3fxTPfNjEVSFY
+7jNLC9YLOlrkym3sf53Jzjr5B/RA+d0ewHOwfs6wxQKBgFSyfjx5wtdHK4fO+Z1+
+q3bxouZryM/4CiPCFuw4+aZmRHPmufuNCvfXdF+IH8dM0E9ObwKZAe/aMP/Y+Abx
+Wz9Vm4CP6g7k3DU3INEygyjmIQQDKQ9lFdDnsP9ESzrPbaGxZhc4x2lo7qmeW1BR
+/RuiAofleFkT4s+EhLrfE/v5
+-----END PRIVATE KEY-----
diff --git a/tools/binman/test/225_pre_load.dts b/tools/binman/test/225_pre_load.dts
new file mode 100644
index 00000000000..c1ffe1a2ff4
--- /dev/null
+++ b/tools/binman/test/225_pre_load.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pre-load {
+ content = <&image>;
+ algo-name = "sha256,rsa2048";
+ key-name = "tools/binman/test/225_dev.key";
+ header-size = <4096>;
+ version = <0x11223344>;
+ };
+
+ image: blob-ext {
+ filename = "refcode.bin";
+ };
+ };
+};
diff --git a/tools/binman/test/226_pre_load_pkcs.dts b/tools/binman/test/226_pre_load_pkcs.dts
new file mode 100644
index 00000000000..3db0a37f774
--- /dev/null
+++ b/tools/binman/test/226_pre_load_pkcs.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pre-load {
+ content = <&image>;
+ algo-name = "sha256,rsa2048";
+ padding-name = "pkcs-1.5";
+ key-name = "tools/binman/test/225_dev.key";
+ header-size = <4096>;
+ version = <0x11223344>;
+ };
+
+ image: blob-ext {
+ filename = "refcode.bin";
+ };
+ };
+};
diff --git a/tools/binman/test/227_pre_load_pss.dts b/tools/binman/test/227_pre_load_pss.dts
new file mode 100644
index 00000000000..b1b01d5ad58
--- /dev/null
+++ b/tools/binman/test/227_pre_load_pss.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pre-load {
+ content = <&image>;
+ algo-name = "sha256,rsa2048";
+ padding-name = "pss";
+ key-name = "tools/binman/test/225_dev.key";
+ header-size = <4096>;
+ version = <0x11223344>;
+ };
+
+ image: blob-ext {
+ filename = "refcode.bin";
+ };
+ };
+};
diff --git a/tools/binman/test/228_pre_load_invalid_padding.dts b/tools/binman/test/228_pre_load_invalid_padding.dts
new file mode 100644
index 00000000000..84fe289183f
--- /dev/null
+++ b/tools/binman/test/228_pre_load_invalid_padding.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pre-load {
+ content = <&image>;
+ algo-name = "sha256,rsa2048";
+ padding-name = "padding";
+ key-name = "tools/binman/test/225_dev.key";
+ header-size = <4096>;
+ version = <1>;
+ };
+
+ image: blob-ext {
+ filename = "refcode.bin";
+ };
+ };
+};
diff --git a/tools/binman/test/229_pre_load_invalid_sha.dts b/tools/binman/test/229_pre_load_invalid_sha.dts
new file mode 100644
index 00000000000..a2b6725c892
--- /dev/null
+++ b/tools/binman/test/229_pre_load_invalid_sha.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pre-load {
+ content = <&image>;
+ algo-name = "sha2560,rsa2048";
+ padding-name = "pkcs-1.5";
+ key-name = "tools/binman/test/225_dev.key";
+ header-size = <4096>;
+ version = <1>;
+ };
+
+ image: blob-ext {
+ filename = "refcode.bin";
+ };
+ };
+};
diff --git a/tools/binman/test/230_pre_load_invalid_algo.dts b/tools/binman/test/230_pre_load_invalid_algo.dts
new file mode 100644
index 00000000000..34c8d34f157
--- /dev/null
+++ b/tools/binman/test/230_pre_load_invalid_algo.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pre-load {
+ content = <&image>;
+ algo-name = "sha256,rsa20480";
+ padding-name = "pkcs-1.5";
+ key-name = "tools/binman/test/225_dev.key";
+ header-size = <4096>;
+ version = <1>;
+ };
+
+ image: blob-ext {
+ filename = "refcode.bin";
+ };
+ };
+};
diff --git a/tools/binman/test/231_pre_load_invalid_key.dts b/tools/binman/test/231_pre_load_invalid_key.dts
new file mode 100644
index 00000000000..08d5a75ddfd
--- /dev/null
+++ b/tools/binman/test/231_pre_load_invalid_key.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pre-load {
+ content = <&image>;
+ algo-name = "sha256,rsa4096";
+ padding-name = "pkcs-1.5";
+ key-name = "tools/binman/test/225_dev.key";
+ header-size = <4096>;
+ version = <1>;
+ };
+
+ image: blob-ext {
+ filename = "refcode.bin";
+ };
+ };
+};
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 15f7c82d619..1884a2eb0b9 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -59,6 +59,9 @@ static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
ret = fit_set_timestamp(ptr, 0, time);
}
+ if (!ret)
+ ret = fit_pre_load_data(params->keydir, dest_blob, ptr);
+
if (!ret) {
ret = fit_cipher_data(params->keydir, dest_blob, ptr,
params->comment,
diff --git a/tools/image-host.c b/tools/image-host.c
index eaeb76545c6..ab6f756cf1b 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -14,6 +14,11 @@
#include <image.h>
#include <version.h>
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+
+#define IMAGE_PRE_LOAD_PATH "/image/pre-load/sig"
+
/**
* fit_set_hash_value - set hash value in requested has node
* @fit: pointer to the FIT format image header
@@ -1111,6 +1116,115 @@ static int fit_config_add_verification_data(const char *keydir,
return 0;
}
+/*
+ * 0) open file (open)
+ * 1) read certificate (PEM_read_X509)
+ * 2) get public key (X509_get_pubkey)
+ * 3) provide der format (d2i_RSAPublicKey)
+ */
+static int read_pub_key(const char *keydir, const void *name,
+ unsigned char **pubkey, int *pubkey_len)
+{
+ char path[1024];
+ EVP_PKEY *key = NULL;
+ X509 *cert;
+ FILE *f;
+ int ret;
+
+ memset(path, 0, 1024);
+ snprintf(path, sizeof(path), "%s/%s.crt", keydir, (char *)name);
+
+ /* Open certificate file */
+ f = fopen(path, "r");
+ if (!f) {
+ fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
+ path, strerror(errno));
+ return -EACCES;
+ }
+
+ /* Read the certificate */
+ cert = NULL;
+ if (!PEM_read_X509(f, &cert, NULL, NULL)) {
+ printf("Couldn't read certificate");
+ ret = -EINVAL;
+ goto err_cert;
+ }
+
+ /* Get the public key from the certificate. */
+ key = X509_get_pubkey(cert);
+ if (!key) {
+ printf("Couldn't read public key\n");
+ ret = -EINVAL;
+ goto err_pubkey;
+ }
+
+ /* Get DER form */
+ ret = i2d_PublicKey(key, pubkey);
+ if (ret < 0) {
+ printf("Couldn't get DER form\n");
+ ret = -EINVAL;
+ goto err_pubkey;
+ }
+
+ *pubkey_len = ret;
+ ret = 0;
+
+err_pubkey:
+ X509_free(cert);
+err_cert:
+ fclose(f);
+ return ret;
+}
+
+int fit_pre_load_data(const char *keydir, void *keydest, void *fit)
+{
+ int pre_load_noffset;
+ const void *algo_name;
+ const void *key_name;
+ unsigned char *pubkey = NULL;
+ int ret, pubkey_len;
+
+ if (!keydir || !keydest || !fit)
+ return 0;
+
+ /* Search node pre-load sig */
+ pre_load_noffset = fdt_path_offset(keydest, IMAGE_PRE_LOAD_PATH);
+ if (pre_load_noffset < 0) {
+ ret = 0;
+ goto out;
+ }
+
+ algo_name = fdt_getprop(keydest, pre_load_noffset, "algo-name", NULL);
+ key_name = fdt_getprop(keydest, pre_load_noffset, "key-name", NULL);
+
+ /* Check that all mandatory properties are present */
+ if (!algo_name || !key_name) {
+ if (!algo_name)
+ printf("The property algo-name is missing in the node %s\n",
+ IMAGE_PRE_LOAD_PATH);
+ if (!key_name)
+ printf("The property key-name is missing in the node %s\n",
+ IMAGE_PRE_LOAD_PATH);
+ ret = -ENODATA;
+ goto out;
+ }
+
+ /* Read public key */
+ ret = read_pub_key(keydir, key_name, &pubkey, &pubkey_len);
+ if (ret < 0)
+ goto out;
+
+ /* Add the public key to the device tree */
+ ret = fdt_setprop(keydest, pre_load_noffset, "public-key",
+ pubkey, pubkey_len);
+ if (ret)
+ printf("Can't set public-key in node %s (ret = %d)\n",
+ IMAGE_PRE_LOAD_PATH, ret);
+
+ out:
+ return ret;
+}
+
int fit_cipher_data(const char *keydir, void *keydest, void *fit,
const char *comment, int require_keys,
const char *engine_id, const char *cmdname)