From 8b46459ae540c32e60c12a9346c60dac3b8e0132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Jul 2013 12:45:26 +0200 Subject: [PATCH 01/16] Add ssl_set_max_frag_len() --- include/polarssl/ssl.h | 28 ++++++++++++++++++++++++++++ library/ssl_tls.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index eca6879e3..9bb0c4438 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -117,6 +117,13 @@ #define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ #define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ +/* RFC 6066 section 4 */ +#define SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ + #define SSL_IS_CLIENT 0 #define SSL_IS_SERVER 1 #define SSL_COMPRESS_NULL 0 @@ -498,6 +505,10 @@ struct _ssl_context size_t out_msglen; /*!< record header: message length */ size_t out_left; /*!< amount of data not yet written */ + /* Maximum fragment length extension (RFC 6066 section 4) */ + unsigned char mfl_code; /*!< numerical code for MaxFragmentLength */ + uint16_t max_frag_len; /*!< value of MaxFragmentLength */ + /* * PKI layer */ @@ -944,6 +955,23 @@ void ssl_set_max_version( ssl_context *ssl, int major, int minor ); */ void ssl_set_min_version( ssl_context *ssl, int major, int minor ); +/** + * \brief Set the maximum fragment length to emit and/or negotiate + * (Default: SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * + * \param ssl SSL context + * \param mfl Code for maximum fragment length (allowed values: + * SSL_MAX_FRAG_LEN_512, SSL_MAX_FRAG_LEN_1024, + * SSL_MAX_FRAG_LEN_2048, SSL_MAX_FRAG_LEN_4096) + * + * \return O if successful or POLARSSL_ERR_SSL_BAD_INPUT_DATA + */ +int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ); + /** * \brief Enable / Disable renegotiation support for connection when * initiated by peer diff --git a/library/ssl_tls.c b/library/ssl_tls.c index dfeed3377..b6bb44f78 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2826,6 +2826,9 @@ int ssl_init( ssl_context *ssl ) memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN ); memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); + ssl->mfl_code = SSL_MAX_FRAG_LEN_NONE; + ssl->max_frag_len = SSL_MAX_CONTENT_LEN; + ssl->hostname = NULL; ssl->hostname_len = 0; @@ -3111,6 +3114,35 @@ void ssl_set_min_version( ssl_context *ssl, int major, int minor ) ssl->min_minor_ver = minor; } +int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ) +{ + switch( mfl_code ) + { + case SSL_MAX_FRAG_LEN_512: + ssl->max_frag_len = 512; + break; + + case SSL_MAX_FRAG_LEN_1024: + ssl->max_frag_len = 1024; + break; + + case SSL_MAX_FRAG_LEN_2048: + ssl->max_frag_len = 2048; + break; + + case SSL_MAX_FRAG_LEN_4096: + ssl->max_frag_len = 4096; + break; + + default: + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + ssl->mfl_code = mfl_code; + + return( 0 ); +} + void ssl_set_renegotiation( ssl_context *ssl, int renegotiation ) { ssl->disable_renegotiation = renegotiation; From 0df6b1f068c0b9d61666b2272e405d42f232b4cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Jul 2013 13:39:57 +0200 Subject: [PATCH 02/16] ssl_client2: add max_frag_len option --- programs/ssl/ssl_client2.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 036cc67ae..63c1b66fd 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -57,6 +57,7 @@ #define DFL_MIN_VERSION -1 #define DFL_MAX_VERSION -1 #define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL +#define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE #define GET_REQUEST "GET %s HTTP/1.0\r\n\r\n" @@ -81,6 +82,7 @@ struct options int min_version; /* minimum protocol version accepted */ int max_version; /* maximum protocol version accepted */ int auth_mode; /* verify mode for connection */ + unsigned char mfl_code; /* code for maximum fragment length */ } opt; static void my_debug( void *ctx, int level, const char *str ) @@ -176,6 +178,8 @@ static int my_verify( void *data, x509_cert *crt, int depth, int *flags ) " options: ssl3, tls1, tls1_1, tls1_2\n" \ " auth_mode=%%s default: \"optional\"\n" \ " options: none, optional, required\n" \ + " max_frag_len=%%d default: 16384 (tls default)" \ + " options: 512, 1024, 2048, 4096" \ USAGE_PSK \ "\n" \ " force_ciphersuite= default: all enabled\n"\ @@ -265,6 +269,7 @@ int main( int argc, char *argv[] ) opt.min_version = DFL_MIN_VERSION; opt.max_version = DFL_MAX_VERSION; opt.auth_mode = DFL_AUTH_MODE; + opt.mfl_code = DFL_MFL_CODE; for( i = 1; i < argc; i++ ) { @@ -387,6 +392,19 @@ int main( int argc, char *argv[] ) else goto usage; } + else if( strcmp( p, "max_frag_len" ) == 0 ) + { + if( strcmp( q, "512" ) == 0 ) + opt.mfl_code = SSL_MAX_FRAG_LEN_512; + else if( strcmp( q, "1024" ) == 0 ) + opt.mfl_code = SSL_MAX_FRAG_LEN_1024; + else if( strcmp( q, "2048" ) == 0 ) + opt.mfl_code = SSL_MAX_FRAG_LEN_2048; + else if( strcmp( q, "4096" ) == 0 ) + opt.mfl_code = SSL_MAX_FRAG_LEN_4096; + else + goto usage; + } else goto usage; } @@ -592,6 +610,8 @@ int main( int argc, char *argv[] ) ssl_set_endpoint( &ssl, SSL_IS_CLIENT ); ssl_set_authmode( &ssl, opt.auth_mode ); + ssl_set_max_frag_len( &ssl, opt.mfl_code ); + ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg ); ssl_set_dbg( &ssl, my_debug, stdout ); ssl_set_bio( &ssl, net_recv, &server_fd, From 787b658bb34200860d224ae7f301dac2917a19c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Jul 2013 15:43:17 +0200 Subject: [PATCH 03/16] Implement max_frag_len write restriction --- library/ssl_tls.c | 4 ++-- programs/ssl/ssl_client2.c | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index b6bb44f78..b2d3dc85a 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3416,8 +3416,8 @@ int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) } } - n = ( len < SSL_MAX_CONTENT_LEN ) - ? len : SSL_MAX_CONTENT_LEN; + n = ( len < ssl->max_frag_len ) + ? len : ssl->max_frag_len; if( ssl->out_left != 0 ) { diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 63c1b66fd..0a7048120 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -59,7 +59,10 @@ #define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL #define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE -#define GET_REQUEST "GET %s HTTP/1.0\r\n\r\n" +/* Uncomment to test sending long paquets */ +#define LONG_HEADER // "User-agent: blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-END\r\n" + +#define GET_REQUEST "GET %s HTTP/1.0\r\n" LONG_HEADER "\r\n" /* * global options @@ -201,7 +204,7 @@ int main( int argc, char *argv[] ) #else int main( int argc, char *argv[] ) { - int ret = 0, len, server_fd, i; + int ret = 0, len, server_fd, i, written; unsigned char buf[1024]; #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) unsigned char psk[256]; @@ -702,17 +705,20 @@ int main( int argc, char *argv[] ) len = sprintf( (char *) buf, GET_REQUEST, opt.request_page ); - while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 ) + for( written = 0; written < len; written += ret ) { - if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) + while( ( ret = ssl_write( &ssl, buf + written, len - written ) ) <= 0 ) { - printf( " failed\n ! ssl_write returned -0x%x\n\n", -ret ); - goto exit; + if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) + { + printf( " failed\n ! ssl_write returned -0x%x\n\n", -ret ); + goto exit; + } } } - len = ret; - printf( " %d bytes written\n\n%s", len, (char *) buf ); + buf[written] = '\0'; + printf( " %d bytes written\n\n%s\n", written, (char *) buf ); /* * 7. Read the HTTP response From 48f8d0dbbd6d86aa16d0df785da163d9fde0a2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 17 Jul 2013 10:25:37 +0200 Subject: [PATCH 04/16] Read max_fragment_length extension (server) --- include/polarssl/ssl.h | 2 ++ library/ssl_srv.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 9bb0c4438..24e60f793 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -247,6 +247,8 @@ #define TLS_EXT_SERVERNAME 0 #define TLS_EXT_SERVERNAME_HOSTNAME 0 +#define TLS_EXT_MAX_FRAGMENT_LENGTH 1 + #define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 #define TLS_EXT_SUPPORTED_POINT_FORMATS 11 diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 2aef9c415..0e3225101 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -291,6 +291,22 @@ static int ssl_parse_supported_point_formats( ssl_context *ssl, } #endif /* POLARSSL_ECP_C */ +static int ssl_parse_max_fragment_length_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( len != 1 || + ( ret = ssl_set_max_frag_len( ssl, buf[0] ) ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + return( 0 ); +} + #if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) static int ssl_parse_client_hello_v2( ssl_context *ssl ) { @@ -825,6 +841,14 @@ static int ssl_parse_client_hello( ssl_context *ssl ) break; #endif /* POLARSSL_ECP_C */ + case TLS_EXT_MAX_FRAGMENT_LENGTH: + SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); + + ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + default: SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", ext_id ) ); From a05284964066af1d60d77e3c82733204930f878d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Jul 2013 17:26:28 +0200 Subject: [PATCH 05/16] Send max_fragment_length extension (client) --- library/ssl_cli.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index aeba799cb..9dbf4e603 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -269,6 +269,30 @@ static void ssl_write_supported_point_formats_ext( ssl_context *ssl, } #endif +static void ssl_write_max_fragment_length_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE ) { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->mfl_code; + + *olen = 5; +} + static int ssl_write_client_hello( ssl_context *ssl ) { int ret; @@ -436,6 +460,9 @@ static int ssl_write_client_hello( ssl_context *ssl ) ext_len += olen; #endif + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", ext_len ) ); @@ -690,6 +717,8 @@ static int ssl_parse_server_hello( ssl_context *ssl ) ext = buf + 44 + n; + SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) ); + while( ext_len ) { unsigned int ext_id = ( ( ext[0] << 8 ) From de600e571a311d1cd5e47dc78c8c3b46465f2b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 17 Jul 2013 10:14:38 +0200 Subject: [PATCH 06/16] Read max_fragment_length extension (client) --- library/ssl_cli.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 9dbf4e603..9050edb84 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -526,6 +526,23 @@ static int ssl_parse_renegotiation_info( ssl_context *ssl, return( 0 ); } +static int ssl_parse_max_fragment_length_ext( ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + /* + * server should use the extension only if we did, + * and if so the server's value should match ours (and len is always 1) + */ + if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE || + len != 1 || + buf[0] != ssl->mfl_code ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + return( 0 ); +} static int ssl_parse_server_hello( ssl_context *ssl ) { @@ -743,6 +760,17 @@ static int ssl_parse_server_hello( ssl_context *ssl ) break; + case TLS_EXT_MAX_FRAGMENT_LENGTH: + SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) ); + + if( ( ret = ssl_parse_max_fragment_length_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; + default: SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", ext_id ) ); From f11a6d78c7c07d682f49d923009a99a5db5f6350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 17 Jul 2013 11:17:14 +0200 Subject: [PATCH 07/16] Rework server extensions writing --- library/ssl_srv.c | 76 ++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 0e3225101..7e1df64b1 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -958,13 +958,42 @@ have_ciphersuite: return( 0 ); } +static void ssl_write_renegotiation_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->secure_renegotiation != SSL_SECURE_RENEGOTIATION ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; + *p++ = ssl->verify_data_len * 2 & 0xFF; + + memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + + *olen = 5 + ssl->verify_data_len * 2; +} + static int ssl_write_server_hello( ssl_context *ssl ) { #if defined(POLARSSL_HAVE_TIME) time_t t; #endif int ret, n; - size_t ext_len = 0; + size_t olen, ext_len = 0; unsigned char *buf, *p; SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); @@ -1010,10 +1039,12 @@ static int ssl_write_server_hello( ssl_context *ssl ) SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); /* - * 38 . 38 session id length - * 39 . 38+n session id - * 39+n . 40+n chosen ciphersuite - * 41+n . 41+n chosen compression alg. + * 38 . 38 session id length + * 39 . 38+n session id + * 39+n . 40+n chosen ciphersuite + * 41+n . 41+n chosen compression alg. + * 42+n . 43+n extensions length + * 44+n . 43+n+m extensions */ ssl->session_negotiate->length = n = 32; *p++ = (unsigned char) ssl->session_negotiate->length; @@ -1064,34 +1095,17 @@ static int ssl_write_server_hello( ssl_context *ssl ) SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", ssl->session_negotiate->compression ) ); - if( ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION ) - { - SSL_DEBUG_MSG( 3, ( "server hello, prepping for secure renegotiation extension" ) ); - ext_len += 5 + ssl->verify_data_len * 2; + /* + * First write extensions, then the total length + */ + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; - SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", - ext_len ) ); + SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); - *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ext_len ) & 0xFF ); - - /* - * Secure renegotiation - */ - SSL_DEBUG_MSG( 3, ( "client hello, secure renegotiation extension" ) ); - - *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); - - *p++ = 0x00; - *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; - *p++ = ssl->verify_data_len * 2 & 0xFF; - - memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); - p += ssl->verify_data_len; - memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); - p += ssl->verify_data_len; - } + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; ssl->out_msglen = p - buf; ssl->out_msgtype = SSL_MSG_HANDSHAKE; From 7bb7899121c20ff7e2ea920d3233bf1325acddc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 17 Jul 2013 13:50:08 +0200 Subject: [PATCH 08/16] Send max_fragment_length extension (server) --- library/ssl_srv.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 7e1df64b1..2177253f3 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -987,6 +987,30 @@ static void ssl_write_renegotiation_ext( ssl_context *ssl, *olen = 5 + ssl->verify_data_len * 2; } +static void ssl_write_max_fragment_length_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE ) { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->mfl_code; + + *olen = 5; +} + static int ssl_write_server_hello( ssl_context *ssl ) { #if defined(POLARSSL_HAVE_TIME) @@ -1101,6 +1125,9 @@ static int ssl_write_server_hello( ssl_context *ssl ) ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); From 30dc7ef3adab20f1d23ccc1ba96039a7b84b49c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 17 Jul 2013 14:03:42 +0200 Subject: [PATCH 09/16] Reset max_fragment_length in ssl_session_reset() --- library/ssl_tls.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index b2d3dc85a..9a1590c58 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2870,6 +2870,9 @@ int ssl_session_reset( ssl_context *ssl ) ssl->out_msglen = 0; ssl->out_left = 0; + ssl->mfl_code = SSL_MAX_FRAG_LEN_NONE; + ssl->max_frag_len = SSL_MAX_CONTENT_LEN; + ssl->transform_in = NULL; ssl->transform_out = NULL; From 6b4f237f6accd027f854f7efa3bdad6b2ba38361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 17 Jul 2013 14:33:38 +0200 Subject: [PATCH 10/16] Forbid setting max_frag_len > MAX_CONTENT_LEN --- library/ssl_tls.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 9a1590c58..d6be98733 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3119,29 +3119,35 @@ void ssl_set_min_version( ssl_context *ssl, int major, int minor ) int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ) { + uint16_t max_frag_len; + switch( mfl_code ) { case SSL_MAX_FRAG_LEN_512: - ssl->max_frag_len = 512; + max_frag_len = 512; break; case SSL_MAX_FRAG_LEN_1024: - ssl->max_frag_len = 1024; + max_frag_len = 1024; break; case SSL_MAX_FRAG_LEN_2048: - ssl->max_frag_len = 2048; + max_frag_len = 2048; break; case SSL_MAX_FRAG_LEN_4096: - ssl->max_frag_len = 4096; + max_frag_len = 4096; break; default: return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); } + if( max_frag_len > SSL_MAX_CONTENT_LEN ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + ssl->mfl_code = mfl_code; + ssl->max_frag_len = max_frag_len; return( 0 ); } From bd7ce6311539b69888a70604f7472958760c367d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 17 Jul 2013 15:34:17 +0200 Subject: [PATCH 11/16] Adapt ssl_server2 to test sending long messages --- programs/ssl/ssl_server2.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 5b7639aed..d367c4ec6 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -69,10 +69,16 @@ #define DFL_MAX_VERSION -1 #define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL +#define LONG_RESPONSE "

blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah

\r\n" + +/* Uncomment LONG_RESPONSE to test sending long paquets */ #define HTTP_RESPONSE \ "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ "

PolarSSL Test Server

\r\n" \ - "

Successful connection using: %s

\r\n" + "

Successful connection using: %s

\r\n" // LONG_RESPONSE /* * global options @@ -168,7 +174,7 @@ int main( int argc, char *argv[] ) #else int main( int argc, char *argv[] ) { - int ret = 0, len; + int ret = 0, len, written; int listen_fd; int client_fd = -1; unsigned char buf[1024]; @@ -748,7 +754,7 @@ reset: } len = ret; - printf( " %d bytes read\n\n%s", len, (char *) buf ); + printf( " %d bytes read\n\n%s\n", len, (char *) buf ); if( memcmp( buf, "SERVERQUIT", 10 ) == 0 ) goto exit; @@ -767,23 +773,26 @@ reset: len = sprintf( (char *) buf, HTTP_RESPONSE, ssl_get_ciphersuite( &ssl ) ); - while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 ) + for( written = 0; written < len; written += ret ) { - if( ret == POLARSSL_ERR_NET_CONN_RESET ) + while( ( ret = ssl_write( &ssl, buf + written, len - written ) ) <= 0 ) { - printf( " failed\n ! peer closed the connection\n\n" ); - goto reset; - } + if( ret == POLARSSL_ERR_NET_CONN_RESET ) + { + printf( " failed\n ! peer closed the connection\n\n" ); + goto reset; + } - if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) - { - printf( " failed\n ! ssl_write returned %d\n\n", ret ); - goto exit; + if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) + { + printf( " failed\n ! ssl_write returned %d\n\n", ret ); + goto exit; + } } } - len = ret; - printf( " %d bytes written\n\n%s\n", len, (char *) buf ); + buf[written] = '\0'; + printf( " %d bytes written\n\n%s\n", written, (char *) buf ); ret = 0; goto reset; From 8e714d7acad8b68e4be7aa6fde88c75b75b44c36 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Thu, 18 Jul 2013 11:05:13 +0200 Subject: [PATCH 12/16] Modified LONG_RESPONSE and comments in ssl_server2 --- programs/ssl/ssl_server2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index d367c4ec6..ab2a87f7a 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -69,12 +69,13 @@ #define DFL_MAX_VERSION -1 #define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL -#define LONG_RESPONSE "

blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ - "blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ - "blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ - "blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah

\r\n" +#define LONG_RESPONSE "

01-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "03-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "04-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah

\r\n" -/* Uncomment LONG_RESPONSE to test sending long paquets */ +/* Uncomment LONG_RESPONSE at the end of HTTP_RESPONSE to test sending longer + * packets (for fragmentation purposes) */ #define HTTP_RESPONSE \ "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ "

PolarSSL Test Server

\r\n" \ From 581e6b6d6cbdc2f913876fd4c0cfb1531da87e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 18 Jul 2013 12:32:27 +0200 Subject: [PATCH 13/16] Prepare migrating max fragment length to session Remove max_frag_len member so that reseting session by memset()ing it to zero does the right thing. --- include/polarssl/ssl.h | 4 +-- library/ssl_tls.c | 56 ++++++++++++++++++++---------------------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 24e60f793..5b4e36f2f 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -117,7 +117,8 @@ #define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ #define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ -/* RFC 6066 section 4 */ +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing session to zero works */ #define SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ #define SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ #define SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ @@ -509,7 +510,6 @@ struct _ssl_context /* Maximum fragment length extension (RFC 6066 section 4) */ unsigned char mfl_code; /*!< numerical code for MaxFragmentLength */ - uint16_t max_frag_len; /*!< value of MaxFragmentLength */ /* * PKI layer diff --git a/library/ssl_tls.c b/library/ssl_tls.c index d6be98733..0374ee818 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -59,6 +59,23 @@ #define strcasecmp _stricmp #endif +/* + * Convert max_fragment_length codes to length. + * RFC 6066 says: + * enum{ + * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) + * } MaxFragmentLength; + * and we add 0 -> extension unused + */ +static unsigned int mfl_code_to_length[] = +{ + SSL_MAX_CONTENT_LEN, /* SSL_MAX_FRAG_LEN_NONE */ + 512, /* SSL_MAX_FRAG_LEN_512 */ + 1024, /* SSL_MAX_FRAG_LEN_1024 */ + 2048, /* SSL_MAX_FRAG_LEN_2048 */ + 4096, /* SSL_MAX_FRAG_LEN_4096 */ +}; + #if defined(POLARSSL_SSL_HW_RECORD_ACCEL) int (*ssl_hw_record_init)(ssl_context *ssl, const unsigned char *key_enc, const unsigned char *key_dec, @@ -2827,7 +2844,6 @@ int ssl_init( ssl_context *ssl ) memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); ssl->mfl_code = SSL_MAX_FRAG_LEN_NONE; - ssl->max_frag_len = SSL_MAX_CONTENT_LEN; ssl->hostname = NULL; ssl->hostname_len = 0; @@ -2871,7 +2887,6 @@ int ssl_session_reset( ssl_context *ssl ) ssl->out_left = 0; ssl->mfl_code = SSL_MAX_FRAG_LEN_NONE; - ssl->max_frag_len = SSL_MAX_CONTENT_LEN; ssl->transform_in = NULL; ssl->transform_out = NULL; @@ -3119,35 +3134,13 @@ void ssl_set_min_version( ssl_context *ssl, int major, int minor ) int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ) { - uint16_t max_frag_len; - - switch( mfl_code ) + if( mfl_code >= sizeof( mfl_code_to_length ) || + mfl_code_to_length[mfl_code] > SSL_MAX_CONTENT_LEN ) { - case SSL_MAX_FRAG_LEN_512: - max_frag_len = 512; - break; - - case SSL_MAX_FRAG_LEN_1024: - max_frag_len = 1024; - break; - - case SSL_MAX_FRAG_LEN_2048: - max_frag_len = 2048; - break; - - case SSL_MAX_FRAG_LEN_4096: - max_frag_len = 4096; - break; - - default: - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); } - if( max_frag_len > SSL_MAX_CONTENT_LEN ) - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - ssl->mfl_code = mfl_code; - ssl->max_frag_len = max_frag_len; return( 0 ); } @@ -3413,6 +3406,7 @@ int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) { int ret; size_t n; + unsigned int max_len; SSL_DEBUG_MSG( 2, ( "=> write" ) ); @@ -3425,8 +3419,12 @@ int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) } } - n = ( len < ssl->max_frag_len ) - ? len : ssl->max_frag_len; + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = mfl_code_to_length[ssl->mfl_code]; + + n = ( len < max_len) ? len : max_len; if( ssl->out_left != 0 ) { From ed4af8b57cefdf9cf6ce1bfee79f4d1f6139112d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 18 Jul 2013 14:07:09 +0200 Subject: [PATCH 14/16] Move negotiated max fragment length to session User-set max fragment length remains in ssl_context. The min of the two is used for sizing fragments. --- include/polarssl/ssl.h | 6 ++++-- library/ssl_srv.c | 11 +++++------ library/ssl_tls.c | 13 ++++++++++--- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 5b4e36f2f..e9e33e357 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -124,6 +124,7 @@ #define SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ #define SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ #define SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ #define SSL_IS_CLIENT 0 #define SSL_IS_SERVER 1 @@ -330,6 +331,8 @@ struct _ssl_session #if defined(POLARSSL_X509_PARSE_C) x509_cert *peer_cert; /*!< peer X.509 cert chain */ #endif /* POLARSSL_X509_PARSE_C */ + + unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ }; /* @@ -508,8 +511,7 @@ struct _ssl_context size_t out_msglen; /*!< record header: message length */ size_t out_left; /*!< amount of data not yet written */ - /* Maximum fragment length extension (RFC 6066 section 4) */ - unsigned char mfl_code; /*!< numerical code for MaxFragmentLength */ + unsigned char mfl_code; /*!< MaxFragmentLength chosen by us */ /* * PKI layer diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 2177253f3..abcc867dd 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -295,15 +295,14 @@ static int ssl_parse_max_fragment_length_ext( ssl_context *ssl, const unsigned char *buf, size_t len ) { - int ret; - - if( len != 1 || - ( ret = ssl_set_max_frag_len( ssl, buf[0] ) ) != 0 ) + if( len != 1 || buf[0] >= SSL_MAX_FRAG_LEN_INVALID ) { SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); } + ssl->session_negotiate->mfl_code = buf[0]; + return( 0 ); } @@ -993,7 +992,7 @@ static void ssl_write_max_fragment_length_ext( ssl_context *ssl, { unsigned char *p = buf; - if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE ) { + if( ssl->session_negotiate->mfl_code == SSL_MAX_FRAG_LEN_NONE ) { *olen = 0; return; } @@ -1006,7 +1005,7 @@ static void ssl_write_max_fragment_length_ext( ssl_context *ssl, *p++ = 0x00; *p++ = 1; - *p++ = ssl->mfl_code; + *p++ = ssl->session_negotiate->mfl_code; *olen = 5; } diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 0374ee818..a230dc939 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -67,7 +67,7 @@ * } MaxFragmentLength; * and we add 0 -> extension unused */ -static unsigned int mfl_code_to_length[] = +static unsigned int mfl_code_to_length[SSL_MAX_FRAG_LEN_INVALID] = { SSL_MAX_CONTENT_LEN, /* SSL_MAX_FRAG_LEN_NONE */ 512, /* SSL_MAX_FRAG_LEN_512 */ @@ -2886,8 +2886,6 @@ int ssl_session_reset( ssl_context *ssl ) ssl->out_msglen = 0; ssl->out_left = 0; - ssl->mfl_code = SSL_MAX_FRAG_LEN_NONE; - ssl->transform_in = NULL; ssl->transform_out = NULL; @@ -3424,6 +3422,15 @@ int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) */ max_len = mfl_code_to_length[ssl->mfl_code]; + /* + * Check if a smaller max length was negociated + */ + 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]; + } + n = ( len < max_len) ? len : max_len; if( ssl->out_left != 0 ) From 0c017a55e0fb50e9ed4c77ff512ce8bc0bcebb29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 18 Jul 2013 14:07:36 +0200 Subject: [PATCH 15/16] Add max_frag_len option in ssl_server2 Also reformat code and output more information in ssl_client2 --- programs/ssl/ssl_client2.c | 17 ++++++++++++----- programs/ssl/ssl_server2.c | 37 ++++++++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 0a7048120..0c770f6d9 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -59,8 +59,15 @@ #define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL #define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE -/* Uncomment to test sending long paquets */ -#define LONG_HEADER // "User-agent: blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-END\r\n" +/* Uncomment to test sending longer paquets (for fragmentation purposes) */ +#define LONG_HEADER // "User-agent: blah-blah-blah-blah-blah-blah-blah-" \ + "-01--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \ + "-02--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \ + "-03--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \ + "-04--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \ + "-05--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \ + "-06--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \ + "-07--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-END\r\n" #define GET_REQUEST "GET %s HTTP/1.0\r\n" LONG_HEADER "\r\n" @@ -204,7 +211,7 @@ int main( int argc, char *argv[] ) #else int main( int argc, char *argv[] ) { - int ret = 0, len, server_fd, i, written; + int ret = 0, len, server_fd, i, written, frags; unsigned char buf[1024]; #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) unsigned char psk[256]; @@ -705,7 +712,7 @@ int main( int argc, char *argv[] ) len = sprintf( (char *) buf, GET_REQUEST, opt.request_page ); - for( written = 0; written < len; written += ret ) + for( written = 0, frags = 0; written < len; written += ret, frags++ ) { while( ( ret = ssl_write( &ssl, buf + written, len - written ) ) <= 0 ) { @@ -718,7 +725,7 @@ int main( int argc, char *argv[] ) } buf[written] = '\0'; - printf( " %d bytes written\n\n%s\n", written, (char *) buf ); + printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf ); /* * 7. Read the HTTP response diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index ab2a87f7a..d5ebb812b 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -68,11 +68,15 @@ #define DFL_MIN_VERSION -1 #define DFL_MAX_VERSION -1 #define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL +#define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE -#define LONG_RESPONSE "

01-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ - "02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ - "03-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ - "04-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah

\r\n" +#define LONG_RESPONSE "

01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "03-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "04-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "05-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "06-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "07-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah

\r\n" /* Uncomment LONG_RESPONSE at the end of HTTP_RESPONSE to test sending longer * packets (for fragmentation purposes) */ @@ -100,6 +104,7 @@ struct options int min_version; /* minimum protocol version accepted */ int max_version; /* maximum protocol version accepted */ int auth_mode; /* verify mode for connection */ + unsigned char mfl_code; /* code for maximum fragment length */ } opt; static void my_debug( void *ctx, int level, const char *str ) @@ -154,6 +159,8 @@ static void my_debug( void *ctx, int level, const char *str ) " options: ssl3, tls1, tls1_1, tls1_2\n" \ " auth_mode=%%s default: \"optional\"\n" \ " options: none, optional, required\n" \ + " max_frag_len=%%d default: 16384 (tls default)" \ + " options: 512, 1024, 2048, 4096" \ USAGE_PSK \ "\n" \ " force_ciphersuite= default: all enabled\n"\ @@ -175,7 +182,7 @@ int main( int argc, char *argv[] ) #else int main( int argc, char *argv[] ) { - int ret = 0, len, written; + int ret = 0, len, written, frags; int listen_fd; int client_fd = -1; unsigned char buf[1024]; @@ -257,6 +264,7 @@ int main( int argc, char *argv[] ) opt.min_version = DFL_MIN_VERSION; opt.max_version = DFL_MAX_VERSION; opt.auth_mode = DFL_AUTH_MODE; + opt.mfl_code = DFL_MFL_CODE; for( i = 1; i < argc; i++ ) { @@ -375,6 +383,19 @@ int main( int argc, char *argv[] ) else goto usage; } + else if( strcmp( p, "max_frag_len" ) == 0 ) + { + if( strcmp( q, "512" ) == 0 ) + opt.mfl_code = SSL_MAX_FRAG_LEN_512; + else if( strcmp( q, "1024" ) == 0 ) + opt.mfl_code = SSL_MAX_FRAG_LEN_1024; + else if( strcmp( q, "2048" ) == 0 ) + opt.mfl_code = SSL_MAX_FRAG_LEN_2048; + else if( strcmp( q, "4096" ) == 0 ) + opt.mfl_code = SSL_MAX_FRAG_LEN_4096; + else + goto usage; + } else goto usage; } @@ -569,6 +590,8 @@ int main( int argc, char *argv[] ) ssl_set_endpoint( &ssl, SSL_IS_SERVER ); ssl_set_authmode( &ssl, opt.auth_mode ); + ssl_set_max_frag_len( &ssl, opt.mfl_code ); + ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg ); ssl_set_dbg( &ssl, my_debug, stdout ); @@ -774,7 +797,7 @@ reset: len = sprintf( (char *) buf, HTTP_RESPONSE, ssl_get_ciphersuite( &ssl ) ); - for( written = 0; written < len; written += ret ) + for( written = 0, frags = 0; written < len; written += ret, frags++ ) { while( ( ret = ssl_write( &ssl, buf + written, len - written ) ) <= 0 ) { @@ -793,7 +816,7 @@ reset: } buf[written] = '\0'; - printf( " %d bytes written\n\n%s\n", written, (char *) buf ); + printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf ); ret = 0; goto reset; From e048b67d0a2f73166b405194d489ff9fa7ee2f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 19 Jul 2013 12:47:00 +0200 Subject: [PATCH 16/16] Misc minor fixes - avoid "multi-line comment" warning in ssl_client2.c - rm useless initialisation of mfl_code in ssl_init() - const-correctness of ssl_parse_*_ext() - a code formating issue --- include/polarssl/ssl.h | 2 +- library/ssl_cli.c | 4 ++-- library/ssl_srv.c | 3 ++- library/ssl_tls.c | 2 -- programs/ssl/ssl_client2.c | 7 ++++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index e9e33e357..4e1d25a83 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -118,7 +118,7 @@ #define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ /* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c - * NONE must be zero so that memset()ing session to zero works */ + * NONE must be zero so that memset()ing structure to zero works */ #define SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ #define SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ #define SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 9050edb84..c89bf0cb0 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -488,7 +488,7 @@ static int ssl_write_client_hello( ssl_context *ssl ) } static int ssl_parse_renegotiation_info( ssl_context *ssl, - unsigned char *buf, + const unsigned char *buf, size_t len ) { int ret; @@ -527,7 +527,7 @@ static int ssl_parse_renegotiation_info( ssl_context *ssl, return( 0 ); } static int ssl_parse_max_fragment_length_ext( ssl_context *ssl, - unsigned char *buf, + const unsigned char *buf, size_t len ) { /* diff --git a/library/ssl_srv.c b/library/ssl_srv.c index abcc867dd..3e1838667 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -992,7 +992,8 @@ static void ssl_write_max_fragment_length_ext( ssl_context *ssl, { unsigned char *p = buf; - if( ssl->session_negotiate->mfl_code == SSL_MAX_FRAG_LEN_NONE ) { + if( ssl->session_negotiate->mfl_code == SSL_MAX_FRAG_LEN_NONE ) + { *olen = 0; return; } diff --git a/library/ssl_tls.c b/library/ssl_tls.c index a230dc939..f701a8a1f 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2843,8 +2843,6 @@ int ssl_init( ssl_context *ssl ) memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN ); memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); - ssl->mfl_code = SSL_MAX_FRAG_LEN_NONE; - ssl->hostname = NULL; ssl->hostname_len = 0; diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 0c770f6d9..56d0e9112 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -59,8 +59,7 @@ #define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL #define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE -/* Uncomment to test sending longer paquets (for fragmentation purposes) */ -#define LONG_HEADER // "User-agent: blah-blah-blah-blah-blah-blah-blah-" \ +#define LONG_HEADER "User-agent: blah-blah-blah-blah-blah-blah-blah-blah-" \ "-01--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \ "-02--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \ "-03--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \ @@ -69,7 +68,9 @@ "-06--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \ "-07--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-END\r\n" -#define GET_REQUEST "GET %s HTTP/1.0\r\n" LONG_HEADER "\r\n" +/* Uncomment LONG_HEADER in the definition of GET_REQUEST to test sending + * longer paquets (for fragmentation purposes) */ +#define GET_REQUEST "GET %s HTTP/1.0\r\n" /* LONG_HEADER */ "\r\n" /* * global options