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>
This commit is contained in:
Andrew Duda 2016-11-08 18:53:41 +00:00 committed by Tom Rini
parent 0c1d74fda7
commit 83dd98e012
5 changed files with 65 additions and 58 deletions

View file

@ -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 image_sig_algo *image_get_sig_algo(const char *name)
struct checksum_algo *image_get_checksum_algo(const char *full_name)
{
int i;
const char *name;
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(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 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(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;
}

View file

@ -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_sig_algo() - Look up a signature algortihm
* image_get_checksum_algo() - Look up a checksum 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 checksum_algo *image_get_checksum_algo(const char *full_name);
/**
* image_get_crypto_algo() - Look up a cryptosystem algorithm
*
* @param full_name Name of algorithm in the form "checksum,crypto"
* @return pointer to algorithm information, or NULL if not found
*/
struct crypto_algo *image_get_crypto_algo(const char *full_name);
/**
* fit_image_verify_required_sigs() - Verify signatures marked as 'required'

View file

@ -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",

View file

@ -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__);

View file

@ -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) {