@@ -113,6 +113,7 @@ pub enum DTLSMessageHandshakeBody<'a> {
113113 Finished ( & ' a [ u8 ] ) ,
114114 CertificateStatus ( TlsCertificateStatusContents < ' a > ) ,
115115 NextProtocol ( TlsNextProtocolContent < ' a > ) ,
116+ Fragment ( & ' a [ u8 ] ) ,
116117}
117118
118119/// DTLS plaintext message
@@ -127,6 +128,17 @@ pub enum DTLSMessage<'a> {
127128 Heartbeat ( TlsMessageHeartbeat < ' a > ) ,
128129}
129130
131+ impl < ' a > DTLSMessage < ' a > {
132+ /// Tell if this DTLSMessage is a (handshake) fragment that needs combining with other
133+ /// fragments to be a complete message.
134+ pub fn is_fragment ( & self ) -> bool {
135+ match self {
136+ DTLSMessage :: Handshake ( h) => matches ! ( h. body, DTLSMessageHandshakeBody :: Fragment ( _) ) ,
137+ _ => false ,
138+ }
139+ }
140+ }
141+
130142// --------------------------- PARSERS ---------------------------
131143
132144/// DTLS record header
@@ -148,6 +160,11 @@ pub fn parse_dtls_record_header(i: &[u8]) -> IResult<&[u8], DTLSRecordHeader> {
148160 Ok ( ( i, record) )
149161}
150162
163+ /// Treat the entire input as an opaque fragment.
164+ fn parse_dtls_fragment ( i : & [ u8 ] ) -> IResult < & [ u8 ] , DTLSMessageHandshakeBody > {
165+ Ok ( ( & [ ] , DTLSMessageHandshakeBody :: Fragment ( i) ) )
166+ }
167+
151168/// DTLS Client Hello
152169// Section 4.2 of RFC6347
153170fn parse_dtls_client_hello ( i : & [ u8 ] ) -> IResult < & [ u8 ] , DTLSMessageHandshakeBody > {
@@ -222,8 +239,16 @@ pub fn parse_dtls_message_handshake(i: &[u8]) -> IResult<&[u8], DTLSMessage> {
222239 let ( i, message_seq) = be_u16 ( i) ?;
223240 let ( i, fragment_offset) = be_u24 ( i) ?;
224241 let ( i, fragment_length) = be_u24 ( i) ?;
225- let ( i, raw_msg) = take ( length) ( i) ?;
242+ // This packet contains fragment_length (which is less than length for fragmentation)
243+ let ( i, raw_msg) = take ( fragment_length) ( i) ?;
244+
245+ // Handshake messages can be fragmented over multiple packets. When fragmented, the user
246+ // needs the fragment_offset, fragment_length and length to determine whether they received
247+ // all the fragments. The DTLS spec allows for overlapping and duplicated fragments.
248+ let is_fragment = fragment_offset > 0 || fragment_length < length;
249+
226250 let ( _, body) = match msg_type {
251+ _ if is_fragment => parse_dtls_fragment ( raw_msg) ,
227252 TlsHandshakeType :: ClientHello => parse_dtls_client_hello ( raw_msg) ,
228253 TlsHandshakeType :: HelloVerifyRequest => parse_dtls_hello_verify_request ( raw_msg) ,
229254 TlsHandshakeType :: ServerHello => parse_dtls_handshake_msg_server_hello_tlsv12 ( raw_msg) ,
@@ -281,18 +306,6 @@ pub fn parse_dtls_record_with_header<'i>(
281306 }
282307}
283308
284- /// Parse DTLS record, leaving `fragment` unparsed
285- // Section 4.1 of RFC6347
286- pub fn parse_dtls_raw_record ( i : & [ u8 ] ) -> IResult < & [ u8 ] , DTLSRawRecord > {
287- let ( i, header) = parse_dtls_record_header ( i) ?;
288- // As in TLS 1.2, the length should not exceed 2^14.
289- if header. length > MAX_RECORD_LEN {
290- return Err ( Err :: Error ( make_error ( i, ErrorKind :: TooLarge ) ) ) ;
291- }
292- let ( i, fragment) = take ( header. length as usize ) ( i) ?;
293- Ok ( ( i, DTLSRawRecord { header, fragment } ) )
294- }
295-
296309/// Parse one DTLS plaintext record
297310// Section 4.1 of RFC6347
298311pub fn parse_dtls_plaintext_record ( i : & [ u8 ] ) -> IResult < & [ u8 ] , DTLSPlaintext > {
0 commit comments