1use crate::{TpmCast, TpmCastMut, TpmError, TpmMarshal, TpmResult, TpmSized, basic::TpmUint32};
6use core::{
7 convert::TryFrom,
8 fmt::Debug,
9 marker::PhantomData,
10 mem::{MaybeUninit, size_of},
11 ops::Deref,
12 slice,
13};
14
15const TPML_COUNT_LEN: usize = size_of::<TpmUint32>();
16
17#[repr(transparent)]
19pub struct Tpml<const CAPACITY: usize>([u8]);
20
21impl<const CAPACITY: usize> Tpml<CAPACITY> {
22 pub fn cast(buf: &[u8]) -> TpmResult<&Self> {
31 Self::validate(buf)?;
32
33 Ok(unsafe { Self::cast_unchecked(buf) })
36 }
37
38 pub fn cast_items<T: TpmCast + ?Sized>(buf: &[u8]) -> TpmResult<&Self> {
45 Self::validate_items::<T>(buf)?;
46
47 Ok(unsafe { Self::cast_unchecked(buf) })
50 }
51
52 pub fn cast_prefix_items<T: TpmCast + ?Sized>(buf: &[u8]) -> TpmResult<(&Self, &[u8])> {
58 let wire_len = Self::validate_prefix_items::<T>(buf)?;
59 if buf.len() < wire_len {
60 return Err(TpmError::UnexpectedEnd(
61 crate::TpmErrorValue::new(0).size(wire_len, buf.len()),
62 ));
63 }
64
65 let (head, tail) = buf.split_at(wire_len);
66
67 Ok((unsafe { Self::cast_unchecked(head) }, tail))
70 }
71
72 #[must_use]
79 pub unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
80 let ptr = core::ptr::from_ref(buf) as *const Self;
81
82 unsafe { &*ptr }
85 }
86
87 pub fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
96 Self::validate(buf)?;
97
98 Ok(unsafe { Self::cast_mut_unchecked(buf) })
101 }
102
103 pub fn cast_items_mut<T: TpmCast + ?Sized>(buf: &mut [u8]) -> TpmResult<&mut Self> {
110 Self::validate_items::<T>(buf)?;
111
112 Ok(unsafe { Self::cast_mut_unchecked(buf) })
115 }
116
117 pub fn cast_prefix_items_mut<T: TpmCast + ?Sized>(
123 buf: &mut [u8],
124 ) -> TpmResult<(&mut Self, &mut [u8])> {
125 let wire_len = Self::validate_prefix_items::<T>(buf)?;
126 if buf.len() < wire_len {
127 return Err(TpmError::UnexpectedEnd(
128 crate::TpmErrorValue::new(0).size(wire_len, buf.len()),
129 ));
130 }
131
132 let (head, tail) = buf.split_at_mut(wire_len);
133
134 Ok((unsafe { Self::cast_mut_unchecked(head) }, tail))
137 }
138
139 #[must_use]
147 pub unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
148 let ptr = core::ptr::from_mut(buf) as *mut Self;
149
150 unsafe { &mut *ptr }
153 }
154
155 #[must_use]
157 pub const fn as_bytes(&self) -> &[u8] {
158 &self.0
159 }
160
161 #[must_use]
163 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
164 &mut self.0
165 }
166
167 #[must_use]
169 pub fn count(&self) -> usize {
170 Self::read_count(&self.0)
171 }
172
173 #[must_use]
175 pub fn items_bytes(&self) -> &[u8] {
176 &self.0[TPML_COUNT_LEN..]
177 }
178
179 #[must_use]
181 pub fn items<T: TpmCast + ?Sized>(&self) -> TpmlIter<'_, T> {
182 TpmlIter {
183 buf: self.items_bytes(),
184 remaining: self.count(),
185 _marker: PhantomData,
186 }
187 }
188
189 #[must_use]
191 pub fn items_bytes_mut(&mut self) -> &mut [u8] {
192 &mut self.0[TPML_COUNT_LEN..]
193 }
194
195 #[must_use]
197 pub const fn len(&self) -> usize {
198 self.0.len()
199 }
200
201 #[must_use]
203 pub fn is_empty(&self) -> bool {
204 self.count() == 0
205 }
206
207 pub fn validate(buf: &[u8]) -> TpmResult<()> {
214 Self::validate_header(buf).map(|_| ())
215 }
216
217 pub fn validate_items<T: TpmCast + ?Sized>(buf: &[u8]) -> TpmResult<()> {
223 let wire_len = Self::validate_prefix_items::<T>(buf)?;
224
225 if buf.len() > wire_len {
226 return Err(TpmError::TrailingData(
227 crate::TpmErrorValue::new(wire_len).actual(buf.len() - wire_len),
228 ));
229 }
230
231 Ok(())
232 }
233
234 pub fn validate_prefix_items<T: TpmCast + ?Sized>(buf: &[u8]) -> TpmResult<usize> {
240 let count = Self::validate_header(buf)?;
241 let mut cursor = &buf[TPML_COUNT_LEN..];
242 let mut consumed = TPML_COUNT_LEN;
243
244 for _ in 0..count {
245 let before = cursor.len();
246 let (_, tail) = T::cast_prefix(cursor)?;
247 let item_len = before
248 .checked_sub(tail.len())
249 .ok_or(TpmError::IntegerTooLarge(
250 crate::TpmErrorValue::new(consumed).value_usize(tail.len()),
251 ))?;
252 consumed = consumed
253 .checked_add(item_len)
254 .ok_or(TpmError::IntegerTooLarge(
255 crate::TpmErrorValue::new(consumed).value_usize(before),
256 ))?;
257 cursor = tail;
258 }
259
260 Ok(consumed)
261 }
262
263 fn validate_header(buf: &[u8]) -> TpmResult<usize> {
264 if buf.len() < TPML_COUNT_LEN {
265 return Err(TpmError::UnexpectedEnd(
266 crate::TpmErrorValue::new(0).size(TPML_COUNT_LEN, buf.len()),
267 ));
268 }
269
270 let item_count = Self::read_count(buf);
271 if item_count > CAPACITY {
272 return Err(TpmError::TooManyItems(
273 crate::TpmErrorValue::new(0).limit(CAPACITY, item_count),
274 ));
275 }
276
277 Ok(item_count)
278 }
279
280 fn read_count(buf: &[u8]) -> usize {
281 let raw = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
282
283 raw as usize
284 }
285}
286
287pub struct TpmlIter<'a, T: TpmCast + ?Sized> {
289 buf: &'a [u8],
290 remaining: usize,
291 _marker: PhantomData<&'a T>,
292}
293
294impl<'a, T: TpmCast + ?Sized> Iterator for TpmlIter<'a, T> {
295 type Item = TpmResult<&'a T>;
296
297 fn next(&mut self) -> Option<Self::Item> {
298 if self.remaining == 0 {
299 return None;
300 }
301
302 self.remaining -= 1;
303
304 match T::cast_prefix(self.buf) {
305 Ok((item, tail)) => {
306 self.buf = tail;
307 Some(Ok(item))
308 }
309 Err(err) => {
310 self.buf = &[];
311 self.remaining = 0;
312 Some(Err(err))
313 }
314 }
315 }
316}
317
318impl<const CAPACITY: usize> TpmCast for Tpml<CAPACITY> {
319 fn cast(buf: &[u8]) -> TpmResult<&Self> {
320 Self::cast(buf)
321 }
322
323 unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
324 unsafe { Self::cast_unchecked(buf) }
326 }
327}
328
329impl<const CAPACITY: usize> TpmCastMut for Tpml<CAPACITY> {
330 fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
331 Self::cast_mut(buf)
332 }
333
334 unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
335 unsafe { Self::cast_mut_unchecked(buf) }
338 }
339}
340
341impl<'a, T: crate::TpmField<'a> + Copy, const CAPACITY: usize> crate::TpmField<'a>
342 for TpmList<T, CAPACITY>
343{
344 type View = &'a Tpml<CAPACITY>;
345
346 fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
347 let count = Tpml::<CAPACITY>::validate_header(buf)?;
348 let mut cursor = &buf[TPML_COUNT_LEN..];
349 let mut consumed = TPML_COUNT_LEN;
350
351 for _ in 0..count {
352 let before = cursor.len();
353 let (_, tail) = T::cast_prefix_field(cursor)?;
354 let item_len = before
355 .checked_sub(tail.len())
356 .ok_or(TpmError::IntegerTooLarge(
357 crate::TpmErrorValue::new(consumed).value_usize(tail.len()),
358 ))?;
359 consumed = consumed
360 .checked_add(item_len)
361 .ok_or(TpmError::IntegerTooLarge(
362 crate::TpmErrorValue::new(consumed).value_usize(before),
363 ))?;
364 cursor = tail;
365 }
366
367 if buf.len() < consumed {
368 return Err(TpmError::UnexpectedEnd(
369 crate::TpmErrorValue::new(0).size(consumed, buf.len()),
370 ));
371 }
372
373 let (head, tail) = buf.split_at(consumed);
374
375 Ok((unsafe { Tpml::<CAPACITY>::cast_unchecked(head) }, tail))
377 }
378}
379
380impl<const CAPACITY: usize> AsRef<[u8]> for Tpml<CAPACITY> {
381 fn as_ref(&self) -> &[u8] {
382 self.as_bytes()
383 }
384}
385
386impl<const CAPACITY: usize> AsMut<[u8]> for Tpml<CAPACITY> {
387 fn as_mut(&mut self) -> &mut [u8] {
388 self.as_bytes_mut()
389 }
390}
391
392#[derive(Clone, Copy)]
394pub struct TpmList<T: Copy, const CAPACITY: usize> {
395 items: [MaybeUninit<T>; CAPACITY],
396 len: usize,
397}
398
399impl<T: Copy, const CAPACITY: usize> TpmList<T, CAPACITY> {
400 #[must_use]
402 pub fn new() -> Self {
403 Self {
404 items: [const { MaybeUninit::uninit() }; CAPACITY],
405 len: 0,
406 }
407 }
408
409 #[must_use]
411 pub fn is_empty(&self) -> bool {
412 self.len == 0
413 }
414
415 pub fn try_push(&mut self, item: T) -> Result<(), TpmError> {
422 if self.len >= CAPACITY {
423 return Err(TpmError::TooManyItems(
424 crate::TpmErrorValue::new(0).limit(CAPACITY, self.len + 1),
425 ));
426 }
427 self.items[self.len].write(item);
428 self.len += 1;
429 Ok(())
430 }
431
432 pub fn try_extend_from_slice(&mut self, slice: &[T]) -> Result<(), TpmError> {
439 let new_len = self
440 .len
441 .checked_add(slice.len())
442 .ok_or(TpmError::TooManyItems(
443 crate::TpmErrorValue::new(0).limit(CAPACITY, usize::MAX),
444 ))?;
445
446 if new_len > CAPACITY {
447 return Err(TpmError::TooManyItems(
448 crate::TpmErrorValue::new(0).limit(CAPACITY, new_len),
449 ));
450 }
451
452 for (dest, src) in self.items[self.len..new_len].iter_mut().zip(slice) {
453 dest.write(*src);
454 }
455 self.len = new_len;
456 Ok(())
457 }
458}
459
460impl<T: Copy, const CAPACITY: usize> Deref for TpmList<T, CAPACITY> {
461 type Target = [T];
462
463 fn deref(&self) -> &Self::Target {
464 unsafe { slice::from_raw_parts(self.items.as_ptr().cast::<T>(), self.len) }
467 }
468}
469
470impl<T: Copy, const CAPACITY: usize> Default for TpmList<T, CAPACITY> {
471 fn default() -> Self {
472 Self::new()
473 }
474}
475
476impl<T: Copy + Debug, const CAPACITY: usize> Debug for TpmList<T, CAPACITY> {
477 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
478 f.debug_list().entries(self.iter()).finish()
479 }
480}
481
482impl<T: Copy + PartialEq, const CAPACITY: usize> PartialEq for TpmList<T, CAPACITY> {
483 fn eq(&self, other: &Self) -> bool {
484 **self == **other
485 }
486}
487
488impl<T: Copy + Eq, const CAPACITY: usize> Eq for TpmList<T, CAPACITY> {}
489
490impl<T: TpmSized + Copy, const CAPACITY: usize> TpmSized for TpmList<T, CAPACITY> {
491 const SIZE: usize = size_of::<TpmUint32>() + (T::SIZE * CAPACITY);
492 fn len(&self) -> usize {
493 size_of::<TpmUint32>() + self.iter().map(TpmSized::len).sum::<usize>()
494 }
495}
496
497impl<T: TpmMarshal + Copy, const CAPACITY: usize> TpmMarshal for TpmList<T, CAPACITY> {
498 fn marshal(&self, writer: &mut crate::TpmWriter) -> TpmResult<()> {
499 let len = TpmUint32::try_from(self.len).map_err(|_| {
500 TpmError::IntegerTooLarge(crate::TpmErrorValue::new(0).value_usize(self.len))
501 })?;
502 TpmMarshal::marshal(&len, writer)?;
503 for item in &**self {
504 TpmMarshal::marshal(item, writer)?;
505 }
506 Ok(())
507 }
508}