rustls_fork_shadow_tls/tls13/
mod.rs

1use crate::cipher::{make_nonce, Iv, MessageDecrypter, MessageEncrypter};
2use crate::enums::{CipherSuite, ProtocolVersion};
3use crate::error::Error;
4use crate::msgs::base::Payload;
5use crate::msgs::codec::Codec;
6use crate::msgs::enums::ContentType;
7use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
8use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
9use crate::suites::{BulkAlgorithm, CipherSuiteCommon, SupportedCipherSuite};
10
11use ring::{aead, hkdf};
12
13use std::fmt;
14
15pub(crate) mod key_schedule;
16use key_schedule::{derive_traffic_iv, derive_traffic_key};
17
18/// The TLS1.3 ciphersuite TLS_CHACHA20_POLY1305_SHA256
19pub static TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
20    SupportedCipherSuite::Tls13(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
21
22pub(crate) static TLS13_CHACHA20_POLY1305_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
23    common: CipherSuiteCommon {
24        suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
25        bulk: BulkAlgorithm::Chacha20Poly1305,
26        aead_algorithm: &ring::aead::CHACHA20_POLY1305,
27    },
28    hkdf_algorithm: ring::hkdf::HKDF_SHA256,
29    #[cfg(feature = "quic")]
30    confidentiality_limit: u64::MAX,
31    #[cfg(feature = "quic")]
32    integrity_limit: 1 << 36,
33};
34
35/// The TLS1.3 ciphersuite TLS_AES_256_GCM_SHA384
36pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite =
37    SupportedCipherSuite::Tls13(&Tls13CipherSuite {
38        common: CipherSuiteCommon {
39            suite: CipherSuite::TLS13_AES_256_GCM_SHA384,
40            bulk: BulkAlgorithm::Aes256Gcm,
41            aead_algorithm: &ring::aead::AES_256_GCM,
42        },
43        hkdf_algorithm: ring::hkdf::HKDF_SHA384,
44        #[cfg(feature = "quic")]
45        confidentiality_limit: 1 << 23,
46        #[cfg(feature = "quic")]
47        integrity_limit: 1 << 52,
48    });
49
50/// The TLS1.3 ciphersuite TLS_AES_128_GCM_SHA256
51pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite =
52    SupportedCipherSuite::Tls13(TLS13_AES_128_GCM_SHA256_INTERNAL);
53
54pub(crate) static TLS13_AES_128_GCM_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
55    common: CipherSuiteCommon {
56        suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
57        bulk: BulkAlgorithm::Aes128Gcm,
58        aead_algorithm: &ring::aead::AES_128_GCM,
59    },
60    hkdf_algorithm: ring::hkdf::HKDF_SHA256,
61    #[cfg(feature = "quic")]
62    confidentiality_limit: 1 << 23,
63    #[cfg(feature = "quic")]
64    integrity_limit: 1 << 52,
65};
66
67/// A TLS 1.3 cipher suite supported by rustls.
68pub struct Tls13CipherSuite {
69    /// Common cipher suite fields.
70    pub common: CipherSuiteCommon,
71    pub(crate) hkdf_algorithm: ring::hkdf::Algorithm,
72    #[cfg(feature = "quic")]
73    pub(crate) confidentiality_limit: u64,
74    #[cfg(feature = "quic")]
75    pub(crate) integrity_limit: u64,
76}
77
78impl Tls13CipherSuite {
79    pub(crate) fn derive_encrypter(&self, secret: &hkdf::Prk) -> Box<dyn MessageEncrypter> {
80        let key = derive_traffic_key(secret, self.common.aead_algorithm);
81        let iv = derive_traffic_iv(secret);
82
83        Box::new(Tls13MessageEncrypter {
84            enc_key: aead::LessSafeKey::new(key),
85            iv,
86        })
87    }
88
89    /// Derive a `MessageDecrypter` object from the concerned TLS 1.3
90    /// cipher suite.
91    pub fn derive_decrypter(&self, secret: &hkdf::Prk) -> Box<dyn MessageDecrypter> {
92        let key = derive_traffic_key(secret, self.common.aead_algorithm);
93        let iv = derive_traffic_iv(secret);
94
95        Box::new(Tls13MessageDecrypter {
96            dec_key: aead::LessSafeKey::new(key),
97            iv,
98        })
99    }
100
101    /// Which hash function to use with this suite.
102    pub fn hash_algorithm(&self) -> &'static ring::digest::Algorithm {
103        self.hkdf_algorithm
104            .hmac_algorithm()
105            .digest_algorithm()
106    }
107
108    /// Can a session using suite self resume from suite prev?
109    pub fn can_resume_from(&self, prev: &'static Self) -> Option<&'static Self> {
110        (prev.hash_algorithm() == self.hash_algorithm()).then(|| prev)
111    }
112}
113
114impl From<&'static Tls13CipherSuite> for SupportedCipherSuite {
115    fn from(s: &'static Tls13CipherSuite) -> Self {
116        Self::Tls13(s)
117    }
118}
119
120impl PartialEq for Tls13CipherSuite {
121    fn eq(&self, other: &Self) -> bool {
122        self.common.suite == other.common.suite
123    }
124}
125
126impl fmt::Debug for Tls13CipherSuite {
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128        f.debug_struct("Tls13CipherSuite")
129            .field("suite", &self.common.suite)
130            .field("bulk", &self.common.bulk)
131            .finish()
132    }
133}
134
135struct Tls13MessageEncrypter {
136    enc_key: aead::LessSafeKey,
137    iv: Iv,
138}
139
140struct Tls13MessageDecrypter {
141    dec_key: aead::LessSafeKey,
142    iv: Iv,
143}
144
145fn unpad_tls13(v: &mut Vec<u8>) -> ContentType {
146    loop {
147        match v.pop() {
148            Some(0) => {}
149            Some(content_type) => return ContentType::from(content_type),
150            None => return ContentType::Unknown(0),
151        }
152    }
153}
154
155fn make_tls13_aad(len: usize) -> ring::aead::Aad<[u8; TLS13_AAD_SIZE]> {
156    ring::aead::Aad::from([
157        0x17, // ContentType::ApplicationData
158        0x3,  // ProtocolVersion (major)
159        0x3,  // ProtocolVersion (minor)
160        (len >> 8) as u8,
161        len as u8,
162    ])
163}
164
165// https://datatracker.ietf.org/doc/html/rfc8446#section-5.2
166const TLS13_AAD_SIZE: usize = 1 + 2 + 2;
167
168impl MessageEncrypter for Tls13MessageEncrypter {
169    fn encrypt(&self, msg: BorrowedPlainMessage, seq: u64) -> Result<OpaqueMessage, Error> {
170        let total_len = msg.payload.len() + 1 + self.enc_key.algorithm().tag_len();
171        let mut payload = Vec::with_capacity(total_len);
172        payload.extend_from_slice(msg.payload);
173        msg.typ.encode(&mut payload);
174
175        let nonce = make_nonce(&self.iv, seq);
176        let aad = make_tls13_aad(total_len);
177
178        self.enc_key
179            .seal_in_place_append_tag(nonce, aad, &mut payload)
180            .map_err(|_| Error::General("encrypt failed".to_string()))?;
181
182        Ok(OpaqueMessage {
183            typ: ContentType::ApplicationData,
184            version: ProtocolVersion::TLSv1_2,
185            payload: Payload::new(payload),
186        })
187    }
188}
189
190impl MessageDecrypter for Tls13MessageDecrypter {
191    fn decrypt(&self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
192        let payload = &mut msg.payload.0;
193        if payload.len() < self.dec_key.algorithm().tag_len() {
194            return Err(Error::DecryptError);
195        }
196
197        let nonce = make_nonce(&self.iv, seq);
198        let aad = make_tls13_aad(payload.len());
199        let plain_len = self
200            .dec_key
201            .open_in_place(nonce, aad, payload)
202            .map_err(|_| Error::DecryptError)?
203            .len();
204
205        payload.truncate(plain_len);
206
207        if payload.len() > MAX_FRAGMENT_LEN + 1 {
208            return Err(Error::PeerSentOversizedRecord);
209        }
210
211        msg.typ = unpad_tls13(payload);
212        if msg.typ == ContentType::Unknown(0) {
213            let msg = "peer sent bad TLSInnerPlaintext".to_string();
214            return Err(Error::PeerMisbehavedError(msg));
215        }
216
217        if payload.len() > MAX_FRAGMENT_LEN {
218            return Err(Error::PeerSentOversizedRecord);
219        }
220
221        msg.version = ProtocolVersion::TLSv1_3;
222        Ok(msg.into_plain_message())
223    }
224}