mirror of
https://github.com/openssl/openssl.git
synced 2025-04-06 20:20:50 +08:00
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)
This commit is contained in:
parent
aee73562d1
commit
899e25643d
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user