Merge remote-tracking branch 'public/pr/1988' into development

This commit is contained in:
Simon Butcher 2018-08-30 00:57:28 +01:00
commit 552754a6ee
8 changed files with 180 additions and 130 deletions

View File

@ -12,7 +12,7 @@ Features
last paragraph). last paragraph).
* Add support for packing multiple records within a single datagram, * Add support for packing multiple records within a single datagram,
enabled by default. enabled by default.
* Add support for buffering out-of-order handshake messages. * Add support for buffering out-of-order handshake messages in DTLS.
The maximum amount of RAM used for this can be controlled by the The maximum amount of RAM used for this can be controlled by the
compile-time constant MBEDTLS_SSL_DTLS_MAX_BUFFERING defined compile-time constant MBEDTLS_SSL_DTLS_MAX_BUFFERING defined
in mbedtls/config.h. in mbedtls/config.h.

View File

@ -3015,6 +3015,15 @@
* Maximum number of heap-allocated bytes for the purpose of * Maximum number of heap-allocated bytes for the purpose of
* DTLS handshake message reassembly and future message buffering. * DTLS handshake message reassembly and future message buffering.
* *
* This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN
* to account for a reassembled handshake message of maximum size,
* together with its reassembly bitmap.
*
* A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default)
* should be sufficient for all practical situations as it allows
* to reassembly a large handshake message (such as a certificate)
* while buffering multiple smaller handshake messages.
*
*/ */
//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 //#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768

View File

@ -243,8 +243,12 @@
#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN #define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
#endif #endif
/*
* Maximum number of heap-allocated bytes for the purpose of
* DTLS handshake message reassembly and future message buffering.
*/
#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING) #if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING)
#define MBEDTLS_SSL_DTLS_MAX_BUFFERING ( 2 * MBEDTLS_SSL_IN_CONTENT_LEN ) #define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768
#endif #endif
/* \} name SECTION: Module settings */ /* \} name SECTION: Module settings */
@ -1027,14 +1031,14 @@ struct mbedtls_ssl_context
int renego_records_seen; /*!< Records since renego request, or with DTLS, int renego_records_seen; /*!< Records since renego request, or with DTLS,
number of retransmissions of request if number of retransmissions of request if
renego_max_records is < 0 */ renego_max_records is < 0 */
#endif #endif /* MBEDTLS_SSL_RENEGOTIATION */
int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */
int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
unsigned badmac_seen; /*!< records with a bad MAC received */ unsigned badmac_seen; /*!< records with a bad MAC received */
#endif #endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ mbedtls_ssl_send_t *f_send; /*!< Callback for network send */
mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */
@ -1090,11 +1094,11 @@ struct mbedtls_ssl_context
uint16_t in_epoch; /*!< DTLS epoch for incoming records */ uint16_t in_epoch; /*!< DTLS epoch for incoming records */
size_t next_record_offset; /*!< offset of the next record in datagram size_t next_record_offset; /*!< offset of the next record in datagram
(equal to in_left if none) */ (equal to in_left if none) */
#endif #endif /* MBEDTLS_SSL_PROTO_DTLS */
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
uint64_t in_window_top; /*!< last validated record seq_num */ uint64_t in_window_top; /*!< last validated record seq_num */
uint64_t in_window; /*!< bitmask for replay detection */ uint64_t in_window; /*!< bitmask for replay detection */
#endif #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
size_t in_hslen; /*!< current handshake message length, size_t in_hslen; /*!< current handshake message length,
including the handshake header */ including the handshake header */
@ -1126,14 +1130,14 @@ struct mbedtls_ssl_context
#if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_PROTO_DTLS)
uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */ uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */
#endif #endif /* MBEDTLS_SSL_PROTO_DTLS */
#if defined(MBEDTLS_ZLIB_SUPPORT) #if defined(MBEDTLS_ZLIB_SUPPORT)
unsigned char *compress_buf; /*!< zlib data buffer */ unsigned char *compress_buf; /*!< zlib data buffer */
#endif #endif /* MBEDTLS_ZLIB_SUPPORT */
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
signed char split_done; /*!< current record already splitted? */ signed char split_done; /*!< current record already splitted? */
#endif #endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
/* /*
* PKI layer * PKI layer
@ -1146,11 +1150,11 @@ struct mbedtls_ssl_context
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
char *hostname; /*!< expected peer CN for verification char *hostname; /*!< expected peer CN for verification
(and SNI if available) */ (and SNI if available) */
#endif #endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_ALPN) #if defined(MBEDTLS_SSL_ALPN)
const char *alpn_chosen; /*!< negotiated protocol */ const char *alpn_chosen; /*!< negotiated protocol */
#endif #endif /* MBEDTLS_SSL_ALPN */
/* /*
* Information for DTLS hello verify * Information for DTLS hello verify
@ -1158,7 +1162,7 @@ struct mbedtls_ssl_context
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
unsigned char *cli_id; /*!< transport-level ID of the client */ unsigned char *cli_id; /*!< transport-level ID of the client */
size_t cli_id_len; /*!< length of cli_id */ size_t cli_id_len; /*!< length of cli_id */
#endif #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */
/* /*
* Secure renegotiation * Secure renegotiation
@ -1170,7 +1174,7 @@ struct mbedtls_ssl_context
size_t verify_data_len; /*!< length of verify data stored */ size_t verify_data_len; /*!< length of verify data stored */
char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */
char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */
#endif #endif /* MBEDTLS_SSL_RENEGOTIATION */
}; };
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
@ -1405,8 +1409,9 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl,
* encapsulation and encryption/authentication if any. * encapsulation and encryption/authentication if any.
* *
* \note This can be called at any point during the connection, for * \note This can be called at any point during the connection, for
* example when a PMTU estimate becomes available from other * example when a Path Maximum Transfer Unit (PMTU)
* sources, such as lower (or higher) protocol layers. * estimate becomes available from other sources,
* such as lower (or higher) protocol layers.
* *
* \note This setting only controls the size of the packets we send, * \note This setting only controls the size of the packets we send,
* and does not restrict the size of the datagrams we're * and does not restrict the size of the datagrams we're

View File

@ -1101,7 +1101,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
return( ret ); return( ret );
} }
#endif #endif /* MBEDTLS_SSL_PROTO_DTLS */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
@ -3414,7 +3414,7 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl )
if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
return( ret ); return( ret );
} }
#endif #endif /* MBEDTLS_SSL_PROTO_DTLS */
/* Change state now, so that it is right in mbedtls_ssl_read_record(), used /* Change state now, so that it is right in mbedtls_ssl_read_record(), used
* by DTLS for dropping out-of-sequence ChangeCipherSpec records */ * by DTLS for dropping out-of-sequence ChangeCipherSpec records */

View File

@ -2397,7 +2397,7 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
return( ret ); return( ret );
} }
#endif #endif /* MBEDTLS_SSL_PROTO_DTLS */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) );
@ -3385,7 +3385,7 @@ static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
return( ret ); return( ret );
} }
#endif #endif /* MBEDTLS_SSL_PROTO_DTLS */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
@ -4264,7 +4264,7 @@ int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl )
if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
return( ret ); return( ret );
} }
#endif #endif /* MBEDTLS_SSL_PROTO_DTLS */
switch( ssl->state ) switch( ssl->state )
{ {

View File

@ -55,7 +55,7 @@
#endif #endif
static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl );
static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context *ssl ); static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl );
/* Length of the "epoch" field in the record header */ /* Length of the "epoch" field in the record header */
static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl )
@ -109,6 +109,17 @@ static void ssl_update_in_pointers( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_PROTO_DTLS)
/* Forward declarations for functions related to message buffering. */
static void ssl_buffering_free( mbedtls_ssl_context *ssl );
static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
uint8_t slot );
static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
static int ssl_buffer_message( mbedtls_ssl_context *ssl );
static int ssl_buffer_future_record( mbedtls_ssl_context *ssl );
static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); 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 ) static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
{ {
@ -183,11 +194,6 @@ static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl
return( (int) remaining ); return( (int) remaining );
} }
static void ssl_buffering_free( mbedtls_ssl_context *ssl );
static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
uint8_t slot );
/* /*
* Double the retransmit timeout value, within the allowed range, * Double the retransmit timeout value, within the allowed range,
* returning -1 if the maximum value has already been reached. * returning -1 if the maximum value has already been reached.
@ -3037,7 +3043,7 @@ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
/* Copy the handshame message content and set records fields */ /* Copy the handshake message content and set records fields */
memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); memcpy( ssl->out_msg + 12, p, cur_hs_frag_len );
ssl->out_msglen = cur_hs_frag_len + 12; ssl->out_msglen = cur_hs_frag_len + 12;
ssl->out_msgtype = cur->type; ssl->out_msgtype = cur->type;
@ -3274,7 +3280,7 @@ int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
} }
#endif /* MBEDTLS_SSL_PROTO_DTLS */ #endif /* MBEDTLS_SSL_PROTO_DTLS */
/* Update running hashes of hanshake messages seen */ /* Update running hashes of handshake messages seen */
if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
} }
@ -3403,8 +3409,8 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
"version = [%d:%d], msglen = %d", "version = [%d:%d], msglen = %d",
ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], len ) ); ssl->out_hdr[0], ssl->out_hdr[1],
ssl->out_hdr[2], len ) );
MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
ssl->out_hdr, protected_record_size ); ssl->out_hdr, protected_record_size );
@ -3440,7 +3446,9 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
remaining = (size_t) ret; remaining = (size_t) ret;
if( remaining == 0 ) if( remaining == 0 )
{
flush = SSL_FORCE_FLUSH; flush = SSL_FORCE_FLUSH;
}
else else
{ {
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) );
@ -3473,21 +3481,21 @@ static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
return( 0 ); return( 0 );
} }
static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context *ssl ) static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl )
{ {
return( ( ssl->in_msg[9] << 16 ) | return( ( ssl->in_msg[9] << 16 ) |
( ssl->in_msg[10] << 8 ) | ( ssl->in_msg[10] << 8 ) |
ssl->in_msg[11] ); ssl->in_msg[11] );
} }
static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context *ssl ) static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
{ {
return( ( ssl->in_msg[6] << 16 ) | return( ( ssl->in_msg[6] << 16 ) |
( ssl->in_msg[7] << 8 ) | ( ssl->in_msg[7] << 8 ) |
ssl->in_msg[8] ); ssl->in_msg[8] );
} }
static int ssl_check_hs_header( mbedtls_ssl_context *ssl ) static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
{ {
uint32_t msg_len, frag_off, frag_len; uint32_t msg_len, frag_off, frag_len;
@ -3585,7 +3593,7 @@ static size_t ssl_get_reassembly_buffer_size( size_t msg_len,
#endif /* MBEDTLS_SSL_PROTO_DTLS */ #endif /* MBEDTLS_SSL_PROTO_DTLS */
static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context *ssl ) static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl )
{ {
return( ( ssl->in_msg[1] << 16 ) | return( ( ssl->in_msg[1] << 16 ) |
( ssl->in_msg[2] << 8 ) | ( ssl->in_msg[2] << 8 ) |
@ -3664,7 +3672,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
/* Message reassembly is handled alongside buffering of future /* Message reassembly is handled alongside buffering of future
* messages; the commonality is that both handshake fragments and * messages; the commonality is that both handshake fragments and
* future messages cannot be forwarded immediately to the handshake * future messages cannot be forwarded immediately to the
* handshake logic layer. */ * handshake logic layer. */
if( ssl_hs_is_proper_fragment( ssl ) == 1 ) if( ssl_hs_is_proper_fragment( ssl ) == 1 )
{ {
@ -4285,14 +4293,6 @@ static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
static int ssl_get_next_record( mbedtls_ssl_context *ssl ); static int ssl_get_next_record( mbedtls_ssl_context *ssl );
static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
static int ssl_buffer_message( mbedtls_ssl_context *ssl );
static int ssl_buffer_future_record( mbedtls_ssl_context *ssl );
static int ssl_another_record_in_datagram( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_PROTO_DTLS */
int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
unsigned update_hs_digest ) unsigned update_hs_digest )
{ {
@ -4316,7 +4316,7 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
/* We only check for buffered messages if the /* We only check for buffered messages if the
* current datagram is fully consumed. */ * current datagram is fully consumed. */
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl_another_record_in_datagram( ssl ) == 0 ) ssl_next_record_is_in_datagram( ssl ) == 0 )
{ {
if( ssl_load_buffered_message( ssl ) == 0 ) if( ssl_load_buffered_message( ssl ) == 0 )
have_buffered = 1; have_buffered = 1;
@ -4331,7 +4331,7 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
if( ret != 0 ) if( ret != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret );
return( ret ); return( ret );
} }
} }
@ -4378,7 +4378,7 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
} }
#if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_PROTO_DTLS)
static int ssl_another_record_in_datagram( mbedtls_ssl_context *ssl ) static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
{ {
if( ssl->in_left > ssl->next_record_offset ) if( ssl->in_left > ssl->next_record_offset )
return( 1 ); return( 1 );
@ -4409,7 +4409,7 @@ static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
goto exit; goto exit;
} }
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Inject buffered CCS message" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) );
ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
ssl->in_msglen = 1; ssl->in_msglen = 1;
ssl->in_msg[0] = 1; ssl->in_msg[0] = 1;
@ -4422,6 +4422,7 @@ static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
goto exit; goto exit;
} }
#if defined(MBEDTLS_DEBUG_C)
/* Debug only */ /* Debug only */
{ {
unsigned offset; unsigned offset;
@ -4432,10 +4433,11 @@ static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
{ {
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.", MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.",
hs->in_msg_seq + offset, hs->in_msg_seq + offset,
hs_buf->is_complete ? "fully" : "partitially" ) ); hs_buf->is_complete ? "fully" : "partially" ) );
} }
} }
} }
#endif /* MBEDTLS_DEBUG_C */
/* Check if we have buffered and/or fully reassembled the /* Check if we have buffered and/or fully reassembled the
* next handshake message. */ * next handshake message. */
@ -4481,7 +4483,6 @@ exit:
return( ret ); return( ret );
} }
static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
size_t desired ) size_t desired )
{ {
@ -4501,9 +4502,9 @@ static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
return( 0 ); return( 0 );
} }
/* We don't have enough space to buffer the next expected /* We don't have enough space to buffer the next expected handshake
* handshake message. Remove buffers used for future msgs * message. Remove buffers used for future messages to gain space,
* to gain space, starting with the most distant one. */ * starting with the most distant one. */
for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;
offset >= 0; offset-- ) offset >= 0; offset-- )
{ {
@ -4706,6 +4707,7 @@ static int ssl_buffer_message( mbedtls_ssl_context *ssl )
} }
default: default:
/* We don't buffer other types of messages. */
break; break;
} }
@ -4851,7 +4853,7 @@ static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
/* Only consider loading future records if the /* Only consider loading future records if the
* input buffer is empty. */ * input buffer is empty. */
if( ssl_another_record_in_datagram( ssl ) == 1 ) if( ssl_next_record_is_in_datagram( ssl ) == 1 )
return( 0 ); return( 0 );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) );
@ -7723,7 +7725,7 @@ int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl )
/* /*
* In all other cases, the rest of the message can be dropped. * In all other cases, the rest of the message can be dropped.
* As in ssl_read_record_layer, this needs to be adapted if * As in ssl_get_next_record, this needs to be adapted if
* we implement support for multiple alerts in single records. * we implement support for multiple alerts in single records.
*/ */

View File

@ -249,8 +249,8 @@ static void get_options( int argc, char *argv[] )
if( *delay_cnt == MAX_DELAYED_HS ) if( *delay_cnt == MAX_DELAYED_HS )
{ {
mbedtls_printf( " maximally %d uses of delay_cli argument allowed\n", mbedtls_printf( " too many uses of %s: only %d allowed\n",
MAX_DELAYED_HS ); p, MAX_DELAYED_HS );
exit_usage( p, NULL ); exit_usage( p, NULL );
} }
@ -663,6 +663,7 @@ int handle_message( const char *way,
delay_list = opt.delay_srv; delay_list = opt.delay_srv;
delay_list_len = opt.delay_srv_cnt; delay_list_len = opt.delay_srv_cnt;
} }
/* Check if message type is in the list of messages /* Check if message type is in the list of messages
* that should be delayed */ * that should be delayed */
for( delay_idx = 0; delay_idx < delay_list_len; delay_idx++ ) for( delay_idx = 0; delay_idx < delay_list_len; delay_idx++ )

View File

@ -142,6 +142,14 @@ get_options() {
done done
} }
# Skip next test; use this macro to skip tests which are legitimate
# in theory and expected to be re-introduced at some point, but
# aren't expected to succeed at the moment due to problems outside
# our control (such as bugs in other TLS implementations).
skip_next_test() {
SKIP_NEXT="YES"
}
# skip next test if the flag is not enabled in config.h # skip next test if the flag is not enabled in config.h
requires_config_enabled() { requires_config_enabled() {
if grep "^#define $1" $CONFIG_H > /dev/null; then :; else if grep "^#define $1" $CONFIG_H > /dev/null; then :; else
@ -156,21 +164,22 @@ requires_config_disabled() {
fi fi
} }
requires_config_value_at_least() { get_config_value_or_default() {
NAME="$1" NAME="$1"
DEF_VAL=$( grep ".*#define.*MBEDTLS_SSL_DTLS_MAX_BUFFERING" ../include/mbedtls/config.h | DEF_VAL=$( grep ".*#define.*${NAME}" ../include/mbedtls/config.h |
sed 's/^.*\s\([0-9]*\)$/\1/' ) sed 's/^.*\s\([0-9]*\)$/\1/' )
VAL=$( ../scripts/config.pl get $NAME || echo "$DEF_VAL" ) ../scripts/config.pl get $NAME || echo "$DEF_VAL"
}
requires_config_value_at_least() {
VAL=$( get_config_value_or_default "$1" )
if [ "$VAL" -lt "$2" ]; then if [ "$VAL" -lt "$2" ]; then
SKIP_NEXT="YES" SKIP_NEXT="YES"
fi fi
} }
requires_config_value_at_most() { requires_config_value_at_most() {
NAME="$1" VAL=$( get_config_value_or_default "$1" )
DEF_VAL=$( grep ".*#define.*MBEDTLS_SSL_DTLS_MAX_BUFFERING" ../include/mbedtls/config.h |
sed 's/^.*\s\([0-9]*\)$/\1/' )
VAL=$( ../scripts/config.pl get $NAME || echo "$DEF_VAL" )
if [ "$VAL" -gt "$2" ]; then if [ "$VAL" -gt "$2" ]; then
SKIP_NEXT="YES" SKIP_NEXT="YES"
fi fi
@ -5317,9 +5326,8 @@ run_test "DTLS fragmenting: proxy MTU, simple handshake, nbio" \
-c "found fragmented DTLS handshake message" \ -c "found fragmented DTLS handshake message" \
-C "error" -C "error"
# This ensures things still work after session_reset(), # This ensures things still work after session_reset().
# for example it would have caught #1941. # It also exercises the "resumed handshake" flow.
# It also exercises the "resumed hanshake" flow.
# Since we don't support reading fragmented ClientHello yet, # Since we don't support reading fragmented ClientHello yet,
# up the MTU to 1450 (larger than ClientHello with session ticket, # up the MTU to 1450 (larger than ClientHello with session ticket,
# but still smaller than client's Certificate to ensure fragmentation). # but still smaller than client's Certificate to ensure fragmentation).
@ -5571,6 +5579,13 @@ run_test "DTLS fragmenting: gnutls server, DTLS 1.0" \
-c "fragmenting handshake message" \ -c "fragmenting handshake message" \
-C "error" -C "error"
# We use --insecure for the GnuTLS client because it expects
# the hostname / IP it connects to to be the name used in the
# certificate obtained from the server. Here, however, it
# connects to 127.0.0.1 while our test certificates use 'localhost'
# as the server name in the certificate. This will make the
# certifiate validation fail, but passing --insecure makes
# GnuTLS continue the connection nonetheless.
requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
requires_config_enabled MBEDTLS_RSA_C requires_config_enabled MBEDTLS_RSA_C
requires_config_enabled MBEDTLS_ECDSA_C requires_config_enabled MBEDTLS_ECDSA_C
@ -5585,6 +5600,7 @@ run_test "DTLS fragmenting: gnutls client, DTLS 1.2" \
0 \ 0 \
-s "fragmenting handshake message" -s "fragmenting handshake message"
# See previous test for the reason to use --insecure
requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
requires_config_enabled MBEDTLS_RSA_C requires_config_enabled MBEDTLS_RSA_C
requires_config_enabled MBEDTLS_ECDSA_C requires_config_enabled MBEDTLS_ECDSA_C
@ -5696,38 +5712,39 @@ run_test "DTLS fragmenting: 3d, gnutls server, DTLS 1.0" \
## https://gitlab.com/gnutls/gnutls/issues/543 ## https://gitlab.com/gnutls/gnutls/issues/543
## We can re-enable them when a fixed version fo GnuTLS is available ## We can re-enable them when a fixed version fo GnuTLS is available
## and installed in our CI system. ## and installed in our CI system.
## skip_next_test
## requires_gnutls requires_gnutls
## requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
## requires_config_enabled MBEDTLS_RSA_C requires_config_enabled MBEDTLS_RSA_C
## requires_config_enabled MBEDTLS_ECDSA_C requires_config_enabled MBEDTLS_ECDSA_C
## requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
## client_needs_more_time 4 client_needs_more_time 4
## run_test "DTLS fragmenting: 3d, gnutls client, DTLS 1.2" \ run_test "DTLS fragmenting: 3d, gnutls client, DTLS 1.2" \
## -p "$P_PXY drop=8 delay=8 duplicate=8" \ -p "$P_PXY drop=8 delay=8 duplicate=8" \
## "$P_SRV dtls=1 debug_level=2 \ "$P_SRV dtls=1 debug_level=2 \
## crt_file=data_files/server7_int-ca.crt \ crt_file=data_files/server7_int-ca.crt \
## key_file=data_files/server7.key \ key_file=data_files/server7.key \
## hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \ hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \
## "$G_CLI -u --insecure 127.0.0.1" \ "$G_CLI -u --insecure 127.0.0.1" \
## 0 \ 0 \
## -s "fragmenting handshake message" -s "fragmenting handshake message"
##
## requires_gnutls skip_next_test
## requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_gnutls
## requires_config_enabled MBEDTLS_RSA_C requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
## requires_config_enabled MBEDTLS_ECDSA_C requires_config_enabled MBEDTLS_RSA_C
## requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1 requires_config_enabled MBEDTLS_ECDSA_C
## client_needs_more_time 4 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
## run_test "DTLS fragmenting: 3d, gnutls client, DTLS 1.0" \ client_needs_more_time 4
## -p "$P_PXY drop=8 delay=8 duplicate=8" \ run_test "DTLS fragmenting: 3d, gnutls client, DTLS 1.0" \
## "$P_SRV dtls=1 debug_level=2 \ -p "$P_PXY drop=8 delay=8 duplicate=8" \
## crt_file=data_files/server7_int-ca.crt \ "$P_SRV dtls=1 debug_level=2 \
## key_file=data_files/server7.key \ crt_file=data_files/server7_int-ca.crt \
## hs_timeout=250-60000 mtu=512 force_version=dtls1" \ key_file=data_files/server7.key \
## "$G_CLI -u --insecure 127.0.0.1" \ hs_timeout=250-60000 mtu=512 force_version=dtls1" \
## 0 \ "$G_CLI -u --insecure 127.0.0.1" \
## -s "fragmenting handshake message" 0 \
-s "fragmenting handshake message"
## Interop test with OpenSSL might triger a bug in recent versions (that ## Interop test with OpenSSL might triger a bug in recent versions (that
## probably won't be fixed before 1.1.1X), so we use an old version that ## probably won't be fixed before 1.1.1X), so we use an old version that
@ -5736,22 +5753,22 @@ run_test "DTLS fragmenting: 3d, gnutls server, DTLS 1.0" \
## Bug report: https://github.com/openssl/openssl/issues/6902 ## Bug report: https://github.com/openssl/openssl/issues/6902
## They should be re-enabled (and the DTLS 1.0 switched back to a non-legacy ## They should be re-enabled (and the DTLS 1.0 switched back to a non-legacy
## version of OpenSSL once a fixed version of OpenSSL is available) ## version of OpenSSL once a fixed version of OpenSSL is available)
## skip_next_test
## requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
## requires_config_enabled MBEDTLS_RSA_C requires_config_enabled MBEDTLS_RSA_C
## requires_config_enabled MBEDTLS_ECDSA_C requires_config_enabled MBEDTLS_ECDSA_C
## requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
## client_needs_more_time 4 client_needs_more_time 4
## run_test "DTLS fragmenting: 3d, openssl server, DTLS 1.2" \ run_test "DTLS fragmenting: 3d, openssl server, DTLS 1.2" \
## -p "$P_PXY drop=8 delay=8 duplicate=8" \ -p "$P_PXY drop=8 delay=8 duplicate=8" \
## "$O_SRV -dtls1_2 -verify 10" \ "$O_SRV -dtls1_2 -verify 10" \
## "$P_CLI dtls=1 debug_level=2 \ "$P_CLI dtls=1 debug_level=2 \
## crt_file=data_files/server8_int-ca2.crt \ crt_file=data_files/server8_int-ca2.crt \
## key_file=data_files/server8.key \ key_file=data_files/server8.key \
## hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \ hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \
## 0 \ 0 \
## -c "fragmenting handshake message" \ -c "fragmenting handshake message" \
## -C "error" -C "error"
requires_openssl_legacy requires_openssl_legacy
requires_config_enabled MBEDTLS_SSL_PROTO_DTLS requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
@ -5935,9 +5952,25 @@ run_test "DTLS reordering: Buffer out-of-order handshake message on client" \
-c "Next handshake message has been buffered - load"\ -c "Next handshake message has been buffered - load"\
-S "Buffering HS message" \ -S "Buffering HS message" \
-S "Next handshake message has been buffered - load"\ -S "Next handshake message has been buffered - load"\
-C "Inject buffered CCS message" \ -C "Injecting buffered CCS message" \
-C "Remember CCS message" \ -C "Remember CCS message" \
-S "Inject buffered CCS message" \ -S "Injecting buffered CCS message" \
-S "Remember CCS message"
run_test "DTLS reordering: Buffer out-of-order handshake message fragment on client" \
-p "$P_PXY delay_srv=ServerHello" \
"$P_SRV mtu=512 dgram_packing=0 cookies=0 dtls=1 debug_level=2" \
"$P_CLI dgram_packing=0 dtls=1 debug_level=2" \
0 \
-c "Buffering HS message" \
-c "found fragmented DTLS handshake message"\
-c "Next handshake message 1 not or only partially bufffered" \
-c "Next handshake message has been buffered - load"\
-S "Buffering HS message" \
-S "Next handshake message has been buffered - load"\
-C "Injecting buffered CCS message" \
-C "Remember CCS message" \
-S "Injecting buffered CCS message" \
-S "Remember CCS message" -S "Remember CCS message"
# The client buffers the ServerKeyExchange before receiving the fragmented # The client buffers the ServerKeyExchange before receiving the fragmented
@ -5955,9 +5988,9 @@ run_test "DTLS reordering: Buffer out-of-order hs msg before reassembling nex
-C "attempt to make space by freeing buffered messages" \ -C "attempt to make space by freeing buffered messages" \
-S "Buffering HS message" \ -S "Buffering HS message" \
-S "Next handshake message has been buffered - load"\ -S "Next handshake message has been buffered - load"\
-C "Inject buffered CCS message" \ -C "Injecting buffered CCS message" \
-C "Remember CCS message" \ -C "Remember CCS message" \
-S "Inject buffered CCS message" \ -S "Injecting buffered CCS message" \
-S "Remember CCS message" -S "Remember CCS message"
# The size constraints ensure that the delayed certificate message can't # The size constraints ensure that the delayed certificate message can't
@ -5975,9 +6008,9 @@ run_test "DTLS reordering: Buffer out-of-order hs msg before reassembling nex
-c "Enough space available after freeing buffered HS messages" \ -c "Enough space available after freeing buffered HS messages" \
-S "Buffering HS message" \ -S "Buffering HS message" \
-S "Next handshake message has been buffered - load"\ -S "Next handshake message has been buffered - load"\
-C "Inject buffered CCS message" \ -C "Injecting buffered CCS message" \
-C "Remember CCS message" \ -C "Remember CCS message" \
-S "Inject buffered CCS message" \ -S "Injecting buffered CCS message" \
-S "Remember CCS message" -S "Remember CCS message"
run_test "DTLS reordering: Buffer out-of-order handshake message on server" \ run_test "DTLS reordering: Buffer out-of-order handshake message on server" \
@ -5989,9 +6022,9 @@ run_test "DTLS reordering: Buffer out-of-order handshake message on server" \
-C "Next handshake message has been buffered - load"\ -C "Next handshake message has been buffered - load"\
-s "Buffering HS message" \ -s "Buffering HS message" \
-s "Next handshake message has been buffered - load" \ -s "Next handshake message has been buffered - load" \
-C "Inject buffered CCS message" \ -C "Injecting buffered CCS message" \
-C "Remember CCS message" \ -C "Remember CCS message" \
-S "Inject buffered CCS message" \ -S "Injecting buffered CCS message" \
-S "Remember CCS message" -S "Remember CCS message"
run_test "DTLS reordering: Buffer out-of-order CCS message on client"\ run_test "DTLS reordering: Buffer out-of-order CCS message on client"\
@ -6003,9 +6036,9 @@ run_test "DTLS reordering: Buffer out-of-order CCS message on client"\
-C "Next handshake message has been buffered - load"\ -C "Next handshake message has been buffered - load"\
-S "Buffering HS message" \ -S "Buffering HS message" \
-S "Next handshake message has been buffered - load" \ -S "Next handshake message has been buffered - load" \
-c "Inject buffered CCS message" \ -c "Injecting buffered CCS message" \
-c "Remember CCS message" \ -c "Remember CCS message" \
-S "Inject buffered CCS message" \ -S "Injecting buffered CCS message" \
-S "Remember CCS message" -S "Remember CCS message"
run_test "DTLS reordering: Buffer out-of-order CCS message on server"\ run_test "DTLS reordering: Buffer out-of-order CCS message on server"\
@ -6017,9 +6050,9 @@ run_test "DTLS reordering: Buffer out-of-order CCS message on server"\
-C "Next handshake message has been buffered - load"\ -C "Next handshake message has been buffered - load"\
-S "Buffering HS message" \ -S "Buffering HS message" \
-S "Next handshake message has been buffered - load" \ -S "Next handshake message has been buffered - load" \
-C "Inject buffered CCS message" \ -C "Injecting buffered CCS message" \
-C "Remember CCS message" \ -C "Remember CCS message" \
-s "Inject buffered CCS message" \ -s "Injecting buffered CCS message" \
-s "Remember CCS message" -s "Remember CCS message"
run_test "DTLS reordering: Buffer encrypted Finished message" \ run_test "DTLS reordering: Buffer encrypted Finished message" \