diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index ae8c7bb8a8b28..ce858f8904451 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -155,6 +155,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_opaque_fn *derive_opaque; } /* EVP_KEYEXCH */; struct evp_signature_st { diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index 14cea6d724f27..8cfa908f45c77 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -115,8 +115,15 @@ static void *evp_keyexch_from_algorithm(int name_id, = OSSL_FUNC_keyexch_settable_ctx_params(fns); sparamfncnt++; break; + case OSSL_FUNC_KEYEXCH_DERIVE_OPAQUE: + if (exchange->derive_opaque != NULL) + break; + exchange->derive_opaque = OSSL_FUNC_keyexch_derive_opaque(fns); + derive_found = 1; + break; } } + fncnt += derive_found; if (fncnt != 4 || (gparamfncnt != 0 && gparamfncnt != 2) || (sparamfncnt != 0 && sparamfncnt != 2)) { @@ -534,6 +541,36 @@ int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen) return ctx->pmeth->derive(ctx, key, pkeylen); } +int EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEY *skey) +{ + if (ctx == NULL || skey == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); + return 0; + } + + if (ctx->op.kex.algctx == NULL || ctx->op.kex.exchange->derive_opaque == NULL) { + ERR_raise(ERR_R_EVP_LIB, ERR_R_UNSUPPORTED); + return 0; + } + + if (skey->keymgmt->prov != ctx->op.kex.exchange->prov) { + ERR_raise(ERR_R_EVP_LIB, ERR_R_UNSUPPORTED); + return 0; + } + + if (skey->keydata != NULL) { + ERR_raise(ERR_R_EVP_LIB, ERR_R_UNSUPPORTED); + return 0; + } + + return ctx->op.kex.exchange->derive_opaque(ctx->op.kex.algctx, &(skey->keydata)); +} + int evp_keyexch_get_number(const EVP_KEYEXCH *keyexch) { return keyexch->name_id; diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c index fd8b518f05fd4..fae9dc51ad65c 100644 --- a/crypto/evp/kdf_lib.c +++ b/crypto/evp/kdf_lib.c @@ -147,8 +147,10 @@ int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen, int EVP_KDF_derive_SKEY(EVP_KDF_CTX *ctx, EVP_SKEY *skey, const OSSL_PARAM params[]) { - if (ctx == NULL || skey == NULL) + if (ctx == NULL || skey == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); return 0; + } if (ctx->meth->derive_opaque == NULL) { ERR_raise(ERR_R_EVP_LIB, ERR_R_UNSUPPORTED); diff --git a/doc/man3/EVP_PKEY_derive.pod b/doc/man3/EVP_PKEY_derive.pod index ec19afad52e40..9db753f22fc06 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,7 @@ 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); + int EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEY *skey); =head1 DESCRIPTION @@ -42,6 +44,9 @@ 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 accepts an B +object that would store an opaque data for the derived key. + =head1 NOTES After the call to EVP_PKEY_derive_init(), algorithm @@ -53,7 +58,7 @@ context if several operations are performed using the same parameters. =head1 RETURN VALUES -EVP_PKEY_derive_init() and EVP_PKEY_derive() return 1 +EVP_PKEY_derive_init(), EVP_PKEY_derive(), and EVP_PKEY_derive_SKEY() return 1 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. @@ -112,9 +117,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.5. + =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/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index c38ea218541c5..0bee6d6b738f0 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -712,6 +712,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_OPAQUE 11 OSSL_CORE_MAKE_FUNC(void *, keyexch_newctx, (void *provctx)) OSSL_CORE_MAKE_FUNC(int, keyexch_init, (void *ctx, void *provkey, @@ -729,6 +730,7 @@ 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(int, keyexch_derive_opaque, (void *ctx, void *secret)) /* Signature */ diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 33a4bea31c481..64e4512193bba 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1983,6 +1983,7 @@ 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); +int EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEY *skey); 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/util/libcrypto.num b/util/libcrypto.num index e8e2434e2815e..5488abdab927b 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5759,3 +5759,4 @@ EVP_SKEY_export ? 3_5_0 EXIST::FUNCTION: EVP_SKEY_up_ref ? 3_5_0 EXIST::FUNCTION: EVP_SKEY_free ? 3_5_0 EXIST::FUNCTION: EVP_KDF_derive_SKEY ? 3_5_0 EXIST::FUNCTION: +EVP_PKEY_derive_SKEY ? 3_5_0 EXIST::FUNCTION: