diff --git a/ChangeLog b/ChangeLog index 265205cdb..474dcd0fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ mbed TLS ChangeLog (Sorted per branch, date) -mbed TLS 2.x.x branch released xxxx-xx-xx += mbed TLS 2.x.x branch released xxxx-xx-xx Security @@ -12,6 +12,14 @@ Bugfix * Remove invalid use of size zero arrays in ECJPAKE test suite. * Fix insufficient support for signature-hash-algorithm extension, resulting in compatibility problems with Chrome. Found by hfloyrd. #823 + * If sending a fatal alert fails, make sure not to hide the error + that triggered the alert. + * In SSLv3, if refusing a renegotiation attempt, don't process any further + data. + +Changes + * Send fatal alerts in many more cases instead of dropping the connection. + = mbed TLS 2.5.0 branch released 2017-05-17 diff --git a/library/ssl_cli.c b/library/ssl_cli.c index fcc7f5ff1..616cadc08 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -264,11 +264,12 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_ECP_C) for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) - { - info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); #else for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) +#endif { +#if defined(MBEDTLS_ECP_C) + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); #endif if( info == NULL ) { @@ -289,11 +290,12 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_ECP_C) for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) - { - info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); #else for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) +#endif { +#if defined(MBEDTLS_ECP_C) + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); #endif elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; @@ -1055,8 +1057,6 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - int ret; - #if defined(MBEDTLS_SSL_RENEGOTIATION) if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) { @@ -1069,10 +1069,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } } @@ -1082,10 +1080,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, if( len != 1 || buf[0] != 0x00 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1108,6 +1104,9 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, len != 1 || buf[0] != ssl->conf->mfl_code ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching max fragment length extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1123,6 +1122,9 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || len != 0 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching truncated HMAC extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1143,6 +1145,9 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || len != 0 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching encrypt-then-MAC extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1163,6 +1168,9 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || len != 0 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching extended master secret extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1182,6 +1190,9 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || len != 0 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching session ticket extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1206,6 +1217,8 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, if( list_size + 1 != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1217,7 +1230,7 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, { #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) ssl->handshake->ecdh_ctx.point_format = p[0]; -#endif +#endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ssl->handshake->ecjpake_ctx.point_format = p[0]; #endif @@ -1230,6 +1243,8 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, } MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || @@ -1258,6 +1273,8 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, buf, len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( ret ); } @@ -1274,7 +1291,12 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, /* If we didn't send it, the server shouldn't send it */ if( ssl->conf->alpn_list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } /* * opaque ProtocolName<1..2^8-1>; @@ -1288,15 +1310,27 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } list_len = ( buf[0] << 8 ) | buf[1]; if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } name_len = buf[2]; if( name_len != list_len - 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } /* Check that the server chosen protocol was in our list and save it */ for( p = ssl->conf->alpn_list; *p != NULL; p++ ) @@ -1309,6 +1343,9 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, } } + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } #endif /* MBEDTLS_SSL_ALPN */ @@ -1413,6 +1450,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) { + /* No alert on a read error. */ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); } @@ -1438,6 +1476,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_RENEGOTIATION */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -1464,6 +1504,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1518,6 +1560,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( n > 32 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1530,6 +1574,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } } @@ -1540,6 +1586,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) else { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1567,6 +1615,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #endif/* MBEDTLS_ZLIB_SUPPORT */ { MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); } @@ -1578,6 +1628,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ssl->transform_negotiate->ciphersuite_info == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -1615,6 +1667,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( ret ); } } @@ -1634,6 +1688,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1645,6 +1701,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1662,6 +1720,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } ssl->session_negotiate->compression = comp; @@ -1680,6 +1740,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ext_size + 4 > ext_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1850,9 +1912,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( handshake_failure == 1 ) { - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -2218,6 +2279,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( ret ); } @@ -2239,6 +2302,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -2256,6 +2321,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) } MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -2272,6 +2339,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } /* FALLTROUGH */ @@ -2293,6 +2362,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2309,6 +2380,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2324,6 +2397,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2354,12 +2429,16 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) &md_alg, &pk_alg ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2391,6 +2470,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( end != p + sig_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } @@ -2462,6 +2543,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) mbedtls_md_info_from_type( md_alg ), 0 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( ret ); } @@ -2485,6 +2568,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ssl->session_negotiate->peer_cert == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -2494,12 +2579,16 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); } if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, md_alg, hash, hashlen, p, sig_len ) ) != 0 ) { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); return( ret ); } @@ -2562,6 +2651,8 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -2615,6 +2706,8 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); } @@ -2640,6 +2733,8 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); } } @@ -2653,6 +2748,8 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); } @@ -2689,6 +2786,8 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); } @@ -3169,6 +3268,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -3186,6 +3287,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); } @@ -3199,6 +3302,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); } @@ -3224,6 +3329,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 5313bca1a..a61ff5f2d 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -101,6 +101,8 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, if( servername_list_size + 2 != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -111,6 +113,8 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, if( hostname_len + 3 > servername_list_size ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -135,6 +139,8 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, if( servername_list_size != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -146,8 +152,6 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - int ret; - #if defined(MBEDTLS_SSL_RENEGOTIATION) if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) { @@ -158,10 +162,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ssl->verify_data_len ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } } @@ -171,10 +173,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, if( len != 1 || buf[0] != 0x0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -216,6 +216,8 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, sig_alg_list_size % 2 != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -282,6 +284,8 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, list_size % 2 != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -289,6 +293,8 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, if( ssl->handshake->curves != NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -299,7 +305,11 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, our_size = MBEDTLS_ECP_DP_MAX; if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } ssl->handshake->curves = curves; @@ -332,6 +342,8 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, if( list_size + 1 != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -377,6 +389,8 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, buf, len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( ret ); } @@ -395,6 +409,8 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -412,6 +428,8 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, if( len != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -432,6 +450,8 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, if( len != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -455,6 +475,8 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, if( len != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -566,11 +588,19 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } list_len = ( buf[0] << 8 ) | buf[1]; if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } /* * Use our order of preference @@ -584,13 +614,21 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, { /* If the list is well formed, we should get equality first */ if( theirs > end ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } cur_len = *theirs++; /* Empty strings MUST NOT be included */ if( cur_len == 0 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } if( cur_len == ours_len && memcmp( theirs, *ours, cur_len ) == 0 ) @@ -873,10 +911,8 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -1022,9 +1058,8 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " "during renegotiation" ) ); - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -1062,11 +1097,9 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) ciphersuite_info = NULL; #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) - { for( i = 0; ciphersuites[i] != 0; i++ ) #else for( i = 0; ciphersuites[i] != 0; i++ ) - { for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) #endif { @@ -1084,7 +1117,6 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) if( ciphersuite_info != NULL ) goto have_ciphersuite_v2; } - } if( got_common_suite ) { @@ -1111,10 +1143,8 @@ have_ciphersuite_v2: ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1127,6 +1157,9 @@ have_ciphersuite_v2: } #endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ +/* This function doesn't alert on errors that happen early during + ClientHello parsing because they might indicate that the client is + not talking SSL/TLS at all and would not understand our alert. */ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) { int ret, got_common_suite; @@ -1170,6 +1203,7 @@ read_record_header: { if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) { + /* No alert on a read error. */ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); return( ret ); } @@ -1182,7 +1216,7 @@ read_record_header: if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) #endif if( ( buf[0] & 0x80 ) != 0 ) - return ssl_parse_client_hello_v2( ssl ); + return( ssl_parse_client_hello_v2( ssl ) ); #endif MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) ); @@ -1422,10 +1456,8 @@ read_record_header: " [%d:%d] < [%d:%d]", ssl->major_ver, ssl->minor_ver, ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); } @@ -1453,6 +1485,8 @@ read_record_header: sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1476,6 +1510,8 @@ read_record_header: if( cookie_offset + 1 + cookie_len + 2 > msg_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1508,6 +1544,7 @@ read_record_header: /* We know we didn't send a cookie, so it should be empty */ if( cookie_len != 0 ) { + /* This may be an attacker's probe, so don't send an alert */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1532,6 +1569,8 @@ read_record_header: ( ciph_len % 2 ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1550,6 +1589,8 @@ read_record_header: comp_len + comp_offset + 1 > msg_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1588,6 +1629,8 @@ read_record_header: if( msg_len < ext_offset + 2 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1598,6 +1641,8 @@ read_record_header: msg_len != ext_offset + 2 + ext_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } } @@ -1617,6 +1662,8 @@ read_record_header: if( ext_size + 4 > ext_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } switch( ext_id ) @@ -1763,6 +1810,8 @@ read_record_header: if( ext_len > 0 && ext_len < 4 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } } @@ -1826,10 +1875,8 @@ read_record_header: { MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " "during renegotiation" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } #endif @@ -1873,9 +1920,8 @@ read_record_header: if( handshake_failure == 1 ) { - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1889,11 +1935,9 @@ read_record_header: ciphersuite_info = NULL; #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) - { for( i = 0; ciphersuites[i] != 0; i++ ) #else for( i = 0; ciphersuites[i] != 0; i++ ) - { for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) #endif { @@ -1910,19 +1954,20 @@ read_record_header: if( ciphersuite_info != NULL ) goto have_ciphersuite; } - } if( got_common_suite ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " "but none of them usable" ) ); - mbedtls_ssl_send_fatal_handshake_failure( ssl ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); } else { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); - mbedtls_ssl_send_fatal_handshake_failure( ssl ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); } @@ -3425,13 +3470,8 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) { MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 ) - { - return( ret ); - } - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ); return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); } diff --git a/library/ssl_tls.c b/library/ssl_tls.c index ddedabb96..1e5f8e493 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3473,7 +3473,6 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) */ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) { - int ret; int major_ver, minor_ver; MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) ); @@ -3494,14 +3493,8 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); - - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 ) - { - return( ret ); - } - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } @@ -4030,6 +4023,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; ssl->out_msglen = 2; @@ -4041,7 +4035,6 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); return( 0 ); @@ -4057,6 +4050,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +/* No certificate support -> dummy functions */ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; @@ -4096,7 +4090,10 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } + #else +/* Some certificate support -> implement write and parse */ + int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; @@ -4219,6 +4216,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) size_t i, n; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; int authmode = ssl->conf->authmode; + uint8_t alert; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); @@ -4258,6 +4256,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); } @@ -4279,6 +4279,9 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); + /* The client was asked for a certificate but didn't send + one. The client should know what's going on, so we + don't send an alert. */ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) return( 0 ); @@ -4300,6 +4303,9 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + /* The client was asked for a certificate but didn't send + one. The client should know what's going on, so we + don't send an alert. */ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) return( 0 ); @@ -4314,6 +4320,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -4321,6 +4329,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); } @@ -4335,6 +4345,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); } @@ -4350,6 +4362,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", sizeof( mbedtls_x509_crt ) ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } @@ -4362,6 +4376,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( ssl->in_msg[i] != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); } @@ -4372,13 +4388,33 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( n < 128 || i + n > ssl->in_hslen ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); } ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, ssl->in_msg + i, n ); - if( 0 != ret && ( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND ) != ret ) + switch( ret ) { + case 0: /*ok*/ + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; + goto crt_parse_der_failed; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + goto crt_parse_der_failed; + + default: + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + crt_parse_der_failed: + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert ); MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); return( ret ); } @@ -4399,6 +4435,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( ssl->session->peer_cert == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); } @@ -4409,6 +4447,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ssl->session->peer_cert->raw.len ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); } } @@ -4435,6 +4475,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( ca_chain == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_CERT ); return( MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED ); } @@ -4485,6 +4527,37 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) ret = 0; + + 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( 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 ); + } } MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); @@ -4537,12 +4610,16 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); } @@ -4565,6 +4642,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) if( ++ssl->in_epoch == 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + /* This is highly unlikely to happen for legitimate reasons, so + treat it as an attack and don't send an alert. */ return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); } } @@ -4589,6 +4668,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); } } @@ -5167,6 +5248,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -5182,6 +5265,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); } @@ -5189,6 +5274,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) buf, hash_len ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); } @@ -6651,11 +6738,11 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) #if defined(MBEDTLS_SSL_PROTO_SSL3) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { - /* - * SSLv3 does not have a "no_renegotiation" alert - */ - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); + /* SSLv3 does not have a "no_renegotiation" warning, so + we send a fatal alert and abort the connection. */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } else #endif /* MBEDTLS_SSL_PROTO_SSL3 */ diff --git a/tests/scripts/run-test-suites.pl b/tests/scripts/run-test-suites.pl index 58f827c14..1f73a545e 100755 --- a/tests/scripts/run-test-suites.pl +++ b/tests/scripts/run-test-suites.pl @@ -33,7 +33,10 @@ if ( defined($switch) && ( $switch eq "-v" || $switch eq "--verbose" ) ) { $verbose = TRUE; } -my @suites = grep { ! /\.(?:c|gcno|gcda|dSYM)$/ } glob 'test_suite_*'; +# All test suites = executable files, excluding source files, debug +# and profiling information, etc. We can't just grep {! /\./} because +#some of our test cases' base names contain a dot. +my @suites = grep { -x $_ || /\.exe$/ } glob 'test_suite_*'; die "$0: no test suite found\n" unless @suites; # in case test suites are linked dynamically diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 61c382742..398405bdd 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -49,15 +49,23 @@ RUN_TEST_NUMBER='' PRESERVE_LOGS=0 +# Pick a "unique" server port in the range 10000-19999, and a proxy +# port which is this plus 10000. Each port number may be independently +# overridden by a command line option. +SRV_PORT=$(($$ % 10000 + 10000)) +PXY_PORT=$((SRV_PORT + 10000)) + print_usage() { echo "Usage: $0 [options]" printf " -h|--help\tPrint this help.\n" printf " -m|--memcheck\tCheck memory leaks and errors.\n" - printf " -f|--filter\tOnly matching tests are executed (default: '$FILTER')\n" - printf " -e|--exclude\tMatching tests are excluded (default: '$EXCLUDE')\n" + printf " -f|--filter\tOnly matching tests are executed (BRE; default: '$FILTER')\n" + printf " -e|--exclude\tMatching tests are excluded (BRE; default: '$EXCLUDE')\n" printf " -n|--number\tExecute only numbered test (comma-separated, e.g. '245,256')\n" printf " -s|--show-numbers\tShow test numbers in front of test names\n" printf " -p|--preserve-logs\tPreserve logs of successful tests as well\n" + printf " --port\tTCP/UDP port (default: randomish 1xxxx)\n" + printf " --proxy-port\tTCP/UDP proxy port (default: randomish 2xxxx)\n" printf " --seed\tInteger seed value to use for this test run\n" } @@ -82,6 +90,12 @@ get_options() { -p|--preserve-logs) PRESERVE_LOGS=1 ;; + --port) + shift; SRV_PORT=$1 + ;; + --proxy-port) + shift; PXY_PORT=$1 + ;; --seed) shift; SEED="$1" ;; @@ -611,13 +625,6 @@ fi CLI_DELAY_FACTOR=1 SRV_DELAY_SECONDS=0 -# Pick a "unique" server port in the range 10000-19999, and a proxy port -PORT_BASE="0000$$" -PORT_BASE="$( printf $PORT_BASE | tail -c 4 )" -SRV_PORT="1$PORT_BASE" -PXY_PORT="2$PORT_BASE" -unset PORT_BASE - # fix commands to use this port, force IPv4 while at it # +SRV_PORT will be replaced by either $SRV_PORT or $PXY_PORT later P_SRV="$P_SRV server_addr=127.0.0.1 server_port=$SRV_PORT" @@ -1825,6 +1832,38 @@ run_test "Authentication: client SHA384, server required" \ -c "Supported Signature Algorithm found: 4," \ -c "Supported Signature Algorithm found: 5," +requires_config_enabled MBEDTLS_SSL_PROTO_SSL3 +run_test "Authentication: client has no cert, server required (SSLv3)" \ + "$P_SRV debug_level=3 min_version=ssl3 auth_mode=required" \ + "$P_CLI debug_level=3 force_version=ssl3 crt_file=none \ + key_file=data_files/server5.key" \ + 1 \ + -S "skip write certificate request" \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -c "got no certificate to send" \ + -S "x509_verify_cert() returned" \ + -s "client has no certificate" \ + -s "! mbedtls_ssl_handshake returned" \ + -c "! mbedtls_ssl_handshake returned" \ + -s "No client certification received from the client, but required by the authentication mode" + +run_test "Authentication: client has no cert, server required (TLS)" \ + "$P_SRV debug_level=3 auth_mode=required" \ + "$P_CLI debug_level=3 crt_file=none \ + key_file=data_files/server5.key" \ + 1 \ + -S "skip write certificate request" \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -c "= write certificate$" \ + -C "skip write certificate$" \ + -S "x509_verify_cert() returned" \ + -s "client has no certificate" \ + -s "! mbedtls_ssl_handshake returned" \ + -c "! mbedtls_ssl_handshake returned" \ + -s "No client certification received from the client, but required by the authentication mode" + run_test "Authentication: client badcert, server required" \ "$P_SRV debug_level=3 auth_mode=required" \ "$P_CLI debug_level=3 crt_file=data_files/server5-badsign.crt \ @@ -1839,8 +1878,12 @@ run_test "Authentication: client badcert, server required" \ -s "x509_verify_cert() returned" \ -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 +# before reading the alert message. run_test "Authentication: client cert not trusted, server required" \ "$P_SRV debug_level=3 auth_mode=required" \ @@ -1930,6 +1973,16 @@ run_test "Authentication: client no cert, openssl server optional" \ -c "skip write certificate verify" \ -C "! mbedtls_ssl_handshake returned" +run_test "Authentication: client no cert, openssl server required" \ + "$O_SRV -Verify 10" \ + "$P_CLI debug_level=3 crt_file=none key_file=none" \ + 1 \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -C "skip write certificate$" \ + -c "skip write certificate verify" \ + -c "! mbedtls_ssl_handshake returned" + requires_config_enabled MBEDTLS_SSL_PROTO_SSL3 run_test "Authentication: client no cert, ssl3" \ "$P_SRV debug_level=3 auth_mode=optional force_version=ssl3" \