[openssl] master update

shane.lontis at oracle.com shane.lontis at oracle.com
Mon Feb 22 03:40:16 UTC 2021


The branch master has been updated
       via  4718326a46ad460fefc5cc240a8599af4b5993c7 (commit)
      from  681618cfc18b4f01f2c07e823308d30f6f47504b (commit)


- Log -----------------------------------------------------------------
commit 4718326a46ad460fefc5cc240a8599af4b5993c7
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Wed Feb 17 13:00:34 2021 +1000

    Add EVP_PKEY_public_check_quick.
    
    Adding the EVP_PKEY_param_check_quick() reminded me that there are also
    partial checks for public keys as part of SP800-56A for FFC (DH named safe
    prime groups) and ECC. The code was mainly already there and just needed
    to be plumbed into the validate methods.
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14206)

-----------------------------------------------------------------------

Summary of changes:
 crypto/dh/dh_group_params.c                  | 11 +++++++++
 crypto/ec/ec_key.c                           | 37 ++++++++++++++++++----------
 crypto/evp/pmeth_check.c                     | 14 +++++++++--
 doc/man3/EVP_PKEY_check.pod                  | 14 ++++++++---
 include/crypto/dh.h                          |  1 +
 include/crypto/ec.h                          |  1 +
 include/openssl/evp.h                        |  1 +
 providers/implementations/keymgmt/dh_kmgmt.c | 13 +++++++---
 providers/implementations/keymgmt/ec_kmgmt.c | 16 +++++++++---
 util/libcrypto.num                           |  1 +
 10 files changed, 84 insertions(+), 25 deletions(-)

diff --git a/crypto/dh/dh_group_params.c b/crypto/dh/dh_group_params.c
index a752cf9a98..0f66d8969d 100644
--- a/crypto/dh/dh_group_params.c
+++ b/crypto/dh/dh_group_params.c
@@ -81,6 +81,17 @@ void dh_cache_named_group(DH *dh)
     }
 }
 
+int ossl_dh_is_named_safe_prime_group(const DH *dh)
+{
+    int id = DH_get_nid(dh);
+
+    /*
+     * Exclude RFC5114 groups (id = 1..3) since they do not have
+     * q = (p - 1) / 2
+     */
+    return (id > 3);
+}
+
 int DH_get_nid(const DH *dh)
 {
     if (dh == NULL)
diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c
index ec0b6bda85..30c524726d 100644
--- a/crypto/ec/ec_key.c
+++ b/crypto/ec/ec_key.c
@@ -442,15 +442,11 @@ err:
 }
 
 /*
- * ECC Key validation as specified in SP800-56A R3.
- * Section 5.6.2.3.3 ECC Full Public-Key Validation.
+ * ECC Partial Public-Key Validation as specified in SP800-56A R3
+ * Section 5.6.2.3.4 ECC Partial Public-Key Validation Routine.
  */
-int ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx)
+int ec_key_public_check_quick(const EC_KEY *eckey, BN_CTX *ctx)
 {
-    int ret = 0;
-    EC_POINT *point = NULL;
-    const BIGNUM *order = NULL;
-
     if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
         ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
@@ -462,21 +458,36 @@ int ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx)
         return 0;
     }
 
-    point = EC_POINT_new(eckey->group);
-    if (point == NULL)
-        return 0;
-
     /* 5.6.2.3.3 (Step 2) Test if the public key is in range */
     if (!ec_key_public_range_check(ctx, eckey)) {
         ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE);
-        goto err;
+        return 0;
     }
 
     /* 5.6.2.3.3 (Step 3) is the pub_key on the elliptic curve */
     if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
         ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE);
-        goto err;
+        return 0;
     }
+    return 1;
+}
+
+/*
+ * ECC Key validation as specified in SP800-56A R3.
+ * Section 5.6.2.3.3 ECC Full Public-Key Validation Routine.
+ */
+int ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx)
+{
+    int ret = 0;
+    EC_POINT *point = NULL;
+    const BIGNUM *order = NULL;
+
+    if (!ec_key_public_check_quick(eckey, ctx))
+        return 0;
+
+    point = EC_POINT_new(eckey->group);
+    if (point == NULL)
+        return 0;
 
     order = eckey->group->order;
     if (BN_is_zero(order)) {
diff --git a/crypto/evp/pmeth_check.c b/crypto/evp/pmeth_check.c
index 61e6db655d..112965e794 100644
--- a/crypto/evp/pmeth_check.c
+++ b/crypto/evp/pmeth_check.c
@@ -42,7 +42,7 @@ static int try_provided_check(EVP_PKEY_CTX *ctx, int selection, int checktype)
     return evp_keymgmt_validate(keymgmt, keydata, selection, checktype);
 }
 
-int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
+static int evp_pkey_public_check_combined(EVP_PKEY_CTX *ctx, int checktype)
 {
     EVP_PKEY *pkey = ctx->pkey;
     int ok;
@@ -53,7 +53,7 @@ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
     }
 
     if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
-                                 OSSL_KEYMGMT_VALIDATE_FULL_CHECK)) != -1)
+                                 checktype)) != -1)
         return ok;
 
     if (pkey->type == EVP_PKEY_NONE)
@@ -76,6 +76,16 @@ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
     return -2;
 }
 
+int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
+{
+    return evp_pkey_public_check_combined(ctx, OSSL_KEYMGMT_VALIDATE_FULL_CHECK);
+}
+
+int EVP_PKEY_public_check_quick(EVP_PKEY_CTX *ctx)
+{
+    return evp_pkey_public_check_combined(ctx, OSSL_KEYMGMT_VALIDATE_QUICK_CHECK);
+}
+
 static int evp_pkey_param_check_combined(EVP_PKEY_CTX *ctx, int checktype)
 {
     EVP_PKEY *pkey = ctx->pkey;
diff --git a/doc/man3/EVP_PKEY_check.pod b/doc/man3/EVP_PKEY_check.pod
index b5d33a41e3..4f91f8f9a2 100644
--- a/doc/man3/EVP_PKEY_check.pod
+++ b/doc/man3/EVP_PKEY_check.pod
@@ -3,7 +3,8 @@
 =head1 NAME
 
 EVP_PKEY_check, EVP_PKEY_param_check, EVP_PKEY_param_check_quick,
-EVP_PKEY_public_check, EVP_PKEY_private_check, EVP_PKEY_pairwise_check
+EVP_PKEY_public_check, EVP_PKEY_public_check_quick, EVP_PKEY_private_check,
+EVP_PKEY_pairwise_check
 - key and parameter validation functions
 
 =head1 SYNOPSIS
@@ -14,6 +15,7 @@ EVP_PKEY_public_check, EVP_PKEY_private_check, EVP_PKEY_pairwise_check
  int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
  int EVP_PKEY_param_check_quick(EVP_PKEY_CTX *ctx);
  int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_public_check_quick(EVP_PKEY_CTX *ctx);
  int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx);
  int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx);
 
@@ -30,6 +32,12 @@ provided then this function call does the same thing as EVP_PKEY_param_check().
 
 EVP_PKEY_public_check() validates the public component of the key given by B<ctx>.
 
+EVP_PKEY_public_check_quick() validates the public component of the key
+given by B<ctx> like EVP_PKEY_public_check() does. However some algorithm
+implementations may offer a quicker form of validation that omits some checks in
+order to perform a lightweight sanity check of the key. If a quicker form is not
+provided then this function call does the same thing as EVP_PKEY_public_check().
+
 EVP_PKEY_private_check() validates the private component of the key given by B<ctx>.
 
 EVP_PKEY_pairwise_check() validates that the public and private components have
@@ -60,8 +68,8 @@ L<EVP_PKEY_fromdata(3)>,
 EVP_PKEY_check(), EVP_PKEY_public_check() and EVP_PKEY_param_check() were added
 in OpenSSL 1.1.1.
 
-EVP_PKEY_param_check_quick(), EVP_PKEY_private_check() and
-EVP_PKEY_pairwise_check() were added in OpenSSL 3.0.
+EVP_PKEY_param_check_quick(), EVP_PKEY_public_check_quick(),
+EVP_PKEY_private_check() and EVP_PKEY_pairwise_check() were added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/include/crypto/dh.h b/include/crypto/dh.h
index 5673bb7ad3..eca2a03056 100644
--- a/include/crypto/dh.h
+++ b/include/crypto/dh.h
@@ -28,6 +28,7 @@ int dh_get_named_group_uid_from_size(int pbits);
 const char *dh_gen_type_id2name(int id);
 int dh_gen_type_name2id(const char *name);
 void dh_cache_named_group(DH *dh);
+int ossl_dh_is_named_safe_prime_group(const DH *dh);
 
 FFC_PARAMS *dh_get0_params(DH *dh);
 int dh_get0_nid(const DH *dh);
diff --git a/include/crypto/ec.h b/include/crypto/ec.h
index 682311b26d..347474a37b 100644
--- a/include/crypto/ec.h
+++ b/include/crypto/ec.h
@@ -60,6 +60,7 @@ int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
                    const EVP_MD *md, OSSL_LIB_CTX *libctx, const char *propq);
 
 int ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx);
+int ec_key_public_check_quick(const EC_KEY *eckey, BN_CTX *ctx);
 int ec_key_private_check(const EC_KEY *eckey);
 int ec_key_pairwise_check(const EC_KEY *eckey, BN_CTX *ctx);
 OSSL_LIB_CTX *ec_key_get_libctx(const EC_KEY *eckey);
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index aeff6de4f7..bdce18c5ee 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1827,6 +1827,7 @@ int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
 int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
 int EVP_PKEY_check(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_public_check_quick(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_param_check_quick(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx);
diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c
index 96886840f0..a967309644 100644
--- a/providers/implementations/keymgmt/dh_kmgmt.c
+++ b/providers/implementations/keymgmt/dh_kmgmt.c
@@ -345,14 +345,21 @@ static int dh_set_params(void *key, const OSSL_PARAM params[])
     return 1;
 }
 
-static int dh_validate_public(const DH *dh)
+static int dh_validate_public(const DH *dh, int checktype)
 {
     const BIGNUM *pub_key = NULL;
+    int res = 0;
 
     DH_get0_key(dh, &pub_key, NULL);
     if (pub_key == NULL)
         return 0;
-    return DH_check_pub_key_ex(dh, pub_key);
+
+    /* The partial test is only valid for named group's with q = (p - 1) / 2 */
+    if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK
+        && ossl_dh_is_named_safe_prime_group(dh))
+        return dh_check_pub_key_partial(dh, pub_key, &res);
+
+    return DH_check_pub_key(dh, pub_key, &res);
 }
 
 static int dh_validate_private(const DH *dh)
@@ -390,7 +397,7 @@ static int dh_validate(const void *keydata, int selection, int checktype)
     }
 
     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
-        ok = ok && dh_validate_public(dh);
+        ok = ok && dh_validate_public(dh, checktype);
 
     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
         ok = ok && dh_validate_private(dh);
diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c
index 33abdc8692..f612d8ed0e 100644
--- a/providers/implementations/keymgmt/ec_kmgmt.c
+++ b/providers/implementations/keymgmt/ec_kmgmt.c
@@ -852,8 +852,12 @@ int sm2_validate(const void *keydata, int selection, int checktype)
     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
         ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
 
-    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
-        ok = ok && ec_key_public_check(eck, ctx);
+    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+        if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
+            ok = ok && ec_key_public_check_quick(eck, ctx);
+        else
+            ok = ok && ec_key_public_check(eck, ctx);
+    }
 
     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
         ok = ok && sm2_key_private_check(eck);
@@ -894,8 +898,12 @@ int ec_validate(const void *keydata, int selection, int checktype)
             ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
     }
 
-    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
-        ok = ok && ec_key_public_check(eck, ctx);
+    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+        if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
+            ok = ok && ec_key_public_check_quick(eck, ctx);
+        else
+            ok = ok && ec_key_public_check(eck, ctx);
+    }
 
     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
         ok = ok && ec_key_private_check(eck);
diff --git a/util/libcrypto.num b/util/libcrypto.num
index c2e5c75486..b602ee4978 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5299,3 +5299,4 @@ EVP_PKEY_get_params                     ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_fromdata_init                  ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_fromdata_settable              ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_param_check_quick              ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_public_check_quick             ?	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list