ytls_extensions/
delegated_credential.rs

1//! yTLS Extension (34) Delegated Credential support
2
3use crate::TlsExtError;
4use ytls_typed::SignatureAlgorithm;
5
6/// Downstream Group Processor
7pub trait ExtDelegatedCredentialProcessor {
8    /// Indicate support for the given Signature Algorithm.
9    fn delegated_credential_signature_algorithm(&mut self, _: SignatureAlgorithm) -> bool;
10}
11
12/// TLS Extension 34 Delegated Credential Support
13pub struct TlsExtDelegatedCredential {}
14
15impl TlsExtDelegatedCredential {
16    /// Parse all the signature algorithms from the Client Hello extension data
17    #[inline]
18    pub fn client_delegated_credential_cb<P: ExtDelegatedCredentialProcessor>(
19        p: &mut P,
20        sig_alg_raw: &[u8],
21    ) -> Result<(), TlsExtError> {
22        if sig_alg_raw.len() < 2 {
23            return Err(TlsExtError::InvalidLength);
24        }
25        let sig_algs_len = u16::from_be_bytes([sig_alg_raw[0], sig_alg_raw[1]]);
26
27        if sig_algs_len == 0 {
28            return Err(TlsExtError::NoData);
29        }
30
31        let remaining = &sig_alg_raw[2..];
32        let expected_len = remaining.len();
33
34        if sig_algs_len as usize != expected_len {
35            return Err(TlsExtError::InvalidLength);
36        }
37
38        let mut sig_algs_i = remaining.chunks(2);
39
40        while let Some(sig_alg) = sig_algs_i.next() {
41            let sig_alg_id = u16::from_be_bytes([sig_alg[0], sig_alg[1]]);
42            p.delegated_credential_signature_algorithm(sig_alg_id.into());
43        }
44        Ok(())
45    }
46}
47
48#[cfg(test)]
49mod test {
50    use super::*;
51    use hex_literal::hex;
52    use rstest::rstest;
53    use ytls_typed::SignatureAlgorithm as Sa;
54
55    #[derive(Debug, Default, PartialEq)]
56    struct Tester {
57        seen: Vec<Sa>,
58    }
59
60    impl ExtDelegatedCredentialProcessor for Tester {
61        fn delegated_credential_signature_algorithm(&mut self, dgsa: Sa) -> bool {
62            self.seen.push(dgsa);
63            true
64        }
65    }
66
67    #[rstest]
68    #[case(
69        "00080403050306030203",
70        Tester { seen: vec![Sa::EcdsaSecp256r1Sha256, Sa::EcdsaSecp384r1Sha384, Sa::EcdsaSecp521r1Sha512, Sa::EcdsaSha1] },
71        Ok(())
72    )]
73    #[case(
74        "",
75        Tester { seen: vec![] },
76        Err(TlsExtError::InvalidLength)
77    )]
78    fn client_delegated_credential_dgsa(
79        #[case] raw_t: &str,
80        #[case] expected_tester: Tester,
81        #[case] expected_res: Result<(), TlsExtError>,
82    ) {
83        let in_raw = hex::decode(raw_t).unwrap();
84        let mut tester = Tester::default();
85        let res = TlsExtDelegatedCredential::client_delegated_credential_cb(&mut tester, &in_raw);
86        assert_eq!(expected_tester, tester);
87        assert_eq!(expected_res, res);
88    }
89}