DH: make the private key length importable / exportable
authorRichard Levitte <levitte@openssl.org>
Thu, 15 Oct 2020 05:10:29 +0000 (07:10 +0200)
committerRichard Levitte <levitte@openssl.org>
Mon, 19 Oct 2020 10:14:11 +0000 (12:14 +0200)
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 <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/13166)

crypto/dh/dh_ameth.c
crypto/dh/dh_backend.c
crypto/dh/dh_lib.c
crypto/param_build_set.c
include/crypto/dh.h
include/internal/param_build_set.h
providers/implementations/keymgmt/dh_kmgmt.c

index 69b166362a8a4fe39bf2ecd442d1e6071fda9e0e..49e65e4d6c8db37bfcdedfe90a67ff4c90a82d11 100644 (file)
@@ -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);
index 704f6efac1ca5088fe2936bfedc0476f0f6c931b..1ce29e652d3038fc0b222530975d5c36d75ff660 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <openssl/core_names.h>
+#include "internal/param_build_set.h"
 #include "crypto/dh.h"
 
 /*
  * 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;
+}
index 94978a2cb2b0839dda6e40df2b6df5d8342327c9..e6eba34ac9cbee32fa948e1db54990afeef27292 100644 (file)
@@ -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;
-}
index b74b0d59eeaa4178c184d91d10601b5ea8689189..1ea8097e881e69af54f898f9052c3281a41015d0 100644 (file)
@@ -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)
 {
index cd7e1e4a8907e47ebec0d7dd1403ba62d0685892..4dbd0c582c835e37f830fb610f4df39ad39c5206 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <openssl/core.h>
+#include <openssl/params.h>
 #include <openssl/dh.h>
 #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);
index 36d3b914d95615ea396f3ad1158437f94ff1599f..d1f18633816d674290db470a11417a6540125994 100644 (file)
@@ -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,
index 3cca031963e3de6bf63325f6a010515d862efff1..bfd70c3962fa7fb309d1949852d878c4c5701394 100644 (file)
@@ -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[] = {