]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add EVP_PKEY_public_check_quick.
authorShane Lontis <shane.lontis@oracle.com>
Wed, 17 Feb 2021 03:00:34 +0000 (13:00 +1000)
committerShane Lontis <shane.lontis@oracle.com>
Mon, 22 Feb 2021 03:31:31 +0000 (13:31 +1000)
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@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14206)

crypto/dh/dh_group_params.c
crypto/ec/ec_key.c
crypto/evp/pmeth_check.c
doc/man3/EVP_PKEY_check.pod
include/crypto/dh.h
include/crypto/ec.h
include/openssl/evp.h
providers/implementations/keymgmt/dh_kmgmt.c
providers/implementations/keymgmt/ec_kmgmt.c
util/libcrypto.num

index a752cf9a9834cba11ae9e6ca2c219e909fce5d9e..0f66d8969df2ff824ac4f8a08daa3cdd08fa94ac 100644 (file)
@@ -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)
index ec0b6bda854026c5fc2a9db49acc7cdd3af0283f..30c524726d007dda75e5ffc42286860d7ddd5ef1 100644 (file)
@@ -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)) {
index 61e6db655da111218a91368d5af7861ac49898be..112965e79449bf83517874d3877ac4ce2008fd55 100644 (file)
@@ -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;
index b5d33a41e3955cea355755790e939090225c2d83..4f91f8f9a2c7ae28e823f766f286718455128da2 100644 (file)
@@ -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
 
index 5673bb7ad38ff99fb192452f65eb093f11f4c860..eca2a0305684f9b91be3545cd13c60be91e9ad50 100644 (file)
@@ -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);
index 682311b26de5d95e63ee4432365ef4b43b1374a4..347474a37b546d1a5c6d833ef0f353a29388c5ac 100644 (file)
@@ -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);
index aeff6de4f7b8cc862987c68e9255b7172523110e..bdce18c5ee8408e6aedd3e21e76a0e9b3b785aed 100644 (file)
@@ -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);
index 96886840f0296342aaf6505580fec911602b278c..a967309644e23b8f533aaf5f09aaa02e35308524 100644 (file)
@@ -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);
index 33abdc86926cdd8a5ffc686798139fd579b65974..f612d8ed0e746c0c21d258e15478fbc18e11d978 100644 (file)
@@ -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);
index c2e5c754868699672db7b7ffc95e208804f8a7d3..b602ee4978c1972a99e4609b6a3478ccb92d1f30 100644 (file)
@@ -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: