DSA: Add export of domain parameters to provider
authorRichard Levitte <levitte@openssl.org>
Mon, 14 Oct 2019 08:11:40 +0000 (10:11 +0200)
committerRichard Levitte <levitte@openssl.org>
Thu, 17 Oct 2019 11:01:14 +0000 (13:01 +0200)
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10169)

crypto/dsa/dsa_ameth.c
providers/implementations/keymgmt/dsa_kmgmt.c

index b72005af2c3e3439bcffa9ed04468eb1dce36bcc..ddd262bdde7e3ef6798eca9288f4dd2039543523 100644 (file)
@@ -533,7 +533,8 @@ static size_t dsa_pkey_dirty_cnt(const EVP_PKEY *pkey)
     return pkey->pkey.dsa->dirty_cnt;
 }
 
-static void *dsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
+static void *dsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt,
+                                int want_domainparams)
 {
     DSA *dsa = pk->pkey.dsa;
     OSSL_PARAM_BLD tmpl;
@@ -541,7 +542,7 @@ static void *dsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
     const BIGNUM *q = DSA_get0_q(dsa), *pub_key = DSA_get0_pub_key(dsa);
     const BIGNUM *priv_key = DSA_get0_priv_key(dsa);
     OSSL_PARAM *params;
-    void *provkey = NULL;
+    void *provdata = NULL;
 
     if (p == NULL || q == NULL || g == NULL)
         return NULL;
@@ -552,12 +553,8 @@ static void *dsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
         || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
         return NULL;
 
-    /*
-     * This may be used to pass domain parameters only without any key data -
-     * so "pub_key" is optional. We can never have a "priv_key" without a
-     * corresponding "pub_key" though.
-     */
-    if (pub_key != NULL) {
+    if (!want_domainparams) {
+        /* A key must at least have a public part. */
         if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PUB_KEY,
                                     pub_key))
             return NULL;
@@ -572,10 +569,12 @@ static void *dsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
     params = ossl_param_bld_to_param(&tmpl);
 
     /* We export, the provider imports */
-    provkey = evp_keymgmt_importkey(keymgmt, params);
+    provdata = want_domainparams
+        ? evp_keymgmt_importdomparams(keymgmt, params)
+        : evp_keymgmt_importkey(keymgmt, params);
 
     ossl_param_bld_free(params);
-    return provkey;
+    return provdata;
 }
 
 /* NB these are sorted in pkey_id order, lowest first */
index 818a451bb9bdadc6840163649cdc8a162e12337d..aae9ddac65e9a1700194c09a4993b86663dfadfe 100644 (file)
 #include <openssl/params.h>
 #include "prov/implementations.h"
 
+static OSSL_OP_keymgmt_importdomparams_fn dsa_importdomparams;
 static OSSL_OP_keymgmt_importkey_fn dsa_importkey;
 
-static int params_to_key(DSA *dsa, const OSSL_PARAM params[])
+static int params_to_domparams(DSA *dsa, const OSSL_PARAM params[])
 {
-    const OSSL_PARAM *param_p, *param_q, *param_g, *param_priv_key;
-    const OSSL_PARAM *param_pub_key;
-    BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
+    const OSSL_PARAM *param_p, *param_q, *param_g;
+    BIGNUM *p = NULL, *q = NULL, *g = NULL;
 
     if (dsa == NULL)
         return 0;
@@ -28,6 +28,35 @@ static int params_to_key(DSA *dsa, const OSSL_PARAM params[])
     param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
     param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q);
     param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
+
+    if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
+        || (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q))
+        || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)))
+        goto err;
+
+    if (!DSA_set0_pqg(dsa, p, q, g))
+        goto err;
+
+    return 1;
+
+ err:
+    BN_free(p);
+    BN_free(q);
+    BN_free(g);
+    return 0;
+}
+
+static int params_to_key(DSA *dsa, const OSSL_PARAM params[])
+{
+    const OSSL_PARAM *param_priv_key, *param_pub_key;
+    BIGNUM *priv_key = NULL, *pub_key = NULL;
+
+    if (dsa == NULL)
+        return 0;
+
+    if (!params_to_domparams(dsa, params))
+        return 0;
+
     param_priv_key =
         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PRIV_KEY);
     param_pub_key =
@@ -40,34 +69,35 @@ static int params_to_key(DSA *dsa, const OSSL_PARAM params[])
     if (param_priv_key != NULL && param_pub_key == NULL)
         return 0;
 
-    if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
-        || (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q))
-        || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g))
-        || (param_priv_key != NULL
-            && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
+    if ((param_priv_key != NULL
+         && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
         || (param_pub_key != NULL
             && !OSSL_PARAM_get_BN(param_pub_key, &pub_key)))
         goto err;
 
-    if (!DSA_set0_pqg(dsa, p, q, g))
-        goto err;
-    p = q = g = NULL;
-
     if (pub_key != NULL && !DSA_set0_key(dsa, pub_key, priv_key))
         goto err;
-    priv_key = pub_key = NULL;
 
     return 1;
 
  err:
-    BN_free(p);
-    BN_free(q);
-    BN_free(g);
     BN_free(priv_key);
     BN_free(pub_key);
     return 0;
 }
 
+static void *dsa_importdomparams(void *provctx, const OSSL_PARAM params[])
+{
+    DSA *dsa;
+
+    if ((dsa = DSA_new()) == NULL
+        || !params_to_domparams(dsa, params)) {
+        DSA_free(dsa);
+        dsa = NULL;
+    }
+    return dsa;
+}
+
 static void *dsa_importkey(void *provctx, const OSSL_PARAM params[])
 {
     DSA *dsa;
@@ -85,6 +115,8 @@ const OSSL_DISPATCH dsa_keymgmt_functions[] = {
      * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also
      * implement OSSL_FUNC_KEYMGMT_EXPORTKEY.
      */
+    { OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS, (void (*)(void))dsa_importdomparams },
+    { OSSL_FUNC_KEYMGMT_FREEDOMPARAMS, (void (*)(void))DSA_free },
     { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dsa_importkey },
     { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DSA_free },
     { 0, NULL }