1use crate::{
6 TpmCast, TpmCastMut, TpmError, TpmMarshal, TpmResult, TpmSized, TpmUnmarshal, basic::TpmUint32,
7};
8use core::{
9 convert::TryFrom,
10 fmt::Debug,
11 marker::PhantomData,
12 mem::{MaybeUninit, size_of},
13 ops::Deref,
14 slice,
15};
16
17const TPML_COUNT_LEN: usize = size_of::<TpmUint32>();
18
19#[repr(transparent)]
21pub struct Tpml<const CAPACITY: usize>([u8]);
22
23impl<const CAPACITY: usize> Tpml<CAPACITY> {
24 pub fn cast(buf: &[u8]) -> TpmResult<&Self> {
33 Self::validate(buf)?;
34
35 Ok(unsafe { Self::cast_unchecked(buf) })
38 }
39
40 pub fn cast_items<T: TpmCast + ?Sized>(buf: &[u8]) -> TpmResult<&Self> {
47 Self::validate_items::<T>(buf)?;
48
49 Ok(unsafe { Self::cast_unchecked(buf) })
52 }
53
54 pub fn cast_prefix_items<T: TpmCast + ?Sized>(buf: &[u8]) -> TpmResult<(&Self, &[u8])> {
60 let wire_len = Self::validate_prefix_items::<T>(buf)?;
61 if buf.len() < wire_len {
62 return Err(TpmError::UnexpectedEnd {
63 offset: 0,
64 needed: wire_len,
65 available: buf.len(),
66 });
67 }
68
69 let (head, tail) = buf.split_at(wire_len);
70
71 Ok((unsafe { Self::cast_unchecked(head) }, tail))
74 }
75
76 pub fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
85 Self::validate(buf)?;
86
87 Ok(unsafe { Self::cast_mut_unchecked(buf) })
90 }
91
92 pub fn cast_items_mut<T: TpmCast + ?Sized>(buf: &mut [u8]) -> TpmResult<&mut Self> {
99 Self::validate_items::<T>(buf)?;
100
101 Ok(unsafe { Self::cast_mut_unchecked(buf) })
104 }
105
106 pub fn cast_prefix_items_mut<T: TpmCast + ?Sized>(
112 buf: &mut [u8],
113 ) -> TpmResult<(&mut Self, &mut [u8])> {
114 let wire_len = Self::validate_prefix_items::<T>(buf)?;
115 if buf.len() < wire_len {
116 return Err(TpmError::UnexpectedEnd {
117 offset: 0,
118 needed: wire_len,
119 available: buf.len(),
120 });
121 }
122
123 let (head, tail) = buf.split_at_mut(wire_len);
124
125 Ok((unsafe { Self::cast_mut_unchecked(head) }, tail))
128 }
129
130 #[must_use]
132 pub const fn as_bytes(&self) -> &[u8] {
133 &self.0
134 }
135
136 #[must_use]
138 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
139 &mut self.0
140 }
141
142 #[must_use]
144 pub fn count(&self) -> usize {
145 Self::read_count(&self.0)
146 }
147
148 #[must_use]
150 pub fn items_bytes(&self) -> &[u8] {
151 &self.0[TPML_COUNT_LEN..]
152 }
153
154 #[must_use]
156 pub fn items<T: TpmCast + ?Sized>(&self) -> TpmlIter<'_, T> {
157 TpmlIter {
158 buf: self.items_bytes(),
159 remaining: self.count(),
160 _marker: PhantomData,
161 }
162 }
163
164 #[must_use]
166 pub fn items_bytes_mut(&mut self) -> &mut [u8] {
167 &mut self.0[TPML_COUNT_LEN..]
168 }
169
170 #[must_use]
172 pub const fn len(&self) -> usize {
173 self.0.len()
174 }
175
176 #[must_use]
178 pub fn is_empty(&self) -> bool {
179 self.count() == 0
180 }
181
182 pub fn validate(buf: &[u8]) -> TpmResult<()> {
189 Self::validate_header(buf).map(|_| ())
190 }
191
192 pub fn validate_items<T: TpmCast + ?Sized>(buf: &[u8]) -> TpmResult<()> {
198 let wire_len = Self::validate_prefix_items::<T>(buf)?;
199
200 if buf.len() > wire_len {
201 return Err(TpmError::TrailingData {
202 offset: wire_len,
203 actual: buf.len() - wire_len,
204 });
205 }
206
207 Ok(())
208 }
209
210 pub fn validate_prefix_items<T: TpmCast + ?Sized>(buf: &[u8]) -> TpmResult<usize> {
216 let count = Self::validate_header(buf)?;
217 let mut cursor = &buf[TPML_COUNT_LEN..];
218 let mut consumed = TPML_COUNT_LEN;
219
220 for _ in 0..count {
221 let before = cursor.len();
222 let (_, tail) = T::cast_prefix(cursor)?;
223 let item_len = before
224 .checked_sub(tail.len())
225 .ok_or(TpmError::IntegerTooLarge {
226 offset: consumed,
227 value: crate::tpm_value(tail.len()),
228 })?;
229 consumed = consumed
230 .checked_add(item_len)
231 .ok_or(TpmError::IntegerTooLarge {
232 offset: consumed,
233 value: crate::tpm_value(before),
234 })?;
235 cursor = tail;
236 }
237
238 Ok(consumed)
239 }
240
241 fn validate_header(buf: &[u8]) -> TpmResult<usize> {
242 if buf.len() < TPML_COUNT_LEN {
243 return Err(TpmError::UnexpectedEnd {
244 offset: 0,
245 needed: TPML_COUNT_LEN,
246 available: buf.len(),
247 });
248 }
249
250 let item_count = Self::read_count(buf);
251 if item_count > CAPACITY {
252 return Err(TpmError::TooManyItems {
253 offset: 0,
254 limit: CAPACITY,
255 actual: item_count,
256 });
257 }
258
259 Ok(item_count)
260 }
261
262 fn read_count(buf: &[u8]) -> usize {
263 let raw = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
264
265 raw as usize
266 }
267}
268
269pub struct TpmlIter<'a, T: TpmCast + ?Sized> {
271 buf: &'a [u8],
272 remaining: usize,
273 _marker: PhantomData<&'a T>,
274}
275
276impl<'a, T: TpmCast + ?Sized> Iterator for TpmlIter<'a, T> {
277 type Item = TpmResult<&'a T>;
278
279 fn next(&mut self) -> Option<Self::Item> {
280 if self.remaining == 0 {
281 return None;
282 }
283
284 self.remaining -= 1;
285
286 match T::cast_prefix(self.buf) {
287 Ok((item, tail)) => {
288 self.buf = tail;
289 Some(Ok(item))
290 }
291 Err(err) => {
292 self.buf = &[];
293 self.remaining = 0;
294 Some(Err(err))
295 }
296 }
297 }
298}
299
300impl<const CAPACITY: usize> TpmCast for Tpml<CAPACITY> {
301 fn cast(buf: &[u8]) -> TpmResult<&Self> {
302 Self::cast(buf)
303 }
304
305 unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
306 unsafe { Self::cast_unchecked(buf) }
308 }
309}
310
311impl<const CAPACITY: usize> TpmCastMut for Tpml<CAPACITY> {
312 fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
313 Self::cast_mut(buf)
314 }
315
316 unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
317 unsafe { Self::cast_mut_unchecked(buf) }
320 }
321}
322
323impl<'a, T: crate::TpmField<'a> + Copy, const CAPACITY: usize> crate::TpmField<'a>
324 for TpmList<T, CAPACITY>
325{
326 type View = &'a Tpml<CAPACITY>;
327
328 fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
329 let count = Tpml::<CAPACITY>::validate_header(buf)?;
330 let mut cursor = &buf[TPML_COUNT_LEN..];
331 let mut consumed = TPML_COUNT_LEN;
332
333 for _ in 0..count {
334 let before = cursor.len();
335 let (_, tail) = T::cast_prefix_field(cursor)?;
336 let item_len = before
337 .checked_sub(tail.len())
338 .ok_or(TpmError::IntegerTooLarge {
339 offset: consumed,
340 value: crate::tpm_value(tail.len()),
341 })?;
342 consumed = consumed
343 .checked_add(item_len)
344 .ok_or(TpmError::IntegerTooLarge {
345 offset: consumed,
346 value: crate::tpm_value(before),
347 })?;
348 cursor = tail;
349 }
350
351 let (head, tail) = buf.split_at(consumed);
352
353 Ok((unsafe { Tpml::<CAPACITY>::cast_unchecked(head) }, tail))
355 }
356}
357
358crate::tpm_byte_view!(Tpml<const CAPACITY: usize>);
359
360#[derive(Clone, Copy)]
362pub struct TpmList<T: Copy, const CAPACITY: usize> {
363 items: [MaybeUninit<T>; CAPACITY],
364 len: usize,
365}
366
367impl<T: Copy, const CAPACITY: usize> TpmList<T, CAPACITY> {
368 #[must_use]
370 pub const fn new() -> Self {
371 Self {
372 items: [const { MaybeUninit::uninit() }; CAPACITY],
373 len: 0,
374 }
375 }
376
377 #[must_use]
379 pub fn is_empty(&self) -> bool {
380 self.len == 0
381 }
382
383 pub fn try_push(&mut self, item: T) -> Result<(), TpmError> {
390 if self.len >= CAPACITY {
391 return Err(TpmError::TooManyItems {
392 offset: 0,
393 limit: CAPACITY,
394 actual: self.len + 1,
395 });
396 }
397 self.items[self.len].write(item);
398 self.len += 1;
399 Ok(())
400 }
401
402 pub fn try_extend_from_slice(&mut self, slice: &[T]) -> Result<(), TpmError> {
409 let new_len = self
410 .len
411 .checked_add(slice.len())
412 .ok_or(TpmError::TooManyItems {
413 offset: 0,
414 limit: CAPACITY,
415 actual: usize::MAX,
416 })?;
417
418 if new_len > CAPACITY {
419 return Err(TpmError::TooManyItems {
420 offset: 0,
421 limit: CAPACITY,
422 actual: new_len,
423 });
424 }
425
426 for (dest, src) in self.items[self.len..new_len].iter_mut().zip(slice) {
427 dest.write(*src);
428 }
429 self.len = new_len;
430 Ok(())
431 }
432}
433
434impl<T: Copy, const CAPACITY: usize> Deref for TpmList<T, CAPACITY> {
435 type Target = [T];
436
437 fn deref(&self) -> &Self::Target {
438 unsafe { slice::from_raw_parts(self.items.as_ptr().cast::<T>(), self.len) }
441 }
442}
443
444impl<T: Copy, const CAPACITY: usize> Default for TpmList<T, CAPACITY> {
445 fn default() -> Self {
446 Self::new()
447 }
448}
449
450impl<T: Copy + Debug, const CAPACITY: usize> Debug for TpmList<T, CAPACITY> {
451 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
452 f.debug_list().entries(self.iter()).finish()
453 }
454}
455
456impl<T: Copy + PartialEq, const CAPACITY: usize> PartialEq for TpmList<T, CAPACITY> {
457 fn eq(&self, other: &Self) -> bool {
458 **self == **other
459 }
460}
461
462impl<T: Copy + Eq, const CAPACITY: usize> Eq for TpmList<T, CAPACITY> {}
463
464impl<T: TpmSized + Copy, const CAPACITY: usize> TpmSized for TpmList<T, CAPACITY> {
465 const SIZE: usize = size_of::<TpmUint32>() + (T::SIZE * CAPACITY);
466 fn len(&self) -> usize {
467 size_of::<TpmUint32>() + self.iter().map(TpmSized::len).sum::<usize>()
468 }
469}
470
471impl<T: TpmMarshal + Copy, const CAPACITY: usize> TpmMarshal for TpmList<T, CAPACITY> {
472 fn marshal(&self, writer: &mut crate::TpmWriter) -> TpmResult<()> {
473 let len = TpmUint32::try_from(self.len).map_err(|_| TpmError::IntegerTooLarge {
474 offset: 0,
475 value: crate::tpm_value(self.len),
476 })?;
477 TpmMarshal::marshal(&len, writer)?;
478 for item in &**self {
479 TpmMarshal::marshal(item, writer)?;
480 }
481 Ok(())
482 }
483}
484
485impl<T: TpmUnmarshal + Copy, const CAPACITY: usize> TpmUnmarshal for TpmList<T, CAPACITY> {
486 fn unmarshal(buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
487 let (count, mut cursor) = TpmUint32::unmarshal(buffer)?;
488 let count = usize::try_from(count.value()).map_err(|_| TpmError::IntegerTooLarge {
489 offset: 0,
490 value: u64::from(count.value()),
491 })?;
492 if count > CAPACITY {
493 return Err(TpmError::TooManyItems {
494 offset: 0,
495 limit: CAPACITY,
496 actual: count,
497 });
498 }
499
500 let mut list = Self::new();
501
502 for _ in 0..count {
503 let (item, tail) = T::unmarshal(cursor)?;
504 list.try_push(item)?;
505 cursor = tail;
506 }
507
508 Ok((list, cursor))
509 }
510}