diff options
-rw-r--r-- | crypto/dh/dh_group_params.c | 11 | ||||
-rw-r--r-- | crypto/ec/ec_key.c | 37 | ||||
-rw-r--r-- | crypto/evp/pmeth_check.c | 14 | ||||
-rw-r--r-- | doc/man3/EVP_PKEY_check.pod | 14 | ||||
-rw-r--r-- | include/crypto/dh.h | 1 | ||||
-rw-r--r-- | include/crypto/ec.h | 1 | ||||
-rw-r--r-- | include/openssl/evp.h | 1 | ||||
-rw-r--r-- | providers/implementations/keymgmt/dh_kmgmt.c | 13 | ||||
-rw-r--r-- | providers/implementations/keymgmt/ec_kmgmt.c | 16 | ||||
-rw-r--r-- | 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: |