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 offset: 0,
62 needed: wire_len,
63 available: buf.len(),
64 });
65 }
66
67 let (head, tail) = buf.split_at(wire_len);
68
69 Ok((unsafe { Self::cast_unchecked(head) }, tail))
72 }
73
74 pub fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
83 Self::validate(buf)?;
84
85 Ok(unsafe { Self::cast_mut_unchecked(buf) })
88 }
89
90 pub fn cast_items_mut<T: TpmCast + ?Sized>(buf: &mut [u8]) -> TpmResult<&mut Self> {
97 Self::validate_items::<T>(buf)?;
98
99 Ok(unsafe { Self::cast_mut_unchecked(buf) })
102 }
103
104 pub fn cast_prefix_items_mut<T: TpmCast + ?Sized>(
110 buf: &mut [u8],
111 ) -> TpmResult<(&mut Self, &mut [u8])> {
112 let wire_len = Self::validate_prefix_items::<T>(buf)?;
113 if buf.len() < wire_len {
114 return Err(TpmError::UnexpectedEnd {
115 offset: 0,
116 needed: wire_len,
117 available: buf.len(),
118 });
119 }
120
121 let (head, tail) = buf.split_at_mut(wire_len);
122
123 Ok((unsafe { Self::cast_mut_unchecked(head) }, tail))
126 }
127
128 #[must_use]
130 pub const fn as_bytes(&self) -> &[u8] {
131 &self.0
132 }
133
134 #[must_use]
136 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
137 &mut self.0
138 }
139
140 #[must_use]
142 pub fn count(&self) -> usize {
143 Self::read_count(&self.0)
144 }
145
146 #[must_use]
148 pub fn items_bytes(&self) -> &[u8] {
149 &self.0[TPML_COUNT_LEN..]
150 }
151
152 #[must_use]
154 pub fn items<T: TpmCast + ?Sized>(&self) -> TpmlIter<'_, T> {
155 TpmlIter {
156 buf: self.items_bytes(),
157 remaining: self.count(),
158 _marker: PhantomData,
159 }
160 }
161
162 #[must_use]
164 pub fn items_bytes_mut(&mut self) -> &mut [u8] {
165 &mut self.0[TPML_COUNT_LEN..]
166 }
167
168 #[must_use]
170 pub const fn len(&self) -> usize {
171 self.0.len()
172 }
173
174 #[must_use]
176 pub fn is_empty(&self) -> bool {
177 self.count() == 0
178 }
179
180 pub fn validate(buf: &[u8]) -> TpmResult<()> {
187 Self::validate_header(buf).map(|_| ())
188 }
189
190 pub fn validate_items<T: TpmCast + ?Sized>(buf: &[u8]) -> TpmResult<()> {
196 let wire_len = Self::validate_prefix_items::<T>(buf)?;
197
198 if buf.len() > wire_len {
199 return Err(TpmError::TrailingData {
200 offset: wire_len,
201 actual: buf.len() - wire_len,
202 });
203 }
204
205 Ok(())
206 }
207
208 pub fn validate_prefix_items<T: TpmCast + ?Sized>(buf: &[u8]) -> TpmResult<usize> {
214 let count = Self::validate_header(buf)?;
215 let mut cursor = &buf[TPML_COUNT_LEN..];
216 let mut consumed = TPML_COUNT_LEN;
217
218 for _ in 0..count {
219 let before = cursor.len();
220 let (_, tail) = T::cast_prefix(cursor)?;
221 let item_len = before
222 .checked_sub(tail.len())
223 .ok_or(TpmError::IntegerTooLarge {
224 offset: consumed,
225 value: crate::tpm_value(tail.len()),
226 })?;
227 consumed = consumed
228 .checked_add(item_len)
229 .ok_or(TpmError::IntegerTooLarge {
230 offset: consumed,
231 value: crate::tpm_value(before),
232 })?;
233 cursor = tail;
234 }
235
236 Ok(consumed)
237 }
238
239 fn validate_header(buf: &[u8]) -> TpmResult<usize> {
240 if buf.len() < TPML_COUNT_LEN {
241 return Err(TpmError::UnexpectedEnd {
242 offset: 0,
243 needed: TPML_COUNT_LEN,
244 available: buf.len(),
245 });
246 }
247
248 let item_count = Self::read_count(buf);
249 if item_count > CAPACITY {
250 return Err(TpmError::TooManyItems {
251 offset: 0,
252 limit: CAPACITY,
253 actual: item_count,
254 });
255 }
256
257 Ok(item_count)
258 }
259
260 fn read_count(buf: &[u8]) -> usize {
261 let raw = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
262
263 raw as usize
264 }
265}
266
267pub struct TpmlIter<'a, T: TpmCast + ?Sized> {
269 buf: &'a [u8],
270 remaining: usize,
271 _marker: PhantomData<&'a T>,
272}
273
274impl<'a, T: TpmCast + ?Sized> Iterator for TpmlIter<'a, T> {
275 type Item = TpmResult<&'a T>;
276
277 fn next(&mut self) -> Option<Self::Item> {
278 if self.remaining == 0 {
279 return None;
280 }
281
282 self.remaining -= 1;
283
284 match T::cast_prefix(self.buf) {
285 Ok((item, tail)) => {
286 self.buf = tail;
287 Some(Ok(item))
288 }
289 Err(err) => {
290 self.buf = &[];
291 self.remaining = 0;
292 Some(Err(err))
293 }
294 }
295 }
296}
297
298impl<const CAPACITY: usize> TpmCast for Tpml<CAPACITY> {
299 fn cast(buf: &[u8]) -> TpmResult<&Self> {
300 Self::cast(buf)
301 }
302
303 unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
304 unsafe { Self::cast_unchecked(buf) }
306 }
307}
308
309impl<const CAPACITY: usize> TpmCastMut for Tpml<CAPACITY> {
310 fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
311 Self::cast_mut(buf)
312 }
313
314 unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
315 unsafe { Self::cast_mut_unchecked(buf) }
318 }
319}
320
321impl<'a, T: crate::TpmField<'a> + Copy, const CAPACITY: usize> crate::TpmField<'a>
322 for TpmList<T, CAPACITY>
323{
324 type View = &'a Tpml<CAPACITY>;
325
326 fn cast_prefix_field(buf: &'a [u8]) -> TpmResult<(Self::View, &'a [u8])> {
327 let count = Tpml::<CAPACITY>::validate_header(buf)?;
328 let mut cursor = &buf[TPML_COUNT_LEN..];
329 let mut consumed = TPML_COUNT_LEN;
330
331 for _ in 0..count {
332 let before = cursor.len();
333 let (_, tail) = T::cast_prefix_field(cursor)?;
334 let item_len = before
335 .checked_sub(tail.len())
336 .ok_or(TpmError::IntegerTooLarge {
337 offset: consumed,
338 value: crate::tpm_value(tail.len()),
339 })?;
340 consumed = consumed
341 .checked_add(item_len)
342 .ok_or(TpmError::IntegerTooLarge {
343 offset: consumed,
344 value: crate::tpm_value(before),
345 })?;
346 cursor = tail;
347 }
348
349 if buf.len() < consumed {
350 return Err(TpmError::UnexpectedEnd {
351 offset: 0,
352 needed: consumed,
353 available: buf.len(),
354 });
355 }
356
357 let (head, tail) = buf.split_at(consumed);
358
359 Ok((unsafe { Tpml::<CAPACITY>::cast_unchecked(head) }, tail))
361 }
362}
363
364crate::tpm_byte_view!(Tpml<const CAPACITY: usize>);
365
366#[derive(Clone, Copy)]
368pub struct TpmList<T: Copy, const CAPACITY: usize> {
369 items: [MaybeUninit<T>; CAPACITY],
370 len: usize,
371}
372
373impl<T: Copy, const CAPACITY: usize> TpmList<T, CAPACITY> {
374 #[must_use]
376 pub fn new() -> Self {
377 Self {
378 items: [const { MaybeUninit::uninit() }; CAPACITY],
379 len: 0,
380 }
381 }
382
383 #[must_use]
385 pub fn is_empty(&self) -> bool {
386 self.len == 0
387 }
388
389 pub fn try_push(&mut self, item: T) -> Result<(), TpmError> {
396 if self.len >= CAPACITY {
397 return Err(TpmError::TooManyItems {
398 offset: 0,
399 limit: CAPACITY,
400 actual: self.len + 1,
401 });
402 }
403 self.items[self.len].write(item);
404 self.len += 1;
405 Ok(())
406 }
407
408 pub fn try_extend_from_slice(&mut self, slice: &[T]) -> Result<(), TpmError> {
415 let new_len = self
416 .len
417 .checked_add(slice.len())
418 .ok_or(TpmError::TooManyItems {
419 offset: 0,
420 limit: CAPACITY,
421 actual: usize::MAX,
422 })?;
423
424 if new_len > CAPACITY {
425 return Err(TpmError::TooManyItems {
426 offset: 0,
427 limit: CAPACITY,
428 actual: new_len,
429 });
430 }
431
432 for (dest, src) in self.items[self.len..new_len].iter_mut().zip(slice) {
433 dest.write(*src);
434 }
435 self.len = new_len;
436 Ok(())
437 }
438}
439
440impl<T: Copy, const CAPACITY: usize> Deref for TpmList<T, CAPACITY> {
441 type Target = [T];
442
443 fn deref(&self) -> &Self::Target {
444 unsafe { slice::from_raw_parts(self.items.as_ptr().cast::<T>(), self.len) }
447 }
448}
449
450impl<T: Copy, const CAPACITY: usize> Default for TpmList<T, CAPACITY> {
451 fn default() -> Self {
452 Self::new()
453 }
454}
455
456impl<T: Copy + Debug, const CAPACITY: usize> Debug for TpmList<T, CAPACITY> {
457 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
458 f.debug_list().entries(self.iter()).finish()
459 }
460}
461
462impl<T: Copy + PartialEq, const CAPACITY: usize> PartialEq for TpmList<T, CAPACITY> {
463 fn eq(&self, other: &Self) -> bool {
464 **self == **other
465 }
466}
467
468impl<T: Copy + Eq, const CAPACITY: usize> Eq for TpmList<T, CAPACITY> {}
469
470impl<T: TpmSized + Copy, const CAPACITY: usize> TpmSized for TpmList<T, CAPACITY> {
471 const SIZE: usize = size_of::<TpmUint32>() + (T::SIZE * CAPACITY);
472 fn len(&self) -> usize {
473 size_of::<TpmUint32>() + self.iter().map(TpmSized::len).sum::<usize>()
474 }
475}
476
477impl<T: TpmMarshal + Copy, const CAPACITY: usize> TpmMarshal for TpmList<T, CAPACITY> {
478 fn marshal(&self, writer: &mut crate::TpmWriter) -> TpmResult<()> {
479 let len = TpmUint32::try_from(self.len).map_err(|_| TpmError::IntegerTooLarge {
480 offset: 0,
481 value: crate::tpm_value(self.len),
482 })?;
483 TpmMarshal::marshal(&len, writer)?;
484 for item in &**self {
485 TpmMarshal::marshal(item, writer)?;
486 }
487 Ok(())
488 }
489}