All of lore.kernel.org
 help / color / mirror / Atom feed
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v4 1/6] lib: rsa: decouple rsa from FIT image verification
Date: Thu, 21 Nov 2019 09:11:16 +0900	[thread overview]
Message-ID: <20191121001121.21854-2-takahiro.akashi@linaro.org> (raw)
In-Reply-To: <20191121001121.21854-1-takahiro.akashi@linaro.org>

Introduce new configuration, CONFIG_RSA_VERIFY which will decouple building
RSA functions from FIT verification and allow for adding a RSA-based
signature verification for other file formats, in particular PE file
for UEFI secure boot.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 Kconfig                |   1 +
 common/Makefile        |   3 +-
 common/image-fit-sig.c | 417 +++++++++++++++++++++++++++++++++++++++++
 common/image-fit.c     |   6 +-
 common/image-sig.c     | 396 --------------------------------------
 include/image.h        |  13 +-
 lib/rsa/Kconfig        |  12 ++
 lib/rsa/Makefile       |   2 +-
 lib/rsa/rsa-verify.c   |  78 +++++---
 tools/Makefile         |   2 +-
 10 files changed, 493 insertions(+), 437 deletions(-)
 create mode 100644 common/image-fit-sig.c

diff --git a/Kconfig b/Kconfig
index 66b059f749a7..63690514b261 100644
--- a/Kconfig
+++ b/Kconfig
@@ -417,6 +417,7 @@ config SPL_FIT_SIGNATURE
 	depends on SPL_DM
 	select SPL_FIT
 	select SPL_RSA
+	select SPL_RSA_VERIFY
 
 config SPL_LOAD_FIT
 	bool "Enable SPL loading U-Boot as a FIT (basic fitImage features)"
diff --git a/common/Makefile b/common/Makefile
index 302d8beaf356..d66c0068bb88 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -112,7 +112,8 @@ obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
 obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o
-obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-sig.o
+obj-$(CONFIG_$(SPL_)RSA_VERIFY) += image-sig.o
+obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-fit-sig.o
 obj-$(CONFIG_IO_TRACE) += iotrace.o
 obj-y += memsize.o
 obj-y += stdio.o
diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c
new file mode 100644
index 000000000000..f6caeb0c5901
--- /dev/null
+++ b/common/image-fit-sig.c
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013, Google Inc.
+ */
+
+#ifdef USE_HOSTCC
+#include "mkimage.h"
+#include <time.h>
+#else
+#include <common.h>
+#include <malloc.h>
+DECLARE_GLOBAL_DATA_PTR;
+#endif /* !USE_HOSTCC*/
+#include <image.h>
+#include <u-boot/rsa.h>
+#include <u-boot/rsa-checksum.h>
+
+#define IMAGE_MAX_HASHED_NODES		100
+
+#ifdef USE_HOSTCC
+void *host_blob;
+
+void image_set_host_blob(void *blob)
+{
+	host_blob = blob;
+}
+
+void *image_get_host_blob(void)
+{
+	return host_blob;
+}
+#endif
+
+/**
+ * fit_region_make_list() - Make a list of image regions
+ *
+ * Given a list of fdt_regions, create a list of image_regions. This is a
+ * simple conversion routine since the FDT and image code use different
+ * structures.
+ *
+ * @fit: FIT image
+ * @fdt_regions: Pointer to FDT regions
+ * @count: Number of FDT regions
+ * @region: Pointer to image regions, which must hold @count records. If
+ * region is NULL, then (except for an SPL build) the array will be
+ * allocated.
+ * @return: Pointer to image regions
+ */
+struct image_region *fit_region_make_list(const void *fit,
+					  struct fdt_region *fdt_regions,
+					  int count,
+					  struct image_region *region)
+{
+	int i;
+
+	debug("Hash regions:\n");
+	debug("%10s %10s\n", "Offset", "Size");
+
+	/*
+	 * Use malloc() except in SPL (to save code size). In SPL the caller
+	 * must allocate the array.
+	 */
+#ifndef CONFIG_SPL_BUILD
+	if (!region)
+		region = calloc(sizeof(*region), count);
+#endif
+	if (!region)
+		return NULL;
+	for (i = 0; i < count; i++) {
+		debug("%10x %10x\n", fdt_regions[i].offset,
+		      fdt_regions[i].size);
+		region[i].data = fit + fdt_regions[i].offset;
+		region[i].size = fdt_regions[i].size;
+	}
+
+	return region;
+}
+
+static int fit_image_setup_verify(struct image_sign_info *info,
+				  const void *fit, int noffset,
+				  int required_keynode, char **err_msgp)
+{
+	char *algo_name;
+	const char *padding_name;
+
+	if (fdt_totalsize(fit) > CONFIG_FIT_SIGNATURE_MAX_SIZE) {
+		*err_msgp = "Total size too large";
+		return 1;
+	}
+
+	if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
+		*err_msgp = "Can't get hash algo property";
+		return -1;
+	}
+
+	padding_name = fdt_getprop(fit, noffset, "padding", NULL);
+	if (!padding_name)
+		padding_name = RSA_DEFAULT_PADDING_NAME;
+
+	memset(info, '\0', sizeof(*info));
+	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+	info->fit = (void *)fit;
+	info->node_offset = noffset;
+	info->name = algo_name;
+	info->checksum = image_get_checksum_algo(algo_name);
+	info->crypto = image_get_crypto_algo(algo_name);
+	info->padding = image_get_padding_algo(padding_name);
+	info->fdt_blob = gd_fdt_blob();
+	info->required_keynode = required_keynode;
+	printf("%s:%s", algo_name, info->keyname);
+
+	if (!info->checksum || !info->crypto || !info->padding) {
+		*err_msgp = "Unknown signature algorithm";
+		return -1;
+	}
+
+	return 0;
+}
+
+int fit_image_check_sig(const void *fit, int noffset, const void *data,
+			size_t size, int required_keynode, char **err_msgp)
+{
+	struct image_sign_info info;
+	struct image_region region;
+	uint8_t *fit_value;
+	int fit_value_len;
+
+	*err_msgp = NULL;
+	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
+				   err_msgp))
+		return -1;
+
+	if (fit_image_hash_get_value(fit, noffset, &fit_value,
+				     &fit_value_len)) {
+		*err_msgp = "Can't get hash value property";
+		return -1;
+	}
+
+	region.data = data;
+	region.size = size;
+
+	if (info.crypto->verify(&info, &region, 1, fit_value, fit_value_len)) {
+		*err_msgp = "Verification failed";
+		return -1;
+	}
+
+	return 0;
+}
+
+static int fit_image_verify_sig(const void *fit, int image_noffset,
+				const char *data, size_t size,
+				const void *sig_blob, int sig_offset)
+{
+	int noffset;
+	char *err_msg = "";
+	int verified = 0;
+	int ret;
+
+	/* Process all hash subnodes of the component image node */
+	fdt_for_each_subnode(noffset, fit, image_noffset) {
+		const char *name = fit_get_name(fit, noffset, NULL);
+
+		if (!strncmp(name, FIT_SIG_NODENAME,
+			     strlen(FIT_SIG_NODENAME))) {
+			ret = fit_image_check_sig(fit, noffset, data,
+						  size, -1, &err_msg);
+			if (ret) {
+				puts("- ");
+			} else {
+				puts("+ ");
+				verified = 1;
+				break;
+			}
+		}
+	}
+
+	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+		err_msg = "Corrupted or truncated tree";
+		goto error;
+	}
+
+	return verified ? 0 : -EPERM;
+
+error:
+	printf(" error!\n%s for '%s' hash node in '%s' image node\n",
+	       err_msg, fit_get_name(fit, noffset, NULL),
+	       fit_get_name(fit, image_noffset, NULL));
+	return -1;
+}
+
+int fit_image_verify_required_sigs(const void *fit, int image_noffset,
+				   const char *data, size_t size,
+				   const void *sig_blob, int *no_sigsp)
+{
+	int verify_count = 0;
+	int noffset;
+	int sig_node;
+
+	/* Work out what we need to verify */
+	*no_sigsp = 1;
+	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
+	if (sig_node < 0) {
+		debug("%s: No signature node found: %s\n", __func__,
+		      fdt_strerror(sig_node));
+		return 0;
+	}
+
+	fdt_for_each_subnode(noffset, sig_blob, sig_node) {
+		const char *required;
+		int ret;
+
+		required = fdt_getprop(sig_blob, noffset, "required", NULL);
+		if (!required || strcmp(required, "image"))
+			continue;
+		ret = fit_image_verify_sig(fit, image_noffset, data, size,
+					   sig_blob, noffset);
+		if (ret) {
+			printf("Failed to verify required signature '%s'\n",
+			       fit_get_name(sig_blob, noffset, NULL));
+			return ret;
+		}
+		verify_count++;
+	}
+
+	if (verify_count)
+		*no_sigsp = 0;
+
+	return 0;
+}
+
+int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
+			 char **err_msgp)
+{
+	char * const exc_prop[] = {"data"};
+	const char *prop, *end, *name;
+	struct image_sign_info info;
+	const uint32_t *strings;
+	uint8_t *fit_value;
+	int fit_value_len;
+	int max_regions;
+	int i, prop_len;
+	char path[200];
+	int count;
+
+	debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
+	      fit_get_name(fit, noffset, NULL),
+	      fit_get_name(gd_fdt_blob(), required_keynode, NULL));
+	*err_msgp = NULL;
+	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
+				   err_msgp))
+		return -1;
+
+	if (fit_image_hash_get_value(fit, noffset, &fit_value,
+				     &fit_value_len)) {
+		*err_msgp = "Can't get hash value property";
+		return -1;
+	}
+
+	/* Count the number of strings in the property */
+	prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
+	end = prop ? prop + prop_len : prop;
+	for (name = prop, count = 0; name < end; name++)
+		if (!*name)
+			count++;
+	if (!count) {
+		*err_msgp = "Can't get hashed-nodes property";
+		return -1;
+	}
+
+	if (prop && prop_len > 0 && prop[prop_len - 1] != '\0') {
+		*err_msgp = "hashed-nodes property must be null-terminated";
+		return -1;
+	}
+
+	/* Add a sanity check here since we are using the stack */
+	if (count > IMAGE_MAX_HASHED_NODES) {
+		*err_msgp = "Number of hashed nodes exceeds maximum";
+		return -1;
+	}
+
+	/* Create a list of node names from those strings */
+	char *node_inc[count];
+
+	debug("Hash nodes (%d):\n", count);
+	for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
+		debug("   '%s'\n", name);
+		node_inc[i] = (char *)name;
+	}
+
+	/*
+	 * Each node can generate one region for each sub-node. Allow for
+	 * 7 sub-nodes (hash-1, signature-1, etc.) and some extra.
+	 */
+	max_regions = 20 + count * 7;
+	struct fdt_region fdt_regions[max_regions];
+
+	/* Get a list of regions to hash */
+	count = fdt_find_regions(fit, node_inc, count,
+				 exc_prop, ARRAY_SIZE(exc_prop),
+				 fdt_regions, max_regions - 1,
+				 path, sizeof(path), 0);
+	if (count < 0) {
+		*err_msgp = "Failed to hash configuration";
+		return -1;
+	}
+	if (count == 0) {
+		*err_msgp = "No data to hash";
+		return -1;
+	}
+	if (count >= max_regions - 1) {
+		*err_msgp = "Too many hash regions";
+		return -1;
+	}
+
+	/* Add the strings */
+	strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
+	if (strings) {
+		/*
+		 * The strings region offset must be a static 0x0.
+		 * This is set in tool/image-host.c
+		 */
+		fdt_regions[count].offset = fdt_off_dt_strings(fit);
+		fdt_regions[count].size = fdt32_to_cpu(strings[1]);
+		count++;
+	}
+
+	/* Allocate the region list on the stack */
+	struct image_region region[count];
+
+	fit_region_make_list(fit, fdt_regions, count, region);
+	if (info.crypto->verify(&info, region, count, fit_value,
+				fit_value_len)) {
+		*err_msgp = "Verification failed";
+		return -1;
+	}
+
+	return 0;
+}
+
+static int fit_config_verify_sig(const void *fit, int conf_noffset,
+				 const void *sig_blob, int sig_offset)
+{
+	int noffset;
+	char *err_msg = "";
+	int verified = 0;
+	int ret;
+
+	/* Process all hash subnodes of the component conf node */
+	fdt_for_each_subnode(noffset, fit, conf_noffset) {
+		const char *name = fit_get_name(fit, noffset, NULL);
+
+		if (!strncmp(name, FIT_SIG_NODENAME,
+			     strlen(FIT_SIG_NODENAME))) {
+			ret = fit_config_check_sig(fit, noffset, sig_offset,
+						   &err_msg);
+			if (ret) {
+				puts("- ");
+			} else {
+				puts("+ ");
+				verified = 1;
+				break;
+			}
+		}
+	}
+
+	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+		err_msg = "Corrupted or truncated tree";
+		goto error;
+	}
+
+	return verified ? 0 : -EPERM;
+
+error:
+	printf(" error!\n%s for '%s' hash node in '%s' config node\n",
+	       err_msg, fit_get_name(fit, noffset, NULL),
+	       fit_get_name(fit, conf_noffset, NULL));
+	return -1;
+}
+
+int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
+				    const void *sig_blob)
+{
+	int noffset;
+	int sig_node;
+
+	/* Work out what we need to verify */
+	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
+	if (sig_node < 0) {
+		debug("%s: No signature node found: %s\n", __func__,
+		      fdt_strerror(sig_node));
+		return 0;
+	}
+
+	fdt_for_each_subnode(noffset, sig_blob, sig_node) {
+		const char *required;
+		int ret;
+
+		required = fdt_getprop(sig_blob, noffset, "required", NULL);
+		if (!required || strcmp(required, "conf"))
+			continue;
+		ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
+					    noffset);
+		if (ret) {
+			printf("Failed to verify required signature '%s'\n",
+			       fit_get_name(sig_blob, noffset, NULL));
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int fit_config_verify(const void *fit, int conf_noffset)
+{
+	return fit_config_verify_required_sigs(fit, conf_noffset,
+					       gd_fdt_blob());
+}
diff --git a/common/image-fit.c b/common/image-fit.c
index 5c63c769de27..2d78f0b47da2 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1216,7 +1216,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
 	int ret;
 
 	/* Verify all required signatures */
-	if (IMAGE_ENABLE_VERIFY &&
+	if (FIT_IMAGE_ENABLE_VERIFY &&
 	    fit_image_verify_required_sigs(fit, image_noffset, data, size,
 					   gd_fdt_blob(), &verify_all)) {
 		err_msg = "Unable to verify required signature";
@@ -1238,7 +1238,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
 						 &err_msg))
 				goto error;
 			puts("+ ");
-		} else if (IMAGE_ENABLE_VERIFY && verify_all &&
+		} else if (FIT_IMAGE_ENABLE_VERIFY && verify_all &&
 				!strncmp(name, FIT_SIG_NODENAME,
 					strlen(FIT_SIG_NODENAME))) {
 			ret = fit_image_check_sig(fit, noffset, data,
@@ -1870,7 +1870,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
 		if (image_type == IH_TYPE_KERNEL)
 			images->fit_uname_cfg = fit_base_uname_config;
 
-		if (IMAGE_ENABLE_VERIFY && images->verify) {
+		if (FIT_IMAGE_ENABLE_VERIFY && images->verify) {
 			puts("   Verifying Hash Integrity ... ");
 			if (fit_config_verify(fit, cfg_noffset)) {
 				puts("Bad Data Hash\n");
diff --git a/common/image-sig.c b/common/image-sig.c
index 639a1124504f..84b2c0439cf8 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -17,18 +17,6 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define IMAGE_MAX_HASHED_NODES		100
 
-#ifdef USE_HOSTCC
-void *host_blob;
-void image_set_host_blob(void *blob)
-{
-	host_blob = blob;
-}
-void *image_get_host_blob(void)
-{
-	return host_blob;
-}
-#endif
-
 struct checksum_algo checksum_algos[] = {
 	{
 		.name = "sha1",
@@ -162,387 +150,3 @@ struct padding_algo *image_get_padding_algo(const char *name)
 
 	return NULL;
 }
-
-/**
- * fit_region_make_list() - Make a list of image regions
- *
- * Given a list of fdt_regions, create a list of image_regions. This is a
- * simple conversion routine since the FDT and image code use different
- * structures.
- *
- * @fit: FIT image
- * @fdt_regions: Pointer to FDT regions
- * @count: Number of FDT regions
- * @region: Pointer to image regions, which must hold @count records. If
- * region is NULL, then (except for an SPL build) the array will be
- * allocated.
- * @return: Pointer to image regions
- */
-struct image_region *fit_region_make_list(const void *fit,
-		struct fdt_region *fdt_regions, int count,
-		struct image_region *region)
-{
-	int i;
-
-	debug("Hash regions:\n");
-	debug("%10s %10s\n", "Offset", "Size");
-
-	/*
-	 * Use malloc() except in SPL (to save code size). In SPL the caller
-	 * must allocate the array.
-	 */
-#ifndef CONFIG_SPL_BUILD
-	if (!region)
-		region = calloc(sizeof(*region), count);
-#endif
-	if (!region)
-		return NULL;
-	for (i = 0; i < count; i++) {
-		debug("%10x %10x\n", fdt_regions[i].offset,
-		      fdt_regions[i].size);
-		region[i].data = fit + fdt_regions[i].offset;
-		region[i].size = fdt_regions[i].size;
-	}
-
-	return region;
-}
-
-static int fit_image_setup_verify(struct image_sign_info *info,
-		const void *fit, int noffset, int required_keynode,
-		char **err_msgp)
-{
-	char *algo_name;
-	const char *padding_name;
-
-	if (fdt_totalsize(fit) > CONFIG_FIT_SIGNATURE_MAX_SIZE) {
-		*err_msgp = "Total size too large";
-		return 1;
-	}
-
-	if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
-		*err_msgp = "Can't get hash algo property";
-		return -1;
-	}
-
-	padding_name = fdt_getprop(fit, noffset, "padding", NULL);
-	if (!padding_name)
-		padding_name = RSA_DEFAULT_PADDING_NAME;
-
-	memset(info, '\0', sizeof(*info));
-	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
-	info->fit = (void *)fit;
-	info->node_offset = noffset;
-	info->name = algo_name;
-	info->checksum = image_get_checksum_algo(algo_name);
-	info->crypto = image_get_crypto_algo(algo_name);
-	info->padding = image_get_padding_algo(padding_name);
-	info->fdt_blob = gd_fdt_blob();
-	info->required_keynode = required_keynode;
-	printf("%s:%s", algo_name, info->keyname);
-
-	if (!info->checksum || !info->crypto || !info->padding) {
-		*err_msgp = "Unknown signature algorithm";
-		return -1;
-	}
-
-	return 0;
-}
-
-int fit_image_check_sig(const void *fit, int noffset, const void *data,
-		size_t size, int required_keynode, char **err_msgp)
-{
-	struct image_sign_info info;
-	struct image_region region;
-	uint8_t *fit_value;
-	int fit_value_len;
-
-	*err_msgp = NULL;
-	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
-				   err_msgp))
-		return -1;
-
-	if (fit_image_hash_get_value(fit, noffset, &fit_value,
-				     &fit_value_len)) {
-		*err_msgp = "Can't get hash value property";
-		return -1;
-	}
-
-	region.data = data;
-	region.size = size;
-
-	if (info.crypto->verify(&info, &region, 1, fit_value, fit_value_len)) {
-		*err_msgp = "Verification failed";
-		return -1;
-	}
-
-	return 0;
-}
-
-static int fit_image_verify_sig(const void *fit, int image_noffset,
-		const char *data, size_t size, const void *sig_blob,
-		int sig_offset)
-{
-	int noffset;
-	char *err_msg = "";
-	int verified = 0;
-	int ret;
-
-	/* Process all hash subnodes of the component image node */
-	fdt_for_each_subnode(noffset, fit, image_noffset) {
-		const char *name = fit_get_name(fit, noffset, NULL);
-
-		if (!strncmp(name, FIT_SIG_NODENAME,
-			     strlen(FIT_SIG_NODENAME))) {
-			ret = fit_image_check_sig(fit, noffset, data,
-							size, -1, &err_msg);
-			if (ret) {
-				puts("- ");
-			} else {
-				puts("+ ");
-				verified = 1;
-				break;
-			}
-		}
-	}
-
-	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
-		err_msg = "Corrupted or truncated tree";
-		goto error;
-	}
-
-	return verified ? 0 : -EPERM;
-
-error:
-	printf(" error!\n%s for '%s' hash node in '%s' image node\n",
-	       err_msg, fit_get_name(fit, noffset, NULL),
-	       fit_get_name(fit, image_noffset, NULL));
-	return -1;
-}
-
-int fit_image_verify_required_sigs(const void *fit, int image_noffset,
-		const char *data, size_t size, const void *sig_blob,
-		int *no_sigsp)
-{
-	int verify_count = 0;
-	int noffset;
-	int sig_node;
-
-	/* Work out what we need to verify */
-	*no_sigsp = 1;
-	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
-	if (sig_node < 0) {
-		debug("%s: No signature node found: %s\n", __func__,
-		      fdt_strerror(sig_node));
-		return 0;
-	}
-
-	fdt_for_each_subnode(noffset, sig_blob, sig_node) {
-		const char *required;
-		int ret;
-
-		required = fdt_getprop(sig_blob, noffset, "required", NULL);
-		if (!required || strcmp(required, "image"))
-			continue;
-		ret = fit_image_verify_sig(fit, image_noffset, data, size,
-					sig_blob, noffset);
-		if (ret) {
-			printf("Failed to verify required signature '%s'\n",
-			       fit_get_name(sig_blob, noffset, NULL));
-			return ret;
-		}
-		verify_count++;
-	}
-
-	if (verify_count)
-		*no_sigsp = 0;
-
-	return 0;
-}
-
-int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
-			 char **err_msgp)
-{
-	char * const exc_prop[] = {"data"};
-	const char *prop, *end, *name;
-	struct image_sign_info info;
-	const uint32_t *strings;
-	uint8_t *fit_value;
-	int fit_value_len;
-	int max_regions;
-	int i, prop_len;
-	char path[200];
-	int count;
-
-	debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
-	      fit_get_name(fit, noffset, NULL),
-	      fit_get_name(gd_fdt_blob(), required_keynode, NULL));
-	*err_msgp = NULL;
-	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
-				   err_msgp))
-		return -1;
-
-	if (fit_image_hash_get_value(fit, noffset, &fit_value,
-				     &fit_value_len)) {
-		*err_msgp = "Can't get hash value property";
-		return -1;
-	}
-
-	/* Count the number of strings in the property */
-	prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
-	end = prop ? prop + prop_len : prop;
-	for (name = prop, count = 0; name < end; name++)
-		if (!*name)
-			count++;
-	if (!count) {
-		*err_msgp = "Can't get hashed-nodes property";
-		return -1;
-	}
-
-	if (prop && prop_len > 0 && prop[prop_len - 1] != '\0') {
-		*err_msgp = "hashed-nodes property must be null-terminated";
-		return -1;
-	}
-
-	/* Add a sanity check here since we are using the stack */
-	if (count > IMAGE_MAX_HASHED_NODES) {
-		*err_msgp = "Number of hashed nodes exceeds maximum";
-		return -1;
-	}
-
-	/* Create a list of node names from those strings */
-	char *node_inc[count];
-
-	debug("Hash nodes (%d):\n", count);
-	for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
-		debug("   '%s'\n", name);
-		node_inc[i] = (char *)name;
-	}
-
-	/*
-	 * Each node can generate one region for each sub-node. Allow for
-	 * 7 sub-nodes (hash-1, signature-1, etc.) and some extra.
-	 */
-	max_regions = 20 + count * 7;
-	struct fdt_region fdt_regions[max_regions];
-
-	/* Get a list of regions to hash */
-	count = fdt_find_regions(fit, node_inc, count,
-			exc_prop, ARRAY_SIZE(exc_prop),
-			fdt_regions, max_regions - 1,
-			path, sizeof(path), 0);
-	if (count < 0) {
-		*err_msgp = "Failed to hash configuration";
-		return -1;
-	}
-	if (count == 0) {
-		*err_msgp = "No data to hash";
-		return -1;
-	}
-	if (count >= max_regions - 1) {
-		*err_msgp = "Too many hash regions";
-		return -1;
-	}
-
-	/* Add the strings */
-	strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
-	if (strings) {
-		/*
-		 * The strings region offset must be a static 0x0.
-		 * This is set in tool/image-host.c
-		 */
-		fdt_regions[count].offset = fdt_off_dt_strings(fit);
-		fdt_regions[count].size = fdt32_to_cpu(strings[1]);
-		count++;
-	}
-
-	/* Allocate the region list on the stack */
-	struct image_region region[count];
-
-	fit_region_make_list(fit, fdt_regions, count, region);
-	if (info.crypto->verify(&info, region, count, fit_value,
-				fit_value_len)) {
-		*err_msgp = "Verification failed";
-		return -1;
-	}
-
-	return 0;
-}
-
-static int fit_config_verify_sig(const void *fit, int conf_noffset,
-		const void *sig_blob, int sig_offset)
-{
-	int noffset;
-	char *err_msg = "";
-	int verified = 0;
-	int ret;
-
-	/* Process all hash subnodes of the component conf node */
-	fdt_for_each_subnode(noffset, fit, conf_noffset) {
-		const char *name = fit_get_name(fit, noffset, NULL);
-
-		if (!strncmp(name, FIT_SIG_NODENAME,
-			     strlen(FIT_SIG_NODENAME))) {
-			ret = fit_config_check_sig(fit, noffset, sig_offset,
-						   &err_msg);
-			if (ret) {
-				puts("- ");
-			} else {
-				puts("+ ");
-				verified = 1;
-				break;
-			}
-		}
-	}
-
-	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
-		err_msg = "Corrupted or truncated tree";
-		goto error;
-	}
-
-	return verified ? 0 : -EPERM;
-
-error:
-	printf(" error!\n%s for '%s' hash node in '%s' config node\n",
-	       err_msg, fit_get_name(fit, noffset, NULL),
-	       fit_get_name(fit, conf_noffset, NULL));
-	return -1;
-}
-
-int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
-		const void *sig_blob)
-{
-	int noffset;
-	int sig_node;
-
-	/* Work out what we need to verify */
-	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
-	if (sig_node < 0) {
-		debug("%s: No signature node found: %s\n", __func__,
-		      fdt_strerror(sig_node));
-		return 0;
-	}
-
-	fdt_for_each_subnode(noffset, sig_blob, sig_node) {
-		const char *required;
-		int ret;
-
-		required = fdt_getprop(sig_blob, noffset, "required", NULL);
-		if (!required || strcmp(required, "conf"))
-			continue;
-		ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
-					    noffset);
-		if (ret) {
-			printf("Failed to verify required signature '%s'\n",
-			       fit_get_name(sig_blob, noffset, NULL));
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-int fit_config_verify(const void *fit, int conf_noffset)
-{
-	return fit_config_verify_required_sigs(fit, conf_noffset,
-					       gd_fdt_blob());
-}
diff --git a/include/image.h b/include/image.h
index f4d2aaf53e87..7eb0b4b53184 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1086,6 +1086,7 @@ int fit_conf_get_prop_node(const void *fit, int noffset,
 
 int fit_check_ramdisk(const void *fit, int os_noffset,
 		uint8_t arch, int verify);
+#endif /* IMAGE_ENABLE_FIT */
 
 int calculate_hash(const void *data, int data_len, const char *algo,
 			uint8_t *value, int *value_len);
@@ -1098,16 +1099,20 @@ int calculate_hash(const void *data, int data_len, const char *algo,
 # if defined(CONFIG_FIT_SIGNATURE)
 #  define IMAGE_ENABLE_SIGN	1
 #  define IMAGE_ENABLE_VERIFY	1
+#  define FIT_IMAGE_ENABLE_VERIFY	1
 #  include <openssl/evp.h>
 # else
 #  define IMAGE_ENABLE_SIGN	0
 #  define IMAGE_ENABLE_VERIFY	0
+#  define FIT_IMAGE_ENABLE_VERIFY	0
 # endif
 #else
 # define IMAGE_ENABLE_SIGN	0
-# define IMAGE_ENABLE_VERIFY	CONFIG_IS_ENABLED(FIT_SIGNATURE)
+# define IMAGE_ENABLE_VERIFY		CONFIG_IS_ENABLED(RSA_VERIFY)
+# define FIT_IMAGE_ENABLE_VERIFY	CONFIG_IS_ENABLED(FIT_SIGNATURE)
 #endif
 
+#if IMAGE_ENABLE_FIT
 #ifdef USE_HOSTCC
 void *image_get_host_blob(void);
 void image_set_host_blob(void *host_blob);
@@ -1121,6 +1126,7 @@ void image_set_host_blob(void *host_blob);
 #else
 #define IMAGE_ENABLE_BEST_MATCH	0
 #endif
+#endif /* IMAGE_ENABLE_FIT */
 
 /* Information passed to the signing routines */
 struct image_sign_info {
@@ -1137,7 +1143,6 @@ struct image_sign_info {
 	const char *require_keys;	/* Value for 'required' property */
 	const char *engine_id;		/* Engine to use for signing */
 };
-#endif /* Allow struct image_region to always be defined for rsa.h */
 
 /* A part of an image, used for hashing */
 struct image_region {
@@ -1145,8 +1150,6 @@ struct image_region {
 	int size;
 };
 
-#if IMAGE_ENABLE_FIT
-
 #if IMAGE_ENABLE_VERIFY
 # include <u-boot/rsa-checksum.h>
 #endif
@@ -1247,6 +1250,8 @@ struct crypto_algo *image_get_crypto_algo(const char *full_name);
  */
 struct padding_algo *image_get_padding_algo(const char *name);
 
+#if IMAGE_ENABLE_FIT
+
 /**
  * fit_image_verify_required_sigs() - Verify signatures marked as 'required'
  *
diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig
index 2b33f323bccc..03ffa2969048 100644
--- a/lib/rsa/Kconfig
+++ b/lib/rsa/Kconfig
@@ -1,5 +1,6 @@
 config RSA
 	bool "Use RSA Library"
+	select RSA_VERIFY
 	select RSA_FREESCALE_EXP if FSL_CAAM && !ARCH_MX7 && !ARCH_MX6 && !ARCH_MX5
 	select RSA_SOFTWARE_EXP if !RSA_FREESCALE_EXP
 	help
@@ -17,6 +18,17 @@ if RSA
 
 config SPL_RSA
 	bool "Use RSA Library within SPL"
+	select SPL_RSA_VERIFY
+
+config SPL_RSA_VERIFY
+	bool
+	help
+	  Add RSA signature verification support in SPL.
+
+config RSA_VERIFY
+	bool
+	help
+	  Add RSA signature verification support.
 
 config RSA_SOFTWARE_EXP
 	bool "Enable driver for RSA Modular Exponentiation in software"
diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
index a51c6e1685fb..c07305188e0c 100644
--- a/lib/rsa/Makefile
+++ b/lib/rsa/Makefile
@@ -5,5 +5,5 @@
 # (C) Copyright 2000-2007
 # Wolfgang Denk, DENX Software Engineering, wd at denx.de.
 
-obj-$(CONFIG_$(SPL_)FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o
+obj-$(CONFIG_$(SPL_)RSA_VERIFY) += rsa-verify.o rsa-checksum.o
 obj-$(CONFIG_RSA_SOFTWARE_EXP) += rsa-mod-exp.o
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index 82dc513260e2..d2fd0692fa13 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -270,6 +270,7 @@ out:
 }
 #endif
 
+#if CONFIG_IS_ENABLED(FIT_SIGNATURE)
 /**
  * rsa_verify_key() - Verify a signature against some data using RSA Key
  *
@@ -341,7 +342,9 @@ static int rsa_verify_key(struct image_sign_info *info,
 
 	return 0;
 }
+#endif
 
+#if CONFIG_IS_ENABLED(FIT_SIGNATURE)
 /**
  * rsa_verify_with_keynode() - Verify a signature against some data using
  * information in node with prperties of RSA Key like modulus, exponent etc.
@@ -395,18 +398,22 @@ static int rsa_verify_with_keynode(struct image_sign_info *info,
 
 	return ret;
 }
+#else
+static int rsa_verify_with_keynode(struct image_sign_info *info,
+				   const void *hash, uint8_t *sig,
+				   uint sig_len, int node)
+{
+	return -EACCES;
+}
+#endif
 
 int rsa_verify(struct image_sign_info *info,
 	       const struct image_region region[], int region_count,
 	       uint8_t *sig, uint sig_len)
 {
-	const void *blob = info->fdt_blob;
 	/* Reserve memory for maximum checksum-length */
 	uint8_t hash[info->crypto->key_len];
-	int ndepth, noffset;
-	int sig_node, node;
-	char name[100];
-	int ret;
+	int ret = -EACCES;
 
 	/*
 	 * Verify that the checksum-length does not exceed the
@@ -419,12 +426,6 @@ int rsa_verify(struct image_sign_info *info,
 		return -EINVAL;
 	}
 
-	sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
-	if (sig_node < 0) {
-		debug("%s: No signature node found\n", __func__);
-		return -ENOENT;
-	}
-
 	/* Calculate checksum with checksum-algorithm */
 	ret = info->checksum->calculate(info->checksum->name,
 					region, region_count, hash);
@@ -433,29 +434,44 @@ int rsa_verify(struct image_sign_info *info,
 		return -EINVAL;
 	}
 
-	/* See if we must use a particular key */
-	if (info->required_keynode != -1) {
-		ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
-			info->required_keynode);
-		return ret;
-	}
+	if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
+		const void *blob = info->fdt_blob;
+		int ndepth, noffset;
+		int sig_node, node;
+		char name[100];
 
-	/* Look for a key that matches our hint */
-	snprintf(name, sizeof(name), "key-%s", info->keyname);
-	node = fdt_subnode_offset(blob, sig_node, name);
-	ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
-	if (!ret)
-		return ret;
+		sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
+		if (sig_node < 0) {
+			debug("%s: No signature node found\n", __func__);
+			return -ENOENT;
+		}
 
-	/* No luck, so try each of the keys in turn */
-	for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth);
-			(noffset >= 0) && (ndepth > 0);
-			noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
-		if (ndepth == 1 && noffset != node) {
+		/* See if we must use a particular key */
+		if (info->required_keynode != -1) {
 			ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
-						      noffset);
-			if (!ret)
-				break;
+						      info->required_keynode);
+			return ret;
+		}
+
+		/* Look for a key that matches our hint */
+		snprintf(name, sizeof(name), "key-%s", info->keyname);
+		node = fdt_subnode_offset(blob, sig_node, name);
+		ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
+		if (!ret)
+			return ret;
+
+		/* No luck, so try each of the keys in turn */
+		for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node,
+							 &ndepth);
+		     (noffset >= 0) && (ndepth > 0);
+		     noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
+			if (ndepth == 1 && noffset != node) {
+				ret = rsa_verify_with_keynode(info, hash,
+							      sig, sig_len,
+							      noffset);
+				if (!ret)
+					break;
+			}
 		}
 	}
 
diff --git a/tools/Makefile b/tools/Makefile
index 345bc84e48db..1f885cca7034 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -58,7 +58,7 @@ hostprogs-$(CONFIG_FIT_SIGNATURE) += fit_info fit_check_sign
 hostprogs-$(CONFIG_CMD_BOOTEFI_SELFTEST) += file2include
 
 FIT_OBJS-$(CONFIG_FIT) := fit_common.o fit_image.o image-host.o common/image-fit.o
-FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o
+FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o common/image-fit-sig.o
 
 # The following files are synced with upstream DTC.
 # Use synced versions from scripts/dtc/libfdt/.
-- 
2.21.0

  reply	other threads:[~2019-11-21  0:11 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-21  0:11 [U-Boot] [PATCH v4 0/6] rsa: extend rsa_verify() for UEFI secure boot AKASHI Takahiro
2019-11-21  0:11 ` AKASHI Takahiro [this message]
2019-12-07  0:25   ` [U-Boot] [PATCH v4 1/6] lib: rsa: decouple rsa from FIT image verification Tom Rini
2019-12-12 10:10     ` AKASHI Takahiro
2019-11-21  0:11 ` [U-Boot] [PATCH v4 2/6] rsa: add CONFIG_RSA_VERIFY_WITH_PKEY config AKASHI Takahiro
2020-01-08 12:35   ` Heinrich Schuchardt
2020-01-14  7:45     ` AKASHI Takahiro
2020-01-14 11:43       ` Heinrich Schuchardt
2020-01-17  2:24         ` AKASHI Takahiro
2020-01-17  5:59           ` Heinrich Schuchardt
2020-01-21  4:29             ` AKASHI Takahiro
2020-01-21 15:34               ` Tom Rini
2019-11-21  0:11 ` [U-Boot] [PATCH v4 3/6] include: image.h: add key info to image_sign_info AKASHI Takahiro
2019-11-21  0:11 ` [U-Boot] [PATCH v4 4/6] lib: rsa: generate additional parameters for public key AKASHI Takahiro
2020-01-08 18:07   ` Heinrich Schuchardt
2020-01-08 18:16     ` Heinrich Schuchardt
2020-01-14  7:15     ` AKASHI Takahiro
2019-11-21  0:11 ` [U-Boot] [PATCH v4 5/6] lib: rsa: add rsa_verify_with_pkey() AKASHI Takahiro
2019-11-21  0:11 ` [U-Boot] [PATCH v4 6/6] test: add rsa_verify() unit test AKASHI Takahiro
2020-01-08 17:43   ` Heinrich Schuchardt
2020-01-08 22:25     ` Heinrich Schuchardt
2020-01-14  7:33     ` AKASHI Takahiro
2020-01-14 12:04       ` Heinrich Schuchardt
2020-01-17  1:53         ` AKASHI Takahiro
2020-01-17  5:26           ` Heinrich Schuchardt
2020-01-21  5:48             ` AKASHI Takahiro
2020-01-21 15:40               ` Tom Rini
2020-01-22  0:22                 ` AKASHI Takahiro
2020-01-22  0:26                   ` Tom Rini
2020-01-18 20:20 ` [PATCH v4 0/6] rsa: extend rsa_verify() for UEFI secure boot Heinrich Schuchardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191121001121.21854-2-takahiro.akashi@linaro.org \
    --to=takahiro.akashi@linaro.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.