]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add generic secret skeymgmt provider, skey abstraction and default skeymgmt
authorSimo Sorce <simo@redhat.com>
Tue, 28 Jan 2025 16:19:28 +0000 (11:19 -0500)
committerDmitry Belyavskiy <beldmit@gmail.com>
Sat, 15 Feb 2025 17:51:30 +0000 (18:51 +0100)
This commits adds an actual skey wrapper structure and skeymgmt
implementation for the default provider

This allows to use fallbacks for any SKEY operation,
and to use it for keys that do not have a specific purpose and
cipher-suite associated to it.

Add a test with a key type that does not have skey support (DES),
to show that the fallback works.

Add raw skey test

Signed-off-by: Simo Sorce <simo@redhat.com>
Signed-off-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/26753)

13 files changed:
include/crypto/types.h
include/internal/skey.h [new file with mode: 0644]
providers/defltprov.c
providers/implementations/build.info
providers/implementations/ciphers/ciphercommon.c
providers/implementations/include/prov/ciphercommon.h
providers/implementations/include/prov/implementations.h
providers/implementations/include/prov/names.h
providers/implementations/skeymgmt/aes_skmgmt.c [new file with mode: 0644]
providers/implementations/skeymgmt/build.info [new file with mode: 0644]
providers/implementations/skeymgmt/generic.c [new file with mode: 0644]
providers/implementations/skeymgmt/skeymgmt_lcl.h [new file with mode: 0644]
test/evp_skey_test.c

index ad17f052e45f5047ad498fa1c55538ee33bc93c4..43f04fd5eab32bb9f57c07963170af66fb0a93b6 100644 (file)
@@ -29,4 +29,6 @@ typedef struct dsa_st DSA;
 typedef struct ecx_key_st ECX_KEY;
 # endif
 
+typedef struct prov_skey_st PROV_SKEY;
+
 #endif
diff --git a/include/internal/skey.h b/include/internal/skey.h
new file mode 100644 (file)
index 0000000..6d0c643
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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
+ */
+
+#ifndef OSSL_CRYPTO_SKEY_H
+# define OSSL_CRYPTO_SKEY_H
+
+/* Known symmetric key type definitions */
+# define SKEY_TYPE_GENERIC 1 /* generic bytes container unknown key types */
+# define SKEY_TYPE_AES 2 /* AES keys */
+
+struct prov_skey_st {
+    /*
+     * Internal skey implementation,
+     * A symmetric key is basically just a buffer of bytes of
+     * defined length, and a type, that defines, what
+     * cryptosystem the key is meant for (AES, HMAC, etc...)
+     */
+    OSSL_LIB_CTX *libctx;
+
+    int type;
+
+    unsigned char *data;
+    size_t length;
+};
+
+#endif /* OSSL_CRYPTO_SKEY_H */
index f8b6cb4d349b9b3e32cf557a508ffc77952e474a..450a53a610ca1709110dec53f3eeb6846c4648f0 100644 (file)
@@ -580,6 +580,14 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
     { NULL, NULL, NULL }
 };
 
+static const OSSL_ALGORITHM deflt_skeymgmt[] = {
+    { PROV_NAMES_AES, "provider=default", ossl_aes_skeymgmt_functions,
+      PROV_DESCS_AES },
+    { PROV_NAMES_GENERIC, "provider=default", ossl_generic_skeymgmt_functions,
+      PROV_DESCS_GENERIC },
+    { NULL, NULL, NULL }
+};
+
 static const OSSL_ALGORITHM deflt_encoder[] = {
 #define ENCODER_PROVIDER "default"
 #include "encoders.inc"
@@ -634,6 +642,8 @@ static const OSSL_ALGORITHM *deflt_query(void *provctx, int operation_id,
         return deflt_decoder;
     case OSSL_OP_STORE:
         return deflt_store;
+    case OSSL_OP_SKEYMGMT:
+        return deflt_skeymgmt;
     }
     return NULL;
 }
index a2f60653e2c285a70990e8e7f3077658593fc355..5cf054f5f32b03193ce2d9a6c821d7692cdd90ef 100644 (file)
@@ -1,2 +1,2 @@
 SUBDIRS=digests ciphers rands macs kdfs exchange keymgmt signature asymciphers \
-        encode_decode storemgmt kem
+        encode_decode storemgmt kem skeymgmt
index d29c6c298d399fdcbe16caa7ccb4f6981060e946..57496c07ad046053755f67771875f313fff91621 100644 (file)
@@ -17,6 +17,8 @@
 #include "ciphercommon_local.h"
 #include "prov/provider_ctx.h"
 #include "prov/providercommon.h"
+#include "internal/skey.h"
+#include "crypto/types.h"
 
 /*-
  * Generic cipher functions for OSSL_PARAM gettables and settables
@@ -242,6 +244,28 @@ int ossl_cipher_generic_dinit(void *vctx, const unsigned char *key,
                                         iv, ivlen, params, 0);
 }
 
+int ossl_cipher_generic_skey_einit(void *vctx, void *skeydata,
+                                   const unsigned char *iv, size_t ivlen,
+                                   const OSSL_PARAM params[])
+{
+    PROV_SKEY *key = skeydata;
+
+    return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx,
+                                        key->data, key->length,
+                                        iv, ivlen, params, 1);
+}
+
+int ossl_cipher_generic_skey_dinit(void *vctx, void *skeydata,
+                                   const unsigned char *iv, size_t ivlen,
+                                   const OSSL_PARAM params[])
+{
+    PROV_SKEY *key = skeydata;
+
+    return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx,
+                                        key->data, key->length,
+                                        iv, ivlen, params, 0);
+}
+
 /* Max padding including padding length byte */
 #define MAX_PADDING 256
 
index 45002ad594a00460e28321e6cfe90cee063e4f64..66918ac7885e154d0c75fdabd6ced5d159b63faa 100644 (file)
@@ -122,6 +122,8 @@ OSSL_FUNC_cipher_set_ctx_params_fn ossl_cipher_var_keylen_set_ctx_params;
 OSSL_FUNC_cipher_settable_ctx_params_fn ossl_cipher_var_keylen_settable_ctx_params;
 OSSL_FUNC_cipher_gettable_ctx_params_fn ossl_cipher_aead_gettable_ctx_params;
 OSSL_FUNC_cipher_settable_ctx_params_fn ossl_cipher_aead_settable_ctx_params;
+OSSL_FUNC_cipher_encrypt_skey_init_fn ossl_cipher_generic_skey_einit;
+OSSL_FUNC_cipher_decrypt_skey_init_fn ossl_cipher_generic_skey_dinit;
 
 int ossl_cipher_generic_get_params(OSSL_PARAM params[], unsigned int md,
                                    uint64_t flags,
@@ -155,6 +157,8 @@ const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = {                \
       (void (*)(void))ossl_cipher_generic_gettable_ctx_params },               \
     { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                    \
      (void (*)(void))ossl_cipher_generic_settable_ctx_params },                \
+    { OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT, (void (*)(void))ossl_cipher_generic_skey_einit },\
+    { OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT, (void (*)(void))ossl_cipher_generic_skey_dinit },\
     OSSL_DISPATCH_END                                                          \
 };
 
@@ -182,6 +186,8 @@ const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = {                \
       (void (*)(void))ossl_cipher_generic_gettable_ctx_params },               \
     { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                    \
      (void (*)(void))ossl_cipher_var_keylen_settable_ctx_params },             \
+    { OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT, (void (*)(void))ossl_cipher_generic_skey_einit },\
+    { OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT, (void (*)(void))ossl_cipher_generic_skey_dinit },\
     OSSL_DISPATCH_END                                                          \
 };
 
index 06d1b3304a7fc67040b8b1b9e51fc3404499620d..1dace9738d874063df7e4e8471a6e4281fb6d7de 100644 (file)
@@ -690,3 +690,6 @@ extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_ml_dsa_65_decoder_fu
 
 extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_ml_dsa_87_decoder_functions[];
 extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_ml_dsa_87_decoder_functions[];
+
+extern const OSSL_DISPATCH ossl_generic_skeymgmt_functions[];
+extern const OSSL_DISPATCH ossl_aes_skeymgmt_functions[];
index 9fc31947776b51f57d9789be32c55fa6444953c0..f14cdb1d353074a4902175a21d3b5c2a168d683e 100644 (file)
  * Symmetric ciphers
  * -----------------
  */
+#define PROV_NAMES_AES "AES:2.16.840.1.101.3.4.1"
+#define PROV_DESCS_AES "OpenSSL AES opaque secret key"
+#define PROV_NAMES_GENERIC "GENERIC-SECRET"
+#define PROV_DESCS_GENERIC "OpenSSL generic opaque secret key"
+
 #define PROV_NAMES_AES_256_ECB "AES-256-ECB:2.16.840.1.101.3.4.1.41"
 #define PROV_NAMES_AES_192_ECB "AES-192-ECB:2.16.840.1.101.3.4.1.21"
 #define PROV_NAMES_AES_128_ECB "AES-128-ECB:2.16.840.1.101.3.4.1.1"
diff --git a/providers/implementations/skeymgmt/aes_skmgmt.c b/providers/implementations/skeymgmt/aes_skmgmt.c
new file mode 100644 (file)
index 0000000..6d3b5f3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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
+ */
+
+#include <openssl/core_dispatch.h>
+#include "crypto/types.h"
+#include "skeymgmt_lcl.h"
+#include "internal/skey.h"
+#include "prov/implementations.h"
+
+static OSSL_FUNC_skeymgmt_import_fn aes_import;
+static OSSL_FUNC_skeymgmt_export_fn aes_export;
+
+static void *aes_import(void *provctx, int selection,
+                        const OSSL_PARAM params[])
+{
+    PROV_SKEY *aes = generic_import(provctx, selection, params);
+
+    if (aes == NULL)
+        return NULL;
+
+    if (aes->length != 16 && aes->length != 24 && aes->length != 32) {
+        generic_free(aes);
+        return NULL;
+    }
+    aes->type = SKEY_TYPE_AES;
+
+    return aes;
+}
+
+static int aes_export(void *keydata, int selection,
+                      OSSL_CALLBACK *param_callback, void *cbarg)
+{
+    PROV_SKEY *aes = keydata;
+
+    if (aes->type != SKEY_TYPE_AES)
+        return 0;
+
+    return generic_export(keydata, selection, param_callback, cbarg);
+}
+
+const OSSL_DISPATCH ossl_aes_skeymgmt_functions[] = {
+    { OSSL_FUNC_SKEYMGMT_FREE, (void (*)(void))generic_free },
+    { OSSL_FUNC_SKEYMGMT_IMPORT, (void (*)(void))aes_import },
+    { OSSL_FUNC_SKEYMGMT_EXPORT, (void (*)(void))aes_export },
+    OSSL_DISPATCH_END
+};
diff --git a/providers/implementations/skeymgmt/build.info b/providers/implementations/skeymgmt/build.info
new file mode 100644 (file)
index 0000000..8bccdd7
--- /dev/null
@@ -0,0 +1,8 @@
+# We make separate GOAL variables for each algorithm, to make it easy to
+# switch each to the Legacy provider when needed.
+
+$AES_GOAL=../../libdefault.a ../../libfips.a
+$GENERIC_GOAL=../../libdefault.a ../../libfips.a
+
+SOURCE[$AES_GOAL]=aes_skmgmt.c
+SOURCE[$GENERIC_GOAL]=generic.c
diff --git a/providers/implementations/skeymgmt/generic.c b/providers/implementations/skeymgmt/generic.c
new file mode 100644 (file)
index 0000000..1333835
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include "crypto/types.h"
+#include "internal/skey.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "skeymgmt_lcl.h"
+
+void generic_free(void *keydata)
+{
+    PROV_SKEY *generic = keydata;
+
+    if (generic == NULL)
+        return;
+
+    OPENSSL_free(generic->data);
+    OPENSSL_free(generic);
+}
+
+void *generic_import(void *provctx, int selection, const OSSL_PARAM params[])
+{
+    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
+    const OSSL_PARAM *raw_bytes;
+    PROV_SKEY *generic = NULL;
+    int ok = 0;
+
+    if (!ossl_prov_is_running())
+        return NULL;
+
+    if ((selection & OSSL_SKEYMGMT_SELECT_SECRET_KEY) == 0)
+        return NULL;
+
+    raw_bytes = OSSL_PARAM_locate_const(params, OSSL_SKEY_PARAM_RAW_BYTES);
+    if (raw_bytes == NULL)
+        return NULL;
+
+    generic = OPENSSL_zalloc(sizeof(PROV_SKEY));
+    generic->libctx = libctx;
+
+    generic->type = SKEY_TYPE_GENERIC;
+
+    if ((generic->data = OPENSSL_memdup(raw_bytes->data, raw_bytes->data_size)) == NULL)
+        goto end;
+    generic->length = raw_bytes->data_size;
+    ok = 1;
+
+end:
+    if (ok == 0) {
+        generic_free(generic);
+        generic = NULL;
+    }
+    return generic;
+}
+
+int generic_export(void *keydata, int selection,
+                   OSSL_CALLBACK *param_callback, void *cbarg)
+{
+    PROV_SKEY *gen = keydata;
+    OSSL_PARAM params[2];
+
+    if (!ossl_prov_is_running() || gen == NULL)
+        return 0;
+
+    /* If we use generic SKEYMGMT as a "base class", we shouldn't check the type */
+    if ((selection & OSSL_SKEYMGMT_SELECT_SECRET_KEY) == 0)
+        return 0;
+
+    params[0] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES,
+                                                  gen->data, gen->length);
+    params[1] = OSSL_PARAM_construct_end();
+
+    return param_callback(params, cbarg);
+}
+
+const OSSL_DISPATCH ossl_generic_skeymgmt_functions[] = {
+    { OSSL_FUNC_SKEYMGMT_FREE, (void (*)(void))generic_free },
+    { OSSL_FUNC_SKEYMGMT_IMPORT, (void (*)(void))generic_import },
+    { OSSL_FUNC_SKEYMGMT_EXPORT, (void (*)(void))generic_export },
+    OSSL_DISPATCH_END
+};
diff --git a/providers/implementations/skeymgmt/skeymgmt_lcl.h b/providers/implementations/skeymgmt/skeymgmt_lcl.h
new file mode 100644 (file)
index 0000000..c180c1d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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
+ */
+
+#ifndef OSSL_PROVIDERS_SKEYMGMT_LCL_H
+# define OSSL_PROVIDERS_SKEYMGMT_LCL_H
+# pragma once
+# include <openssl/core_dispatch.h>
+
+OSSL_FUNC_skeymgmt_import_fn generic_import;
+OSSL_FUNC_skeymgmt_export_fn generic_export;
+OSSL_FUNC_skeymgmt_free_fn generic_free;
+
+#endif
index 2a413b1c47afc35bfca9ade3a08892ad505b24dd..618d8738c26a805aef4c3b9eb630b7249573113f 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <openssl/provider.h>
 #include <openssl/params.h>
+#include <openssl/param_build.h>
 #include <openssl/core_names.h>
 #include <openssl/evp.h>
 #include "testutil.h"
@@ -70,7 +71,7 @@ static int test_skey_cipher(void)
         goto end;
 
     /* Export params */
-    if (!TEST_int_gt(EVP_SKEY_export(key, OSSL_SKEYMGMT_SELECT_ALL,
+    if (!TEST_int_gt(EVP_SKEY_export(key, OSSL_SKEYMGMT_SELECT_SECRET_KEY,
                                      ossl_pkey_todata_cb, &export_params), 0))
         goto end;
 
@@ -91,6 +92,159 @@ end:
     return ret;
 }
 
+#define IV_SIZE 16
+#define DATA_SIZE 32
+static int test_aes_raw_skey(void)
+{
+    const unsigned char data[DATA_SIZE] = {
+        0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
+        0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
+        0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
+        0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2
+    };
+    unsigned char aes_key[KEY_SIZE], aes_iv[IV_SIZE];
+    unsigned char encrypted_skey[DATA_SIZE + IV_SIZE];
+    unsigned char encrypted_raw[DATA_SIZE + IV_SIZE];
+    int enc_len, fin_len;
+    const unsigned char *export_key = NULL;
+    size_t export_length;
+    EVP_CIPHER *aes_cbc = NULL;
+    EVP_CIPHER_CTX *ctx = NULL;
+    EVP_SKEY *skey = NULL;
+    OSSL_PARAM_BLD *tmpl = NULL;
+    OSSL_PARAM *params = NULL;
+    int ret = 0;
+
+    deflprov = OSSL_PROVIDER_load(libctx, "default");
+    if (!TEST_ptr(deflprov))
+        return 0;
+
+    memset(encrypted_skey, 0, sizeof(encrypted_skey));
+    memset(encrypted_raw,  0, sizeof(encrypted_raw));
+    memset(aes_key, 1, KEY_SIZE);
+    memset(aes_iv, 2, IV_SIZE);
+
+    /* Do a direct fetch to see it works */
+    aes_cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", "provider=default");
+    if (!TEST_ptr(aes_cbc))
+        goto end;
+
+    /* Create EVP_SKEY */
+    skey = EVP_SKEY_import_raw_key(libctx, "AES-128", aes_key, KEY_SIZE, NULL);
+    if (!TEST_ptr(skey))
+        goto end;
+
+    if (!TEST_int_gt(EVP_SKEY_get_raw_key(skey, &export_key, &export_length), 0)
+        || !TEST_mem_eq(aes_key, KEY_SIZE, export_key, export_length))
+        goto end;
+
+    enc_len = sizeof(encrypted_skey);
+    fin_len = 0;
+    if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
+        || !TEST_int_gt(EVP_CipherInit_SKEY(ctx, aes_cbc, skey, aes_iv, IV_SIZE, 1, NULL), 0)
+        || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_skey, &enc_len, data, DATA_SIZE), 0)
+        || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_skey + enc_len, &fin_len), 0))
+        goto end;
+
+    EVP_CIPHER_CTX_free(ctx);
+    ctx = EVP_CIPHER_CTX_new();
+
+    enc_len = sizeof(encrypted_raw);
+    fin_len = 0;
+    if (!TEST_int_gt(EVP_CipherInit_ex2(ctx, aes_cbc, aes_key, aes_iv, 1, NULL), 0)
+        || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_raw, &enc_len, data, DATA_SIZE), 0)
+        || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_raw + enc_len, &fin_len), 0)
+        || !TEST_mem_eq(encrypted_skey, DATA_SIZE + IV_SIZE, encrypted_raw, DATA_SIZE + IV_SIZE))
+        goto end;
+
+    ret = 1;
+end:
+    OSSL_PARAM_free(params);
+    OSSL_PARAM_BLD_free(tmpl);
+    EVP_SKEY_free(skey);
+    EVP_CIPHER_free(aes_cbc);
+    EVP_CIPHER_CTX_free(ctx);
+    OSSL_PROVIDER_unload(deflprov);
+    return ret;
+}
+
+#ifndef OPENSSL_NO_DES
+/* DES is used to test a "skey-unware" cipher provider */
+# define DES_KEY_SIZE 24
+# define DES_IV_SIZE 8
+static int test_des_raw_skey(void)
+{
+    const unsigned char data[DATA_SIZE] = {
+        0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
+        0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
+        0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
+        0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2
+    };
+    unsigned char des_key[DES_KEY_SIZE], des_iv[DES_IV_SIZE];
+    unsigned char encrypted_skey[DATA_SIZE + DES_IV_SIZE];
+    unsigned char encrypted_raw[DATA_SIZE + DES_IV_SIZE];
+    int enc_len, fin_len;
+    const unsigned char *export_key = NULL;
+    size_t export_length;
+    EVP_CIPHER *des_cbc = NULL;
+    EVP_CIPHER_CTX *ctx = NULL;
+    EVP_SKEY *skey = NULL;
+    int ret = 0;
+
+    deflprov = OSSL_PROVIDER_load(libctx, "default");
+    if (!TEST_ptr(deflprov))
+        return 0;
+
+    memset(encrypted_skey, 0, sizeof(encrypted_skey));
+    memset(encrypted_raw,  0, sizeof(encrypted_raw));
+    memset(des_key, 1, DES_KEY_SIZE);
+    memset(des_iv, 2, DES_IV_SIZE);
+
+    /* Do a direct fetch to see it works */
+    des_cbc = EVP_CIPHER_fetch(libctx, "DES-EDE3-CBC", "provider=default");
+    if (!TEST_ptr(des_cbc))
+        goto end;
+
+    /* Create EVP_SKEY */
+    skey = EVP_SKEY_import_raw_key(libctx, "GENERIC-SECRET", des_key,
+                                   sizeof(des_key), NULL);
+    if (!TEST_ptr(skey))
+        goto end;
+
+    if (!TEST_int_gt(EVP_SKEY_get_raw_key(skey, &export_key, &export_length), 0)
+        || !TEST_mem_eq(des_key, DES_KEY_SIZE, export_key, export_length))
+        goto end;
+
+    enc_len = sizeof(encrypted_skey);
+    fin_len = 0;
+    if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
+        || !TEST_int_gt(EVP_CipherInit_SKEY(ctx, des_cbc, skey, des_iv, DES_IV_SIZE, 1, NULL), 0)
+        || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_skey, &enc_len, data, DATA_SIZE), 0)
+        || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_skey + enc_len, &fin_len), 0))
+        goto end;
+
+    EVP_CIPHER_CTX_free(ctx);
+    ctx = EVP_CIPHER_CTX_new();
+
+    enc_len = sizeof(encrypted_raw);
+    fin_len = 0;
+    if (!TEST_int_gt(EVP_CipherInit_ex2(ctx, des_cbc, des_key, des_iv, 1, NULL), 0)
+        || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_raw, &enc_len, data, DATA_SIZE), 0)
+        || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_raw + enc_len, &fin_len), 0)
+        || !TEST_mem_eq(encrypted_skey, DATA_SIZE + DES_IV_SIZE, encrypted_raw,
+                        DATA_SIZE + DES_IV_SIZE))
+        goto end;
+
+    ret = 1;
+end:
+    EVP_SKEY_free(skey);
+    EVP_CIPHER_free(des_cbc);
+    EVP_CIPHER_CTX_free(ctx);
+    OSSL_PROVIDER_unload(deflprov);
+    return ret;
+}
+#endif
+
 int setup_tests(void)
 {
     libctx = OSSL_LIB_CTX_new();
@@ -99,6 +253,11 @@ int setup_tests(void)
 
     ADD_TEST(test_skey_cipher);
 
+    ADD_TEST(test_aes_raw_skey);
+#ifndef OPENSSL_NO_DES
+    ADD_TEST(test_des_raw_skey);
+#endif
+
     return 1;
 }