DH, DSA, EC_KEY: Fix exporters to allow domain parameter keys
authorRichard Levitte <levitte@openssl.org>
Thu, 19 Mar 2020 21:29:10 +0000 (22:29 +0100)
committerRichard Levitte <levitte@openssl.org>
Mon, 23 Mar 2020 09:07:38 +0000 (10:07 +0100)
The export-to-provider functions for DH, DSA and EC_KEY assumed that a
public key is always present, and would fail if not.  This blocks any
attempt to export a key structure with only domain parameters.

While fixing this, we also modify the selection declaration to
evp_keymgmt_import() to be more adaptive, the diverse selection bits
are now added when the corresponding data is added to the OSSL_PARAM
array.

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11374)

crypto/dh/dh_ameth.c
crypto/dsa/dsa_ameth.c
crypto/ec/ec_ameth.c
crypto/ec/ecx_meth.c
crypto/rsa/rsa_ameth.c

index ecec5fb..877a66f 100644 (file)
@@ -498,6 +498,7 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     const BIGNUM *pub_key = DH_get0_pub_key(dh);
     const BIGNUM *priv_key = DH_get0_priv_key(dh);
     OSSL_PARAM *params;
+    int selection = 0;
     int rv;
 
     /*
@@ -518,21 +519,24 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
         if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
             return 0;
     }
-    /* A key must at least have a public part. */
-    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
-        return 0;
+    selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
+    if (pub_key != NULL) {
+        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
+            return 0;
+        selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+    }
     if (priv_key != NULL) {
         if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
                                     priv_key))
             return 0;
+        selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
     }
 
     if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
         return 0;
 
     /* We export, the provider imports */
-    rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
-                            params);
+    rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
 
     ossl_param_bld_free(params);
 
index 94f3f43..92134f9 100644 (file)
@@ -526,6 +526,7 @@ static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     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;
+    int selection = 0;
     int rv;
 
     /*
@@ -543,21 +544,25 @@ static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
         || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q)
         || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
         return 0;
-    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PUB_KEY,
-                                pub_key))
-        return 0;
+    selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
+    if (pub_key != NULL) {
+        if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PUB_KEY,
+                                    pub_key))
+            return 0;
+        selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+    }
     if (priv_key != NULL) {
         if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
                                     priv_key))
             return 0;
+        selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
     }
 
     if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
         return 0;
 
     /* We export, the provider imports */
-    rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
-                            params);
+    rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
 
     ossl_param_bld_free(params);
 
index 652086a..944fc05 100644 (file)
@@ -630,6 +630,7 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     OSSL_PARAM *params = NULL;
     const BIGNUM *priv_key = NULL;
     const EC_POINT *pub_point = NULL;
+    int selection = 0;
     int rv = 0;
 
     if (from == NULL
@@ -648,26 +649,24 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
 
     /* export the domain parameters */
     if (!ecparams_to_params(eckey, &tmpl))
-        return 0;
+        goto err;
+    selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
 
     priv_key = EC_KEY_get0_private_key(eckey);
     pub_point = EC_KEY_get0_public_key(eckey);
 
-    /* public_key must be present, priv_key is optional */
-    if (pub_point == NULL)
-        return 0;
-
-    /* convert pub_point to a octet string according to the SECG standard */
-    if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point,
-                                             POINT_CONVERSION_COMPRESSED,
-                                             &pub_key_buf, NULL)) == 0)
-        return 0;
-
-    if (!ossl_param_bld_push_octet_string(&tmpl,
-                OSSL_PKEY_PARAM_PUB_KEY,
-                pub_key_buf,
-                pub_key_buflen))
-        goto err;
+    if (pub_point != NULL) {
+        /* convert pub_point to a octet string according to the SECG standard */
+        if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point,
+                                                 POINT_CONVERSION_COMPRESSED,
+                                                 &pub_key_buf, NULL)) == 0
+            || !ossl_param_bld_push_octet_string(&tmpl,
+                                                 OSSL_PKEY_PARAM_PUB_KEY,
+                                                 pub_key_buf,
+                                                 pub_key_buflen))
+            goto err;
+        selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+    }
 
     if (priv_key != NULL) {
         size_t sz;
@@ -716,6 +715,7 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
                                         OSSL_PKEY_PARAM_PRIV_KEY,
                                         priv_key, sz))
             goto err;
+        selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
 
         /*
          * The ECDH Cofactor Mode is defined only if the EC_KEY actually
@@ -730,13 +730,13 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
                                      OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
                                      ecdh_cofactor_mode))
             goto err;
+        selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
     }
 
     params = ossl_param_bld_to_param(&tmpl);
 
     /* We export, the provider imports */
-    rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
-                            params);
+    rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
 
  err:
     ossl_param_bld_free(params);
index 5f85927..9b9536f 100644 (file)
@@ -423,6 +423,7 @@ static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     const ECX_KEY *key = from->pkey.ecx;
     OSSL_PARAM_BLD tmpl;
     OSSL_PARAM *params = NULL;
+    int selection = 0;
     int rv = 0;
 
     ossl_param_bld_init(&tmpl);
@@ -431,19 +432,20 @@ static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     if (!ossl_param_bld_push_octet_string(&tmpl, OSSL_PKEY_PARAM_PUB_KEY,
                                           key->pubkey, key->keylen))
         goto err;
+    selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
 
     if (key->privkey != NULL) {
         if (!ossl_param_bld_push_octet_string(&tmpl,
                                               OSSL_PKEY_PARAM_PRIV_KEY,
                                               key->privkey, key->keylen))
             goto err;
+        selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
     }
 
     params = ossl_param_bld_to_param(&tmpl);
 
     /* We export, the provider imports */
-    rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
-                            params);
+    rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
 
  err:
     ossl_param_bld_free(params);
index 3411b73..06d7a8c 100644 (file)
@@ -1090,6 +1090,7 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     STACK_OF(BIGNUM_const) *primes = NULL, *exps = NULL, *coeffs = NULL;
     int numprimes = 0, numexps = 0, numcoeffs = 0;
     OSSL_PARAM *params = NULL;
+    int selection = 0;
     int rv = 0;
 
     /*
@@ -1110,6 +1111,7 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
         goto err;
     if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_N, n))
         goto err;
+    selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
 
     if (d != NULL) {
         int i;
@@ -1144,6 +1146,7 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
 
         if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_D, d))
             goto err;
+        selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
 
         for (i = 0; i < numprimes; i++) {
             const BIGNUM *num = sk_BIGNUM_const_value(primes, i);
@@ -1174,8 +1177,7 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
         goto err;
 
     /* We export, the provider imports */
-    rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
-                            params);
+    rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
 
  err:
     sk_BIGNUM_const_free(primes);