From a2cda6bfaff6b6a261b489c0eda3d254cb869ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 31 Aug 2015 18:30:52 +0200 Subject: [PATCH] Add mbedtls_ssl_get_max_frag_len() This is not very useful for TLS as mbedtls_ssl_write() will automatically fragment and return the length used, and the application should check for that anyway, but this is useful for DTLS where mbedtls_ssl_write() returns an error, and the application needs to be able to query the maximum length instead of just guessing. --- ChangeLog | 2 ++ include/mbedtls/ssl.h | 20 +++++++++++++++++++ library/ssl_tls.c | 41 ++++++++++++++++++++++---------------- programs/ssl/ssl_client2.c | 5 +++++ programs/ssl/ssl_server2.c | 5 +++++ tests/ssl-opt.sh | 13 ++++++++++++ 6 files changed, 69 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8d8152427..c43be03c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -37,6 +37,8 @@ Changes compiler's command line. * Prepend a "thread identifier" to debug messages (issue pointed out by Hugo Leisink) (#210). + * Add mbedtls_ssl_get_max_frag_len() to query the current maximum fragment + length. = mbed TLS 2.0.0 released 2015-07-13 diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 288627bf1..dd799ab38 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2027,6 +2027,26 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); */ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Return the maximum fragment length (payload, in bytes). + * This is the value negotiated with peer if any, + * or the locally configured value. + * + * \note With DTLS, \c mbedtls_ssl_write() will return an error if + * called with a larger length value. + * With TLS, \c mbedtls_ssl_write() will fragment the input if + * necessary and return the number of bytes written; it is up + * to the caller to call \c mbedtls_ssl_write() again in + * order to send the remaining bytes if any. + * + * \param ssl SSL context + * + * \return Current maximum fragment length. + */ +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Return the peer certificate from the current connection diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 9007562fb..283e80a72 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -5862,6 +5862,29 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) return( (int)( mbedtls_ssl_hdr_len( ssl ) + transform_expansion ) ); } +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len; + + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = mfl_code_to_length[ssl->conf->mfl_code]; + + /* + * Check if a smaller max length was negotiated + */ + if( ssl->session_out != NULL && + mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) + { + max_len = mfl_code_to_length[ssl->session_out->mfl_code]; + } + + return max_len; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + #if defined(MBEDTLS_X509_CRT_PARSE_C) const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) { @@ -6339,23 +6362,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, { int ret; #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - unsigned int max_len; -#endif - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - /* - * Assume mfl_code is correct since it was checked when set - */ - max_len = mfl_code_to_length[ssl->conf->mfl_code]; - - /* - * Check if a smaller max length was negotiated - */ - if( ssl->session_out != NULL && - mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) - { - max_len = mfl_code_to_length[ssl->session_out->mfl_code]; - } + size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); if( len > max_len ) { diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 2e0ac1edc..c60e7100f 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -1240,6 +1240,11 @@ int main( int argc, char *argv[] ) else mbedtls_printf( " [ Record expansion is unknown (compression) ]\n" ); +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + mbedtls_printf( " [ Maximum fragment length is %u ]\n", + (unsigned int) mbedtls_ssl_get_max_frag_len( &ssl ) ); +#endif + #if defined(MBEDTLS_SSL_ALPN) if( opt.alpn_string != NULL ) { diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 3aa05d5f1..e4940b889 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -1946,6 +1946,11 @@ reset: else mbedtls_printf( " [ Record expansion is unknown (compression) ]\n" ); +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + mbedtls_printf( " [ Maximum fragment length is %u ]\n", + (unsigned int) mbedtls_ssl_get_max_frag_len( &ssl ) ); +#endif + #if defined(MBEDTLS_SSL_ALPN) if( opt.alpn_string != NULL ) { diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index bd36e227b..77db588db 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1085,6 +1085,8 @@ run_test "Max fragment length: not used, reference" \ "$P_SRV debug_level=3" \ "$P_CLI debug_level=3" \ 0 \ + -c "Maximum fragment length is 16384" \ + -s "Maximum fragment length is 16384" \ -C "client hello, adding max_fragment_length extension" \ -S "found max fragment length extension" \ -S "server hello, max_fragment_length extension" \ @@ -1094,6 +1096,8 @@ run_test "Max fragment length: used by client" \ "$P_SRV debug_level=3" \ "$P_CLI debug_level=3 max_frag_len=4096" \ 0 \ + -c "Maximum fragment length is 4096" \ + -s "Maximum fragment length is 4096" \ -c "client hello, adding max_fragment_length extension" \ -s "found max fragment length extension" \ -s "server hello, max_fragment_length extension" \ @@ -1103,6 +1107,8 @@ run_test "Max fragment length: used by server" \ "$P_SRV debug_level=3 max_frag_len=4096" \ "$P_CLI debug_level=3" \ 0 \ + -c "Maximum fragment length is 16384" \ + -s "Maximum fragment length is 4096" \ -C "client hello, adding max_fragment_length extension" \ -S "found max fragment length extension" \ -S "server hello, max_fragment_length extension" \ @@ -1113,6 +1119,7 @@ run_test "Max fragment length: gnutls server" \ "$G_SRV" \ "$P_CLI debug_level=3 max_frag_len=4096" \ 0 \ + -c "Maximum fragment length is 4096" \ -c "client hello, adding max_fragment_length extension" \ -c "found max_fragment_length extension" @@ -1120,6 +1127,8 @@ 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 "Maximum fragment length is 2048" \ + -s "Maximum fragment length is 2048" \ -c "client hello, adding max_fragment_length extension" \ -s "found max fragment length extension" \ -s "server hello, max_fragment_length extension" \ @@ -1131,6 +1140,8 @@ 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 "Maximum fragment length is 2048" \ + -s "Maximum fragment length is 2048" \ -c "client hello, adding max_fragment_length extension" \ -s "found max fragment length extension" \ -s "server hello, max_fragment_length extension" \ @@ -1143,6 +1154,8 @@ run_test "Max fragment length: DTLS 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 "Maximum fragment length is 2048" \ + -s "Maximum fragment length is 2048" \ -c "client hello, adding max_fragment_length extension" \ -s "found max fragment length extension" \ -s "server hello, max_fragment_length extension" \