1*60b67249SAndroid Build Coastguard Worker // Copyright 2024 Google LLC 2*60b67249SAndroid Build Coastguard Worker // 3*60b67249SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4*60b67249SAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of 5*60b67249SAndroid Build Coastguard Worker // the License at 6*60b67249SAndroid Build Coastguard Worker // 7*60b67249SAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*60b67249SAndroid Build Coastguard Worker // 9*60b67249SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*60b67249SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11*60b67249SAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12*60b67249SAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under 13*60b67249SAndroid Build Coastguard Worker // the License. 14*60b67249SAndroid Build Coastguard Worker 15*60b67249SAndroid Build Coastguard Worker //! Types and functions to help with memory buffer management. 16*60b67249SAndroid Build Coastguard Worker 17*60b67249SAndroid Build Coastguard Worker use crate::constants::*; 18*60b67249SAndroid Build Coastguard Worker use crate::error::{DpeResult, ErrCode}; 19*60b67249SAndroid Build Coastguard Worker use heapless::Vec; 20*60b67249SAndroid Build Coastguard Worker use zeroize::ZeroizeOnDrop; 21*60b67249SAndroid Build Coastguard Worker 22*60b67249SAndroid Build Coastguard Worker /// Creates a byte array wrapper type for the sake of precise typing. 23*60b67249SAndroid Build Coastguard Worker #[macro_export] 24*60b67249SAndroid Build Coastguard Worker macro_rules! byte_array_wrapper { 25*60b67249SAndroid Build Coastguard Worker ($type_name:ident, $len:ident, $desc:expr) => { 26*60b67249SAndroid Build Coastguard Worker #[doc = "A byte array wrapper to represent a "] 27*60b67249SAndroid Build Coastguard Worker #[doc = $desc] 28*60b67249SAndroid Build Coastguard Worker #[doc = "."] 29*60b67249SAndroid Build Coastguard Worker #[derive(Clone, Debug, Eq, PartialEq, Hash, ZeroizeOnDrop)] 30*60b67249SAndroid Build Coastguard Worker pub struct $type_name([u8; $len]); 31*60b67249SAndroid Build Coastguard Worker impl $type_name { 32*60b67249SAndroid Build Coastguard Worker #[doc = "Returns the length of the array."] 33*60b67249SAndroid Build Coastguard Worker pub fn len(&self) -> usize { 34*60b67249SAndroid Build Coastguard Worker self.0.len() 35*60b67249SAndroid Build Coastguard Worker } 36*60b67249SAndroid Build Coastguard Worker 37*60b67249SAndroid Build Coastguard Worker #[doc = "Whether the array is empty."] 38*60b67249SAndroid Build Coastguard Worker pub fn is_empty(&self) -> bool { 39*60b67249SAndroid Build Coastguard Worker self.0.is_empty() 40*60b67249SAndroid Build Coastguard Worker } 41*60b67249SAndroid Build Coastguard Worker 42*60b67249SAndroid Build Coastguard Worker #[doc = "Borrows the array as a slice."] 43*60b67249SAndroid Build Coastguard Worker pub fn as_slice(&self) -> &[u8] { 44*60b67249SAndroid Build Coastguard Worker self.0.as_slice() 45*60b67249SAndroid Build Coastguard Worker } 46*60b67249SAndroid Build Coastguard Worker 47*60b67249SAndroid Build Coastguard Worker #[doc = "Mutably borrows the array as a slice."] 48*60b67249SAndroid Build Coastguard Worker pub fn as_mut_slice(&mut self) -> &mut [u8] { 49*60b67249SAndroid Build Coastguard Worker &mut self.0 50*60b67249SAndroid Build Coastguard Worker } 51*60b67249SAndroid Build Coastguard Worker 52*60b67249SAndroid Build Coastguard Worker #[doc = "Borrows the array."] 53*60b67249SAndroid Build Coastguard Worker pub fn as_array(&self) -> &[u8; $len] { 54*60b67249SAndroid Build Coastguard Worker &self.0 55*60b67249SAndroid Build Coastguard Worker } 56*60b67249SAndroid Build Coastguard Worker 57*60b67249SAndroid Build Coastguard Worker #[doc = "Creates a "] 58*60b67249SAndroid Build Coastguard Worker #[doc = stringify!($type_name)] 59*60b67249SAndroid Build Coastguard Worker #[doc = " from a slice. Fails if the slice length is not "] 60*60b67249SAndroid Build Coastguard Worker #[doc = stringify!($len)] 61*60b67249SAndroid Build Coastguard Worker #[doc = "."] 62*60b67249SAndroid Build Coastguard Worker pub fn from_slice(s: &[u8]) -> DpeResult<Self> { 63*60b67249SAndroid Build Coastguard Worker Self::try_from(s) 64*60b67249SAndroid Build Coastguard Worker } 65*60b67249SAndroid Build Coastguard Worker 66*60b67249SAndroid Build Coastguard Worker #[doc = "Creates a "] 67*60b67249SAndroid Build Coastguard Worker #[doc = stringify!($type_name)] 68*60b67249SAndroid Build Coastguard Worker #[doc = " from a slice infallibly. If the length of the slice is less than "] 69*60b67249SAndroid Build Coastguard Worker #[doc = stringify!($len)] 70*60b67249SAndroid Build Coastguard Worker #[doc = ", the remainder of the array is the default value. If the length "] 71*60b67249SAndroid Build Coastguard Worker #[doc = "of the slice is more than "] 72*60b67249SAndroid Build Coastguard Worker #[doc = stringify!($len)] 73*60b67249SAndroid Build Coastguard Worker #[doc = ", only the first "] 74*60b67249SAndroid Build Coastguard Worker #[doc = stringify!($len)] 75*60b67249SAndroid Build Coastguard Worker #[doc = " bytes are used. This method is infallible."] 76*60b67249SAndroid Build Coastguard Worker pub fn from_slice_infallible(value: &[u8]) -> Self { 77*60b67249SAndroid Build Coastguard Worker #![allow(clippy::indexing_slicing)] 78*60b67249SAndroid Build Coastguard Worker let mut tmp: Self = Default::default(); 79*60b67249SAndroid Build Coastguard Worker if value.len() < $len { 80*60b67249SAndroid Build Coastguard Worker tmp.0[..value.len()].copy_from_slice(value); 81*60b67249SAndroid Build Coastguard Worker } else { 82*60b67249SAndroid Build Coastguard Worker tmp.0.copy_from_slice(&value[..$len]); 83*60b67249SAndroid Build Coastguard Worker } 84*60b67249SAndroid Build Coastguard Worker tmp 85*60b67249SAndroid Build Coastguard Worker } 86*60b67249SAndroid Build Coastguard Worker 87*60b67249SAndroid Build Coastguard Worker #[doc = "Creates a "] 88*60b67249SAndroid Build Coastguard Worker #[doc = stringify!($type_name)] 89*60b67249SAndroid Build Coastguard Worker #[doc = " from an array."] 90*60b67249SAndroid Build Coastguard Worker pub fn from_array(value: &[u8; $len]) -> Self { 91*60b67249SAndroid Build Coastguard Worker Self(*value) 92*60b67249SAndroid Build Coastguard Worker } 93*60b67249SAndroid Build Coastguard Worker } 94*60b67249SAndroid Build Coastguard Worker 95*60b67249SAndroid Build Coastguard Worker impl Default for $type_name { 96*60b67249SAndroid Build Coastguard Worker fn default() -> Self { 97*60b67249SAndroid Build Coastguard Worker Self([0; $len]) 98*60b67249SAndroid Build Coastguard Worker } 99*60b67249SAndroid Build Coastguard Worker } 100*60b67249SAndroid Build Coastguard Worker 101*60b67249SAndroid Build Coastguard Worker impl TryFrom<&[u8]> for $type_name { 102*60b67249SAndroid Build Coastguard Worker type Error = $crate::error::ErrCode; 103*60b67249SAndroid Build Coastguard Worker 104*60b67249SAndroid Build Coastguard Worker fn try_from(value: &[u8]) -> Result<Self, Self::Error> { 105*60b67249SAndroid Build Coastguard Worker value.try_into().map(Self).map_err(|_| { 106*60b67249SAndroid Build Coastguard Worker log::error!("Invalid length for fixed length value: {}", $desc); 107*60b67249SAndroid Build Coastguard Worker $crate::error::ErrCode::InvalidArgument 108*60b67249SAndroid Build Coastguard Worker }) 109*60b67249SAndroid Build Coastguard Worker } 110*60b67249SAndroid Build Coastguard Worker } 111*60b67249SAndroid Build Coastguard Worker 112*60b67249SAndroid Build Coastguard Worker impl From<[u8; $len]> for $type_name { 113*60b67249SAndroid Build Coastguard Worker fn from(value: [u8; $len]) -> Self { 114*60b67249SAndroid Build Coastguard Worker Self(value) 115*60b67249SAndroid Build Coastguard Worker } 116*60b67249SAndroid Build Coastguard Worker } 117*60b67249SAndroid Build Coastguard Worker }; 118*60b67249SAndroid Build Coastguard Worker } 119*60b67249SAndroid Build Coastguard Worker 120*60b67249SAndroid Build Coastguard Worker /// Wraps a [heapless::Vec] of bytes and provides various convenience methods 121*60b67249SAndroid Build Coastguard Worker /// that are useful when processing DPE messages. The inner `vec` is also 122*60b67249SAndroid Build Coastguard Worker /// accessible directly. 123*60b67249SAndroid Build Coastguard Worker #[derive(Clone, Debug, Default, Eq, PartialEq, Hash, ZeroizeOnDrop)] 124*60b67249SAndroid Build Coastguard Worker pub struct SizedMessage<const S: usize> { 125*60b67249SAndroid Build Coastguard Worker /// The wrapped Vec. 126*60b67249SAndroid Build Coastguard Worker pub vec: Vec<u8, S>, 127*60b67249SAndroid Build Coastguard Worker } 128*60b67249SAndroid Build Coastguard Worker 129*60b67249SAndroid Build Coastguard Worker impl<const S: usize> SizedMessage<S> { 130*60b67249SAndroid Build Coastguard Worker /// Creates a new, empty instance. 131*60b67249SAndroid Build Coastguard Worker /// 132*60b67249SAndroid Build Coastguard Worker /// # Example 133*60b67249SAndroid Build Coastguard Worker /// 134*60b67249SAndroid Build Coastguard Worker /// ```rust 135*60b67249SAndroid Build Coastguard Worker /// type MyMessage = dpe_rs::memory::SizedMessage<200>; 136*60b67249SAndroid Build Coastguard Worker /// 137*60b67249SAndroid Build Coastguard Worker /// assert_eq!(MyMessage::new().len(), 0); 138*60b67249SAndroid Build Coastguard Worker /// ``` new() -> Self139*60b67249SAndroid Build Coastguard Worker pub fn new() -> Self { 140*60b67249SAndroid Build Coastguard Worker Default::default() 141*60b67249SAndroid Build Coastguard Worker } 142*60b67249SAndroid Build Coastguard Worker 143*60b67249SAndroid Build Coastguard Worker /// Creates a new instance from a slice. 144*60b67249SAndroid Build Coastguard Worker /// 145*60b67249SAndroid Build Coastguard Worker /// # Errors 146*60b67249SAndroid Build Coastguard Worker /// 147*60b67249SAndroid Build Coastguard Worker /// If `value` exceeds the available capacity, returns an OutOfMemory error. 148*60b67249SAndroid Build Coastguard Worker /// 149*60b67249SAndroid Build Coastguard Worker /// # Example 150*60b67249SAndroid Build Coastguard Worker /// 151*60b67249SAndroid Build Coastguard Worker /// ```rust 152*60b67249SAndroid Build Coastguard Worker /// type MyMessage = dpe_rs::memory::SizedMessage<200>; 153*60b67249SAndroid Build Coastguard Worker /// 154*60b67249SAndroid Build Coastguard Worker /// assert_eq!(MyMessage::from_slice(&[0; 12]).unwrap().as_slice(), &[0; 12]); 155*60b67249SAndroid Build Coastguard Worker /// ``` from_slice(value: &[u8]) -> DpeResult<Self>156*60b67249SAndroid Build Coastguard Worker pub fn from_slice(value: &[u8]) -> DpeResult<Self> { 157*60b67249SAndroid Build Coastguard Worker Ok(Self { 158*60b67249SAndroid Build Coastguard Worker vec: Vec::from_slice(value).map_err(|_| ErrCode::OutOfMemory)?, 159*60b67249SAndroid Build Coastguard Worker }) 160*60b67249SAndroid Build Coastguard Worker } 161*60b67249SAndroid Build Coastguard Worker 162*60b67249SAndroid Build Coastguard Worker /// Clones `slice`, replacing any existing content. 163*60b67249SAndroid Build Coastguard Worker /// 164*60b67249SAndroid Build Coastguard Worker /// # Errors 165*60b67249SAndroid Build Coastguard Worker /// 166*60b67249SAndroid Build Coastguard Worker /// If `slice` exceeds the available capacity, returns an OutOfMemory error. 167*60b67249SAndroid Build Coastguard Worker /// 168*60b67249SAndroid Build Coastguard Worker /// # Example 169*60b67249SAndroid Build Coastguard Worker /// 170*60b67249SAndroid Build Coastguard Worker /// ```rust 171*60b67249SAndroid Build Coastguard Worker /// type MyMessage = dpe_rs::memory::SizedMessage<200>; 172*60b67249SAndroid Build Coastguard Worker /// 173*60b67249SAndroid Build Coastguard Worker /// let mut m = MyMessage::from_slice(&[0; 12]).unwrap(); 174*60b67249SAndroid Build Coastguard Worker /// m.clone_from_slice(&[1; 3]).unwrap(); 175*60b67249SAndroid Build Coastguard Worker /// assert_eq!(m.as_slice(), &[1; 3]); 176*60b67249SAndroid Build Coastguard Worker /// ``` clone_from_slice(&mut self, slice: &[u8]) -> DpeResult<()>177*60b67249SAndroid Build Coastguard Worker pub fn clone_from_slice(&mut self, slice: &[u8]) -> DpeResult<()> { 178*60b67249SAndroid Build Coastguard Worker self.clear(); 179*60b67249SAndroid Build Coastguard Worker self.vec.extend_from_slice(slice).map_err(|_| ErrCode::OutOfMemory) 180*60b67249SAndroid Build Coastguard Worker } 181*60b67249SAndroid Build Coastguard Worker 182*60b67249SAndroid Build Coastguard Worker /// Borrows the inner byte array. as_slice(&self) -> &[u8]183*60b67249SAndroid Build Coastguard Worker pub fn as_slice(&self) -> &[u8] { 184*60b67249SAndroid Build Coastguard Worker self.vec.as_slice() 185*60b67249SAndroid Build Coastguard Worker } 186*60b67249SAndroid Build Coastguard Worker 187*60b67249SAndroid Build Coastguard Worker /// Mutably borrows the inner byte array after resizing. This is useful when 188*60b67249SAndroid Build Coastguard Worker /// using the type as an output buffer. 189*60b67249SAndroid Build Coastguard Worker /// 190*60b67249SAndroid Build Coastguard Worker /// # Errors 191*60b67249SAndroid Build Coastguard Worker /// 192*60b67249SAndroid Build Coastguard Worker /// If `size` exceeds the available capacity, returns an OutOfMemory error. 193*60b67249SAndroid Build Coastguard Worker /// 194*60b67249SAndroid Build Coastguard Worker /// # Example 195*60b67249SAndroid Build Coastguard Worker /// 196*60b67249SAndroid Build Coastguard Worker /// ```rust 197*60b67249SAndroid Build Coastguard Worker /// use rand_core::{RngCore, SeedableRng}; 198*60b67249SAndroid Build Coastguard Worker /// 199*60b67249SAndroid Build Coastguard Worker /// type MyMessage = dpe_rs::memory::SizedMessage<200>; 200*60b67249SAndroid Build Coastguard Worker /// 201*60b67249SAndroid Build Coastguard Worker /// let mut buffer = MyMessage::new(); 202*60b67249SAndroid Build Coastguard Worker /// <rand_chacha::ChaCha12Rng as SeedableRng>::seed_from_u64(0) 203*60b67249SAndroid Build Coastguard Worker /// .fill_bytes(buffer.as_mut_sized(100).unwrap()); 204*60b67249SAndroid Build Coastguard Worker /// assert_eq!(buffer.len(), 100); 205*60b67249SAndroid Build Coastguard Worker /// ``` as_mut_sized(&mut self, size: usize) -> DpeResult<&mut [u8]>206*60b67249SAndroid Build Coastguard Worker pub fn as_mut_sized(&mut self, size: usize) -> DpeResult<&mut [u8]> { 207*60b67249SAndroid Build Coastguard Worker self.vec.resize_default(size).map_err(|_| ErrCode::OutOfMemory)?; 208*60b67249SAndroid Build Coastguard Worker Ok(self.vec.as_mut()) 209*60b67249SAndroid Build Coastguard Worker } 210*60b67249SAndroid Build Coastguard Worker 211*60b67249SAndroid Build Coastguard Worker /// Returns the length of the inner vec. len(&self) -> usize212*60b67249SAndroid Build Coastguard Worker pub fn len(&self) -> usize { 213*60b67249SAndroid Build Coastguard Worker self.vec.len() 214*60b67249SAndroid Build Coastguard Worker } 215*60b67249SAndroid Build Coastguard Worker 216*60b67249SAndroid Build Coastguard Worker /// Whether the inner vec is empty. is_empty(&self) -> bool217*60b67249SAndroid Build Coastguard Worker pub fn is_empty(&self) -> bool { 218*60b67249SAndroid Build Coastguard Worker self.vec.is_empty() 219*60b67249SAndroid Build Coastguard Worker } 220*60b67249SAndroid Build Coastguard Worker 221*60b67249SAndroid Build Coastguard Worker /// Clears the inner vec. clear(&mut self)222*60b67249SAndroid Build Coastguard Worker pub fn clear(&mut self) { 223*60b67249SAndroid Build Coastguard Worker self.vec.clear() 224*60b67249SAndroid Build Coastguard Worker } 225*60b67249SAndroid Build Coastguard Worker 226*60b67249SAndroid Build Coastguard Worker /// Removes the first `prefix_size` bytes from the message. This carries the 227*60b67249SAndroid Build Coastguard Worker /// cost of moving the remaining bytes to the front of the buffer. 228*60b67249SAndroid Build Coastguard Worker /// 229*60b67249SAndroid Build Coastguard Worker /// # Errors 230*60b67249SAndroid Build Coastguard Worker /// 231*60b67249SAndroid Build Coastguard Worker /// If `prefix_size` is larger than the current length, returns an 232*60b67249SAndroid Build Coastguard Worker /// InternalError error. 233*60b67249SAndroid Build Coastguard Worker /// 234*60b67249SAndroid Build Coastguard Worker /// # Example 235*60b67249SAndroid Build Coastguard Worker /// 236*60b67249SAndroid Build Coastguard Worker /// ```rust 237*60b67249SAndroid Build Coastguard Worker /// type MyMessage = dpe_rs::memory::SizedMessage<200>; 238*60b67249SAndroid Build Coastguard Worker /// 239*60b67249SAndroid Build Coastguard Worker /// let mut m = MyMessage::from_slice("prefixdata".as_bytes()).unwrap(); 240*60b67249SAndroid Build Coastguard Worker /// m.remove_prefix(6).unwrap(); 241*60b67249SAndroid Build Coastguard Worker /// assert_eq!(m.as_slice(), "data".as_bytes()); 242*60b67249SAndroid Build Coastguard Worker /// ``` remove_prefix(&mut self, prefix_size: usize) -> DpeResult<()>243*60b67249SAndroid Build Coastguard Worker pub fn remove_prefix(&mut self, prefix_size: usize) -> DpeResult<()> { 244*60b67249SAndroid Build Coastguard Worker if prefix_size > self.len() { 245*60b67249SAndroid Build Coastguard Worker return Err(ErrCode::InternalError); 246*60b67249SAndroid Build Coastguard Worker } 247*60b67249SAndroid Build Coastguard Worker if prefix_size == self.len() { 248*60b67249SAndroid Build Coastguard Worker self.clear(); 249*60b67249SAndroid Build Coastguard Worker } else if prefix_size > 0 { 250*60b67249SAndroid Build Coastguard Worker let slice: &mut [u8] = self.vec.as_mut(); 251*60b67249SAndroid Build Coastguard Worker slice.copy_within(prefix_size.., 0); 252*60b67249SAndroid Build Coastguard Worker self.vec.truncate(self.len() - prefix_size); 253*60b67249SAndroid Build Coastguard Worker } 254*60b67249SAndroid Build Coastguard Worker Ok(()) 255*60b67249SAndroid Build Coastguard Worker } 256*60b67249SAndroid Build Coastguard Worker 257*60b67249SAndroid Build Coastguard Worker /// Inserts `prefix` at the start of the message. This carries the cost of 258*60b67249SAndroid Build Coastguard Worker /// moving the existing bytes to make room for the prefix. 259*60b67249SAndroid Build Coastguard Worker /// 260*60b67249SAndroid Build Coastguard Worker /// # Errors 261*60b67249SAndroid Build Coastguard Worker /// 262*60b67249SAndroid Build Coastguard Worker /// If inserting `prefix` overflows the available capacity, returns an 263*60b67249SAndroid Build Coastguard Worker /// OutOfMemory error. 264*60b67249SAndroid Build Coastguard Worker /// 265*60b67249SAndroid Build Coastguard Worker /// # Example 266*60b67249SAndroid Build Coastguard Worker /// 267*60b67249SAndroid Build Coastguard Worker /// ```rust 268*60b67249SAndroid Build Coastguard Worker /// type MyMessage = dpe_rs::memory::SizedMessage<200>; 269*60b67249SAndroid Build Coastguard Worker /// 270*60b67249SAndroid Build Coastguard Worker /// let mut m = MyMessage::from_slice("data".as_bytes()).unwrap(); 271*60b67249SAndroid Build Coastguard Worker /// m.insert_prefix("prefix".as_bytes()).unwrap(); 272*60b67249SAndroid Build Coastguard Worker /// assert_eq!(m.as_slice(), "prefixdata".as_bytes()); 273*60b67249SAndroid Build Coastguard Worker /// ``` insert_prefix(&mut self, prefix: &[u8]) -> DpeResult<()>274*60b67249SAndroid Build Coastguard Worker pub fn insert_prefix(&mut self, prefix: &[u8]) -> DpeResult<()> { 275*60b67249SAndroid Build Coastguard Worker let old_len = self.len(); 276*60b67249SAndroid Build Coastguard Worker self.vec 277*60b67249SAndroid Build Coastguard Worker .resize_default(self.len() + prefix.len()) 278*60b67249SAndroid Build Coastguard Worker .map_err(|_| ErrCode::OutOfMemory)?; 279*60b67249SAndroid Build Coastguard Worker let slice: &mut [u8] = self.vec.as_mut(); 280*60b67249SAndroid Build Coastguard Worker slice.copy_within(0..old_len, prefix.len()); 281*60b67249SAndroid Build Coastguard Worker slice 282*60b67249SAndroid Build Coastguard Worker .get_mut(..prefix.len()) 283*60b67249SAndroid Build Coastguard Worker .ok_or(ErrCode::InternalError)? 284*60b67249SAndroid Build Coastguard Worker .copy_from_slice(prefix); 285*60b67249SAndroid Build Coastguard Worker Ok(()) 286*60b67249SAndroid Build Coastguard Worker } 287*60b67249SAndroid Build Coastguard Worker } 288*60b67249SAndroid Build Coastguard Worker 289*60b67249SAndroid Build Coastguard Worker /// Represents a DPE command/response message. This type is large and should not 290*60b67249SAndroid Build Coastguard Worker /// be instantiated unnecessarily. 291*60b67249SAndroid Build Coastguard Worker pub type Message = SizedMessage<MAX_MESSAGE_SIZE>; 292