OpenSSL 4.0 removed the ENGINE API entirely. u-boot-tools uses
ENGINE_get_id, ENGINE_load_public_key, ENGINE_finish, ENGINE_free
in lib/rsa/rsa-sign.c which causes link failures.

Backport the Provider API support patch from upstream u-boot which
adds OpenSSL Provider support while maintaining backward compatibility
with older OpenSSL versions that still have ENGINE.

Upstream-Status: Backport [https://github.com/u-boot/u-boot/pull/918]
Signed-off-by: Jaipaul Cheernam <[email protected]>
---
 ...Add-support-for-OpenSSL-Provider-API.patch | 300 ++++++++++++++++++
 .../u-boot/u-boot-tools_2026.07.bb            |   4 +-
 2 files changed, 303 insertions(+), 1 deletion(-)
 create mode 100644 
meta/recipes-bsp/u-boot/files/0001-Add-support-for-OpenSSL-Provider-API.patch

diff --git 
a/meta/recipes-bsp/u-boot/files/0001-Add-support-for-OpenSSL-Provider-API.patch 
b/meta/recipes-bsp/u-boot/files/0001-Add-support-for-OpenSSL-Provider-API.patch
new file mode 100644
index 0000000000..2136afe2f4
--- /dev/null
+++ 
b/meta/recipes-bsp/u-boot/files/0001-Add-support-for-OpenSSL-Provider-API.patch
@@ -0,0 +1,300 @@
+From a81cb0932dce109af44d7245d47489fe54ae390f Mon Sep 17 00:00:00 2001
+From: Eddie Kovsky <[email protected]>
+Date: Mon, 23 Feb 2026 09:43:22 -0700
+Subject: [PATCH] Add support for OpenSSL Provider API
+
+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.
+
+Add support for the Provider API while continuing to support 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.
+
+Signed-off-by: Eddie Kovsky <[email protected]>
+
+Upstream-Status: Backport [https://github.com/u-boot/u-boot/pull/918]
+Signed-off-by: Jaipaul Cheernam <[email protected]>
+---
+ lib/aes/aes-encrypt.c |   4 +-
+ lib/rsa/rsa-sign.c    | 102 +++++++++++++++++++++++++++++++++++++++---
+ 2 files changed, 100 insertions(+), 6 deletions(-)
+
+diff --git a/lib/aes/aes-encrypt.c b/lib/aes/aes-encrypt.c
+index 90e1407b4f09..4fc4ce232478 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>
+-#include <openssl/engine.h>
++#if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0)
++# include <openssl/engine.h>
++#endif
+ #include <uboot_aes.h>
+ 
+ #if OPENSSL_VERSION_NUMBER >= 0x10000000L
+diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
+index 0e38c9e802fd..f456f3c58e65 100644
+--- a/lib/rsa/rsa-sign.c
++++ b/lib/rsa/rsa-sign.c
+@@ -19,7 +19,47 @@
+ #include <openssl/err.h>
+ #include <openssl/ssl.h>
+ #include <openssl/evp.h>
+-#include <openssl/engine.h>
++#if OPENSSL_VERSION_MAJOR >= 3
++# define USE_PKCS11_PROVIDER
++# include <err.h>
++# include <openssl/provider.h>
++# include <openssl/store.h>
++#else
++# if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0)
++#  define USE_PKCS11_ENGINE
++#  include <openssl/engine.h>
++# endif
++#endif
++
++#ifdef USE_PKCS11_PROVIDER
++#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
+ 
+ static int rsa_err(const char *msg)
+ {
+@@ -94,10 +134,11 @@ static int rsa_pem_get_pub_key(const char *keydir, const 
char *name, EVP_PKEY **
+  *
+  * @keydir:   Key prefix
+  * @name      Name of key
+- * @engine    Engine to use
++ * @engine    Engine to use or NULL when using pkcs11 provider
+  * @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)
+  */
++#ifdef USE_PKCS11_ENGINE
+ static int rsa_engine_get_pub_key(const char *keydir, const char *name,
+                                 ENGINE *engine, EVP_PKEY **evpp)
+ {
+@@ -157,21 +198,24 @@ static int rsa_engine_get_pub_key(const char *keydir, 
const char *name,
+ 
+       return 0;
+ }
++#endif
+ 
+ /**
+  * rsa_get_pub_key() - read a public key
+  *
+  * @keydir:   Directory containing the key (PEM file) or key prefix (engine)
+  * @name      Name of key file (will have a .crt extension)
+- * @engine    Engine to use
++ * @engine    Engine to use or NULL when using pkcs11 provider
+  * @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)
+  */
+ static int rsa_get_pub_key(const char *keydir, const char *name,
+                          ENGINE *engine, EVP_PKEY **evpp)
+ {
++#ifdef USE_PKCS11_ENGINE
+       if (engine)
+               return rsa_engine_get_pub_key(keydir, name, engine, evpp);
++#endif
+       return rsa_pem_get_pub_key(keydir, name, evpp);
+ }
+ 
+@@ -207,13 +251,44 @@ static int rsa_pem_get_priv_key(const char *keydir, 
const char *name,
+               return -ENOENT;
+       }
+ 
++#ifdef USE_PKCS11_PROVIDER
++      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);
+               return -EPROTO;
+       }
+       fclose(f);
+-
++#endif
+       return 0;
+ }
+ 
+@@ -226,6 +301,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)
+  */
++#ifdef USE_PKCS11_ENGINE
+ static int rsa_engine_get_priv_key(const char *keydir, const char *name,
+                                  const char *keyfile,
+                                  ENGINE *engine, EVP_PKEY **evpp)
+@@ -293,22 +369,25 @@ static int rsa_engine_get_priv_key(const char *keydir, 
const char *name,
+ 
+       return 0;
+ }
++#endif
+ 
+ /**
+  * rsa_get_priv_key() - read a private key
+  *
+  * @keydir:   Directory containing the key (PEM file) or key prefix (engine)
+  * @name      Name of key
+- * @engine    Engine to use for signing
++ * @engine    Engine to use or NULL when using pkcs11 provider
+  * @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)
+  */
+ static int rsa_get_priv_key(const char *keydir, const char *name,
+                           const char *keyfile, ENGINE *engine, EVP_PKEY 
**evpp)
+ {
++#ifdef USE_PKCS11_ENGINE
+       if (engine)
+               return rsa_engine_get_priv_key(keydir, name, keyfile, engine,
+                                              evpp);
++#endif
+       return rsa_pem_get_priv_key(keydir, name, keyfile, evpp);
+ }
+ 
+@@ -325,6 +404,7 @@ static int rsa_init(void)
+       return 0;
+ }
+ 
++#ifdef USE_PKCS11_ENGINE
+ static int rsa_engine_init(const char *engine_id, ENGINE **pe)
+ {
+       const char *key_pass;
+@@ -380,6 +460,7 @@ static void rsa_engine_remove(ENGINE *e)
+               ENGINE_free(e);
+       }
+ }
++#endif
+ 
+ static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo 
*padding_algo,
+                            struct checksum_algo *checksum_algo,
+@@ -480,11 +561,13 @@ int rsa_sign(struct image_sign_info *info,
+       if (ret)
+               return ret;
+ 
++#ifdef USE_PKCS11_ENGINE
+       if (info->engine_id) {
+               ret = rsa_engine_init(info->engine_id, &e);
+               if (ret)
+                       return ret;
+       }
++#endif
+ 
+       ret = rsa_get_priv_key(info->keydir, info->keyname, info->keyfile,
+                              e, &pkey);
+@@ -496,16 +579,21 @@ int rsa_sign(struct image_sign_info *info,
+               goto err_sign;
+ 
+       EVP_PKEY_free(pkey);
++
++#ifdef USE_PKCS11_ENGINE
+       if (info->engine_id)
+               rsa_engine_remove(e);
++#endif
+ 
+       return ret;
+ 
+ err_sign:
+       EVP_PKEY_free(pkey);
+ err_priv:
++#ifdef USE_PKCS11_ENGINE
+       if (info->engine_id)
+               rsa_engine_remove(e);
++#endif
+       return ret;
+ }
+ 
+@@ -645,11 +733,13 @@ int rsa_add_verify_data(struct image_sign_info *info, 
void *keydest)
+       ENGINE *e = NULL;
+ 
+       debug("%s: Getting verification data\n", __func__);
++#ifdef USE_PKCS11_ENGINE
+       if (info->engine_id) {
+               ret = rsa_engine_init(info->engine_id, &e);
+               if (ret)
+                       return ret;
+       }
++#endif
+       ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey);
+       if (ret)
+               goto err_get_pub_key;
+@@ -726,8 +816,10 @@ int rsa_add_verify_data(struct image_sign_info *info, 
void *keydest)
+ err_get_params:
+       EVP_PKEY_free(pkey);
+ err_get_pub_key:
++#ifdef USE_PKCS11_ENGINE
+       if (info->engine_id)
+               rsa_engine_remove(e);
++#endif
+ 
+       if (ret)
+               return ret;
diff --git a/meta/recipes-bsp/u-boot/u-boot-tools_2026.07.bb 
b/meta/recipes-bsp/u-boot/u-boot-tools_2026.07.bb
index 9e7a178310..17c4b1e128 100644
--- a/meta/recipes-bsp/u-boot/u-boot-tools_2026.07.bb
+++ b/meta/recipes-bsp/u-boot/u-boot-tools_2026.07.bb
@@ -1,4 +1,6 @@
 require u-boot-common.inc
 require u-boot-tools.inc
 
-SRC_URI += "file://0001-tools-mkeficapsule-Detect-GnuTLS-PKCS-11-support.patch"
+SRC_URI += "file://0001-tools-mkeficapsule-Detect-GnuTLS-PKCS-11-support.patch 
\
+            file://0001-Add-support-for-OpenSSL-Provider-API.patch \
+           "
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#243402): 
https://lists.openembedded.org/g/openembedded-core/message/243402
Mute This Topic: https://lists.openembedded.org/mt/120745102/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to