ssh_encoding/decode.rs
1//! Decoder-side implementation of the SSH protocol's data type representations
2//! as described in [RFC4251 § 5].
3//!
4//! [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
5
6use crate::{reader::Reader, Error, Result};
7
8#[cfg(feature = "alloc")]
9use alloc::{string::String, vec::Vec};
10
11#[cfg(feature = "bytes")]
12use bytes::Bytes;
13
14#[cfg(feature = "pem")]
15use {crate::PEM_LINE_WIDTH, pem::PemLabel};
16
17/// Maximum size of a `usize` this library will accept.
18const MAX_SIZE: usize = 0xFFFFF;
19
20/// Decoding trait.
21///
22/// This trait describes how to decode a given type.
23pub trait Decode: Sized {
24 /// Type returned in the event of a decoding error.
25 type Error: From<Error>;
26
27 /// Attempt to decode a value of this type using the provided [`Reader`].
28 fn decode(reader: &mut impl Reader) -> core::result::Result<Self, Self::Error>;
29}
30
31/// Decoding trait for PEM documents.
32///
33/// This is an extension trait which is auto-impl'd for types which impl the
34/// [`Decode`], [`PemLabel`], and [`Sized`] traits.
35#[cfg(feature = "pem")]
36pub trait DecodePem: Decode + PemLabel + Sized {
37 /// Decode the provided PEM-encoded string, interpreting the Base64-encoded
38 /// body of the document using the [`Decode`] trait.
39 fn decode_pem(pem: impl AsRef<[u8]>) -> core::result::Result<Self, Self::Error>;
40}
41
42#[cfg(feature = "pem")]
43impl<T: Decode + PemLabel + Sized> DecodePem for T {
44 fn decode_pem(pem: impl AsRef<[u8]>) -> core::result::Result<Self, Self::Error> {
45 let mut reader =
46 pem::Decoder::new_wrapped(pem.as_ref(), PEM_LINE_WIDTH).map_err(Error::from)?;
47
48 Self::validate_pem_label(reader.type_label()).map_err(Error::from)?;
49 let ret = Self::decode(&mut reader)?;
50 Ok(reader.finish(ret)?)
51 }
52}
53
54/// Decode a single `byte` from the input data.
55impl Decode for u8 {
56 type Error = Error;
57
58 fn decode(reader: &mut impl Reader) -> Result<Self> {
59 let mut buf = [0];
60 reader.read(&mut buf)?;
61 Ok(buf[0])
62 }
63}
64
65/// Decode a `uint32` as described in [RFC4251 § 5]:
66///
67/// > Represents a 32-bit unsigned integer. Stored as four bytes in the
68/// > order of decreasing significance (network byte order).
69/// > For example: the value 699921578 (0x29b7f4aa) is stored as 29 b7 f4 aa.
70///
71/// [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
72impl Decode for u32 {
73 type Error = Error;
74
75 fn decode(reader: &mut impl Reader) -> Result<Self> {
76 let mut bytes = [0u8; 4];
77 reader.read(&mut bytes)?;
78 Ok(u32::from_be_bytes(bytes))
79 }
80}
81
82/// Decode a `uint64` as described in [RFC4251 § 5]:
83///
84/// > Represents a 64-bit unsigned integer. Stored as eight bytes in
85/// > the order of decreasing significance (network byte order).
86///
87/// [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
88impl Decode for u64 {
89 type Error = Error;
90
91 fn decode(reader: &mut impl Reader) -> Result<Self> {
92 let mut bytes = [0u8; 8];
93 reader.read(&mut bytes)?;
94 Ok(u64::from_be_bytes(bytes))
95 }
96}
97
98/// Decode a `usize`.
99///
100/// Uses [`Decode`] impl on `u32` and then converts to a `usize`, handling
101/// potential overflow if `usize` is smaller than `u32`.
102///
103/// Enforces a library-internal limit of 1048575, as the main use case for
104/// `usize` is length prefixes.
105impl Decode for usize {
106 type Error = Error;
107
108 fn decode(reader: &mut impl Reader) -> Result<Self> {
109 let n = usize::try_from(u32::decode(reader)?)?;
110
111 if n <= MAX_SIZE {
112 Ok(n)
113 } else {
114 Err(Error::Overflow)
115 }
116 }
117}
118
119/// Decodes a byte array from `byte[n]` as described in [RFC4251 § 5]:
120///
121/// > A byte represents an arbitrary 8-bit value (octet). Fixed length
122/// > data is sometimes represented as an array of bytes, written
123/// > `byte[n]`, where n is the number of bytes in the array.
124///
125/// [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
126impl<const N: usize> Decode for [u8; N] {
127 type Error = Error;
128
129 fn decode(reader: &mut impl Reader) -> Result<Self> {
130 reader.read_prefixed(|reader| {
131 let mut result = [(); N].map(|_| 0);
132 reader.read(&mut result)?;
133 Ok(result)
134 })
135 }
136}
137
138/// Decodes `Vec<u8>` from `byte[n]` as described in [RFC4251 § 5]:
139///
140/// > A byte represents an arbitrary 8-bit value (octet). Fixed length
141/// > data is sometimes represented as an array of bytes, written
142/// > `byte[n]`, where n is the number of bytes in the array.
143///
144/// [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
145#[cfg(feature = "alloc")]
146impl Decode for Vec<u8> {
147 type Error = Error;
148
149 fn decode(reader: &mut impl Reader) -> Result<Self> {
150 reader.read_prefixed(|reader| {
151 let mut result = vec![0u8; reader.remaining_len()];
152 reader.read(&mut result)?;
153 Ok(result)
154 })
155 }
156}
157
158#[cfg(feature = "alloc")]
159impl Decode for String {
160 type Error = Error;
161
162 fn decode(reader: &mut impl Reader) -> Result<Self> {
163 String::from_utf8(Vec::decode(reader)?).map_err(|_| Error::CharacterEncoding)
164 }
165}
166
167#[cfg(feature = "alloc")]
168impl Decode for Vec<String> {
169 type Error = Error;
170
171 fn decode(reader: &mut impl Reader) -> Result<Self> {
172 reader.read_prefixed(|reader| {
173 let mut entries = Self::new();
174
175 while !reader.is_finished() {
176 entries.push(String::decode(reader)?);
177 }
178
179 Ok(entries)
180 })
181 }
182}
183
184/// Decodes `Bytes` from `byte[n]` as described in [RFC4251 § 5]:
185///
186/// > A byte represents an arbitrary 8-bit value (octet). Fixed length
187/// > data is sometimes represented as an array of bytes, written
188/// > `byte[n]`, where n is the number of bytes in the array.
189///
190/// [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
191#[cfg(feature = "bytes")]
192impl Decode for Bytes {
193 type Error = Error;
194
195 fn decode(reader: &mut impl Reader) -> Result<Self> {
196 Vec::<u8>::decode(reader).map(Into::into)
197 }
198}