From 37e08e1689abeebcf4f0eb46062d31de5b339f7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 13 Oct 2014 17:55:52 +0200 Subject: [PATCH] Fix max_fragment_length with DTLS --- include/polarssl/ssl.h | 6 ++++++ library/ssl_tls.c | 28 +++++++++++++++++++++------- tests/ssl-opt.sh | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index d2559ba77..91f92f923 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -1946,6 +1946,12 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ); * \note When this function returns POLARSSL_ERR_NET_WANT_WRITE, * it must be called later with the *same* arguments, * until it returns a positive value. + * + * \note When DTLS is in use, and a maximum fragment length was + * either set with \c ssl_set_max_frag_len() or negotiated by + * the peer, len must not not be greater than the maximum + * fragment length, or POLARSSL_ERR_SSL_BAD_INPUT_DATA is + * returned. */ int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 4edf19a95..3206a734e 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -5894,8 +5894,9 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ) int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) { int ret; - size_t n; - unsigned int max_len = SSL_MAX_CONTENT_LEN; +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + unsigned int max_len; +#endif SSL_DEBUG_MSG( 2, ( "=> write" ) ); @@ -5922,9 +5923,22 @@ int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) { max_len = mfl_code_to_length[ssl->session_out->mfl_code]; } -#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ - n = ( len < max_len) ? len : max_len; + if( len > max_len ) + { +#if defined(POLARSSL_SSL_PROTO_DTLS) + if( ssl->transport == SSL_TRANSPORT_DATAGRAM ) + { + SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " + "maximum fragment length: %d > %d", + len, max_len ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + else +#endif + len = max_len; + } +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ if( ssl->out_left != 0 ) { @@ -5936,9 +5950,9 @@ int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) } else { - ssl->out_msglen = n; + ssl->out_msglen = len; ssl->out_msgtype = SSL_MSG_APPLICATION_DATA; - memcpy( ssl->out_msg, buf, n ); + memcpy( ssl->out_msg, buf, len ); if( ( ret = ssl_write_record( ssl ) ) != 0 ) { @@ -5949,7 +5963,7 @@ int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) SSL_DEBUG_MSG( 2, ( "<= write" ) ); - return( (int) n ); + return( (int) len ); } /* diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index df94fe026..e9a097141 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -748,6 +748,39 @@ run_test "Max fragment length: gnutls server" \ -c "client hello, adding max_fragment_length extension" \ -c "found max_fragment_length extension" +run_test "Max fragment length: client, message just fits" \ + "$P_SRV debug_level=3" \ + "$P_CLI debug_level=3 max_frag_len=2048 request_size=2048" \ + 0 \ + -c "client hello, adding max_fragment_length extension" \ + -s "found max fragment length extension" \ + -s "server hello, max_fragment_length extension" \ + -c "found max_fragment_length extension" \ + -c "2048 bytes written in 1 fragments" \ + -s "2048 bytes read" + +run_test "Max fragment length: client, larger message" \ + "$P_SRV debug_level=3" \ + "$P_CLI debug_level=3 max_frag_len=2048 request_size=2345" \ + 0 \ + -c "client hello, adding max_fragment_length extension" \ + -s "found max fragment length extension" \ + -s "server hello, max_fragment_length extension" \ + -c "found max_fragment_length extension" \ + -c "2345 bytes written in 2 fragments" \ + -s "2048 bytes read" \ + -s "297 bytes read" + +run_test "Max fragment length: client, larger message" \ + "$P_SRV debug_level=3 dtls=1" \ + "$P_CLI debug_level=3 dtls=1 max_frag_len=2048 request_size=2345" \ + 1 \ + -c "client hello, adding max_fragment_length extension" \ + -s "found max fragment length extension" \ + -s "server hello, max_fragment_length extension" \ + -c "found max_fragment_length extension" \ + -c "fragment larger than.*maximum" + # Tests for renegotiation run_test "Renegotiation: none, for reference" \