Skip to main content

net_wire/tls/
handshake.rs

1//! TLS handshake framing views.
2use super::{
3    error::{TlsBuildError, TlsParseError},
4    hello::{ClientHello, ServerHello},
5    types::TlsHandshakeType,
6};
7/// A single structurally bounded TLS handshake message.
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub struct TlsHandshake<'a> {
10    bytes: &'a [u8],
11}
12impl<'a> TlsHandshake<'a> {
13    /// Parses the first complete handshake and excludes any suffix.
14    pub fn parse(bytes: &'a [u8]) -> Result<Self, TlsParseError> {
15        let total = declared(bytes)?;
16        Ok(Self {
17            bytes: &bytes[..total],
18        })
19    }
20    /// Returns the handshake type.
21    pub fn handshake_type(&self) -> TlsHandshakeType {
22        TlsHandshakeType::new(self.bytes[0])
23    }
24    /// Returns the handshake body.
25    pub fn body(&self) -> &'a [u8] {
26        &self.bytes[4..]
27    }
28    /// Returns the represented handshake bytes.
29    pub fn as_bytes(&self) -> &'a [u8] {
30        self.bytes
31    }
32    /// Parses a ClientHello when this message has that type.
33    pub fn client_hello(&self) -> Result<Option<ClientHello<'a>>, TlsParseError> {
34        if self.handshake_type() == TlsHandshakeType::CLIENT_HELLO {
35            ClientHello::parse(self.body()).map(Some)
36        } else {
37            Ok(None)
38        }
39    }
40    /// Parses a ServerHello when this message has that type.
41    pub fn server_hello(&self) -> Result<Option<ServerHello<'a>>, TlsParseError> {
42        if self.handshake_type() == TlsHandshakeType::SERVER_HELLO {
43            ServerHello::parse(self.body()).map(Some)
44        } else {
45            Ok(None)
46        }
47    }
48}
49/// Builds a TLS handshake frame in caller-owned storage.
50pub struct TlsHandshakeBuilder<'a, 'b> {
51    buffer: &'a mut [u8],
52    handshake_type: TlsHandshakeType,
53    body: &'b [u8],
54}
55impl<'a, 'b> TlsHandshakeBuilder<'a, 'b> {
56    /// Starts a handshake builder with a copied body input.
57    pub fn new(buffer: &'a mut [u8], handshake_type: TlsHandshakeType, body: &'b [u8]) -> Self {
58        Self {
59            buffer,
60            handshake_type,
61            body,
62        }
63    }
64    /// Validates all inputs before writing the handshake.
65    pub fn build(self) -> Result<&'a mut [u8], TlsBuildError> {
66        if self.body.len() > 0x00ff_ffff {
67            return Err(TlsBuildError::LengthTooLarge);
68        }
69        let total = 4usize
70            .checked_add(self.body.len())
71            .ok_or(TlsBuildError::LengthTooLarge)?;
72        if self.buffer.len() < total {
73            return Err(TlsBuildError::BufferTooShort {
74                required: total,
75                available: self.buffer.len(),
76            });
77        }
78        let bytes = &mut self.buffer[..total];
79        bytes[0] = self.handshake_type.raw();
80        let len = self.body.len() as u32;
81        bytes[1] = (len >> 16) as u8;
82        bytes[2] = (len >> 8) as u8;
83        bytes[3] = len as u8;
84        bytes[4..].copy_from_slice(self.body);
85        Ok(bytes)
86    }
87}
88fn declared(bytes: &[u8]) -> Result<usize, TlsParseError> {
89    if bytes.len() < 4 {
90        return Err(TlsParseError::Incomplete {
91            required: 4,
92            available: bytes.len(),
93        });
94    }
95    let body = (usize::from(bytes[1]) << 16) | (usize::from(bytes[2]) << 8) | usize::from(bytes[3]);
96    let total = 4 + body;
97    if bytes.len() < total {
98        return Err(TlsParseError::Incomplete {
99            required: total,
100            available: bytes.len(),
101        });
102    }
103    Ok(total)
104}