rsa: support write public hash in spl

Signed-off-by: Jason Zhu <jason.zhu@rock-chips.com>
Change-Id: I4120d0cad1cb24b45c3b281649e1eba520a11ee2
This commit is contained in:
Jason Zhu 2020-12-10 15:59:22 +08:00
parent 5c0419f083
commit 78263d89a3
4 changed files with 192 additions and 43 deletions

View File

@ -424,6 +424,12 @@ int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
*err_msgp = "Verification failed";
return -1;
}
/* Get the secure flag here and write the secure data and the secure flag */
#if !defined(USE_HOSTCC)
#ifdef CONFIG_SPL_FIT_HW_CRYPTO
rsa_burn_key_hash(&info);
#endif
#endif
return 0;
}

View File

@ -21,6 +21,7 @@
struct key_prop {
const void *rr; /* R^2 can be treated as byte array */
const void *modulus; /* modulus as byte array */
uint32_t burn_key; /* The flag to burn key's hash */
const void *public_exponent; /* public exponent as byte array */
const void *public_exponent_BN; /* public exponent as byte array */
#ifdef CONFIG_ROCKCHIP_CRYPTO_V1
@ -28,6 +29,7 @@ struct key_prop {
#else
const void *factor_np; /* rockchip crypto v2 accelerate factor */
#endif
const void *hash; /* the key hash */
uint32_t n0inv; /* -1 / modulus[0] mod 2^32 */
int num_bits; /* Key length in bits */
uint32_t exp_len; /* Exponent length in number of uint8_t */

View File

@ -103,6 +103,12 @@ int padding_pkcs_15_verify(struct image_sign_info *info,
uint8_t *msg, int msg_len,
const uint8_t *hash, int hash_len);
#if !defined(USE_HOSTCC)
#ifdef CONFIG_SPL_FIT_HW_CRYPTO
int rsa_burn_key_hash(struct image_sign_info *info);
#endif
#endif
#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
int padding_pss_verify(struct image_sign_info *info,
uint8_t *msg, int msg_len,

View File

@ -8,6 +8,7 @@
#include <common.h>
#include <crypto.h>
#include <fdtdec.h>
#include <misc.h>
#include <asm/types.h>
#include <asm/byteorder.h>
#include <linux/errno.h>
@ -414,6 +415,62 @@ static int rsa_verify_key(struct image_sign_info *info,
return 0;
}
static int rsa_get_key_prop(struct key_prop *prop, struct image_sign_info *info, int node)
{
const void *blob = info->fdt_blob;
int length;
int hash_node;
if (node < 0) {
debug("%s: Skipping invalid node", __func__);
return -EBADF;
}
if (!prop) {
debug("%s: The prop is NULL", __func__);
return -EBADF;
}
prop->burn_key = fdtdec_get_int(blob, node, "burn-key-hash", 0);
prop->num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
prop->n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
prop->public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
if (!prop->public_exponent || length < sizeof(uint64_t))
prop->public_exponent = NULL;
prop->exp_len = sizeof(uint64_t);
prop->modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
prop->public_exponent_BN = fdt_getprop(blob, node, "rsa,exponent-BN", NULL);
prop->rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
#ifdef CONFIG_ROCKCHIP_CRYPTO_V1
hash_node = fdt_subnode_offset(blob, node, "hash@c");
#else
hash_node = fdt_subnode_offset(blob, node, "hash@np");
#endif
if (hash_node >= 0)
prop->hash = fdt_getprop(blob, hash_node, "value", NULL);
if (!prop->num_bits || !prop->modulus) {
debug("%s: Missing RSA key info", __func__);
return -EFAULT;
}
#ifdef CONFIG_ROCKCHIP_CRYPTO_V1
prop->factor_c = fdt_getprop(blob, node, "rsa,c", NULL);
if (!prop.factor_c)
return -EFAULT;
#else
prop->factor_np = fdt_getprop(blob, node, "rsa,np", NULL);
if (!prop->factor_np)
return -EFAULT;
#endif
return 0;
}
/**
* rsa_verify_with_keynode() - Verify a signature against some data using
* information in node with prperties of RSA Key like modulus, exponent etc.
@ -433,53 +490,13 @@ static int rsa_verify_with_keynode(struct image_sign_info *info,
const void *hash, uint8_t *sig,
uint sig_len, int node)
{
const void *blob = info->fdt_blob;
struct key_prop prop;
int length;
int ret = 0;
if (node < 0) {
debug("%s: Skipping invalid node", __func__);
return -EBADF;
}
prop.num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
prop.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
prop.public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
if (!prop.public_exponent || length < sizeof(uint64_t))
prop.public_exponent = NULL;
prop.exp_len = sizeof(uint64_t);
prop.modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
prop.public_exponent_BN = fdt_getprop(blob, node, "rsa,exponent-BN", NULL);
prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
if (!prop.num_bits || !prop.modulus) {
debug("%s: Missing RSA key info", __func__);
if (rsa_get_key_prop(&prop, info, node))
return -EFAULT;
}
#if !defined(USE_HOSTCC)
#if CONFIG_IS_ENABLED(FIT_HW_CRYPTO)
#ifdef CONFIG_ROCKCHIP_CRYPTO_V1
prop.factor_c = fdt_getprop(blob, node, "rsa,c", NULL);
if (!prop.factor_c)
return -EFAULT;
#else
prop.factor_np = fdt_getprop(blob, node, "rsa,np", NULL);
if (!prop.factor_np)
return -EFAULT;
#endif
#endif
#endif
ret = rsa_verify_key(info, &prop, sig, sig_len, hash,
info->crypto->key_len);
return ret;
return rsa_verify_key(info, &prop, sig, sig_len, hash,
info->crypto->key_len);
}
int rsa_verify(struct image_sign_info *info,
@ -548,3 +565,121 @@ int rsa_verify(struct image_sign_info *info,
return ret;
}
#if !defined(USE_HOSTCC)
#ifdef CONFIG_SPL_FIT_HW_CRYPTO
int rsa_burn_key_hash(struct image_sign_info *info)
{
char *rsa_key;
void *n, *e, *c;
uint32_t key_len;
struct udevice *dev;
struct key_prop prop;
char name[100] = {0};
char secure_boot_enable = 0;
const void *blob = info->fdt_blob;
uint8_t digest[FIT_MAX_HASH_LEN];
uint8_t digest_read[FIT_MAX_HASH_LEN];
int sig_node, node, digest_len, i, ret = 0;
dev = misc_otp_get_device(OTP_S);
if (!dev)
return -ENODEV;
ret = misc_otp_read(dev, OTP_SECURE_BOOT_ENABLE_ADDR,
&secure_boot_enable, OTP_SECURE_BOOT_ENABLE_SIZE);
if (ret)
return ret;
if (secure_boot_enable)
return 0;
sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
if (sig_node < 0) {
debug("%s: No signature node found\n", __func__);
return -ENOENT;
}
snprintf(name, sizeof(name), "key-%s", info->keyname);
node = fdt_subnode_offset(blob, sig_node, name);
if (rsa_get_key_prop(&prop, info, node))
return -1;
if (!(prop.burn_key))
return -EPERM;
if (!prop.hash || !prop.modulus || !prop.public_exponent_BN)
return -ENOENT;
#ifdef CONFIG_ROCKCHIP_CRYPTO_V1
if (!prop.factor_c)
return -ENOENT;
#else
if (!prop.factor_np)
return -ENOENT;
#endif
key_len = info->crypto->key_len;
if (info->crypto->key_len != RSA2048_BYTES)
return -EINVAL;
rsa_key = malloc(key_len * 3);
if (!rsa_key)
return -ENOMEM;
n = rsa_key;
e = rsa_key + key_len;
c = rsa_key + key_len * 2;
rsa_convert_big_endian(n, (uint32_t *)prop.modulus,
key_len / sizeof(uint32_t));
rsa_convert_big_endian(e, (uint32_t *)prop.public_exponent_BN,
key_len / sizeof(uint32_t));
#ifdef CONFIG_ROCKCHIP_CRYPTO_V1
rsa_convert_big_endian(c, (uint32_t *)prop.factor_c,
key_len / sizeof(uint32_t));
#else
rsa_convert_big_endian(c, (uint32_t *)prop.factor_np,
key_len / sizeof(uint32_t));
#endif
ret = calculate_hash(rsa_key, key_len * 2 + OTP_RSA2048_C_SIZE,
info->checksum->name, digest, &digest_len);
if (ret)
goto error;
if (memcmp(digest, prop.hash, digest_len) != 0) {
printf("RSA: Compare public key fail.\n");
goto error;
}
/* burn key hash here */
ret = misc_otp_read(dev, OTP_RSA_HASH_ADDR, digest_read, OTP_RSA_HASH_SIZE);
if (ret)
goto error;
for (i = 0; i < OTP_RSA_HASH_SIZE; i++) {
if (digest_read[i]) {
printf("RSA: The secure region has been written.\n");
ret = -EIO;
goto error;
}
}
ret = misc_otp_write(dev, OTP_RSA_HASH_ADDR, digest, OTP_RSA_HASH_SIZE);
if (ret)
goto error;
secure_boot_enable = 0xff;
ret = misc_otp_write(dev, OTP_SECURE_BOOT_ENABLE_ADDR,
&secure_boot_enable, OTP_SECURE_BOOT_ENABLE_SIZE);
if (ret)
goto error;
printf("RSAWrite key hash successfully\n");
error:
free(rsa_key);
return ret;
}
#endif
#endif