rustls/
record_layer.rs

1use crate::cipher::{MessageDecrypter, MessageEncrypter};
2use crate::error::Error;
3use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
4
5#[cfg(feature = "logging")]
6use crate::log::trace;
7
8static SEQ_SOFT_LIMIT: u64 = 0xffff_ffff_ffff_0000u64;
9static SEQ_HARD_LIMIT: u64 = 0xffff_ffff_ffff_fffeu64;
10
11#[derive(PartialEq)]
12enum DirectionState {
13    /// No keying material.
14    Invalid,
15
16    /// Keying material present, but not yet in use.
17    Prepared,
18
19    /// Keying material in use.
20    Active,
21}
22
23/// Record layer that tracks decryption and encryption keys.
24pub struct RecordLayer {
25    message_encrypter: Box<dyn MessageEncrypter>,
26    message_decrypter: Box<dyn MessageDecrypter>,
27    write_seq: u64,
28    read_seq: u64,
29    encrypt_state: DirectionState,
30    decrypt_state: DirectionState,
31
32    // Message encrypted with other keys may be encountered, so failures
33    // should be swallowed by the caller.  This struct tracks the amount
34    // of message size this is allowed for.
35    trial_decryption_len: Option<usize>,
36}
37
38impl RecordLayer {
39    /// Create new record layer with no keys.
40    pub fn new() -> Self {
41        Self {
42            message_encrypter: <dyn MessageEncrypter>::invalid(),
43            message_decrypter: <dyn MessageDecrypter>::invalid(),
44            write_seq: 0,
45            read_seq: 0,
46            encrypt_state: DirectionState::Invalid,
47            decrypt_state: DirectionState::Invalid,
48            trial_decryption_len: None,
49        }
50    }
51
52    pub(crate) fn is_encrypting(&self) -> bool {
53        self.encrypt_state == DirectionState::Active
54    }
55
56    #[cfg(feature = "secret_extraction")]
57    pub(crate) fn write_seq(&self) -> u64 {
58        self.write_seq
59    }
60
61    #[cfg(feature = "secret_extraction")]
62    pub(crate) fn read_seq(&self) -> u64 {
63        self.read_seq
64    }
65
66    fn doing_trial_decryption(&mut self, requested: usize) -> bool {
67        match self
68            .trial_decryption_len
69            .and_then(|value| value.checked_sub(requested))
70        {
71            Some(remaining) => {
72                self.trial_decryption_len = Some(remaining);
73                true
74            }
75            _ => false,
76        }
77    }
78
79    /// Prepare to use the given `MessageEncrypter` for future message encryption.
80    /// It is not used until you call `start_encrypting`.
81    pub(crate) fn prepare_message_encrypter(&mut self, cipher: Box<dyn MessageEncrypter>) {
82        self.message_encrypter = cipher;
83        self.write_seq = 0;
84        self.encrypt_state = DirectionState::Prepared;
85    }
86
87    /// Prepare to use the given `MessageDecrypter` for future message decryption.
88    /// It is not used until you call `start_decrypting`.
89    pub(crate) fn prepare_message_decrypter(&mut self, cipher: Box<dyn MessageDecrypter>) {
90        self.message_decrypter = cipher;
91        self.read_seq = 0;
92        self.decrypt_state = DirectionState::Prepared;
93    }
94
95    /// Start using the `MessageEncrypter` previously provided to the previous
96    /// call to `prepare_message_encrypter`.
97    pub(crate) fn start_encrypting(&mut self) {
98        debug_assert!(self.encrypt_state == DirectionState::Prepared);
99        self.encrypt_state = DirectionState::Active;
100    }
101
102    /// Start using the `MessageDecrypter` previously provided to the previous
103    /// call to `prepare_message_decrypter`.
104    pub(crate) fn start_decrypting(&mut self) {
105        debug_assert!(self.decrypt_state == DirectionState::Prepared);
106        self.decrypt_state = DirectionState::Active;
107    }
108
109    /// Set and start using the given `MessageEncrypter` for future outgoing
110    /// message encryption.
111    pub(crate) fn set_message_encrypter(&mut self, cipher: Box<dyn MessageEncrypter>) {
112        self.prepare_message_encrypter(cipher);
113        self.start_encrypting();
114    }
115
116    /// Set and start using the given `MessageDecrypter` for future incoming
117    /// message decryption.
118    pub(crate) fn set_message_decrypter(&mut self, cipher: Box<dyn MessageDecrypter>) {
119        self.prepare_message_decrypter(cipher);
120        self.start_decrypting();
121        self.trial_decryption_len = None;
122    }
123
124    /// Set and start using the given `MessageDecrypter` for future incoming
125    /// message decryption, and enable "trial decryption" mode for when TLS1.3
126    /// 0-RTT is attempted but rejected by the server.
127    pub(crate) fn set_message_decrypter_with_trial_decryption(
128        &mut self,
129        cipher: Box<dyn MessageDecrypter>,
130        max_length: usize,
131    ) {
132        self.prepare_message_decrypter(cipher);
133        self.start_decrypting();
134        self.trial_decryption_len = Some(max_length);
135    }
136
137    pub(crate) fn finish_trial_decryption(&mut self) {
138        self.trial_decryption_len = None;
139    }
140
141    /// Return true if we are getting close to encrypting too many
142    /// messages with our encryption key.
143    pub(crate) fn wants_close_before_encrypt(&self) -> bool {
144        self.write_seq == SEQ_SOFT_LIMIT
145    }
146
147    /// Return true if we outright refuse to do anything with the
148    /// encryption key.
149    pub(crate) fn encrypt_exhausted(&self) -> bool {
150        self.write_seq >= SEQ_HARD_LIMIT
151    }
152
153    /// Decrypt a TLS message.
154    ///
155    /// `encr` is a decoded message allegedly received from the peer.
156    /// If it can be decrypted, its decryption is returned.  Otherwise,
157    /// an error is returned.
158    pub(crate) fn decrypt_incoming(
159        &mut self,
160        encr: OpaqueMessage,
161    ) -> Result<Option<Decrypted>, Error> {
162        if self.decrypt_state != DirectionState::Active {
163            return Ok(Some(Decrypted {
164                want_close_before_decrypt: false,
165                plaintext: encr.into_plain_message(),
166            }));
167        }
168
169        // Set to `true` if the peer appears to getting close to encrypting
170        // too many messages with this key.
171        //
172        // Perhaps if we send an alert well before their counter wraps, a
173        // buggy peer won't make a terrible mistake here?
174        //
175        // Note that there's no reason to refuse to decrypt: the security
176        // failure has already happened.
177        let want_close_before_decrypt = self.read_seq == SEQ_SOFT_LIMIT;
178
179        let encrypted_len = encr.payload.0.len();
180        match self
181            .message_decrypter
182            .decrypt(encr, self.read_seq)
183        {
184            Ok(plaintext) => {
185                self.read_seq += 1;
186                Ok(Some(Decrypted {
187                    want_close_before_decrypt,
188                    plaintext,
189                }))
190            }
191            Err(Error::DecryptError) if self.doing_trial_decryption(encrypted_len) => {
192                trace!("Dropping undecryptable message after aborted early_data");
193                Ok(None)
194            }
195            Err(err) => Err(err),
196        }
197    }
198
199    /// Encrypt a TLS message.
200    ///
201    /// `plain` is a TLS message we'd like to send.  This function
202    /// panics if the requisite keying material hasn't been established yet.
203    pub(crate) fn encrypt_outgoing(&mut self, plain: BorrowedPlainMessage) -> OpaqueMessage {
204        debug_assert!(self.encrypt_state == DirectionState::Active);
205        assert!(!self.encrypt_exhausted());
206        let seq = self.write_seq;
207        self.write_seq += 1;
208        self.message_encrypter
209            .encrypt(plain, seq)
210            .unwrap()
211    }
212}
213
214/// Result of decryption.
215#[derive(Debug)]
216pub struct Decrypted {
217    /// Whether the peer appears to be getting close to encrypting too many messages with this key.
218    pub want_close_before_decrypt: bool,
219    /// The decrypted message.
220    pub plaintext: PlainMessage,
221}