diff --git a/meta-oe/recipes-support/imx-cst/imx-cst/0017-cst-port-pkcs11-signing-from-engine-to-provider.patch b/meta-oe/recipes-support/imx-cst/imx-cst/0017-cst-port-pkcs11-signing-from-engine-to-provider.patch new file mode 100644 index 0000000000..699402a447 --- /dev/null +++ b/meta-oe/recipes-support/imx-cst/imx-cst/0017-cst-port-pkcs11-signing-from-engine-to-provider.patch @@ -0,0 +1,236 @@ +From: Johannes Schneider +Subject: cst: port pkcs11 signing from the OpenSSL ENGINE to a provider + +OpenSSL 4.0 removed the ENGINE API, so CST's pkcs11-backed signing stops +working: ENGINE_by_id("pkcs11") returns NULL and engine_ctx_init() fails. + +Reimplement the pkcs11 certificate and key loading on OSSL_STORE and the +pkcs11 provider. engine_ctx_init() loads the default and pkcs11 providers -- +default explicitly, because activating any provider stops OpenSSL +auto-loading default, which would drop the EVP digest and signature algorithms +the signer needs. ENGINE_load_certificate()/ENGINE_load_key() open the pkcs11 +URI through OSSL_STORE and return the X509 / EVP_PKEY, feeding the existing CMS +and EVP signing unchanged. The public entry points keep their names and +signatures; the ENGINE * argument is now vestigial. The PIN travels in the URI +(pin-value=). + +Upstream-Status: Pending +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Johannes Schneider +--- +Builds on the engine-stub change already in this recipe's series +(0015-fix-openssl-4-engine-api-removal), which only makes the file compile and +noted that pkcs11-backed signing was still unavailable on OpenSSL 4; this +restores it. +--- a/src/lib/back_end/engine.c ++++ b/src/lib/back_end/engine.c +@@ -7,8 +7,9 @@ + /* + * OpenSSL 4.0 removed the ENGINE API. still declares + * it for source compatibility, and defining OPENSSL_ENGINE_STUBS turns the +- * declarations into inline no-ops so this file keeps linking. The pkcs11 +- * engine simply does not exist there, which engine_ctx_init() reports. ++ * declarations into inline no-ops so this file keeps linking. Signing no ++ * longer uses an engine (see engine_ctx_init); the vestigial ENGINE * only ++ * keeps the public entry points' signatures unchanged. + */ + #define OPENSSL_ENGINE_STUBS + +@@ -19,6 +20,8 @@ + #include + #include + #include ++#include ++#include + #include + + #if CST_WITH_PKCS11 +@@ -31,6 +34,76 @@ + } + #endif + ++/* Load default and pkcs11 once; "default" explicitly, or activating pkcs11 stops OpenSSL auto-loading it and the signer loses its EVP algorithms. */ ++static int load_providers(void) ++{ ++ static int loaded; ++ ++ if (loaded) ++ return 1; ++ ++ if (!OSSL_PROVIDER_load(NULL, "default")) { ++ fprintf(stderr, "ERROR: cannot load the default OpenSSL provider\n"); ++ return 0; ++ } ++ if (!OSSL_PROVIDER_load(NULL, "pkcs11")) { ++ fprintf(stderr, "ERROR: cannot load the pkcs11 OpenSSL provider; " ++ "is pkcs11-provider installed and OPENSSL_MODULES set?\n"); ++ return 0; ++ } ++ ++ loaded = 1; ++ return 1; ++} ++ ++/* Load a certificate and/or key from a PKCS#11 (or any OSSL_STORE) URI; returns 1 only if every requested object was found. */ ++static int store_load(const char *uri, X509 **cert_out, EVP_PKEY **key_out) ++{ ++ OSSL_STORE_CTX *store = NULL; ++ int ok = 0; ++ ++ if (!uri) ++ return 0; ++ ++ store = OSSL_STORE_open(uri, NULL, NULL, NULL, NULL); ++ if (!store) { ++ fprintf(stderr, "ERROR: cannot open PKCS#11 store for %s\n", uri); ++ return 0; ++ } ++ ++ while (!OSSL_STORE_eof(store)) { ++ OSSL_STORE_INFO *info = OSSL_STORE_load(store); ++ ++ if (!info) { ++ /* NULL means EOF or a non-fatal error; break on the error flag, or a bad object spins forever (eof stays 0). */ ++ if (OSSL_STORE_error(store)) ++ break; ++ continue; ++ } ++ ++ switch (OSSL_STORE_INFO_get_type(info)) { ++ case OSSL_STORE_INFO_CERT: ++ if (cert_out && !*cert_out) ++ *cert_out = OSSL_STORE_INFO_get1_CERT(info); ++ break; ++ case OSSL_STORE_INFO_PKEY: ++ if (key_out && !*key_out) ++ *key_out = OSSL_STORE_INFO_get1_PKEY(info); ++ break; ++ default: ++ break; ++ } ++ OSSL_STORE_INFO_free(info); ++ ++ if ((!cert_out || *cert_out) && (!key_out || *key_out)) ++ break; ++ } ++ ++ OSSL_STORE_close(store); ++ ok = (!cert_out || *cert_out) && (!key_out || *key_out); ++ return ok; ++} ++ + struct engine_ctx *engine_ctx_new(void) + { + struct engine_ctx *ctx = NULL; +@@ -41,16 +114,13 @@ + + int32_t engine_ctx_destroy(struct engine_ctx *ctx) + { +- if (ctx) { +- ENGINE_free(ctx->engine); ++ if (ctx) + OPENSSL_free(ctx); +- } + return 1; + } + + int32_t engine_ctx_init(struct engine_ctx *ctx) + { +- dynamic_fns fns; + /* OpenSSL Initialization */ + #if OPENSSL_VERSION_NUMBER >= 0x10100000 + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | +@@ -66,60 +136,46 @@ + + ERR_clear_error(); + +- ENGINE_load_builtin_engines(); +- +- ctx->engine = ENGINE_by_id("pkcs11"); +- +- if (!ctx->engine) { +- fprintf(stderr, "ERROR: cannot load the pkcs11 OpenSSL engine\n"); +-#if OPENSSL_VERSION_MAJOR >= 4 +- fprintf(stderr, +- "ERROR: OpenSSL 4.0 removed ENGINE support, so PKCS#11 " +- "backed signing is unavailable\n"); +-#endif ++ if (!load_providers()) + return 0; +- } + +-#ifdef DEBUG +- ENGINE_ctrl_cmd_string(ctx->engine, "VERBOSE", NULL, 0); +-#endif +- +- if (!ENGINE_init(ctx->engine)) { +- ENGINE_free(ctx->engine); +- return 0; +- } ++ ctx->engine = NULL; + + return 1; + } + + int32_t engine_ctx_finish(struct engine_ctx *ctx) + { +- if (ctx) +- ENGINE_finish(ctx->engine); ++ (void)ctx; + return 1; + } + + X509 *ENGINE_load_certificate(ENGINE *e, const char *cert_ref) + { +- struct { +- const char *s_slot_cert_id; +- X509 *cert; +- } params = {0}; ++ X509 *cert = NULL; + +- params.s_slot_cert_id = cert_ref; +- params.cert = NULL; ++ (void)e; + +- if (!ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, ¶ms, NULL, 1)) { ++ if (!store_load(cert_ref, &cert, NULL)) { + ERR_print_errors_fp(stderr); + return NULL; + } + +- return params.cert; ++ return cert; + } + + EVP_PKEY *ENGINE_load_key(ENGINE *e, const char *key_ref) + { +- return ENGINE_load_private_key(e, key_ref, 0, 0); ++ EVP_PKEY *key = NULL; ++ ++ (void)e; ++ ++ if (!store_load(key_ref, NULL, &key)) { ++ ERR_print_errors_fp(stderr); ++ return NULL; ++ } ++ ++ return key; + } + + X509 *engine_read_certificate(const char *cert_ref) +@@ -161,14 +217,8 @@ + #endif + + out: +- if (ctx) { +- /* +- * Destroy the context: ctx_finish is not called here since +- * ENGINE_finish cleanups the engine instance. Calling ctx_destroy +- * next will lead to null pointer dereference. +- */ ++ if (ctx) + engine_ctx_destroy(ctx); +- } + + if (error) + ERR_print_errors_fp(stderr); diff --git a/meta-oe/recipes-support/imx-cst/imx-cst_4.0.1.bb b/meta-oe/recipes-support/imx-cst/imx-cst_4.0.1.bb index ec6838e95d..3a0f717440 100644 --- a/meta-oe/recipes-support/imx-cst/imx-cst_4.0.1.bb +++ b/meta-oe/recipes-support/imx-cst/imx-cst_4.0.1.bb @@ -29,6 +29,7 @@ SRC_URI = "\ file://0014-fix-pointer-sign-errors-with-clang.patch \ file://0015-fix-openssl-4-engine-api-removal.patch \ file://0016-fix-openssl-4-const-subject-name.patch \ + file://0017-cst-port-pkcs11-signing-from-engine-to-provider.patch \ " SRC_URI[sha256sum] = "fd92a1a9faa10fb81bbf752c7ee1e257f17e1ec4c2964f8a47adf8a3eaa7df41"