From a9c5a713dbc5ba02ae904fdeb604abc914948928 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 8 Nov 2024 14:14:33 +0100 Subject: [PATCH] EVP_SKEY tests --- test/build.info | 5 + test/evp_skey_test.c | 75 +++++++ test/fake_cipherprov.c | 375 ++++++++++++++++++++++++++++++++ test/fake_cipherprov.h | 20 ++ test/recipes/30-test_evp_skey.t | 13 ++ 5 files changed, 488 insertions(+) create mode 100644 test/evp_skey_test.c create mode 100644 test/fake_cipherprov.c create mode 100644 test/fake_cipherprov.h create mode 100644 test/recipes/30-test_evp_skey.t diff --git a/test/build.info b/test/build.info index 51ff81d5730b5..908cb51d74ec6 100644 --- a/test/build.info +++ b/test/build.info @@ -1114,6 +1114,11 @@ IF[{- !$disabled{tests} -}] INCLUDE[provider_pkey_test]=../include ../apps/include DEPEND[provider_pkey_test]=../libcrypto libtestutil.a + PROGRAMS{noinst}=evp_skey_test + SOURCE[evp_skey_test]=evp_skey_test.c fake_cipherprov.c + INCLUDE[evp_skey_test]=../include ../apps/include + DEPEND[evp_skey_test]=../libcrypto libtestutil.a + PROGRAMS{noinst}=provider_default_search_path_test SOURCE[provider_default_search_path_test]=provider_default_search_path_test.c INCLUDE[provider_default_search_path_test]=../include ../apps/include diff --git a/test/evp_skey_test.c b/test/evp_skey_test.c new file mode 100644 index 0000000000000..d38640fad81c4 --- /dev/null +++ b/test/evp_skey_test.c @@ -0,0 +1,75 @@ +/* + * Copyright 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 +#include +#include +#include +#include "testutil.h" +#include "fake_cipherprov.h" + +static OSSL_LIB_CTX *libctx = NULL; + +static int test_skey_cipher(void) +{ + int ret = 0; + OSSL_PROVIDER *fake_prov = NULL; + EVP_SKEY *key = NULL; + EVP_CIPHER *fake_cipher = NULL; + EVP_CIPHER_CTX *ctx = NULL; + const OSSL_PARAM params[] = {{FAKE_CIPHER_PARAM_KEY_NAME, OSSL_PARAM_UTF8_STRING, "fake key name", 14, 0}, OSSL_PARAM_END}; + + if (!TEST_ptr(fake_prov = fake_cipher_start(libctx))) + return 0; + + /* Do a direct fetch to see it works */ + fake_cipher = EVP_CIPHER_fetch(libctx, "fake_cipher", FAKE_CIPHER_FETCH_PROPS); + if (!TEST_ptr(fake_cipher)) + goto end; + + /* Create EVP_SKEY*/ + key = EVP_SKEY_new(libctx, "fake_cipher", FAKE_CIPHER_FETCH_PROPS); + if (!TEST_ptr(key)) + goto end; + + /* Import params */ + if(!TEST_int_gt(EVP_SKEY_import(key, params), 0)) + goto end; + + /* Init cipher */ + if(!TEST_ptr(ctx = EVP_CIPHER_CTX_new()) + || !TEST_int_gt(EVP_CipherInit_skey(ctx, fake_cipher, key, NULL, 1, NULL), 0)) + goto end; + + ret = 1; + +end: + EVP_SKEY_free(key); + EVP_CIPHER_free(fake_cipher); + EVP_CIPHER_CTX_free(ctx); + fake_cipher_finish(fake_prov); + + return ret; +} + +int setup_tests(void) +{ + libctx = OSSL_LIB_CTX_new(); + if (libctx == NULL) + return 0; + + ADD_TEST(test_skey_cipher); + + return 1; +} + +void cleanup_tests(void) +{ + OSSL_LIB_CTX_free(libctx); +} diff --git a/test/fake_cipherprov.c b/test/fake_cipherprov.c new file mode 100644 index 0000000000000..5d4a9b6c027f2 --- /dev/null +++ b/test/fake_cipherprov.c @@ -0,0 +1,375 @@ +/* + * Copyright 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 may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +#include +#include +#include +#include +#include +#include +#include "testutil.h" +#include "fake_cipherprov.h" + +#define MAX_KEYNAME 32 + +typedef struct prov_cipher_fake_ctx_st { + char key_name[MAX_KEYNAME]; + unsigned char key; +} PROV_CIPHER_FAKE_CTX; + + +static int ctx_from_key_params(PROV_CIPHER_FAKE_CTX *pctx, const OSSL_PARAM *params) +{ + const OSSL_PARAM *p; + char key_name[MAX_KEYNAME]; + char *pval = key_name; + size_t i; + + memset(key_name, 0, MAX_KEYNAME); + + p = OSSL_PARAM_locate_const(params, FAKE_CIPHER_PARAM_KEY_NAME); + if (p != NULL && !OSSL_PARAM_get_utf8_string(p, &pval, MAX_KEYNAME)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + + memcpy(pctx->key_name, key_name, MAX_KEYNAME); + pctx->key = 0; + + for (i = 0; i < MAX_KEYNAME; i++) + pctx->key ^= pctx->key_name[i]; + + return 1; +} + + +static void *fake_keymgmt_new(void *provctx) +{ + PROV_CIPHER_FAKE_CTX *ctx; + + if (!TEST_ptr(ctx = OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX)))) + return NULL; + + return ctx; +} + +static void fake_keymgmt_free(void *keydata) +{ + OPENSSL_free(keydata); +} + +static int fake_keymgmt_import(void *keydata, int selection, + const OSSL_PARAM *p) +{ + PROV_CIPHER_FAKE_CTX *ctx = (PROV_CIPHER_FAKE_CTX *)keydata; + return ctx_from_key_params(ctx, p); +} + +static int fake_keymgmt_export(void *keydata, int selection, + OSSL_CALLBACK *param_callback, void *cbarg) +{ + OSSL_PARAM *params = NULL; + int ret; + + /* FIXME */ + + ret = param_callback(params, cbarg); + OSSL_PARAM_free(params); + return ret; +} + +static int fake_keymgmt_has(const void *key, int selection) +{ + return 1; +} + +static const OSSL_PARAM fake_import_key_types[] = { + OSSL_PARAM_utf8_string(FAKE_CIPHER_PARAM_KEY_NAME, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *fake_keymgmt_imptypes(int selection) +{ + return fake_import_key_types; +} + +static const OSSL_PARAM fake_export_key_types[] = { + OSSL_PARAM_utf8_string(FAKE_CIPHER_PARAM_KEY_NAME, NULL, 0), + OSSL_PARAM_int(FAKE_CIPHER_PARAM_RAW_KEY, NULL), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *fake_keymgmt_exptypes(int selection) +{ + return fake_export_key_types; +} + +static const OSSL_DISPATCH fake_keymgmt_funcs[] = { + { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))fake_keymgmt_new }, + { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))fake_keymgmt_free} , + { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))fake_keymgmt_has}, + { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))fake_keymgmt_import }, + { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, + (void (*)(void))fake_keymgmt_imptypes }, + { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))fake_keymgmt_export }, + { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, + (void (*)(void))fake_keymgmt_exptypes }, + OSSL_DISPATCH_END +}; + +static const OSSL_ALGORITHM fake_keymgmt_algs[] = { + { "fake_cipher", FAKE_CIPHER_FETCH_PROPS, fake_keymgmt_funcs, "Fake Cipher Key Management" }, + { NULL, NULL, NULL, NULL } +}; +static OSSL_FUNC_cipher_newctx_fn fake_newctx; +static void *fake_newctx(void *provctx) +{ + return OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX)); +} + +static OSSL_FUNC_cipher_freectx_fn fake_freectx; +static void fake_freectx(void *vctx) +{ + OPENSSL_free(vctx); +} + +static int fake_opaque_init(PROV_CIPHER_FAKE_CTX *ctx, void *pkeyparam, + const unsigned char *iv, size_t ivlen, + const OSSL_PARAM params[]) +{ + if (pkeyparam != NULL) { + memcpy(ctx, pkeyparam, sizeof(PROV_CIPHER_FAKE_CTX)); + } + return 1; +} + +static OSSL_FUNC_cipher_encrypt_opaque_init_fn fake_opaque_einit; +static int fake_opaque_einit(void *vctx, void *pkeyparam, + const unsigned char *iv, size_t ivlen, + const OSSL_PARAM params[]) +{ + PROV_CIPHER_FAKE_CTX *ctx = (PROV_CIPHER_FAKE_CTX *)vctx; + if (fake_opaque_init(ctx, pkeyparam, iv, ivlen, params) != 1) + return 0; + + return 1; +} + +static OSSL_FUNC_cipher_decrypt_opaque_init_fn fake_opaque_dinit; +static int fake_opaque_dinit(void *vctx, void *pkeyparam, + const unsigned char *iv, size_t ivlen, + const OSSL_PARAM params[]) +{ + PROV_CIPHER_FAKE_CTX *ctx = (PROV_CIPHER_FAKE_CTX *)vctx; + if (fake_opaque_init(ctx, pkeyparam, iv, ivlen, params) != 1) + return 0; + + return 1; +} + +static OSSL_FUNC_cipher_cipher_fn fake_cipher; +static int fake_cipher(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, size_t inl) +{ + PROV_CIPHER_FAKE_CTX *ctx = (PROV_CIPHER_FAKE_CTX *)vctx; + size_t i; + + if (outsize < inl) + return 0; + if (out != NULL && in != out) + memcpy(out, in, inl); + for (i=0; i < inl; i++) + out[i] ^= ctx->key; + *outl = inl; + return 1; +} + +static OSSL_FUNC_cipher_final_fn fake_final; +static int fake_final(void *vctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + *outl = 0; + return 1; +} + +static OSSL_FUNC_cipher_get_params_fn fake_get_params; +static int fake_get_params(OSSL_PARAM params[]) +{ + /* FIXME copy of ossl_cipher_generic_get_params */ + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); + if (p != NULL && !OSSL_PARAM_set_uint(p, EVP_CIPH_ECB_MODE)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD); + if (p != NULL + && !OSSL_PARAM_set_int(p, 0)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_CUSTOM_IV); + if (p != NULL + && !OSSL_PARAM_set_int(p, 0)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_CTS); + if (p != NULL + && !OSSL_PARAM_set_int(p, 0)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK); + if (p != NULL + && !OSSL_PARAM_set_int(p, 0)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_HAS_RAND_KEY); + if (p != NULL + && !OSSL_PARAM_set_int(p, 0)) { + 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, 1)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE); + if (p != NULL && !OSSL_PARAM_set_size_t(p, 1)) { + 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, 0)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + return 1; +} + +static const OSSL_PARAM fake_known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), + OSSL_PARAM_END +}; + +static OSSL_FUNC_cipher_gettable_ctx_params_fn fake_gettable_ctx_params; +static const OSSL_PARAM *fake_gettable_ctx_params(ossl_unused void *cctx, + ossl_unused void *provctx) +{ + return fake_known_gettable_ctx_params; +} + +static OSSL_FUNC_cipher_get_ctx_params_fn fake_get_ctx_params; +static int fake_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, 0)) { + 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, 1)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + return 1; +} + +static const OSSL_PARAM fake_known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(FAKE_CIPHER_PARAM_KEY_NAME, NULL, 0), + OSSL_PARAM_END +}; + +static OSSL_FUNC_cipher_settable_ctx_params_fn fake_settable_ctx_params; +static const OSSL_PARAM *fake_settable_ctx_params(ossl_unused void *cctx, + ossl_unused void *provctx) +{ + return fake_known_settable_ctx_params; +} + +static const OSSL_DISPATCH ossl_fake_functions[] = { + { OSSL_FUNC_CIPHER_NEWCTX, + (void (*)(void)) fake_newctx }, + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) fake_freectx }, + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) fake_newctx }, + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))fake_cipher }, + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))fake_final }, + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))fake_cipher }, + { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void)) fake_get_params }, + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))fake_get_ctx_params }, + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, + (void (*)(void))fake_gettable_ctx_params }, +/* { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))fake_set_ctx_params }, */ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, + (void (*)(void))fake_settable_ctx_params }, + { OSSL_FUNC_CIPHER_ENCRYPT_OPAQUE_INIT, (void (*)(void))fake_opaque_einit }, + { OSSL_FUNC_CIPHER_DECRYPT_OPAQUE_INIT, (void (*)(void))fake_opaque_dinit }, + OSSL_DISPATCH_END +}; + +static const OSSL_ALGORITHM fake_cipher_algs[] = { + { "fake_cipher", FAKE_CIPHER_FETCH_PROPS, ossl_fake_functions}, + { NULL, NULL, NULL } +}; + +static const OSSL_ALGORITHM *fake_cipher_query(void *provctx, + int operation_id, + int *no_cache) +{ + *no_cache = 0; + switch (operation_id) { + case OSSL_OP_CIPHER: + return fake_cipher_algs; + case OSSL_OP_KEYMGMT: + return fake_keymgmt_algs; + } + return NULL; +} + +/* Functions we provide to the core */ +static const OSSL_DISPATCH fake_cipher_method[] = { + { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OSSL_LIB_CTX_free }, + { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fake_cipher_query }, + OSSL_DISPATCH_END +}; + +static int fake_cipher_provider_init(const OSSL_CORE_HANDLE *handle, + const OSSL_DISPATCH *in, + const OSSL_DISPATCH **out, void **provctx) +{ + if (!TEST_ptr(*provctx = OSSL_LIB_CTX_new())) + return 0; + *out = fake_cipher_method; + return 1; +} + +OSSL_PROVIDER *fake_cipher_start(OSSL_LIB_CTX *libctx) +{ + OSSL_PROVIDER *p; + + if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, FAKE_PROV_NAME, + fake_cipher_provider_init)) + || !TEST_ptr(p = OSSL_PROVIDER_try_load(libctx, FAKE_PROV_NAME, 1))) + return NULL; + + return p; +} + +void fake_cipher_finish(OSSL_PROVIDER *p) +{ + OSSL_PROVIDER_unload(p); +} diff --git a/test/fake_cipherprov.h b/test/fake_cipherprov.h new file mode 100644 index 0000000000000..22f474167ab0f --- /dev/null +++ b/test/fake_cipherprov.h @@ -0,0 +1,20 @@ +/* + * Copyright 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 RSA provider implementation */ +OSSL_PROVIDER *fake_cipher_start(OSSL_LIB_CTX *libctx); +void fake_cipher_finish(OSSL_PROVIDER *p); + +# define FAKE_PROV_NAME "fake-cipher" +# define FAKE_CIPHER_FETCH_PROPS "provider=fake-cipher" + +# define FAKE_CIPHER_PARAM_KEY_NAME "key_name" +# define FAKE_CIPHER_PARAM_RAW_KEY "raw_key" diff --git a/test/recipes/30-test_evp_skey.t b/test/recipes/30-test_evp_skey.t new file mode 100644 index 0000000000000..c44b8489af669 --- /dev/null +++ b/test/recipes/30-test_evp_skey.t @@ -0,0 +1,13 @@ +#! /usr/bin/env perl +# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright (c) 2018, Oracle and/or its affiliates. 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 + + +use OpenSSL::Test::Simple; + +simple_test("test_evp_skey", "evp_skey_test");