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.rey...@softathome.com>
Reviewed-by: Simon Glass <s...@chromium.org>
---
 common/image-fit.c   |  5 +++++
 common/image-sig.c   | 29 ++++++++++++++++++++++++++
 include/image.h      | 16 +++++++++++++++
 include/u-boot/rsa.h | 13 ++++++++++++
 lib/rsa/rsa-sign.c   | 15 +++++++++++---
 lib/rsa/rsa-verify.c | 57 ++++++++++++++++++++++++++++++++++------------------
 tools/image-host.c   |  4 ++++
 7 files changed, 116 insertions(+), 23 deletions(-)

Changelog:
v2:
- no change

diff --git a/common/image-fit.c b/common/image-fit.c
index 8d39a24..ac901e1 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -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);
diff --git a/common/image-sig.c b/common/image-sig.c
index 5a269d3..b7ca657 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -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);
diff --git a/include/image.h b/include/image.h
index 3bb7d29..5c8154e 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1099,6 +1099,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 */
@@ -1184,6 +1185,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
  *
@@ -1201,6 +1209,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'
  *
  * @fit:               FIT to check
diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
index 68bcb14..16b4c4c 100644
--- a/include/u-boot/rsa.h
+++ b/include/u-boot/rsa.h
@@ -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)
 
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
index 78e348e..6aa0e2a 100644
--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -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;
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index bc83354..279a9ba 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -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;
 }
diff --git a/tools/image-host.c b/tools/image-host.c
index 09e4f47..88b3295 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -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) {
-- 
2.7.4

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to