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}