Fix client-side max fragment length negotiation

If the server does not acknowledge our fragment length proposal we should revert back to not fragmenting.

Signed-off-by: Deomid rojer Ryabkov <rojer@rojer.me>
This commit is contained in:
Deomid rojer Ryabkov 2024-03-11 17:12:55 +00:00
parent 8e1937d037
commit fb804e5baf
2 changed files with 26 additions and 12 deletions

View File

@ -1280,6 +1280,14 @@ static int ssl_handshake_init(mbedtls_ssl_context *ssl)
}
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
/* Client starts with the desired fragment length. */
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
ssl->session_negotiate->mfl_code = ssl->conf->mfl_code;
}
#endif
return 0;
}
@ -3183,17 +3191,9 @@ size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl)
size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN;
size_t read_mfl;
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
/* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE) {
return ssl_mfl_code_to_length(ssl->conf->mfl_code);
}
#endif
/* Check if a smaller max length was negotiated */
if (ssl->session_out != NULL) {
read_mfl = ssl_mfl_code_to_length(ssl->session_out->mfl_code);
if (ssl->session_in != NULL) {
read_mfl = ssl_mfl_code_to_length(ssl->session_in->mfl_code);
if (read_mfl < max_len) {
max_len = read_mfl;
}

View File

@ -265,7 +265,7 @@ static int ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl,
*olen = 0;
if (ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE) {
if (ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE) {
return 0;
}
@ -280,7 +280,7 @@ static int ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl,
*p++ = 0x00;
*p++ = 1;
*p++ = ssl->conf->mfl_code;
*p++ = ssl->session_negotiate->mfl_code;
*olen = 5;
@ -1186,6 +1186,9 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl)
unsigned char comp;
#if defined(MBEDTLS_SSL_RENEGOTIATION)
int renegotiation_info_seen = 0;
#endif
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
int max_fragment_length_seen = 0;
#endif
int handshake_failure = 0;
const mbedtls_ssl_ciphersuite_t *suite_info;
@ -1482,6 +1485,8 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl)
return ret;
}
max_fragment_length_seen = 1;
break;
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
@ -1656,6 +1661,15 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl)
return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
}
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
if (ssl->session_negotiate->mfl_code != MBEDTLS_SSL_MAX_FRAG_LEN_NONE &&
!max_fragment_length_seen) {
MBEDTLS_SSL_DEBUG_MSG(3,
("server did not confirm our fragment length request, disabling"));
ssl->session_negotiate->mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_NONE;
}
#endif
MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello"));
return 0;