[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