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:
Philippe Reynes 2018-11-14 13:51:00 +01:00 committed by Tom Rini
parent 3b5d6979fc
commit 20031567e1
7 changed files with 116 additions and 23 deletions

View file

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

View file

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

View file

@ -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'
*

View file

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

View file

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

View file

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

View file

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