ytls_extensions/
supported_groups.rs

1//! yTLS Extension (10) supported groups
2//! https://datatracker.ietf.org/doc/html/rfc8422
3//! https://datatracker.ietf.org/doc/html/rfc4492#section-5.1.1
4//! FFDHE https://datatracker.ietf.org/doc/html/rfc7919#section-2
5//! Hybrids https://datatracker.ietf.org/doc/html/draft-kwiatkowski-tls-ecdhe-mlkem-03
6
7use crate::TlsExtError;
8use ytls_typed::Group;
9
10/// Downstream Group Processor
11pub trait ExtGroupProcessor {
12    /// Check whether any of the provided groups matches.
13    /// When any of the entries matches, result will be
14    /// true and otherwise false.
15    fn group(&mut self, _: Group) -> bool;
16}
17
18/// TLS Extension 10 (EC) Group handling
19pub struct TlsExtGroup {}
20
21impl TlsExtGroup {
22    /// Check with the provided Processor whether
23    /// any of the Client Hello provided SNIs matches
24    #[inline]
25    pub fn client_group_cb<P: ExtGroupProcessor>(
26        p: &mut P,
27        group_raw: &[u8],
28    ) -> Result<(), TlsExtError> {
29        if group_raw.len() < 2 {
30            return Err(TlsExtError::InvalidLength);
31        }
32        let group_len = u16::from_be_bytes([group_raw[0], group_raw[1]]);
33
34        if group_len == 0 {
35            return Err(TlsExtError::NoData);
36        }
37
38        let remaining = &group_raw[2..];
39        let expected_len = remaining.len();
40
41        if group_len as usize != expected_len {
42            return Err(TlsExtError::InvalidLength);
43        }
44
45        let mut group_i = remaining.chunks(2);
46
47        while let Some(group) = group_i.next() {
48            let g_id = u16::from_be_bytes([group[0], group[1]]);
49            p.group(g_id.into());
50        }
51        Ok(())
52    }
53}