> From: Eddie Kovsky <[email protected]> > Date: Fri, 17 Oct 2025 11:13:27 -0600 > > The Engine API has been deprecated since the release of OpenSSL > 3.0. End users have been advised to migrate to the new Provider > interface. Several distributions have already removed support for > engines, which is preventing U-Boot from being compiled in those > environments. > > The Kconfig option OPENSSL_NO_DEPRECATED introduces support for the > Provider API while continuing to use the existing Engine API on > distros shipping older releases of OpenSSL. > > This is based on similar work contributed by Jan Stancek > updating Linux to use the Provider interface. > > commit 558bdc45dfb2669e1741384a0c80be9c82fa052c > Author: Jan Stancek <[email protected]> > Date: Fri Sep 20 19:52:48 2024 +0300 > > sign-file,extract-cert: use pkcs11 provider for OPENSSL MAJOR >= 3 > > The changes have been tested with the FIT signature verification > vboot tests on Fedora 42 and Debian 13. All 30 tests pass with both > the legacy Engine library installed and with the Provider API.
Did you test this with LibreSSL? > Signed-off-by: Eddie Kovsky <[email protected]> > --- > lib/aes/aes-encrypt.c | 2 + > lib/rsa/Kconfig | 8 ++++ > lib/rsa/rsa-sign.c | 93 ++++++++++++++++++++++++++++++++++++++++++- > 3 files changed, 101 insertions(+), 2 deletions(-) > > diff --git a/lib/aes/aes-encrypt.c b/lib/aes/aes-encrypt.c > index 90e1407b4f09..9595772cf58b 100644 > --- a/lib/aes/aes-encrypt.c > +++ b/lib/aes/aes-encrypt.c > @@ -16,7 +16,9 @@ > #include <openssl/err.h> > #include <openssl/ssl.h> > #include <openssl/evp.h> > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > #include <openssl/engine.h> > +#endif > #include <uboot_aes.h> > > #if OPENSSL_VERSION_NUMBER >= 0x10000000L > diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig > index 9033384e60a3..622f06f8dba0 100644 > --- a/lib/rsa/Kconfig > +++ b/lib/rsa/Kconfig > @@ -20,6 +20,14 @@ config SPL_RSA > bool "Use RSA Library within SPL" > depends on SPL > > +config OPENSSL_NO_DEPRECATED > + bool "Build U-Boot without support for OpenSSL Engine" > + default n > + help > + Add support for the OpenSSL Provider API, which is the officially > + supported mechanism in OpenSSL 3.x and later releases for accessing > + hardware and software cryptography. > + > config SPL_RSA_VERIFY > bool > depends on SPL_RSA > diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c > index 92b9d7876e52..9ebbcdfd52f3 100644 > --- a/lib/rsa/rsa-sign.c > +++ b/lib/rsa/rsa-sign.c > @@ -19,15 +19,51 @@ > #include <openssl/err.h> > #include <openssl/ssl.h> > #include <openssl/evp.h> > +#if (IS_ENABLED(CONFIG_OPENSSL_NO_DEPRECATED)) > +#include <err.h> > +#include <openssl/provider.h> > +#include <openssl/store.h> > +#else > #include <openssl/engine.h> > +#endif // CONFIG_OPENSSL_NO_DEPRECATED > + > +#if (IS_ENABLED(CONFIG_OPENSSL_NO_DEPRECATED)) > +#define ERR(cond, fmt, ...) \ > + do { \ > + bool __cond = (cond); \ > + drain_openssl_errors(__LINE__, 0); \ > + if (__cond) { \ > + errx(1, fmt, ## __VA_ARGS__); \ > + } \ > + } while (0) > + > +static void drain_openssl_errors(int l, int silent) > +{ > + const char *file; > + char buf[120]; > + int e, line; > + > + if (ERR_peek_error() == 0) > + return; > + if (!silent) > + fprintf(stderr, "At main.c:%d:\n", l); > + > + while ((e = ERR_peek_error_line(&file, &line))) { > + ERR_error_string(e, buf); > + if (!silent) > + fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line); > + ERR_get_error(); > + } > +} > +#endif // CONFIG_OPENSSL_NO_DEPRECATED > > static int rsa_err(const char *msg) > { > - unsigned long sslErr = ERR_get_error(); > + unsigned long ssl_err = ERR_get_error(); > > fprintf(stderr, "%s", msg); > fprintf(stderr, ": %s\n", > - ERR_error_string(sslErr, 0)); > + ERR_error_string(ssl_err, 0)); > > return -1; > } > @@ -98,6 +134,7 @@ err_cert: > * @evpp Returns EVP_PKEY object, or NULL on failure > * Return: 0 if ok, -ve on error (in which case *evpp will be set to NULL) > */ > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > static int rsa_engine_get_pub_key(const char *keydir, const char *name, > ENGINE *engine, EVP_PKEY **evpp) > { > @@ -157,6 +194,7 @@ static int rsa_engine_get_pub_key(const char *keydir, > const char *name, > > return 0; > } > +#endif // !CONFIG_OPENSSL_NO_DEPRECATED > > /** > * rsa_get_pub_key() - read a public key > @@ -170,8 +208,10 @@ static int rsa_engine_get_pub_key(const char *keydir, > const char *name, > static int rsa_get_pub_key(const char *keydir, const char *name, > ENGINE *engine, EVP_PKEY **evpp) > { > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > if (engine) > return rsa_engine_get_pub_key(keydir, name, engine, evpp); > +#endif // !CONFIG_OPENSSL_NO_DEPRECATED > return rsa_pem_get_pub_key(keydir, name, evpp); > } > > @@ -207,6 +247,37 @@ static int rsa_pem_get_priv_key(const char *keydir, > const char *name, > return -ENOENT; > } > > +#if (IS_ENABLED(CONFIG_OPENSSL_NO_DEPRECATED)) > + EVP_PKEY *private_key = NULL; > + OSSL_STORE_CTX *store; > + > + if (!OSSL_PROVIDER_try_load(NULL, "pkcs11", true)) > + ERR(1, "OSSL_PROVIDER_try_load(pkcs11)"); > + if (!OSSL_PROVIDER_try_load(NULL, "default", true)) > + ERR(1, "OSSL_PROVIDER_try_load(default)"); > + > + store = OSSL_STORE_open(path, NULL, NULL, NULL, NULL); > + ERR(!store, "OSSL_STORE_open"); > + > + while (!OSSL_STORE_eof(store)) { > + OSSL_STORE_INFO *info = OSSL_STORE_load(store); > + > + if (!info) { > + drain_openssl_errors(__LINE__, 0); > + continue; > + } > + if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) { > + private_key = OSSL_STORE_INFO_get1_PKEY(info); > + ERR(!private_key, "OSSL_STORE_INFO_get1_PKEY"); > + } > + OSSL_STORE_INFO_free(info); > + if (private_key) > + break; > + } > + OSSL_STORE_close(store); > + > + *evpp = private_key; > +#else > if (!PEM_read_PrivateKey(f, evpp, NULL, path)) { > rsa_err("Failure reading private key"); > fclose(f); > @@ -214,6 +285,7 @@ static int rsa_pem_get_priv_key(const char *keydir, const > char *name, > } > fclose(f); > > +#endif // CONFIG_OPENSSL_NO_DEPRECATED > return 0; > } > > @@ -226,6 +298,7 @@ static int rsa_pem_get_priv_key(const char *keydir, const > char *name, > * @evpp Returns EVP_PKEY object, or NULL on failure > * Return: 0 if ok, -ve on error (in which case *evpp will be set to NULL) > */ > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > static int rsa_engine_get_priv_key(const char *keydir, const char *name, > const char *keyfile, > ENGINE *engine, EVP_PKEY **evpp) > @@ -293,6 +366,7 @@ static int rsa_engine_get_priv_key(const char *keydir, > const char *name, > > return 0; > } > +#endif // !CONFIG_OPENSSL_NO_DEPRECATED > > /** > * rsa_get_priv_key() - read a private key > @@ -306,9 +380,11 @@ static int rsa_engine_get_priv_key(const char *keydir, > const char *name, > static int rsa_get_priv_key(const char *keydir, const char *name, > const char *keyfile, ENGINE *engine, EVP_PKEY > **evpp) > { > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > if (engine) > return rsa_engine_get_priv_key(keydir, name, keyfile, engine, > evpp); > +#endif // !CONFIG_OPENSSL_NO_DEPRECATED > return rsa_pem_get_priv_key(keydir, name, keyfile, evpp); > } > > @@ -325,6 +401,7 @@ static int rsa_init(void) > return 0; > } > > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > static int rsa_engine_init(const char *engine_id, ENGINE **pe) > { > const char *key_pass; > @@ -380,6 +457,7 @@ static void rsa_engine_remove(ENGINE *e) > ENGINE_free(e); > } > } > +#endif // !CONFIG_OPENSSL_NO_DEPRECATED > > static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo > *padding_algo, > struct checksum_algo *checksum_algo, > @@ -480,11 +558,13 @@ int rsa_sign(struct image_sign_info *info, > if (ret) > return ret; > > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > if (info->engine_id) { > ret = rsa_engine_init(info->engine_id, &e); > if (ret) > return ret; > } > +#endif // !CONFIG_OPENSSL_NO_DEPRECATED > > ret = rsa_get_priv_key(info->keydir, info->keyname, info->keyfile, > e, &pkey); > @@ -496,16 +576,21 @@ int rsa_sign(struct image_sign_info *info, > goto err_sign; > > EVP_PKEY_free(pkey); > + > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > if (info->engine_id) > rsa_engine_remove(e); > +#endif // !CONFIG_OPENSSL_NO_DEPRECATED > > return ret; > > err_sign: > EVP_PKEY_free(pkey); > err_priv: > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > if (info->engine_id) > rsa_engine_remove(e); > +#endif // !CONFIG_OPENSSL_NO_DEPRECATED > return ret; > } > > @@ -645,11 +730,13 @@ int rsa_add_verify_data(struct image_sign_info *info, > void *keydest) > ENGINE *e = NULL; > > debug("%s: Getting verification data\n", __func__); > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > if (info->engine_id) { > ret = rsa_engine_init(info->engine_id, &e); > if (ret) > return ret; > } > +#endif // !CONFIG_OPENSSL_NO_DEPRECATED > ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey); > if (ret) > goto err_get_pub_key; > @@ -726,8 +813,10 @@ done: > err_get_params: > EVP_PKEY_free(pkey); > err_get_pub_key: > +#ifndef CONFIG_OPENSSL_NO_DEPRECATED > if (info->engine_id) > rsa_engine_remove(e); > +#endif // !CONFIG_OPENSSL_NO_DEPRECATED > > if (ret) > return ret; > -- > 2.51.0 > >

