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}