ssh_encoding/
reader.rs

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