rustls/tls13/
mod.rs

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