mkimage: add public key for image pre-load stage
This commit enhances mkimage to update the node
/image/pre-load/sig with the public key.
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com>
diff --git a/include/image.h b/include/image.h
index 496b7af..498eb7f 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1019,6 +1019,21 @@
int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
+/**
+ * fit_pre_load_data() - add public key to fdt blob
+ *
+ * Adds public key to the node pre load.
+ *
+ * @keydir: Directory containing keys
+ * @keydest: FDT blob to write public key
+ * @fit: Pointer to the FIT format image header
+ *
+ * returns:
+ * 0, on success
+ * < 0, on failure
+ */
+int fit_pre_load_data(const char *keydir, void *keydest, void *fit);
+
int fit_cipher_data(const char *keydir, void *keydest, void *fit,
const char *comment, int require_keys,
const char *engine_id, const char *cmdname);
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 15f7c82..1884a2e 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -59,6 +59,9 @@
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 eaeb765..ab6f756 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 @@
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)