[PATCH] Add support for OpenSSL Provider API

Mark Kettenis mark.kettenis at xs4all.nl
Sat Oct 18 13:22:47 CEST 2025


> From: Eddie Kovsky <ekovsky at redhat.com>
> 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 <jstancek at redhat.com>
>     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 <ekovsky at redhat.com>
> ---
>  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
> 
> 


More information about the U-Boot mailing list