diff options
author | Todd Short <todd.short@me.com> | 2024-02-02 05:09:38 +0100 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2024-04-09 20:19:07 +0200 |
commit | 6b566687b58fde08b28e3331377f050768fad89b (patch) | |
tree | abd753bfb8153bd397271168f7dd6e677be29c15 /crypto/evp | |
parent | Add demo for ECDH key exchange (diff) | |
download | openssl-6b566687b58fde08b28e3331377f050768fad89b.tar.xz openssl-6b566687b58fde08b28e3331377f050768fad89b.zip |
Fix EVP_PKEY_CTX_add1_hkdf_info() behavior
Fix #23448
`EVP_PKEY_CTX_add1_hkdf_info()` behaves like a `set1` function.
Fix the setting of the parameter in the params code.
Update the TLS_PRF code to also use the params code.
Add tests.
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23456)
Diffstat (limited to 'crypto/evp')
-rw-r--r-- | crypto/evp/pmeth_lib.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index c4b96156fd..65f5fcb804 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -1002,6 +1002,69 @@ static int evp_pkey_ctx_set1_octet_string(EVP_PKEY_CTX *ctx, int fallback, return EVP_PKEY_CTX_set_params(ctx, octet_string_params); } +static int evp_pkey_ctx_add1_octet_string(EVP_PKEY_CTX *ctx, int fallback, + const char *param, int op, int ctrl, + const unsigned char *data, + int datalen) +{ + OSSL_PARAM os_params[2]; + unsigned char *info = NULL; + size_t info_len = 0; + size_t info_alloc = 0; + int ret = 0; + + if (ctx == NULL || (ctx->operation & op) == 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* Code below to be removed when legacy support is dropped. */ + if (fallback) + return EVP_PKEY_CTX_ctrl(ctx, -1, op, ctrl, datalen, (void *)(data)); + /* end of legacy support */ + + if (datalen < 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH); + return 0; + } + + /* Get the original value length */ + os_params[0] = OSSL_PARAM_construct_octet_string(param, NULL, 0); + os_params[1] = OSSL_PARAM_construct_end(); + + if (!EVP_PKEY_CTX_get_params(ctx, os_params)) + return 0; + + /* Older provider that doesn't support getting this parameter */ + if (os_params[0].return_size == OSSL_PARAM_UNMODIFIED) + return evp_pkey_ctx_set1_octet_string(ctx, fallback, param, op, ctrl, data, datalen); + + info_alloc = os_params[0].return_size + datalen; + if (info_alloc == 0) + return 0; + info = OPENSSL_zalloc(info_alloc); + if (info == NULL) + return 0; + info_len = os_params[0].return_size; + + os_params[0] = OSSL_PARAM_construct_octet_string(param, info, info_alloc); + + /* if we have data, then go get it */ + if (info_len > 0) { + if (!EVP_PKEY_CTX_get_params(ctx, os_params)) + goto error; + } + + /* Copy the input data */ + memcpy(&info[info_len], data, datalen); + ret = EVP_PKEY_CTX_set_params(ctx, os_params); + + error: + OPENSSL_clear_free(info, info_alloc); + return ret; +} + int EVP_PKEY_CTX_set1_tls1_prf_secret(EVP_PKEY_CTX *ctx, const unsigned char *sec, int seclen) { @@ -1052,7 +1115,7 @@ int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx, int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx, const unsigned char *info, int infolen) { - return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL, + return evp_pkey_ctx_add1_octet_string(ctx, ctx->op.kex.algctx == NULL, OSSL_KDF_PARAM_INFO, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_INFO, |