amebazii/types/image/
mod.rs

1use super::{FromStream, ToStream};
2use crate::error::Error;
3use std::io;
4
5pub mod boot;
6pub use boot::BootImage;
7
8pub mod ota;
9pub use ota::{OTAImage, SubImage};
10
11pub mod pt;
12pub use pt::{PartTab, PartitionTableImage, Record, TrapConfig};
13
14pub type RawImage = Vec<u8>;
15
16/// A generic enum representing either encrypted or plain data.
17///
18/// The `EncryptedOr` enum is used to differentiate between encrypted data and unencrypted (plain) data.
19/// It allows to store either type of data in the same structure while providing methods to safely access
20/// or mutate the contents, depending on whether the data is encrypted or not.
21#[derive(Debug)]
22pub enum EncryptedOr<T> {
23    /// Contains encrypted data as a vector of bytes.
24    Encrypted(Vec<u8>),
25
26    /// Contains plain, unencrypted data of type `T`.
27    Plain(T),
28}
29
30impl<T> AsRef<T> for EncryptedOr<T> {
31    /// Returns a reference to the plain data if available.
32    ///
33    /// # Panics
34    /// Panics if the data is encrypted, as the method expects plain data.
35    fn as_ref(&self) -> &T {
36        match self {
37            EncryptedOr::Encrypted(_) => {
38                panic!("Cannot get reference to encrypted data when plain is expected")
39            }
40            EncryptedOr::Plain(t) => t,
41        }
42    }
43}
44
45impl<T> AsRef<[u8]> for EncryptedOr<T> {
46    /// Returns a reference to the encrypted data if available.
47    ///
48    /// # Panics
49    /// Panics if the data is plain, as the method expects encrypted data.
50    fn as_ref(&self) -> &[u8] {
51        match self {
52            EncryptedOr::Encrypted(v) => v,
53            EncryptedOr::Plain(_) => {
54                panic!("Cannot get reference to plain data when encrypted is expected")
55            }
56        }
57    }
58}
59
60impl<T> EncryptedOr<T> {
61    /// Returns `true` if the data is encrypted.
62    ///
63    /// This method allows checking if the current instance of `EncryptedOr` contains encrypted data.
64    pub fn is_encrypted(&self) -> bool {
65        match self {
66            EncryptedOr::Encrypted(_) => true,
67            EncryptedOr::Plain(_) => false,
68        }
69    }
70
71    /// Returns `true` if the data is plain.
72    ///
73    /// This method allows checking if the current instance of `EncryptedOr` contains plain (unencrypted) data.
74    pub fn is_plain(&self) -> bool {
75        match self {
76            EncryptedOr::Encrypted(_) => false,
77            EncryptedOr::Plain(_) => true,
78        }
79    }
80
81    pub fn unwrap(self) -> T {
82        match self {
83            EncryptedOr::Encrypted(_) => panic!("Attempted to unwrap encrypted data"),
84            EncryptedOr::Plain(t) => t,
85        }
86    }
87}
88
89impl<T> AsMut<T> for EncryptedOr<T> {
90    /// Returns a mutable reference to the plain data if available.
91    ///
92    /// # Panics
93    /// Panics if the data is encrypted, as the method expects plain data.
94    fn as_mut(&mut self) -> &mut T {
95        match self {
96            EncryptedOr::Encrypted(_) => {
97                panic!("Cannot get mutable reference to encrypted data when plain is expected")
98            }
99            EncryptedOr::Plain(t) => t,
100        }
101    }
102}
103
104impl<T> AsMut<[u8]> for EncryptedOr<T> {
105    /// Returns a mutable reference to the encrypted data if available.
106    ///
107    /// # Panics
108    /// Panics if the data is plain, as the method expects encrypted data.
109    fn as_mut(&mut self) -> &mut [u8] {
110        match self {
111            EncryptedOr::Encrypted(v) => v,
112            EncryptedOr::Plain(_) => {
113                panic!("Cannot get mutable reference to encrypted data when plain is expected")
114            }
115        }
116    }
117}
118
119impl<T: ToStream> ToStream for EncryptedOr<T> {
120    /// Writes the data to a stream, either encrypted or plain.
121    ///
122    /// This method is used to serialize the data into a stream. If the data is encrypted, it writes the encrypted byte vector,
123    /// otherwise it serializes the plain data of type `T`.
124    fn write_to<W>(&self, writer: &mut W) -> Result<(), Error>
125    where
126        W: io::Write + io::Seek,
127    {
128        match self {
129            EncryptedOr::Encrypted(v) => writer.write_all(v)?,
130            EncryptedOr::Plain(t) => return t.write_to(writer),
131        }
132        Ok(())
133    }
134}
135
136impl<T: ToStream> ToStream for EncryptedOr<Vec<T>> {
137    fn write_to<W>(&self, writer: &mut W) -> Result<(), Error>
138    where
139        W: io::Write + io::Seek,
140    {
141        match self {
142            EncryptedOr::Encrypted(v) => writer.write_all(v)?,
143            EncryptedOr::Plain(t) => {
144                for item in t {
145                    item.write_to(writer)?;
146                }
147            }
148        }
149        Ok(())
150    }
151}
152
153impl<T: FromStream> FromStream for EncryptedOr<T> {
154    /// Reads the data from a stream, either encrypted or plain.
155    ///
156    /// This method deserializes the data from a stream. If the data is encrypted, it reads the encrypted byte vector,
157    /// otherwise it reads the plain data of type `T`.
158    fn read_from<R>(&mut self, reader: &mut R) -> Result<(), Error>
159    where
160        R: io::Read + io::Seek,
161    {
162        match self {
163            EncryptedOr::Encrypted(v) => reader.read_exact(v)?,
164            EncryptedOr::Plain(t) => return t.read_from(reader),
165        }
166        Ok(())
167    }
168}
169
170/// A trait that provides common functionality for image-like objects,
171/// such as computing and setting the segment size and signature.
172pub trait AsImage {
173    /// Computes the segment size for the image.
174    ///
175    /// The segment size typically represents the total size of the image segment,
176    /// including all of its components (e.g., header, records, user data, etc.).
177    ///
178    /// # Returns:
179    /// - `u32` representing the segment size.
180    ///
181    /// # Example:
182    /// ```rust
183    /// let segment_size = image.build_segment_size();
184    /// ```
185    fn build_segment_size(&self) -> u32;
186
187    /// Sets the segment size for the image.
188    ///
189    /// This method allows setting the segment size, typically after calculating
190    /// it or modifying the image in some way.
191    ///
192    /// # Arguments:
193    /// - `size`: The new segment size to set.
194    ///
195    /// # Example:
196    /// ```rust
197    /// image.set_segment_size(1024);
198    /// ```
199    fn set_segment_size(&mut self, size: u32);
200
201    /// Computes the signature for the image using the provided key.
202    ///
203    /// The signature is usually a hash or HMAC generated from the image data and
204    /// a secret key, often used for verification or authentication purposes.
205    ///
206    /// # Arguments:
207    /// - `key`: The key used to compute the signature.
208    ///
209    /// # Returns:
210    /// - `Result<Vec<u8>, crate::error::Error>`: The signature as a `Vec<u8>`, or an error.
211    ///
212    /// # Example:
213    /// ```rust
214    /// let signature = image.build_signature(&key);
215    /// ```
216    fn build_signature(&self, key: Option<&[u8]>) -> Result<Vec<u8>, crate::error::Error>;
217
218    /// Sets the signature for the image.
219    ///
220    /// This method allows setting the signature after computing it or for some
221    /// validation process.
222    ///
223    /// # Arguments:
224    /// - `signature`: The computed signature to set.
225    ///
226    /// # Example:
227    /// ```rust
228    /// image.set_signature(&signature);
229    /// ```
230    fn set_signature(&mut self, signature: &[u8]);
231}
232
233/// Builds the signature for a given image.
234///
235/// This function uses the `build_signature` method from the `AsImage` trait to generate
236/// the signature for the image using the provided key.
237///
238/// # Arguments:
239/// - `image`: The image-like object that implements `AsImage`.
240/// - `key`: The key used to compute the signature.
241///
242/// # Returns:
243/// - `Result<Vec<u8>, crate::error::Error>`: The computed signature.
244pub fn build_default_signature<I>(
245    image: &I,
246    key: Option<&[u8]>,
247) -> Result<Vec<u8>, crate::error::Error>
248where
249    I: AsImage,
250{
251    image.build_signature(key)
252}
253
254/// Sets the signature for a given image.
255///
256/// This function computes the signature using `build_default_signature` and then sets
257/// the signature for the image using `set_signature`.
258///
259/// # Arguments:
260/// - `image`: The image-like object that implements `AsImage`.
261/// - `key`: The key used to compute the signature.
262///
263/// # Returns:
264/// - `Result<(), crate::error::Error>`: An empty result on success, or an error.
265pub fn set_default_signature<I>(
266    image: &mut I,
267    key: Option<&[u8]>,
268) -> Result<(), crate::error::Error>
269where
270    I: AsImage,
271{
272    let signature = build_default_signature(image, key)?;
273    image.set_signature(&signature);
274    Ok(())
275}
276
277/// Builds the segment size for a given image.
278///
279/// # Arguments:
280/// - `image`: The image-like object that implements `AsImage`.
281///
282/// # Returns:
283/// - `u32`: The computed segment size.
284pub fn build_segment_size<I>(image: &I) -> u32
285where
286    I: AsImage,
287{
288    image.build_segment_size()
289}
290
291/// Sets the segment size for a given image.
292///
293/// # Arguments:
294/// - `image`: The image-like object that implements `AsImage`.
295///
296/// # Returns:
297/// - `()`: An empty result on success.
298pub fn set_default_segment_size<I>(image: &mut I)
299where
300    I: AsImage,
301{
302    image.set_segment_size(image.build_segment_size())
303}