Make use of CRT acquire/release in ssl_parse_certificate_verify()

Access the peer's PK through the PK acquire/release API only.

Care has to be taken not to accidentally overwrite the return
value `ret` from the CRT chain verification.
This commit is contained in:
Hanno Becker 2019-02-26 16:48:17 +00:00
parent 6cb5f86dac
commit 8c13ee615f

View file

@ -6455,6 +6455,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
void *rs_ctx )
{
int ret = 0;
int verify_ret;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->handshake->ciphersuite_info;
mbedtls_x509_crt *ca_chain;
@ -6479,7 +6480,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
/*
* Main check: verify certificate
*/
ret = mbedtls_x509_crt_verify_restartable(
verify_ret = mbedtls_x509_crt_verify_restartable(
chain,
ca_chain, ca_crl,
ssl->conf->cert_profile,
@ -6487,13 +6488,13 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
&ssl->session_negotiate->verify_result,
ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx );
if( ret != 0 )
if( verify_ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", verify_ret );
}
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
if( verify_ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
#endif
@ -6503,29 +6504,37 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECP_C)
{
const mbedtls_pk_context *pk = &chain->pk;
mbedtls_pk_context *pk;
ret = mbedtls_x509_crt_pk_acquire( chain, &pk );
if( ret != 0 )
return( ret );
/* If certificate uses an EC key, make sure the curve is OK */
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) )
ret = mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id );
mbedtls_x509_crt_pk_release( chain, pk );
if( ret != 0 )
{
ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) );
if( ret == 0 )
ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
if( verify_ret == 0 )
verify_ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
}
}
#endif /* MBEDTLS_ECP_C */
if( mbedtls_ssl_check_cert_usage( chain,
ciphersuite_info,
! ssl->conf->endpoint,
&ssl->session_negotiate->verify_result ) != 0 )
ret = mbedtls_ssl_check_cert_usage( chain,
ciphersuite_info,
! ssl->conf->endpoint,
&ssl->session_negotiate->verify_result );
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) );
if( ret == 0 )
ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
if( verify_ret == 0 )
verify_ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
}
/* mbedtls_x509_crt_verify_with_profile is supposed to report a
@ -6535,19 +6544,19 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
* functions, are treated as fatal and lead to a failure of
* ssl_parse_certificate even if verification was optional. */
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) )
( verify_ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
verify_ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) )
{
ret = 0;
verify_ret = 0;
}
if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
verify_ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
}
if( ret != 0 )
if( verify_ret != 0 )
{
uint8_t alert;
@ -6592,7 +6601,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_DEBUG_C */
return( ret );
return( verify_ret );
}
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
@ -6759,8 +6768,8 @@ crt_verify:
crt_len = chain->raw.len;
#endif /* MBEDTLS_SSL_RENEGOTIATION */
pk_start = chain->pk_raw.p;
pk_len = chain->pk_raw.len;
pk_start = chain->cache->pk_raw.p;
pk_len = chain->cache->pk_raw.len;
/* Free the CRT structures before computing
* digest and copying the peer's public key. */