From 0ba71d6a63add7efb244965c0f18502bd786a0f7 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Thu, 15 Oct 2020 07:10:29 +0200 Subject: DH: make the private key length importable / exportable The DH private key length, which is an optional parameter, wasn't properly imported / exported between legacy and provider side implementations. Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/13166) --- crypto/dh/dh_ameth.c | 8 +++++- crypto/dh/dh_backend.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ crypto/dh/dh_lib.c | 19 --------------- 3 files changed, 73 insertions(+), 20 deletions(-) (limited to 'crypto/dh') diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 69b166362a..49e65e4d6c 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -485,6 +485,7 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata, DH *dh = from->pkey.dh; OSSL_PARAM_BLD *tmpl; const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh); + long l = DH_get_length(dh); const BIGNUM *pub_key = DH_get0_pub_key(dh); const BIGNUM *priv_key = DH_get0_priv_key(dh); OSSL_PARAM *params = NULL; @@ -512,6 +513,11 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata, goto err; } selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; + if (l > 0) { + if (!OSSL_PARAM_BLD_push_long(tmpl, OSSL_PKEY_PARAM_DH_PRIV_LEN, l)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS; + } if (pub_key != NULL) { if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key)) goto err; @@ -550,7 +556,7 @@ static int dh_pkey_import_from_type(const OSSL_PARAM params[], void *vpctx, DH_clear_flags(dh, DH_FLAG_TYPE_MASK); DH_set_flags(dh, type == EVP_PKEY_DH ? DH_FLAG_TYPE_DH : DH_FLAG_TYPE_DHX); - if (!dh_ffc_params_fromdata(dh, params) + if (!dh_params_fromdata(dh, params) || !dh_key_fromdata(dh, params) || !EVP_PKEY_assign(pkey, type, dh)) { DH_free(dh); diff --git a/crypto/dh/dh_backend.c b/crypto/dh/dh_backend.c index 704f6efac1..1ce29e652d 100644 --- a/crypto/dh/dh_backend.c +++ b/crypto/dh/dh_backend.c @@ -8,6 +8,7 @@ */ #include +#include "internal/param_build_set.h" #include "crypto/dh.h" /* @@ -16,6 +17,41 @@ * implementations alike. */ +static int dh_ffc_params_fromdata(DH *dh, const OSSL_PARAM params[]) +{ + int ret; + FFC_PARAMS *ffc; + + if (dh == NULL) + return 0; + ffc = dh_get0_params(dh); + if (ffc == NULL) + return 0; + + ret = ossl_ffc_params_fromdata(ffc, params); + if (ret) + dh_cache_named_group(dh); /* This increments dh->dirt_cnt */ + return ret; +} + +int dh_params_fromdata(DH *dh, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *param_priv_len; + long priv_len; + + if (!dh_ffc_params_fromdata(dh, params)) + return 0; + + param_priv_len = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN); + if (param_priv_len != NULL + && (!OSSL_PARAM_get_long(param_priv_len, &priv_len) + || !DH_set_length(dh, priv_len))) + return 0; + + return 1; +} + int dh_key_fromdata(DH *dh, const OSSL_PARAM params[]) { const OSSL_PARAM *param_priv_key, *param_pub_key; @@ -52,3 +88,33 @@ int dh_key_fromdata(DH *dh, const OSSL_PARAM params[]) BN_free(pub_key); return 0; } + +int dh_params_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) +{ + long l = DH_get_length(dh); + + if (!ossl_ffc_params_todata(dh_get0_params(dh), bld, params)) + return 0; + if (l > 0 + && !ossl_param_build_set_long(bld, params, OSSL_PKEY_PARAM_DH_PRIV_LEN, l)) + return 0; + return 1; +} + +int dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) +{ + const BIGNUM *priv = NULL, *pub = NULL; + + if (dh == NULL) + return 0; + + DH_get0_key(dh, &pub, &priv); + if (priv != NULL + && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv)) + return 0; + if (pub != NULL + && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PUB_KEY, pub)) + return 0; + + return 1; +} diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index 94978a2cb2..e6eba34ac9 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -325,22 +325,3 @@ int dh_get0_nid(const DH *dh) { return dh->params.nid; } - -int dh_ffc_params_fromdata(DH *dh, const OSSL_PARAM params[]) -{ - int ret; - FFC_PARAMS *ffc; - - if (dh == NULL) - return 0; - ffc = dh_get0_params(dh); - if (ffc == NULL) - return 0; - - ret = ossl_ffc_params_fromdata(ffc, params); - if (ret) { - dh_cache_named_group(dh); - dh->dirty_cnt++; - } - return ret; -} -- cgit v1.2.3