From: Dmitry Belyavskiy Date: Fri, 15 Nov 2024 15:21:04 +0000 (+0100) Subject: Implement EVP_PKEY_derive_SKEY X-Git-Tag: openssl-3.6.0-alpha1~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7d42becc0d3ec1d1f16054288ea897b3cd85961d;p=thirdparty%2Fopenssl.git Implement EVP_PKEY_derive_SKEY Signed-off-by: Dmitry Belyavskiy Signed-off-by: Simo Sorce Reviewed-by: Tim Hudson Reviewed-by: Matt Caswell Reviewed-by: Neil Horman (Merged from https://github.com/openssl/openssl/pull/28369) --- diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 9a216c30c84..677711ebea0 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -156,6 +156,7 @@ struct evp_keyexch_st { OSSL_FUNC_keyexch_settable_ctx_params_fn *settable_ctx_params; OSSL_FUNC_keyexch_get_ctx_params_fn *get_ctx_params; OSSL_FUNC_keyexch_gettable_ctx_params_fn *gettable_ctx_params; + OSSL_FUNC_keyexch_derive_skey_fn *derive_skey; } /* EVP_KEYEXCH */; struct evp_signature_st { diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index dae3a2c5a85..504458bc3ee 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -7,6 +7,7 @@ * https://www.openssl.org/source/license.html */ +#include #include #include #include @@ -52,7 +53,7 @@ static void *evp_keyexch_from_algorithm(int name_id, { const OSSL_DISPATCH *fns = algodef->implementation; EVP_KEYEXCH *exchange = NULL; - int fncnt = 0, sparamfncnt = 0, gparamfncnt = 0; + int fncnt = 0, sparamfncnt = 0, gparamfncnt = 0, derive_found = 0; if ((exchange = evp_keyexch_new(prov)) == NULL) { ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); @@ -87,7 +88,7 @@ static void *evp_keyexch_from_algorithm(int name_id, if (exchange->derive != NULL) break; exchange->derive = OSSL_FUNC_keyexch_derive(fns); - fncnt++; + derive_found = 1; break; case OSSL_FUNC_KEYEXCH_FREECTX: if (exchange->freectx != NULL) @@ -126,8 +127,15 @@ static void *evp_keyexch_from_algorithm(int name_id, = OSSL_FUNC_keyexch_settable_ctx_params(fns); sparamfncnt++; break; + case OSSL_FUNC_KEYEXCH_DERIVE_SKEY: + if (exchange->derive_skey != NULL) + break; + exchange->derive_skey = OSSL_FUNC_keyexch_derive_skey(fns); + derive_found = 1; + break; } } + fncnt += derive_found; if (fncnt != 4 || (gparamfncnt != 0 && gparamfncnt != 2) || (sparamfncnt != 0 && sparamfncnt != 2)) { @@ -548,6 +556,108 @@ int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen) return ctx->pmeth->derive(ctx, key, pkeylen); } +EVP_SKEY *EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEYMGMT *mgmt, + const char *key_type, const char *propquery, + size_t keylen, const OSSL_PARAM params[]) +{ + EVP_SKEYMGMT *skeymgmt = NULL; + EVP_SKEY *ret = NULL; + + if (ctx == NULL || key_type == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); + return NULL; + } + + if (ctx->op.kex.algctx == NULL) { + ERR_raise(ERR_R_EVP_LIB, ERR_R_UNSUPPORTED); + return NULL; + } + + if (mgmt != NULL) { + skeymgmt = mgmt; + } else { + skeymgmt = evp_skeymgmt_fetch_from_prov(ctx->op.kex.exchange->prov, + key_type, propquery); + if (skeymgmt == NULL) { + /* + * The provider does not support skeymgmt, let's try to fallback + * to a provider that supports it + */ + skeymgmt = EVP_SKEYMGMT_fetch(ctx->libctx, key_type, propquery); + } + if (skeymgmt == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_FETCH_FAILED); + return NULL; + } + } + + /* Fallback to raw derive + import if necessary */ + if (skeymgmt->prov != ctx->op.kex.exchange->prov || + ctx->op.kex.exchange->derive_skey == NULL) { + size_t tmplen = keylen; + unsigned char *key = NULL; + OSSL_PARAM import_params[2] = {OSSL_PARAM_END, OSSL_PARAM_END}; + + if (ctx->op.kex.exchange->derive == NULL) { + ERR_raise(ERR_R_EVP_LIB, ERR_R_UNSUPPORTED); + return NULL; + } + + key = OPENSSL_zalloc(keylen); + if (key == NULL) { + ERR_raise(ERR_R_EVP_LIB, ERR_R_CRYPTO_LIB); + return NULL; + } + + if (!ctx->op.kex.exchange->derive(ctx->op.kex.algctx, key, &tmplen, + tmplen)) { + OPENSSL_free(key); + return NULL; + } + + if (keylen != tmplen) { + OPENSSL_free(key); + ERR_raise(ERR_R_EVP_LIB, ERR_R_INTERNAL_ERROR); + return NULL; + } + import_params[0] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES, + key, keylen); + + ret = EVP_SKEY_import_SKEYMGMT(ctx->libctx, skeymgmt, + OSSL_SKEYMGMT_SELECT_SECRET_KEY, import_params); + OPENSSL_clear_free(key, keylen); + if (mgmt != skeymgmt) + EVP_SKEYMGMT_free(skeymgmt); + return ret; + } + + ret = evp_skey_alloc(skeymgmt); + if (ret == NULL) { + if (mgmt != skeymgmt) + EVP_SKEYMGMT_free(skeymgmt); + return NULL; + } + + ret->keydata = ctx->op.kex.exchange->derive_skey(ctx->op.kex.algctx, + ossl_provider_ctx(skeymgmt->prov), + skeymgmt->import, keylen, params); + + if (mgmt != skeymgmt) + EVP_SKEYMGMT_free(skeymgmt); + + if (ret->keydata == NULL) { + EVP_SKEY_free(ret); + return NULL; + } + + return ret; +} + int evp_keyexch_get_number(const EVP_KEYEXCH *keyexch) { return keyexch->name_id; diff --git a/doc/man3/EVP_PKEY_derive.pod b/doc/man3/EVP_PKEY_derive.pod index ec19afad52e..5bc938d7e32 100644 --- a/doc/man3/EVP_PKEY_derive.pod +++ b/doc/man3/EVP_PKEY_derive.pod @@ -3,7 +3,8 @@ =head1 NAME EVP_PKEY_derive_init, EVP_PKEY_derive_init_ex, -EVP_PKEY_derive_set_peer_ex, EVP_PKEY_derive_set_peer, EVP_PKEY_derive +EVP_PKEY_derive_set_peer_ex, EVP_PKEY_derive_set_peer, EVP_PKEY_derive, +EVP_PKEY_derive_SKEY - derive public key algorithm shared secret =head1 SYNOPSIS @@ -16,6 +17,9 @@ EVP_PKEY_derive_set_peer_ex, EVP_PKEY_derive_set_peer, EVP_PKEY_derive int validate_peer); int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer); int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); + EVP_SKEY *EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEYMGMT *mgmt, + const char *key_type, const char *propquery, + size_t keylen, const OSSL_PARAM params[]); =head1 DESCRIPTION @@ -42,6 +46,14 @@ parameter should contain the length of the I buffer, if the call is successful the shared secret is written to I and the amount of data written to I. +EVP_PKEY_derive_SKEY() is similar to EVP_PKEY_derive() but returns an +B object that stores the opaque data for the derived key. If +B argument is passed, it would be explicitly used for the +B creation. Otherwise the B object used for B +will be fetched according to I and I. If +I is NULL, the name matching the key exchange method name is +assumed. + =head1 NOTES After the call to EVP_PKEY_derive_init(), algorithm @@ -58,6 +70,9 @@ for success and 0 or a negative value for failure. In particular a return value of -2 indicates the operation is not supported by the public key algorithm. +EVP_PKEY_derive_SKEY() returns a freshly created B object on success +or NULL on failure. + =head1 EXAMPLES Derive shared secret (for example DH or EC keys): @@ -112,9 +127,11 @@ functions were originally added in OpenSSL 1.0.0. The EVP_PKEY_derive_init_ex() and EVP_PKEY_derive_set_peer_ex() functions were added in OpenSSL 3.0. +The EVP_PKEY_derive_SKEY() function was added in OpenSSL 3.6. + =head1 COPYRIGHT -Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-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 diff --git a/doc/man7/provider-keyexch.pod b/doc/man7/provider-keyexch.pod index 1d3604e783a..f8fa85a2462 100644 --- a/doc/man7/provider-keyexch.pod +++ b/doc/man7/provider-keyexch.pod @@ -28,6 +28,9 @@ provider-keyexch - The keyexch library E-E provider functions int OSSL_FUNC_keyexch_set_peer(void *ctx, void *provkey); int OSSL_FUNC_keyexch_derive(void *ctx, unsigned char *secret, size_t *secretlen, size_t outlen); + int OSSL_FUNC_keyexch_derive_skey(void *ctx, void *provctx, + OSSL_FUNC_skeymgmt_import_fn *import, + size_t keylen, const OSSL_PARAM params[]); /* Key Exchange parameters */ int OSSL_FUNC_keyexch_set_ctx_params(void *ctx, const OSSL_PARAM params[]); @@ -73,6 +76,7 @@ macros in L, as follows: OSSL_FUNC_keyexch_init OSSL_FUNC_KEYEXCH_INIT OSSL_FUNC_keyexch_set_peer OSSL_FUNC_KEYEXCH_SET_PEER OSSL_FUNC_keyexch_derive OSSL_FUNC_KEYEXCH_DERIVE + OSSL_FUNC_keyexch_derive_skey OSSL_FUNC_KEYEXCH_DERIVE_SKEY OSSL_FUNC_keyexch_set_ctx_params OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS OSSL_FUNC_keyexch_settable_ctx_params OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS @@ -81,7 +85,8 @@ macros in L, as follows: A key exchange algorithm implementation may not implement all of these functions. In order to be a consistent set of functions a provider must implement -OSSL_FUNC_keyexch_newctx, OSSL_FUNC_keyexch_freectx, OSSL_FUNC_keyexch_init and OSSL_FUNC_keyexch_derive. +OSSL_FUNC_keyexch_newctx, OSSL_FUNC_keyexch_freectx, OSSL_FUNC_keyexch_init and at least one +of OSSL_FUNC_keyexch_derive and OSSL_FUNC_keyexch_derive_skey. All other functions are optional. A key exchange algorithm must also implement some mechanism for generating, @@ -133,6 +138,9 @@ The length of the shared secret should be written to I<*secretlen>. If I is NULL then the maximum length of the shared secret should be written to I<*secretlen>. +OSSL_FUNC_keyexch_derive_skey() is similar to OSSL_FUNC_keyexch_derive() but works +with an opaque provider-specific object instead of raw bytes buffer. + =head2 Key Exchange Parameters Functions OSSL_FUNC_keyexch_set_ctx_params() sets key exchange parameters associated with the @@ -242,6 +250,7 @@ OSSL_FUNC_keyexch_newctx() and OSSL_FUNC_keyexch_dupctx() should return the newl provider side key exchange context, or NULL on failure. OSSL_FUNC_keyexch_init(), OSSL_FUNC_keyexch_set_peer(), OSSL_FUNC_keyexch_derive(), +OSSL_FUNC_keyexch_derive_skey(), OSSL_FUNC_keyexch_set_params(), and OSSL_FUNC_keyexch_get_params() should return 1 for success or 0 on error. @@ -259,6 +268,8 @@ The provider KEYEXCH interface was introduced in OpenSSL 3.0. The Key Exchange Parameters "fips-indicator", "key-check" and "digest-check" were added in OpenSSL 3.4. +The OSSL_FUNC_keyexch_derive_skey() function was added in OpenSSL 3.6. + =head1 COPYRIGHT Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index cc152ceeb72..41c42124826 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -825,6 +825,7 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keymgmt_export_types_ex, # define OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS 8 # define OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS 9 # define OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS 10 +# define OSSL_FUNC_KEYEXCH_DERIVE_SKEY 11 OSSL_CORE_MAKE_FUNC(void *, keyexch_newctx, (void *provctx)) OSSL_CORE_MAKE_FUNC(int, keyexch_init, (void *ctx, void *provkey, @@ -842,6 +843,9 @@ OSSL_CORE_MAKE_FUNC(int, keyexch_get_ctx_params, (void *ctx, OSSL_PARAM params[])) OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keyexch_gettable_ctx_params, (void *ctx, void *provctx)) +OSSL_CORE_MAKE_FUNC(void *, keyexch_derive_skey, (void *ctx, void *provctx, + OSSL_FUNC_skeymgmt_import_fn *import, + size_t keylen, const OSSL_PARAM params[])) /* Signature */ @@ -955,52 +959,6 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, signature_settable_ctx_md_params, (void *ctx)) OSSL_CORE_MAKE_FUNC(const char **, signature_query_key_types, (void)) -/*- - * Symmetric key management - * - * The Key Management takes care of provider side of symmetric key objects, and - * includes essentially everything that manipulates the keys themselves and - * their parameters. - * - * The key objects are commonly referred to as |keydata|, and it MUST be able - * to contain parameters if the key has any, and the secret key. - * - * Key objects are created with OSSL_FUNC_skeymgmt_import() (there is no - * dedicated memory allocation function), exported with - * OSSL_FUNC_skeymgmt_export() and destroyed with OSSL_FUNC_keymgmt_free(). - * - */ - -/* Key data subset selection - individual bits */ -# define OSSL_SKEYMGMT_SELECT_PARAMETERS 0x01 -# define OSSL_SKEYMGMT_SELECT_SECRET_KEY 0x02 - -/* Key data subset selection - combinations */ -# define OSSL_SKEYMGMT_SELECT_ALL \ - (OSSL_SKEYMGMT_SELECT_PARAMETERS | OSSL_SKEYMGMT_SELECT_SECRET_KEY) - -# define OSSL_FUNC_SKEYMGMT_FREE 1 -# define OSSL_FUNC_SKEYMGMT_IMPORT 2 -# define OSSL_FUNC_SKEYMGMT_EXPORT 3 -# define OSSL_FUNC_SKEYMGMT_GENERATE 4 -# define OSSL_FUNC_SKEYMGMT_GET_KEY_ID 5 -# define OSSL_FUNC_SKEYMGMT_IMP_SETTABLE_PARAMS 6 -# define OSSL_FUNC_SKEYMGMT_GEN_SETTABLE_PARAMS 7 - -OSSL_CORE_MAKE_FUNC(void, skeymgmt_free, (void *keydata)) -OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, - skeymgmt_imp_settable_params, (void *provctx)) -OSSL_CORE_MAKE_FUNC(void *, skeymgmt_import, (void *provctx, int selection, - const OSSL_PARAM params[])) -OSSL_CORE_MAKE_FUNC(int, skeymgmt_export, - (void *keydata, int selection, - OSSL_CALLBACK *param_cb, void *cbarg)) -OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, - skeymgmt_gen_settable_params, (void *provctx)) -OSSL_CORE_MAKE_FUNC(void *, skeymgmt_generate, (void *provctx, - const OSSL_PARAM params[])) -OSSL_CORE_MAKE_FUNC(const char *, skeymgmt_get_key_id, (void *keydata)) - /* Asymmetric Ciphers */ # define OSSL_FUNC_ASYM_CIPHER_NEWCTX 1 diff --git a/include/openssl/evp.h b/include/openssl/evp.h index ec37c22d3f7..61e50b266d6 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -2067,6 +2067,9 @@ int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer, int validate_peer); int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer); int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); +EVP_SKEY *EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEYMGMT *mgmt, + const char *key_type, const char *propquery, + size_t keylen, const OSSL_PARAM params[]); int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]); int EVP_PKEY_auth_encapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpriv, diff --git a/providers/implementations/exchange/ecdh_exch.c.in b/providers/implementations/exchange/ecdh_exch.c.in index 16295b4ad28..00f2e8101dd 100644 --- a/providers/implementations/exchange/ecdh_exch.c.in +++ b/providers/implementations/exchange/ecdh_exch.c.in @@ -36,6 +36,7 @@ static OSSL_FUNC_keyexch_newctx_fn ecdh_newctx; static OSSL_FUNC_keyexch_init_fn ecdh_init; static OSSL_FUNC_keyexch_set_peer_fn ecdh_set_peer; static OSSL_FUNC_keyexch_derive_fn ecdh_derive; +static OSSL_FUNC_keyexch_derive_skey_fn ecdh_derive_skey; static OSSL_FUNC_keyexch_freectx_fn ecdh_freectx; static OSSL_FUNC_keyexch_dupctx_fn ecdh_dupctx; static OSSL_FUNC_keyexch_set_ctx_params_fn ecdh_set_ctx_params; @@ -617,10 +618,45 @@ int ecdh_derive(void *vpecdhctx, unsigned char *secret, return 0; } +static +void *ecdh_derive_skey(void *vpecdhctx, void *provctx, OSSL_FUNC_skeymgmt_import_fn *import, + size_t outlen, const OSSL_PARAM params_in[] ossl_unused) +{ + unsigned char *secret = NULL; + size_t secretlen = 0; + void *ret = NULL; + OSSL_PARAM params[2] = {OSSL_PARAM_END, OSSL_PARAM_END}; + + if (import == NULL || outlen == 0) + return NULL; + + if (ecdh_derive(vpecdhctx, secret, &secretlen, outlen) == 0) + return NULL; + + if ((secret = OPENSSL_malloc(secretlen)) == NULL) + return NULL; + + if (ecdh_derive(vpecdhctx, secret, &secretlen, outlen) == 0 + || secretlen != outlen) { + OPENSSL_clear_free(secret, secretlen); + return NULL; + } + + params[0] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES, + (void *)secret, outlen); + + /* This is mandatory, no need to check for its presence */ + ret = import(provctx, OSSL_SKEYMGMT_SELECT_SECRET_KEY, params); + OPENSSL_clear_free(secret, secretlen); + + return ret; +} + const OSSL_DISPATCH ossl_ecdh_keyexch_functions[] = { { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))ecdh_newctx }, { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ecdh_init }, { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecdh_derive }, + { OSSL_FUNC_KEYEXCH_DERIVE_SKEY, (void (*)(void))ecdh_derive_skey }, { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecdh_set_peer }, { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecdh_freectx }, { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecdh_dupctx }, diff --git a/test/ectest.c b/test/ectest.c index a1bb1a57767..d2ffc6514a1 100644 --- a/test/ectest.c +++ b/test/ectest.c @@ -2825,6 +2825,9 @@ static int custom_params_test(int id) unsigned char *pub1 = NULL , *pub2 = NULL; OSSL_PARAM_BLD *param_bld = NULL; OSSL_PARAM *params1 = NULL, *params2 = NULL; + const unsigned char *export = NULL; + size_t export_size = 0; + EVP_SKEY *skey = NULL; /* Do some setup */ nid = curves[id].nid; @@ -3053,9 +3056,22 @@ static int custom_params_test(int id) || !TEST_mem_eq(buf1, t, buf2, sslen)) goto err; + /* compute keyexchange once more using the EVP_SKEY export */ + EVP_PKEY_CTX_free(pctx1); + if (!TEST_ptr(pctx1 = EVP_PKEY_CTX_new(pkey1, NULL)) + || !TEST_int_eq(EVP_PKEY_derive_init(pctx1), 1) + || !TEST_int_eq(EVP_PKEY_derive_set_peer(pctx1, pkey2), 1) + || !TEST_ptr(skey = EVP_PKEY_derive_SKEY(pctx1, NULL, OSSL_SKEY_TYPE_GENERIC, + NULL, t, NULL)) + || !TEST_int_eq(EVP_SKEY_get0_raw_key(skey, &export, &export_size), 1) + /* compare with previous result */ + || !TEST_mem_eq(export, export_size, buf2, sslen)) + goto err; + ret = 1; err: + EVP_SKEY_free(skey); BN_CTX_end(ctx); BN_CTX_free(ctx); OSSL_PARAM_BLD_free(param_bld); diff --git a/test/pkey_meth_kdf_test.c b/test/pkey_meth_kdf_test.c index ad58adf4826..cf4fd6bf18b 100644 --- a/test/pkey_meth_kdf_test.c +++ b/test/pkey_meth_kdf_test.c @@ -145,7 +145,7 @@ err: } #ifndef OPENSSL_NO_SCRYPT -static int test_kdf_scrypt(void) +static int test_kdf_scrypt(int index) { int ret = 0; EVP_PKEY_CTX *pctx; @@ -192,8 +192,26 @@ static int test_kdf_scrypt(void) TEST_error("EVP_PKEY_CTX_set_maxmem_bytes"); goto err; } - if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) { - TEST_error("EVP_PKEY_derive"); + if (index == 0) { + if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) { + TEST_error("EVP_PKEY_derive"); + goto err; + } + } else if (index == 1) { + EVP_SKEY *skey = NULL; + const unsigned char *key = NULL; + size_t keysize = 0; + + if ((skey = EVP_PKEY_derive_SKEY(pctx, NULL, "GENERIC", NULL, + outlen, NULL)) == NULL) { + TEST_error("EVP_PKEY_derive_SKEY"); + goto err; + } + if (!TEST_int_gt(EVP_SKEY_get0_raw_key(skey, &key, &keysize), 0)) + goto err; + memcpy(out, key, keysize); + EVP_SKEY_free(skey); + } else { goto err; } @@ -229,7 +247,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_kdf_tls1_prf, tests); ADD_ALL_TESTS(test_kdf_hkdf, tests); #ifndef OPENSSL_NO_SCRYPT - ADD_TEST(test_kdf_scrypt); + ADD_ALL_TESTS(test_kdf_scrypt, 1); #endif return 1; }