Now that we have a struct public_key as a general container for keys
create and use functions making use of it. Move the list from struct
rsa_public_key to struct public_key, add public_key_verify() and use
it instead of rsa_verify(), move key_name_hint to struct public_key.

With this we do not need to bother the FIT image code when adding
support for ECDSA keys.

Signed-off-by: Sascha Hauer <[email protected]>
---
 common/image-fit.c          | 20 ++++----
 crypto/public-keys.c        | 92 ++++++++++++++++++++++++++++++-------
 crypto/rsa.c                | 74 +++++++++--------------------
 include/crypto/public_key.h | 15 ++++++
 include/rsa.h               | 16 +------
 scripts/keytoc.c            |  3 +-
 6 files changed, 126 insertions(+), 94 deletions(-)

diff --git a/common/image-fit.c b/common/image-fit.c
index 4a69049abc..c5d2196bda 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -20,7 +20,7 @@
 #include <errno.h>
 #include <linux/err.h>
 #include <stringlist.h>
-#include <rsa.h>
+#include <crypto/public_key.h>
 #include <uncompress.h>
 #include <image-fit.h>
 
@@ -253,10 +253,10 @@ static struct digest *fit_alloc_digest(struct device_node 
*sig_node,
        return digest;
 }
 
-static int fit_check_rsa_signature(struct device_node *sig_node,
-                                  enum hash_algo algo, void *hash)
+static int fit_check_signature(struct device_node *sig_node,
+                              enum hash_algo algo, void *hash)
 {
-       const struct rsa_public_key *key;
+       const struct public_key *key;
        const char *key_name = NULL;
        int sig_len;
        const char *sig_value;
@@ -270,19 +270,19 @@ static int fit_check_rsa_signature(struct device_node 
*sig_node,
 
        of_property_read_string(sig_node, "key-name-hint", &key_name);
        if (key_name) {
-               key = rsa_get_key(key_name);
+               key = public_key_get(key_name);
                if (key) {
-                       ret = rsa_verify(key, sig_value, sig_len, hash, algo);
+                       ret = public_key_verify(key, sig_value, sig_len, hash, 
algo);
                        if (!ret)
                                goto ok;
                }
        }
 
-       for_each_rsa_key(key) {
+       for_each_public_key(key) {
                if (key_name && !strcmp(key->key_name_hint, key_name))
                        continue;
 
-               ret = rsa_verify(key, sig_value, sig_len, hash, algo);
+               ret = public_key_verify(key, sig_value, sig_len, hash, algo);
                if (!ret)
                        goto ok;
        }
@@ -341,7 +341,7 @@ static int fit_verify_signature(struct device_node 
*sig_node, const void *fit)
        hash = xzalloc(digest_length(digest));
        digest_final(digest, hash);
 
-       ret = fit_check_rsa_signature(sig_node, algo, hash);
+       ret = fit_check_signature(sig_node, algo, hash);
        if (ret)
                goto out_free_hash;
 
@@ -464,7 +464,7 @@ static int fit_image_verify_signature(struct fit_handle 
*handle,
        hash = xzalloc(digest_length(digest));
        digest_final(digest, hash);
 
-       ret = fit_check_rsa_signature(sig_node, algo, hash);
+       ret = fit_check_signature(sig_node, algo, hash);
 
        free(hash);
 
diff --git a/crypto/public-keys.c b/crypto/public-keys.c
index a3ef3bafc8..36c308908d 100644
--- a/crypto/public-keys.c
+++ b/crypto/public-keys.c
@@ -2,31 +2,91 @@
 #include <crypto/public_key.h>
 #include <rsa.h>
 
+static LIST_HEAD(public_keys);
+
+const struct public_key *public_key_next(const struct public_key *prev)
+{
+       prev = list_prepare_entry(prev, &public_keys, list);
+       list_for_each_entry_continue(prev, &public_keys, list)
+               return prev;
+
+       return NULL;
+}
+
+const struct public_key *public_key_get(const char *name)
+{
+       const struct public_key *key;
+
+       list_for_each_entry(key, &public_keys, list) {
+               if (!strcmp(key->key_name_hint, name))
+                       return key;
+       }
+
+       return NULL;
+}
+
+int public_key_add(struct public_key *key)
+{
+       if (public_key_get(key->key_name_hint))
+               return -EEXIST;
+
+       list_add_tail(&key->list, &public_keys);
+
+       return 0;
+}
+
+static struct public_key *public_key_dup(const struct public_key *key)
+{
+       struct public_key *k = xzalloc(sizeof(*k));
+
+       k->type = key->type;
+       if (key->key_name_hint)
+               k->key_name_hint = xstrdup(key->key_name_hint);
+
+       switch (key->type) {
+       case PUBLIC_KEY_TYPE_RSA:
+               k->rsa = rsa_key_dup(key->rsa);
+               if (!k->rsa)
+                       goto err;
+               break;
+       default:
+               goto err;
+       }
+
+       return k;
+err:
+       free(k->key_name_hint);
+       free(k);
+
+       return NULL;
+}
+
+int public_key_verify(const struct public_key *key, const uint8_t *sig,
+                     const uint32_t sig_len, const uint8_t *hash,
+                     enum hash_algo algo)
+{
+       switch (key->type) {
+       case PUBLIC_KEY_TYPE_RSA:
+               return rsa_verify(key->rsa, sig, sig_len, hash, algo);
+       }
+
+       return -ENOKEY;
+}
+
 extern const struct public_key * const __public_keys_start;
 extern const struct public_key * const __public_keys_end;
 
 static int init_public_keys(void)
 {
        const struct public_key * const *iter;
-       int ret;
 
        for (iter = &__public_keys_start; iter != &__public_keys_end; iter++) {
-               struct rsa_public_key *rsa_key;
-
-               switch ((*iter)->type) {
-               case PUBLIC_KEY_TYPE_RSA:
-                       rsa_key = rsa_key_dup((*iter)->rsa);
-                       if (!rsa_key)
-                               continue;
-
-                       ret = rsa_key_add(rsa_key);
-                       if (ret)
-                               pr_err("Cannot add rsa key: %pe\n", 
ERR_PTR(ret));
-                       break;
-               default:
-                       pr_err("Ignoring unknown key type %u\n", (*iter)->type);
-               }
+               struct public_key *key = public_key_dup(*iter);
+
+               if (!key)
+                       continue;
 
+               public_key_add(key);
        }
 
        return 0;
diff --git a/crypto/rsa.c b/crypto/rsa.c
index 8eab07beed..969dbfb32b 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -15,6 +15,7 @@
 #include <asm/byteorder.h>
 #include <errno.h>
 #include <rsa.h>
+#include <crypto/public_key.h>
 #include <asm/unaligned.h>
 
 #define UINT64_MULT32(v, multby)  (((uint64_t)(v)) * ((uint32_t)(multby)))
@@ -380,105 +381,74 @@ static void rsa_convert_big_endian(uint32_t *dst, const 
uint32_t *src, int len)
                dst[i] = fdt32_to_cpu(src[len - 1 - i]);
 }
 
-struct rsa_public_key *rsa_of_read_key(struct device_node *node)
+struct public_key *rsa_of_read_key(struct device_node *node)
 {
        const void *modulus, *rr;
        const uint64_t *public_exponent;
        int length;
-       struct rsa_public_key *key;
+       struct public_key *key;
+       struct rsa_public_key *rsa;
        int err;
 
        if (strncmp(node->name, "key-", 4))
                return ERR_PTR(-EINVAL);
 
        key = xzalloc(sizeof(*key));
+       rsa = key->rsa = xzalloc(sizeof(*rsa));
 
        key->key_name_hint = xstrdup(node->name + 4);
 
-       of_property_read_u32(node, "rsa,num-bits", &key->len);
-       of_property_read_u32(node, "rsa,n0-inverse", &key->n0inv);
+       of_property_read_u32(node, "rsa,num-bits", &rsa->len);
+       of_property_read_u32(node, "rsa,n0-inverse", &rsa->n0inv);
 
        public_exponent = of_get_property(node, "rsa,exponent", &length);
        if (!public_exponent || length < sizeof(*public_exponent))
-               key->exponent = RSA_DEFAULT_PUBEXP;
+               rsa->exponent = RSA_DEFAULT_PUBEXP;
        else
-               key->exponent = fdt64_to_cpu(*public_exponent);
+               rsa->exponent = fdt64_to_cpu(*public_exponent);
 
        modulus = of_get_property(node, "rsa,modulus", NULL);
        rr = of_get_property(node, "rsa,r-squared", NULL);
 
-       if (!key->len || !modulus || !rr) {
+       if (!rsa->len || !modulus || !rr) {
                pr_debug("%s: Missing RSA key info", __func__);
                err = -EFAULT;
                goto out;
        }
 
        /* Sanity check for stack size */
-       if (key->len > RSA_MAX_KEY_BITS || key->len < RSA_MIN_KEY_BITS) {
+       if (rsa->len > RSA_MAX_KEY_BITS || rsa->len < RSA_MIN_KEY_BITS) {
                pr_debug("RSA key bits %u outside allowed range %d..%d\n",
-                        key->len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS);
+                        rsa->len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS);
                err = -EFAULT;
                goto out;
        }
 
-       key->len /= sizeof(uint32_t) * 8;
+       rsa->len /= sizeof(uint32_t) * 8;
 
-       key->modulus = xzalloc(RSA_MAX_KEY_BITS / 8);
-       key->rr = xzalloc(RSA_MAX_KEY_BITS / 8);
+       rsa->modulus = xzalloc(RSA_MAX_KEY_BITS / 8);
+       rsa->rr = xzalloc(RSA_MAX_KEY_BITS / 8);
 
-       rsa_convert_big_endian(key->modulus, modulus, key->len);
-       rsa_convert_big_endian(key->rr, rr, key->len);
+       rsa_convert_big_endian(rsa->modulus, modulus, rsa->len);
+       rsa_convert_big_endian(rsa->rr, rr, rsa->len);
 
        err = 0;
 out:
-       if (err)
+       if (err) {
                free(key);
+               free(rsa);
+       }
 
        return err ? ERR_PTR(err) : key;
 }
 
 void rsa_key_free(struct rsa_public_key *key)
 {
-       list_del(&key->list);
-
        free(key->modulus);
        free(key->rr);
        free(key);
 }
 
-static LIST_HEAD(rsa_keys);
-
-const struct rsa_public_key *rsa_key_next(const struct rsa_public_key *prev)
-{
-       prev = list_prepare_entry(prev, &rsa_keys, list);
-       list_for_each_entry_continue(prev, &rsa_keys, list)
-               return prev;
-
-       return NULL;
-}
-
-const struct rsa_public_key *rsa_get_key(const char *name)
-{
-       const struct rsa_public_key *key;
-
-       list_for_each_entry(key, &rsa_keys, list) {
-               if (!strcmp(key->key_name_hint, name))
-                       return key;
-       }
-
-       return NULL;
-}
-
-int rsa_key_add(struct rsa_public_key *key)
-{
-       if (rsa_get_key(key->key_name_hint))
-               return -EEXIST;
-
-       list_add_tail(&key->list, &rsa_keys);
-
-       return 0;
-}
-
 struct rsa_public_key *rsa_key_dup(const struct rsa_public_key *key)
 {
        struct rsa_public_key *new;
@@ -493,7 +463,7 @@ struct rsa_public_key *rsa_key_dup(const struct 
rsa_public_key *key)
 static void rsa_init_keys_of(void)
 {
        struct device_node *sigs, *sig;
-       struct rsa_public_key *key;
+       struct public_key *key;
        int ret;
 
        if (!IS_ENABLED(CONFIG_OFTREE))
@@ -511,7 +481,7 @@ static void rsa_init_keys_of(void)
                        continue;
                }
 
-               ret = rsa_key_add(key);
+               ret = public_key_add(key);
                if (ret)
                        pr_err("Cannot add rsa key %s: %s\n",
                                key->key_name_hint, strerror(-ret));
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index 83e8401aed..1b91063042 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -1,6 +1,8 @@
 #ifndef __CRYPTO_PUBLIC_KEY_H
 #define __CRYPTO_PUBLIC_KEY_H
 
+#include <digest.h>
+
 struct rsa_public_key;
 struct ecdsa_public_key;
 
@@ -10,6 +12,8 @@ enum pulic_key_type {
 
 struct public_key {
        enum pulic_key_type type;
+       struct list_head list;
+       char *key_name_hint;
 
        union {
                struct rsa_public_key *rsa;
@@ -17,4 +21,15 @@ struct public_key {
        };
 };
 
+int public_key_add(struct public_key *key);
+const struct public_key *public_key_get(const char *name);
+const struct public_key *public_key_next(const struct public_key *prev);
+
+#define for_each_public_key(key) \
+               for (key = public_key_next(NULL); key; key = 
public_key_next(key))
+
+int public_key_verify(const struct public_key *key, const uint8_t *sig,
+                     const uint32_t sig_len, const uint8_t *hash,
+                     enum hash_algo algo);
+
 #endif /* __CRYPTO_PUBLIC_KEY_H */
diff --git a/include/rsa.h b/include/rsa.h
index ecb2f42957..ef03a925b8 100644
--- a/include/rsa.h
+++ b/include/rsa.h
@@ -29,8 +29,6 @@ struct rsa_public_key {
        uint32_t *modulus;      /* modulus as little endian array */
        uint32_t *rr;           /* R^2 as little endian array */
        uint64_t exponent;      /* public exponent */
-       char *key_name_hint;
-       struct list_head list;
 };
 
 /**
@@ -54,24 +52,12 @@ int rsa_verify(const struct rsa_public_key *key, const 
uint8_t *sig,
 
 struct device_node;
 
-struct rsa_public_key *rsa_of_read_key(struct device_node *node);
+struct public_key *rsa_of_read_key(struct device_node *node);
 void rsa_key_free(struct rsa_public_key *key);
-const struct rsa_public_key *rsa_get_key(const char *name);
-
-const struct rsa_public_key *rsa_key_next(const struct rsa_public_key *prev);
-
-#define for_each_rsa_key(key) \
-               for (key = rsa_key_next(NULL); key; key = rsa_key_next(key))
 
 #ifdef CONFIG_CRYPTO_RSA
-int rsa_key_add(struct rsa_public_key *key);
 struct rsa_public_key *rsa_key_dup(const struct rsa_public_key *key);
 #else
-static inline int rsa_key_add(struct rsa_public_key *key)
-{
-       return -ENOSYS;
-}
-
 static inline struct rsa_public_key *rsa_key_dup(const struct rsa_public_key 
*key);
 {
        return NULL;
diff --git a/scripts/keytoc.c b/scripts/keytoc.c
index e66c5989bf..8b29118c95 100644
--- a/scripts/keytoc.c
+++ b/scripts/keytoc.c
@@ -491,6 +491,7 @@ static int gen_key_ecdsa(EVP_PKEY *key, const char 
*key_name, const char *key_na
                if (!standalone) {
                        fprintf(outfilep, "\nstatic struct public_key 
%s_public_key = {\n", key_name_c);
                        fprintf(outfilep, "\t.type = PUBLIC_KEY_TYPE_ECDSA,\n");
+                       fprintf(outfilep, "\t.key_name_hint = \"%s\",\n", 
key_name);
                        fprintf(outfilep, "\t.ecdsa = &%s,\n", key_name_c);
                        fprintf(outfilep, "};");
                        fprintf(outfilep, "\nstruct public_key *%s_ecdsa_p 
__attribute__((section(\".public_keys.rodata.%s\"))) = &%s_public_key;\n",
@@ -551,12 +552,12 @@ static int gen_key_rsa(EVP_PKEY *key, const char 
*key_name, const char *key_name
                fprintf(outfilep, "\t.modulus = %s_modulus,\n", key_name_c);
                fprintf(outfilep, "\t.rr = %s_rr,\n", key_name_c);
                fprintf(outfilep, "\t.exponent = 0x%0lx,\n", exponent);
-               fprintf(outfilep, "\t.key_name_hint = \"%s\",\n", key_name);
                fprintf(outfilep, "};\n");
 
                if (!standalone) {
                        fprintf(outfilep, "\nstatic struct public_key 
%s_public_key = {\n", key_name_c);
                        fprintf(outfilep, "\t.type = PUBLIC_KEY_TYPE_RSA,\n");
+                       fprintf(outfilep, "\t.key_name_hint = \"%s\",\n", 
key_name);
                        fprintf(outfilep, "\t.rsa = &%s,\n", key_name_c);
                        fprintf(outfilep, "};");
                        fprintf(outfilep, "\nstruct public_key *%sp 
__attribute__((section(\".public_keys.rodata.%s\"))) = &%s_public_key;\n",
-- 
2.39.2


Reply via email to