diff --git a/CHANGELOG.md b/CHANGELOG.md index 6db26dc1..51748c28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased + * Reject malformed DTLS 1.3 ClientHello extension vectors #133 * Reject malformed DTLS 1.3 KeyUpdate bodies #131 * Reject malformed DTLS 1.3 ACK record-number vectors #130 * Parse DTLS 1.2-only ClientHellos for auto-sense fallback #129 diff --git a/src/dtls13/message/client_hello.rs b/src/dtls13/message/client_hello.rs index 49029065..b6ceedad 100644 --- a/src/dtls13/message/client_hello.rs +++ b/src/dtls13/message/client_hello.rs @@ -114,11 +114,10 @@ impl ClientHello { let original_input = input; let (remaining, extensions_len) = be_u16(input)?; - if extensions_len == 0 { - return Ok((remaining, extensions)); - } - let (remaining, extensions_data) = take(extensions_len)(remaining)?; + if !remaining.is_empty() { + return Err(Err::Failure(Error::new(remaining, ErrorKind::LengthValue))); + } let consumed = extensions_data.as_ptr() as usize - original_input.as_ptr() as usize; let data_base_offset = base_offset + consumed; @@ -356,4 +355,31 @@ mod tests { ); } } + + #[test] + fn zero_length_extension_vector_rejects_trailing_bytes() { + let mut message = MESSAGE.to_vec(); + message.extend_from_slice(&0u16.to_be_bytes()); + message.extend_from_slice(&ExtensionType::Cookie.as_u16().to_be_bytes()); + message.extend_from_slice(&0u16.to_be_bytes()); + + assert!( + ClientHello::parse(&message, 0).is_err(), + "extension vector length 0 must consume the remaining ClientHello body" + ); + } + + #[test] + fn underdeclared_extension_vector_rejects_trailing_bytes() { + let mut message = MESSAGE.to_vec(); + message.extend_from_slice(&4u16.to_be_bytes()); + message.extend_from_slice(&ExtensionType::Cookie.as_u16().to_be_bytes()); + message.extend_from_slice(&0u16.to_be_bytes()); + message.push(0); + + assert!( + ClientHello::parse(&message, 0).is_err(), + "declared extension vector length must consume the remaining ClientHello body" + ); + } }