From: Dmitry Belyavskiy Date: Fri, 8 Nov 2024 13:14:33 +0000 (+0100) Subject: EVP_SKEY tests X-Git-Tag: openssl-3.5.0-alpha1~487 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9422ab6a7e354510a049a7adcbad3b1e4b2e04fc;p=thirdparty%2Fopenssl.git EVP_SKEY tests Signed-off-by: Dmitry Belyavskiy Signed-off-by: Simo Sorce Reviewed-by: Tomas Mraz Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/26753) --- diff --git a/test/build.info b/test/build.info index 30b3c42ff02..e14809f4b20 100644 --- a/test/build.info +++ b/test/build.info @@ -1144,6 +1144,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 00000000000..2a413b1c47a --- /dev/null +++ b/test/evp_skey_test.c @@ -0,0 +1,108 @@ +/* + * 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 OSSL_PROVIDER *deflprov = NULL; + +#define KEY_SIZE 16 + +static OSSL_CALLBACK ossl_pkey_todata_cb; + +static int ossl_pkey_todata_cb(const OSSL_PARAM params[], void *arg) +{ + OSSL_PARAM **ret = arg; + + *ret = OSSL_PARAM_dup(params); + return 1; +} + +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 unsigned char import_key[KEY_SIZE] = { + 0x53, 0x4B, 0x45, 0x59, 0x53, 0x4B, 0x45, 0x59, + 0x53, 0x4B, 0x45, 0x59, 0x53, 0x4B, 0x45, 0x59, + }; + OSSL_PARAM params[3]; + OSSL_PARAM *export_params = NULL; + const unsigned char *export; + size_t export_len; + + 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 */ + params[0] = OSSL_PARAM_construct_utf8_string(FAKE_CIPHER_PARAM_KEY_NAME, + "fake key name", 0); + params[1] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES, + (void *)import_key, KEY_SIZE); + params[2] = OSSL_PARAM_construct_end(); + key = EVP_SKEY_import(libctx, "fake_cipher", FAKE_CIPHER_FETCH_PROPS, + OSSL_SKEYMGMT_SELECT_ALL, params); + if (!TEST_ptr(key)) + goto end; + + /* Init cipher */ + if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()) + || !TEST_int_gt(EVP_CipherInit_SKEY(ctx, fake_cipher, key, NULL, 0, 1, NULL), 0)) + goto end; + + /* Export params */ + if (!TEST_int_gt(EVP_SKEY_export(key, OSSL_SKEYMGMT_SELECT_ALL, + ossl_pkey_todata_cb, &export_params), 0)) + goto end; + + /* Export raw key */ + if (!TEST_int_gt(EVP_SKEY_get_raw_key(key, &export, &export_len), 0) + || !TEST_mem_eq(export, export_len, import_key, sizeof(import_key))) + goto end; + + ret = 1; + +end: + OSSL_PARAM_free(export_params); + 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 00000000000..c9c038b17b3 --- /dev/null +++ b/test/fake_cipherprov.c @@ -0,0 +1,321 @@ +/* + * 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 +#include "testutil.h" +#include "fake_cipherprov.h" + +#define MAX_KEYNAME 32 +#define FAKE_KEY_LEN 16 + +typedef struct prov_cipher_fake_ctx_st { + char key_name[MAX_KEYNAME]; + unsigned char key[FAKE_KEY_LEN]; +} 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; + + memset(key_name, 0, MAX_KEYNAME); + + p = OSSL_PARAM_locate_const(params, FAKE_CIPHER_PARAM_KEY_NAME); + if (p != NULL) { + if (!OSSL_PARAM_get_utf8_string(p, &pval, sizeof(key_name))) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + + memcpy(pctx->key_name, key_name, sizeof(key_name)); + } + + p = OSSL_PARAM_locate_const(params, OSSL_SKEY_PARAM_RAW_BYTES); + if (p != NULL) { + size_t data_size = p->data_size; + + if (data_size > FAKE_KEY_LEN) + data_size = FAKE_KEY_LEN; + memcpy(pctx->key, p->data, data_size); + } + + return 1; +} + +static void fake_skeymgmt_free(void *keydata) +{ + OPENSSL_free(keydata); +} + +static void *fake_skeymgmt_import(void *provctx, int selection, const OSSL_PARAM *p) +{ + PROV_CIPHER_FAKE_CTX *ctx = NULL; + + if (!TEST_ptr(ctx = OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX)))) + return 0; + + if (ctx_from_key_params(ctx, p) != 1) { + OPENSSL_free(ctx); + return NULL; + } + + return ctx; +} + +static int fake_skeymgmt_export(void *keydata, int selection, + OSSL_CALLBACK *param_callback, void *cbarg) +{ + OSSL_PARAM params[3]; + PROV_CIPHER_FAKE_CTX *ctx = (PROV_CIPHER_FAKE_CTX *)keydata; + OSSL_PARAM *p = params; + + if (selection & OSSL_SKEYMGMT_SELECT_PARAMETERS) { + *p = OSSL_PARAM_construct_utf8_string(FAKE_CIPHER_PARAM_KEY_NAME, + ctx->key_name, + strlen(ctx->key_name)); + p++; + } + + if (selection & OSSL_SKEYMGMT_SELECT_SECRET_KEY) { + *p = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES, + ctx->key, + sizeof(ctx->key)); + p++; + } + *p = OSSL_PARAM_construct_end(); + + return param_callback(params, cbarg); +} + +static const OSSL_DISPATCH fake_skeymgmt_funcs[] = { + { OSSL_FUNC_SKEYMGMT_FREE, (void (*)(void))fake_skeymgmt_free }, + { OSSL_FUNC_SKEYMGMT_IMPORT, (void (*)(void))fake_skeymgmt_import }, + { OSSL_FUNC_SKEYMGMT_EXPORT, (void (*)(void))fake_skeymgmt_export }, + OSSL_DISPATCH_END +}; + +static const OSSL_ALGORITHM fake_skeymgmt_algs[] = { + { "fake_cipher", FAKE_CIPHER_FETCH_PROPS, fake_skeymgmt_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_skey_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_skey_init_fn fake_skey_einit; +static int fake_skey_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_skey_init(ctx, pkeyparam, iv, ivlen, params) != 1) + return 0; + + return 1; +} + +static OSSL_FUNC_cipher_decrypt_skey_init_fn fake_skey_dinit; +static int fake_skey_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_skey_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[i % FAKE_KEY_LEN]; + *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_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; + } + 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_BLOCK_SIZE, 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, sizeof((PROV_CIPHER_FAKE_CTX *)vctx)->key)) { + 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_SETTABLE_CTX_PARAMS, + (void (*)(void)) fake_settable_ctx_params }, + { OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT, (void (*)(void)) fake_skey_einit }, + { OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT, (void (*)(void)) fake_skey_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_SKEYMGMT: + return fake_skeymgmt_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 00000000000..967bde28da8 --- /dev/null +++ b/test/fake_cipherprov.h @@ -0,0 +1,19 @@ +/* + * 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 cipher 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" diff --git a/test/recipes/30-test_evp_skey.t b/test/recipes/30-test_evp_skey.t new file mode 100644 index 00000000000..b535b28849d --- /dev/null +++ b/test/recipes/30-test_evp_skey.t @@ -0,0 +1,13 @@ +#! /usr/bin/env perl +# Copyright 2025 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");