Introduce helper function for peer CRT chain verification

This commit is contained in:
Hanno Becker 2019-02-05 14:36:34 +00:00
parent fcd9e71cdf
commit 6863619a2f

View file

@ -5981,80 +5981,20 @@ static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
return( SSL_CERTIFICATE_EXPECTED );
}
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
int authmode,
mbedtls_x509_crt *chain,
void *rs_ctx )
{
int ret = 0;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
int crt_expected;
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
? ssl->handshake->sni_authmode
: ssl->conf->authmode;
#else
const int authmode = ssl->conf->authmode;
#endif
void *rs_ctx = NULL;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
crt_expected = ssl_parse_certificate_coordinate( ssl, authmode );
if( crt_expected == SSL_CERTIFICATE_SKIP )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
goto exit;
}
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled &&
ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
{
goto crt_verify;
}
#endif
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
/* mbedtls_ssl_read_record may have sent an alert already. We
let it decide whether to alert. */
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
}
#if defined(MBEDTLS_SSL_SRV_C)
if( ssl_srv_check_client_no_crt_notification( ssl ) == 0 )
{
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
ret = 0;
else
ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
goto exit;
}
#endif /* MBEDTLS_SSL_SRV_C */
/* In case we tried to reuse a session but it failed. */
ssl_clear_peer_cert( ssl->session_negotiate );
if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 )
return( ret );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled)
ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
crt_verify:
if( ssl->handshake->ecrs_enabled)
rs_ctx = &ssl->handshake->ecrs_ctx;
#endif
if( authmode != MBEDTLS_SSL_VERIFY_NONE )
{
mbedtls_x509_crt *ca_chain;
mbedtls_x509_crl *ca_crl;
if( authmode == MBEDTLS_SSL_VERIFY_NONE )
return( 0 );
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if( ssl->handshake->sni_ca_chain != NULL )
{
@ -6072,7 +6012,7 @@ crt_verify:
* Main check: verify certificate
*/
ret = mbedtls_x509_crt_verify_restartable(
ssl->session_negotiate->peer_cert,
chain,
ca_chain, ca_crl,
ssl->conf->cert_profile,
ssl->hostname,
@ -6095,7 +6035,7 @@ crt_verify:
#if defined(MBEDTLS_ECP_C)
{
const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk;
const mbedtls_pk_context *pk = &chain->pk;
/* If certificate uses an EC key, make sure the curve is OK */
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
@ -6110,7 +6050,7 @@ crt_verify:
}
#endif /* MBEDTLS_ECP_C */
if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert,
if( mbedtls_ssl_check_cert_usage( chain,
ciphersuite_info,
! ssl->conf->endpoint,
&ssl->session_negotiate->verify_result ) != 0 )
@ -6183,8 +6123,83 @@ crt_verify:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) );
}
#endif /* MBEDTLS_DEBUG_C */
return( ret );
}
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
{
int ret = 0;
int crt_expected;
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
? ssl->handshake->sni_authmode
: ssl->conf->authmode;
#else
const int authmode = ssl->conf->authmode;
#endif
void *rs_ctx = NULL;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
crt_expected = ssl_parse_certificate_coordinate( ssl, authmode );
if( crt_expected == SSL_CERTIFICATE_SKIP )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
goto exit;
}
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled &&
ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
{
goto crt_verify;
}
#endif
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
/* mbedtls_ssl_read_record may have sent an alert already. We
let it decide whether to alert. */
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
}
#if defined(MBEDTLS_SSL_SRV_C)
if( ssl_srv_check_client_no_crt_notification( ssl ) == 0 )
{
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
ret = 0;
else
ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
goto exit;
}
#endif /* MBEDTLS_SSL_SRV_C */
/* In case we tried to reuse a session but it failed. */
ssl_clear_peer_cert( ssl->session_negotiate );
if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 )
return( ret );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled)
ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
crt_verify:
if( ssl->handshake->ecrs_enabled)
rs_ctx = &ssl->handshake->ecrs_ctx;
#endif
ret = ssl_parse_certificate_verify( ssl, authmode,
ssl->session_negotiate->peer_cert,
rs_ctx );
if( ret != 0 )
return( ret );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
exit: