diff --git a/ChangeLog.d/tls13-cert-regressions.txt b/ChangeLog.d/tls13-cert-regressions.txt new file mode 100644 index 0000000000..8dd8a327d6 --- /dev/null +++ b/ChangeLog.d/tls13-cert-regressions.txt @@ -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. diff --git a/library/ssl_misc.h b/library/ssl_misc.h index a8807f67c6..762c478328 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -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 */ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index d6077a2baa..8f5c37ad42 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -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 */ diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index b5b975ff40..0878749464 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -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; diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 651a17b5a2..3f1f551dd1 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -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 diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 91828ef03a..c3f7c25fdb 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -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