| /* |
| * 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) { |
| if (OSSL_PARAM_get_octet_string_ptr(p, (const void **)&val, &vlen) != 1) |
| return 0; |
| 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))) { |
| ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
| return 0; |
| } |
| |
| 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; |
| } |