Skip to main content

wireforge_app/tls/
extensions.rs

1//! TLS extensions parser.
2
3/// A single TLS extension (type + data).
4#[derive(Debug, Clone)]
5pub struct TlsExtension<'a> {
6    pub extension_type: u16,
7    pub data: &'a [u8],
8}
9
10/// Iterator over TLS extensions.
11pub struct TlsExtensionsIter<'a> { data: &'a [u8] }
12
13impl<'a> TlsExtensionsIter<'a> {
14    pub fn new(data: &'a [u8]) -> Self { Self { data } }
15}
16
17impl<'a> Iterator for TlsExtensionsIter<'a> {
18    type Item = TlsExtension<'a>;
19
20    fn next(&mut self) -> Option<Self::Item> {
21        if self.data.len() < 4 { return None; }
22        let ext_type = u16::from_be_bytes([self.data[0], self.data[1]]);
23        let len = u16::from_be_bytes([self.data[2], self.data[3]]) as usize;
24        if self.data.len() < 4 + len { return None; }
25        let ext_data = &self.data[4..4 + len];
26        self.data = &self.data[4 + len..];
27        Some(TlsExtension { extension_type: ext_type, data: ext_data })
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    #[test]
36    fn iterate_two_extensions() {
37        // ext1: type=0x0000 (SNI), len=2, data=[0xAA,0xBB]
38        // ext2: type=0x002b (supported_versions), len=1, data=[0x04]
39        let data = &[0x00u8, 0x00, 0x00, 0x02, 0xAA, 0xBB,
40                     0x00, 0x2b, 0x00, 0x01, 0x04];
41        let exts: Vec<_> = TlsExtensionsIter::new(data).collect();
42        assert_eq!(exts.len(), 2);
43        assert_eq!(exts[0].extension_type, 0x0000);
44        assert_eq!(exts[0].data, &[0xAA, 0xBB]);
45        assert_eq!(exts[1].extension_type, 0x002b);
46        assert_eq!(exts[1].data, &[0x04]);
47    }
48
49    #[test]
50    fn iterator_empty() {
51        let exts: Vec<_> = TlsExtensionsIter::new(&[]).collect();
52        assert!(exts.is_empty());
53    }
54
55    #[test]
56    fn iterator_truncated() {
57        // len says 5 bytes but only 2 remain
58        let data = &[0x00u8, 0x00, 0x00, 0x05, 0xAA];
59        let exts: Vec<_> = TlsExtensionsIter::new(data).collect();
60        assert!(exts.is_empty());
61    }
62}