rsa: add a structure for the padding
The rsa signature use a padding algorithm. By default, we use the padding pkcs-1.5. In order to add some new padding algorithm, we add a padding framework to manage several padding algorithm. The choice of the padding is done in the file .its. Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
3b5d6979fc
commit
20031567e1
@ -165,6 +165,7 @@ static void fit_image_print_data(const void *fit, int noffset, const char *p,
|
||||
uint8_t *value;
|
||||
int value_len;
|
||||
char *algo;
|
||||
const char *padding;
|
||||
int required;
|
||||
int ret, i;
|
||||
|
||||
@ -184,6 +185,10 @@ static void fit_image_print_data(const void *fit, int noffset, const char *p,
|
||||
printf(" (required)");
|
||||
printf("\n");
|
||||
|
||||
padding = fdt_getprop(fit, noffset, "padding", NULL);
|
||||
if (padding)
|
||||
printf("%s %s padding: %s\n", p, type, padding);
|
||||
|
||||
ret = fit_image_hash_get_value(fit, noffset, &value,
|
||||
&value_len);
|
||||
printf("%s %s value: ", p, type);
|
||||
|
@ -71,6 +71,13 @@ struct crypto_algo crypto_algos[] = {
|
||||
|
||||
};
|
||||
|
||||
struct padding_algo padding_algos[] = {
|
||||
{
|
||||
.name = "pkcs-1.5",
|
||||
.verify = padding_pkcs_15_verify,
|
||||
},
|
||||
};
|
||||
|
||||
struct checksum_algo *image_get_checksum_algo(const char *full_name)
|
||||
{
|
||||
int i;
|
||||
@ -106,6 +113,21 @@ struct crypto_algo *image_get_crypto_algo(const char *full_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct padding_algo *image_get_padding_algo(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(padding_algos); i++) {
|
||||
if (!strcmp(padding_algos[i].name, name))
|
||||
return &padding_algos[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* fit_region_make_list() - Make a list of image regions
|
||||
*
|
||||
@ -155,6 +177,7 @@ static int fit_image_setup_verify(struct image_sign_info *info,
|
||||
char **err_msgp)
|
||||
{
|
||||
char *algo_name;
|
||||
const char *padding_name;
|
||||
|
||||
if (fdt_totalsize(fit) > CONFIG_FIT_SIGNATURE_MAX_SIZE) {
|
||||
*err_msgp = "Total size too large";
|
||||
@ -165,6 +188,11 @@ static int fit_image_setup_verify(struct image_sign_info *info,
|
||||
*err_msgp = "Can't get hash algo property";
|
||||
return -1;
|
||||
}
|
||||
|
||||
padding_name = fdt_getprop(fit, noffset, "padding", NULL);
|
||||
if (!padding_name)
|
||||
padding_name = RSA_DEFAULT_PADDING_NAME;
|
||||
|
||||
memset(info, '\0', sizeof(*info));
|
||||
info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
|
||||
info->fit = (void *)fit;
|
||||
@ -172,6 +200,7 @@ static int fit_image_setup_verify(struct image_sign_info *info,
|
||||
info->name = algo_name;
|
||||
info->checksum = image_get_checksum_algo(algo_name);
|
||||
info->crypto = image_get_crypto_algo(algo_name);
|
||||
info->padding = image_get_padding_algo(padding_name);
|
||||
info->fdt_blob = gd_fdt_blob();
|
||||
info->required_keynode = required_keynode;
|
||||
printf("%s:%s", algo_name, info->keyname);
|
||||
|
@ -1101,6 +1101,7 @@ struct image_sign_info {
|
||||
int node_offset; /* Offset of signature node */
|
||||
const char *name; /* Algorithm name */
|
||||
struct checksum_algo *checksum; /* Checksum algorithm information */
|
||||
struct padding_algo *padding; /* Padding 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 */
|
||||
@ -1186,6 +1187,13 @@ struct crypto_algo {
|
||||
uint8_t *sig, uint sig_len);
|
||||
};
|
||||
|
||||
struct padding_algo {
|
||||
const char *name;
|
||||
int (*verify)(struct image_sign_info *info,
|
||||
uint8_t *pad, int pad_len,
|
||||
const uint8_t *hash, int hash_len);
|
||||
};
|
||||
|
||||
/**
|
||||
* image_get_checksum_algo() - Look up a checksum algorithm
|
||||
*
|
||||
@ -1202,6 +1210,14 @@ struct checksum_algo *image_get_checksum_algo(const char *full_name);
|
||||
*/
|
||||
struct crypto_algo *image_get_crypto_algo(const char *full_name);
|
||||
|
||||
/**
|
||||
* image_get_padding_algo() - Look up a padding algorithm
|
||||
*
|
||||
* @param name Name of padding algorithm
|
||||
* @return pointer to algorithm information, or NULL if not found
|
||||
*/
|
||||
struct padding_algo *image_get_padding_algo(const char *name);
|
||||
|
||||
/**
|
||||
* fit_image_verify_required_sigs() - Verify signatures marked as 'required'
|
||||
*
|
||||
|
@ -97,6 +97,10 @@ static inline int rsa_add_verify_data(struct image_sign_info *info,
|
||||
int rsa_verify(struct image_sign_info *info,
|
||||
const struct image_region region[], int region_count,
|
||||
uint8_t *sig, uint sig_len);
|
||||
|
||||
int padding_pkcs_15_verify(struct image_sign_info *info,
|
||||
uint8_t *msg, int msg_len,
|
||||
const uint8_t *hash, int hash_len);
|
||||
#else
|
||||
static inline int rsa_verify(struct image_sign_info *info,
|
||||
const struct image_region region[], int region_count,
|
||||
@ -104,8 +108,17 @@ static inline int rsa_verify(struct image_sign_info *info,
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static inline int padding_pkcs_15_verify(struct image_sign_info *info,
|
||||
uint8_t *msg, int msg_len,
|
||||
const uint8_t *hash, int hash_len)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define RSA_DEFAULT_PADDING_NAME "pkcs-1.5"
|
||||
|
||||
#define RSA2048_BYTES (2048 / 8)
|
||||
#define RSA4096_BYTES (4096 / 8)
|
||||
|
||||
|
@ -387,11 +387,13 @@ static void rsa_engine_remove(ENGINE *e)
|
||||
}
|
||||
}
|
||||
|
||||
static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
|
||||
static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo,
|
||||
struct checksum_algo *checksum_algo,
|
||||
const struct image_region region[], int region_count,
|
||||
uint8_t **sigp, uint *sig_size)
|
||||
{
|
||||
EVP_PKEY *key;
|
||||
EVP_PKEY_CTX *ckey;
|
||||
EVP_MD_CTX *context;
|
||||
int ret = 0;
|
||||
size_t size;
|
||||
@ -422,7 +424,14 @@ static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
|
||||
goto err_create;
|
||||
}
|
||||
EVP_MD_CTX_init(context);
|
||||
if (EVP_DigestSignInit(context, NULL,
|
||||
|
||||
ckey = EVP_PKEY_CTX_new(key, NULL);
|
||||
if (!ckey) {
|
||||
ret = rsa_err("EVP key context creation failed");
|
||||
goto err_create;
|
||||
}
|
||||
|
||||
if (EVP_DigestSignInit(context, &ckey,
|
||||
checksum_algo->calculate_sign(),
|
||||
NULL, key) <= 0) {
|
||||
ret = rsa_err("Signer setup failed");
|
||||
@ -488,7 +497,7 @@ int rsa_sign(struct image_sign_info *info,
|
||||
ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
|
||||
if (ret)
|
||||
goto err_priv;
|
||||
ret = rsa_sign_with_key(rsa, info->checksum, region,
|
||||
ret = rsa_sign_with_key(rsa, info->padding, info->checksum, region,
|
||||
region_count, sigp, sig_len);
|
||||
if (ret)
|
||||
goto err_sign;
|
||||
|
@ -57,31 +57,57 @@ static int rsa_verify_padding(const uint8_t *msg, const int pad_len,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int padding_pkcs_15_verify(struct image_sign_info *info,
|
||||
uint8_t *msg, int msg_len,
|
||||
const uint8_t *hash, int hash_len)
|
||||
{
|
||||
struct checksum_algo *checksum = info->checksum;
|
||||
int ret, pad_len = msg_len - checksum->checksum_len;
|
||||
|
||||
/* Check pkcs1.5 padding bytes. */
|
||||
ret = rsa_verify_padding(msg, pad_len, checksum);
|
||||
if (ret) {
|
||||
debug("In RSAVerify(): Padding check failed!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check hash. */
|
||||
if (memcmp((uint8_t *)msg + pad_len, hash, msg_len - pad_len)) {
|
||||
debug("In RSAVerify(): Hash check failed!\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* rsa_verify_key() - Verify a signature against some data using RSA Key
|
||||
*
|
||||
* Verify a RSA PKCS1.5 signature against an expected hash using
|
||||
* the RSA Key properties in prop structure.
|
||||
*
|
||||
* @info: Specifies key and FIT information
|
||||
* @prop: Specifies key
|
||||
* @sig: Signature
|
||||
* @sig_len: Number of bytes in signature
|
||||
* @hash: Pointer to the expected hash
|
||||
* @key_len: Number of bytes in rsa key
|
||||
* @algo: Checksum algo structure having information on DER encoding etc.
|
||||
* @return 0 if verified, -ve on error
|
||||
*/
|
||||
static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig,
|
||||
static int rsa_verify_key(struct image_sign_info *info,
|
||||
struct key_prop *prop, const uint8_t *sig,
|
||||
const uint32_t sig_len, const uint8_t *hash,
|
||||
const uint32_t key_len, struct checksum_algo *algo)
|
||||
const uint32_t key_len)
|
||||
{
|
||||
int pad_len;
|
||||
int ret;
|
||||
#if !defined(USE_HOSTCC)
|
||||
struct udevice *mod_exp_dev;
|
||||
#endif
|
||||
struct checksum_algo *checksum = info->checksum;
|
||||
struct padding_algo *padding = info->padding;
|
||||
int hash_len = checksum->checksum_len;
|
||||
|
||||
if (!prop || !sig || !hash || !algo)
|
||||
if (!prop || !sig || !hash || !checksum)
|
||||
return -EIO;
|
||||
|
||||
if (sig_len != (prop->num_bits / 8)) {
|
||||
@ -89,7 +115,7 @@ static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
debug("Checksum algorithm: %s", algo->name);
|
||||
debug("Checksum algorithm: %s", checksum->name);
|
||||
|
||||
/* Sanity check for stack size */
|
||||
if (sig_len > RSA_MAX_SIG_BITS / 8) {
|
||||
@ -116,19 +142,10 @@ static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig,
|
||||
return ret;
|
||||
}
|
||||
|
||||
pad_len = key_len - algo->checksum_len;
|
||||
|
||||
/* Check pkcs1.5 padding bytes. */
|
||||
ret = rsa_verify_padding(buf, pad_len, algo);
|
||||
ret = padding->verify(info, buf, key_len, hash, hash_len);
|
||||
if (ret) {
|
||||
debug("In RSAVerify(): Padding check failed!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check hash. */
|
||||
if (memcmp((uint8_t *)buf + pad_len, hash, sig_len - pad_len)) {
|
||||
debug("In RSAVerify(): Hash check failed!\n");
|
||||
return -EACCES;
|
||||
debug("In RSAVerify(): padding check failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -182,8 +199,8 @@ static int rsa_verify_with_keynode(struct image_sign_info *info,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = rsa_verify_key(&prop, sig, sig_len, hash,
|
||||
info->crypto->key_len, info->checksum);
|
||||
ret = rsa_verify_key(info, &prop, sig, sig_len, hash,
|
||||
info->crypto->key_len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -157,6 +157,7 @@ static int fit_image_setup_sig(struct image_sign_info *info,
|
||||
{
|
||||
const char *node_name;
|
||||
char *algo_name;
|
||||
const char *padding_name;
|
||||
|
||||
node_name = fit_get_name(fit, noffset, NULL);
|
||||
if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
|
||||
@ -165,6 +166,8 @@ static int fit_image_setup_sig(struct image_sign_info *info,
|
||||
return -1;
|
||||
}
|
||||
|
||||
padding_name = fdt_getprop(fit, noffset, "padding", NULL);
|
||||
|
||||
memset(info, '\0', sizeof(*info));
|
||||
info->keydir = keydir;
|
||||
info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
|
||||
@ -173,6 +176,7 @@ static int fit_image_setup_sig(struct image_sign_info *info,
|
||||
info->name = strdup(algo_name);
|
||||
info->checksum = image_get_checksum_algo(algo_name);
|
||||
info->crypto = image_get_crypto_algo(algo_name);
|
||||
info->padding = image_get_padding_algo(padding_name);
|
||||
info->require_keys = require_keys;
|
||||
info->engine_id = engine_id;
|
||||
if (!info->checksum || !info->crypto) {
|
||||
|
Loading…
Reference in New Issue
Block a user