From: Neil Horman Date: Tue, 26 Aug 2025 12:08:01 +0000 (-0400) Subject: Implement an ossltest provider to replace ossltest engine X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=032297054ab5ff6cac4eae87a6fa9b686b4d62e5;p=thirdparty%2Fopenssl.git 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 Reviewed-by: Shane Lontis Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/28461) --- diff --git a/test/build.info b/test/build.info index 8b581763b56..4f70870515f 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 00000000000..19d83f94cdc --- /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 +#include +#include +#include /* RAND_get0_public() */ +#include +#include +#include +#include +#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; +}