tpm2_protocol/basic/
list.rs1use crate::{
6 TpmCast, TpmCastMut, TpmError, TpmMarshal, TpmResult, TpmSized, TpmUnmarshal, basic::TpmUint32,
7};
8use core::{
9 convert::TryFrom,
10 fmt::Debug,
11 mem::{MaybeUninit, size_of},
12 ops::Deref,
13 slice,
14};
15
16const TPML_COUNT_LEN: usize = size_of::<TpmUint32>();
17
18#[repr(transparent)]
20pub struct Tpml<const CAPACITY: usize>([u8]);
21
22impl<const CAPACITY: usize> Tpml<CAPACITY> {
23 pub fn cast(buf: &[u8]) -> TpmResult<&Self> {
32 Self::validate(buf)?;
33
34 Ok(unsafe { Self::cast_unchecked(buf) })
37 }
38
39 #[must_use]
46 pub unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
47 let ptr = core::ptr::from_ref(buf) as *const Self;
48
49 unsafe { &*ptr }
52 }
53
54 pub fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
63 Self::validate(buf)?;
64
65 Ok(unsafe { Self::cast_mut_unchecked(buf) })
68 }
69
70 #[must_use]
78 pub unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
79 let ptr = core::ptr::from_mut(buf) as *mut Self;
80
81 unsafe { &mut *ptr }
84 }
85
86 #[must_use]
88 pub const fn as_bytes(&self) -> &[u8] {
89 &self.0
90 }
91
92 #[must_use]
94 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
95 &mut self.0
96 }
97
98 #[must_use]
100 pub fn count(&self) -> usize {
101 Self::read_count(&self.0)
102 }
103
104 #[must_use]
106 pub fn items_bytes(&self) -> &[u8] {
107 &self.0[TPML_COUNT_LEN..]
108 }
109
110 #[must_use]
112 pub fn items_bytes_mut(&mut self) -> &mut [u8] {
113 &mut self.0[TPML_COUNT_LEN..]
114 }
115
116 #[must_use]
118 pub const fn len(&self) -> usize {
119 self.0.len()
120 }
121
122 #[must_use]
124 pub fn is_empty(&self) -> bool {
125 self.count() == 0
126 }
127
128 fn validate(buf: &[u8]) -> TpmResult<()> {
129 if buf.len() < TPML_COUNT_LEN {
130 return Err(TpmError::UnexpectedEnd(
131 crate::TpmErrorValue::new(0).size(TPML_COUNT_LEN, buf.len()),
132 ));
133 }
134
135 let item_count = Self::read_count(buf);
136 if item_count > CAPACITY {
137 return Err(TpmError::TooManyItems(
138 crate::TpmErrorValue::new(0).limit(CAPACITY, item_count),
139 ));
140 }
141
142 Ok(())
143 }
144
145 fn read_count(buf: &[u8]) -> usize {
146 let raw = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
147
148 raw as usize
149 }
150}
151
152impl<const CAPACITY: usize> TpmCast for Tpml<CAPACITY> {
153 fn cast(buf: &[u8]) -> TpmResult<&Self> {
154 Self::cast(buf)
155 }
156
157 unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
158 unsafe { Self::cast_unchecked(buf) }
160 }
161}
162
163impl<const CAPACITY: usize> TpmCastMut for Tpml<CAPACITY> {
164 fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
165 Self::cast_mut(buf)
166 }
167
168 unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
169 unsafe { Self::cast_mut_unchecked(buf) }
172 }
173}
174
175impl<const CAPACITY: usize> AsRef<[u8]> for Tpml<CAPACITY> {
176 fn as_ref(&self) -> &[u8] {
177 self.as_bytes()
178 }
179}
180
181impl<const CAPACITY: usize> AsMut<[u8]> for Tpml<CAPACITY> {
182 fn as_mut(&mut self) -> &mut [u8] {
183 self.as_bytes_mut()
184 }
185}
186
187#[derive(Clone, Copy)]
189pub struct TpmList<T: Copy, const CAPACITY: usize> {
190 items: [MaybeUninit<T>; CAPACITY],
191 len: usize,
192}
193
194impl<T: Copy, const CAPACITY: usize> TpmList<T, CAPACITY> {
195 #[must_use]
197 pub fn new() -> Self {
198 Self {
199 items: [const { MaybeUninit::uninit() }; CAPACITY],
200 len: 0,
201 }
202 }
203
204 #[must_use]
206 pub fn is_empty(&self) -> bool {
207 self.len == 0
208 }
209
210 pub fn try_push(&mut self, item: T) -> Result<(), TpmError> {
217 if self.len >= CAPACITY {
218 return Err(TpmError::TooManyItems(
219 crate::TpmErrorValue::new(0).limit(CAPACITY, self.len + 1),
220 ));
221 }
222 self.items[self.len].write(item);
223 self.len += 1;
224 Ok(())
225 }
226
227 pub fn try_extend_from_slice(&mut self, slice: &[T]) -> Result<(), TpmError> {
234 let new_len = self
235 .len
236 .checked_add(slice.len())
237 .ok_or(TpmError::TooManyItems(
238 crate::TpmErrorValue::new(0).limit(CAPACITY, usize::MAX),
239 ))?;
240
241 if new_len > CAPACITY {
242 return Err(TpmError::TooManyItems(
243 crate::TpmErrorValue::new(0).limit(CAPACITY, new_len),
244 ));
245 }
246
247 for (dest, src) in self.items[self.len..new_len].iter_mut().zip(slice) {
248 dest.write(*src);
249 }
250 self.len = new_len;
251 Ok(())
252 }
253}
254
255impl<T: Copy, const CAPACITY: usize> Deref for TpmList<T, CAPACITY> {
256 type Target = [T];
257
258 fn deref(&self) -> &Self::Target {
259 unsafe { slice::from_raw_parts(self.items.as_ptr().cast::<T>(), self.len) }
262 }
263}
264
265impl<T: Copy, const CAPACITY: usize> Default for TpmList<T, CAPACITY> {
266 fn default() -> Self {
267 Self::new()
268 }
269}
270
271impl<T: Copy + Debug, const CAPACITY: usize> Debug for TpmList<T, CAPACITY> {
272 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
273 f.debug_list().entries(self.iter()).finish()
274 }
275}
276
277impl<T: Copy + PartialEq, const CAPACITY: usize> PartialEq for TpmList<T, CAPACITY> {
278 fn eq(&self, other: &Self) -> bool {
279 **self == **other
280 }
281}
282
283impl<T: Copy + Eq, const CAPACITY: usize> Eq for TpmList<T, CAPACITY> {}
284
285impl<T: TpmSized + Copy, const CAPACITY: usize> TpmSized for TpmList<T, CAPACITY> {
286 const SIZE: usize = size_of::<TpmUint32>() + (T::SIZE * CAPACITY);
287 fn len(&self) -> usize {
288 size_of::<TpmUint32>() + self.iter().map(TpmSized::len).sum::<usize>()
289 }
290}
291
292impl<T: TpmMarshal + Copy, const CAPACITY: usize> TpmMarshal for TpmList<T, CAPACITY> {
293 fn marshal(&self, writer: &mut crate::TpmWriter) -> TpmResult<()> {
294 let len = TpmUint32::try_from(self.len).map_err(|_| {
295 TpmError::IntegerTooLarge(crate::TpmErrorValue::new(0).value_usize(self.len))
296 })?;
297 TpmMarshal::marshal(&len, writer)?;
298 for item in &**self {
299 TpmMarshal::marshal(item, writer)?;
300 }
301 Ok(())
302 }
303}
304
305impl<T: TpmUnmarshal + Copy, const CAPACITY: usize> TpmUnmarshal for TpmList<T, CAPACITY> {
306 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
307 let (count_u32, mut buf) = TpmUint32::unmarshal(buf)?;
308 let count = u32::from(count_u32) as usize;
309 if count > CAPACITY {
310 return Err(TpmError::TooManyItems(
311 crate::TpmErrorValue::new(0).limit(CAPACITY, count),
312 ));
313 }
314
315 let mut list = Self::new();
316 for _ in 0..count {
317 let (item, rest) = T::unmarshal(buf)?;
318 list.try_push(item)?;
319 buf = rest;
320 }
321
322 Ok((list, buf))
323 }
324}