diff options
author | Matt Caswell <matt@openssl.org> | 2021-02-09 15:50:05 +0000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2021-02-15 14:17:36 +1000 |
commit | 899e25643dc63a84a924d08f86d7d19613714431 (patch) | |
tree | f79751777385af9b6d4d05a8dc1739a94f59510b | |
parent | aee73562d17499f2660c14f8c150459097680a1d (diff) | |
download | openssl-new-899e25643dc63a84a924d08f86d7d19613714431.tar.gz |
Implement EVP_PKEY_param_check_quick() and use it in libssl
The low level DH API has two functions for checking parameters:
DH_check_ex() and DH_check_params_ex(). The former does a "full" check,
while the latter does a "quick" check. Most importantly it skips the
check for a safe prime. We're ok without using safe primes here because
we're doing ephemeral DH.
Now that libssl is fully using the EVP API, we need a way to specify that
we want a quick check instead of a full check. Therefore we introduce
EVP_PKEY_param_check_quick() and use it.
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/14146)
-rw-r--r-- | crypto/evp/keymgmt_meth.c | 4 | ||||
-rw-r--r-- | crypto/evp/pmeth_check.c | 31 | ||||
-rw-r--r-- | doc/man7/provider-keymgmt.pod | 9 | ||||
-rw-r--r-- | include/crypto/evp.h | 2 | ||||
-rw-r--r-- | include/openssl/core_dispatch.h | 6 | ||||
-rw-r--r-- | include/openssl/evp.h | 1 | ||||
-rw-r--r-- | providers/implementations/keymgmt/dh_kmgmt.c | 15 | ||||
-rw-r--r-- | providers/implementations/keymgmt/dsa_kmgmt.c | 2 | ||||
-rw-r--r-- | providers/implementations/keymgmt/ec_kmgmt.c | 4 | ||||
-rw-r--r-- | providers/implementations/keymgmt/ecx_kmgmt.c | 8 | ||||
-rw-r--r-- | providers/implementations/keymgmt/rsa_kmgmt.c | 2 | ||||
-rw-r--r-- | ssl/statem/statem_clnt.c | 8 | ||||
-rw-r--r-- | util/libcrypto.num | 1 |
13 files changed, 67 insertions, 26 deletions
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c index 7ef2d703f8..460fd24cec 100644 --- a/crypto/evp/keymgmt_meth.c +++ b/crypto/evp/keymgmt_meth.c @@ -404,12 +404,12 @@ int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keydata, int selection) } int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata, - int selection) + int selection, int checktype) { /* We assume valid if the implementation doesn't have a function */ if (keymgmt->validate == NULL) return 1; - return keymgmt->validate(keydata, selection); + return keymgmt->validate(keydata, selection, checktype); } int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt, diff --git a/crypto/evp/pmeth_check.c b/crypto/evp/pmeth_check.c index c9a5a7bc65..36dbb4c4e6 100644 --- a/crypto/evp/pmeth_check.c +++ b/crypto/evp/pmeth_check.c @@ -23,7 +23,7 @@ * 0 False * -1 Unsupported (use legacy path) */ -static int try_provided_check(EVP_PKEY_CTX *ctx, int selection) +static int try_provided_check(EVP_PKEY_CTX *ctx, int selection, int checktype) { EVP_KEYMGMT *keymgmt; void *keydata; @@ -39,7 +39,7 @@ static int try_provided_check(EVP_PKEY_CTX *ctx, int selection) return 0; } - return evp_keymgmt_validate(keymgmt, keydata, selection); + return evp_keymgmt_validate(keymgmt, keydata, selection, checktype); } int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx) @@ -52,7 +52,8 @@ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx) return 0; } - if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY)) != -1) + if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, + OSSL_KEYMGMT_VALIDATE_FULL_CHECK)) != -1) return ok; if (pkey->type == EVP_PKEY_NONE) @@ -75,7 +76,7 @@ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx) return -2; } -int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) +static int evp_pkey_param_check_combined(EVP_PKEY_CTX *ctx, int checktype) { EVP_PKEY *pkey = ctx->pkey; int ok; @@ -86,7 +87,8 @@ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) } if ((ok = try_provided_check(ctx, - OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)) != -1) + OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, + checktype)) != -1) return ok; if (pkey->type == EVP_PKEY_NONE) @@ -109,6 +111,16 @@ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) return -2; } +int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) +{ + return evp_pkey_param_check_combined(ctx, OSSL_KEYMGMT_VALIDATE_FULL_CHECK); +} + +int EVP_PKEY_param_check_quick(EVP_PKEY_CTX *ctx) +{ + return evp_pkey_param_check_combined(ctx, OSSL_KEYMGMT_VALIDATE_QUICK_CHECK); +} + int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx) { EVP_PKEY *pkey = ctx->pkey; @@ -119,7 +131,8 @@ int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx) return 0; } - if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) != -1) + if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, + OSSL_KEYMGMT_VALIDATE_FULL_CHECK)) != -1) return ok; /* not supported for legacy keys */ @@ -137,7 +150,8 @@ int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx) return 0; } - if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_KEYPAIR)) != -1) + if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_KEYPAIR, + OSSL_KEYMGMT_VALIDATE_FULL_CHECK)) != -1) return ok; /* not supported for legacy keys */ @@ -155,7 +169,8 @@ int EVP_PKEY_check(EVP_PKEY_CTX *ctx) return 0; } - if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_KEYPAIR)) != -1) + if ((ok = try_provided_check(ctx, OSSL_KEYMGMT_SELECT_KEYPAIR, + OSSL_KEYMGMT_VALIDATE_FULL_CHECK)) != -1) return ok; if (pkey->type == EVP_PKEY_NONE) diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod index 0095da00ca..4c1f032744 100644 --- a/doc/man7/provider-keymgmt.pod +++ b/doc/man7/provider-keymgmt.pod @@ -54,7 +54,7 @@ provider-keymgmt - The KEYMGMT library E<lt>-E<gt> provider functions int OSSL_FUNC_keymgmt_copy(void *keydata_to, const void *keydata_from, int selection); /* Key object validation */ - int OSSL_FUNC_keymgmt_validate(const void *keydata, int selection); + int OSSL_FUNC_keymgmt_validate(const void *keydata, int selection, int checktype); =head1 DESCRIPTION @@ -298,7 +298,12 @@ data subsets may cause validation of the combined data. For example, the combination of B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY> and B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY> (or B<OSSL_KEYMGMT_SELECT_KEYPAIR> for short) is expected to check that the pairwise consistency of -I<keydata> is valid. +I<keydata> is valid. The I<checktype> parameter controls what type of check is +performed on the subset of data. Two types of check are defined: +B<OSSL_KEYMGMT_VALIDATE_FULL_CHECK> and B<OSSL_KEYMGMT_VALIDATE_QUICK_CHECK>. +The interpretation of how much checking is performed in a full check versus a +quick check is key type specific. Some providers may have no distinction +between a full check and a quick check. OSSL_FUNC_keymgmt_match() should check if the data subset indicated by I<selection> in I<keydata1> and I<keydata2> match. It is assumed that diff --git a/include/crypto/evp.h b/include/crypto/evp.h index b78535aed0..1017ace03d 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -778,7 +778,7 @@ void *evp_keymgmt_load(const EVP_KEYMGMT *keymgmt, int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keyddata, int selection); int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata, - int selection); + int selection, int checktype); int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt, const void *keydata1, const void *keydata2, int selection); diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index 1689778c72..7823af7cbd 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -491,6 +491,9 @@ OSSL_CORE_MAKE_FUNC(int,rand_verify_zeroization, # define OSSL_KEYMGMT_SELECT_ALL \ ( OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS ) +# define OSSL_KEYMGMT_VALIDATE_FULL_CHECK 0 +# define OSSL_KEYMGMT_VALIDATE_QUICK_CHECK 1 + /* Basic key object creation */ # define OSSL_FUNC_KEYMGMT_NEW 1 OSSL_CORE_MAKE_FUNC(void *, keymgmt_new, (void *provctx)) @@ -551,7 +554,8 @@ OSSL_CORE_MAKE_FUNC(int, keymgmt_has, (const void *keydata, int selection)) /* Key checks - validation */ # define OSSL_FUNC_KEYMGMT_VALIDATE 22 -OSSL_CORE_MAKE_FUNC(int, keymgmt_validate, (const void *keydata, int selection)) +OSSL_CORE_MAKE_FUNC(int, keymgmt_validate, (const void *keydata, int selection, + int checktype)) /* Key checks - matching */ # define OSSL_FUNC_KEYMGMT_MATCH 23 diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 5f9de9d8b9..aeff6de4f7 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1828,6 +1828,7 @@ 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_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); int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx); diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index 1691f66f44..007ab6a5b5 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -366,7 +366,7 @@ static int dh_validate_private(const DH *dh) return dh_check_priv_key(dh, priv_key, &status);; } -static int dh_validate(const void *keydata, int selection) +static int dh_validate(const void *keydata, int selection, int checktype) { const DH *dh = keydata; int ok = 0; @@ -377,8 +377,17 @@ static int dh_validate(const void *keydata, int selection) if ((selection & DH_POSSIBLE_SELECTIONS) != 0) ok = 1; - if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) - ok = ok && DH_check_ex(dh); + if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { + /* + * Both of these functions check parameters. DH_check_params_ex() + * performs a lightweight check (e.g. it does not check that p is a + * safe prime) + */ + if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK) + ok = ok && DH_check_params_ex(dh); + else + ok = ok && DH_check_ex(dh); + } if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) ok = ok && dh_validate_public(dh); diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c index bc4591b1d6..28e8409aa2 100644 --- a/providers/implementations/keymgmt/dsa_kmgmt.c +++ b/providers/implementations/keymgmt/dsa_kmgmt.c @@ -338,7 +338,7 @@ static int dsa_validate_private(const DSA *dsa) return dsa_check_priv_key(dsa, priv_key, &status); } -static int dsa_validate(const void *keydata, int selection) +static int dsa_validate(const void *keydata, int selection, int checktype) { const DSA *dsa = keydata; int ok = 0; diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index bb479181c3..33abdc8692 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -833,7 +833,7 @@ const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx) } static -int sm2_validate(const void *keydata, int selection) +int sm2_validate(const void *keydata, int selection, int checktype) { const EC_KEY *eck = keydata; int ok = 0; @@ -868,7 +868,7 @@ int sm2_validate(const void *keydata, int selection) #endif static -int ec_validate(const void *keydata, int selection) +int ec_validate(const void *keydata, int selection, int checktype) { const EC_KEY *eck = keydata; int ok = 0; diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index 076e59eafe..3c057f3da4 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -726,22 +726,22 @@ static int ecx_validate(const void *keydata, int selection, int type, size_t key return ok; } -static int x25519_validate(const void *keydata, int selection) +static int x25519_validate(const void *keydata, int selection, int checktype) { return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN); } -static int x448_validate(const void *keydata, int selection) +static int x448_validate(const void *keydata, int selection, int checktype) { return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN); } -static int ed25519_validate(const void *keydata, int selection) +static int ed25519_validate(const void *keydata, int selection, int checktype) { return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN); } -static int ed448_validate(const void *keydata, int selection) +static int ed448_validate(const void *keydata, int selection, int checktype) { return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN); } diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c index 64779ca6be..e4e10084b8 100644 --- a/providers/implementations/keymgmt/rsa_kmgmt.c +++ b/providers/implementations/keymgmt/rsa_kmgmt.c @@ -359,7 +359,7 @@ static const OSSL_PARAM *rsa_gettable_params(void *provctx) return rsa_params; } -static int rsa_validate(const void *keydata, int selection) +static int rsa_validate(const void *keydata, int selection, int checktype) { const RSA *rsa = keydata; int ok = 0; diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 2358e2c616..e5a255d75d 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -2071,7 +2071,13 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey) EVP_PKEY_CTX_free(pctx); pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, peer_tmp, s->ctx->propq); if (pctx == NULL - || EVP_PKEY_param_check(pctx) != 1 + /* + * EVP_PKEY_param_check() will verify that the DH params are using + * a safe prime. In this context, because we're using ephemeral DH, + * we're ok with it not being a safe prime. + * EVP_PKEY_param_check_quick() skips the safe prime check. + */ + || EVP_PKEY_param_check_quick(pctx) != 1 || EVP_PKEY_public_check(pctx) != 1) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_DH_VALUE); goto err; diff --git a/util/libcrypto.num b/util/libcrypto.num index fa7a096145..5e3ee9e408 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5298,3 +5298,4 @@ EVP_PKEY_get_field_type ? 3_0_0 EXIST::FUNCTION: 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: |