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 -------- crypto/param_build_set.c | 11 +++++ include/crypto/dh.h | 5 ++- include/internal/param_build_set.h | 2 + providers/implementations/keymgmt/dh_kmgmt.c | 30 +++---------- 7 files changed, 96 insertions(+), 45 deletions(-) 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; -} diff --git a/crypto/param_build_set.c b/crypto/param_build_set.c index b74b0d59ee..1ea8097e88 100644 --- a/crypto/param_build_set.c +++ b/crypto/param_build_set.c @@ -30,6 +30,17 @@ int ossl_param_build_set_int(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, return 1; } +int ossl_param_build_set_long(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, long num) +{ + if (bld != NULL) + return OSSL_PARAM_BLD_push_long(bld, key, num); + p = OSSL_PARAM_locate(p, key); + if (p != NULL) + return OSSL_PARAM_set_long(p, num); + return 1; +} + int ossl_param_build_set_utf8_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, const char *buf) { diff --git a/include/crypto/dh.h b/include/crypto/dh.h index cd7e1e4a89..4dbd0c582c 100644 --- a/include/crypto/dh.h +++ b/include/crypto/dh.h @@ -8,6 +8,7 @@ */ #include +#include #include #include "internal/ffc.h" @@ -24,8 +25,10 @@ void dh_cache_named_group(DH *dh); FFC_PARAMS *dh_get0_params(DH *dh); int dh_get0_nid(const DH *dh); -int dh_ffc_params_fromdata(DH *dh, const OSSL_PARAM params[]); +int dh_params_fromdata(DH *dh, const OSSL_PARAM params[]); int dh_key_fromdata(DH *dh, const OSSL_PARAM params[]); +int dh_params_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]); +int dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]); int dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret); int dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret); diff --git a/include/internal/param_build_set.h b/include/internal/param_build_set.h index 36d3b914d9..d1f1863381 100644 --- a/include/internal/param_build_set.h +++ b/include/internal/param_build_set.h @@ -12,6 +12,8 @@ int ossl_param_build_set_int(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, int num); +int ossl_param_build_set_long(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, + const char *key, long num); int ossl_param_build_set_utf8_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, const char *buf); int ossl_param_build_set_octet_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index 3cca031963..bfd70c3962 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -24,7 +24,6 @@ #include "crypto/dh.h" #include "internal/sizes.h" #include "internal/nelem.h" -#include "internal/param_build_set.h" static OSSL_FUNC_keymgmt_new_fn dh_newdata; static OSSL_FUNC_keymgmt_free_fn dh_freedata; @@ -113,24 +112,6 @@ static int dh_gen_type_name2id(const char *name) return -1; } -static 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; -} - static void *dh_newdata(void *provctx) { DH *dh = NULL; @@ -215,7 +196,7 @@ static int dh_import(void *keydata, int selection, const OSSL_PARAM params[]) return 0; if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) - ok = ok && dh_ffc_params_fromdata(dh, params); + ok = ok && dh_params_fromdata(dh, params); if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) ok = ok && dh_key_fromdata(dh, params); @@ -239,7 +220,7 @@ static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, return 0; if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) - ok = ok && ossl_ffc_params_todata(dh_get0_params(dh), tmpl, NULL); + ok = ok && dh_params_todata(dh, tmpl, NULL); if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) ok = ok && dh_key_todata(dh, tmpl, NULL); @@ -266,7 +247,8 @@ err: OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), \ OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), \ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0), \ - OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0) + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), \ + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL, 0) # define DH_IMEXPORTABLE_PUBLIC_KEY \ OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0) # define DH_IMEXPORTABLE_PRIVATE_KEY \ @@ -337,8 +319,8 @@ static ossl_inline int dh_get_params(void *key, OSSL_PARAM params[]) return 0; } - return ossl_ffc_params_todata(dh_get0_params(dh), NULL, params) - && dh_key_todata(dh, NULL, params); + return dh_params_todata(dh, NULL, params) + && dh_key_todata(dh, NULL, params); } static const OSSL_PARAM dh_params[] = { -- cgit v1.2.3