Skip to main content

ytls_server/server_ctx/s_handshake/
r_server_handshake_finished.rs

1//! Server handshake finished for Server Handshake Ctx
2
3use crate::{CtxError, ServerHandshakeCtx, TlsServerCtxConfig};
4
5use ytls_traits::CryptoSha256TranscriptProcessor;
6
7use ytls_traits::CryptoConfig;
8use ytls_traits::CryptoRng;
9use ytls_traits::TlsLeftOut;
10
11use ytls_record::WrappedStaticRecordBuilder;
12use ytls_traits::CryptoChaCha20Poly1305Processor;
13use ytls_traits::CryptoSha256HmacProcessor;
14use ytls_traits::ServerHandshakeFinishedBuilder;
15use ytls_traits::WrappedHandshakeBuilder;
16
17use ytls_traits::Tls13KeyScheduleHandshakeSha256;
18
19impl<Config, Crypto, Rng> ServerHandshakeFinishedBuilder for ServerHandshakeCtx<Config, Crypto, Rng>
20where
21    Config: TlsServerCtxConfig,
22    Crypto: CryptoConfig,
23    Rng: CryptoRng,
24{
25    fn hash_finished(&self) -> &[u8] {
26        match self.hash_finished {
27            Some(ref h) => h,
28            None => &[],
29        }
30    }
31}
32
33impl<Config, Crypto, Rng> ServerHandshakeCtx<Config, Crypto, Rng>
34where
35    Config: TlsServerCtxConfig,
36    Crypto: CryptoConfig,
37    Rng: CryptoRng,
38{
39    #[inline]
40    pub(crate) fn do_server_handshake_finished<
41        L: TlsLeftOut,
42        T: CryptoSha256TranscriptProcessor,
43    >(
44        &mut self,
45        left: &mut L,
46        transcript: &mut T,
47    ) -> Result<(), CtxError> {
48        let key: [u8; 32] = match self.handshake_server_key {
49            None => return Err(CtxError::MissingHandshakeKey),
50            Some(k) => k,
51        };
52
53        let nonce: [u8; 12] = match self.handshake_server_iv {
54            None => return Err(CtxError::MissingHandshakeIv),
55            Some(ref mut n) => match n.use_and_incr() {
56                Some(cur) => cur,
57                None => return Err(CtxError::ExhaustedIv),
58            },
59        };
60
61        let cipher = Crypto::aead_chaha20poly1305(&key);
62
63        // snapshot transcript hash for cert verify
64        let ctx_transcript = transcript.sha256_fork();
65        let ctx_hash_input = ctx_transcript.sha256_finalize();
66
67        let hs_key = match self.handshake_finished_server_key {
68            Some(ref k) => k,
69            None => &[
70                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71                0, 0, 0, 0,
72            ],
73        };
74
75        let mut mac = Crypto::hmac_sha256_init_with_key(hs_key);
76        mac.hmac_sha256_update(&ctx_hash_input);
77
78        let finished_hmac = mac.hmac_sha256_finalize();
79
80        self.hash_finished = Some(finished_hmac);
81
82        let mut server_handshake_finished =
83            WrappedStaticRecordBuilder::<8192>::server_handshake_finished(self)
84                .map_err(CtxError::Builder)?;
85
86        transcript.sha256_update(server_handshake_finished.as_hashing_context_ref());
87
88        let tag = if let Ok([additional_data, encrypt_payload]) =
89            server_handshake_finished.as_disjoint_mut_for_aead()
90        {
91            cipher
92                .encrypt_in_place(&nonce, &additional_data, encrypt_payload.as_mut())
93                .map_err(|_| CtxError::Bug("Encrypt failure."))?
94        } else {
95            return Err(CtxError::Bug(
96                "Disjoint for AEAD failed at certificate verify.",
97            ));
98        };
99
100        server_handshake_finished.set_auth_tag(&tag);
101
102        left.send_record_out(server_handshake_finished.as_encoded_bytes());
103        Ok(())
104    }
105}