diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index b781adcb7..3080046e1 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -2213,11 +2213,36 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) p += 4; #endif /* MBEDTLS_HAVE_TIME */ - if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 28)) != 0) { + if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 20)) != 0) { return ret; } + p += 20; - p += 28; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* + * RFC 8446 + * TLS 1.3 has a downgrade protection mechanism embedded in the server's + * random value. TLS 1.3 servers which negotiate TLS 1.2 or below in + * response to a ClientHello MUST set the last 8 bytes of their Random + * value specially in their ServerHello. + */ + if (mbedtls_ssl_conf_is_tls13_enabled(ssl->conf)) { + static const unsigned char magic_tls12_downgrade_string[] = + { 'D', 'O', 'W', 'N', 'G', 'R', 'D', 1 }; + + MBEDTLS_STATIC_ASSERT( + sizeof(magic_tls12_downgrade_string) == 8, + "magic_tls12_downgrade_string does not have the expected size"); + + memcpy(p, magic_tls12_downgrade_string, 8); + } else +#endif + { + if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 8)) != 0) { + return ret; + } + } + p += 8; memcpy(ssl->handshake->randbytes + 32, buf + 6, 32); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 74fb9f296..da9581454 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1946,12 +1946,33 @@ run_test "Default, DTLS" \ -s "Protocol is DTLSv1.2" \ -s "Ciphersuite is TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256" +# GnuTLS can be setup to send a ClientHello containing a supported versions +# extension proposing TLS 1.2 (preferred) and then TLS 1.3. In that case, +# a TLS 1.3 and TLS 1.2 capable server is supposed to negotiate TLS 1.2 and +# to indicate in the ServerHello that it downgrades from TLS 1.3. The GnuTLS +# client then detects the downgrade indication and aborts the handshake even +# if TLS 1.2 was its preferred version. Keeping the test even if the +# handshake fails eventually as it exercices parts of the Mbed TLS +# implementation that are otherwise not exercised. requires_gnutls_tls1_3 requires_config_enabled MBEDTLS_DEBUG_C requires_config_enabled MBEDTLS_SSL_SRV_C requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -run_test "Server selecting TLS 1.2, over TLS 1.3 if supported" \ +run_test "Server selecting TLS 1.2 over TLS 1.3" \ + "$P_SRV crt_file=data_files/server5.crt key_file=data_files/server5.key" \ + "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.3" \ + 1 \ + -c "Detected downgrade to TLS 1.2 from TLS 1.3" + +requires_gnutls_tls1_3 +requires_config_enabled MBEDTLS_DEBUG_C +requires_config_enabled MBEDTLS_SSL_SRV_C +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +run_test "Server selecting TLS 1.2" \ "$P_SRV crt_file=data_files/server5.crt key_file=data_files/server5.key" \ "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.3" \ 0 \ @@ -8733,7 +8754,7 @@ run_test "SSL async private: decrypt callback not present" \ "$P_SRV debug_level=1 \ async_operations=s async_private_delay1=1 async_private_delay2=1" \ "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA; - [ \$? -eq 1 ] && $P_CLI" \ + [ \$? -eq 1 ] && $P_CLI force_version=tls12" \ 0 \ -S "Async decrypt callback" \ -s "! mbedtls_ssl_handshake returned" \