* [PATCH 0/5] Allow to compile in rsa public keys directly @ 2019-10-15 7:55 Sascha Hauer 2019-10-15 7:55 ` [PATCH 1/5] Kbuild: Add config_filename macro from kernel Sascha Hauer ` (4 more replies) 0 siblings, 5 replies; 9+ messages in thread From: Sascha Hauer @ 2019-10-15 7:55 UTC (permalink / raw) To: Barebox List So far we relied on U-Boots mkimage tool to generate dts snippets from RSA public keys which are then compiled into barebox. This series simplifies this by allowing to compile in RSA public keys directly into barebox. Keys are retrieved from certificate files in PEM format or from PKCS#11 URIs. Sascha Hauer (5): Kbuild: Add config_filename macro from kernel scripts: Add rsatoc tool rsa: let rsa_of_read_key() return a fully allocated key rsa: Allow to directly compile in rsa public keys fit-image: Use compiled-in keys common/image-fit.c | 27 +- crypto/.gitignore | 2 + crypto/Kconfig | 19 ++ crypto/Makefile | 10 + crypto/rsa.c | 59 +++- include/asm-generic/barebox.lds.h | 6 + include/rsa.h | 5 +- scripts/.gitignore | 1 + scripts/Kbuild.include | 49 ++++ scripts/Makefile | 3 + scripts/Makefile.lib | 18 ++ scripts/rsatoc.c | 445 ++++++++++++++++++++++++++++++ 12 files changed, 629 insertions(+), 15 deletions(-) create mode 100644 crypto/.gitignore create mode 100644 scripts/rsatoc.c -- 2.23.0 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/5] Kbuild: Add config_filename macro from kernel 2019-10-15 7:55 [PATCH 0/5] Allow to compile in rsa public keys directly Sascha Hauer @ 2019-10-15 7:55 ` Sascha Hauer 2019-10-15 7:55 ` [PATCH 2/5] scripts: Add rsatoc tool Sascha Hauer ` (3 subsequent siblings) 4 siblings, 0 replies; 9+ messages in thread From: Sascha Hauer @ 2019-10-15 7:55 UTC (permalink / raw) To: Barebox List The config_filename allows to extract a filename from a Kconfig string option. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- scripts/Kbuild.include | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index a2dbbd8a00..c08b9a824d 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -268,6 +268,55 @@ why = \ echo-why = $(call escsq, $(strip $(why))) endif +############################################################################### +# +# When a Kconfig string contains a filename, it is suitable for +# passing to shell commands. It is surrounded by double-quotes, and +# any double-quotes or backslashes within it are escaped by +# backslashes. +# +# This is no use for dependencies or $(wildcard). We need to strip the +# surrounding quotes and the escaping from quotes and backslashes, and +# we *do* need to escape any spaces in the string. So, for example: +# +# Usage: $(eval $(call config_filename,FOO)) +# +# Defines FOO_FILENAME based on the contents of the CONFIG_FOO option, +# transformed as described above to be suitable for use within the +# makefile. +# +# Also, if the filename is a relative filename and exists in the source +# tree but not the build tree, define FOO_SRCPREFIX as $(srctree)/ to +# be prefixed to *both* command invocation and dependencies. +# +# Note: We also print the filenames in the quiet_cmd_foo text, and +# perhaps ought to have a version specially escaped for that purpose. +# But it's only cosmetic, and $(patsubst "%",%,$(CONFIG_FOO)) is good +# enough. It'll strip the quotes in the common case where there's no +# space and it's a simple filename, and it'll retain the quotes when +# there's a space. There are some esoteric cases in which it'll print +# the wrong thing, but we don't really care. The actual dependencies +# and commands *do* get it right, with various combinations of single +# and double quotes, backslashes and spaces in the filenames. +# +############################################################################### +# +define config_filename +ifneq ($$(CONFIG_$(1)),"") +$(1)_FILENAME := $$(subst \\,\,$$(subst \$$(quote),$$(quote),$$(subst $$(space_escape),\$$(space),$$(patsubst "%",%,$$(subst $$(space),$$(space_escape),$$(CONFIG_$(1))))))) +ifneq ($$(patsubst /%,%,$$(firstword $$($(1)_FILENAME))),$$(firstword $$($(1)_FILENAME))) +else +ifeq ($$(wildcard $$($(1)_FILENAME)),) +ifneq ($$(wildcard $$(srctree)/$$($(1)_FILENAME)),) +$(1)_SRCPREFIX := $(srctree)/ +endif +endif +endif +endif +endef +# +############################################################################### + # delete partially updated (i.e. corrupted) files on error .DELETE_ON_ERROR: -- 2.23.0 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/5] scripts: Add rsatoc tool 2019-10-15 7:55 [PATCH 0/5] Allow to compile in rsa public keys directly Sascha Hauer 2019-10-15 7:55 ` [PATCH 1/5] Kbuild: Add config_filename macro from kernel Sascha Hauer @ 2019-10-15 7:55 ` Sascha Hauer 2019-10-15 10:21 ` Ahmad Fatoum 2019-10-15 7:55 ` [PATCH 3/5] rsa: let rsa_of_read_key() return a fully allocated key Sascha Hauer ` (2 subsequent siblings) 4 siblings, 1 reply; 9+ messages in thread From: Sascha Hauer @ 2019-10-15 7:55 UTC (permalink / raw) To: Barebox List The rsatoc tool converts rsa public keys into C structs suitable to compile with barebox. Most of the openssl rsa related stuff has been taken from the U-Boot mkimage tool. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- scripts/.gitignore | 1 + scripts/Makefile | 3 + scripts/rsatoc.c | 445 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 449 insertions(+) create mode 100644 scripts/rsatoc.c diff --git a/scripts/.gitignore b/scripts/.gitignore index 45c81bf8f4..76ea271abb 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -29,3 +29,4 @@ mxs-usb-loader omap4_usbboot omap3-usb-loader mips-relocs +rsatoc diff --git a/scripts/Makefile b/scripts/Makefile index dffab53c73..81d1a501b0 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -10,6 +10,9 @@ hostprogs-y += fix_size hostprogs-y += bareboxenv hostprogs-y += bareboxcrc32 hostprogs-y += kernel-install +hostprogs-$(CONFIG_CRYPTO_RSA_BUILTIN_KEYS) += rsatoc +HOSTCFLAGS_rsatoc = `pkg-config --cflags openssl` +HOSTLDLIBS_rsatoc = `pkg-config --libs openssl` hostprogs-$(CONFIG_IMD) += bareboximd hostprogs-$(CONFIG_KALLSYMS) += kallsyms hostprogs-$(CONFIG_MIPS) += mips-relocs diff --git a/scripts/rsatoc.c b/scripts/rsatoc.c new file mode 100644 index 0000000000..f853691908 --- /dev/null +++ b/scripts/rsatoc.c @@ -0,0 +1,445 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * rsatoc - utility to convert an RSA key to a C struct + * + * This tool converts an RSA key given as file or PKCS#11 + * URI to a C struct suitable to compile with barebox. + */ +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <openssl/bn.h> +#include <openssl/rsa.h> +#include <openssl/pem.h> +#include <openssl/err.h> +#include <openssl/ssl.h> +#include <openssl/evp.h> +#include <openssl/engine.h> + +static int rsa_err(const char *msg) +{ + unsigned long sslErr = ERR_get_error(); + + fprintf(stderr, "%s", msg); + fprintf(stderr, ": %s\n", + ERR_error_string(sslErr, 0)); + + return -1; +} + +/** + * rsa_pem_get_pub_key() - read a public key from a .crt file + * + * @keydir: Directory containins the key + * @name Name of key file (will have a .crt extension) + * @rsap Returns RSA object, or NULL on failure + * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL) + */ +static int rsa_pem_get_pub_key(const char *path, RSA **rsap) +{ + EVP_PKEY *key; + X509 *cert; + RSA *rsa; + FILE *f; + int ret; + + *rsap = NULL; + f = fopen(path, "r"); + if (!f) { + fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n", + path, strerror(errno)); + return -EACCES; + } + + /* Read the certificate */ + cert = NULL; + if (!PEM_read_X509(f, &cert, NULL, NULL)) { + rsa_err("Couldn't read certificate"); + ret = -EINVAL; + goto err_cert; + } + + /* Get the public key from the certificate. */ + key = X509_get_pubkey(cert); + if (!key) { + rsa_err("Couldn't read public key\n"); + ret = -EINVAL; + goto err_pubkey; + } + + /* Convert to a RSA_style key. */ + rsa = EVP_PKEY_get1_RSA(key); + if (!rsa) { + rsa_err("Couldn't convert to a RSA style key"); + ret = -EINVAL; + goto err_rsa; + } + fclose(f); + EVP_PKEY_free(key); + X509_free(cert); + *rsap = rsa; + + return 0; + +err_rsa: + EVP_PKEY_free(key); +err_pubkey: + X509_free(cert); +err_cert: + fclose(f); + return ret; +} + +/** + * rsa_engine_get_pub_key() - read a public key from given engine + * + * @keydir: Key prefix + * @name Name of key + * @engine Engine to use + * @rsap Returns RSA object, or NULL on failure + * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL) + */ +static int rsa_engine_get_pub_key(const char *key_id, + ENGINE *engine, RSA **rsap) +{ + EVP_PKEY *key; + RSA *rsa; + int ret; + + *rsap = NULL; + + key = ENGINE_load_public_key(engine, key_id, NULL, NULL); + if (!key) + return rsa_err("Failure loading public key from engine"); + + /* Convert to a RSA_style key. */ + rsa = EVP_PKEY_get1_RSA(key); + if (!rsa) { + rsa_err("Couldn't convert to a RSA style key"); + ret = -EINVAL; + goto err_rsa; + } + + EVP_PKEY_free(key); + *rsap = rsa; + + return 0; + +err_rsa: + EVP_PKEY_free(key); + return ret; +} + +/* + * rsa_get_exponent(): - Get the public exponent from an RSA key + */ +static int rsa_get_exponent(RSA *key, uint64_t *e) +{ + int ret; + BIGNUM *bn_te; + const BIGNUM *key_e; + uint64_t te; + + ret = -EINVAL; + bn_te = NULL; + + if (!e) + goto cleanup; + + RSA_get0_key(key, NULL, &key_e, NULL); + if (BN_num_bits(key_e) > 64) + goto cleanup; + + *e = BN_get_word(key_e); + + if (BN_num_bits(key_e) < 33) { + ret = 0; + goto cleanup; + } + + bn_te = BN_dup(key_e); + if (!bn_te) + goto cleanup; + + if (!BN_rshift(bn_te, bn_te, 32)) + goto cleanup; + + if (!BN_mask_bits(bn_te, 32)) + goto cleanup; + + te = BN_get_word(bn_te); + te <<= 32; + *e |= te; + ret = 0; + +cleanup: + if (bn_te) + BN_free(bn_te); + + return ret; +} + +/* + * rsa_get_params(): - Get the important parameters of an RSA public key + */ +int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp, + BIGNUM **modulusp, BIGNUM **r_squaredp) +{ + BIGNUM *big1, *big2, *big32, *big2_32; + BIGNUM *n, *r, *r_squared, *tmp; + const BIGNUM *key_n; + BN_CTX *bn_ctx = BN_CTX_new(); + int ret = 0; + + /* Initialize BIGNUMs */ + big1 = BN_new(); + big2 = BN_new(); + big32 = BN_new(); + r = BN_new(); + r_squared = BN_new(); + tmp = BN_new(); + big2_32 = BN_new(); + n = BN_new(); + if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 || + !n) { + fprintf(stderr, "Out of memory (bignum)\n"); + return -ENOMEM; + } + + if (0 != rsa_get_exponent(key, exponent)) + ret = -1; + + RSA_get0_key(key, &key_n, NULL, NULL); + if (!BN_copy(n, key_n) || !BN_set_word(big1, 1L) || + !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L)) + ret = -1; + + /* big2_32 = 2^32 */ + if (!BN_exp(big2_32, big2, big32, bn_ctx)) + ret = -1; + + /* Calculate n0_inv = -1 / n[0] mod 2^32 */ + if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) || + !BN_sub(tmp, big2_32, tmp)) + ret = -1; + *n0_invp = BN_get_word(tmp); + + /* Calculate R = 2^(# of key bits) */ + if (!BN_set_word(tmp, BN_num_bits(n)) || + !BN_exp(r, big2, tmp, bn_ctx)) + ret = -1; + + /* Calculate r_squared = R^2 mod n */ + if (!BN_copy(r_squared, r) || + !BN_mul(tmp, r_squared, r, bn_ctx) || + !BN_mod(r_squared, tmp, n, bn_ctx)) + ret = -1; + + *modulusp = n; + *r_squaredp = r_squared; + + BN_free(big1); + BN_free(big2); + BN_free(big32); + BN_free(r); + BN_free(tmp); + BN_free(big2_32); + if (ret) { + fprintf(stderr, "Bignum operations failed\n"); + return -ENOMEM; + } + + return ret; +} + +static int rsa_engine_init(ENGINE **pe) +{ + ENGINE *e; + int ret; + + ENGINE_load_builtin_engines(); + + e = ENGINE_by_id("pkcs11"); + if (!e) { + fprintf(stderr, "Engine isn't available\n"); + ret = -1; + goto err_engine_by_id; + } + + if (!ENGINE_init(e)) { + fprintf(stderr, "Couldn't initialize engine\n"); + ret = -1; + goto err_engine_init; + } + + if (!ENGINE_set_default_RSA(e)) { + fprintf(stderr, "Couldn't set engine as default for RSA\n"); + ret = -1; + goto err_set_rsa; + } + + *pe = e; + + return 0; + +err_set_rsa: + ENGINE_finish(e); +err_engine_init: + ENGINE_free(e); +err_engine_by_id: +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) + ENGINE_cleanup(); +#endif + return ret; +} + +static int print_bignum(BIGNUM *num, int num_bits) +{ + BIGNUM *tmp, *big2, *big32, *big2_32; + BN_CTX *ctx; + int i; + + tmp = BN_new(); + big2 = BN_new(); + big32 = BN_new(); + big2_32 = BN_new(); + + /* + * Note: This code assumes that all of the above succeed, or all fail. + * In practice memory allocations generally do not fail (unless the + * process is killed), so it does not seem worth handling each of these + * as a separate case. Technicaly this could leak memory on failure, + * but a) it won't happen in practice, and b) it doesn't matter as we + * will immediately exit with a failure code. + */ + if (!tmp || !big2 || !big32 || !big2_32) { + fprintf(stderr, "Out of memory (bignum)\n"); + return -ENOMEM; + } + ctx = BN_CTX_new(); + if (!tmp) { + fprintf(stderr, "Out of memory (bignum context)\n"); + return -ENOMEM; + } + BN_set_word(big2, 2L); + BN_set_word(big32, 32L); + BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */ + + for (i = 0; i < num_bits / 32; i++) { + BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */ + if (i % 4) + printf(" "); + else + printf("\n\t"); + printf("0x%08lx,", BN_get_word(tmp)); + BN_rshift(num, num, 32); /* N = N/B */ + } + + BN_free(tmp); + BN_free(big2); + BN_free(big32); + BN_free(big2_32); + + return 0; +} + +static int gen_key(const char *keyname, const char *path) +{ + BIGNUM *modulus, *r_squared; + uint64_t exponent; + uint32_t n0_inv; + int ret; + int bits; + RSA *rsa; + ENGINE *e = NULL; + char *tmp, *key_name_c; + + tmp = key_name_c = strdup(keyname); + + while (*tmp) { + if (*tmp == '-') + *tmp = '_'; + tmp++; + } + + if (!strncmp(path, "__ENV__", 7)) { + const char *var = getenv(path + 7); + if (!var) { + fprintf(stderr, + "environment variable \"%s\" is empty\n", path + 7); + exit(1); + } + path = var; + } + + if (!strncmp(path, "pkcs11:", 7)) { + ret = rsa_engine_init(&e); + if (ret) + exit(1); + ret = rsa_engine_get_pub_key(path, e, &rsa); + if (ret) + exit(1); + } else { + ret = rsa_pem_get_pub_key(path, &rsa); + if (ret) + exit(1); + } + + ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared); + if (ret) + return ret; + + bits = BN_num_bits(modulus); + + printf("\nstatic uint32_t %s_modulus[] = {", key_name_c); + print_bignum(modulus, bits); + printf("\n};\n\n"); + + printf("static uint32_t %s_rr[] = {", key_name_c); + print_bignum(r_squared, bits); + printf("\n};\n\n"); + + printf("static struct rsa_public_key %s = {\n", key_name_c); + printf("\t.len = %d,\n", bits / 32); + printf("\t.n0inv = 0x%0x,\n", n0_inv); + printf("\t.modulus = %s_modulus,\n", key_name_c); + printf("\t.rr = %s_rr,\n", key_name_c); + printf("\t.exponent = 0x%0lx,\n", exponent); + printf("\t.key_name_hint = \"%s\",\n", keyname); + printf("};\n\n"); + + printf("struct rsa_public_key *%sp __attribute__((section(\".rsa_keys.rodata.%s\"))) = &%s;\n", + key_name_c, key_name_c, key_name_c); + + return 0; +} + +int main(int argc, char *argv[]) +{ + char *path, *keyname; + int i; + + if (argc < 2) { + fprintf(stderr, "Usage: %s <key_name_hint>:<crt> ...\n", argv[0]); + exit(1); + } + + for (i = 1; i < argc; i++) { + keyname = argv[i]; + + path = strchr(keyname, ':'); + if (!path) { + fprintf(stderr, + "keys must be given as <key_name_hint>:<crt>\n"); + exit(1); + } + + *path = 0; + path++; + + gen_key(keyname, path); + } + + exit(0); +} -- 2.23.0 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/5] scripts: Add rsatoc tool 2019-10-15 7:55 ` [PATCH 2/5] scripts: Add rsatoc tool Sascha Hauer @ 2019-10-15 10:21 ` Ahmad Fatoum 2019-10-15 13:15 ` Sascha Hauer 0 siblings, 1 reply; 9+ messages in thread From: Ahmad Fatoum @ 2019-10-15 10:21 UTC (permalink / raw) To: barebox, Sascha Hauer Hello Sascha, On 10/15/19 9:55 AM, Sascha Hauer wrote: > The rsatoc tool converts rsa public keys into C structs suitable to > compile with barebox. Most of the openssl rsa related stuff has been > taken from the U-Boot mkimage tool. I don't have any FIT image or RSA options enabled, yet my build fails now with: RSAKEY crypto/rsa-keys.h /bin/sh: 1: ./scripts/rsatoc: not found ./crypto/Makefile:27: recipe for target 'crypto/rsa-keys.h' failed make[2]: *** [crypto/rsa-keys.h] Error 127 ./Makefile:802: recipe for target 'crypto' failed make[1]: *** [crypto] Error 2 Cheers Ahmad > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > scripts/.gitignore | 1 + > scripts/Makefile | 3 + > scripts/rsatoc.c | 445 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 449 insertions(+) > create mode 100644 scripts/rsatoc.c > > diff --git a/scripts/.gitignore b/scripts/.gitignore > index 45c81bf8f4..76ea271abb 100644 > --- a/scripts/.gitignore > +++ b/scripts/.gitignore > @@ -29,3 +29,4 @@ mxs-usb-loader > omap4_usbboot > omap3-usb-loader > mips-relocs > +rsatoc > diff --git a/scripts/Makefile b/scripts/Makefile > index dffab53c73..81d1a501b0 100644 > --- a/scripts/Makefile > +++ b/scripts/Makefile > @@ -10,6 +10,9 @@ hostprogs-y += fix_size > hostprogs-y += bareboxenv > hostprogs-y += bareboxcrc32 > hostprogs-y += kernel-install > +hostprogs-$(CONFIG_CRYPTO_RSA_BUILTIN_KEYS) += rsatoc > +HOSTCFLAGS_rsatoc = `pkg-config --cflags openssl` > +HOSTLDLIBS_rsatoc = `pkg-config --libs openssl` > hostprogs-$(CONFIG_IMD) += bareboximd > hostprogs-$(CONFIG_KALLSYMS) += kallsyms > hostprogs-$(CONFIG_MIPS) += mips-relocs > diff --git a/scripts/rsatoc.c b/scripts/rsatoc.c > new file mode 100644 > index 0000000000..f853691908 > --- /dev/null > +++ b/scripts/rsatoc.c > @@ -0,0 +1,445 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * rsatoc - utility to convert an RSA key to a C struct > + * > + * This tool converts an RSA key given as file or PKCS#11 > + * URI to a C struct suitable to compile with barebox. > + */ > +#include <stdio.h> > +#include <string.h> > +#include <time.h> > +#include <openssl/bn.h> > +#include <openssl/rsa.h> > +#include <openssl/pem.h> > +#include <openssl/err.h> > +#include <openssl/ssl.h> > +#include <openssl/evp.h> > +#include <openssl/engine.h> > + > +static int rsa_err(const char *msg) > +{ > + unsigned long sslErr = ERR_get_error(); > + > + fprintf(stderr, "%s", msg); > + fprintf(stderr, ": %s\n", > + ERR_error_string(sslErr, 0)); > + > + return -1; > +} > + > +/** > + * rsa_pem_get_pub_key() - read a public key from a .crt file > + * > + * @keydir: Directory containins the key > + * @name Name of key file (will have a .crt extension) > + * @rsap Returns RSA object, or NULL on failure > + * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL) > + */ > +static int rsa_pem_get_pub_key(const char *path, RSA **rsap) > +{ > + EVP_PKEY *key; > + X509 *cert; > + RSA *rsa; > + FILE *f; > + int ret; > + > + *rsap = NULL; > + f = fopen(path, "r"); > + if (!f) { > + fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n", > + path, strerror(errno)); > + return -EACCES; > + } > + > + /* Read the certificate */ > + cert = NULL; > + if (!PEM_read_X509(f, &cert, NULL, NULL)) { > + rsa_err("Couldn't read certificate"); > + ret = -EINVAL; > + goto err_cert; > + } > + > + /* Get the public key from the certificate. */ > + key = X509_get_pubkey(cert); > + if (!key) { > + rsa_err("Couldn't read public key\n"); > + ret = -EINVAL; > + goto err_pubkey; > + } > + > + /* Convert to a RSA_style key. */ > + rsa = EVP_PKEY_get1_RSA(key); > + if (!rsa) { > + rsa_err("Couldn't convert to a RSA style key"); > + ret = -EINVAL; > + goto err_rsa; > + } > + fclose(f); > + EVP_PKEY_free(key); > + X509_free(cert); > + *rsap = rsa; > + > + return 0; > + > +err_rsa: > + EVP_PKEY_free(key); > +err_pubkey: > + X509_free(cert); > +err_cert: > + fclose(f); > + return ret; > +} > + > +/** > + * rsa_engine_get_pub_key() - read a public key from given engine > + * > + * @keydir: Key prefix > + * @name Name of key > + * @engine Engine to use > + * @rsap Returns RSA object, or NULL on failure > + * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL) > + */ > +static int rsa_engine_get_pub_key(const char *key_id, > + ENGINE *engine, RSA **rsap) > +{ > + EVP_PKEY *key; > + RSA *rsa; > + int ret; > + > + *rsap = NULL; > + > + key = ENGINE_load_public_key(engine, key_id, NULL, NULL); > + if (!key) > + return rsa_err("Failure loading public key from engine"); > + > + /* Convert to a RSA_style key. */ > + rsa = EVP_PKEY_get1_RSA(key); > + if (!rsa) { > + rsa_err("Couldn't convert to a RSA style key"); > + ret = -EINVAL; > + goto err_rsa; > + } > + > + EVP_PKEY_free(key); > + *rsap = rsa; > + > + return 0; > + > +err_rsa: > + EVP_PKEY_free(key); > + return ret; > +} > + > +/* > + * rsa_get_exponent(): - Get the public exponent from an RSA key > + */ > +static int rsa_get_exponent(RSA *key, uint64_t *e) > +{ > + int ret; > + BIGNUM *bn_te; > + const BIGNUM *key_e; > + uint64_t te; > + > + ret = -EINVAL; > + bn_te = NULL; > + > + if (!e) > + goto cleanup; > + > + RSA_get0_key(key, NULL, &key_e, NULL); > + if (BN_num_bits(key_e) > 64) > + goto cleanup; > + > + *e = BN_get_word(key_e); > + > + if (BN_num_bits(key_e) < 33) { > + ret = 0; > + goto cleanup; > + } > + > + bn_te = BN_dup(key_e); > + if (!bn_te) > + goto cleanup; > + > + if (!BN_rshift(bn_te, bn_te, 32)) > + goto cleanup; > + > + if (!BN_mask_bits(bn_te, 32)) > + goto cleanup; > + > + te = BN_get_word(bn_te); > + te <<= 32; > + *e |= te; > + ret = 0; > + > +cleanup: > + if (bn_te) > + BN_free(bn_te); > + > + return ret; > +} > + > +/* > + * rsa_get_params(): - Get the important parameters of an RSA public key > + */ > +int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp, > + BIGNUM **modulusp, BIGNUM **r_squaredp) > +{ > + BIGNUM *big1, *big2, *big32, *big2_32; > + BIGNUM *n, *r, *r_squared, *tmp; > + const BIGNUM *key_n; > + BN_CTX *bn_ctx = BN_CTX_new(); > + int ret = 0; > + > + /* Initialize BIGNUMs */ > + big1 = BN_new(); > + big2 = BN_new(); > + big32 = BN_new(); > + r = BN_new(); > + r_squared = BN_new(); > + tmp = BN_new(); > + big2_32 = BN_new(); > + n = BN_new(); > + if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 || > + !n) { > + fprintf(stderr, "Out of memory (bignum)\n"); > + return -ENOMEM; > + } > + > + if (0 != rsa_get_exponent(key, exponent)) > + ret = -1; > + > + RSA_get0_key(key, &key_n, NULL, NULL); > + if (!BN_copy(n, key_n) || !BN_set_word(big1, 1L) || > + !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L)) > + ret = -1; > + > + /* big2_32 = 2^32 */ > + if (!BN_exp(big2_32, big2, big32, bn_ctx)) > + ret = -1; > + > + /* Calculate n0_inv = -1 / n[0] mod 2^32 */ > + if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) || > + !BN_sub(tmp, big2_32, tmp)) > + ret = -1; > + *n0_invp = BN_get_word(tmp); > + > + /* Calculate R = 2^(# of key bits) */ > + if (!BN_set_word(tmp, BN_num_bits(n)) || > + !BN_exp(r, big2, tmp, bn_ctx)) > + ret = -1; > + > + /* Calculate r_squared = R^2 mod n */ > + if (!BN_copy(r_squared, r) || > + !BN_mul(tmp, r_squared, r, bn_ctx) || > + !BN_mod(r_squared, tmp, n, bn_ctx)) > + ret = -1; > + > + *modulusp = n; > + *r_squaredp = r_squared; > + > + BN_free(big1); > + BN_free(big2); > + BN_free(big32); > + BN_free(r); > + BN_free(tmp); > + BN_free(big2_32); > + if (ret) { > + fprintf(stderr, "Bignum operations failed\n"); > + return -ENOMEM; > + } > + > + return ret; > +} > + > +static int rsa_engine_init(ENGINE **pe) > +{ > + ENGINE *e; > + int ret; > + > + ENGINE_load_builtin_engines(); > + > + e = ENGINE_by_id("pkcs11"); > + if (!e) { > + fprintf(stderr, "Engine isn't available\n"); > + ret = -1; > + goto err_engine_by_id; > + } > + > + if (!ENGINE_init(e)) { > + fprintf(stderr, "Couldn't initialize engine\n"); > + ret = -1; > + goto err_engine_init; > + } > + > + if (!ENGINE_set_default_RSA(e)) { > + fprintf(stderr, "Couldn't set engine as default for RSA\n"); > + ret = -1; > + goto err_set_rsa; > + } > + > + *pe = e; > + > + return 0; > + > +err_set_rsa: > + ENGINE_finish(e); > +err_engine_init: > + ENGINE_free(e); > +err_engine_by_id: > +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ > + (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) > + ENGINE_cleanup(); > +#endif > + return ret; > +} > + > +static int print_bignum(BIGNUM *num, int num_bits) > +{ > + BIGNUM *tmp, *big2, *big32, *big2_32; > + BN_CTX *ctx; > + int i; > + > + tmp = BN_new(); > + big2 = BN_new(); > + big32 = BN_new(); > + big2_32 = BN_new(); > + > + /* > + * Note: This code assumes that all of the above succeed, or all fail. > + * In practice memory allocations generally do not fail (unless the > + * process is killed), so it does not seem worth handling each of these > + * as a separate case. Technicaly this could leak memory on failure, > + * but a) it won't happen in practice, and b) it doesn't matter as we > + * will immediately exit with a failure code. > + */ > + if (!tmp || !big2 || !big32 || !big2_32) { > + fprintf(stderr, "Out of memory (bignum)\n"); > + return -ENOMEM; > + } > + ctx = BN_CTX_new(); > + if (!tmp) { > + fprintf(stderr, "Out of memory (bignum context)\n"); > + return -ENOMEM; > + } > + BN_set_word(big2, 2L); > + BN_set_word(big32, 32L); > + BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */ > + > + for (i = 0; i < num_bits / 32; i++) { > + BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */ > + if (i % 4) > + printf(" "); > + else > + printf("\n\t"); > + printf("0x%08lx,", BN_get_word(tmp)); > + BN_rshift(num, num, 32); /* N = N/B */ > + } > + > + BN_free(tmp); > + BN_free(big2); > + BN_free(big32); > + BN_free(big2_32); > + > + return 0; > +} > + > +static int gen_key(const char *keyname, const char *path) > +{ > + BIGNUM *modulus, *r_squared; > + uint64_t exponent; > + uint32_t n0_inv; > + int ret; > + int bits; > + RSA *rsa; > + ENGINE *e = NULL; > + char *tmp, *key_name_c; > + > + tmp = key_name_c = strdup(keyname); > + > + while (*tmp) { > + if (*tmp == '-') > + *tmp = '_'; > + tmp++; > + } > + > + if (!strncmp(path, "__ENV__", 7)) { > + const char *var = getenv(path + 7); > + if (!var) { > + fprintf(stderr, > + "environment variable \"%s\" is empty\n", path + 7); > + exit(1); > + } > + path = var; > + } > + > + if (!strncmp(path, "pkcs11:", 7)) { > + ret = rsa_engine_init(&e); > + if (ret) > + exit(1); > + ret = rsa_engine_get_pub_key(path, e, &rsa); > + if (ret) > + exit(1); > + } else { > + ret = rsa_pem_get_pub_key(path, &rsa); > + if (ret) > + exit(1); > + } > + > + ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared); > + if (ret) > + return ret; > + > + bits = BN_num_bits(modulus); > + > + printf("\nstatic uint32_t %s_modulus[] = {", key_name_c); > + print_bignum(modulus, bits); > + printf("\n};\n\n"); > + > + printf("static uint32_t %s_rr[] = {", key_name_c); > + print_bignum(r_squared, bits); > + printf("\n};\n\n"); > + > + printf("static struct rsa_public_key %s = {\n", key_name_c); > + printf("\t.len = %d,\n", bits / 32); > + printf("\t.n0inv = 0x%0x,\n", n0_inv); > + printf("\t.modulus = %s_modulus,\n", key_name_c); > + printf("\t.rr = %s_rr,\n", key_name_c); > + printf("\t.exponent = 0x%0lx,\n", exponent); > + printf("\t.key_name_hint = \"%s\",\n", keyname); > + printf("};\n\n"); > + > + printf("struct rsa_public_key *%sp __attribute__((section(\".rsa_keys.rodata.%s\"))) = &%s;\n", > + key_name_c, key_name_c, key_name_c); > + > + return 0; > +} > + > +int main(int argc, char *argv[]) > +{ > + char *path, *keyname; > + int i; > + > + if (argc < 2) { > + fprintf(stderr, "Usage: %s <key_name_hint>:<crt> ...\n", argv[0]); > + exit(1); > + } > + > + for (i = 1; i < argc; i++) { > + keyname = argv[i]; > + > + path = strchr(keyname, ':'); > + if (!path) { > + fprintf(stderr, > + "keys must be given as <key_name_hint>:<crt>\n"); > + exit(1); > + } > + > + *path = 0; > + path++; > + > + gen_key(keyname, path); > + } > + > + exit(0); > +} > -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/5] scripts: Add rsatoc tool 2019-10-15 10:21 ` Ahmad Fatoum @ 2019-10-15 13:15 ` Sascha Hauer 2019-10-15 13:19 ` Ahmad Fatoum 0 siblings, 1 reply; 9+ messages in thread From: Sascha Hauer @ 2019-10-15 13:15 UTC (permalink / raw) To: Ahmad Fatoum; +Cc: barebox On Tue, Oct 15, 2019 at 12:21:31PM +0200, Ahmad Fatoum wrote: > Hello Sascha, > > On 10/15/19 9:55 AM, Sascha Hauer wrote: > > The rsatoc tool converts rsa public keys into C structs suitable to > > compile with barebox. Most of the openssl rsa related stuff has been > > taken from the U-Boot mkimage tool. > > I don't have any FIT image or RSA options enabled, yet my build fails now with: > > RSAKEY crypto/rsa-keys.h > /bin/sh: 1: ./scripts/rsatoc: not found > ./crypto/Makefile:27: recipe for target 'crypto/rsa-keys.h' failed > make[2]: *** [crypto/rsa-keys.h] Error 127 > ./Makefile:802: recipe for target 'crypto' failed > make[1]: *** [crypto] Error 2 Try again. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/5] scripts: Add rsatoc tool 2019-10-15 13:15 ` Sascha Hauer @ 2019-10-15 13:19 ` Ahmad Fatoum 0 siblings, 0 replies; 9+ messages in thread From: Ahmad Fatoum @ 2019-10-15 13:19 UTC (permalink / raw) To: Sascha Hauer; +Cc: barebox On 10/15/19 3:15 PM, Sascha Hauer wrote: > On Tue, Oct 15, 2019 at 12:21:31PM +0200, Ahmad Fatoum wrote: >> Hello Sascha, >> >> On 10/15/19 9:55 AM, Sascha Hauer wrote: >>> The rsatoc tool converts rsa public keys into C structs suitable to >>> compile with barebox. Most of the openssl rsa related stuff has been >>> taken from the U-Boot mkimage tool. >> >> I don't have any FIT image or RSA options enabled, yet my build fails now with: >> >> RSAKEY crypto/rsa-keys.h >> /bin/sh: 1: ./scripts/rsatoc: not found >> ./crypto/Makefile:27: recipe for target 'crypto/rsa-keys.h' failed >> make[2]: *** [crypto/rsa-keys.h] Error 127 >> ./Makefile:802: recipe for target 'crypto' failed >> make[1]: *** [crypto] Error 2 > > Try again. Works, thanks. > > Sascha > -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/5] rsa: let rsa_of_read_key() return a fully allocated key 2019-10-15 7:55 [PATCH 0/5] Allow to compile in rsa public keys directly Sascha Hauer 2019-10-15 7:55 ` [PATCH 1/5] Kbuild: Add config_filename macro from kernel Sascha Hauer 2019-10-15 7:55 ` [PATCH 2/5] scripts: Add rsatoc tool Sascha Hauer @ 2019-10-15 7:55 ` Sascha Hauer 2019-10-15 7:55 ` [PATCH 4/5] rsa: Allow to directly compile in rsa public keys Sascha Hauer 2019-10-15 7:55 ` [PATCH 5/5] fit-image: Use compiled-in keys Sascha Hauer 4 siblings, 0 replies; 9+ messages in thread From: Sascha Hauer @ 2019-10-15 7:55 UTC (permalink / raw) To: Barebox List Until now rsa_of_read_key() took a pointer to a key and filled the struct rsa_public_key members with allocated values. So far we have never freed these values. Change rsa_of_read_key() to always return a fully allocated key and provide rsa_key_free() to free it. Let the FIT image code free the key after usage. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- common/image-fit.c | 10 ++++++---- crypto/rsa.c | 26 ++++++++++++++++++++++---- include/rsa.h | 3 ++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/common/image-fit.c b/common/image-fit.c index 6ac4644686..71053fbef5 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -269,7 +269,7 @@ static struct digest *fit_alloc_digest(struct device_node *sig_node, static int fit_check_rsa_signature(struct device_node *sig_node, enum hash_algo algo, void *hash) { - struct rsa_public_key key = {}; + struct rsa_public_key *key; const char *key_name; char *key_path; struct device_node *key_node; @@ -296,18 +296,20 @@ static int fit_check_rsa_signature(struct device_node *sig_node, } free(key_path); - ret = rsa_of_read_key(key_node, &key); - if (ret) { + key = rsa_of_read_key(key_node); + if (IS_ERR(key)) { pr_info("failed to read key in %s\n", key_node->full_name); return -ENOENT; } - ret = rsa_verify(&key, sig_value, sig_len, hash, algo); + ret = rsa_verify(key, sig_value, sig_len, hash, algo); if (ret) pr_err("image signature BAD\n"); else pr_info("image signature OK\n"); + rsa_key_free(key); + return ret; } diff --git a/crypto/rsa.c b/crypto/rsa.c index 591d15c415..2e70c8127d 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -380,11 +380,15 @@ static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len) dst[i] = fdt32_to_cpu(src[len - 1 - i]); } -int rsa_of_read_key(struct device_node *node, struct rsa_public_key *key) +struct rsa_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; + int err; + + key = xzalloc(sizeof(*key)); of_property_read_u32(node, "rsa,num-bits", &key->len); of_property_read_u32(node, "rsa,n0-inverse", &key->n0inv); @@ -400,14 +404,16 @@ int rsa_of_read_key(struct device_node *node, struct rsa_public_key *key) if (!key->len || !modulus || !rr) { debug("%s: Missing RSA key info", __func__); - return -EFAULT; + err = -EFAULT; + goto out; } /* Sanity check for stack size */ if (key->len > RSA_MAX_KEY_BITS || key->len < RSA_MIN_KEY_BITS) { debug("RSA key bits %u outside allowed range %d..%d\n", key->len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS); - return -EFAULT; + err = -EFAULT; + goto out; } key->len /= sizeof(uint32_t) * 8; @@ -418,5 +424,17 @@ int rsa_of_read_key(struct device_node *node, struct rsa_public_key *key) rsa_convert_big_endian(key->modulus, modulus, key->len); rsa_convert_big_endian(key->rr, rr, key->len); - return 0; + err = 0; +out: + if (err) + free(key); + + return err ? ERR_PTR(err) : key; +} + +void rsa_key_free(struct rsa_public_key *key) +{ + free(key->modulus); + free(key->rr); + free(key); } diff --git a/include/rsa.h b/include/rsa.h index feb8c31200..cf2e6c7e08 100644 --- a/include/rsa.h +++ b/include/rsa.h @@ -49,6 +49,7 @@ int rsa_verify(const struct rsa_public_key *key, const uint8_t *sig, /* This is the maximum signature length that we support, in bits */ #define RSA_MAX_SIG_BITS 4096 -int rsa_of_read_key(struct device_node *node, struct rsa_public_key *key); +struct rsa_public_key *rsa_of_read_key(struct device_node *node); +void rsa_key_free(struct rsa_public_key *key); #endif -- 2.23.0 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/5] rsa: Allow to directly compile in rsa public keys 2019-10-15 7:55 [PATCH 0/5] Allow to compile in rsa public keys directly Sascha Hauer ` (2 preceding siblings ...) 2019-10-15 7:55 ` [PATCH 3/5] rsa: let rsa_of_read_key() return a fully allocated key Sascha Hauer @ 2019-10-15 7:55 ` Sascha Hauer 2019-10-15 7:55 ` [PATCH 5/5] fit-image: Use compiled-in keys Sascha Hauer 4 siblings, 0 replies; 9+ messages in thread From: Sascha Hauer @ 2019-10-15 7:55 UTC (permalink / raw) To: Barebox List So far we relied on the U-Boot mkimage tool to generate us device tree snippets containing rsa public keys which we then compiled into barebox. Make this easier and allow to directly specify a filename or PKCS#11 URI in Kconfig. With this we no longer need the U-Boot mkimage tool here and no more external steps to prepare device tree snippets. With this rsa public keys can be directly compiled as C structs into barebox which is much more direct than putting it into the device tree. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- crypto/.gitignore | 2 ++ crypto/Kconfig | 19 ++++++++++++++++++ crypto/Makefile | 10 ++++++++++ crypto/rsa.c | 33 +++++++++++++++++++++++++++++++ include/asm-generic/barebox.lds.h | 6 ++++++ include/rsa.h | 2 ++ scripts/Makefile.lib | 18 +++++++++++++++++ 7 files changed, 90 insertions(+) create mode 100644 crypto/.gitignore diff --git a/crypto/.gitignore b/crypto/.gitignore new file mode 100644 index 0000000000..92d8af3cf4 --- /dev/null +++ b/crypto/.gitignore @@ -0,0 +1,2 @@ +rsa-keys.h +rsa-keys.h.tmp diff --git a/crypto/Kconfig b/crypto/Kconfig index c06d3c054e..42b018b296 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -94,6 +94,25 @@ config CRYPTO_PBKDF2 config CRYPTO_RSA bool +config CRYPTO_RSA_BUILTIN_KEYS + bool + default y if CRYPTO_RSA_KEYS != "" + +config CRYPTO_RSA_KEY + depends on CRYPTO_RSA + string "RSA key to compile in" + help + This option should be a filename of a PEM-formatted file containing + X.509 certificates to be included into barebox. If the string starts + with "pkcs11:" it is interpreted as a PKCS#11 URI rather than a file. + +config CRYPTO_RSA_KEY_NAME_HINT + depends on CRYPTO_RSA + string "FIT image key name hint" + help + In FIT images keys are identified by a key name hint string. Provide + the key name hint here. + config CRYPTO_KEYSTORE bool "Keystore" help diff --git a/crypto/Makefile b/crypto/Makefile index d6fb74aad9..018f85e253 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -16,3 +16,13 @@ obj-$(CONFIG_DIGEST_SHA512_GENERIC) += sha4.o obj-$(CONFIG_CRYPTO_PBKDF2) += pbkdf2.o obj-$(CONFIG_CRYPTO_RSA) += rsa.o obj-$(CONFIG_CRYPTO_KEYSTORE) += keystore.o + +extra-y += rsa-keys.h + +ifdef CONFIG_CRYPTO_RSA_BUILTIN_KEYS + +$(obj)/rsa.o: $(obj)/rsa-keys.h +$(eval $(call config_filename,CRYPTO_RSA_KEY)) +$(obj)/rsa-keys.h: FORCE + $(call cmd,rsa_keys,$(CONFIG_CRYPTO_RSA_KEY_NAME_HINT):$(CRYPTO_RSA_KEY_SRCPREFIX)$(CRYPTO_RSA_KEY_FILENAME)) +endif diff --git a/crypto/rsa.c b/crypto/rsa.c index 2e70c8127d..64241854c8 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -438,3 +438,36 @@ void rsa_key_free(struct rsa_public_key *key) free(key->rr); free(key); } + +#ifdef CONFIG_CRYPTO_RSA_BUILTIN_KEYS +#include "rsa-keys.h" + +extern const struct rsa_public_key * const __rsa_keys_start; +extern const struct rsa_public_key * const __rsa_keys_end; + +struct rsa_public_key *rsa_get_key(const char *name) +{ + const struct rsa_public_key *key; + struct rsa_public_key *new; + const struct rsa_public_key * const *iter; + + for (iter = &__rsa_keys_start; iter != &__rsa_keys_end; iter++) { + key = *iter; + if (!strcmp(name, key->key_name_hint)) + goto found; + } + + return ERR_PTR(-ENOENT); +found: + new = xmemdup(key, sizeof(*key)); + new->modulus = xmemdup(key->modulus, key->len * sizeof(uint32_t)); + new->rr = xmemdup(key->rr, key->len * sizeof(uint32_t)); + + return new; +} +#else +struct rsa_public_key *rsa_get_key(const char *name) +{ + return ERR_PTR(-ENOENT); +} +#endif diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h index 8e8ae183db..b6ca8eb2be 100644 --- a/include/asm-generic/barebox.lds.h +++ b/include/asm-generic/barebox.lds.h @@ -98,6 +98,11 @@ #define BAREBOX_PCI_FIXUP #endif +#define BAREBOX_RSA_KEYS \ + __rsa_keys_start = .; \ + KEEP(*(.rsa_keys.rodata.*)); \ + __rsa_keys_end = .; \ + #define RO_DATA_SECTION \ BAREBOX_INITCALLS \ BAREBOX_EXITCALLS \ @@ -107,6 +112,7 @@ BAREBOX_MAGICVARS \ BAREBOX_CLK_TABLE \ BAREBOX_DTB \ + BAREBOX_RSA_KEYS \ BAREBOX_PCI_FIXUP #if defined(CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE) && \ diff --git a/include/rsa.h b/include/rsa.h index cf2e6c7e08..803660d19a 100644 --- a/include/rsa.h +++ b/include/rsa.h @@ -28,6 +28,7 @@ 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; }; /** @@ -51,5 +52,6 @@ int rsa_verify(const struct rsa_public_key *key, const uint8_t *sig, struct rsa_public_key *rsa_of_read_key(struct device_node *node); void rsa_key_free(struct rsa_public_key *key); +struct rsa_public_key *rsa_get_key(const char *name); #endif diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index c4d307ae30..ecaf5e1e7b 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -526,5 +526,23 @@ quiet_cmd_stm32_image = STM32-IMG $@ quiet_cmd_b64dec = B64DEC $@ cmd_b64dec = base64 -d $< > $@ +# rsa_keys +# --------------------------------------------------------------------------- +# Build a header file containing a rsa public key. +# +# The keys can change without the build system noticing, so we always +# have to call rsatoc. To avoid unnecessary rebuilds of barebox compare +# its output to the last rsatoc output. Only if it differs overwrite the +# target file. +quiet_cmd_rsa_keys = RSAKEY $@ +cmd_rsa_keys = \ + $(srctree)/scripts/rsatoc $2 \ + > $@.tmp && \ + if cmp -s $@.tmp $@; then \ + rm $@.tmp; \ + else \ + mv $@.tmp $@; \ + fi + %: %.base64 $(call cmd,b64dec) -- 2.23.0 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/5] fit-image: Use compiled-in keys 2019-10-15 7:55 [PATCH 0/5] Allow to compile in rsa public keys directly Sascha Hauer ` (3 preceding siblings ...) 2019-10-15 7:55 ` [PATCH 4/5] rsa: Allow to directly compile in rsa public keys Sascha Hauer @ 2019-10-15 7:55 ` Sascha Hauer 4 siblings, 0 replies; 9+ messages in thread From: Sascha Hauer @ 2019-10-15 7:55 UTC (permalink / raw) To: Barebox List The compiled-in keys can be retrieved with rsa_get_key(). Try to use them first before falling back to looking up the keys in the device tree. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- common/image-fit.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/common/image-fit.c b/common/image-fit.c index 71053fbef5..ca4d9ca10c 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -287,16 +287,21 @@ static int fit_check_rsa_signature(struct device_node *sig_node, pr_err("key name not found in %s\n", sig_node->full_name); return -EINVAL; } - key_path = xasprintf("/signature/key-%s", key_name); - key_node = of_find_node_by_path(key_path); - if (!key_node) { - pr_info("failed to find key node %s\n", key_path); + + key = rsa_get_key(key_name); + if (IS_ERR(key)) { + key_path = xasprintf("/signature/key-%s", key_name); + key_node = of_find_node_by_path(key_path); + if (!key_node) { + pr_info("failed to find key node %s\n", key_path); + free(key_path); + return -ENOENT; + } free(key_path); - return -ENOENT; + + key = rsa_of_read_key(key_node); } - free(key_path); - key = rsa_of_read_key(key_node); if (IS_ERR(key)) { pr_info("failed to read key in %s\n", key_node->full_name); return -ENOENT; -- 2.23.0 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2019-10-15 13:20 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-10-15 7:55 [PATCH 0/5] Allow to compile in rsa public keys directly Sascha Hauer 2019-10-15 7:55 ` [PATCH 1/5] Kbuild: Add config_filename macro from kernel Sascha Hauer 2019-10-15 7:55 ` [PATCH 2/5] scripts: Add rsatoc tool Sascha Hauer 2019-10-15 10:21 ` Ahmad Fatoum 2019-10-15 13:15 ` Sascha Hauer 2019-10-15 13:19 ` Ahmad Fatoum 2019-10-15 7:55 ` [PATCH 3/5] rsa: let rsa_of_read_key() return a fully allocated key Sascha Hauer 2019-10-15 7:55 ` [PATCH 4/5] rsa: Allow to directly compile in rsa public keys Sascha Hauer 2019-10-15 7:55 ` [PATCH 5/5] fit-image: Use compiled-in keys Sascha Hauer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox