From 35aca9eccbaf0abbd0d7f350e199a7c97274845a Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 27 Jun 2019 16:37:44 +0100 Subject: [PATCH 1/1] Add the ability to set PKCS#3 DH padding in providers This also adds the ability to set arbitrary parameters on key exchange algorithms. The ability to pad the output is one such parameter for DH. Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/9266) --- crypto/evp/evp_locl.h | 1 + crypto/evp/exchange.c | 8 ++++- crypto/evp/pmeth_lib.c | 66 ++++++++++++++++++++++++++++++++-- include/openssl/core_names.h | 4 +++ include/openssl/core_numbers.h | 3 ++ include/openssl/dh.h | 4 +-- include/openssl/evp.h | 1 + providers/common/exchange/dh.c | 23 +++++++++++- util/libcrypto.num | 2 ++ 9 files changed, 105 insertions(+), 7 deletions(-) diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h index 659305b8d6..8aeb5d4003 100644 --- a/crypto/evp/evp_locl.h +++ b/crypto/evp/evp_locl.h @@ -73,6 +73,7 @@ struct evp_keyexch_st { OSSL_OP_keyexch_derive_fn *derive; OSSL_OP_keyexch_freectx_fn *freectx; OSSL_OP_keyexch_dupctx_fn *dupctx; + OSSL_OP_keyexch_set_params_fn *set_params; } /* EVP_KEYEXCH */; diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index 479cc0d42d..208bb9885a 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -76,13 +76,19 @@ static void *evp_keyexch_from_dispatch(const OSSL_DISPATCH *fns, break; exchange->dupctx = OSSL_get_OP_keyexch_dupctx(fns); break; + case OSSL_FUNC_KEYEXCH_SET_PARAMS: + if (exchange->set_params != NULL) + break; + exchange->set_params = OSSL_get_OP_keyexch_set_params(fns); + break; } } if (fncnt != 4) { /* * In order to be a consistent set of functions we must have at least * a complete set of "exchange" functions: init, derive, newctx, - * and freectx. The dupctx and set_peer functions are optional. + * and freectx. The dupctx, set_peer and set_params functions are + * optional. */ EVP_KEYEXCH_free(exchange); EVPerr(EVP_F_EVP_KEYEXCH_FROM_DISPATCH, diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index b10663cf70..d444e7168d 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -9,10 +9,12 @@ #include #include -#include "internal/cryptlib.h" #include #include #include +#include +#include +#include "internal/cryptlib.h" #include "internal/asn1_int.h" #include "internal/evp_int.h" #include "internal/numbers.h" @@ -384,12 +386,52 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) OPENSSL_free(ctx); } +int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) +{ + if (ctx->exchprovctx != NULL && ctx->exchange != NULL) + return ctx->exchange->set_params(ctx->exchprovctx, params); + return 0; +} + +int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad) +{ + OSSL_PARAM dh_pad_params[2]; + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (ctx->exchprovctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_DERIVE, + EVP_PKEY_CTRL_DH_PAD, pad, NULL); + + dh_pad_params[0] = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_PAD, &pad); + dh_pad_params[1] = OSSL_PARAM_construct_end(); + + return EVP_PKEY_CTX_set_params(ctx, dh_pad_params); +} + +static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, int p1, void *p2) +{ + switch (cmd) { + case EVP_PKEY_CTRL_DH_PAD: + return EVP_PKEY_CTX_set_dh_pad(ctx, p1); + } + return 0; +} + int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2) { int ret; - if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) { + if (ctx == NULL) { + EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); + return -2; + } + + if (ctx->exchprovctx != NULL) + return legacy_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2); + + if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) { EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); return -2; } @@ -425,9 +467,29 @@ int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, return EVP_PKEY_CTX_ctrl(ctx, keytype, optype, cmd, 0, &value); } +static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name, + const char *value) +{ + if (strcmp(name, "dh_pad") == 0) { + int pad; + + pad = atoi(value); + return EVP_PKEY_CTX_set_dh_pad(ctx, pad); + } + return 0; +} + int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *name, const char *value) { + if (ctx == NULL) { + EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); + return -2; + } + + if (ctx->exchprovctx != NULL) + return legacy_ctrl_str_to_param(ctx, name, value); + if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) { EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); return -2; diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index 143668a0b9..d1ba624d65 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -65,6 +65,10 @@ extern "C" { #define OSSL_PKEY_PARAM_DH_PUB_KEY "dh-pub" #define OSSL_PKEY_PARAM_DH_PRIV_KEY "dh-priv" +/* Key Exchange parameters */ + +#define OSSL_EXCHANGE_PARAM_PAD "exchange-pad" + # ifdef __cplusplus } # endif diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h index 0a61c21bf7..c5892431e4 100644 --- a/include/openssl/core_numbers.h +++ b/include/openssl/core_numbers.h @@ -239,6 +239,7 @@ OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_set_params, (void *cctx, # define OSSL_FUNC_KEYEXCH_SET_PEER 4 # define OSSL_FUNC_KEYEXCH_FREECTX 5 # define OSSL_FUNC_KEYEXCH_DUPCTX 6 +# define OSSL_FUNC_KEYEXCH_SET_PARAMS 7 OSSL_CORE_MAKE_FUNC(void *, OP_keyexch_newctx, (void *provctx)) OSSL_CORE_MAKE_FUNC(int, OP_keyexch_init, (void *ctx, @@ -249,6 +250,8 @@ OSSL_CORE_MAKE_FUNC(int, OP_keyexch_set_peer, (void *ctx, OSSL_PARAM params[])) OSSL_CORE_MAKE_FUNC(void, OP_keyexch_freectx, (void *ctx)) OSSL_CORE_MAKE_FUNC(void *, OP_keyexch_dupctx, (void *ctx)) +OSSL_CORE_MAKE_FUNC(int, OP_keyexch_set_params, (void *ctx, + OSSL_PARAM params[])) # ifdef __cplusplus } diff --git a/include/openssl/dh.h b/include/openssl/dh.h index 18858ebf20..e96c81154d 100644 --- a/include/openssl/dh.h +++ b/include/openssl/dh.h @@ -253,9 +253,7 @@ int DH_meth_set_generate_params(DH_METHOD *dhm, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN, \ EVP_PKEY_CTRL_DH_NID, nid, NULL) -# define EVP_PKEY_CTX_set_dh_pad(ctx, pad) \ - EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_DERIVE, \ - EVP_PKEY_CTRL_DH_PAD, pad, NULL) +int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad); # define EVP_PKEY_CTX_set_dh_kdf_type(ctx, kdf) \ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ diff --git a/include/openssl/evp.h b/include/openssl/evp.h index a2cb66aaf3..377b4b16c0 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1416,6 +1416,7 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx); void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); +int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params); int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2); int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, diff --git a/providers/common/exchange/dh.c b/providers/common/exchange/dh.c index f3d49259fa..ca6f0fc2cb 100644 --- a/providers/common/exchange/dh.c +++ b/providers/common/exchange/dh.c @@ -25,6 +25,7 @@ static OSSL_OP_keyexch_dupctx_fn dh_dupctx; typedef struct { DH *dh; DH *dhpeer; + int pad; } PROV_DH_CTX; static void *dh_newctx(void *provctx) @@ -122,7 +123,8 @@ static int dh_derive(void *vpdhctx, unsigned char *key, size_t *keylen, return 0; DH_get0_key(pdhctx->dhpeer, &pub_key, NULL); - ret = DH_compute_key(key, pub_key, pdhctx->dh); + ret = (pdhctx->pad) ? DH_compute_key_padded(key, pub_key, pdhctx->dh) + : DH_compute_key(key, pub_key, pdhctx->dh); if (ret <= 0) return 0; @@ -162,6 +164,24 @@ static void *dh_dupctx(void *vpdhctx) return dstctx; } +static int dh_set_params(void *vpdhctx, OSSL_PARAM params[]) +{ + PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; + const OSSL_PARAM *p; + int pad; + + if (pdhctx == NULL || params == NULL) + return 0; + + p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_PAD); + if (p == NULL || !OSSL_PARAM_get_int(p, &pad)) + return 0; + + pdhctx->pad = pad; + + return 1; +} + const OSSL_DISPATCH dh_functions[] = { { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx }, { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init }, @@ -169,5 +189,6 @@ const OSSL_DISPATCH dh_functions[] = { { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer }, { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx }, { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx }, + { OSSL_FUNC_KEYEXCH_SET_PARAMS, (void (*)(void))dh_set_params }, { 0, NULL } }; diff --git a/util/libcrypto.num b/util/libcrypto.num index 9e95e3ee76..d0362490bc 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4683,3 +4683,5 @@ EVP_PKEY_derive_init_ex 4788 3_0_0 EXIST::FUNCTION: EVP_KEYEXCH_free 4789 3_0_0 EXIST::FUNCTION: EVP_KEYEXCH_up_ref 4790 3_0_0 EXIST::FUNCTION: EVP_KEYEXCH_fetch 4791 3_0_0 EXIST::FUNCTION: +EVP_PKEY_CTX_set_dh_pad 4792 3_0_0 EXIST::FUNCTION:DH +EVP_PKEY_CTX_set_params 4793 3_0_0 EXIST::FUNCTION: -- 2.34.1