Make handshake reassembly work with openssl
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index bf20c37..7474c14 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -779,8 +779,8 @@
size_t in_msglen; /*!< record header: message length */
size_t in_left; /*!< amount of data read so far */
#if defined(POLARSSL_SSL_PROTO_DTLS)
- size_t next_record_offset; /*!< offset of the next record in datagram,
- or 0 if none */
+ size_t next_record_offset; /*!< offset of the next record in datagram
+ (equal to in_left if none) */
#endif
size_t in_hslen; /*!< current handshake message length */
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 95fcdfb..39d93f9 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1832,7 +1832,7 @@
* with datagram transport (DTLS) on success ssl->in_left >= nb_want,
* since we always read a whole datagram at once.
*
- * For DTLS, It is up to the caller to set ssl->next_record_offset when
+ * For DTLS, it is up to the caller to set ssl->next_record_offset when
* they're done reading a record.
*/
int ssl_fetch_input( ssl_context *ssl, size_t nb_want )
@@ -2289,6 +2289,31 @@
SSL_DEBUG_MSG( 2, ( "handshake message completed" ) );
+ if( ssl->in_left > ssl->next_record_offset )
+ {
+ /*
+ * We've got more data in the buffer after the current record,
+ * that we don't want to overwrite. Move it before writing the
+ * reassembled message, and adjust in_left and next_record_offset.
+ */
+ unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset;
+ unsigned char *new_remain = ssl->in_msg + ssl->in_hslen;
+ size_t remain_len = ssl->in_left - ssl->next_record_offset;
+
+ /* First compute and check new lengths */
+ ssl->next_record_offset = new_remain - ssl->in_hdr;
+ ssl->in_left = ssl->next_record_offset + remain_len;
+
+ if( ssl->in_left > SSL_BUFFER_LEN -
+ (size_t)( ssl->in_hdr - ssl->in_buf ) )
+ {
+ SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) );
+ return( POLARSSL_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+ memmove( new_remain, cur_remain, remain_len );
+ }
+
memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen );
polarssl_free( ssl->handshake->hs_msg );
@@ -2409,6 +2434,8 @@
return( ret );
}
+ SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, ssl_hdr_len( ssl ) );
+
ssl->in_msgtype = ssl->in_hdr[0];
ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1];
ssl_read_version( &major_ver, &minor_ver, ssl->transport, ssl->in_hdr + 1 );
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index d5b1a29..13847dd 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -1988,27 +1988,26 @@
-C "found fragmented DTLS handshake message" \
-C "error"
-# Not working yet
-#run_test "DTLS reassembly: fragmentation (openssl server)" \
-# "$O_SRV -dtls1 -mtu 256" \
-# "$P_CLI dtls=1 debug_level=2" \
-# 0 \
-# -c "found fragmented DTLS handshake message" \
-# -C "error"
-#
-#run_test "DTLS reassembly: fragmentation (openssl server)" \
-# "$O_SRV -dtls1 -mtu 256" \
-# "$P_CLI dtls=1 debug_level=2" \
-# 0 \
-# -c "found fragmented DTLS handshake message" \
-# -C "error"
-#
-#run_test "DTLS reassembly: fragmentation, nbio (openssl server)" \
-# "$O_SRV -dtls1 -mtu 256" \
-# "$P_CLI dtls=1 nbio=2 debug_level=2" \
-# 0 \
-# -c "found fragmented DTLS handshake message" \
-# -C "error"
+run_test "DTLS reassembly: fragmentation (openssl server)" \
+ "$O_SRV -dtls1 -mtu 256" \
+ "$P_CLI dtls=1 debug_level=2" \
+ 0 \
+ -c "found fragmented DTLS handshake message" \
+ -C "error"
+
+run_test "DTLS reassembly: fragmentation (openssl server)" \
+ "$O_SRV -dtls1 -mtu 256" \
+ "$P_CLI dtls=1 debug_level=2" \
+ 0 \
+ -c "found fragmented DTLS handshake message" \
+ -C "error"
+
+run_test "DTLS reassembly: fragmentation, nbio (openssl server)" \
+ "$O_SRV -dtls1 -mtu 256" \
+ "$P_CLI dtls=1 nbio=2 debug_level=2" \
+ 0 \
+ -c "found fragmented DTLS handshake message" \
+ -C "error"
# TODO: fragmentation with renegotiation, openssl + gnutls