[U-Boot] [PATCH 4/4] image: Combine image_sig_algo with image_sign_info

aduda aduda at meraki.com
Tue Nov 8 19:53:41 CET 2016


From: Andrew Duda <aduda at meraki.com>

Remove the need to explicitly add SHA/RSA pairings. Invalid SHA/RSA
pairings will still fail on verify operations when the hash length is
longer than the key length.

Follow the same naming scheme "checksum,crytpo" without explicitly
defining the string.

Indirectly adds support for "sha1,rsa4096" signing/verification.

Signed-off-by: Andrew Duda <aduda at meraki.com>
Signed-off-by: aduda <aduda at meraki.com>
---

 common/image-sig.c   | 57 ++++++++++++++++++++++++++++------------------------
 include/image.h      | 24 ++++++++++++----------
 lib/rsa/rsa-sign.c   |  4 ++--
 lib/rsa/rsa-verify.c | 14 ++++++-------
 tools/image-host.c   | 16 ++++++++-------
 5 files changed, 61 insertions(+), 54 deletions(-)

diff --git a/common/image-sig.c b/common/image-sig.c
index 8b4314d..455f2b9 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -72,32 +72,36 @@ struct crypto_algo crypto_algos[] = {
 
 };
 
-struct image_sig_algo image_sig_algos[] = {
-	{
-		"sha1,rsa2048",
-		&crypto_algos[0],
-		&checksum_algos[0],
-	},
-	{
-		"sha256,rsa2048",
-		&crypto_algos[0],
-		&checksum_algos[1],
-	},
-	{
-		"sha256,rsa4096",
-		&crypto_algos[1],
-		&checksum_algos[1],
+struct checksum_algo *image_get_checksum_algo(const char *full_name)
+{
+	int i;
+	const char *name;
+
+	for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) {
+		name = checksum_algos[i].name;
+		/* Make sure names match and next char is a comma */
+		if (!strncmp(name, full_name, strlen(name)) &&
+		    full_name[strlen(name)] == ',')
+			return &checksum_algos[i];
 	}
 
-};
+	return NULL;
+}
 
-struct image_sig_algo *image_get_sig_algo(const char *name)
+struct crypto_algo *image_get_crypto_algo(const char *full_name)
 {
 	int i;
+	const char *name;
+
+	/* Move name to after the comma */
+	name = strchr(full_name, ',');
+	if (!name)
+		return NULL;
+	name += 1;
 
-	for (i = 0; i < ARRAY_SIZE(image_sig_algos); i++) {
-		if (!strcmp(image_sig_algos[i].name, name))
-			return &image_sig_algos[i];
+	for (i = 0; i < ARRAY_SIZE(crypto_algos); i++) {
+		if (!strcmp(crypto_algos[i].name, name))
+			return &crypto_algos[i];
 	}
 
 	return NULL;
@@ -161,12 +165,14 @@ static int fit_image_setup_verify(struct image_sign_info *info,
 	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
 	info->fit = (void *)fit;
 	info->node_offset = noffset;
-	info->algo = image_get_sig_algo(algo_name);
+	info->name = algo_name;
+	info->checksum = image_get_checksum_algo(algo_name);
+	info->crypto = image_get_crypto_algo(algo_name);
 	info->fdt_blob = gd_fdt_blob();
 	info->required_keynode = required_keynode;
 	printf("%s:%s", algo_name, info->keyname);
 
-	if (!info->algo) {
+	if (!info->checksum || !info->crypto) {
 		*err_msgp = "Unknown signature algorithm";
 		return -1;
 	}
@@ -196,8 +202,7 @@ int fit_image_check_sig(const void *fit, int noffset, const void *data,
 	region.data = data;
 	region.size = size;
 
-	if (info.algo->crypto->verify(&info, &region, 1, fit_value,
-				      fit_value_len)) {
+	if (info.crypto->verify(&info, &region, 1, fit_value, fit_value_len)) {
 		*err_msgp = "Verification failed";
 		return -1;
 	}
@@ -378,8 +383,8 @@ int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
 	struct image_region region[count];
 
 	fit_region_make_list(fit, fdt_regions, count, region);
-	if (info.algo->crypto->verify(&info, region, count, fit_value,
-				      fit_value_len)) {
+	if (info.crypto->verify(&info, region, count, fit_value,
+				fit_value_len)) {
 		*err_msgp = "Verification failed";
 		return -1;
 	}
diff --git a/include/image.h b/include/image.h
index c3c9866..8131595 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1049,7 +1049,9 @@ struct image_sign_info {
 	const char *keyname;		/* Name of key to use */
 	void *fit;			/* Pointer to FIT blob */
 	int node_offset;		/* Offset of signature node */
-	struct image_sig_algo *algo;	/* Algorithm information */
+	const char *name;		/* Algorithm name */
+	struct checksum_algo *checksum;	/* Checksum algorithm information */
+	struct crypto_algo *crypto;	/* Crypto algorithm information */
 	const void *fdt_blob;		/* FDT containing public keys */
 	int required_keynode;		/* Node offset of key to use: -1=any */
 	const char *require_keys;	/* Value for 'required' property */
@@ -1133,21 +1135,21 @@ struct crypto_algo {
 		      uint8_t *sig, uint sig_len);
 };
 
-struct image_sig_algo {
-	const char *name;
-	/* pointer to cryptosystem algorithm */
-	struct crypto_algo *crypto;
-	/* pointer to checksum algorithm */
-	struct checksum_algo *checksum;
-};
+/**
+ * image_get_checksum_algo() - Look up a checksum algorithm
+ *
+ * @param full_name	Name of algorithm in the form "checksum,crypto"
+ * @return pointer to algorithm information, or NULL if not found
+ */
+struct checksum_algo *image_get_checksum_algo(const char *full_name);
 
 /**
- * image_get_sig_algo() - Look up a signature algortihm
+ * image_get_crypto_algo() - Look up a cryptosystem algorithm
  *
- * @param name		Name of algorithm
+ * @param full_name	Name of algorithm in the form "checksum,crypto"
  * @return pointer to algorithm information, or NULL if not found
  */
-struct image_sig_algo *image_get_sig_algo(const char *name);
+struct crypto_algo *image_get_crypto_algo(const char *full_name);
 
 /**
  * fit_image_verify_required_sigs() - Verify signatures marked as 'required'
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
index c26f741..9a09280 100644
--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -244,7 +244,7 @@ int rsa_sign(struct image_sign_info *info,
 	ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
 	if (ret)
 		goto err_priv;
-	ret = rsa_sign_with_key(rsa, info->algo->checksum, region,
+	ret = rsa_sign_with_key(rsa, info->checksum, region,
 				region_count, sigp, sig_len);
 	if (ret)
 		goto err_sign;
@@ -508,7 +508,7 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
 	}
 	if (!ret) {
 		ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
-					 info->algo->name);
+					 info->name);
 	}
 	if (!ret && info->require_keys) {
 		ret = fdt_setprop_string(keydest, node, "required",
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index 61dc4c2..0d548f8 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -184,8 +184,7 @@ static int rsa_verify_with_keynode(struct image_sign_info *info,
 	}
 
 	ret = rsa_verify_key(&prop, sig, sig_len, hash,
-			     info->algo->crypto->key_len,
-			     info->algo->checksum);
+			     info->crypto->key_len, info->checksum);
 
 	return ret;
 }
@@ -196,7 +195,7 @@ int rsa_verify(struct image_sign_info *info,
 {
 	const void *blob = info->fdt_blob;
 	/* Reserve memory for maximum checksum-length */
-	uint8_t hash[info->algo->crypto->key_len];
+	uint8_t hash[info->crypto->key_len];
 	int ndepth, noffset;
 	int sig_node, node;
 	char name[100];
@@ -206,11 +205,10 @@ int rsa_verify(struct image_sign_info *info,
 	 * Verify that the checksum-length does not exceed the
 	 * rsa-signature-length
 	 */
-	if (info->algo->checksum->checksum_len >
-	    info->algo->crypto->key_len) {
+	if (info->checksum->checksum_len >
+	    info->crypto->key_len) {
 		debug("%s: invlaid checksum-algorithm %s for %s\n",
-		      __func__, info->algo->checksum->name,
-		      info->algo->crypto->name);
+		      __func__, info->checksum->name, info->crypto->name);
 		return -EINVAL;
 	}
 
@@ -221,7 +219,7 @@ int rsa_verify(struct image_sign_info *info,
 	}
 
 	/* Calculate checksum with checksum-algorithm */
-	ret = info->algo->checksum->calculate(info->algo->checksum->name,
+	ret = info->checksum->calculate(info->checksum->name,
 					region, region_count, hash);
 	if (ret < 0) {
 		debug("%s: Error in checksum calculation\n", __func__);
diff --git a/tools/image-host.c b/tools/image-host.c
index dac85b4..c1a0122 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -166,9 +166,11 @@ static int fit_image_setup_sig(struct image_sign_info *info,
 	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
 	info->fit = fit;
 	info->node_offset = noffset;
-	info->algo = image_get_sig_algo(algo_name);
+	info->name = algo_name;
+	info->checksum = image_get_checksum_algo(algo_name);
+	info->crypto = image_get_crypto_algo(algo_name);
 	info->require_keys = require_keys;
-	if (!info->algo) {
+	if (!info->checksum || !info->crypto) {
 		printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
 		       algo_name, node_name, image_name);
 		return -1;
@@ -213,7 +215,7 @@ static int fit_image_process_sig(const char *keydir, void *keydest,
 	node_name = fit_get_name(fit, noffset, NULL);
 	region.data = data;
 	region.size = size;
-	ret = info.algo->crypto->sign(&info, &region, 1, &value, &value_len);
+	ret = info.crypto->sign(&info, &region, 1, &value, &value_len);
 	if (ret) {
 		printf("Failed to sign '%s' signature node in '%s' image node: %d\n",
 		       node_name, image_name, ret);
@@ -239,7 +241,7 @@ static int fit_image_process_sig(const char *keydir, void *keydest,
 	info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
 
 	if (keydest)
-		ret = info.algo->crypto->add_verify_data(&info, keydest);
+		ret = info.crypto->add_verify_data(&info, keydest);
 	else
 		return -1;
 
@@ -588,8 +590,8 @@ static int fit_config_process_sig(const char *keydir, void *keydest,
 				require_keys ? "conf" : NULL))
 		return -1;
 
-	ret = info.algo->crypto->sign(&info, region, region_count, &value,
-				      &value_len);
+	ret = info.crypto->sign(&info, region, region_count, &value,
+				&value_len);
 	free(region);
 	if (ret) {
 		printf("Failed to sign '%s' signature node in '%s' conf node\n",
@@ -618,7 +620,7 @@ static int fit_config_process_sig(const char *keydir, void *keydest,
 
 	/* Write the public key into the supplied FDT file */
 	if (keydest) {
-		ret = info.algo->crypto->add_verify_data(&info, keydest);
+		ret = info.crypto->add_verify_data(&info, keydest);
 		if (ret == -ENOSPC)
 			return -ENOSPC;
 		if (ret) {
-- 
2.10.2



More information about the U-Boot mailing list