Skip to main content

net_wire/tls/extensions/
key_share.rs

1use super::layout::{len, v16};
2use crate::tls::{error::TlsParseError, types::TlsNamedGroup};
3
4/// Ordered ClientHello key-share entries.
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6pub struct ClientKeyShare<'a> {
7    bytes: &'a [u8],
8}
9impl<'a> ClientKeyShare<'a> {
10    pub(super) fn parse(b: &'a [u8]) -> Result<Self, TlsParseError> {
11        let x = v16(b, 0, false)?;
12        shares_ok(x)?;
13        Ok(Self { bytes: x })
14    }
15    /// Returns key shares in their original wire order.
16    pub fn iter(&self) -> KeyShareIter<'a> {
17        KeyShareIter { bytes: self.bytes }
18    }
19}
20/// One named-group key-share entry.
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
22pub struct KeyShareEntry<'a> {
23    group: TlsNamedGroup,
24    key_exchange: &'a [u8],
25}
26impl<'a> KeyShareEntry<'a> {
27    /// Returns the raw named group.
28    pub const fn group(self) -> TlsNamedGroup {
29        self.group
30    }
31    /// Returns the opaque key-exchange bytes.
32    pub const fn key_exchange(self) -> &'a [u8] {
33        self.key_exchange
34    }
35}
36/// A fallible iterator over key-share entries.
37#[derive(Clone, Debug)]
38pub struct KeyShareIter<'a> {
39    bytes: &'a [u8],
40}
41impl<'a> Iterator for KeyShareIter<'a> {
42    type Item = Result<KeyShareEntry<'a>, TlsParseError>;
43    fn next(&mut self) -> Option<Self::Item> {
44        if self.bytes.is_empty() {
45            return None;
46        }
47        match share(self.bytes) {
48            Ok((x, n)) => {
49                self.bytes = &self.bytes[n..];
50                Some(Ok(x))
51            }
52            Err(e) => {
53                self.bytes = &[];
54                Some(Err(e))
55            }
56        }
57    }
58}
59fn share(b: &[u8]) -> Result<(KeyShareEntry<'_>, usize), TlsParseError> {
60    if b.len() < 4 {
61        return Err(TlsParseError::Incomplete {
62            required: 4,
63            available: b.len(),
64        });
65    }
66    let n = usize::from(u16::from_be_bytes([b[2], b[3]]));
67    if n == 0 {
68        return Err(TlsParseError::InvalidValue);
69    }
70    if b.len() < n + 4 {
71        return Err(TlsParseError::Incomplete {
72            required: n + 4,
73            available: b.len(),
74        });
75    }
76    Ok((
77        KeyShareEntry {
78            group: TlsNamedGroup::new(u16::from_be_bytes([b[0], b[1]])),
79            key_exchange: &b[4..n + 4],
80        },
81        n + 4,
82    ))
83}
84fn shares_ok(mut b: &[u8]) -> Result<(), TlsParseError> {
85    while !b.is_empty() {
86        let (_, n) = share(b)?;
87        b = &b[n..]
88    }
89    Ok(())
90}
91/// The single key share carried by a ServerHello.
92#[derive(Clone, Copy, Debug, Eq, PartialEq)]
93pub struct ServerKeyShare<'a>(KeyShareEntry<'a>);
94impl<'a> ServerKeyShare<'a> {
95    pub(super) fn parse(b: &'a [u8]) -> Result<Self, TlsParseError> {
96        let (x, n) = share(b)?;
97        if n != b.len() {
98            return Err(TlsParseError::TrailingBytes);
99        }
100        Ok(Self(x))
101    }
102    /// Returns the selected key-share entry.
103    pub const fn entry(self) -> KeyShareEntry<'a> {
104        self.0
105    }
106}
107/// The named group selected by a HelloRetryRequest.
108#[derive(Clone, Copy, Debug, Eq, PartialEq)]
109pub struct HrrKeyShare(TlsNamedGroup);
110impl HrrKeyShare {
111    pub(super) fn parse(b: &[u8]) -> Result<Self, TlsParseError> {
112        if b.len() != 2 {
113            return Err(len(2, b.len()));
114        }
115        Ok(Self(TlsNamedGroup::new(u16::from_be_bytes([b[0], b[1]]))))
116    }
117    /// Returns the selected named group.
118    pub const fn group(self) -> TlsNamedGroup {
119        self.0
120    }
121}