Commit 032297054a for openssl.org
commit 032297054ab5ff6cac4eae87a6fa9b686b4d62e5
Author: Neil Horman <nhorman@openssl.org>
Date: Tue Aug 26 08:08:01 2025 -0400
Implement an ossltest provider to replace ossltest engine
Part of the effort to remove engines creates a problem for our test
suite, in that we have a large number of tests that rely on the use of a
test engine (ossltest), which implements the aes-128-cbc, aes-128-gcm,
aes-128-cbc-hmac-sha1 ciphers, several digests and a random number
generator to produce predictable outputs for the purposes of doing
testing against known values.
Since we're getting rid of engines, these tests need to be updated to
use a provider that presents the same functionality.
This commit implements that provider.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/28461)
diff --git a/test/build.info b/test/build.info
index 8b581763b5..4f70870515 100644
--- a/test/build.info
+++ b/test/build.info
@@ -1149,11 +1149,15 @@ IF[{- !$disabled{tests} -}]
INCLUDE[provider_test]=../include ../apps/include ..
DEPEND[provider_test]=../libcrypto libtestutil.a
IF[{- !$disabled{module} -}]
- MODULES{noinst}=p_test
+ MODULES{noinst}=p_test p_ossltest
SOURCE[p_test]=p_test.c
+ SOURCE[p_ossltest]=p_ossltest.c ../providers/prov_running.c
INCLUDE[p_test]=../include ..
+ INCLUDE[p_ossltest]=../include .. ../providers/common/include ../providers/implementations/include ../providers/implementations
+ DEPEND[p_ossltest]=../providers/libcommon.a ../libcrypto
IF[{- defined $target{shared_defflag} -}]
SOURCE[p_test]=p_test.ld
+ SOURCE[p_ossltest]=p_test.ld
GENERATE[p_test.ld]=../util/providers.num
ENDIF
MODULES{noinst}=p_minimal
diff --git a/test/p_ossltest.c b/test/p_ossltest.c
new file mode 100644
index 0000000000..19d83f94cd
--- /dev/null
+++ b/test/p_ossltest.c
@@ -0,0 +1,1822 @@
+/*
+ * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/**
+ * @file p_ossltest.c
+ * @brief a test provider for use in several of our unit tests
+ *
+ * This file implements a provider that goes through the motions of implementing
+ * various algorithms, but then discards the actual results of that work in favor
+ * of predictable return data for the purposes of having known data to compare against
+ * in our various tls tests.
+ *
+ * It implements the following algorithms
+ *
+ * The AES-128-CBC cipher
+ * The AES-128-GCM cipher
+ * The AES-128-CBC-HMAC-SHA1 cipher
+ * The MD5 digest
+ * The SHA1, SHA256, SHA384 and SHA512 digests
+ * The CTR-DRBG random number generator
+ *
+ * Note that the implementations of the above algorithms are designed not to
+ * actually follow the prescribed algorithms themselves, but rather just to
+ * returns known/predictable data values for the purposes of testing. As such
+ * DO NOT USE THIS PROVIDER FOR ANY PRODUCTION PURPOSE. TESTING ONLY!!!!
+ *
+ * The digests all return incremental data in accordance with the size of their message
+ * digest
+ *
+ * The ciphers all return data that is a copy of their input plaintext, padded and augmented
+ * according to the specific ciphers needs
+ *
+ * The random number generator just returns incremental data of the requested size
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/rand.h> /* RAND_get0_public() */
+#include <openssl/proverr.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <openssl/prov_ssl.h>
+#include "prov/provider_ctx.h"
+#include "prov/digestcommon.h"
+#include "prov/ciphercommon.h"
+#include "prov/names.h"
+#include "prov/implementations.h"
+#include "ciphers/cipher_aes.h"
+#include "internal/cryptlib.h"
+#include "internal/provider.h"
+#include "crypto/context.h"
+#include "internal/core.h"
+
+/**
+ * @brief Release resources and clean up the context.
+ *
+ * @param provctx void *provctx.
+ * @return void.
+ */
+
+static void ossltest_teardown(void *provctx)
+{
+ OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx));
+ ossl_prov_ctx_free(provctx);
+}
+
+static const OSSL_PARAM ossltest_param_types[] = {
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
+ OSSL_PARAM_END
+};
+
+/**
+ * @brief Describe parameters that can be queried.
+ *
+ * Just returns the standard provider query-able parameters
+ * OSSL_PROV_PARAM_NAME - The name of our provider
+ * OSSL_PROV_PARAM_VERSION - The version of this provider build
+ * OSSL_PROV_PARAM_BUILDINFO - The configuration it was built with
+ * OSSL_PROV_PARAM_STATUS - Weather or not its currently activated
+ *
+ * @param provctx void *provctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *ossltest_gettable_params(void *provctx)
+{
+ return ossltest_param_types;
+}
+
+/**
+ * @brief Return provider parameters.
+ *
+ * @param provctx void *provctx.
+ * @param params OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossltest_get_params(void *provctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL ossltest Provider"))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO);
+ if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_FULL_VERSION_STR))
+ return 0;
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS);
+ if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running()))
+ return 0;
+ return 1;
+}
+
+/**
+ * @brief Fill a buffer with deterministic test bytes.
+ *
+ * @param md unsigned char *md.
+ * @param len unsigned int len.
+ * @return void.
+ */
+
+static void fill_known_data(unsigned char *md, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ md[i] = (unsigned char)(i & 0xff);
+}
+
+/**
+ * @brief Initialize the context state for our digests.
+ *
+ * Because all our digests return known data in this provider
+ * this can just be a no-op function. Its used for each digest we support
+ *
+ * @param ctx void *ctx.
+ * @return int.
+ */
+
+static int ossltest_dgst_init(void *ctx)
+{
+ return 1;
+}
+
+/**
+ * @brief Process input data to update the digest state.
+ * Since this provider returns fixed data for each digest
+ * we don't actually have to do any work here, just return 1.
+ * This is used for all our provided digests
+ *
+ * @param ctx void *ctx.
+ * @param data const void *data.
+ * @param count size_t count.
+ * @return int.
+ */
+
+static int ossltest_dgst_update(void *ctx, const void *data,
+ size_t count)
+{
+ return 1;
+}
+
+/**
+ * @brief Finalize the digest output.
+ *
+ * provide pre-set data (increasing count) for the MD5 DIGEST
+ *
+ * @param md unsigned char *md.
+ * @param ctx void *ctx.
+ * @return int.
+ */
+
+static int ossltest_MD5_final(unsigned char *md, void *ctx)
+{
+ fill_known_data(md, MD5_DIGEST_LENGTH);
+ return 1;
+}
+
+/**
+ * @brief Finalize the digest output.
+ *
+ * provide pre-set data (increasing count) for the SHA1 DIGEST
+ *
+ * @param md unsigned char *md.
+ * @param ctx void *ctx.
+ * @return int.
+ */
+
+static int ossltest_SHA1_final(unsigned char *md, void *ctx)
+{
+ fill_known_data(md, SHA_DIGEST_LENGTH);
+ return 1;
+}
+
+/**
+ * @brief Finalize the digest output.
+ *
+ * provide pre-set data (increasing count) for the SHA256 DIGEST
+ *
+ * @param md unsigned char *md.
+ * @param ctx void *ctx.
+ * @return int.
+ */
+
+static int ossltest_SHA256_final(unsigned char *md, void *ctx)
+{
+ fill_known_data(md, SHA256_DIGEST_LENGTH);
+ return 1;
+}
+
+/**
+ * @brief Finalize the digest output.
+ *
+ * provide pre-set data (increasing count) for the SHA384 DIGEST
+ *
+ * @param md unsigned char *md.
+ * @param ctx void *ctx.
+ * @return int.
+ */
+
+static int ossltest_SHA384_final(unsigned char *md, void *ctx)
+{
+ fill_known_data(md, SHA384_DIGEST_LENGTH);
+ return 1;
+}
+
+/**
+ * @brief Finalize the digest output.
+ *
+ * provide pre-set data (increasing count) for the SHA512 DIGEST
+ *
+ * @param md unsigned char *md.
+ * @param ctx void *ctx.
+ * @return int.
+ */
+
+static int ossltest_SHA512_final(unsigned char *md, void *ctx)
+{
+ fill_known_data(md, SHA512_DIGEST_LENGTH);
+ return 1;
+}
+
+/*
+ * NOTE: These externs are just here to make the compiler happy
+ * The IMPLEMENT_digest_functions macros below define these arrays
+ * as non-static so that real providers can pick them up in other C files
+ * And they get externed in other header files. But we only use them internally
+ * to this provider here. To avoid having to re-implement and co-ordinate the below
+ * macros in what is already a large C file, just define them as extern to prevent some
+ * compilers from complaining about a non-static definition with no prior extern declaration
+ * mark them as such here. They won't get exported anyway as p_ossltest only gets built as
+ * a DSO, and the linker map we use doesn't list them as exported
+ */
+extern const OSSL_DISPATCH ossl_testmd5_functions[];
+extern const OSSL_DISPATCH ossl_testsha1_functions[];
+extern const OSSL_DISPATCH ossl_testsha256_functions[];
+extern const OSSL_DISPATCH ossl_testsha384_functions[];
+extern const OSSL_DISPATCH ossl_testsha512_functions[];
+
+IMPLEMENT_digest_functions(testmd5, MD5_CTX, MD5_CBLOCK, MD5_DIGEST_LENGTH, 0,
+ ossltest_dgst_init, ossltest_dgst_update, ossltest_MD5_final)
+
+#define SHA2_FLAGS PROV_DIGEST_FLAG_ALGID_ABSENT
+IMPLEMENT_digest_functions(testsha1, SHA_CTX, SHA_CBLOCK, SHA_DIGEST_LENGTH, SHA2_FLAGS,
+ ossltest_dgst_init, ossltest_dgst_update, ossltest_SHA1_final)
+
+IMPLEMENT_digest_functions(testsha256, SHA256_CTX,
+ SHA256_CBLOCK, SHA256_DIGEST_LENGTH, SHA2_FLAGS,
+ ossltest_dgst_init, ossltest_dgst_update, ossltest_SHA256_final)
+
+IMPLEMENT_digest_functions(testsha384, SHA512_CTX,
+ SHA512_CBLOCK, SHA512_DIGEST_LENGTH, SHA2_FLAGS,
+ ossltest_dgst_init, ossltest_dgst_update, ossltest_SHA384_final)
+
+IMPLEMENT_digest_functions(testsha512, SHA512_CTX,
+ SHA512_CBLOCK, SHA512_DIGEST_LENGTH, SHA2_FLAGS,
+ ossltest_dgst_init, ossltest_dgst_update, ossltest_SHA512_final)
+
+#define ALG(NAMES, FUNC) \
+ { NAMES, "provider=p_ossltest", FUNC }
+
+static const OSSL_ALGORITHM ossltest_digests[] = {
+ ALG(PROV_NAMES_MD5, ossl_testmd5_functions),
+ ALG(PROV_NAMES_SHA1, ossl_testsha1_functions),
+ ALG(PROV_NAMES_SHA2_256, ossl_testsha256_functions),
+ ALG(PROV_NAMES_SHA2_384, ossl_testsha384_functions),
+ ALG(PROV_NAMES_SHA2_512, ossl_testsha512_functions),
+ {NULL, NULL, NULL}
+};
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ EVP_CIPHER_CTX *sub_ctx;
+} PROV_EVP_AES128_CBC_CTX;
+
+/**
+ * @brief Allocate and initialize a new aes-128-cbc context.
+ *
+ * @param provctx void *provctx.
+ * @return void *.
+ */
+
+static void *ossl_testaes128_cbc_newctx(void *provctx)
+{
+ PROV_EVP_AES128_CBC_CTX *new;
+ EVP_CIPHER *cph = NULL;
+ int ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ new = OPENSSL_zalloc(sizeof(PROV_EVP_AES128_CBC_CTX));
+ if (new == NULL)
+ return NULL;
+ new->sub_ctx = EVP_CIPHER_CTX_new();
+ if (new->sub_ctx == NULL)
+ goto err;
+
+ new->libctx = PROV_LIBCTX_OF(provctx);
+
+ cph = EVP_CIPHER_fetch(new->libctx, "AES-128-CBC", "provider=default");
+ if (cph == NULL)
+ goto err;
+
+ ret = EVP_CipherInit_ex2(new->sub_ctx, cph, NULL, NULL, 1, NULL);
+
+ EVP_CIPHER_free(cph);
+
+ if (ret <= 0)
+ goto err;
+
+ return new;
+err:
+ EVP_CIPHER_CTX_free(new->sub_ctx);
+ OPENSSL_free(new);
+ return NULL;
+}
+
+/**
+ * @brief Release resources and clean up an aes-128-cbc context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @return void.
+ */
+
+static void ossl_test_aes128cbc_freectx(void *vprovctx)
+{
+ PROV_EVP_AES128_CBC_CTX *ctx = (PROV_EVP_AES128_CBC_CTX *)vprovctx;
+
+ EVP_CIPHER_CTX_free(ctx->sub_ctx);
+ OPENSSL_free(ctx);
+}
+
+/**
+ * @brief Duplicate an aes-128-cbc context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @return void *.
+ */
+
+static void *ossl_test_aes128cbc_dupctx(void *vprovctx)
+{
+ PROV_EVP_AES128_CBC_CTX *ctx = (PROV_EVP_AES128_CBC_CTX *)vprovctx;
+ PROV_EVP_AES128_CBC_CTX *dup;
+
+ dup = OPENSSL_memdup(ctx, sizeof(PROV_EVP_AES128_CBC_CTX));
+
+ if (dup != NULL) {
+ dup->sub_ctx = EVP_CIPHER_CTX_dup(ctx->sub_ctx);
+ if (dup->sub_ctx == NULL) {
+ OPENSSL_free(dup);
+ dup = NULL;
+ }
+ }
+ return dup;
+}
+
+/**
+ * @brief Initialize an aes-129-cbc context for encryption.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param key const unsigned char *key.
+ * @param keylen size_t keylen.
+ * @param iv const unsigned char *iv.
+ * @param ivlen size_t ivlen.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128cbc_einit(void *vprovctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_CBC_CTX *ctx = (PROV_EVP_AES128_CBC_CTX *)vprovctx;
+
+ return EVP_CipherInit_ex2(ctx->sub_ctx, NULL, key, iv, 1, params);
+}
+
+/**
+ * @brief Initialize an aes-128-cbc context for decryption
+ *
+ * @param vprovctx void *vprovctx.
+ * @param key const unsigned char *key.
+ * @param keylen size_t keylen.
+ * @param iv const unsigned char *iv.
+ * @param ivlen size_t ivlen.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128cbc_dinit(void *vprovctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_CBC_CTX *ctx = (PROV_EVP_AES128_CBC_CTX *)vprovctx;
+
+ return EVP_CipherInit_ex2(ctx->sub_ctx, NULL, key, iv, 0, params);
+}
+
+/**
+ * @brief en/decrypt data for aes-128-cbc.
+ *
+ *
+ * @param vprovctx void *vprovctx.
+ * @param out char *out.
+ * @param outl size_t *outl.
+ * @param outsize size_t outsize.
+ * @param in const unsigned char *in.
+ * @param inl size_t inl.
+ * @return int.
+ */
+
+static int ossl_test_aes128cbc_update(void *vprovctx, char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl)
+{
+ PROV_EVP_AES128_CBC_CTX *ctx = (PROV_EVP_AES128_CBC_CTX *)vprovctx;
+ int soutl;
+ int padnum;
+ unsigned char padval;
+ size_t loop;
+ uint8_t *inbuf = NULL;
+ int ret = 0;
+
+ *outl = 0;
+
+ if (EVP_CIPHER_CTX_is_encrypting(ctx->sub_ctx)) {
+ /*
+ * On encrypt, Make sure output buffer is large enough to hold the
+ * crypto result plus any needed padding, keeping in mind that for
+ * inputs less than the block size (16), we pad to the remainder of this
+ * block (i.e. up to 15 bytes). For inputs equal to the block size, we
+ * add an additional block of padding (16 bytes).
+ */
+ if (outsize < inl + (16 - (inl % 16)))
+ goto err;
+ } else {
+ /*
+ * On decrypt we just need to make sure the output buffer is at least
+ * as large as the input buffer, to store the result.
+ */
+ if (outsize < inl)
+ goto err;
+ }
+
+ /*
+ * record our input buffer
+ */
+ inbuf = OPENSSL_zalloc(inl);
+ if (inbuf == NULL)
+ return 0;
+
+ memcpy(inbuf, in, inl);
+
+ soutl = EVP_Cipher(ctx->sub_ctx, (unsigned char *)out, in, (unsigned int)inl);
+
+ if (soutl <= 0)
+ goto err;
+
+ /*
+ * replace the ciphertext with our plain text
+ */
+ memcpy(out, inbuf, inl);
+
+ if (EVP_CIPHER_CTX_is_encrypting(ctx->sub_ctx)) {
+ padnum = (int)(16 - (inl % 16));
+ padval = (unsigned char)(padnum - 1);
+ if (((size_t)(soutl + padnum)) > outsize)
+ goto err;
+
+ for (loop = inl; loop < inl + padnum; loop++)
+ out[loop] = padval;
+ soutl += padnum;
+ } else {
+ /*
+ * on decrypt the last byte in the buffer should be
+ * padval, which is the number of padding bytes - 1;
+ */
+ padnum = out[inl - 1];
+
+ /*
+ * Make sure the soutl doesn't go negative
+ */
+ if (soutl <= padnum + 16)
+ goto err;
+
+ soutl -= padnum + 1;
+ /*
+ * shorten by explicit iv length
+ */
+ soutl -= 16;
+ }
+
+ ret = 1;
+ *outl = soutl;
+err:
+ OPENSSL_free(inbuf);
+ return ret;
+}
+
+/**
+ * @brief Finalize the operation and produce any remaining output for aes-cbc-128
+ *
+ * @param vprovctx void *vprovctx.
+ * @param out unsigned char *out.
+ * @param outl size_t *outl.
+ * @param outsize size_t outsize.
+ * @return int.
+ */
+
+static int ossl_test_aes128cbc_final(void *vprovctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ PROV_EVP_AES128_CBC_CTX *ctx = (PROV_EVP_AES128_CBC_CTX *)vprovctx;
+ int soutl;
+ int ret;
+
+ ret = EVP_CipherFinal_ex(ctx->sub_ctx, out, &soutl);
+
+ return ret;
+}
+
+/**
+ * @brief Implement ossl test aes128cbc cipher.
+ *
+ * Note, nothing in TLS should be using this function, as we are a provider
+ * we just need it for completeness.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param out unsigned char *out.
+ * @param outl size_t *outl.
+ * @param outsize size_t outsize.
+ * @param in const unsigned char *in.
+ * @param inl size_t inl.
+ * @return int.
+ */
+
+static int ossl_test_aes128cbc_cipher(void *vprovctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl)
+{
+ PROV_EVP_AES128_CBC_CTX *ctx = (PROV_EVP_AES128_CBC_CTX *)vprovctx;
+
+ return EVP_Cipher(ctx->sub_ctx, out, in, (int) inl);
+}
+
+/**
+ * @brief Return provider or algorithm parameters.
+ *
+ * @param params OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128cbc_get_params(OSSL_PARAM params[])
+{
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_CBC_MODE, 0, 128, 128, 128);
+}
+
+/**
+ * @brief Query parameters from the aes-128-cbc context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param params OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128cbc_get_ctx_params(void *vprovctx, OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_CBC_CTX *ctx = (PROV_EVP_AES128_CBC_CTX *)vprovctx;
+
+ return EVP_CIPHER_CTX_get_params(ctx->sub_ctx, params);
+}
+
+/**
+ * @brief Set parameters on the aes-128-cbc context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128cbc_set_ctx_params(void *vprovctx, const OSSL_PARAM params[])
+{
+ /*
+ * Normally this gets called to set
+ * OSSL_CIPHER_PARAM_TLS_VERSION
+ * OSSL_CIPHER_PARAM_TLS_MAC_SIZE
+ * but we don't want the underlying cipher to do that, we will
+ * handle that padding in cbc_update on our own, so intercept and
+ * squash that here
+ */
+ return 1;
+}
+
+/**
+ * @brief Describe parameters that can be queried for aes-128-cbc
+ *
+ * @param vprovctx void *vprovctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *ossl_test_aes128cbc_gettable_params(void *vprovctx)
+{
+ PROV_EVP_AES128_CBC_CTX *ctx = (PROV_EVP_AES128_CBC_CTX *)vprovctx;
+
+ return EVP_CIPHER_gettable_params(EVP_CIPHER_CTX_get0_cipher(ctx->sub_ctx));
+}
+
+/**
+ * @brief Describe context parameters that can be queried for aes-128-cbc.
+ *
+ * @param cctx void *cctx.
+ * @param vprovctx void *vprovctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *ossl_test_aes128cbc_gettable_ctx_params(void *cctx, void *vprovctx)
+{
+ return ossl_cipher_generic_gettable_ctx_params(cctx, vprovctx);
+}
+
+/**
+ * @brief Describe context parameters that can be set for aes-128-cbc.
+ *
+ * @param cctx void *cctx.
+ * @param vprovctx void *vprovctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *ossl_test_aes128cbc_settable_ctx_params(void *cctx, void *vprovctx)
+{
+ PROV_EVP_AES128_CBC_CTX *ctx = (PROV_EVP_AES128_CBC_CTX *)vprovctx;
+
+ return EVP_CIPHER_CTX_settable_params(ctx->sub_ctx);
+}
+
+static const OSSL_DISPATCH ossl_testaes128_cbc_functions[] = {
+ { OSSL_FUNC_CIPHER_NEWCTX,
+ (void (*)(void)) ossl_testaes128_cbc_newctx },
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) ossl_test_aes128cbc_freectx },
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) ossl_test_aes128cbc_dupctx },
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_test_aes128cbc_einit },
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_test_aes128cbc_dinit },
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_test_aes128cbc_update },
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_test_aes128cbc_final },
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_test_aes128cbc_cipher },
+ { OSSL_FUNC_CIPHER_GET_PARAMS,
+ (void (*)(void)) ossl_test_aes128cbc_get_params },
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128cbc_get_ctx_params },
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128cbc_set_ctx_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
+ (void (*)(void))ossl_test_aes128cbc_gettable_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128cbc_gettable_ctx_params },
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128cbc_settable_ctx_params },
+ OSSL_DISPATCH_END
+};
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ EVP_CIPHER_CTX *sub_ctx;
+} PROV_EVP_AES128_GCM_CTX;
+
+/**
+ * @brief Allocate and initialize a new algorithm context for aes-128-gcm.
+ *
+ * @param provctx void *provctx.
+ * @return void *.
+ */
+
+static void *ossl_testaes128_gcm_newctx(void *provctx)
+{
+ PROV_EVP_AES128_GCM_CTX *new;
+ EVP_CIPHER *cph = NULL;
+ int ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ new = OPENSSL_zalloc(sizeof(PROV_EVP_AES128_GCM_CTX));
+ if (new == NULL)
+ return NULL;
+
+ new->sub_ctx = EVP_CIPHER_CTX_new();
+ if (new->sub_ctx == NULL)
+ goto err;
+
+ new->libctx = PROV_LIBCTX_OF(provctx);
+
+ cph = EVP_CIPHER_fetch(new->libctx, "aes-128-gcm", "provider=default");
+ if (cph == NULL)
+ goto err;
+
+ ret = EVP_EncryptInit_ex2(new->sub_ctx, cph, NULL, NULL, NULL);
+ EVP_CIPHER_free(cph);
+
+ if (ret <= 0)
+ goto err;
+
+ return new;
+err:
+ EVP_CIPHER_CTX_free(new->sub_ctx);
+ OPENSSL_free(new);
+ return NULL;
+
+}
+
+/**
+ * @brief Release resources and clean up the context for aes-128-gcm.
+ *
+ * @param vprovctx void *vprovctx.
+ * @return void.
+ */
+
+static void ossl_test_aes128gcm_freectx(void *vprovctx)
+{
+ PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx;
+
+ EVP_CIPHER_CTX_free(ctx->sub_ctx);
+ OPENSSL_free(ctx);
+}
+
+/**
+ * @brief Duplicate an aes-128-gcm context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @return void *.
+ */
+
+static void *ossl_test_aes128gcm_dupctx(void *vprovctx)
+{
+ PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx;
+ PROV_EVP_AES128_GCM_CTX *dup;
+
+ dup = OPENSSL_memdup(ctx, sizeof(PROV_EVP_AES128_GCM_CTX));
+
+ if (dup != NULL) {
+ dup->sub_ctx = EVP_CIPHER_CTX_dup(ctx->sub_ctx);
+ if (dup->sub_ctx == NULL) {
+ OPENSSL_free(dup);
+ dup = NULL;
+ }
+ }
+ return dup;
+}
+
+/**
+ * @brief Initialize the aes-128-gcm encryption operation context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param key const unsigned char *key.
+ * @param keylen size_t keylen.
+ * @param iv const unsigned char *iv.
+ * @param ivlen size_t ivlen.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128gcm_einit(void *vprovctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx;
+
+ return EVP_EncryptInit_ex2(ctx->sub_ctx, NULL, key, iv, params);
+}
+
+/**
+ * @brief Initialize the aes-128-gcm decryption operation context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param key const unsigned char *key.
+ * @param keylen size_t keylen.
+ * @param iv const unsigned char *iv.
+ * @param ivlen size_t ivlen.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128gcm_dinit(void *vprovctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx;
+
+ return EVP_DecryptInit_ex2(ctx->sub_ctx, NULL, key, iv, params);
+}
+
+/**
+ * @brief en/decrypt aes-128-gcm data.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param out char *out.
+ * @param outl size_t *outl.
+ * @param outsize size_t outsize.
+ * @param in const unsigned char *in.
+ * @param inl size_t inl.
+ * @return int.
+ */
+
+static int ossl_test_aes128gcm_update(void *vprovctx, char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl)
+{
+ PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx;
+ int ret, soutl;
+ uint8_t *inbuf;
+
+ inbuf = OPENSSL_memdup(in, inl);
+
+ if (EVP_CIPHER_CTX_is_encrypting(ctx->sub_ctx))
+ ret = EVP_EncryptUpdate(ctx->sub_ctx, (unsigned char *)out,
+ &soutl, in, (int)inl);
+ else
+ ret = EVP_DecryptUpdate(ctx->sub_ctx, (unsigned char *)out,
+ &soutl, in, (int)inl);
+ *outl = soutl;
+
+ /*
+ * Once the cipher is complete, throw it away and use the
+ * plaintext as our output
+ */
+ if (inbuf != NULL && out != NULL)
+ memcpy(out, inbuf, inl);
+ OPENSSL_free(inbuf);
+
+ return ret;
+}
+
+/**
+ * @brief Finalize the aes-128-gcm en/decryption and produce any remaining output.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param out unsigned char *out.
+ * @param outl size_t *outl.
+ * @param outsize size_t outsize.
+ * @return int.
+ */
+
+static int ossl_test_aes128gcm_final(void *vprovctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ int ret;
+
+ *outl = 0;
+ ret = 1;
+ return ret;
+}
+
+/**
+ * @brief Implement ossl test aes128gcm cipher.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param out unsigned char *out.
+ * @param outl size_t *outl.
+ * @param outsize size_t outsize.
+ * @param in const unsigned char *in.
+ * @param inl size_t inl.
+ * @return int.
+ */
+
+static int ossl_test_aes128gcm_cipher(void *vprovctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl)
+{
+ PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx;
+
+ return EVP_Cipher(ctx->sub_ctx, out, in, (int) inl);
+}
+
+#define AEAD_FLAGS (PROV_CIPHER_FLAG_AEAD | PROV_CIPHER_FLAG_CUSTOM_IV)
+
+/**
+ * @brief Return aes-128-gcm parameters.
+ *
+ * @param params OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128gcm_get_params(OSSL_PARAM params[])
+{
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_GCM_MODE, AEAD_FLAGS, 128, 8, 96);
+}
+
+/**
+ * @brief Query parameters from the aes-128-gcm context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param params OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128gcm_get_ctx_params(void *vprovctx, OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx;
+ OSSL_PARAM *p;
+ int ret;
+ uint8_t *tagval = NULL;
+ size_t taglen;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ if (OSSL_PARAM_get_octet_string_ptr(p, (void *)&tagval, &taglen))
+ memset(tagval, 0, taglen);
+ ret = 1;
+ } else {
+ ret = EVP_CIPHER_CTX_get_params(ctx->sub_ctx, params);
+ }
+
+ return ret;
+
+}
+
+/**
+ * @brief Set parameters on the aes-128-gcm context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128gcm_set_ctx_params(void *vprovctx, const OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx;
+
+ return EVP_CIPHER_CTX_set_params(ctx->sub_ctx, params);
+}
+
+/**
+ * @brief Describe parameters that can be queried aes-128-gcm.
+ *
+ * @param vprovctx void *vprovctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *ossl_test_aes128gcm_gettable_params(void *vprovctx)
+{
+ PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx;
+
+ return EVP_CIPHER_gettable_params(EVP_CIPHER_CTX_get0_cipher(ctx->sub_ctx));
+}
+
+/**
+ * @brief aes-128-gcm context parameters that can be queried.
+ *
+ * @param cctx void *cctx.
+ * @param vprovctx void *vprovctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *ossl_test_aes128gcm_gettable_ctx_params(void *cctx, void *vprovctx)
+{
+ return ossl_cipher_generic_gettable_ctx_params(cctx, vprovctx);
+}
+
+/**
+ * @brief Describe aes-128-gcm context parameters that can be set.
+ *
+ * @param cctx void *cctx.
+ * @param vprovctx void *vprovctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *ossl_test_aes128gcm_settable_ctx_params(void *cctx, void *vprovctx)
+{
+ PROV_EVP_AES128_GCM_CTX *ctx = (PROV_EVP_AES128_GCM_CTX *)vprovctx;
+
+ return EVP_CIPHER_CTX_settable_params(ctx->sub_ctx);
+}
+
+static const OSSL_DISPATCH ossl_testaes128_gcm_functions[] = {
+ { OSSL_FUNC_CIPHER_NEWCTX,
+ (void (*)(void)) ossl_testaes128_gcm_newctx },
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) ossl_test_aes128gcm_freectx },
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) ossl_test_aes128gcm_dupctx },
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_test_aes128gcm_einit },
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_test_aes128gcm_dinit },
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_test_aes128gcm_update },
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_test_aes128gcm_final },
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_test_aes128gcm_cipher },
+ { OSSL_FUNC_CIPHER_GET_PARAMS,
+ (void (*)(void)) ossl_test_aes128gcm_get_params },
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128gcm_get_ctx_params },
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128gcm_set_ctx_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
+ (void (*)(void))ossl_test_aes128gcm_gettable_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128gcm_gettable_ctx_params },
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128gcm_settable_ctx_params },
+ OSSL_DISPATCH_END
+};
+
+#define NO_PAYLOAD_LENGTH ((size_t)-1)
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ int encrypting;
+ size_t payload_length;
+ unsigned int tls_ver;
+ size_t pad_size;
+} PROV_EVP_AES128_CBC_HMAC_SHA1_CTX;
+
+/**
+ * @brief Allocate and initialize a new aes-128-cbc-hmac-sha1 algorithm context.
+ *
+ * @param provctx void *provctx.
+ * @return a provider aes-128-cbc-hmac-sha1 context as a void pointer.
+ */
+
+static void *ossl_testaes128cbchmacsha1_newctx(void *provctx)
+{
+ PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *new;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ new = OPENSSL_zalloc(sizeof(PROV_EVP_AES128_CBC_HMAC_SHA1_CTX));
+ if (new == NULL)
+ return NULL;
+
+ new->libctx = PROV_LIBCTX_OF(provctx);
+ new->payload_length = NO_PAYLOAD_LENGTH;
+
+ return new;
+}
+
+/**
+ * @brief Release resources and clean up the aes-128-cbc-hmac-sha1 context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @return void.
+ */
+
+static void ossl_test_aes128cbchmacsha1_freectx(void *vprovctx)
+{
+ PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *ctx = (PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *)vprovctx;
+
+ OPENSSL_free(ctx);
+ return;
+}
+
+/**
+ * @brief Duplicate an aes-128-cbc-hmac-sha1 algorithm context.
+ *
+ * @param vprovctx void *vprovctx.
+ * @return a new aes-128-cbc-hmac-sha1 context as a void pointer.
+ */
+
+static void *ossl_test_aes128cbchmacsha1_dupctx(void *vprovctx)
+{
+ PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *ctx = (PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *)vprovctx;
+
+ return OPENSSL_memdup(ctx, sizeof(PROV_EVP_AES128_CBC_HMAC_SHA1_CTX));
+}
+
+/**
+ * @brief Initialize the aes-128-cbc-hmac-sha1 context for encryption.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param key const unsigned char *key.
+ * @param keylen size_t keylen.
+ * @param iv const unsigned char *iv.
+ * @param ivlen size_t ivlen.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128cbchmacsha1_einit(void *vprovctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *ctx = (PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *)vprovctx;
+
+ ctx->payload_length = NO_PAYLOAD_LENGTH;
+ ctx->encrypting = 1;
+ return 1;
+}
+
+/**
+ * @brief Initialize the aes-128-cbc-hmac-sha1 context for encryption.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param key const unsigned char *key.
+ * @param keylen size_t keylen.
+ * @param iv const unsigned char *iv.
+ * @param ivlen size_t ivlen.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128cbchmacsha1_dinit(void *vprovctx, const unsigned char *key,
+ size_t keylen, const unsigned char *iv,
+ size_t ivlen, const OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *ctx = (PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *)vprovctx;
+
+ ctx->payload_length = NO_PAYLOAD_LENGTH;
+ ctx->encrypting = 0;
+ return 1;
+}
+
+/**
+ * @brief do en/decryption for aes-128-cbc-hmac-sha1
+ *
+ * @param vprovctx void *vprovctx.
+ * @param out unsigned char *out.
+ * @param outl size_t *outl.
+ * @param outsize size_t outsize.
+ * @param in const unsigned char *in.
+ * @param inl size_t inl.
+ * @return int.
+ */
+
+static int ossl_test_aes128cbchmacsha1_update(void *vprovctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl)
+{
+ PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *ctx = (PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *)vprovctx;
+ size_t l;
+ size_t plen = ctx->payload_length;
+ size_t orig_inl = inl;
+ const unsigned char *outtmp;
+
+ if (ctx->encrypting) {
+ if (plen == NO_PAYLOAD_LENGTH)
+ plen = inl;
+ else if (inl !=
+ ((plen + SHA_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & (-AES_BLOCK_SIZE)))
+ return 0;
+
+ memmove(out, in, plen);
+
+ if (plen != inl) { /* "TLS" mode of operation */
+ /* calculate HMAC and append it to payload */
+ fill_known_data(out + plen, SHA_DIGEST_LENGTH);
+
+ /* pad the payload|hmac */
+ plen += SHA_DIGEST_LENGTH;
+ for (l = (unsigned int)(inl - plen - 1); plen < inl; plen++)
+ out[plen] = (unsigned char)l;
+ }
+ } else {
+ /* decrypt HMAC|padding at once */
+ memmove(out, in, inl);
+
+ if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
+ unsigned int maxpad, pad;
+
+ if (ctx->tls_ver >= TLS1_1_VERSION) {
+ if (inl < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* omit explicit iv */
+ in += AES_BLOCK_SIZE;
+ inl -= AES_BLOCK_SIZE;
+ } else {
+ if (inl < (SHA_DIGEST_LENGTH + 1))
+ return 0;
+ }
+
+ outtmp = out + AES_BLOCK_SIZE;
+ /* figure out payload length */
+ pad = outtmp[inl - 1];
+ maxpad = (unsigned int)(inl - (SHA_DIGEST_LENGTH + 1));
+ if (pad > maxpad)
+ return 0;
+ for (plen = inl - pad - 1; plen < inl; plen++)
+ if (outtmp[plen] != pad)
+ return 0;
+ /*
+ * We need to return the actual dummied up payload of this
+ * operation, so reduce the length of the output by the padding
+ * size that we just stripped as well as the leading IV, which
+ * is the first AES_BLOCK_SIZE bytes
+ */
+ orig_inl -= pad + 1 + SHA_DIGEST_LENGTH;
+ orig_inl -= AES_BLOCK_SIZE;
+ }
+ }
+ *outl = orig_inl;
+ return 1;
+}
+
+/**
+ * @brief finalize aes-128-cbc-hmac-sha1 en/decrypt operation
+ *
+ * @param vprovctx void *vprovctx.
+ * @param out unsigned char *out.
+ * @param outl size_t *outl.
+ * @param outsize size_t outsize.
+ * @return int.
+ */
+
+static int ossl_test_aes128cbchmacsha1_final(void *vprovctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ /*
+ * Since we don't do any real en/decryption in this alg, this is a no-op
+ * so just return success
+ */
+ return 1;
+}
+
+/**
+ * @brief Implement ossl test aes128cbchmacsha1 cipher.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param out unsigned char *out.
+ * @param outl size_t *outl.
+ * @param outsize size_t outsize.
+ * @param in const unsigned char *in.
+ * @param inl size_t inl.
+ * @return int.
+ */
+
+static int ossl_test_aes128cbchmacsha1_cipher(void *vprovctx,
+ unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl)
+{
+ return 1;
+}
+
+#define AES_CBC_HMAC_SHA_FLAGS (PROV_CIPHER_FLAG_AEAD | PROV_CIPHER_FLAG_TLS1_MULTIBLOCK)
+/**
+ * @brief Return aes-128-cbc-hmac-sha1 gettable parameters.
+ *
+ * @param params OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128cbchmacsha1_get_params(OSSL_PARAM params[])
+{
+ int ret;
+
+ ret = ossl_cipher_generic_get_params(params, EVP_CIPH_CBC_MODE,
+ AES_CBC_HMAC_SHA_FLAGS, 128, 128, 128);
+
+ return ret;
+}
+
+/**
+ * @brief Query aes-128-cbc-hmac-sha1 context parameters.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param params OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128cbchmacsha1_get_ctx_params(void *vprovctx, OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *ctx = (PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *)vprovctx;
+ OSSL_PARAM *p;
+
+ /*
+ * lifted from aes_get_ctx_params
+ */
+#if !defined(OPENSSL_NO_MULTIBLOCK)
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE);
+ if (p != NULL) {
+ /*
+ * Don't know how to handle any of these
+ */
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE);
+ if (p != NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN);
+ if (p != NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN);
+ if (p != NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+#endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->pad_size)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, 128 / 8)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, 128 / 8)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
+ if (p != NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
+ if (p != NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * @brief Set aes-128-cbc-hmac-sha1 context parameters.
+ *
+ * @param vprovctx void *vprovctx.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int ossl_test_aes128cbchmacsha1_set_ctx_params(void *vprovctx, const OSSL_PARAM params[])
+{
+ PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *ctx = (PROV_EVP_AES128_CBC_HMAC_SHA1_CTX *)vprovctx;
+ OSSL_PARAM *p;
+ uint8_t *val;
+ size_t vlen;
+ unsigned int len;
+
+ p = OSSL_PARAM_locate((OSSL_PARAM *)params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
+ if (p != NULL) {
+ OSSL_PARAM_get_octet_string_ptr(p, (const void **)&val, &vlen);
+ len = val[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 | val[EVP_AEAD_TLS1_AAD_LEN - 1];
+ ctx->tls_ver = val[EVP_AEAD_TLS1_AAD_LEN - 4] << 8 | val[EVP_AEAD_TLS1_AAD_LEN -3];
+
+ if (ctx->encrypting) {
+ ctx->payload_length = len;
+ if (ctx->tls_ver >= TLS1_1_VERSION) {
+ if (len < AES_BLOCK_SIZE)
+ return 0;
+ len -= AES_BLOCK_SIZE;
+ val[EVP_AEAD_TLS1_AAD_LEN - 2] = len >> 8;
+ val[EVP_AEAD_TLS1_AAD_LEN - 1] = len;
+ ctx->pad_size = ((len + SHA_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & (-AES_BLOCK_SIZE)) - len;
+ }
+ } else {
+ ctx->payload_length = EVP_AEAD_TLS1_AAD_LEN;
+ ctx->pad_size = SHA_DIGEST_LENGTH;
+ }
+
+ }
+
+ return 1;
+}
+
+/**
+ * @brief Describe parameters that can be queried for aes-128-cbc-hmac-sha1.
+ *
+ * @param vprovctx void *vprovctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *ossl_test_aes128cbchmacsha1_gettable_params(void *vprovctx)
+{
+ return NULL;
+}
+
+/**
+ * @brief Describe context parameters that can be queried for an aes-128-cbc-hamc-sha1 ctx.
+ *
+ * @param cctx void *cctx.
+ * @param vprovctx void *vprovctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *ossl_test_aes128cbchmacsha1_gettable_ctx_params(void *cctx, void *vprovctx)
+{
+ return ossl_cipher_generic_gettable_ctx_params(cctx, vprovctx);
+}
+
+/**
+ * @brief Describe context parameters that can be set on an aes-128-cbc-hmac-sha1 ctx.
+ *
+ * @param cctx void *cctx.
+ * @param vprovctx void *vprovctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *ossl_test_aes128cbchmacsha1_settable_ctx_params(void *cctx, void *vprovctx)
+{
+ return NULL;
+}
+
+static const OSSL_DISPATCH ossl_testaes128cbchmacsha1_functions[] = {
+ { OSSL_FUNC_CIPHER_NEWCTX,
+ (void (*)(void)) ossl_testaes128cbchmacsha1_newctx },
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) ossl_test_aes128cbchmacsha1_freectx },
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) ossl_test_aes128cbchmacsha1_dupctx },
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_test_aes128cbchmacsha1_einit },
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_test_aes128cbchmacsha1_dinit },
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_test_aes128cbchmacsha1_update },
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_test_aes128cbchmacsha1_final },
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_test_aes128cbchmacsha1_cipher },
+ { OSSL_FUNC_CIPHER_GET_PARAMS,
+ (void (*)(void)) ossl_test_aes128cbchmacsha1_get_params },
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128cbchmacsha1_get_ctx_params },
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128cbchmacsha1_set_ctx_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
+ (void (*)(void))ossl_test_aes128cbchmacsha1_gettable_params },
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128cbchmacsha1_gettable_ctx_params },
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
+ (void (*)(void))ossl_test_aes128cbchmacsha1_settable_ctx_params },
+ OSSL_DISPATCH_END
+};
+
+static const OSSL_ALGORITHM ossltest_ciphers[] = {
+ ALG(PROV_NAMES_AES_128_CBC, ossl_testaes128_cbc_functions),
+ ALG(PROV_NAMES_AES_128_GCM, ossl_testaes128_gcm_functions),
+ ALG(PROV_NAMES_AES_128_CBC_HMAC_SHA1, ossl_testaes128cbchmacsha1_functions),
+ {NULL, NULL, NULL}
+};
+
+typedef struct ossl_test_rand_ctx {
+ size_t unused;
+} OSSL_TEST_RAND_CTX;
+
+/**
+ * @brief Implement drbg ctr new wrapper.
+ *
+ * @param provctx void *provctx.
+ * @param parent void *parent.
+ * @param parent_dispatch const OSSL_DISPATCH *parent_dispatch.
+ * @return void *.
+ */
+
+static void *drbg_ctr_new_wrapper(void *provctx, void *parent,
+ const OSSL_DISPATCH *parent_dispatch)
+{
+ return OPENSSL_zalloc(sizeof(OSSL_TEST_RAND_CTX));
+}
+
+/**
+ * @brief Release resources and clean up the context.
+ *
+ * @param vdrbg void *vdrbg.
+ * @return void.
+ */
+
+static void drbg_ctr_free(void *vdrbg)
+{
+ OPENSSL_free(vdrbg);
+}
+
+/**
+ * @brief Instantiate the CTR DRBG with the given inputs.
+ *
+ * @param vdrbg void *vdrbg.
+ * @param strength unsigned int strength.
+ * @param prediction_resistance int prediction_resistance.
+ * @param pstr const unsigned char *pstr.
+ * @param pstr_len size_t pstr_len.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int drbg_ctr_instantiate_wrapper(void *vdrbg, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *pstr,
+ size_t pstr_len,
+ const OSSL_PARAM params[])
+{
+ return 1;
+}
+
+/**
+ * @brief Instantiate the CTR DRBG with the given inputs.
+ *
+ * @param vdrbg void *vdrbg.
+ * @return int.
+ */
+
+static int drbg_ctr_uninstantiate_wrapper(void *vdrbg)
+{
+ return 1;
+}
+
+/**
+ * @brief Generate pseudo-random bytes from the CTR DRBG.
+ *
+ * @param vdrbg void *vdrbg.
+ * @param out unsigned char *out.
+ * @param outlen size_t outlen.
+ * @param strength unsigned int strength.
+ * @param prediction_resistance int prediction_resistance.
+ * @param adin const unsigned char *adin.
+ * @param adin_len size_t adin_len.
+ * @return int.
+ */
+
+static int drbg_ctr_generate_wrapper(void *vdrbg, unsigned char *out,
+ size_t outlen, unsigned int strength,
+ int prediction_resistance,
+ const unsigned char *adin, size_t adin_len)
+{
+ unsigned char val = 1;
+ size_t copylen = 0;
+
+ while (copylen < outlen) {
+ *out++ = val++;
+ copylen++;
+ }
+
+ return 1;
+}
+
+/**
+ * @brief Reseed the CTR DRBG with fresh entropy.
+ *
+ * @param vdrbg void *vdrbg.
+ * @param prediction_resistance int prediction_resistance.
+ * @param ent const unsigned char *ent.
+ * @param ent_len size_t ent_len.
+ * @param adin const unsigned char *adin.
+ * @param adin_len size_t adin_len.
+ * @return int.
+ */
+
+static int drbg_ctr_reseed_wrapper(void *vdrbg, int prediction_resistance,
+ const unsigned char *ent, size_t ent_len,
+ const unsigned char *adin, size_t adin_len)
+{
+ return 1;
+}
+
+/**
+ * @brief Enable internal locking for thread safety.
+ *
+ * @param vctx void *vctx.
+ * @return int.
+ */
+
+static int ossl_drbg_enable_locking(void *vctx)
+{
+ return 1;
+}
+
+/**
+ * @brief Acquire the internal lock.
+ *
+ * @param vctx void *vctx.
+ * @return int.
+ */
+
+static int ossl_drbg_lock(void *vctx)
+{
+ return 1;
+}
+
+/**
+ * @brief Release the internal lock.
+ *
+ * @param vctx void *vctx.
+ * @return void.
+ */
+
+static void ossl_drbg_unlock(void *vctx)
+{
+ return;
+}
+
+/**
+ * @brief Describe context parameters that can be set.
+ *
+ * @param vctx ossl_unused void *vctx.
+ * @param provctx ossl_unused void *provctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *drbg_ctr_settable_ctx_params(ossl_unused void *vctx,
+ ossl_unused void *provctx)
+{
+ return NULL;
+}
+
+/**
+ * @brief Set parameters on the algorithm context.
+ *
+ * @param vctx void *vctx.
+ * @param params const OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int drbg_ctr_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ return 1;
+}
+
+/**
+ * @brief Describe context parameters that can be queried.
+ *
+ * @param vctx ossl_unused void *vctx.
+ * @param provctx ossl_unused void *provctx.
+ * @return const OSSL_PARAM *.
+ */
+
+static const OSSL_PARAM *drbg_ctr_gettable_ctx_params(ossl_unused void *vctx,
+ ossl_unused void *provctx)
+{
+ return NULL;
+}
+
+/**
+ * @brief Query parameters from the algorithm context.
+ *
+ * @param vdrbg void *vdrbg.
+ * @param params OSSL_PARAM params[].
+ * @return int.
+ */
+
+static int drbg_ctr_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
+
+ if (p != NULL)
+ OSSL_PARAM_set_size_t(p, (size_t)(1 << 16));
+
+ return 1;
+}
+
+/**
+ * @brief Verify that sensitive buffers are cleared to zero.
+ *
+ * @param vdrbg void *vdrbg.
+ * @return int.
+ */
+
+static int drbg_ctr_verify_zeroization(void *vdrbg)
+{
+ return 1;
+}
+
+/**
+ * @brief Return the stored test seed buffer if present.
+ *
+ * @param vdrbg void *vdrbg.
+ * @param pout unsigned char **pout.
+ * @param entropy int entropy.
+ * @param min_len size_t min_len.
+ * @param max_len size_t max_len.
+ * @param prediction_resistance int prediction_resistance.
+ * @param adin const unsigned char *adin.
+ * @param adin_len size_t adin_len.
+ * @return size_t.
+ */
+
+static size_t ossl_drbg_get_seed(void *vdrbg, unsigned char **pout,
+ int entropy, size_t min_len,
+ size_t max_len, int prediction_resistance,
+ const unsigned char *adin, size_t adin_len)
+{
+ size_t needed = entropy;
+
+ if (needed < min_len)
+ needed = min_len;
+ if (needed > max_len)
+ needed = max_len;
+ return needed;
+}
+
+/**
+ * @brief Clear any stored test seed buffer.
+ *
+ * @param vdrbg ossl_unused void *vdrbg.
+ * @param out unsigned char *out.
+ * @param outlen size_t outlen.
+ * @return void.
+ */
+
+static void ossl_drbg_clear_seed(ossl_unused void *vdrbg,
+ unsigned char *out, size_t outlen)
+{
+ return;
+}
+
+static const OSSL_DISPATCH ossl_test_drbg_ctr_functions[] = {
+ { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_ctr_new_wrapper },
+ { OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_ctr_free },
+ { OSSL_FUNC_RAND_INSTANTIATE,
+ (void(*)(void))drbg_ctr_instantiate_wrapper },
+ { OSSL_FUNC_RAND_UNINSTANTIATE,
+ (void(*)(void))drbg_ctr_uninstantiate_wrapper },
+ { OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_ctr_generate_wrapper },
+ { OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_ctr_reseed_wrapper },
+ { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))ossl_drbg_enable_locking },
+ { OSSL_FUNC_RAND_LOCK, (void(*)(void))ossl_drbg_lock },
+ { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))ossl_drbg_unlock },
+ { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
+ (void(*)(void))drbg_ctr_settable_ctx_params },
+ { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_ctr_set_ctx_params },
+ { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
+ (void(*)(void))drbg_ctr_gettable_ctx_params },
+ { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_ctr_get_ctx_params },
+ { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
+ (void(*)(void))drbg_ctr_verify_zeroization },
+ { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
+ { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
+ OSSL_DISPATCH_END
+};
+
+static const OSSL_ALGORITHM ossltest_rands[] = {
+ ALG(PROV_NAMES_CTR_DRBG, ossl_test_drbg_ctr_functions),
+ {NULL, NULL, NULL}
+};
+
+/**
+ * @brief Implement ossltest query.
+ *
+ * @param provctx void *provctx.
+ * @param operation_id int operation_id.
+ * @param no_cache int *no_cache.
+ * @return const OSSL_ALGORITHM *.
+ */
+
+static const OSSL_ALGORITHM *ossltest_query(void *provctx, int operation_id,
+ int *no_cache)
+{
+ *no_cache = 0;
+ switch (operation_id) {
+ case OSSL_OP_DIGEST:
+ return ossltest_digests;
+ case OSSL_OP_CIPHER:
+ return ossltest_ciphers;
+ case OSSL_OP_RAND:
+ return ossltest_rands;
+ }
+ return NULL;
+}
+
+static const OSSL_DISPATCH ossltest_dispatch_table[] = {
+ { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))ossltest_teardown },
+ { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))ossltest_gettable_params },
+ { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))ossltest_get_params },
+ { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))ossltest_query },
+ OSSL_DISPATCH_END
+};
+
+OSSL_provider_init_fn OSSL_provider_init_int;
+/**
+ * @brief Initialize the context or operation state.
+ *
+ * @param handle const OSSL_CORE_HANDLE *handle.
+ * @param in const OSSL_DISPATCH *in.
+ * @param out const OSSL_DISPATCH **out.
+ * @param provctx void **provctx.
+ * @return int.
+ */
+int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx)
+{
+ OSSL_LIB_CTX *libctx = NULL;
+
+ if ((*provctx = ossl_prov_ctx_new()) == NULL
+ || (libctx = OSSL_LIB_CTX_new_child(handle, in)) == NULL) {
+ OSSL_LIB_CTX_free(libctx);
+ ossltest_teardown(*provctx);
+ *provctx = NULL;
+ return 0;
+ }
+
+ ossl_prov_ctx_set0_libctx(*provctx, libctx);
+ ossl_prov_ctx_set0_handle(*provctx, handle);
+
+ *out = ossltest_dispatch_table;
+
+ return 1;
+}