Coverage Report

Created: 2025-12-31 06:11

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