From 78ec287ad4d0ecc7f937d878998d22d6ea0256ec Mon Sep 17 00:00:00 2001 From: David Seifert Date: Sun, 25 Oct 2026 11:24:32 +0100 Subject: [PATCH] sbsign, sbvarsign: replace ENGINE key loading with OpenSSL providers The ENGINE API is deprecated since OpenSSL 3.0 and removed in OpenSSL 4, so sbsigntools no longer builds against it. Replace fileio_read_engine_key() with fileio_read_provider_key(), which loads the "default" provider plus the requested one and reads the private key through OSSL_STORE, prompting for a pass phrase via the existing UI method. The --engine/-e option of sbsign and sbvarsign becomes --provider/-p. The key argument is now an OSSL_STORE URI, e.g. sbsign --provider pkcs11 --key 'pkcs11:token=foo;object=bar' ... Signed-off-by: David Seifert --- src/fileio.c | 52 ++++++++++++++++++++++++++++++++++--------------- src/fileio.h | 2 +- src/sbsign.c | 18 ++++++++--------- src/sbvarsign.c | 18 ++++++++--------- 4 files changed, 55 insertions(+), 35 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 032eb1e..35fbbb3 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -39,7 +39,9 @@ #include #include #include -#include +#include +#include +#include #include #include @@ -55,22 +57,23 @@ static int ui_read(UI *ui, UI_STRING *uis) if (UI_get_string_type(uis) != UIT_PROMPT) return 0; - EVP_read_pw_string(password, sizeof(password), "Enter engine key pass phrase:", 0); + EVP_read_pw_string(password, sizeof(password), "Enter key pass phrase:", 0); UI_set_result(ui, uis, password); return 1; } -EVP_PKEY *fileio_read_engine_key(const char *engine, const char *filename) +EVP_PKEY *fileio_read_provider_key(const char *provider, const char *uri) { - UI_METHOD *ui; - ENGINE *e; + UI_METHOD *ui = NULL; + OSSL_STORE_CTX *store = NULL; + OSSL_STORE_INFO *info; EVP_PKEY *pkey = NULL; - ENGINE_load_builtin_engines(); - e = ENGINE_by_id(engine); - - if (!e) { - fprintf(stderr, "Failed to load engine: %s\n", engine); + /* explicitly loading any provider disables the implicit default + * provider, which we still need for digests and PKCS#7 */ + if (!OSSL_PROVIDER_load(NULL, "default") || + !OSSL_PROVIDER_load(NULL, provider)) { + fprintf(stderr, "Failed to load provider: %s\n", provider); ERR_print_errors_fp(stderr); return NULL; } @@ -79,21 +82,38 @@ EVP_PKEY *fileio_read_engine_key(const char *engine, const char *filename) if (!ui) { fprintf(stderr, "Failed to create UI method\n"); ERR_print_errors_fp(stderr); - goto out_free; + return NULL; } UI_method_set_reader(ui, ui_read); - if (!ENGINE_init(e)) { - fprintf(stderr, "Failed to initialize engine %s\n", engine); + store = OSSL_STORE_open(uri, ui, NULL, NULL, NULL); + if (!store) { + fprintf(stderr, "Failed to open key store: %s\n", uri); ERR_print_errors_fp(stderr); goto out_free; } + OSSL_STORE_expect(store, OSSL_STORE_INFO_PKEY); + + while (!pkey && !OSSL_STORE_eof(store)) { + info = OSSL_STORE_load(store); + if (!info) { + if (OSSL_STORE_error(store)) + break; + continue; + } + if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) + pkey = OSSL_STORE_INFO_get1_PKEY(info); + OSSL_STORE_INFO_free(info); + } - pkey = ENGINE_load_private_key(e, filename, ui, NULL); - ENGINE_finish(e); + if (!pkey) { + fprintf(stderr, "Can't load key from '%s'\n", uri); + ERR_print_errors_fp(stderr); + } out_free: - ENGINE_free(e); + OSSL_STORE_close(store); + UI_destroy_method(ui); return pkey; } diff --git a/src/fileio.h b/src/fileio.h index b3ed22c..2688d50 100644 --- a/src/fileio.h +++ b/src/fileio.h @@ -38,7 +38,7 @@ #include EVP_PKEY *fileio_read_pkey(const char *filename); -EVP_PKEY *fileio_read_engine_key(const char *engine, const char *filename); +EVP_PKEY *fileio_read_provider_key(const char *provider, const char *uri); X509 *fileio_read_cert(const char *filename); int fileio_read_file(void *ctx, const char *filename, diff --git a/src/sbsign.c b/src/sbsign.c index 898fe66..dad58f1 100644 --- a/src/sbsign.c +++ b/src/sbsign.c @@ -76,7 +76,7 @@ static struct option options[] = { { "verbose", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, - { "engine", required_argument, NULL, 'e'}, + { "provider", required_argument, NULL, 'p'}, { "addcert", required_argument, NULL, 'a'}, { NULL, 0, NULL, 0 }, }; @@ -87,7 +87,7 @@ static void usage(void) "\n" "Sign an EFI boot image for use with secure boot.\n\n" "Options:\n" - "\t--engine use the specified engine to load the key\n" + "\t--provider use the specified provider to load the key\n" "\t--key signing key (PEM-encoded RSA " "private key)\n" "\t--cert certificate (x509 certificate)\n" @@ -152,7 +152,7 @@ static int add_intermediate_certs(PKCS7 *p7, const char *filename) int main(int argc, char **argv) { - const char *keyfilename, *certfilename, *addcertfilename, *engine; + const char *keyfilename, *certfilename, *addcertfilename, *provider; struct sign_context *ctx; uint8_t *buf, *tmp; int rc, c, sigsize; @@ -163,11 +163,11 @@ int main(int argc, char **argv) keyfilename = NULL; certfilename = NULL; addcertfilename = NULL; - engine = NULL; + provider = NULL; for (;;) { int idx; - c = getopt_long(argc, argv, "o:c:k:dvVhe:a:", options, &idx); + c = getopt_long(argc, argv, "o:c:k:dvVhp:a:", options, &idx); if (c == -1) break; @@ -193,8 +193,8 @@ int main(int argc, char **argv) case 'h': usage(); return EXIT_SUCCESS; - case 'e': - engine = optarg; + case 'p': + provider = optarg; break; case 'a': addcertfilename = optarg; @@ -244,8 +244,8 @@ int main(int argc, char **argv) * module isn't present). In either case ignore the errors * (malloc will cause other failures out lower down */ ERR_clear_error(); - if (engine) - pkey = fileio_read_engine_key(engine, keyfilename); + if (provider) + pkey = fileio_read_provider_key(provider, keyfilename); else pkey = fileio_read_pkey(keyfilename); if (!pkey) diff --git a/src/sbvarsign.c b/src/sbvarsign.c index 58031ec..9f2db11 100644 --- a/src/sbvarsign.c +++ b/src/sbvarsign.c @@ -397,7 +397,7 @@ static struct option options[] = { { "verbose", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, - { "engine", required_argument, NULL, 'e'}, + { "provider", required_argument, NULL, 'p'}, { NULL, 0, NULL, 0 }, }; @@ -409,7 +409,7 @@ void usage(void) " \n" "Sign a blob of data for use in SetVariable().\n\n" "Options:\n" - "\t--engine use the specified engine to load the key\n" + "\t--provider use the specified provider to load the key\n" "\t--key signing key (PEM-encoded RSA " "private key)\n" "\t--cert certificate (x509 certificate)\n" @@ -438,7 +438,7 @@ static void version(void) int main(int argc, char **argv) { - const char *guid_str, *attr_str, *varname, *engine; + const char *guid_str, *attr_str, *varname, *provider; const char *keyfilename, *certfilename; struct varsign_context *ctx; bool include_attrs; @@ -448,14 +448,14 @@ int main(int argc, char **argv) keyfilename = NULL; certfilename = NULL; - engine = NULL; + provider = NULL; guid_str = NULL; attr_str= NULL; include_attrs = false; for (;;) { int idx; - c = getopt_long(argc, argv, "o:g:a:k:c:ivVhe:", options, &idx); + c = getopt_long(argc, argv, "o:g:a:k:c:ivVhp:", options, &idx); if (c == -1) break; @@ -487,8 +487,8 @@ int main(int argc, char **argv) case 'h': usage(); return EXIT_SUCCESS; - case 'e': - engine = optarg; + case 'p': + provider = optarg; break; } } @@ -551,8 +551,8 @@ int main(int argc, char **argv) if (fileio_read_file(ctx, ctx->infilename, &ctx->data, &ctx->data_len)) return EXIT_FAILURE; - if (engine) - ctx->key = fileio_read_engine_key(engine, keyfilename); + if (provider) + ctx->key = fileio_read_provider_key(provider, keyfilename); else ctx->key = fileio_read_pkey(keyfilename); if (!ctx->key)