diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index 39226ad4f2..9b49f6bd0b 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -700,6 +700,83 @@ int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp, return ret; } +static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len) +{ + int i; + + for (i = 0; i < len; i++) + dst[i] = fdt32_to_cpu(src[len - 1 - i]); +} + +static int rsa_set_key_hash(void *keydest, int key_node, + int key_len, const char *csum_algo) +{ + const void *rsa_n, *rsa_e, *rsa_c, *rsa_np; + void *n, *e, *c, *np; + uint8_t value[FIT_MAX_HASH_LEN]; + char hash_c[] = "hash@c"; + char hash_np[] = "hash@np"; + char *rsa_key; + int key_word; + int hash_node; + int value_len; + int ret = -ENOSPC; + + rsa_key = malloc(key_len * 3); + if (!rsa_key) + return -ENOSPC; + + rsa_n = fdt_getprop(keydest, key_node, "rsa,modulus", NULL); + rsa_e = fdt_getprop(keydest, key_node, "rsa,exponent-BN", NULL); + rsa_c = fdt_getprop(keydest, key_node, "rsa,c", NULL); + rsa_np = fdt_getprop(keydest, key_node, "rsa,np", NULL); + if (!rsa_c || !rsa_np || !rsa_n || !rsa_e) + goto err_nospc; + + n = rsa_key; + e = rsa_key + key_len; + key_word = key_len / sizeof(uint32_t); + rsa_convert_big_endian(n, rsa_n, key_word); + rsa_convert_big_endian(e, rsa_e, key_word); + + /* hash@c node: n, e, c */ + c = rsa_key + key_len * 2; + rsa_convert_big_endian(c, rsa_c, key_word); + hash_node = fdt_add_subnode(keydest, key_node, hash_c); + if (hash_node < 0) + goto err_nospc; + ret = calculate_hash(rsa_key, key_len * 3, csum_algo, value, &value_len); + if (ret) + goto err_nospc; + ret = fdt_setprop(keydest, hash_node, FIT_VALUE_PROP, value, value_len); + if (ret) + goto err_nospc; + ret = fdt_setprop_string(keydest, hash_node, FIT_ALGO_PROP, csum_algo); + if (ret < 0) + goto err_nospc; + + /* hash@np node: n, e, np */ + np = rsa_key + key_len * 2; + rsa_convert_big_endian(np, rsa_np, key_word); + hash_node = fdt_add_subnode(keydest, key_node, hash_np); + if (hash_node < 0) + goto err_nospc; + + ret = calculate_hash(rsa_key, key_len * 2 + 20, csum_algo, value, &value_len); + if (ret) + goto err_nospc; + ret = fdt_setprop(keydest, hash_node, FIT_VALUE_PROP, value, value_len); + if (ret < 0) + goto err_nospc; + ret = fdt_setprop_string(keydest, hash_node, FIT_ALGO_PROP, csum_algo); + +err_nospc: + if (rsa_key) + free(rsa_key); + + return ret ? -ENOSPC : 0; +} + static int fdt_add_bignum(void *blob, int noffset, const char *prop_name, BIGNUM *num, int num_bits) { @@ -854,6 +931,10 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest) ret = fdt_setprop_string(keydest, node, "required", info->require_keys); } + if (!ret) { + ret = rsa_set_key_hash(keydest, node, info->crypto->key_len, + info->checksum->name); + } done: BN_free(modulus); BN_free(r_squared);