Merge pull request #1265 from mpg/refactor-tls123-verif

[3.6] Refactor TLS 1.2/1.3 certificate verification code
This commit is contained in:
Manuel Pégourié-Gonnard 2024-08-21 23:42:14 +02:00 committed by GitHub
commit 6298d73f5e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 495 additions and 462 deletions

View File

@ -0,0 +1,18 @@
Bugfix
* Fixed a regression introduced in 3.6.0 where the CA callback set with
mbedtls_ssl_conf_ca_cb() would stop working when connections were
upgraded to TLS 1.3. Fixed by adding support for the CA callback with TLS
1.3.
* Fixed a regression introduced in 3.6.0 where clients that relied on
optional/none authentication mode, by calling mbedtls_ssl_conf_authmode()
with MBEDTLS_SSL_VERIFY_OPTIONAL or MBEDTLS_SSL_VERIFY_NONE, would stop
working when connections were upgraded to TLS 1.3. Fixed by adding
support for optional/none with TLS 1.3 as well. Note that the TLS 1.3
standard makes server authentication mandatory; users are advised not to
use authmode none, and to carefully check the results when using optional
mode.
* Fixed a regression introduced in 3.6.0 where context-specific certificate
verify callbacks, set with mbedtls_ssl_set_verify() as opposed to
mbedtls_ssl_conf_verify(), would stop working when connections were
upgraded to TLS 1.3. Fixed by adding support for context-specific verify
callback in TLS 1.3.

View File

@ -1674,18 +1674,53 @@ static inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl)
}
/*
* Check usage of a certificate wrt extensions:
* keyUsage, extendedKeyUsage (later), and nSCertType (later).
* Verify a certificate.
*
* Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we
* check a cert we received from them)!
* [in/out] ssl: misc. things read
* ssl->session_negotiate->verify_result updated
* [in] authmode: one of MBEDTLS_SSL_VERIFY_{NONE,OPTIONAL,REQUIRED}
* [in] chain: the certificate chain to verify (ie the peer's chain)
* [in] ciphersuite_info: For TLS 1.2, this session's ciphersuite;
* for TLS 1.3, may be left NULL.
* [in] rs_ctx: restart context if restartable ECC is in use;
* leave NULL for no restartable behaviour.
*
* Return:
* - 0 if the handshake should continue. Depending on the
* authmode it means:
* - REQUIRED: the certificate was found to be valid, trusted & acceptable.
* ssl->session_negotiate->verify_result is 0.
* - OPTIONAL: the certificate may or may not be acceptable, but
* ssl->session_negotiate->verify_result was updated with the result.
* - NONE: the certificate wasn't even checked.
* - MBEDTLS_ERR_X509_CERT_VERIFY_FAILED or MBEDTLS_ERR_SSL_BAD_CERTIFICATE if
* the certificate was found to be invalid/untrusted/unacceptable and the
* handshake should be aborted (can only happen with REQUIRED).
* - another error code if another error happened (out-of-memory, etc.)
*/
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl,
int authmode,
mbedtls_x509_crt *chain,
const mbedtls_ssl_ciphersuite_t *ciphersuite_info,
void *rs_ctx);
/*
* Check usage of a certificate wrt usage extensions:
* keyUsage and extendedKeyUsage.
* (Note: nSCertType is deprecated and not standard, we don't check it.)
*
* Note: if tls_version is 1.3, ciphersuite is ignored and can be NULL.
*
* Note: recv_endpoint is the receiver's endpoint.
*
* Return 0 if everything is OK, -1 if not.
*/
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
const mbedtls_ssl_ciphersuite_t *ciphersuite,
int cert_endpoint,
int recv_endpoint,
mbedtls_ssl_protocol_version tls_version,
uint32_t *flags);
#endif /* MBEDTLS_X509_CRT_PARSE_C */

View File

@ -1354,29 +1354,6 @@ static int ssl_conf_check(const mbedtls_ssl_context *ssl)
return ret;
}
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
/* RFC 8446 section 4.4.3
*
* If the verification fails, the receiver MUST terminate the handshake with
* a "decrypt_error" alert.
*
* If the client is configured as TLS 1.3 only with optional verify, return
* bad config.
*
*/
if (mbedtls_ssl_conf_tls13_is_ephemeral_enabled(
(mbedtls_ssl_context *) ssl) &&
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
ssl->conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
ssl->conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
ssl->conf->authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) {
MBEDTLS_SSL_DEBUG_MSG(
1, ("Optional verify auth mode "
"is not available for TLS 1.3 client"));
return MBEDTLS_ERR_SSL_BAD_CONFIG;
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
if (ssl->conf->f_rng == NULL) {
MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
return MBEDTLS_ERR_SSL_NO_RNG;
@ -6358,71 +6335,6 @@ const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id)
}
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C)
int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
const mbedtls_ssl_ciphersuite_t *ciphersuite,
int cert_endpoint,
uint32_t *flags)
{
int ret = 0;
unsigned int usage = 0;
const char *ext_oid;
size_t ext_len;
if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) {
/* Server part of the key exchange */
switch (ciphersuite->key_exchange) {
case MBEDTLS_KEY_EXCHANGE_RSA:
case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
break;
case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
break;
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
usage = MBEDTLS_X509_KU_KEY_AGREEMENT;
break;
/* Don't use default: we want warnings when adding new values */
case MBEDTLS_KEY_EXCHANGE_NONE:
case MBEDTLS_KEY_EXCHANGE_PSK:
case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
usage = 0;
}
} else {
/* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */
usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
}
if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) {
*flags |= MBEDTLS_X509_BADCERT_KEY_USAGE;
ret = -1;
}
if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) {
ext_oid = MBEDTLS_OID_SERVER_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
} else {
ext_oid = MBEDTLS_OID_CLIENT_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
}
if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) {
*flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;
ret = -1;
}
return ret;
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,
const mbedtls_md_type_t md,
@ -7941,196 +7853,6 @@ static int ssl_parse_certificate_coordinate(mbedtls_ssl_context *ssl,
return SSL_CERTIFICATE_EXPECTED;
}
MBEDTLS_CHECK_RETURN_CRITICAL
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->handshake->ciphersuite_info;
int have_ca_chain = 0;
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
void *p_vrfy;
if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
return 0;
}
if (ssl->f_vrfy != NULL) {
MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback"));
f_vrfy = ssl->f_vrfy;
p_vrfy = ssl->p_vrfy;
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback"));
f_vrfy = ssl->conf->f_vrfy;
p_vrfy = ssl->conf->p_vrfy;
}
/*
* Main check: verify certificate
*/
#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
if (ssl->conf->f_ca_cb != NULL) {
((void) rs_ctx);
have_ca_chain = 1;
MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification"));
ret = mbedtls_x509_crt_verify_with_ca_cb(
chain,
ssl->conf->f_ca_cb,
ssl->conf->p_ca_cb,
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
f_vrfy, p_vrfy);
} else
#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
{
mbedtls_x509_crt *ca_chain;
mbedtls_x509_crl *ca_crl;
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if (ssl->handshake->sni_ca_chain != NULL) {
ca_chain = ssl->handshake->sni_ca_chain;
ca_crl = ssl->handshake->sni_ca_crl;
} else
#endif
{
ca_chain = ssl->conf->ca_chain;
ca_crl = ssl->conf->ca_crl;
}
if (ca_chain != NULL) {
have_ca_chain = 1;
}
ret = mbedtls_x509_crt_verify_restartable(
chain,
ca_chain, ca_crl,
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
f_vrfy, p_vrfy, rs_ctx);
}
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
}
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
}
#endif
/*
* Secondary checks: always done, but change 'ret' only if it was 0
*/
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
{
const mbedtls_pk_context *pk = &chain->pk;
/* If certificate uses an EC key, make sure the curve is OK.
* This is a public key, so it can't be opaque, so can_do() is a good
* enough check to ensure pk_ec() is safe to use here. */
if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) {
/* and in the unlikely case the above assumption no longer holds
* we are making sure that pk_ec() here does not return a NULL
*/
mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(pk);
if (grp_id == MBEDTLS_ECP_DP_NONE) {
MBEDTLS_SSL_DEBUG_MSG(1, ("invalid group ID"));
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}
if (mbedtls_ssl_check_curve(ssl, grp_id) != 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_CERTIFICATE;
}
}
}
}
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
if (mbedtls_ssl_check_cert_usage(chain,
ciphersuite_info,
!ssl->conf->endpoint,
&ssl->session_negotiate->verify_result) != 0) {
MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
if (ret == 0) {
ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
}
}
/* mbedtls_x509_crt_verify_with_profile is supposed to report a
* verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
* with details encoded in the verification flags. All other kinds
* of error codes, including those from the user provided f_vrfy
* 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_CERTIFICATE)) {
ret = 0;
}
if (have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {
MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain"));
ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
}
if (ret != 0) {
uint8_t alert;
/* The certificate may have been rejected for several reasons.
Pick one and send the corresponding alert. Which alert to send
may be a subject of debate in some cases. */
if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) {
alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
} else {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
}
mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
alert);
}
#if defined(MBEDTLS_DEBUG_C)
if (ssl->session_negotiate->verify_result != 0) {
MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
(unsigned int) ssl->session_negotiate->verify_result));
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
}
#endif /* MBEDTLS_DEBUG_C */
return ret;
}
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_remember_peer_crt_digest(mbedtls_ssl_context *ssl,
@ -8187,6 +7909,7 @@ int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl)
{
int ret = 0;
int crt_expected;
/* Authmode: precedence order is SNI if used else configuration */
#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
@ -8266,8 +7989,9 @@ crt_verify:
}
#endif
ret = ssl_parse_certificate_verify(ssl, authmode,
chain, rs_ctx);
ret = mbedtls_ssl_verify_certificate(ssl, authmode, chain,
ssl->handshake->ciphersuite_info,
rs_ctx);
if (ret != 0) {
goto exit;
}
@ -9933,4 +9657,274 @@ int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session,
return 0;
}
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
/*
* The following functions are used by 1.2 and 1.3, client and server.
*/
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
const mbedtls_ssl_ciphersuite_t *ciphersuite,
int recv_endpoint,
mbedtls_ssl_protocol_version tls_version,
uint32_t *flags)
{
int ret = 0;
unsigned int usage = 0;
const char *ext_oid;
size_t ext_len;
/*
* keyUsage
*/
/* Note: don't guard this with MBEDTLS_SSL_CLI_C because the server wants
* to check what a compliant client will think while choosing which cert
* to send to the client. */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
recv_endpoint == MBEDTLS_SSL_IS_CLIENT) {
/* TLS 1.2 server part of the key exchange */
switch (ciphersuite->key_exchange) {
case MBEDTLS_KEY_EXCHANGE_RSA:
case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
break;
case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
break;
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
usage = MBEDTLS_X509_KU_KEY_AGREEMENT;
break;
/* Don't use default: we want warnings when adding new values */
case MBEDTLS_KEY_EXCHANGE_NONE:
case MBEDTLS_KEY_EXCHANGE_PSK:
case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
usage = 0;
}
} else
#endif
{
/* This is either TLS 1.3 authentication, which always uses signatures,
* or 1.2 client auth: rsa_sign and mbedtls_ecdsa_sign are the only
* options we implement, both using signatures. */
(void) tls_version;
(void) ciphersuite;
usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
}
if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) {
*flags |= MBEDTLS_X509_BADCERT_KEY_USAGE;
ret = -1;
}
/*
* extKeyUsage
*/
if (recv_endpoint == MBEDTLS_SSL_IS_CLIENT) {
ext_oid = MBEDTLS_OID_SERVER_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
} else {
ext_oid = MBEDTLS_OID_CLIENT_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
}
if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) {
*flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;
ret = -1;
}
return ret;
}
int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl,
int authmode,
mbedtls_x509_crt *chain,
const mbedtls_ssl_ciphersuite_t *ciphersuite_info,
void *rs_ctx)
{
if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
return 0;
}
/*
* Primary check: use the appropriate X.509 verification function
*/
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
void *p_vrfy;
if (ssl->f_vrfy != NULL) {
MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback"));
f_vrfy = ssl->f_vrfy;
p_vrfy = ssl->p_vrfy;
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback"));
f_vrfy = ssl->conf->f_vrfy;
p_vrfy = ssl->conf->p_vrfy;
}
int ret = 0;
int have_ca_chain_or_callback = 0;
#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
if (ssl->conf->f_ca_cb != NULL) {
((void) rs_ctx);
have_ca_chain_or_callback = 1;
MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification"));
ret = mbedtls_x509_crt_verify_with_ca_cb(
chain,
ssl->conf->f_ca_cb,
ssl->conf->p_ca_cb,
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
f_vrfy, p_vrfy);
} else
#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
{
mbedtls_x509_crt *ca_chain;
mbedtls_x509_crl *ca_crl;
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if (ssl->handshake->sni_ca_chain != NULL) {
ca_chain = ssl->handshake->sni_ca_chain;
ca_crl = ssl->handshake->sni_ca_crl;
} else
#endif
{
ca_chain = ssl->conf->ca_chain;
ca_crl = ssl->conf->ca_crl;
}
if (ca_chain != NULL) {
have_ca_chain_or_callback = 1;
}
ret = mbedtls_x509_crt_verify_restartable(
chain,
ca_chain, ca_crl,
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
f_vrfy, p_vrfy, rs_ctx);
}
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
}
#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
}
#endif
/*
* Secondary checks: always done, but change 'ret' only if it was 0
*/
/* With TLS 1.2 and ECC certs, check that the curve used by the
* certificate is on our list of acceptable curves.
*
* With TLS 1.3 this is not needed because the curve is part of the
* signature algorithm (eg ecdsa_secp256r1_sha256) which is checked when
* we validate the signature made with the key associated to this cert.
*/
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_PK_HAVE_ECC_KEYS)
if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
mbedtls_pk_can_do(&chain->pk, MBEDTLS_PK_ECKEY)) {
if (mbedtls_ssl_check_curve(ssl, mbedtls_pk_get_ec_group_id(&chain->pk)) != 0) {
MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (EC key curve)"));
ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
if (ret == 0) {
ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
}
}
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_PK_HAVE_ECC_KEYS */
/* Check X.509 usage extensions (keyUsage, extKeyUsage) */
if (mbedtls_ssl_check_cert_usage(chain,
ciphersuite_info,
ssl->conf->endpoint,
ssl->tls_version,
&ssl->session_negotiate->verify_result) != 0) {
MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
if (ret == 0) {
ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
}
}
/* With authmode optional, we want to keep going if the certificate was
* unacceptable, but still fail on other errors (out of memory etc),
* including fatal errors from the f_vrfy callback.
*
* The only acceptable errors are:
* - MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: cert rejected by primary check;
* - MBEDTLS_ERR_SSL_BAD_CERTIFICATE: cert rejected by secondary checks.
* Anything else is a fatal error. */
if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) {
ret = 0;
}
/* Return a specific error as this is a user error: inconsistent
* configuration - can't verify without trust anchors. */
if (have_ca_chain_or_callback == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {
MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain"));
ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
}
if (ret != 0) {
uint8_t alert;
/* The certificate may have been rejected for several reasons.
Pick one and send the corresponding alert. Which alert to send
may be a subject of debate in some cases. */
if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) {
alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) {
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
} else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
} else {
alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
}
mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
alert);
}
#if defined(MBEDTLS_DEBUG_C)
if (ssl->session_negotiate->verify_result != 0) {
MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
(unsigned int) ssl->session_negotiate->verify_result));
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
}
#endif /* MBEDTLS_DEBUG_C */
return ret;
}
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_TLS_C */

View File

@ -756,7 +756,9 @@ static int ssl_pick_cert(mbedtls_ssl_context *ssl,
* and decrypting with the same RSA key.
*/
if (mbedtls_ssl_check_cert_usage(cur->cert, ciphersuite_info,
MBEDTLS_SSL_IS_SERVER, &flags) != 0) {
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_VERSION_TLS1_2,
&flags) != 0) {
MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: "
"(extended) key usage extension"));
continue;

View File

@ -472,6 +472,7 @@ int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,
mbedtls_free(ssl->session_negotiate->peer_cert);
}
/* This is used by ssl_tls13_validate_certificate() */
if (certificate_list_len == 0) {
ssl->session_negotiate->peer_cert = NULL;
ret = 0;
@ -627,25 +628,13 @@ int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
{
int ret = 0;
int authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
mbedtls_x509_crt *ca_chain;
mbedtls_x509_crl *ca_crl;
const char *ext_oid;
size_t ext_len;
uint32_t verify_result = 0;
/* If SNI was used, overwrite authentication mode
* from the configuration. */
#if defined(MBEDTLS_SSL_SRV_C)
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) {
authmode = ssl->handshake->sni_authmode;
} else
#endif
authmode = ssl->conf->authmode;
}
/* Authmode: precedence order is SNI if used else configuration */
#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
/*
@ -677,6 +666,11 @@ static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
#endif /* MBEDTLS_SSL_SRV_C */
#if defined(MBEDTLS_SSL_CLI_C)
/* Regardless of authmode, the server is not allowed to send an empty
* certificate chain. (Last paragraph before 4.4.2.1 in RFC 8446: "The
* server's certificate_list MUST always be non-empty.") With authmode
* optional/none, we continue the handshake if we can't validate the
* server's cert, but we still break it if no certificate was sent. */
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT,
MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE);
@ -685,124 +679,9 @@ static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
#endif /* MBEDTLS_SSL_CLI_C */
}
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if (ssl->handshake->sni_ca_chain != NULL) {
ca_chain = ssl->handshake->sni_ca_chain;
ca_crl = ssl->handshake->sni_ca_crl;
} else
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
{
ca_chain = ssl->conf->ca_chain;
ca_crl = ssl->conf->ca_crl;
}
/*
* Main check: verify certificate
*/
ret = mbedtls_x509_crt_verify_with_profile(
ssl->session_negotiate->peer_cert,
ca_chain, ca_crl,
ssl->conf->cert_profile,
ssl->hostname,
&verify_result,
ssl->conf->f_vrfy, ssl->conf->p_vrfy);
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
}
/*
* Secondary checks: always done, but change 'ret' only if it was 0
*/
/* keyUsage */
if ((mbedtls_x509_crt_check_key_usage(
ssl->session_negotiate->peer_cert,
MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0)) {
MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
if (ret == 0) {
ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
}
verify_result |= MBEDTLS_X509_BADCERT_KEY_USAGE;
}
/* extKeyUsage */
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
ext_oid = MBEDTLS_OID_SERVER_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
} else {
ext_oid = MBEDTLS_OID_CLIENT_AUTH;
ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
}
if ((mbedtls_x509_crt_check_extended_key_usage(
ssl->session_negotiate->peer_cert,
ext_oid, ext_len) != 0)) {
MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
if (ret == 0) {
ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
}
verify_result |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;
}
/* mbedtls_x509_crt_verify_with_profile is supposed to report a
* verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
* with details encoded in the verification flags. All other kinds
* of error codes, including those from the user provided f_vrfy
* functions, are treated as fatal and lead to a failure of
* mbedtls_ssl_tls13_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_CERTIFICATE)) {
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;
}
if (ret != 0) {
/* The certificate may have been rejected for several reasons.
Pick one and send the corresponding alert. Which alert to send
may be a subject of debate in some cases. */
if (verify_result & MBEDTLS_X509_BADCERT_OTHER) {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED, ret);
} else if (verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret);
} else if (verify_result & (MBEDTLS_X509_BADCERT_KEY_USAGE |
MBEDTLS_X509_BADCERT_EXT_KEY_USAGE |
MBEDTLS_X509_BADCERT_NS_CERT_TYPE |
MBEDTLS_X509_BADCERT_BAD_PK |
MBEDTLS_X509_BADCERT_BAD_KEY)) {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, ret);
} else if (verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED, ret);
} else if (verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED, ret);
} else if (verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA, ret);
} else {
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN, ret);
}
}
#if defined(MBEDTLS_DEBUG_C)
if (verify_result != 0) {
MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
(unsigned int) verify_result));
} else {
MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
}
#endif /* MBEDTLS_DEBUG_C */
ssl->session_negotiate->verify_result = verify_result;
return ret;
return mbedtls_ssl_verify_certificate(ssl, authmode,
ssl->session_negotiate->peer_cert,
NULL, NULL);
}
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
MBEDTLS_CHECK_RETURN_CRITICAL

View File

@ -2155,7 +2155,7 @@ run_test "TLS: password protected server key, two certificates" \
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "CA callback on client" \
"$P_SRV debug_level=3" \
"$P_CLI force_version=tls12 ca_callback=1 debug_level=3 " \
"$P_CLI ca_callback=1 debug_level=3 " \
0 \
-c "use CA callback for X.509 CRT verification" \
-S "error" \
@ -2165,7 +2165,7 @@ requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
requires_config_enabled MBEDTLS_X509_CRT_PARSE_C
requires_hash_alg SHA_256
run_test "CA callback on server" \
"$P_SRV force_version=tls12 auth_mode=required" \
"$P_SRV auth_mode=required" \
"$P_CLI ca_callback=1 debug_level=3 crt_file=$DATA_FILES_PATH/server5.crt \
key_file=$DATA_FILES_PATH/server5.key" \
0 \
@ -2722,9 +2722,10 @@ run_test "Single supported algorithm sending: openssl client" \
0
# Tests for certificate verification callback
requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
run_test "Configuration-specific CRT verification callback" \
"$P_SRV debug_level=3" \
"$P_CLI force_version=tls12 context_crt_cb=0 debug_level=3" \
"$P_CLI context_crt_cb=0 debug_level=3" \
0 \
-S "error" \
-c "Verify requested for " \
@ -2732,9 +2733,10 @@ run_test "Configuration-specific CRT verification callback" \
-C "Use context-specific verification callback" \
-C "error"
requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
run_test "Context-specific CRT verification callback" \
"$P_SRV debug_level=3" \
"$P_CLI force_version=tls12 context_crt_cb=1 debug_level=3" \
"$P_CLI context_crt_cb=1 debug_level=3" \
0 \
-S "error" \
-c "Verify requested for " \
@ -5809,38 +5811,78 @@ run_test "DER format: with 9 trailing random bytes" \
# Tests for auth_mode, there are duplicated tests using ca callback for authentication
# When updating these tests, modify the matching authentication tests accordingly
# The next 4 cases test the 3 auth modes with a badly signed server cert.
requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
run_test "Authentication: server badcert, client required" \
"$P_SRV crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
"$P_CLI debug_level=1 auth_mode=required" \
"$P_CLI debug_level=3 auth_mode=required" \
1 \
-c "x509_verify_cert() returned" \
-c "! The certificate is not correctly signed by the trusted CA" \
-c "! mbedtls_ssl_handshake returned" \
-c "send alert level=2 message=48" \
-c "X509 - Certificate verification failed"
# MBEDTLS_X509_BADCERT_NOT_TRUSTED -> MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA
# We don't check that the server receives the alert because it might
# detect that its write end of the connection is closed and abort
# before reading the alert message.
run_test "Authentication: server badcert, client required (1.2)" \
"$P_SRV crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
"$P_CLI force_version=tls12 debug_level=3 auth_mode=required" \
1 \
-c "x509_verify_cert() returned" \
-c "! The certificate is not correctly signed by the trusted CA" \
-c "! mbedtls_ssl_handshake returned" \
-c "send alert level=2 message=48" \
-c "X509 - Certificate verification failed"
# MBEDTLS_X509_BADCERT_NOT_TRUSTED -> MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA
run_test "Authentication: server badcert, client optional" \
"$P_SRV crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
"$P_CLI force_version=tls12 debug_level=1 auth_mode=optional" \
"$P_CLI force_version=tls13 debug_level=3 auth_mode=optional" \
0 \
-c "x509_verify_cert() returned" \
-c "! The certificate is not correctly signed by the trusted CA" \
-C "! mbedtls_ssl_handshake returned" \
-C "send alert level=2 message=48" \
-C "X509 - Certificate verification failed"
requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
run_test "Authentication: server goodcert, client optional, no trusted CA" \
"$P_SRV" \
"$P_CLI force_version=tls12 debug_level=3 auth_mode=optional ca_file=none ca_path=none" \
run_test "Authentication: server badcert, client optional (1.2)" \
"$P_SRV crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
"$P_CLI force_version=tls12 debug_level=3 auth_mode=optional" \
0 \
-c "x509_verify_cert() returned" \
-c "! The certificate is not correctly signed by the trusted CA" \
-c "! Certificate verification flags"\
-C "! mbedtls_ssl_handshake returned" \
-C "X509 - Certificate verification failed" \
-C "SSL - No CA Chain is set, but required to operate"
-C "send alert level=2 message=48" \
-C "X509 - Certificate verification failed"
run_test "Authentication: server badcert, client none" \
"$P_SRV crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
"$P_CLI debug_level=3 auth_mode=none" \
0 \
-C "x509_verify_cert() returned" \
-C "! The certificate is not correctly signed by the trusted CA" \
-C "! mbedtls_ssl_handshake returned" \
-C "send alert level=2 message=48" \
-C "X509 - Certificate verification failed"
run_test "Authentication: server badcert, client none (1.2)" \
"$P_SRV crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
"$P_CLI force_version=tls12 debug_level=3 auth_mode=none" \
0 \
-C "x509_verify_cert() returned" \
-C "! The certificate is not correctly signed by the trusted CA" \
-C "! mbedtls_ssl_handshake returned" \
-C "send alert level=2 message=48" \
-C "X509 - Certificate verification failed"
requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
run_test "Authentication: server goodcert, client required, no trusted CA" \
@ -5853,6 +5895,65 @@ run_test "Authentication: server goodcert, client required, no trusted CA" \
-c "! mbedtls_ssl_handshake returned" \
-c "SSL - No CA Chain is set, but required to operate"
requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
run_test "Authentication: server goodcert, client required, no trusted CA (1.2)" \
"$P_SRV force_version=tls12" \
"$P_CLI debug_level=3 auth_mode=required ca_file=none ca_path=none" \
1 \
-c "x509_verify_cert() returned" \
-c "! The certificate is not correctly signed by the trusted CA" \
-c "! Certificate verification flags"\
-c "! mbedtls_ssl_handshake returned" \
-c "SSL - No CA Chain is set, but required to operate"
requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
run_test "Authentication: server goodcert, client optional, no trusted CA" \
"$P_SRV" \
"$P_CLI debug_level=3 auth_mode=optional ca_file=none ca_path=none" \
0 \
-c "x509_verify_cert() returned" \
-c "! The certificate is not correctly signed by the trusted CA" \
-c "! Certificate verification flags"\
-C "! mbedtls_ssl_handshake returned" \
-C "X509 - Certificate verification failed" \
-C "SSL - No CA Chain is set, but required to operate"
requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
run_test "Authentication: server goodcert, client optional, no trusted CA (1.2)" \
"$P_SRV" \
"$P_CLI force_version=tls12 debug_level=3 auth_mode=optional ca_file=none ca_path=none" \
0 \
-c "x509_verify_cert() returned" \
-c "! The certificate is not correctly signed by the trusted CA" \
-c "! Certificate verification flags"\
-C "! mbedtls_ssl_handshake returned" \
-C "X509 - Certificate verification failed" \
-C "SSL - No CA Chain is set, but required to operate"
requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
run_test "Authentication: server goodcert, client none, no trusted CA" \
"$P_SRV" \
"$P_CLI debug_level=3 auth_mode=none ca_file=none ca_path=none" \
0 \
-C "x509_verify_cert() returned" \
-C "! The certificate is not correctly signed by the trusted CA" \
-C "! Certificate verification flags"\
-C "! mbedtls_ssl_handshake returned" \
-C "X509 - Certificate verification failed" \
-C "SSL - No CA Chain is set, but required to operate"
requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
run_test "Authentication: server goodcert, client none, no trusted CA (1.2)" \
"$P_SRV" \
"$P_CLI force_version=tls12 debug_level=3 auth_mode=none ca_file=none ca_path=none" \
0 \
-C "x509_verify_cert() returned" \
-C "! The certificate is not correctly signed by the trusted CA" \
-C "! Certificate verification flags"\
-C "! mbedtls_ssl_handshake returned" \
-C "X509 - Certificate verification failed" \
-C "SSL - No CA Chain is set, but required to operate"
# The purpose of the next two tests is to test the client's behaviour when receiving a server
# certificate with an unsupported elliptic curve. This should usually not happen because
# the client informs the server about the supported curves - it does, though, in the
@ -5878,16 +5979,6 @@ run_test "Authentication: server ECDH p256v1, client optional, p256v1 unsuppo
-c "! Certificate verification flags"\
-c "bad server certificate (ECDH curve)" # Expect failure only at ECDH params check
run_test "Authentication: server badcert, client none" \
"$P_SRV crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
"$P_CLI force_version=tls12 debug_level=1 auth_mode=none" \
0 \
-C "x509_verify_cert() returned" \
-C "! The certificate is not correctly signed by the trusted CA" \
-C "! mbedtls_ssl_handshake returned" \
-C "X509 - Certificate verification failed"
requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
run_test "Authentication: client SHA256, server required" \
"$P_SRV auth_mode=required" \
@ -6098,7 +6189,7 @@ requires_full_size_output_buffer
run_test "Authentication: server max_int+1 chain, client optional" \
"$P_SRV crt_file=$DATA_FILES_PATH/dir-maxpath/c10.pem \
key_file=$DATA_FILES_PATH/dir-maxpath/10.key" \
"$P_CLI force_version=tls12 server_name=CA10 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt \
"$P_CLI server_name=CA10 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt \
auth_mode=optional" \
1 \
-c "X509 - A fatal error occurred"
@ -6219,7 +6310,7 @@ requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: server badcert, client required" \
"$P_SRV crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
"$P_CLI force_version=tls12 ca_callback=1 debug_level=3 auth_mode=required" \
"$P_CLI ca_callback=1 debug_level=3 auth_mode=required" \
1 \
-c "use CA callback for X.509 CRT verification" \
-c "x509_verify_cert() returned" \
@ -6231,7 +6322,7 @@ requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: server badcert, client optional" \
"$P_SRV crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
"$P_CLI force_version=tls12 ca_callback=1 debug_level=3 auth_mode=optional" \
"$P_CLI ca_callback=1 debug_level=3 auth_mode=optional" \
0 \
-c "use CA callback for X.509 CRT verification" \
-c "x509_verify_cert() returned" \
@ -6239,6 +6330,18 @@ run_test "Authentication, CA callback: server badcert, client optional" \
-C "! mbedtls_ssl_handshake returned" \
-C "X509 - Certificate verification failed"
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: server badcert, client none" \
"$P_SRV crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
"$P_CLI ca_callback=1 debug_level=3 auth_mode=none" \
0 \
-C "use CA callback for X.509 CRT verification" \
-C "x509_verify_cert() returned" \
-C "! The certificate is not correctly signed by the trusted CA" \
-C "! mbedtls_ssl_handshake returned" \
-C "X509 - Certificate verification failed"
# The purpose of the next two tests is to test the client's behaviour when receiving a server
# certificate with an unsupported elliptic curve. This should usually not happen because
# the client informs the server about the supported curves - it does, though, in the
@ -6270,7 +6373,7 @@ run_test "Authentication, CA callback: server ECDH p256v1, client optional, p
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
run_test "Authentication, CA callback: client SHA256, server required" \
run_test "Authentication, CA callback: client SHA384, server required" \
"$P_SRV ca_callback=1 debug_level=3 auth_mode=required" \
"$P_CLI debug_level=3 crt_file=$DATA_FILES_PATH/server6.crt \
key_file=$DATA_FILES_PATH/server6.key \
@ -6282,7 +6385,7 @@ run_test "Authentication, CA callback: client SHA256, server required" \
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
run_test "Authentication, CA callback: client SHA384, server required" \
run_test "Authentication, CA callback: client SHA256, server required" \
"$P_SRV ca_callback=1 debug_level=3 auth_mode=required" \
"$P_CLI debug_level=3 crt_file=$DATA_FILES_PATH/server6.crt \
key_file=$DATA_FILES_PATH/server6.key \
@ -6294,7 +6397,7 @@ run_test "Authentication, CA callback: client SHA384, server required" \
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: client badcert, server required" \
"$P_SRV force_version=tls12 ca_callback=1 debug_level=3 auth_mode=required" \
"$P_SRV ca_callback=1 debug_level=3 auth_mode=required" \
"$P_CLI debug_level=3 crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
1 \
@ -6309,7 +6412,6 @@ run_test "Authentication, CA callback: client badcert, server required" \
-s "! The certificate is not correctly signed by the trusted CA" \
-s "! mbedtls_ssl_handshake returned" \
-s "send alert level=2 message=48" \
-c "! mbedtls_ssl_handshake returned" \
-s "X509 - Certificate verification failed"
# We don't check that the client receives the alert because it might
# detect that its write end of the connection is closed and abort
@ -6317,7 +6419,7 @@ run_test "Authentication, CA callback: client badcert, server required" \
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: client cert not trusted, server required" \
"$P_SRV force_version=tls12 ca_callback=1 debug_level=3 auth_mode=required" \
"$P_SRV ca_callback=1 debug_level=3 auth_mode=required" \
"$P_CLI debug_level=3 crt_file=$DATA_FILES_PATH/server5-selfsigned.crt \
key_file=$DATA_FILES_PATH/server5.key" \
1 \
@ -6331,12 +6433,11 @@ run_test "Authentication, CA callback: client cert not trusted, server requir
-s "x509_verify_cert() returned" \
-s "! The certificate is not correctly signed by the trusted CA" \
-s "! mbedtls_ssl_handshake returned" \
-c "! mbedtls_ssl_handshake returned" \
-s "X509 - Certificate verification failed"
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: client badcert, server optional" \
"$P_SRV force_version=tls12 ca_callback=1 debug_level=3 auth_mode=optional" \
"$P_SRV ca_callback=1 debug_level=3 auth_mode=optional" \
"$P_CLI debug_level=3 crt_file=$DATA_FILES_PATH/server5-badsign.crt \
key_file=$DATA_FILES_PATH/server5.key" \
0 \
@ -6359,7 +6460,7 @@ requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: server max_int chain, client default" \
"$P_SRV crt_file=$DATA_FILES_PATH/dir-maxpath/c09.pem \
key_file=$DATA_FILES_PATH/dir-maxpath/09.key" \
"$P_CLI force_version=tls12 ca_callback=1 debug_level=3 server_name=CA09 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt" \
"$P_CLI ca_callback=1 debug_level=3 server_name=CA09 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt" \
0 \
-c "use CA callback for X.509 CRT verification" \
-C "X509 - A fatal error occurred"
@ -6370,7 +6471,7 @@ requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: server max_int+1 chain, client default" \
"$P_SRV crt_file=$DATA_FILES_PATH/dir-maxpath/c10.pem \
key_file=$DATA_FILES_PATH/dir-maxpath/10.key" \
"$P_CLI force_version=tls12 debug_level=3 ca_callback=1 server_name=CA10 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt" \
"$P_CLI debug_level=3 ca_callback=1 server_name=CA10 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt" \
1 \
-c "use CA callback for X.509 CRT verification" \
-c "X509 - A fatal error occurred"
@ -6381,7 +6482,7 @@ requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: server max_int+1 chain, client optional" \
"$P_SRV crt_file=$DATA_FILES_PATH/dir-maxpath/c10.pem \
key_file=$DATA_FILES_PATH/dir-maxpath/10.key" \
"$P_CLI force_version=tls12 ca_callback=1 server_name=CA10 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt \
"$P_CLI ca_callback=1 server_name=CA10 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt \
debug_level=3 auth_mode=optional" \
1 \
-c "use CA callback for X.509 CRT verification" \
@ -6391,7 +6492,7 @@ requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
requires_full_size_output_buffer
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: client max_int+1 chain, server optional" \
"$P_SRV force_version=tls12 ca_callback=1 debug_level=3 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt auth_mode=optional" \
"$P_SRV ca_callback=1 debug_level=3 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt auth_mode=optional" \
"$P_CLI crt_file=$DATA_FILES_PATH/dir-maxpath/c10.pem \
key_file=$DATA_FILES_PATH/dir-maxpath/10.key" \
1 \
@ -6402,7 +6503,7 @@ requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
requires_full_size_output_buffer
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: client max_int+1 chain, server required" \
"$P_SRV force_version=tls12 ca_callback=1 debug_level=3 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt auth_mode=required" \
"$P_SRV ca_callback=1 debug_level=3 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt auth_mode=required" \
"$P_CLI crt_file=$DATA_FILES_PATH/dir-maxpath/c10.pem \
key_file=$DATA_FILES_PATH/dir-maxpath/10.key" \
1 \
@ -6413,7 +6514,7 @@ requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
requires_full_size_output_buffer
requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
run_test "Authentication, CA callback: client max_int chain, server required" \
"$P_SRV force_version=tls12 ca_callback=1 debug_level=3 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt auth_mode=required" \
"$P_SRV ca_callback=1 debug_level=3 ca_file=$DATA_FILES_PATH/dir-maxpath/00.crt auth_mode=required" \
"$P_CLI crt_file=$DATA_FILES_PATH/dir-maxpath/c09.pem \
key_file=$DATA_FILES_PATH/dir-maxpath/09.key" \
0 \
@ -6578,7 +6679,9 @@ run_test "SNI: CA override with CRL" \
-S "skip parse certificate verify" \
-s "x509_verify_cert() returned" \
-S "! The certificate is not correctly signed by the trusted CA" \
-s "send alert level=2 message=44" \
-s "The certificate has been revoked (is on a CRL)"
# MBEDTLS_X509_BADCERT_REVOKED -> MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED
# Tests for SNI and DTLS
@ -6726,7 +6829,9 @@ run_test "SNI: DTLS, CA override with CRL" \
-S "skip parse certificate verify" \
-s "x509_verify_cert() returned" \
-S "! The certificate is not correctly signed by the trusted CA" \
-s "send alert level=2 message=44" \
-s "The certificate has been revoked (is on a CRL)"
# MBEDTLS_X509_BADCERT_REVOKED -> MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED
# Tests for non-blocking I/O: exercise a variety of handshake flows