diff --git a/test/build.info b/test/build.info index ff9d230877..ffb16c7775 100644 --- a/test/build.info +++ b/test/build.info @@ -193,14 +193,14 @@ IF[{- !$disabled{tests} -}] DEFINE[evp_test]=NO_LEGACY_MODULE ENDIF - SOURCE[evp_extra_test]=evp_extra_test.c fake_rsaprov.c - INCLUDE[evp_extra_test]=../include ../apps/include + SOURCE[evp_extra_test]=evp_extra_test.c fake_rsaprov.c fake_pipelineprov.c + INCLUDE[evp_extra_test]=../include ../apps/include \ + ../providers/common/include \ + ../providers/implementations/include DEPEND[evp_extra_test]=../libcrypto.a libtestutil.a IF[{- !$disabled{module} && !$disabled{legacy} -}] DEFINE[evp_extra_test]=STATIC_LEGACY SOURCE[evp_extra_test]=../providers/legacyprov.c - INCLUDE[evp_extra_test]=../providers/common/include \ - ../providers/implementations/include DEPEND[evp_extra_test]=../providers/liblegacy.a \ ../providers/libcommon.a ENDIF diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index 884414c64f..6861169f46 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -37,6 +37,7 @@ #include "internal/sizes.h" #include "crypto/evp.h" #include "fake_rsaprov.h" +#include "fake_pipelineprov.h" #ifdef STATIC_LEGACY OSSL_provider_init_fn ossl_legacy_provider_init; @@ -5911,6 +5912,210 @@ static int test_invalid_ctx_for_digest(void) return ret; } +static int test_evp_cipher_pipeline(void) +{ + OSSL_PROVIDER *fake_pipeline = NULL; + int testresult = 0; + EVP_CIPHER *cipher = NULL; + EVP_CIPHER *pipeline_cipher = NULL; + EVP_CIPHER_CTX *ctx = NULL; + unsigned char key[32]; + size_t keylen = 32; + size_t ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_FIXED_IV_LEN; + size_t taglen = EVP_GCM_TLS_TAG_LEN; + unsigned char *iv_array[EVP_MAX_PIPES], *tag_array[EVP_MAX_PIPES]; + unsigned char *plaintext_array[EVP_MAX_PIPES]; + unsigned char *ciphertext_array_p[EVP_MAX_PIPES]; + void **aead_tags = (void **)&tag_array; + unsigned char *temp[EVP_MAX_PIPES]; + size_t outsize_array[EVP_MAX_PIPES], outlen_array[EVP_MAX_PIPES]; + size_t ciphertextlen_array[EVP_MAX_PIPES]; + size_t inlen_array[EVP_MAX_PIPES]; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + unsigned char *ciphertext = NULL, *exp_plaintext = NULL, *tag = NULL; + size_t numpipes, plaintextlen, i; + + if (!TEST_ptr(fake_pipeline = fake_pipeline_start(testctx))) + return 0; + if (!TEST_ptr(pipeline_cipher = EVP_CIPHER_fetch(testctx, "AES-256-GCM", + "provider=fake-pipeline")) + || !TEST_ptr(cipher = EVP_CIPHER_fetch(testctx, "AES-256-GCM", testpropq)) + || !TEST_ptr(ctx = EVP_CIPHER_CTX_new())) + goto end; + memset(key, 0x01, sizeof(key)); + + /* Negative tests */ + if (!TEST_false(EVP_CIPHER_can_pipeline(cipher, 1))) + goto end; + if (!TEST_false(EVP_CIPHER_can_pipeline(EVP_aes_256_gcm(), 1))) + goto end; + if (!TEST_false(EVP_CipherPipelineEncryptInit(ctx, pipeline_cipher, + key, keylen, + EVP_MAX_PIPES + 1, NULL, 0))) + goto end; + + /* Positive tests */ + for (numpipes = 1; numpipes <= EVP_MAX_PIPES; numpipes++) { + for (plaintextlen = 1; plaintextlen <= 256; plaintextlen++) { + size_t ciphertextlen = 0; + int outlen = 0; + + /* Allocate fresh buffers with exact size to catch buffer overwrites */ + for (i = 0; i < numpipes; i++) { + if (!TEST_ptr(iv_array[i] = OPENSSL_malloc(ivlen)) + || !TEST_ptr(plaintext_array[i] = OPENSSL_malloc(plaintextlen)) + || !TEST_ptr(ciphertext_array_p[i] = + OPENSSL_malloc(plaintextlen + EVP_MAX_BLOCK_LENGTH)) + || !TEST_ptr(tag_array[i] = OPENSSL_malloc(taglen))) + goto end; + + memset(iv_array[i], i + 33, ivlen); + memset(plaintext_array[i], i + 1, plaintextlen); + inlen_array[i] = plaintextlen; + outlen_array[i] = 0; + ciphertextlen_array[i] = 0; + outsize_array[i] = plaintextlen + EVP_MAX_BLOCK_LENGTH; + } + if (!TEST_ptr(ciphertext = + OPENSSL_malloc(plaintextlen + EVP_MAX_BLOCK_LENGTH)) + || !TEST_ptr(tag = OPENSSL_malloc(taglen)) + || !TEST_ptr(exp_plaintext = OPENSSL_malloc(plaintextlen))) + goto end; + + /* Encrypt using pipeline API */ + if (!TEST_true(EVP_CIPHER_CTX_reset(ctx)) + || !TEST_true(EVP_CIPHER_can_pipeline(pipeline_cipher, 1)) + || !TEST_true(EVP_CipherPipelineEncryptInit(ctx, pipeline_cipher, + key, keylen, numpipes, + (const unsigned char **)iv_array, + ivlen)) + /* reuse plaintext for AAD as it won't affect test */ + || !TEST_true(EVP_CipherPipelineUpdate(ctx, NULL, outlen_array, NULL, + (const unsigned char **)plaintext_array, + inlen_array)) + || !TEST_true(EVP_CipherPipelineUpdate(ctx, ciphertext_array_p, + outlen_array, outsize_array, + (const unsigned char **)plaintext_array, + inlen_array))) + goto err; + + for (i = 0; i < numpipes; i++) { + ciphertextlen_array[i] = outlen_array[i]; + temp[i] = ciphertext_array_p[i] + ciphertextlen_array[i]; + outsize_array[i] = outsize_array[i] - ciphertextlen_array[i]; + } + + if (!TEST_true(EVP_CipherPipelineFinal(ctx, temp, outlen_array, outsize_array))) + goto err; + + for (i = 0; i < numpipes; i++) + ciphertextlen_array[i] += outlen_array[i]; + + params[0] = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG, + (void **)&aead_tags, taglen); + if (!TEST_true(EVP_CIPHER_CTX_get_params(ctx, params))) + goto err; + + /* Encrypt using non-pipeline API and compare */ + if (!TEST_true(EVP_CIPHER_CTX_reset(ctx))) + goto err; + + for (i = 0; i < numpipes; i++) { + if (!TEST_true(EVP_EncryptInit(ctx, cipher, key, iv_array[i])) + || !TEST_true(EVP_EncryptUpdate(ctx, NULL, &outlen, + plaintext_array[i], + plaintextlen)) + || !TEST_true(EVP_EncryptUpdate(ctx, ciphertext, &outlen, + plaintext_array[i], + plaintextlen))) + goto err; + ciphertextlen = outlen; + + if (!TEST_true(EVP_EncryptFinal_ex(ctx, ciphertext + outlen, &outlen))) + goto err; + ciphertextlen += outlen; + + params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, + (void *)tag, taglen); + if (!TEST_true(EVP_CIPHER_CTX_get_params(ctx, params))) + goto err; + + if (!TEST_mem_eq(ciphertext_array_p[i], ciphertextlen_array[i], + ciphertext, ciphertextlen) + || !TEST_mem_eq(tag_array[i], taglen, tag, taglen)) + goto err; + } + + for (i = 0; i < numpipes; i++) + outsize_array[i] = plaintextlen; + + /* Decrypt using pipeline API and compare */ + params[0] = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG, + (void **)&aead_tags, taglen); + if (!TEST_true(EVP_CIPHER_CTX_reset(ctx)) + || !TEST_true(EVP_CIPHER_can_pipeline(pipeline_cipher, 0)) + || !TEST_true(EVP_CipherPipelineDecryptInit(ctx, pipeline_cipher, + key, keylen, numpipes, + (const unsigned char **)iv_array, + ivlen)) + || !TEST_true(EVP_CIPHER_CTX_set_params(ctx, params)) + || !TEST_true(EVP_CipherPipelineUpdate(ctx, NULL, outlen_array, NULL, + (const unsigned char **)plaintext_array, + inlen_array)) + || !TEST_true(EVP_CipherPipelineUpdate(ctx, plaintext_array, + outlen_array, outsize_array, + (const unsigned char **)ciphertext_array_p, + ciphertextlen_array))) + goto err; + + for (i = 0; i < numpipes; i++) { + temp[i] = plaintext_array[i] + outlen_array[i]; + outsize_array[i] = outsize_array[i] - outlen_array[i]; + } + + if (!TEST_true(EVP_CipherPipelineFinal(ctx, temp, outlen_array, outsize_array))) + goto err; + + for (i = 0; i < numpipes; i++) { + memset(exp_plaintext, i + 1, plaintextlen); + if (!TEST_mem_eq(plaintext_array[i], plaintextlen, + exp_plaintext, plaintextlen)) + goto err; + } + + for (i = 0; i < numpipes; i++) { + OPENSSL_free(iv_array[i]); + OPENSSL_free(plaintext_array[i]); + OPENSSL_free(ciphertext_array_p[i]); + OPENSSL_free(tag_array[i]); + } + OPENSSL_free(exp_plaintext); + OPENSSL_free(ciphertext); + OPENSSL_free(tag); + } + } + + testresult = 1; + goto end; + +err: + for (i = 0; i < numpipes; i++) { + OPENSSL_free(iv_array[i]); + OPENSSL_free(plaintext_array[i]); + OPENSSL_free(ciphertext_array_p[i]); + OPENSSL_free(tag_array[i]); + } + OPENSSL_free(exp_plaintext); + OPENSSL_free(ciphertext); + OPENSSL_free(tag); +end: + EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_free(cipher); + EVP_CIPHER_free(pipeline_cipher); + fake_pipeline_finish(fake_pipeline); + return testresult; +} + int setup_tests(void) { char *config_file = NULL; @@ -6096,6 +6301,8 @@ int setup_tests(void) ADD_TEST(test_invalid_ctx_for_digest); + ADD_TEST(test_evp_cipher_pipeline); + return 1; } diff --git a/test/fake_pipelineprov.c b/test/fake_pipelineprov.c new file mode 100644 index 0000000000..4761d2fde5 --- /dev/null +++ b/test/fake_pipelineprov.c @@ -0,0 +1,344 @@ +/* + * Copyright 2020-2024 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 + */ + +/* + * This file uses the low level AES functions (which are deprecated for + * non-internal use) in order to implement provider AES ciphers. + */ +#include "internal/deprecated.h" + +#include +#include +#include +#include +#include "prov/providercommon.h" +#include "prov/ciphercommon.h" +#include "prov/ciphercommon_aead.h" +#include "testutil.h" +#include "fake_pipelineprov.h" + +/* + * This file provides a fake provider that implements a pipeline cipher + * for AES GCM. + */ + +typedef struct fake_pipeline_ctx_st { + size_t keylen; + size_t ivlen; + size_t numpipes; + EVP_CIPHER *cipher; + EVP_CIPHER_CTX *cipher_ctxs[EVP_MAX_PIPES]; +} CIPHER_PIPELINE_CTX; + +static void *fake_pipeline_newctx(void *provctx, char *ciphername, + size_t kbits, size_t ivbits) +{ + CIPHER_PIPELINE_CTX *ctx; + + if (!ossl_prov_is_running()) + return NULL; + + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (ctx == NULL) + return NULL; + + ctx->keylen = kbits / 8; + ctx->ivlen = ivbits / 8; + ctx->numpipes = 0; + ctx->cipher = EVP_CIPHER_fetch(provctx, ciphername, "provider=default"); + + return ctx; +} + +static OSSL_FUNC_cipher_freectx_fn fake_pipeline_freectx; +static void fake_pipeline_freectx(void *vctx) +{ + CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; + size_t i; + + EVP_CIPHER_free(ctx->cipher); + for (i = 0; i < ctx->numpipes; i++) + EVP_CIPHER_CTX_free(ctx->cipher_ctxs[i]); + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +OSSL_FUNC_cipher_pipeline_encrypt_init_fn fake_pipeline_einit; +OSSL_FUNC_cipher_pipeline_decrypt_init_fn fake_pipeline_dinit; +OSSL_FUNC_cipher_pipeline_update_fn fake_pipeline_update; +OSSL_FUNC_cipher_pipeline_final_fn fake_pipeline_final; +OSSL_FUNC_cipher_gettable_ctx_params_fn fake_pipeline_aead_gettable_ctx_params; +OSSL_FUNC_cipher_get_ctx_params_fn fake_pipeline_aead_get_ctx_params; +OSSL_FUNC_cipher_settable_ctx_params_fn fake_pipeline_aead_settable_ctx_params; +OSSL_FUNC_cipher_set_ctx_params_fn fake_pipeline_aead_set_ctx_params; + +static int fake_pipeline_init(void *vctx, + const unsigned char *key, size_t keylen, + size_t numpipes, const unsigned char **iv, + size_t ivlen, int enc) +{ + CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; + size_t i = 0; + + ctx->numpipes = numpipes; + for (i = 0; i < numpipes; i++) { + ctx->cipher_ctxs[i] = EVP_CIPHER_CTX_new(); + if (ctx->cipher_ctxs[i] == NULL) + return 0; + if (!EVP_CipherInit(ctx->cipher_ctxs[i], ctx->cipher, key, iv[i], enc)) + return 0; + } + + return 1; +} + +int fake_pipeline_einit(void *vctx, + const unsigned char *key, size_t keylen, + size_t numpipes, const unsigned char **iv, + size_t ivlen, const OSSL_PARAM params[]) +{ + return fake_pipeline_init(vctx, key, keylen, numpipes, iv, ivlen, 1); +} + +int fake_pipeline_dinit(void *vctx, + const unsigned char *key, size_t keylen, + size_t numpipes, const unsigned char **iv, + size_t ivlen, const OSSL_PARAM params[]) +{ + return fake_pipeline_init(vctx, key, keylen, numpipes, iv, ivlen, 0); +} + +int fake_pipeline_update(void *vctx, size_t numpipes, + unsigned char **out, size_t *outl, + const size_t *outsize, + const unsigned char **in, const size_t *inl) +{ + CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; + int ioutl, inl_; + size_t i = 0; + + for (i = 0; i < numpipes; i++) { + inl_ = (int)inl[i]; + if (!EVP_CipherUpdate(ctx->cipher_ctxs[i], + (out != NULL) ? out[i] : NULL, + &ioutl, + in[i], inl_)) + return 0; + outl[i] = (size_t)ioutl; + } + return 1; +} + +int fake_pipeline_final(void *vctx, size_t numpipes, + unsigned char **out, size_t *outl, + const size_t *outsize) +{ + CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; + int ioutl; + size_t i = 0; + + for (i = 0; i < numpipes; i++) { + if (!EVP_CipherFinal(ctx->cipher_ctxs[i], out[i], &ioutl)) + return 0; + outl[i] = (size_t)ioutl; + } + return 1; +} + +static const OSSL_PARAM fake_pipeline_aead_known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL), + OSSL_PARAM_octet_ptr(OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG, NULL, 0), + OSSL_PARAM_END +}; +const OSSL_PARAM *fake_pipeline_aead_gettable_ctx_params(ossl_unused void *cctx, + ossl_unused void *provctx) +{ + return fake_pipeline_aead_known_gettable_ctx_params; +} + +static const OSSL_PARAM fake_pipeline_aead_known_settable_ctx_params[] = { + OSSL_PARAM_octet_ptr(OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG, NULL, 0), + OSSL_PARAM_END +}; +const OSSL_PARAM *fake_pipeline_aead_settable_ctx_params(ossl_unused void *cctx, + ossl_unused void *provctx) +{ + return fake_pipeline_aead_known_settable_ctx_params; +} + +int fake_pipeline_aead_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; + OSSL_PARAM *p; + size_t taglen, i; + unsigned char **aead_tags = NULL; + OSSL_PARAM aead_params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + if (ossl_param_is_empty(params)) + return 1; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL) { + if (!OSSL_PARAM_set_size_t(p, ctx->ivlen)) { + 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) { + if (!OSSL_PARAM_set_size_t(p, ctx->keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG); + if (p != NULL) { + if (!OSSL_PARAM_get_octet_ptr(p, (const void **)&aead_tags, &taglen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + for (i = 0; i < ctx->numpipes; i++) { + aead_params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, + (void *)aead_tags[i], + taglen); + if (!EVP_CIPHER_CTX_get_params(ctx->cipher_ctxs[i], aead_params)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + } + + return 1; +} + +int fake_pipeline_aead_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; + const OSSL_PARAM *p; + size_t taglen, i; + unsigned char **aead_tags = NULL; + OSSL_PARAM aead_params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG); + if (p != NULL) { + if (!OSSL_PARAM_get_octet_ptr(p, (const void **)&aead_tags, &taglen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + for (i = 0; i < ctx->numpipes; i++) { + aead_params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, + (void *)aead_tags[i], + taglen); + if (!EVP_CIPHER_CTX_set_params(ctx->cipher_ctxs[i], aead_params)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + } + + /* No other settable ctx param */ + return 1; +} + +#define IMPLEMENT_aead_cipher_pipeline(alg, lc, UCMODE, flags, kbits, blkbits, \ + ivbits, ciphername) \ + static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \ + static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \ + { \ + return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ + flags, kbits, blkbits, ivbits); \ + } \ + static OSSL_FUNC_cipher_newctx_fn fake_pipeline_##alg##_##kbits##_##lc##_newctx; \ + static void * fake_pipeline_##alg##_##kbits##_##lc##_newctx(void *provctx) \ + { \ + return fake_pipeline_newctx(provctx, ciphername, kbits, ivbits); \ + } \ + static const OSSL_DISPATCH fake_pipeline_##alg##kbits##lc##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void))fake_pipeline_##alg##_##kbits##_##lc##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, \ + (void (*)(void))fake_pipeline_freectx }, \ + { OSSL_FUNC_CIPHER_PIPELINE_ENCRYPT_INIT, \ + (void (*)(void))fake_pipeline_einit }, \ + { OSSL_FUNC_CIPHER_PIPELINE_DECRYPT_INIT, \ + (void (*)(void))fake_pipeline_dinit }, \ + { OSSL_FUNC_CIPHER_PIPELINE_UPDATE, \ + (void (*)(void))fake_pipeline_update }, \ + { OSSL_FUNC_CIPHER_PIPELINE_FINAL, \ + (void (*)(void))fake_pipeline_final }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void)) alg##_##kbits##_##lc##_get_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void)) fake_pipeline_aead_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void)) fake_pipeline_aead_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void)) ossl_cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void)) fake_pipeline_aead_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void)) fake_pipeline_aead_settable_ctx_params }, \ + OSSL_DISPATCH_END \ + } + +IMPLEMENT_aead_cipher_pipeline(aes, gcm, GCM, AEAD_FLAGS, 256, 8, 96, "AES-256-GCM"); + +static const OSSL_ALGORITHM fake_ciphers[] = { + {"AES-256-GCM", "provider=fake-pipeline", fake_pipeline_aes256gcm_functions}, + {NULL, NULL, NULL} +}; + +static const OSSL_ALGORITHM *fake_pipeline_query(OSSL_PROVIDER *prov, + int operation_id, + int *no_cache) +{ + *no_cache = 0; + switch (operation_id) { + case OSSL_OP_CIPHER: + return fake_ciphers; + } + return NULL; +} + +/* Functions we provide to the core */ +static const OSSL_DISPATCH fake_pipeline_method[] = { + { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OSSL_LIB_CTX_free }, + { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fake_pipeline_query }, + OSSL_DISPATCH_END +}; + +static int fake_pipeline_provider_init(const OSSL_CORE_HANDLE *handle, + const OSSL_DISPATCH *in, + const OSSL_DISPATCH **out, void **provctx) +{ + if (!TEST_ptr(*provctx = OSSL_LIB_CTX_new())) + return 0; + *out = fake_pipeline_method; + return 1; +} + +OSSL_PROVIDER *fake_pipeline_start(OSSL_LIB_CTX *libctx) +{ + OSSL_PROVIDER *p; + + if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, "fake-pipeline", + fake_pipeline_provider_init)) + || !TEST_ptr(p = OSSL_PROVIDER_try_load(libctx, "fake-pipeline", 1))) + return NULL; + + return p; +} + +void fake_pipeline_finish(OSSL_PROVIDER *p) +{ + OSSL_PROVIDER_unload(p); +} diff --git a/test/fake_pipelineprov.h b/test/fake_pipelineprov.h new file mode 100644 index 0000000000..10a20c62bd --- /dev/null +++ b/test/fake_pipelineprov.h @@ -0,0 +1,14 @@ +/* + * Copyright 2020-2024 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 + */ + +#include + +/* Fake pipeline provider implementation */ +OSSL_PROVIDER *fake_pipeline_start(OSSL_LIB_CTX *libctx); +void fake_pipeline_finish(OSSL_PROVIDER *p);