Start implementing fragmentation
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 5f03223..6e0f6b6 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -2852,16 +2852,23 @@
MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise fligh transmission" ) );
ssl->handshake->cur_msg = ssl->handshake->flight;
+ ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;
ssl_swap_epochs( ssl );
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;
}
+ /*
+ * XXX: this should not be hardcoded.
+ * Currently UDP limit - HS header - Record header
+ * (Should account for encryption overhead (renegotiation, finished)?)
+ */
+#define HS_LIMIT ( 512 - 12 - 13 )
+
while( ssl->handshake->cur_msg != NULL )
{
int ret;
- mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg;
-
+ const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;
/* 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 */
@@ -2871,14 +2878,64 @@
ssl_swap_epochs( ssl );
}
- memcpy( ssl->out_msg, cur->p, cur->len );
- ssl->out_msglen = cur->len;
- ssl->out_msgtype = cur->type;
+ /* CCS is copied as is, while HS messages may need fragmentation */
+ if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ memcpy( ssl->out_msg, cur->p, cur->len );
+ ssl->out_msglen = cur->len;
+ ssl->out_msgtype = cur->type;
- ssl->handshake->cur_msg = cur->next;
+ /* Update position inside current message */
+ ssl->handshake->cur_msg_p += cur->len;
+ }
+ else
+ {
+ 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 > HS_LIMIT ? HS_LIMIT : rem_len;
- MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
+ /* Messages are stored with handshake headers as if not fragmented,
+ * copy beginning of headers then fill fragmentation fields.
+ * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */
+ memcpy( ssl->out_msg, cur->p, 6 );
+ ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff );
+ 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 );
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
+
+ /* Copy the handshame message content and set records fields */
+ memcpy( ssl->out_msg + 12, p, frag_len );
+ ssl->out_msglen = frag_len + 12;
+ ssl->out_msgtype = cur->type;
+
+ /* Update position inside current message */
+ ssl->handshake->cur_msg_p += frag_len;
+ }
+
+ /* If done with the current message move to the next one if any */
+ if( ssl->handshake->cur_msg_p >= cur->p + cur->len )
+ {
+ if( cur->next != NULL )
+ {
+ ssl->handshake->cur_msg = cur->next;
+ ssl->handshake->cur_msg_p = cur->next->p + 12;
+ }
+ else
+ {
+ ssl->handshake->cur_msg = NULL;
+ ssl->handshake->cur_msg_p = NULL;
+ }
+ }
+
+ /* Actually send the message out */
if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
@@ -2886,6 +2943,7 @@
}
}
+ /* Update state and set timer */
if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
else