Commit cedff47f38 for openssl.org
commit cedff47f3895f17979988f4b5e93d0482ae5931c
Author: Jakub Zelenka <jakub.zelenka@openssl.foundation>
Date: Tue Jun 30 00:29:23 2026 +0200
test: build the fake cipher provider as a loadable module
The fake cipher provider was only available in-process, linked into test
binaries via fake_cipher_start(). To exercise app success paths (e.g.
skeyutl -genkey) the openssl app needs to load it as a provider module the
same way it loads legacy.
Make test/fake_cipherprov.c dual-buildable: drop the testutil dependency so
the source links cleanly into a module, add an OSSL_provider_init entry point
under FAKE_CIPHER_AS_MODULE, and add a fake-cipher MODULES target in
test/build.info. Also implement skeymgmt generate so opaque key generation
works, and cover the skeyutl -genkey success path in 20-test_skeyutl.t.
Assisted-by: Claude:claude-opus-4-8
Reviewed-by: Matt Caswell <matt@openssl.foundation>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
MergeDate: Mon Jul 13 14:58:53 2026
(Merged from https://github.com/openssl/openssl/pull/31781)
diff --git a/test/build.info b/test/build.info
index 86174be7c5..94e6d08865 100644
--- a/test/build.info
+++ b/test/build.info
@@ -1265,6 +1265,16 @@ IF[{- !$disabled{tests} -}]
SOURCE[p_minimal]=p_minimal.ld
GENERATE[p_minimal.ld]=../util/providers.num
ENDIF
+ # Loadable form of the fake cipher provider.
+ MODULES{noinst}=fake-cipher
+ SOURCE[fake-cipher]=fake_cipherprov.c
+ DEFINE[fake-cipher]=FAKE_CIPHER_AS_MODULE
+ INCLUDE[fake-cipher]=../include
+ DEPEND[fake-cipher]=../libcrypto
+ IF[{- defined $target{shared_defflag} -}]
+ SOURCE[fake-cipher]=fake-cipher.ld
+ GENERATE[fake-cipher.ld]=../util/providers.num
+ ENDIF
ENDIF
IF[{- $disabled{module} || !$target{dso_scheme} -}]
DEFINE[provider_test]=NO_PROVIDER_MODULE
diff --git a/test/fake_cipherprov.c b/test/fake_cipherprov.c
index 16fde61221..ad28a6b94b 100644
--- a/test/fake_cipherprov.c
+++ b/test/fake_cipherprov.c
@@ -9,13 +9,13 @@
*/
#include <string.h>
+#include <openssl/err.h>
#include <openssl/core_names.h>
#include <openssl/core_object.h>
#include <openssl/rand.h>
#include <openssl/provider.h>
#include <openssl/proverr.h>
#include <openssl/param_build.h>
-#include "testutil.h"
#include "fake_cipherprov.h"
#define MAX_KEYNAME 32
@@ -65,7 +65,7 @@ static void *fake_skeymgmt_import(void *provctx, int selection, const OSSL_PARAM
{
PROV_CIPHER_FAKE_CTX *ctx = NULL;
- if (!TEST_ptr(ctx = OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX))))
+ if ((ctx = OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX))) == NULL)
return 0;
if (ctx_from_key_params(ctx, p) != 1) {
@@ -76,6 +76,26 @@ static void *fake_skeymgmt_import(void *provctx, int selection, const OSSL_PARAM
return ctx;
}
+static void *fake_skeymgmt_generate(void *provctx, const OSSL_PARAM *params)
+{
+ PROV_CIPHER_FAKE_CTX *ctx = NULL;
+ size_t i;
+
+ if ((ctx = OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX))) == NULL)
+ return NULL;
+
+ if (ctx_from_key_params(ctx, params) != 1) {
+ OPENSSL_free(ctx);
+ return NULL;
+ }
+
+ /* Deterministic fill so the provider doesn't depend on a DRBG. */
+ for (i = 0; i < sizeof(ctx->key); i++)
+ ctx->key[i] = (unsigned char)i;
+
+ return ctx;
+}
+
static int fake_skeymgmt_export(void *keydata, int selection,
OSSL_CALLBACK *param_callback, void *cbarg)
{
@@ -103,6 +123,7 @@ static int fake_skeymgmt_export(void *keydata, int selection,
static const OSSL_DISPATCH fake_skeymgmt_funcs[] = {
{ OSSL_FUNC_SKEYMGMT_FREE, (void (*)(void))fake_skeymgmt_free },
+ { OSSL_FUNC_SKEYMGMT_GENERATE, (void (*)(void))fake_skeymgmt_generate },
{ OSSL_FUNC_SKEYMGMT_IMPORT, (void (*)(void))fake_skeymgmt_import },
{ OSSL_FUNC_SKEYMGMT_EXPORT, (void (*)(void))fake_skeymgmt_export },
OSSL_DISPATCH_END
@@ -308,19 +329,29 @@ static int fake_cipher_provider_init(const OSSL_CORE_HANDLE *handle,
const OSSL_DISPATCH *in,
const OSSL_DISPATCH **out, void **provctx)
{
- if (!TEST_ptr(*provctx = OSSL_LIB_CTX_new()))
+ if ((*provctx = OSSL_LIB_CTX_new()) == NULL)
return 0;
*out = fake_cipher_method;
return 1;
}
+#ifdef FAKE_CIPHER_AS_MODULE
+/* Entry point when built as a loadable module (e.g. -provider fake-cipher). */
+int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out, void **provctx)
+{
+ return fake_cipher_provider_init(handle, in, out, provctx);
+}
+#endif
+
OSSL_PROVIDER *fake_cipher_start(OSSL_LIB_CTX *libctx)
{
OSSL_PROVIDER *p;
- if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, FAKE_PROV_NAME,
- fake_cipher_provider_init))
- || !TEST_ptr(p = OSSL_PROVIDER_try_load(libctx, FAKE_PROV_NAME, 1)))
+ if (!OSSL_PROVIDER_add_builtin(libctx, FAKE_PROV_NAME,
+ fake_cipher_provider_init)
+ || (p = OSSL_PROVIDER_try_load(libctx, FAKE_PROV_NAME, 1)) == NULL)
return NULL;
return p;
diff --git a/test/recipes/20-test_skeyutl.t b/test/recipes/20-test_skeyutl.t
index e173ba1d13..1c69935cac 100644
--- a/test/recipes/20-test_skeyutl.t
+++ b/test/recipes/20-test_skeyutl.t
@@ -9,12 +9,16 @@
use strict;
use warnings;
-use OpenSSL::Test qw/:DEFAULT with/;
+use OpenSSL::Test qw/:DEFAULT bldtop_dir with/;
use OpenSSL::Test::Utils;
setup("test_skeyutl");
-plan tests => 14;
+# The success path needs the loadable fake-cipher provider, which is only built
+# when module support is enabled.
+my $fake_cipher = !disabled('module');
+
+plan tests => 14 + ($fake_cipher ? 2 : 0);
# Helper: run skeyutl expecting a non-zero (failure) exit code, and optionally
# check that stderr matches a regular expression.
@@ -78,3 +82,18 @@ skeyutl_fails("skeyutl with an unknown cipher fails",
skeyutl_fails("skeyutl with an unknown option fails",
qr/Unknown option/,
'-not-an-option');
+
+# Success path: load the fake-cipher provider, which implements opaque key
+# generation, and generate a key with it.
+if ($fake_cipher) {
+ $ENV{OPENSSL_MODULES} = bldtop_dir("test");
+ my @prov = ('-provider-path', bldtop_dir("test"), '-provider', 'fake-cipher');
+
+ my $status;
+ my @out = run(app(['openssl', 'skeyutl', @prov,
+ '-genkey', '-skeymgmt', 'fake_cipher']),
+ capture => 1, statusvar => \$status);
+ ok($status, "skeyutl -genkey with fake-cipher provider succeeds");
+ ok(grep(/opaque key/, @out),
+ "skeyutl -genkey reports the generated opaque key");
+}