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 <chenjh@rock-chips.com>
Change-Id: Id9454100f9fdb06b30f9a4b2a7bdd180f117cb68
This commit is contained in:
Joseph Chen 2020-12-02 10:17:40 +08:00 committed by Jianhong Chen
parent bf8034353d
commit b6ea0cb4ad
1 changed files with 81 additions and 0 deletions

View File

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