diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 67e7e9058569e9..3c9edae56bad0f 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 14cea6d724f27b..af7b25e9402d65 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->skeymgmt->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 be5d40d9d53853..4b3a3a6ab40344 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 ec19afad52e409..9db753f22fc060 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/doc/man7/provider-keyexch.pod b/doc/man7/provider-keyexch.pod index 1d3604e783a358..d3a4c5c31badca 100644 --- a/doc/man7/provider-keyexch.pod +++ b/doc/man7/provider-keyexch.pod @@ -28,6 +28,7 @@ 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_opaque(void *ctx, void *secret); /* Key Exchange parameters */ int OSSL_FUNC_keyexch_set_ctx_params(void *ctx, const OSSL_PARAM params[]); @@ -73,6 +74,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_opaque OSSL_FUNC_KEYEXCH_DERIVE_OPAQUE 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 +83,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_opaque. All other functions are optional. A key exchange algorithm must also implement some mechanism for generating, @@ -133,6 +136,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_opaque() 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 +248,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_opaque(), OSSL_FUNC_keyexch_set_params(), and OSSL_FUNC_keyexch_get_params() should return 1 for success or 0 on error. @@ -259,6 +266,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_opaque() function was added in OpenSSL 3.5. + =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 90791fce2bdc9c..d17cb64621374c 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 ee7bce7487eb90..adfe93de40daae 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1998,6 +1998,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 18c3cc307b703d..32bfc4f1d9ea98 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5758,3 +5758,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: