ssh_encoding/
reader.rs

1//! Reader trait and associated implementations.
2
3use crate::{decode::Decode, Error, Result};
4use core::str;
5
6/// Constant-time Base64 reader implementation.
7#[cfg(feature = "base64")]
8pub type Base64Reader<'i> = base64::Decoder<'i, base64::Base64>;
9
10/// Reader trait which decodes the binary SSH protocol serialization from
11/// various inputs.
12pub trait Reader: Sized {
13    /// Read as much data as is needed to exactly fill `out`.
14    ///
15    /// This is the base decoding method on which the rest of the trait is
16    /// implemented in terms of.
17    ///
18    /// # Returns
19    /// - `Ok(bytes)` if the expected amount of data was read
20    /// - `Err(Error::Length)` if the exact amount of data couldn't be read
21    fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]>;
22
23    /// Get the length of the remaining data after Base64 decoding.
24    fn remaining_len(&self) -> usize;
25
26    /// Is decoding finished?
27    fn is_finished(&self) -> bool {
28        self.remaining_len() == 0
29    }
30
31    /// Decode length-prefixed data.
32    ///
33    /// Decodes a `uint32` which identifies the length of some encapsulated
34    /// data, then calls the given reader function with the length of the
35    /// remaining data.
36    fn read_prefixed<'r, T, E, F>(&'r mut self, f: F) -> core::result::Result<T, E>
37    where
38        E: From<Error>,
39        F: FnOnce(&mut NestedReader<'r, Self>) -> core::result::Result<T, E>,
40    {
41        let len = usize::decode(self)?;
42
43        f(&mut NestedReader {
44            inner: self,
45            remaining_len: len,
46        })
47    }
48
49    /// Decodes `[u8]` from `byte[n]` as described in [RFC4251 § 5]:
50    ///
51    /// > A byte represents an arbitrary 8-bit value (octet).  Fixed length
52    /// > data is sometimes represented as an array of bytes, written
53    /// > `byte[n]`, where n is the number of bytes in the array.
54    ///
55    /// Storage for the byte array must be provided as mutable byte slice in
56    /// order to accommodate `no_std` use cases.
57    ///
58    /// The [`Decode`] impl on `Vec<u8>` can be used to allocate a buffer for
59    /// the result.
60    ///
61    /// [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
62    fn read_byten<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
63        self.read_prefixed(|reader| {
64            let slice = out.get_mut(..reader.remaining_len()).ok_or(Error::Length)?;
65            reader.read(slice)?;
66            Ok(slice as &[u8])
67        })
68    }
69
70    /// Decode a `string` as described in [RFC4251 § 5]:
71    ///
72    /// > Arbitrary length binary string.  Strings are allowed to contain
73    /// > arbitrary binary data, including null characters and 8-bit
74    /// > characters.  They are stored as a uint32 containing its length
75    /// > (number of bytes that follow) and zero (= empty string) or more
76    /// > bytes that are the value of the string.  Terminating null
77    /// > characters are not used.
78    /// >
79    /// > Strings are also used to store text.  In that case, US-ASCII is
80    /// > used for internal names, and ISO-10646 UTF-8 for text that might
81    /// > be displayed to the user.  The terminating null character SHOULD
82    /// > NOT normally be stored in the string.  For example: the US-ASCII
83    /// > string "testing" is represented as 00 00 00 07 t e s t i n g.  The
84    /// > UTF-8 mapping does not alter the encoding of US-ASCII characters.
85    ///
86    /// Storage for the string data must be provided as mutable byte slice in
87    /// order to accommodate `no_std` use cases.
88    ///
89    /// The [`Decode`] impl on `String` can be used to allocate a buffer for
90    /// the result.
91    ///
92    /// [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
93    fn read_string<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o str> {
94        Ok(str::from_utf8(self.read_byten(buf)?)?)
95    }
96
97    /// Drain the given number of bytes from the reader, discarding them.
98    fn drain(&mut self, n_bytes: usize) -> Result<()> {
99        let mut byte = [0];
100        for _ in 0..n_bytes {
101            self.read(&mut byte)?;
102        }
103        Ok(())
104    }
105
106    /// Decode a `u32` length prefix, and then drain the length of the body.
107    ///
108    /// Upon success, returns the number of bytes drained sans the length of
109    /// the `u32` length prefix (4-bytes).
110    fn drain_prefixed(&mut self) -> Result<usize> {
111        self.read_prefixed(|reader| {
112            let len = reader.remaining_len();
113            reader.drain(len)?;
114            Ok(len)
115        })
116    }
117
118    /// Finish decoding, returning the given value if there is no remaining
119    /// data, or an error otherwise.
120    fn finish<T>(self, value: T) -> Result<T> {
121        if self.is_finished() {
122            Ok(value)
123        } else {
124            Err(Error::TrailingData {
125                remaining: self.remaining_len(),
126            })
127        }
128    }
129}
130
131impl Reader for &[u8] {
132    fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
133        if self.len() >= out.len() {
134            let (head, tail) = self.split_at(out.len());
135            *self = tail;
136            out.copy_from_slice(head);
137            Ok(out)
138        } else {
139            Err(Error::Length)
140        }
141    }
142
143    fn remaining_len(&self) -> usize {
144        self.len()
145    }
146}
147
148#[cfg(feature = "base64")]
149impl Reader for Base64Reader<'_> {
150    fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
151        Ok(self.decode(out)?)
152    }
153
154    fn remaining_len(&self) -> usize {
155        self.remaining_len()
156    }
157}
158
159#[cfg(feature = "pem")]
160impl Reader for pem::Decoder<'_> {
161    fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
162        Ok(self.decode(out)?)
163    }
164
165    fn remaining_len(&self) -> usize {
166        self.remaining_len()
167    }
168}
169
170/// Reader type used by [`Reader::read_prefixed`].
171pub struct NestedReader<'r, R: Reader> {
172    /// Inner reader type.
173    inner: &'r mut R,
174
175    /// Remaining length in the prefixed reader.
176    remaining_len: usize,
177}
178
179impl<'r, R: Reader> Reader for NestedReader<'r, R> {
180    fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
181        let remaining_len = self
182            .remaining_len
183            .checked_sub(out.len())
184            .ok_or(Error::Length)?;
185
186        let ret = self.inner.read(out)?;
187        self.remaining_len = remaining_len;
188        Ok(ret)
189    }
190
191    fn remaining_len(&self) -> usize {
192        self.remaining_len
193    }
194}