image: Combine image_sig_algo with image_sign_info
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@meraki.com>
Signed-off-by: aduda <aduda@meraki.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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 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 @@
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 @@
region.data = data;
region.size = size;
- if (info.algo->crypto->verify(&info, ®ion, 1, fit_value,
- fit_value_len)) {
+ if (info.crypto->verify(&info, ®ion, 1, fit_value, fit_value_len)) {
*err_msgp = "Verification failed";
return -1;
}
@@ -378,8 +383,8 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
{
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 @@
* 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 @@
}
/* 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 @@
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 @@
node_name = fit_get_name(fit, noffset, NULL);
region.data = data;
region.size = size;
- ret = info.algo->crypto->sign(&info, ®ion, 1, &value, &value_len);
+ ret = info.crypto->sign(&info, ®ion, 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 @@
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 @@
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 @@
/* 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) {