diff --git a/ChangeLog b/ChangeLog index aae130d16..0f9d6bd60 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,15 @@ Features is controlled by the maximum fragment length as set locally or negotiated with the peer, as well as by a new per-connection MTU option, set using mbedtls_ssl_set_mtu(). + * Add support for auto-adjustment of MTU to a safe value during the + handshake when flights do not get through (RFC 6347, section 4.1.1.1, + last paragraph). + * Add support for packing multiple records within a single datagram, + enabled by default. + +API Changes + * Add function mbedtls_ssl_set_datagram_packing() to configure + the use of datagram packing (enabled by default). Bugfix * Fixes an issue with MBEDTLS_CHACHAPOLY_C which would not compile if diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 090660733..da4b68828 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1098,6 +1098,11 @@ struct mbedtls_ssl_context int keep_current_message; /*!< drop or reuse current message on next call to record layer? */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint8_t disable_datagram_packing; /*!< Disable packing multiple records + * within a single datagram. */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* * Record layer (outgoing data) */ @@ -1112,6 +1117,8 @@ struct mbedtls_ssl_context size_t out_msglen; /*!< record header: message length */ size_t out_left; /*!< amount of data not yet written */ + unsigned char cur_out_ctr[8]; /*!< Outgoing record sequence number. */ + #if defined(MBEDTLS_SSL_PROTO_DTLS) uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */ #endif @@ -1806,6 +1813,38 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi #endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ #if defined(MBEDTLS_SSL_PROTO_DTLS) + +/** + * \brief Allow or disallow packing of multiple handshake records + * within a single datagram. + * + * \param ssl The SSL context to configure. + * \param allow_packing This determines whether datagram packing may + * be used or not. A value of \c 0 means that every + * record will be sent in a separate datagram; a + * value of \c 1 means that, if space permits, + * multiple handshake messages (including CCS) belonging to + * a single flight may be packed within a single datagram. + * + * \note This is enabled by default and should only be disabled + * for test purposes, or if datagram packing causes + * interoperability issues with peers that don't support it. + * + * \note Allowing datagram packing reduces the network load since + * there's less overhead if multiple messages share the same + * datagram. Also, it increases the handshake efficiency + * since messages belonging to a single datagram will not + * be reordered in transit, and so future message buffering + * or flight retransmission (if no buffering is used) as + * means to deal with reordering are needed less frequently. + * + * \note Application records are not affected by this option and + * are currently always sent in separate datagrams. + * + */ +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ); + /** * \brief Set retransmit timeout values for the DTLS handshake. * (DTLS only, no effect on TLS.) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 18982f89a..65b1fc9e7 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -307,6 +307,7 @@ struct mbedtls_ssl_handshake_params resending messages */ unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter for resending messages */ + uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* @@ -561,7 +562,7 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ); int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ); int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); diff --git a/library/ssl_srv.c b/library/ssl_srv.c index eda50bb34..7101f461f 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -1294,7 +1294,7 @@ read_record_header: return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } - memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 ); + memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 ); #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 1a8d791d2..1818abdee 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -54,6 +54,8 @@ #include "mbedtls/oid.h" #endif +static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); + /* Length of the "epoch" field in the record header */ static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) { @@ -96,7 +98,90 @@ static int ssl_check_timer( mbedtls_ssl_context *ssl ) return( 0 ); } +static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); +static void ssl_update_in_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); + +#define SSL_DONT_FORCE_FLUSH 0 +#define SSL_FORCE_FLUSH 1 + #if defined(MBEDTLS_SSL_PROTO_DTLS) + +static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); +static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) +{ + size_t mtu = ssl_get_current_mtu( ssl ); + + if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN ) + return( mtu ); + + return( MBEDTLS_SSL_OUT_BUFFER_LEN ); +} + +static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) +{ + size_t const bytes_written = ssl->out_left; + size_t const mtu = ssl_get_maximum_datagram_size( ssl ); + + /* Double-check that the write-index hasn't gone + * past what we can transmit in a single datagram. */ + if( bytes_written > mtu ) + { + /* Should never happen... */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int) ( mtu - bytes_written ) ); +} + +static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) +{ + int ret; + size_t remaining, expansion; + size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; + + /* By the standard (RFC 6066 Sect. 4), the MFL extension + * only limits the maximum record payload size, so in theory + * we would be allowed to pack multiple records of payload size + * MFL into a single datagram. However, this would mean that there's + * no way to explicitly communicate MTU restrictions to the peer. + * + * The following reduction of max_len makes sure that we never + * write datagrams larger than MFL + Record Expansion Overhead. + */ + if( max_len <= ssl->out_left ) + return( 0 ); + + max_len -= ssl->out_left; +#endif + + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + remaining = (size_t) ret; + + ret = mbedtls_ssl_get_record_expansion( ssl ); + if( ret < 0 ) + return( ret ); + expansion = (size_t) ret; + + if( remaining <= expansion ) + return( 0 ); + + remaining -= expansion; + if( remaining >= max_len ) + remaining = max_len; + + return( (int) remaining ); +} + /* * Double the retransmit timeout value, within the allowed range, * returning -1 if the maximum value has already been reached. @@ -108,6 +193,15 @@ static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) return( -1 ); + /* Implement the final paragraph of RFC 6347 section 4.1.1.1 + * in the following way: after the initial transmission and a first + * retransmission, back off to a temporary estimated MTU of 508 bytes. + * This value is guaranteed to be deliverable (if not guaranteed to be + * delivered) of any compliant IPv4 (and IPv6) network, and should work + * on most non-IP stacks too. */ + if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) + ssl->handshake->mtu = 508; + new_timeout = 2 * ssl->handshake->retransmit_timeout; /* Avoid arithmetic overflow and range overflow */ @@ -1345,14 +1439,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", ssl->out_msg, ssl->out_msglen ); - if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d", - (unsigned) ssl->out_msglen, - MBEDTLS_SSL_OUT_CONTENT_LEN ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - /* * Add MAC before if needed */ @@ -2644,7 +2730,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) { int ret; - unsigned char *buf, i; + unsigned char *buf; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); @@ -2667,8 +2753,7 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); - buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) + - ssl->out_msglen - ssl->out_left; + buf = ssl->out_hdr - ssl->out_left; ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); @@ -2687,16 +2772,17 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) ssl->out_left -= ret; } - for( i = 8; i > ssl_ep_len( ssl ); i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == ssl_ep_len( ssl ) ) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + ssl->out_hdr = ssl->out_buf; } + else +#endif + { + ssl->out_hdr = ssl->out_buf + 8; + } + ssl_update_out_pointers( ssl, ssl->transform_out ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); @@ -2713,6 +2799,9 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) static int ssl_flight_append( mbedtls_ssl_context *ssl ) { mbedtls_ssl_flight_item *msg; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight", + ssl->out_msg, ssl->out_msglen ); /* Allocate space for current message */ if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) @@ -2746,6 +2835,7 @@ static int ssl_flight_append( mbedtls_ssl_context *ssl ) cur->next = msg; } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) ); return( 0 ); } @@ -2794,19 +2884,12 @@ static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) ssl->handshake->alt_transform_out = tmp_transform; /* Swap epoch + sequence_number */ - memcpy( tmp_out_ctr, ssl->out_ctr, 8 ); - memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 ); + memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 ); + memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 ); memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); /* Adjust to the newly activated transform */ - if( ssl->transform_out != NULL && - ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen - - ssl->transform_out->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; + ssl_update_out_pointers( ssl, ssl->transform_out ); #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_activate != NULL ) @@ -2845,6 +2928,7 @@ int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) */ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) { + int ret; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) ); if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) @@ -2860,22 +2944,43 @@ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) while( ssl->handshake->cur_msg != NULL ) { - int ret; + size_t max_frag_len; const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; + + int const is_finished = + ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ); + + uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? + SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; + /* Swap epochs before sending Finished: we can't do it after * sending ChangeCipherSpec, in case write returns WANT_READ. * Must be done before copying, may change out_msg pointer */ - if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && - cur->p[0] == MBEDTLS_SSL_HS_FINISHED ) + if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) ) { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) ); ssl_swap_epochs( ssl ); } + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + max_frag_len = (size_t) ret; + /* CCS is copied as is, while HS messages may need fragmentation */ if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) { + if( max_frag_len == 0 ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + memcpy( ssl->out_msg, cur->p, cur->len ); - ssl->out_msglen = cur->len; + ssl->out_msglen = cur->len; ssl->out_msgtype = cur->type; /* Update position inside current message */ @@ -2883,29 +2988,32 @@ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) } else { - const int ret_payload = mbedtls_ssl_get_max_out_record_payload( ssl ); - const size_t max_record_payload = (size_t) ret_payload; - /* DTLS handshake headers are 12 bytes */ - const size_t max_hs_fragment_len = max_record_payload - 12; const unsigned char * const p = ssl->handshake->cur_msg_p; const size_t hs_len = cur->len - 12; const size_t frag_off = p - ( cur->p + 12 ); const size_t rem_len = hs_len - frag_off; - const size_t frag_len = rem_len > max_hs_fragment_len - ? max_hs_fragment_len : rem_len; + size_t cur_hs_frag_len, max_hs_frag_len; - if( ret_payload < 0 ) + if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", - ret_payload ); - return( ret_payload ); - } + if( is_finished ) + ssl_swap_epochs( ssl ); - if( frag_off == 0 && frag_len != hs_len ) + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + max_hs_frag_len = max_frag_len - 12; + + cur_hs_frag_len = rem_len > max_hs_frag_len ? + max_hs_frag_len : rem_len; + + if( frag_off == 0 && cur_hs_frag_len != hs_len ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)", - (unsigned) hs_len, - (unsigned) max_hs_fragment_len ) ); + (unsigned) cur_hs_frag_len, + (unsigned) max_hs_frag_len ) ); } /* Messages are stored with handshake headers as if not fragmented, @@ -2917,19 +3025,19 @@ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff ); ssl->out_msg[8] = ( ( frag_off ) & 0xff ); - ssl->out_msg[ 9] = ( ( frag_len >> 16 ) & 0xff ); - ssl->out_msg[10] = ( ( frag_len >> 8 ) & 0xff ); - ssl->out_msg[11] = ( ( frag_len ) & 0xff ); + ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff ); + ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff ); + ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff ); MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); - /* Copy the handshake message content and set records fields */ - memcpy( ssl->out_msg + 12, p, frag_len ); - ssl->out_msglen = frag_len + 12; + /* Copy the handshame message content and set records fields */ + memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); + ssl->out_msglen = cur_hs_frag_len + 12; ssl->out_msgtype = cur->type; /* Update position inside current message */ - ssl->handshake->cur_msg_p += frag_len; + ssl->handshake->cur_msg_p += cur_hs_frag_len; } /* If done with the current message move to the next one if any */ @@ -2948,13 +3056,16 @@ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) } /* Actually send the message out */ - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } } + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + /* Update state and set timer */ if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; @@ -3082,6 +3193,23 @@ int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) } #endif + /* Double-check that we did not exceed the bounds + * of the outgoing record buffer. + * This should never fail as the various message + * writing functions must obey the bounds of the + * outgoing record buffer, but better be safe. + * + * Note: We deliberately do not check for the MTU or MFL here. + */ + if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: " + "size %u, maximum %u", + (unsigned) ssl->out_msglen, + (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + /* * Fill handshake headers */ @@ -3154,7 +3282,7 @@ int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) else #endif { - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret ); return( ret ); @@ -3178,10 +3306,11 @@ int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) * - ssl->out_msglen: length of the record content (excl headers) * - ssl->out_msg: record content */ -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) { int ret, done = 0; size_t len = ssl->out_msglen; + uint8_t flush = force_flush; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); @@ -3217,10 +3346,14 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ if( !done ) { + unsigned i; + size_t protected_record_size; + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, ssl->conf->transport, ssl->out_hdr + 1 ); + memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 ); ssl->out_len[0] = (unsigned char)( len >> 8 ); ssl->out_len[1] = (unsigned char)( len ); @@ -3237,18 +3370,74 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) ssl->out_len[1] = (unsigned char)( len ); } - ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen; + protected_record_size = len + mbedtls_ssl_hdr_len( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* In case of DTLS, double-check that we don't exceed + * the remaining space in the datagram. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + + if( protected_record_size > (size_t) ret ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], - ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) ); + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], len ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", - ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen ); + ssl->out_hdr, protected_record_size ); + + ssl->out_left += protected_record_size; + ssl->out_hdr += protected_record_size; + ssl_update_out_pointers( ssl, ssl->transform_out ); + + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } } - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + flush == SSL_DONT_FORCE_FLUSH ) + { + size_t remaining; + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram", + ret ); + return( ret ); + } + + remaining = (size_t) ret; + if( remaining == 0 ) + flush = SSL_FORCE_FLUSH; + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ( flush == SSL_FORCE_FLUSH ) && + ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); return( ret ); @@ -4530,7 +4719,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, ssl->out_msg[0] = level; ssl->out_msg[1] = message; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); @@ -5179,16 +5368,7 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_PROTO_DTLS */ memset( ssl->in_ctr, 0, 8 ); - /* - * Set the in_msg pointer to the correct location based on IV length - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen - - ssl->transform_negotiate->fixed_ivlen; - } - else - ssl->in_msg = ssl->in_iv; + ssl_update_in_pointers( ssl, ssl->transform_negotiate ); #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_activate != NULL ) @@ -5639,16 +5819,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); - /* - * Set the out_msg pointer to the correct location based on IV length - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen - - ssl->transform_negotiate->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; + ssl_update_out_pointers( ssl, ssl->transform_negotiate ); ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); @@ -5700,14 +5871,14 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) /* Remember current epoch settings for resending */ ssl->handshake->alt_transform_out = ssl->transform_out; - memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 ); + memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 ); /* Set sequence_number to zero */ - memset( ssl->out_ctr + 2, 0, 6 ); + memset( ssl->cur_out_ctr + 2, 0, 6 ); /* Increment epoch */ for( i = 2; i > 0; i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) break; /* The loop goes to its end iff the counter is wrapping */ @@ -5719,7 +5890,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ - memset( ssl->out_ctr, 0, 8 ); + memset( ssl->cur_out_ctr, 0, 8 ); ssl->transform_out = ssl->transform_negotiate; ssl->session_out = ssl->session_negotiate; @@ -6007,6 +6178,78 @@ static int ssl_cookie_check_dummy( void *ctx, } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ +/* Once ssl->out_hdr as the address of the beginning of the + * next outgoing record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->out_hdr, + * and the caller has to make sure there's space for this. + */ + +static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_ctr = ssl->out_hdr + 3; + ssl->out_len = ssl->out_hdr + 11; + ssl->out_iv = ssl->out_hdr + 13; + } + else +#endif + { + ssl->out_ctr = ssl->out_hdr - 8; + ssl->out_len = ssl->out_hdr + 3; + ssl->out_iv = ssl->out_hdr + 5; + } + + /* Adjust out_msg to make space for explicit IV, if used. */ + if( transform != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; +} + +/* Once ssl->in_hdr as the address of the beginning of the + * next incoming record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->in_hdr, + * and the caller has to make sure there's space for this. + */ + +static void ssl_update_in_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->in_ctr = ssl->in_hdr + 3; + ssl->in_len = ssl->in_hdr + 11; + ssl->in_iv = ssl->in_hdr + 13; + } + else +#endif + { + ssl->in_ctr = ssl->in_hdr - 8; + ssl->in_len = ssl->in_hdr + 3; + ssl->in_iv = ssl->in_hdr + 5; + } + + /* Offset in_msg from in_iv to allow space for explicit IV, if used. */ + if( transform != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->in_msg = ssl->in_iv + transform->ivlen - transform->fixed_ivlen; + } + else + ssl->in_msg = ssl->in_iv; +} + /* * Initialize an SSL context */ @@ -6018,6 +6261,28 @@ void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) /* * Setup an SSL context */ + +static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ) +{ + /* Set the incoming and outgoing record pointers. */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->in_hdr = ssl->in_buf; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ssl->out_hdr = ssl->out_buf + 8; + ssl->in_hdr = ssl->in_buf + 8; + } + + /* Derive other internal pointers. */ + ssl_update_out_pointers( ssl, NULL /* no transform enabled */ ); + ssl_update_in_pointers ( ssl, NULL /* no transform enabled */ ); +} + int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf ) { @@ -6044,36 +6309,7 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ssl->out_hdr = ssl->out_buf; - ssl->out_ctr = ssl->out_buf + 3; - ssl->out_len = ssl->out_buf + 11; - ssl->out_iv = ssl->out_buf + 13; - ssl->out_msg = ssl->out_buf + 13; - - ssl->in_hdr = ssl->in_buf; - ssl->in_ctr = ssl->in_buf + 3; - ssl->in_len = ssl->in_buf + 11; - ssl->in_iv = ssl->in_buf + 13; - ssl->in_msg = ssl->in_buf + 13; - } - else -#endif - { - ssl->out_ctr = ssl->out_buf; - ssl->out_hdr = ssl->out_buf + 8; - ssl->out_len = ssl->out_buf + 11; - ssl->out_iv = ssl->out_buf + 13; - ssl->out_msg = ssl->out_buf + 13; - - ssl->in_ctr = ssl->in_buf; - ssl->in_hdr = ssl->in_buf + 8; - ssl->in_len = ssl->in_buf + 11; - ssl->in_iv = ssl->in_buf + 13; - ssl->in_msg = ssl->in_buf + 13; - } + ssl_reset_in_out_pointers( ssl ); if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) return( ret ); @@ -6092,6 +6328,11 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) { int ret; +#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \ + !defined(MBEDTLS_SSL_SRV_C) + ((void) partial); +#endif + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; /* Cancel any possibly running timer */ @@ -6108,12 +6349,10 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; ssl->in_offt = NULL; + ssl_reset_in_out_pointers( ssl ); - ssl->in_msg = ssl->in_buf + 13; ssl->in_msgtype = 0; ssl->in_msglen = 0; - if( partial == 0 ) - ssl->in_left = 0; #if defined(MBEDTLS_SSL_PROTO_DTLS) ssl->next_record_offset = 0; ssl->in_epoch = 0; @@ -6127,7 +6366,6 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->keep_current_message = 0; - ssl->out_msg = ssl->out_buf + 13; ssl->out_msgtype = 0; ssl->out_msglen = 0; ssl->out_left = 0; @@ -6136,6 +6374,8 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->split_done = 0; #endif + memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) ); + ssl->transform_in = NULL; ssl->transform_out = NULL; @@ -6143,8 +6383,14 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->session_out = NULL; memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) if( partial == 0 ) +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + { + ssl->in_left = 0; memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN ); + } #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_reset != NULL ) @@ -6177,7 +6423,9 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) if( partial == 0 ) +#endif { mbedtls_free( ssl->cli_id ); ssl->cli_id = NULL; @@ -6228,7 +6476,15 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ) + +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ) +{ + ssl->disable_datagram_packing = !allow_packing; +} + +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, + uint32_t min, uint32_t max ) { conf->hs_timeout_min = min; conf->hs_timeout_max = max; @@ -7025,7 +7281,6 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_ZLIB_SUPPORT) if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } #endif switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) @@ -7095,6 +7350,20 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ) +{ + if( ssl->handshake == NULL || ssl->handshake->mtu == 0 ) + return( ssl->mtu ); + + if( ssl->mtu == 0 ) + return( ssl->handshake->mtu ); + + return( ssl->mtu < ssl->handshake->mtu ? + ssl->mtu : ssl->handshake->mtu ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) { size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; @@ -7112,9 +7381,9 @@ int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->mtu != 0 ) + if( ssl_get_current_mtu( ssl ) != 0 ) { - const size_t mtu = ssl->mtu; + const size_t mtu = ssl_get_current_mtu( ssl ); const int ret = mbedtls_ssl_get_record_expansion( ssl ); const size_t overhead = (size_t) ret; @@ -7130,6 +7399,11 @@ int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) if( max_len > mtu - overhead ) max_len = mtu - overhead; } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); #endif return( (int) max_len ); @@ -7354,7 +7628,7 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, ssl->conf->renego_period + ep_len, 8 - ep_len ); - out_ctr_cmp = memcmp( ssl->out_ctr + ep_len, + out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len, ssl->conf->renego_period + ep_len, 8 - ep_len ); if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) @@ -7735,7 +8009,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; memcpy( ssl->out_msg, buf, len ); - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index e4a7412a9..efd2b3043 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -107,6 +107,7 @@ int main( void ) #define DFL_HS_TO_MIN 0 #define DFL_HS_TO_MAX 0 #define DFL_DTLS_MTU -1 +#define DFL_DGRAM_PACKING 1 #define DFL_FALLBACK -1 #define DFL_EXTENDED_MS -1 #define DFL_ETM -1 @@ -200,7 +201,10 @@ int main( void ) " dtls=%%d default: 0 (TLS)\n" \ " hs_timeout=%%d-%%d default: (library default: 1000-60000)\n" \ " range of DTLS handshake timeouts in millisecs\n" \ - " mtu=%%d default: (library default: unlimited)\n" + " mtu=%%d default: (library default: unlimited)\n" \ + " dgram_packing=%%d default: 1 (allowed)\n" \ + " allow or forbid packing of multiple\n" \ + " records within a single datgram.\n" #else #define USAGE_DTLS "" #endif @@ -349,6 +353,7 @@ struct options uint32_t hs_to_max; /* Max value of DTLS handshake timer */ int dtls_mtu; /* UDP Maximum tranport unit for DTLS */ int fallback; /* is this a fallback connection? */ + int dgram_packing; /* allow/forbid datagram packing */ int extended_ms; /* negotiate extended master secret? */ int etm; /* negotiate encrypt then mac? */ } opt; @@ -624,6 +629,7 @@ int main( int argc, char *argv[] ) opt.fallback = DFL_FALLBACK; opt.extended_ms = DFL_EXTENDED_MS; opt.etm = DFL_ETM; + opt.dgram_packing = DFL_DGRAM_PACKING; for( i = 1; i < argc; i++ ) { @@ -937,6 +943,15 @@ int main( int argc, char *argv[] ) if( opt.dtls_mtu < 0 ) goto usage; } + else if( strcmp( p, "dgram_packing" ) == 0 ) + { + opt.dgram_packing = atoi( q ); + if( opt.dgram_packing != 0 && + opt.dgram_packing != 1 ) + { + goto usage; + } + } else if( strcmp( p, "recsplit" ) == 0 ) { opt.recsplit = atoi( q ); @@ -1337,7 +1352,10 @@ int main( int argc, char *argv[] ) if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX ) mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min, opt.hs_to_max ); -#endif + + if( opt.dgram_packing != DFL_DGRAM_PACKING ) + mbedtls_ssl_set_datagram_packing( &ssl, opt.dgram_packing ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) if( ( ret = mbedtls_ssl_conf_max_frag_len( &conf, opt.mfl_code ) ) != 0 ) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 71ec85bd3..070c00555 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -152,6 +152,7 @@ int main( void ) #define DFL_HS_TO_MAX 0 #define DFL_DTLS_MTU -1 #define DFL_BADMAC_LIMIT -1 +#define DFL_DGRAM_PACKING 1 #define DFL_EXTENDED_MS -1 #define DFL_ETM -1 @@ -299,7 +300,10 @@ int main( void ) " dtls=%%d default: 0 (TLS)\n" \ " hs_timeout=%%d-%%d default: (library default: 1000-60000)\n" \ " range of DTLS handshake timeouts in millisecs\n" \ - " mtu=%%d default: (library default: unlimited)\n" + " mtu=%%d default: (library default: unlimited)\n" \ + " dgram_packing=%%d default: 1 (allowed)\n" \ + " allow or forbid packing of multiple\n" \ + " records within a single datgram.\n" #else #define USAGE_DTLS "" #endif @@ -473,6 +477,7 @@ struct options uint32_t hs_to_min; /* Initial value of DTLS handshake timer */ uint32_t hs_to_max; /* Max value of DTLS handshake timer */ int dtls_mtu; /* UDP Maximum tranport unit for DTLS */ + int dgram_packing; /* allow/forbid datagram packing */ int badmac_limit; /* Limit of records with bad MAC */ } opt; @@ -1342,6 +1347,7 @@ int main( int argc, char *argv[] ) opt.hs_to_min = DFL_HS_TO_MIN; opt.hs_to_max = DFL_HS_TO_MAX; opt.dtls_mtu = DFL_DTLS_MTU; + opt.dgram_packing = DFL_DGRAM_PACKING; opt.badmac_limit = DFL_BADMAC_LIMIT; opt.extended_ms = DFL_EXTENDED_MS; opt.etm = DFL_ETM; @@ -1694,6 +1700,15 @@ int main( int argc, char *argv[] ) if( opt.dtls_mtu < 0 ) goto usage; } + else if( strcmp( p, "dgram_packing" ) == 0 ) + { + opt.dgram_packing = atoi( q ); + if( opt.dgram_packing != 0 && + opt.dgram_packing != 1 ) + { + goto usage; + } + } else if( strcmp( p, "sni" ) == 0 ) { opt.sni = q; @@ -2165,6 +2180,9 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_SSL_PROTO_DTLS) if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX ) mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min, opt.hs_to_max ); + + if( opt.dgram_packing != DFL_DGRAM_PACKING ) + mbedtls_ssl_set_datagram_packing( &ssl, opt.dgram_packing ); #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index c3ec692d3..daeebc4aa 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -931,6 +931,35 @@ run_test "SHA-256 allowed by default in client certificate" \ "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha256.crt" \ 0 +# Tests for datagram packing +run_test "DTLS: multiple records in same datagram, client and server" \ + "$P_SRV dtls=1 dgram_packing=1 debug_level=2" \ + "$P_CLI dtls=1 dgram_packing=1 debug_level=2" \ + 0 \ + -c "next record in same datagram" \ + -s "next record in same datagram" + +run_test "DTLS: multiple records in same datagram, client only" \ + "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \ + "$P_CLI dtls=1 dgram_packing=1 debug_level=2" \ + 0 \ + -s "next record in same datagram" \ + -C "next record in same datagram" + +run_test "DTLS: multiple records in same datagram, server only" \ + "$P_SRV dtls=1 dgram_packing=1 debug_level=2" \ + "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \ + 0 \ + -S "next record in same datagram" \ + -c "next record in same datagram" + +run_test "DTLS: multiple records in same datagram, neither client nor server" \ + "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \ + "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \ + 0 \ + -S "next record in same datagram" \ + -C "next record in same datagram" + # Tests for Truncated HMAC extension run_test "Truncated HMAC: client default, server default" \ @@ -4979,11 +5008,11 @@ run_test "DTLS fragmenting: none (for reference)" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ crt_file=data_files/server7_int-ca.crt \ key_file=data_files/server7.key \ - max_frag_len=2048" \ + max_frag_len=4096" \ "$P_CLI dtls=1 debug_level=2 \ crt_file=data_files/server8_int-ca2.crt \ key_file=data_files/server8.key \ - max_frag_len=2048" \ + max_frag_len=4096" \ 0 \ -S "found fragmented DTLS handshake message" \ -C "found fragmented DTLS handshake message" \ @@ -5007,6 +5036,10 @@ run_test "DTLS fragmenting: server only (max_frag_len)" \ -c "found fragmented DTLS handshake message" \ -C "error" +# With the MFL extension, the server has no way of forcing +# the client to not exceed a certain MTU; hence, the following +# test can't be replicated with an MTU proxy such as the one +# `client-initiated, server only (max_frag_len)` below. requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_RSA_C requires_config_enabled MBEDTLS_ECDSA_C @@ -5019,7 +5052,7 @@ run_test "DTLS fragmenting: server only (more) (max_frag_len)" \ "$P_CLI dtls=1 debug_level=2 \ crt_file=data_files/server8_int-ca2.crt \ key_file=data_files/server8.key \ - max_frag_len=2048" \ + max_frag_len=4096" \ 0 \ -S "found fragmented DTLS handshake message" \ -c "found fragmented DTLS handshake message" \ @@ -5043,6 +5076,32 @@ run_test "DTLS fragmenting: client-initiated, server only (max_frag_len)" \ -c "found fragmented DTLS handshake message" \ -C "error" +# While not required by the standard defining the MFL extension +# (according to which it only applies to records, not to datagrams), +# Mbed TLS will never send datagrams larger than MFL + { Max record expansion }, +# as otherwise there wouldn't be any means to communicate MTU restrictions +# to the peer. +# The next test checks that no datagrams significantly larger than the +# negotiated MFL are sent. +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_config_enabled MBEDTLS_RSA_C +requires_config_enabled MBEDTLS_ECDSA_C +requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +run_test "DTLS fragmenting: client-initiated, server only (max_frag_len), proxy MTU" \ + -p "$P_PXY mtu=560" \ + "$P_SRV dtls=1 debug_level=2 auth_mode=none \ + crt_file=data_files/server7_int-ca.crt \ + key_file=data_files/server7.key \ + max_frag_len=2048" \ + "$P_CLI dtls=1 debug_level=2 \ + crt_file=data_files/server8_int-ca2.crt \ + key_file=data_files/server8.key \ + max_frag_len=512" \ + 0 \ + -S "found fragmented DTLS handshake message" \ + -c "found fragmented DTLS handshake message" \ + -C "error" + requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_RSA_C requires_config_enabled MBEDTLS_ECDSA_C @@ -5061,6 +5120,32 @@ run_test "DTLS fragmenting: client-initiated, both (max_frag_len)" \ -c "found fragmented DTLS handshake message" \ -C "error" +# While not required by the standard defining the MFL extension +# (according to which it only applies to records, not to datagrams), +# Mbed TLS will never send datagrams larger than MFL + { Max record expansion }, +# as otherwise there wouldn't be any means to communicate MTU restrictions +# to the peer. +# The next test checks that no datagrams significantly larger than the +# negotiated MFL are sent. +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_config_enabled MBEDTLS_RSA_C +requires_config_enabled MBEDTLS_ECDSA_C +requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +run_test "DTLS fragmenting: client-initiated, both (max_frag_len), proxy MTU" \ + -p "$P_PXY mtu=560" \ + "$P_SRV dtls=1 debug_level=2 auth_mode=required \ + crt_file=data_files/server7_int-ca.crt \ + key_file=data_files/server7.key \ + max_frag_len=2048" \ + "$P_CLI dtls=1 debug_level=2 \ + crt_file=data_files/server8_int-ca2.crt \ + key_file=data_files/server8.key \ + max_frag_len=512" \ + 0 \ + -s "found fragmented DTLS handshake message" \ + -c "found fragmented DTLS handshake message" \ + -C "error" + requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_RSA_C requires_config_enabled MBEDTLS_ECDSA_C @@ -5068,11 +5153,11 @@ run_test "DTLS fragmenting: none (for reference) (MTU)" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ crt_file=data_files/server7_int-ca.crt \ key_file=data_files/server7.key \ - mtu=2048" \ + mtu=4096" \ "$P_CLI dtls=1 debug_level=2 \ crt_file=data_files/server8_int-ca2.crt \ key_file=data_files/server8.key \ - mtu=2048" \ + mtu=4096" \ 0 \ -S "found fragmented DTLS handshake message" \ -C "found fragmented DTLS handshake message" \ @@ -5085,7 +5170,7 @@ run_test "DTLS fragmenting: client (MTU)" \ "$P_SRV dtls=1 debug_level=2 auth_mode=required \ crt_file=data_files/server7_int-ca.crt \ key_file=data_files/server7.key \ - mtu=2048" \ + mtu=4096" \ "$P_CLI dtls=1 debug_level=2 \ crt_file=data_files/server8_int-ca2.crt \ key_file=data_files/server8.key \ @@ -5130,6 +5215,25 @@ run_test "DTLS fragmenting: both (MTU)" \ -c "found fragmented DTLS handshake message" \ -C "error" +# Test for automatic MTU reduction on repeated resend +requires_config_enabled MBEDTLS_SSL_PROTO_DTLS +requires_config_enabled MBEDTLS_RSA_C +requires_config_enabled MBEDTLS_ECDSA_C +run_test "DTLS fragmenting: proxy MTU: auto-reduction" \ + -p "$P_PXY mtu=508" \ + "$P_SRV dtls=1 debug_level=2 auth_mode=required \ + crt_file=data_files/server7_int-ca.crt \ + key_file=data_files/server7.key\ + hs_timeout=100-400" \ + "$P_CLI dtls=1 debug_level=2 \ + crt_file=data_files/server8_int-ca2.crt \ + key_file=data_files/server8.key \ + hs_timeout=100-400" \ + 0 \ + -s "found fragmented DTLS handshake message" \ + -c "found fragmented DTLS handshake message" \ + -C "error" + # the proxy shouldn't drop or mess up anything, so we shouldn't need to resend # OTOH the client might resend if the server is to slow to reset after sending # a HelloVerifyRequest, so only check for no retransmission server-side @@ -5179,6 +5283,8 @@ run_test "DTLS fragmenting: proxy MTU, simple handshake, nbio" \ # Since we don't support reading fragmented ClientHello yet, # up the MTU to 1450 (larger than ClientHello with session ticket, # but still smaller than client's Certificate to ensure fragmentation). +# A resend on the client-side might happen if the server is +# slow to reset, therefore omitting '-C "resend"' below. # reco_delay avoids races where the client reconnects before the server has # resumed listening, which would result in a spurious resend. not_with_valgrind # spurious resend due to timeout @@ -5201,6 +5307,8 @@ run_test "DTLS fragmenting: proxy MTU, resumed handshake" \ -c "found fragmented DTLS handshake message" \ -C "error" +# A resend on the client-side might happen if the server is +# slow to reset, therefore omitting '-C "resend"' below. not_with_valgrind # spurious resend due to timeout requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_RSA_C @@ -5228,6 +5336,8 @@ run_test "DTLS fragmenting: proxy MTU, ChachaPoly renego" \ -c "found fragmented DTLS handshake message" \ -C "error" +# A resend on the client-side might happen if the server is +# slow to reset, therefore omitting '-C "resend"' below. not_with_valgrind # spurious resend due to timeout requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_RSA_C @@ -5256,6 +5366,8 @@ run_test "DTLS fragmenting: proxy MTU, AES-GCM renego" \ -c "found fragmented DTLS handshake message" \ -C "error" +# A resend on the client-side might happen if the server is +# slow to reset, therefore omitting '-C "resend"' below. not_with_valgrind # spurious resend due to timeout requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_RSA_C @@ -5284,6 +5396,8 @@ run_test "DTLS fragmenting: proxy MTU, AES-CCM renego" \ -c "found fragmented DTLS handshake message" \ -C "error" +# A resend on the client-side might happen if the server is +# slow to reset, therefore omitting '-C "resend"' below. not_with_valgrind # spurious resend due to timeout requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_RSA_C @@ -5313,6 +5427,8 @@ run_test "DTLS fragmenting: proxy MTU, AES-CBC EtM renego" \ -c "found fragmented DTLS handshake message" \ -C "error" +# A resend on the client-side might happen if the server is +# slow to reset, therefore omitting '-C "resend"' below. not_with_valgrind # spurious resend due to timeout requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_RSA_C @@ -5347,11 +5463,11 @@ requires_config_enabled MBEDTLS_ECDSA_C client_needs_more_time 2 run_test "DTLS fragmenting: proxy MTU + 3d" \ -p "$P_PXY mtu=512 drop=8 delay=8 duplicate=8" \ - "$P_SRV dtls=1 debug_level=2 auth_mode=required \ + "$P_SRV dgram_packing=0 dtls=1 debug_level=2 auth_mode=required \ crt_file=data_files/server7_int-ca.crt \ key_file=data_files/server7.key \ hs_timeout=250-10000 mtu=512" \ - "$P_CLI dtls=1 debug_level=2 \ + "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \ crt_file=data_files/server8_int-ca2.crt \ key_file=data_files/server8.key \ hs_timeout=250-10000 mtu=512" \ @@ -5383,6 +5499,7 @@ run_test "DTLS fragmenting: proxy MTU + 3d, nbio" \ # # here and below we just want to test that the we fragment in a way that # pleases other implementations, so we don't need the peer to fragment +requires_gnutls requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_RSA_C requires_config_enabled MBEDTLS_ECDSA_C @@ -5398,6 +5515,7 @@ run_test "DTLS fragmenting: gnutls server, DTLS 1.2" \ -c "fragmenting handshake message" \ -C "error" +requires_gnutls requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_RSA_C requires_config_enabled MBEDTLS_ECDSA_C @@ -5508,7 +5626,7 @@ client_needs_more_time 4 run_test "DTLS fragmenting: 3d, gnutls server, DTLS 1.2" \ -p "$P_PXY drop=8 delay=8 duplicate=8" \ "$G_NEXT_SRV -u" \ - "$P_CLI dtls=1 debug_level=2 \ + "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \ crt_file=data_files/server8_int-ca2.crt \ key_file=data_files/server8.key \ hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \ @@ -5525,7 +5643,7 @@ client_needs_more_time 4 run_test "DTLS fragmenting: 3d, gnutls server, DTLS 1.0" \ -p "$P_PXY drop=8 delay=8 duplicate=8" \ "$G_NEXT_SRV -u" \ - "$P_CLI dtls=1 debug_level=2 \ + "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \ crt_file=data_files/server8_int-ca2.crt \ key_file=data_files/server8.key \ hs_timeout=250-60000 mtu=512 force_version=dtls1" \ @@ -5604,7 +5722,7 @@ client_needs_more_time 4 run_test "DTLS fragmenting: 3d, openssl server, DTLS 1.0" \ -p "$P_PXY drop=8 delay=8 duplicate=8" \ "$O_LEGACY_SRV -dtls1 -verify 10" \ - "$P_CLI dtls=1 debug_level=2 \ + "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \ crt_file=data_files/server8_int-ca2.crt \ key_file=data_files/server8.key \ hs_timeout=250-60000 mtu=512 force_version=dtls1" \ @@ -5638,7 +5756,7 @@ requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1 client_needs_more_time 4 run_test "DTLS fragmenting: 3d, openssl client, DTLS 1.0" \ -p "$P_PXY drop=8 delay=8 duplicate=8" \ - "$P_SRV dtls=1 debug_level=2 \ + "$P_SRV dgram_packing=0 dtls=1 debug_level=2 \ crt_file=data_files/server7_int-ca.crt \ key_file=data_files/server7.key \ hs_timeout=250-60000 mtu=512 force_version=dtls1" \ @@ -5667,8 +5785,8 @@ run_test "DTLS proxy: reference" \ not_with_valgrind # spurious resend due to timeout run_test "DTLS proxy: duplicate every packet" \ -p "$P_PXY duplicate=1" \ - "$P_SRV dtls=1 debug_level=2" \ - "$P_CLI dtls=1 debug_level=2" \ + "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \ + "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \ 0 \ -c "replayed record" \ -s "replayed record" \ @@ -5680,8 +5798,8 @@ run_test "DTLS proxy: duplicate every packet" \ run_test "DTLS proxy: duplicate every packet, server anti-replay off" \ -p "$P_PXY duplicate=1" \ - "$P_SRV dtls=1 debug_level=2 anti_replay=0" \ - "$P_CLI dtls=1 debug_level=2" \ + "$P_SRV dtls=1 dgram_packing=0 debug_level=2 anti_replay=0" \ + "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \ 0 \ -c "replayed record" \ -S "replayed record" \ @@ -5694,24 +5812,24 @@ run_test "DTLS proxy: duplicate every packet, server anti-replay off" \ run_test "DTLS proxy: multiple records in same datagram" \ -p "$P_PXY pack=50" \ - "$P_SRV dtls=1 debug_level=2" \ - "$P_CLI dtls=1 debug_level=2" \ + "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \ + "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \ 0 \ -c "next record in same datagram" \ -s "next record in same datagram" run_test "DTLS proxy: multiple records in same datagram, duplicate every packet" \ -p "$P_PXY pack=50 duplicate=1" \ - "$P_SRV dtls=1 debug_level=2" \ - "$P_CLI dtls=1 debug_level=2" \ + "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \ + "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \ 0 \ -c "next record in same datagram" \ -s "next record in same datagram" run_test "DTLS proxy: inject invalid AD record, default badmac_limit" \ -p "$P_PXY bad_ad=1" \ - "$P_SRV dtls=1 debug_level=1" \ - "$P_CLI dtls=1 debug_level=1 read_timeout=100" \ + "$P_SRV dtls=1 dgram_packing=0 debug_level=1" \ + "$P_CLI dtls=1 dgram_packing=0 debug_level=1 read_timeout=100" \ 0 \ -c "discarding invalid record (mac)" \ -s "discarding invalid record (mac)" \ @@ -5722,8 +5840,8 @@ run_test "DTLS proxy: inject invalid AD record, default badmac_limit" \ run_test "DTLS proxy: inject invalid AD record, badmac_limit 1" \ -p "$P_PXY bad_ad=1" \ - "$P_SRV dtls=1 debug_level=1 badmac_limit=1" \ - "$P_CLI dtls=1 debug_level=1 read_timeout=100" \ + "$P_SRV dtls=1 dgram_packing=0 debug_level=1 badmac_limit=1" \ + "$P_CLI dtls=1 dgram_packing=0 debug_level=1 read_timeout=100" \ 1 \ -C "discarding invalid record (mac)" \ -S "discarding invalid record (mac)" \ @@ -5734,8 +5852,8 @@ run_test "DTLS proxy: inject invalid AD record, badmac_limit 1" \ run_test "DTLS proxy: inject invalid AD record, badmac_limit 2" \ -p "$P_PXY bad_ad=1" \ - "$P_SRV dtls=1 debug_level=1 badmac_limit=2" \ - "$P_CLI dtls=1 debug_level=1 read_timeout=100" \ + "$P_SRV dtls=1 dgram_packing=0 debug_level=1 badmac_limit=2" \ + "$P_CLI dtls=1 dgram_packing=0 debug_level=1 read_timeout=100" \ 0 \ -c "discarding invalid record (mac)" \ -s "discarding invalid record (mac)" \ @@ -5746,8 +5864,8 @@ run_test "DTLS proxy: inject invalid AD record, badmac_limit 2" \ run_test "DTLS proxy: inject invalid AD record, badmac_limit 2, exchanges 2"\ -p "$P_PXY bad_ad=1" \ - "$P_SRV dtls=1 debug_level=1 badmac_limit=2 exchanges=2" \ - "$P_CLI dtls=1 debug_level=1 read_timeout=100 exchanges=2" \ + "$P_SRV dtls=1 dgram_packing=0 debug_level=1 badmac_limit=2 exchanges=2" \ + "$P_CLI dtls=1 dgram_packing=0 debug_level=1 read_timeout=100 exchanges=2" \ 1 \ -c "discarding invalid record (mac)" \ -s "discarding invalid record (mac)" \ @@ -5758,8 +5876,8 @@ run_test "DTLS proxy: inject invalid AD record, badmac_limit 2, exchanges 2"\ run_test "DTLS proxy: delay ChangeCipherSpec" \ -p "$P_PXY delay_ccs=1" \ - "$P_SRV dtls=1 debug_level=1" \ - "$P_CLI dtls=1 debug_level=1" \ + "$P_SRV dtls=1 debug_level=1 dgram_packing=0" \ + "$P_CLI dtls=1 debug_level=1 dgram_packing=0" \ 0 \ -c "record from another epoch" \ -s "record from another epoch" \ @@ -5771,9 +5889,9 @@ run_test "DTLS proxy: delay ChangeCipherSpec" \ client_needs_more_time 2 run_test "DTLS proxy: 3d (drop, delay, duplicate), \"short\" PSK handshake" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 auth_mode=none \ psk=abc123" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 psk=abc123 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ -s "Extra-header:" \ @@ -5782,8 +5900,8 @@ run_test "DTLS proxy: 3d (drop, delay, duplicate), \"short\" PSK handshake" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, \"short\" RSA handshake" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 auth_mode=none" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 \ force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \ 0 \ -s "Extra-header:" \ @@ -5792,8 +5910,8 @@ run_test "DTLS proxy: 3d, \"short\" RSA handshake" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, \"short\" (no ticket, no cli_auth) FS handshake" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 auth_mode=none" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0" \ 0 \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" @@ -5801,8 +5919,8 @@ run_test "DTLS proxy: 3d, \"short\" (no ticket, no cli_auth) FS handshake" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, FS, client auth" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=required" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 auth_mode=required" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0" \ 0 \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" @@ -5810,8 +5928,8 @@ run_test "DTLS proxy: 3d, FS, client auth" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, FS, ticket" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=1 auth_mode=none" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=1" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=1 auth_mode=none" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=1" \ 0 \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" @@ -5819,8 +5937,8 @@ run_test "DTLS proxy: 3d, FS, ticket" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, max handshake (FS, ticket + client auth)" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=1 auth_mode=required" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=1" \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=1 auth_mode=required" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=1" \ 0 \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" @@ -5828,9 +5946,9 @@ run_test "DTLS proxy: 3d, max handshake (FS, ticket + client auth)" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, max handshake, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 nbio=2 tickets=1 \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 nbio=2 tickets=1 \ auth_mode=required" \ - "$P_CLI dtls=1 hs_timeout=250-10000 nbio=2 tickets=1" \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 nbio=2 tickets=1" \ 0 \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" @@ -5838,9 +5956,9 @@ run_test "DTLS proxy: 3d, max handshake, nbio" \ client_needs_more_time 4 run_test "DTLS proxy: 3d, min handshake, resumption" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 auth_mode=none \ psk=abc123 debug_level=3" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 psk=abc123 \ debug_level=3 reconnect=1 read_timeout=1000 max_resend=10 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ @@ -5852,9 +5970,9 @@ run_test "DTLS proxy: 3d, min handshake, resumption" \ client_needs_more_time 4 run_test "DTLS proxy: 3d, min handshake, resumption, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 auth_mode=none \ psk=abc123 debug_level=3 nbio=2" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 psk=abc123 \ debug_level=3 reconnect=1 read_timeout=1000 max_resend=10 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8 nbio=2" \ 0 \ @@ -5867,9 +5985,9 @@ client_needs_more_time 4 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: 3d, min handshake, client-initiated renego" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 auth_mode=none \ psk=abc123 renegotiation=1 debug_level=2" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 psk=abc123 \ renegotiate=1 debug_level=2 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ @@ -5882,9 +6000,9 @@ client_needs_more_time 4 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: 3d, min handshake, client-initiated renego, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 auth_mode=none \ psk=abc123 renegotiation=1 debug_level=2" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 psk=abc123 \ renegotiate=1 debug_level=2 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ @@ -5897,10 +6015,10 @@ client_needs_more_time 4 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: 3d, min handshake, server-initiated renego" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 auth_mode=none \ psk=abc123 renegotiate=1 renegotiation=1 exchanges=4 \ debug_level=2" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 psk=abc123 \ renegotiation=1 exchanges=4 debug_level=2 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ @@ -5913,10 +6031,10 @@ client_needs_more_time 4 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: 3d, min handshake, server-initiated renego, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 auth_mode=none \ psk=abc123 renegotiate=1 renegotiation=1 exchanges=4 \ debug_level=2 nbio=2" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 dgram_packing=0 hs_timeout=250-10000 tickets=0 psk=abc123 \ renegotiation=1 exchanges=4 debug_level=2 nbio=2 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ @@ -5930,7 +6048,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, openssl server" \ -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \ "$O_SRV -dtls1 -mtu 2048" \ - "$P_CLI dtls=1 hs_timeout=250-60000 tickets=0" \ + "$P_CLI dgram_packing=0 dtls=1 hs_timeout=250-60000 tickets=0" \ 0 \ -c "HTTP/1.0 200 OK" @@ -5939,7 +6057,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, openssl server, fragmentation" \ -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \ "$O_SRV -dtls1 -mtu 768" \ - "$P_CLI dtls=1 hs_timeout=250-60000 tickets=0" \ + "$P_CLI dgram_packing=0 dtls=1 hs_timeout=250-60000 tickets=0" \ 0 \ -c "HTTP/1.0 200 OK" @@ -5948,7 +6066,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, openssl server, fragmentation, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \ "$O_SRV -dtls1 -mtu 768" \ - "$P_CLI dtls=1 hs_timeout=250-60000 nbio=2 tickets=0" \ + "$P_CLI dgram_packing=0 dtls=1 hs_timeout=250-60000 nbio=2 tickets=0" \ 0 \ -c "HTTP/1.0 200 OK" @@ -5958,7 +6076,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, gnutls server" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ "$G_SRV -u --mtu 2048 -a" \ - "$P_CLI dtls=1 hs_timeout=250-60000" \ + "$P_CLI dgram_packing=0 dtls=1 hs_timeout=250-60000" \ 0 \ -s "Extra-header:" \ -c "Extra-header:" @@ -5969,7 +6087,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, gnutls server, fragmentation" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ "$G_SRV -u --mtu 512" \ - "$P_CLI dtls=1 hs_timeout=250-60000" \ + "$P_CLI dgram_packing=0 dtls=1 hs_timeout=250-60000" \ 0 \ -s "Extra-header:" \ -c "Extra-header:" @@ -5980,7 +6098,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, gnutls server, fragmentation, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ "$G_SRV -u --mtu 512" \ - "$P_CLI dtls=1 hs_timeout=250-60000 nbio=2" \ + "$P_CLI dgram_packing=0 dtls=1 hs_timeout=250-60000 nbio=2" \ 0 \ -s "Extra-header:" \ -c "Extra-header:"