Skip to main content

ytls_server/server_ctx/s_handshake/
r_server_certificate_verify.rs

1//! Encrypted Extensions handler for Server Handshake Ctx
2
3use crate::{CtxError, ServerHandshakeCtx, TlsServerCtxConfig};
4
5use ytls_traits::CryptoChaCha20Poly1305Processor;
6use ytls_traits::CryptoSha256TranscriptProcessor;
7use ytls_traits::CryptoSignerP256Processor;
8
9use ytls_traits::Tls13KeyScheduleHandshakeSha256;
10
11use ytls_traits::CryptoConfig;
12use ytls_traits::CryptoRng;
13use ytls_traits::TlsLeftOut;
14
15use ytls_record::WrappedStaticRecordBuilder;
16use ytls_traits::ServerCertificateVerifyBuilder;
17use ytls_traits::WrappedHandshakeBuilder;
18
19impl<Config, Crypto, Rng> ServerCertificateVerifyBuilder for ServerHandshakeCtx<Config, Crypto, Rng>
20where
21    Config: TlsServerCtxConfig,
22    Crypto: CryptoConfig,
23    Rng: CryptoRng,
24{
25    #[inline]
26    fn signature_algorithm(&self) -> [u8; 2] {
27        // ecdsa_secp256r1_sha256
28        [0x04, 0x03]
29    }
30    #[inline]
31    fn sign_cert_verify(&self) -> &[u8] {
32        match self.signature_cert_verify {
33            Some(ref s) => &s[..self.signature_cert_verify_len],
34            None => &[],
35        }
36    }
37}
38
39impl<Config, Crypto, Rng> ServerHandshakeCtx<Config, Crypto, Rng>
40where
41    Config: TlsServerCtxConfig,
42    Crypto: CryptoConfig,
43    Rng: CryptoRng,
44{
45    #[inline]
46    pub(crate) fn do_server_certificate_verify<
47        L: TlsLeftOut,
48        T: CryptoSha256TranscriptProcessor,
49    >(
50        &mut self,
51        left: &mut L,
52        transcript: &mut T,
53    ) -> Result<(), CtxError> {
54        let key: [u8; 32] = match self.handshake_server_key {
55            None => return Err(CtxError::MissingHandshakeKey),
56            Some(k) => k,
57        };
58
59        let nonce: [u8; 12] = match self.handshake_server_iv {
60            None => return Err(CtxError::MissingHandshakeIv),
61            Some(ref mut n) => match n.use_and_incr() {
62                Some(cur) => cur,
63                None => return Err(CtxError::ExhaustedIv),
64            },
65        };
66
67        // snapshot transcript hash for cert verify
68        let ctx_transcript = transcript.sha256_fork();
69        let ctx_hash_input = ctx_transcript.sha256_finalize();
70        self.cert_verify_hash = Some(ctx_hash_input);
71
72        let h = match self.cert_verify_hash {
73            Some(h) => h,
74            None => return Err(CtxError::Bug("Missing certificate verify hash.")),
75        };
76
77        // +64 bytes of 0x20 (30)
78        // +33 bytes of "Context"
79        //  +1 byte content separator
80        // +32 bytes of hash
81        // ---------------------------
82        // 130 bytes total
83        let verify: [u8; 130] = [
84            // 1     2     3     4     5     6     7     8     9     0
85            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
86            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
87            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
88            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
89            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
90            //  123456789012345678901234567890123  (33 bytes)
91            // "TLS 1.3, server CertificateVerify"
92            0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, 0x2c, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65,
93            0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56,
94            0x65, 0x72, 0x69, 0x66, 0x79, // content separator \0 (1 byte)
95            0x00, // 32 bytes hash
96            h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13],
97            h[14], h[15], h[16], h[17], h[18], h[19], h[20], h[21], h[22], h[23], h[24], h[25],
98            h[26], h[27], h[28], h[29], h[30], h[31],
99        ];
100
101        let raw_signing_key = self.config.server_private_key();
102        let signer = match Crypto::sign_p256_init(raw_signing_key) {
103            Some(signer) => signer,
104            None => return Err(CtxError::PrivateKey),
105        };
106        let mut c_bytes: [u8; 100] = [0; 100];
107        let c_bytes_len = match signer.sign_p256(&verify, &mut c_bytes) {
108            None => return Err(CtxError::Crypto),
109            Some(out_len) => out_len,
110        };
111
112        self.signature_cert_verify = Some(c_bytes);
113        self.signature_cert_verify_len = c_bytes_len;
114
115        let cipher = Crypto::aead_chaha20poly1305(&key);
116
117        let mut server_certificate_verify =
118            WrappedStaticRecordBuilder::<8192>::server_certificate_verify(self)
119                .map_err(CtxError::Builder)?;
120
121        transcript.sha256_update(server_certificate_verify.as_hashing_context_ref());
122
123        let tag = if let Ok([additional_data, encrypt_payload]) =
124            server_certificate_verify.as_disjoint_mut_for_aead()
125        {
126            cipher
127                .encrypt_in_place(&nonce, &additional_data, encrypt_payload.as_mut())
128                .map_err(|_| CtxError::Bug("Encrypt failure."))?
129        } else {
130            return Err(CtxError::Bug(
131                "Disjoint for AEAD failed at certificate verify.",
132            ));
133        };
134
135        server_certificate_verify.set_auth_tag(&tag);
136
137        left.send_record_out(server_certificate_verify.as_encoded_bytes());
138        Ok(())
139    }
140}