From b6ea0cb4adae620c68f381ac2f0a0e6d716e13f4 Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Wed, 2 Dec 2020 10:17:40 +0800 Subject: [PATCH] lib: rsa-sign: add rockchip rsa key hash SPL requires key hash to verify and flash it to OTP/EFUSE. - hash@c: n, e, c - hash@np: n, e, np / { signature { key-dev { required = "conf"; algo = "sha256,rsa2048"; rsa,np = <...>; rsa,c = <...>; rsa,modulus = <...>; rsa,exponent-BN = <...>; ... key-name-hint = "dev"; hash@np { algo = "sha256"; value = <0x0934bc4d 0xfbc31ffe 0x9224d6c2 0x1a3aa280 0x881d881e 0xe2006246 0x01b9e724 0x35c03428>; }; hash@c { algo = "sha256"; value = <0x08962385 0x34585e06 0x0b73a496 0x374b148d 0xa2700a75 0x4aae08ad 0xb2a324a3 0x95ee6b52>; }; }; }; ... }; But after processed by scripts/fit.sh, only one of "hash@c" and "hash@np" would be left. Signed-off-by: Joseph Chen Change-Id: Id9454100f9fdb06b30f9a4b2a7bdd180f117cb68 --- lib/rsa/rsa-sign.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) 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);