Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/rustls-0.23.22/src/msgs/codec.rs
Line
Count
Source (jump to first uncovered line)
1
use alloc::vec::Vec;
2
use core::fmt::Debug;
3
4
use crate::error::InvalidMessage;
5
6
/// Wrapper over a slice of bytes that allows reading chunks from
7
/// with the current position state held using a cursor.
8
///
9
/// A new reader for a sub section of the buffer can be created
10
/// using the `sub` function or a section of a certain length can
11
/// be obtained using the `take` function
12
pub struct Reader<'a> {
13
    /// The underlying buffer storing the readers content
14
    buffer: &'a [u8],
15
    /// Stores the current reading position for the buffer
16
    cursor: usize,
17
}
18
19
impl<'a> Reader<'a> {
20
    /// Creates a new Reader of the provided `bytes` slice with
21
    /// the initial cursor position of zero.
22
0
    pub fn init(bytes: &'a [u8]) -> Self {
23
0
        Reader {
24
0
            buffer: bytes,
25
0
            cursor: 0,
26
0
        }
27
0
    }
28
29
    /// Attempts to create a new Reader on a sub section of this
30
    /// readers bytes by taking a slice of the provided `length`
31
    /// will return None if there is not enough bytes
32
0
    pub fn sub(&mut self, length: usize) -> Result<Self, InvalidMessage> {
33
0
        match self.take(length) {
34
0
            Some(bytes) => Ok(Reader::init(bytes)),
35
0
            None => Err(InvalidMessage::MessageTooShort),
36
        }
37
0
    }
38
39
    /// Borrows a slice of all the remaining bytes
40
    /// that appear after the cursor position.
41
    ///
42
    /// Moves the cursor to the end of the buffer length.
43
0
    pub fn rest(&mut self) -> &'a [u8] {
44
0
        let rest = &self.buffer[self.cursor..];
45
0
        self.cursor = self.buffer.len();
46
0
        rest
47
0
    }
48
49
    /// Attempts to borrow a slice of bytes from the current
50
    /// cursor position of `length` if there is not enough
51
    /// bytes remaining after the cursor to take the length
52
    /// then None is returned instead.
53
0
    pub fn take(&mut self, length: usize) -> Option<&'a [u8]> {
54
0
        if self.left() < length {
55
0
            return None;
56
0
        }
57
0
        let current = self.cursor;
58
0
        self.cursor += length;
59
0
        Some(&self.buffer[current..current + length])
60
0
    }
61
62
    /// Used to check whether the reader has any content left
63
    /// after the cursor (cursor has not reached end of buffer)
64
0
    pub fn any_left(&self) -> bool {
65
0
        self.cursor < self.buffer.len()
66
0
    }
67
68
0
    pub fn expect_empty(&self, name: &'static str) -> Result<(), InvalidMessage> {
69
0
        match self.any_left() {
70
0
            true => Err(InvalidMessage::TrailingData(name)),
71
0
            false => Ok(()),
72
        }
73
0
    }
74
75
    /// Returns the cursor position which is also the number
76
    /// of bytes that have been read from the buffer.
77
0
    pub fn used(&self) -> usize {
78
0
        self.cursor
79
0
    }
80
81
    /// Returns the number of bytes that are still able to be
82
    /// read (The number of remaining takes)
83
0
    pub fn left(&self) -> usize {
84
0
        self.buffer.len() - self.cursor
85
0
    }
86
}
87
88
/// Trait for implementing encoding and decoding functionality
89
/// on something.
90
pub trait Codec<'a>: Debug + Sized {
91
    /// Function for encoding itself by appending itself to
92
    /// the provided vec of bytes.
93
    fn encode(&self, bytes: &mut Vec<u8>);
94
95
    /// Function for decoding itself from the provided reader
96
    /// will return Some if the decoding was successful or
97
    /// None if it was not.
98
    fn read(_: &mut Reader<'a>) -> Result<Self, InvalidMessage>;
99
100
    /// Convenience function for encoding the implementation
101
    /// into a vec and returning it
102
0
    fn get_encoding(&self) -> Vec<u8> {
103
0
        let mut bytes = Vec::new();
104
0
        self.encode(&mut bytes);
105
0
        bytes
106
0
    }
Unexecuted instantiation: <rustls::msgs::handshake::ClientHelloPayload as rustls::msgs::codec::Codec>::get_encoding
Unexecuted instantiation: <rustls::msgs::handshake::CertificatePayloadTls13 as rustls::msgs::codec::Codec>::get_encoding
Unexecuted instantiation: <rustls::msgs::handshake::HandshakeMessagePayload as rustls::msgs::codec::Codec>::get_encoding
Unexecuted instantiation: <rustls::msgs::handshake::Random as rustls::msgs::codec::Codec>::get_encoding
Unexecuted instantiation: <rustls::msgs::persist::ServerSessionValue as rustls::msgs::codec::Codec>::get_encoding
107
108
    /// Function for wrapping a call to the read function in
109
    /// a Reader for the slice of bytes provided
110
    ///
111
    /// Returns `Err(InvalidMessage::ExcessData(_))` if
112
    /// `Self::read` does not read the entirety of `bytes`.
113
0
    fn read_bytes(bytes: &'a [u8]) -> Result<Self, InvalidMessage> {
114
0
        let mut reader = Reader::init(bytes);
115
0
        Self::read(&mut reader).and_then(|r| {
116
0
            reader.expect_empty("read_bytes")?;
117
0
            Ok(r)
118
0
        })
Unexecuted instantiation: <rustls::msgs::codec::u24 as rustls::msgs::codec::Codec>::read_bytes::{closure#0}
Unexecuted instantiation: <rustls::msgs::persist::ServerSessionValue as rustls::msgs::codec::Codec>::read_bytes::{closure#0}
119
0
    }
Unexecuted instantiation: <rustls::msgs::codec::u24 as rustls::msgs::codec::Codec>::read_bytes
Unexecuted instantiation: <rustls::msgs::persist::ServerSessionValue as rustls::msgs::codec::Codec>::read_bytes
120
}
121
122
impl Codec<'_> for u8 {
123
0
    fn encode(&self, bytes: &mut Vec<u8>) {
124
0
        bytes.push(*self);
125
0
    }
126
127
0
    fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
128
0
        match r.take(1) {
129
0
            Some(&[byte]) => Ok(byte),
130
0
            _ => Err(InvalidMessage::MissingData("u8")),
131
        }
132
0
    }
133
}
134
135
0
pub(crate) fn put_u16(v: u16, out: &mut [u8]) {
136
0
    let out: &mut [u8; 2] = (&mut out[..2]).try_into().unwrap();
137
0
    *out = u16::to_be_bytes(v);
138
0
}
139
140
impl Codec<'_> for u16 {
141
0
    fn encode(&self, bytes: &mut Vec<u8>) {
142
0
        let mut b16 = [0u8; 2];
143
0
        put_u16(*self, &mut b16);
144
0
        bytes.extend_from_slice(&b16);
145
0
    }
146
147
0
    fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
148
0
        match r.take(2) {
149
0
            Some(&[b1, b2]) => Ok(Self::from_be_bytes([b1, b2])),
150
0
            _ => Err(InvalidMessage::MissingData("u16")),
151
        }
152
0
    }
153
}
154
155
// Make a distinct type for u24, even though it's a u32 underneath
156
#[allow(non_camel_case_types)]
157
#[derive(Debug, Copy, Clone)]
158
pub struct u24(pub u32);
159
160
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
161
impl From<u24> for usize {
162
    #[inline]
163
0
    fn from(v: u24) -> Self {
164
0
        v.0 as Self
165
0
    }
166
}
167
168
impl Codec<'_> for u24 {
169
0
    fn encode(&self, bytes: &mut Vec<u8>) {
170
0
        let be_bytes = u32::to_be_bytes(self.0);
171
0
        bytes.extend_from_slice(&be_bytes[1..]);
172
0
    }
173
174
0
    fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
175
0
        match r.take(3) {
176
0
            Some(&[a, b, c]) => Ok(Self(u32::from_be_bytes([0, a, b, c]))),
177
0
            _ => Err(InvalidMessage::MissingData("u24")),
178
        }
179
0
    }
180
}
181
182
impl Codec<'_> for u32 {
183
0
    fn encode(&self, bytes: &mut Vec<u8>) {
184
0
        bytes.extend(Self::to_be_bytes(*self));
185
0
    }
186
187
0
    fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
188
0
        match r.take(4) {
189
0
            Some(&[a, b, c, d]) => Ok(Self::from_be_bytes([a, b, c, d])),
190
0
            _ => Err(InvalidMessage::MissingData("u32")),
191
        }
192
0
    }
193
}
194
195
0
pub(crate) fn put_u64(v: u64, bytes: &mut [u8]) {
196
0
    let bytes: &mut [u8; 8] = (&mut bytes[..8]).try_into().unwrap();
197
0
    *bytes = u64::to_be_bytes(v);
198
0
}
199
200
impl Codec<'_> for u64 {
201
0
    fn encode(&self, bytes: &mut Vec<u8>) {
202
0
        let mut b64 = [0u8; 8];
203
0
        put_u64(*self, &mut b64);
204
0
        bytes.extend_from_slice(&b64);
205
0
    }
206
207
0
    fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
208
0
        match r.take(8) {
209
0
            Some(&[a, b, c, d, e, f, g, h]) => Ok(Self::from_be_bytes([a, b, c, d, e, f, g, h])),
210
0
            _ => Err(InvalidMessage::MissingData("u64")),
211
        }
212
0
    }
213
}
214
215
/// Implement `Codec` for lists of elements that implement `TlsListElement`.
216
///
217
/// `TlsListElement` provides the size of the length prefix for the list.
218
impl<'a, T: Codec<'a> + TlsListElement + Debug> Codec<'a> for Vec<T> {
219
0
    fn encode(&self, bytes: &mut Vec<u8>) {
220
0
        let nest = LengthPrefixedBuffer::new(T::SIZE_LEN, bytes);
221
222
0
        for i in self {
223
0
            i.encode(nest.buf);
224
0
        }
225
0
    }
Unexecuted instantiation: <alloc::vec::Vec<rustls_pki_types::CertificateDer> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::NamedGroup> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::Compression> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ECPointFormat> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ExtensionType> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::CertificateType> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::PSKKeyExchangeMode> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ClientCertificateType> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ServerName> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ResponderId> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ProtocolName> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::KeyShareEntry> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ClientExtension> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ServerExtension> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertReqExtension> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertificateEntry> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::EchConfigPayload> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::DistinguishedName> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::EchConfigExtension> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::PresharedKeyBinder> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::HelloRetryExtension> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertificateExtension> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::PresharedKeyIdentity> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::HpkeSymmetricCipherSuite> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::NewSessionTicketExtension> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::CipherSuite> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::ProtocolVersion> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::SignatureScheme> as rustls::msgs::codec::Codec>::encode
Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::CertificateCompressionAlgorithm> as rustls::msgs::codec::Codec>::encode
226
227
0
    fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
228
0
        let len = match T::SIZE_LEN {
229
0
            ListLength::U8 => usize::from(u8::read(r)?),
230
0
            ListLength::U16 => usize::from(u16::read(r)?),
231
0
            ListLength::U24 { max, error } => match usize::from(u24::read(r)?) {
232
0
                len if len > max => return Err(error),
233
0
                len => len,
234
            },
235
        };
236
237
0
        let mut sub = r.sub(len)?;
238
0
        let mut ret = Self::new();
239
0
        while sub.any_left() {
240
0
            ret.push(T::read(&mut sub)?);
241
        }
242
243
0
        Ok(ret)
244
0
    }
Unexecuted instantiation: <alloc::vec::Vec<rustls_pki_types::CertificateDer> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::NamedGroup> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::Compression> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ECPointFormat> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ExtensionType> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::CertificateType> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::PSKKeyExchangeMode> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ClientCertificateType> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ServerName> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ResponderId> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ProtocolName> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::KeyShareEntry> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ClientExtension> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ServerExtension> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertReqExtension> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertificateEntry> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::EchConfigPayload> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::DistinguishedName> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::EchConfigExtension> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::PresharedKeyBinder> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::HelloRetryExtension> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertificateExtension> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::PresharedKeyIdentity> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::HpkeSymmetricCipherSuite> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::NewSessionTicketExtension> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::CipherSuite> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::ProtocolVersion> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::SignatureScheme> as rustls::msgs::codec::Codec>::read
Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::CertificateCompressionAlgorithm> as rustls::msgs::codec::Codec>::read
245
}
246
247
/// A trait for types that can be encoded and decoded in a list.
248
///
249
/// This trait is used to implement `Codec` for `Vec<T>`. Lists in the TLS wire format are
250
/// prefixed with a length, the size of which depends on the type of the list elements.
251
/// As such, the `Codec` implementation for `Vec<T>` requires an implementation of this trait
252
/// for its element type `T`.
253
pub(crate) trait TlsListElement {
254
    const SIZE_LEN: ListLength;
255
}
256
257
/// The length of the length prefix for a list.
258
///
259
/// The types that appear in lists are limited to three kinds of length prefixes:
260
/// 1, 2, and 3 bytes. For the latter kind, we require a `TlsListElement` implementer
261
/// to specify a maximum length and error if the actual length is larger.
262
pub(crate) enum ListLength {
263
    U8,
264
    U16,
265
    U24 { max: usize, error: InvalidMessage },
266
}
267
268
/// Tracks encoding a length-delimited structure in a single pass.
269
pub(crate) struct LengthPrefixedBuffer<'a> {
270
    pub(crate) buf: &'a mut Vec<u8>,
271
    len_offset: usize,
272
    size_len: ListLength,
273
}
274
275
impl<'a> LengthPrefixedBuffer<'a> {
276
    /// Inserts a dummy length into `buf`, and remembers where it went.
277
    ///
278
    /// After this, the body of the length-delimited structure should be appended to `LengthPrefixedBuffer::buf`.
279
    /// The length header is corrected in `LengthPrefixedBuffer::drop`.
280
0
    pub(crate) fn new(size_len: ListLength, buf: &'a mut Vec<u8>) -> Self {
281
0
        let len_offset = buf.len();
282
0
        buf.extend(match size_len {
283
0
            ListLength::U8 => &[0xff][..],
284
0
            ListLength::U16 => &[0xff, 0xff],
285
0
            ListLength::U24 { .. } => &[0xff, 0xff, 0xff],
286
        });
287
288
0
        Self {
289
0
            buf,
290
0
            len_offset,
291
0
            size_len,
292
0
        }
293
0
    }
294
}
295
296
impl Drop for LengthPrefixedBuffer<'_> {
297
    /// Goes back and corrects the length previously inserted at the start of the structure.
298
0
    fn drop(&mut self) {
299
0
        match self.size_len {
300
            ListLength::U8 => {
301
0
                let len = self.buf.len() - self.len_offset - 1;
302
0
                debug_assert!(len <= 0xff);
303
0
                self.buf[self.len_offset] = len as u8;
304
            }
305
            ListLength::U16 => {
306
0
                let len = self.buf.len() - self.len_offset - 2;
307
0
                debug_assert!(len <= 0xffff);
308
0
                let out: &mut [u8; 2] = (&mut self.buf[self.len_offset..self.len_offset + 2])
309
0
                    .try_into()
310
0
                    .unwrap();
311
0
                *out = u16::to_be_bytes(len as u16);
312
            }
313
            ListLength::U24 { .. } => {
314
0
                let len = self.buf.len() - self.len_offset - 3;
315
0
                debug_assert!(len <= 0xff_ffff);
316
0
                let len_bytes = u32::to_be_bytes(len as u32);
317
0
                let out: &mut [u8; 3] = (&mut self.buf[self.len_offset..self.len_offset + 3])
318
0
                    .try_into()
319
0
                    .unwrap();
320
0
                out.copy_from_slice(&len_bytes[1..]);
321
            }
322
        }
323
0
    }
324
}
325
326
#[cfg(test)]
327
mod tests {
328
    use std::prelude::v1::*;
329
    use std::vec;
330
331
    use super::*;
332
333
    #[test]
334
    fn interrupted_length_prefixed_buffer_leaves_maximum_length() {
335
        let mut buf = Vec::new();
336
        let nested = LengthPrefixedBuffer::new(ListLength::U16, &mut buf);
337
        nested.buf.push(0xaa);
338
        assert_eq!(nested.buf, &vec![0xff, 0xff, 0xaa]);
339
        // <- if the buffer is accidentally read here, there is no possibility
340
        //    that the contents of the length-prefixed buffer are interpreted
341
        //    as a subsequent encoding (perhaps allowing injection of a different
342
        //    extension)
343
        drop(nested);
344
        assert_eq!(buf, vec![0x00, 0x01, 0xaa]);
345
    }
346
}