tpm2_protocol/basic/
list.rs1use crate::{
6 TpmCast, TpmCastMut, TpmMarshal, TpmProtocolError, TpmResult, TpmSized, TpmUnmarshal,
7 basic::TpmUint32,
8};
9use core::{
10 convert::TryFrom,
11 fmt::Debug,
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 #[must_use]
47 pub unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
48 let ptr = core::ptr::from_ref(buf) as *const Self;
49
50 unsafe { &*ptr }
53 }
54
55 pub fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
64 Self::validate(buf)?;
65
66 Ok(unsafe { Self::cast_mut_unchecked(buf) })
69 }
70
71 #[must_use]
79 pub unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
80 let ptr = core::ptr::from_mut(buf) as *mut Self;
81
82 unsafe { &mut *ptr }
85 }
86
87 #[must_use]
89 pub const fn as_bytes(&self) -> &[u8] {
90 &self.0
91 }
92
93 #[must_use]
95 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
96 &mut self.0
97 }
98
99 #[must_use]
101 pub fn count(&self) -> usize {
102 Self::read_count(&self.0)
103 }
104
105 #[must_use]
107 pub fn items_bytes(&self) -> &[u8] {
108 &self.0[TPML_COUNT_LEN..]
109 }
110
111 #[must_use]
113 pub fn items_bytes_mut(&mut self) -> &mut [u8] {
114 &mut self.0[TPML_COUNT_LEN..]
115 }
116
117 #[must_use]
119 pub const fn len(&self) -> usize {
120 self.0.len()
121 }
122
123 #[must_use]
125 pub fn is_empty(&self) -> bool {
126 self.count() == 0
127 }
128
129 fn validate(buf: &[u8]) -> TpmResult<()> {
130 if buf.len() < TPML_COUNT_LEN {
131 return Err(TpmProtocolError::UnexpectedEnd);
132 }
133
134 let item_count = Self::read_count(buf);
135 if item_count > CAPACITY {
136 return Err(TpmProtocolError::TooManyItems);
137 }
138
139 Ok(())
140 }
141
142 fn read_count(buf: &[u8]) -> usize {
143 let raw = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
144
145 raw as usize
146 }
147}
148
149impl<const CAPACITY: usize> TpmCast for Tpml<CAPACITY> {
150 fn cast(buf: &[u8]) -> TpmResult<&Self> {
151 Self::cast(buf)
152 }
153
154 unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
155 unsafe { Self::cast_unchecked(buf) }
157 }
158}
159
160impl<const CAPACITY: usize> TpmCastMut for Tpml<CAPACITY> {
161 fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
162 Self::cast_mut(buf)
163 }
164
165 unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
166 unsafe { Self::cast_mut_unchecked(buf) }
169 }
170}
171
172impl<const CAPACITY: usize> AsRef<[u8]> for Tpml<CAPACITY> {
173 fn as_ref(&self) -> &[u8] {
174 self.as_bytes()
175 }
176}
177
178impl<const CAPACITY: usize> AsMut<[u8]> for Tpml<CAPACITY> {
179 fn as_mut(&mut self) -> &mut [u8] {
180 self.as_bytes_mut()
181 }
182}
183
184#[derive(Clone, Copy)]
186pub struct TpmList<T: Copy, const CAPACITY: usize> {
187 items: [MaybeUninit<T>; CAPACITY],
188 len: usize,
189}
190
191impl<T: Copy, const CAPACITY: usize> TpmList<T, CAPACITY> {
192 #[must_use]
194 pub fn new() -> Self {
195 Self {
196 items: [const { MaybeUninit::uninit() }; CAPACITY],
197 len: 0,
198 }
199 }
200
201 #[must_use]
203 pub fn is_empty(&self) -> bool {
204 self.len == 0
205 }
206
207 pub fn try_push(&mut self, item: T) -> Result<(), TpmProtocolError> {
214 if self.len >= CAPACITY {
215 return Err(TpmProtocolError::TooManyItems);
216 }
217 self.items[self.len].write(item);
218 self.len += 1;
219 Ok(())
220 }
221
222 pub fn try_extend_from_slice(&mut self, slice: &[T]) -> Result<(), TpmProtocolError> {
229 let new_len = self
230 .len
231 .checked_add(slice.len())
232 .ok_or(TpmProtocolError::TooManyItems)?;
233
234 if new_len > CAPACITY {
235 return Err(TpmProtocolError::TooManyItems);
236 }
237
238 for (dest, src) in self.items[self.len..new_len].iter_mut().zip(slice) {
239 dest.write(*src);
240 }
241 self.len = new_len;
242 Ok(())
243 }
244}
245
246impl<T: Copy, const CAPACITY: usize> Deref for TpmList<T, CAPACITY> {
247 type Target = [T];
248
249 fn deref(&self) -> &Self::Target {
250 unsafe { slice::from_raw_parts(self.items.as_ptr().cast::<T>(), self.len) }
253 }
254}
255
256impl<T: Copy, const CAPACITY: usize> Default for TpmList<T, CAPACITY> {
257 fn default() -> Self {
258 Self::new()
259 }
260}
261
262impl<T: Copy + Debug, const CAPACITY: usize> Debug for TpmList<T, CAPACITY> {
263 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
264 f.debug_list().entries(self.iter()).finish()
265 }
266}
267
268impl<T: Copy + PartialEq, const CAPACITY: usize> PartialEq for TpmList<T, CAPACITY> {
269 fn eq(&self, other: &Self) -> bool {
270 **self == **other
271 }
272}
273
274impl<T: Copy + Eq, const CAPACITY: usize> Eq for TpmList<T, CAPACITY> {}
275
276impl<T: TpmSized + Copy, const CAPACITY: usize> TpmSized for TpmList<T, CAPACITY> {
277 const SIZE: usize = size_of::<TpmUint32>() + (T::SIZE * CAPACITY);
278 fn len(&self) -> usize {
279 size_of::<TpmUint32>() + self.iter().map(TpmSized::len).sum::<usize>()
280 }
281}
282
283impl<T: TpmMarshal + Copy, const CAPACITY: usize> TpmMarshal for TpmList<T, CAPACITY> {
284 fn marshal(&self, writer: &mut crate::TpmWriter) -> TpmResult<()> {
285 let len = TpmUint32::try_from(self.len).map_err(|_| TpmProtocolError::IntegerTooLarge)?;
286 TpmMarshal::marshal(&len, writer)?;
287 for item in &**self {
288 TpmMarshal::marshal(item, writer)?;
289 }
290 Ok(())
291 }
292}
293
294impl<T: TpmUnmarshal + Copy, const CAPACITY: usize> TpmUnmarshal for TpmList<T, CAPACITY> {
295 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
296 let (count_u32, mut buf) = TpmUint32::unmarshal(buf)?;
297 let count = u32::from(count_u32) as usize;
298 if count > CAPACITY {
299 return Err(TpmProtocolError::TooManyItems);
300 }
301
302 let mut list = Self::new();
303 for _ in 0..count {
304 let (item, rest) = T::unmarshal(buf)?;
305 list.try_push(item)?;
306 buf = rest;
307 }
308
309 Ok((list, buf))
310 }
311}