]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
EVP_SKEY tests
authorDmitry Belyavskiy <beldmit@gmail.com>
Fri, 8 Nov 2024 13:14:33 +0000 (14:14 +0100)
committerDmitry Belyavskiy <beldmit@gmail.com>
Sat, 15 Feb 2025 17:51:30 +0000 (18:51 +0100)
Signed-off-by: Dmitry Belyavskiy <beldmit@gmail.com>
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26753)

test/build.info
test/evp_skey_test.c [new file with mode: 0644]
test/fake_cipherprov.c [new file with mode: 0644]
test/fake_cipherprov.h [new file with mode: 0644]
test/recipes/30-test_evp_skey.t [new file with mode: 0644]

index 30b3c42ff025958959ec1b836f97059798c2b1e1..e14809f4b209659b9ce8ffed52912c2959bba442 100644 (file)
@@ -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 (file)
index 0000000..2a413b1
--- /dev/null
@@ -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 <openssl/provider.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#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 (file)
index 0000000..c9c038b
--- /dev/null
@@ -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 <string.h>
+#include <openssl/core_names.h>
+#include <openssl/core_object.h>
+#include <openssl/rand.h>
+#include <openssl/provider.h>
+#include <openssl/proverr.h>
+#include <openssl/param_build.h>
+#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 (file)
index 0000000..967bde2
--- /dev/null
@@ -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 <openssl/core_dispatch.h>
+
+/* 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 (file)
index 0000000..b535b28
--- /dev/null
@@ -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");