1use super::{TPM_DISPATCH_TABLE, TPM_HEADER_SIZE};
6use crate::{
7 TpmCast, TpmCastMut, TpmError, TpmResult,
8 constant::MAX_SESSIONS,
9 data::{TpmCc, TpmRc, TpmRcBase, TpmSt},
10};
11use core::{mem::size_of, ops::Range};
12
13const HEADER_SIZE: usize = TPM_HEADER_SIZE as usize;
14const TAG_OFFSET: usize = 0;
15const SIZE_OFFSET: usize = 2;
16const CODE_OFFSET: usize = 6;
17
18#[repr(transparent)]
20pub struct TpmCommand([u8]);
21
22impl TpmCommand {
23 pub fn cast(buf: &[u8]) -> TpmResult<&Self> {
29 Self::validate_envelope(buf)?;
30
31 Ok(unsafe { Self::cast_unchecked(buf) })
34 }
35
36 pub fn cast_prefix(buf: &[u8]) -> TpmResult<(&Self, &[u8])> {
43 let frame_len = frame_prefix_size(buf)?;
44 let (frame, tail) = buf.split_at(frame_len);
45
46 Self::validate_envelope(frame)?;
47
48 Ok((unsafe { Self::cast_unchecked(frame) }, tail))
50 }
51
52 #[must_use]
59 pub unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
60 let ptr = core::ptr::from_ref(buf) as *const Self;
61
62 unsafe { &*ptr }
65 }
66
67 pub fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
73 Self::validate_envelope(buf)?;
74
75 Ok(unsafe { Self::cast_mut_unchecked(buf) })
79 }
80
81 pub fn cast_prefix_mut(buf: &mut [u8]) -> TpmResult<(&mut Self, &mut [u8])> {
88 let frame_len = frame_prefix_size(buf)?;
89 let (frame, tail) = buf.split_at_mut(frame_len);
90
91 Self::validate_envelope(frame)?;
92
93 Ok((unsafe { Self::cast_mut_unchecked(frame) }, tail))
95 }
96
97 #[must_use]
105 pub unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
106 let ptr = core::ptr::from_mut(buf) as *mut Self;
107
108 unsafe { &mut *ptr }
111 }
112
113 #[must_use]
115 pub const fn as_bytes(&self) -> &[u8] {
116 &self.0
117 }
118
119 #[must_use]
121 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
122 &mut self.0
123 }
124
125 pub fn tag(&self) -> TpmResult<TpmSt> {
132 let raw = read_u16(&self.0, TAG_OFFSET);
133
134 TpmSt::try_from(raw).map_err(|_| {
135 TpmError::InvalidTag(crate::TpmErrorValue::new(TAG_OFFSET).value(u64::from(raw)))
136 })
137 }
138
139 #[must_use]
141 pub fn size(&self) -> u32 {
142 read_u32(&self.0, SIZE_OFFSET)
143 }
144
145 pub fn cc(&self) -> TpmResult<TpmCc> {
152 command_code(&self.0)
153 }
154
155 pub fn set_tag(&mut self, tag: TpmSt) {
157 write_u16(&mut self.0, TAG_OFFSET, tag.value());
158 }
159
160 pub fn set_cc(&mut self, cc: TpmCc) -> TpmResult<()> {
167 let _ = dispatch_for(cc)?;
168
169 write_u32(&mut self.0, CODE_OFFSET, cc.value());
170 Ok(())
171 }
172
173 pub fn handles(&self) -> TpmResult<&[u8]> {
179 let range = self.handle_area_range()?;
180
181 Ok(&self.0[range])
182 }
183
184 pub fn handles_mut(&mut self) -> TpmResult<&mut [u8]> {
190 let range = self.handle_area_range()?;
191
192 Ok(&mut self.0[range])
193 }
194
195 pub fn auth_area(&self) -> TpmResult<&[u8]> {
202 let (auth_area, _) = self.session_and_parameter_ranges()?;
203
204 Ok(&self.0[auth_area])
205 }
206
207 pub fn auth_area_mut(&mut self) -> TpmResult<&mut [u8]> {
214 let (auth_area, _) = self.session_and_parameter_ranges()?;
215
216 Ok(&mut self.0[auth_area])
217 }
218
219 pub fn parameters(&self) -> TpmResult<&[u8]> {
225 let (_, parameters) = self.session_and_parameter_ranges()?;
226
227 Ok(&self.0[parameters])
228 }
229
230 pub fn parameters_mut(&mut self) -> TpmResult<&mut [u8]> {
236 let (_, parameters) = self.session_and_parameter_ranges()?;
237
238 Ok(&mut self.0[parameters])
239 }
240
241 pub fn validate(&self) -> TpmResult<()> {
247 Self::validate_envelope(&self.0)?;
248 let auth_area = self.auth_area()?;
249
250 validate_auth_commands(&self.0, auth_area)
251 }
252
253 #[must_use]
255 pub const fn is_empty(&self) -> bool {
256 self.0.is_empty()
257 }
258
259 #[must_use]
261 pub const fn len(&self) -> usize {
262 self.0.len()
263 }
264
265 fn handle_area_range(&self) -> TpmResult<Range<usize>> {
266 let dispatch = dispatch_for(self.cc()?)?;
267 let handle_area_size = handle_area_size(dispatch.handles, HEADER_SIZE)?;
268 let handle_area_end =
269 HEADER_SIZE
270 .checked_add(handle_area_size)
271 .ok_or(TpmError::IntegerTooLarge(
272 crate::TpmErrorValue::new(HEADER_SIZE).value_usize(handle_area_size),
273 ))?;
274
275 if self.0.len() < handle_area_end {
276 return Err(TpmError::UnexpectedEnd(
277 crate::TpmErrorValue::new(HEADER_SIZE)
278 .size(handle_area_size, self.0.len().saturating_sub(HEADER_SIZE)),
279 ));
280 }
281
282 Ok(HEADER_SIZE..handle_area_end)
283 }
284
285 fn session_and_parameter_ranges(&self) -> TpmResult<(Range<usize>, Range<usize>)> {
286 let handle_area = self.handle_area_range()?;
287 let tag = self.tag()?;
288 let after_handles_start = handle_area.end;
289
290 if tag != TpmSt::Sessions {
291 return Ok((
292 after_handles_start..after_handles_start,
293 after_handles_start..self.0.len(),
294 ));
295 }
296
297 let after_handles = &self.0[after_handles_start..];
298
299 if after_handles.len() < size_of::<u32>() {
300 return Err(TpmError::UnexpectedEnd(
301 crate::TpmErrorValue::new(after_handles_start)
302 .size(size_of::<u32>(), after_handles.len()),
303 ));
304 }
305
306 let auth_size = read_u32(after_handles, 0) as usize;
307 let auth_start = size_of::<u32>();
308 let auth_end = auth_start
309 .checked_add(auth_size)
310 .ok_or(TpmError::IntegerTooLarge(
311 crate::TpmErrorValue::new(after_handles_start).value_usize(auth_size),
312 ))?;
313
314 if after_handles.len() < auth_end {
315 return Err(TpmError::UnexpectedEnd(
316 crate::TpmErrorValue::new(after_handles_start + auth_start)
317 .size(auth_size, after_handles.len().saturating_sub(auth_start)),
318 ));
319 }
320
321 let auth_start = after_handles_start + auth_start;
322 let auth_end = after_handles_start + auth_end;
323
324 Ok((auth_start..auth_end, auth_end..self.0.len()))
325 }
326
327 fn validate_envelope(buf: &[u8]) -> TpmResult<()> {
328 validate_frame_size(buf)?;
329
330 let raw_tag = read_u16(buf, TAG_OFFSET);
331 let tag = TpmSt::try_from(raw_tag).map_err(|_| {
332 TpmError::InvalidTag(crate::TpmErrorValue::new(TAG_OFFSET).value(u64::from(raw_tag)))
333 })?;
334 if tag != TpmSt::NoSessions && tag != TpmSt::Sessions {
335 return Err(TpmError::InvalidTag(
336 crate::TpmErrorValue::new(TAG_OFFSET).value(u64::from(raw_tag)),
337 ));
338 }
339
340 let dispatch = dispatch_for(command_code(buf)?)?;
341 let body = &buf[HEADER_SIZE..];
342 let handle_area_size = handle_area_size(dispatch.handles, HEADER_SIZE)?;
343
344 if body.len() < handle_area_size {
345 return Err(TpmError::UnexpectedEnd(
346 crate::TpmErrorValue::new(HEADER_SIZE).size(handle_area_size, body.len()),
347 ));
348 }
349
350 if tag == TpmSt::Sessions {
351 let after_handles = &body[handle_area_size..];
352 if after_handles.len() < size_of::<u32>() {
353 return Err(TpmError::UnexpectedEnd(
354 crate::TpmErrorValue::new(HEADER_SIZE + handle_area_size)
355 .size(size_of::<u32>(), after_handles.len()),
356 ));
357 }
358
359 let auth_size = read_u32(after_handles, 0) as usize;
360 let auth_end =
361 size_of::<u32>()
362 .checked_add(auth_size)
363 .ok_or(TpmError::IntegerTooLarge(
364 crate::TpmErrorValue::new(HEADER_SIZE + handle_area_size)
365 .value_usize(auth_size),
366 ))?;
367
368 if after_handles.len() < auth_end {
369 return Err(TpmError::UnexpectedEnd(
370 crate::TpmErrorValue::new(HEADER_SIZE + handle_area_size + size_of::<u32>())
371 .size(
372 auth_size,
373 after_handles.len().saturating_sub(size_of::<u32>()),
374 ),
375 ));
376 }
377 }
378
379 Ok(())
380 }
381}
382
383impl TpmCast for TpmCommand {
384 fn cast(buf: &[u8]) -> TpmResult<&Self> {
385 Self::cast(buf)
386 }
387
388 fn cast_prefix(buf: &[u8]) -> TpmResult<(&Self, &[u8])> {
389 Self::cast_prefix(buf)
390 }
391
392 unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
393 unsafe { Self::cast_unchecked(buf) }
395 }
396}
397
398impl TpmCastMut for TpmCommand {
399 fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
400 Self::cast_mut(buf)
401 }
402
403 fn cast_prefix_mut(buf: &mut [u8]) -> TpmResult<(&mut Self, &mut [u8])> {
404 Self::cast_prefix_mut(buf)
405 }
406
407 unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
408 unsafe { Self::cast_mut_unchecked(buf) }
411 }
412}
413
414impl AsRef<[u8]> for TpmCommand {
415 fn as_ref(&self) -> &[u8] {
416 self.as_bytes()
417 }
418}
419
420impl AsMut<[u8]> for TpmCommand {
421 fn as_mut(&mut self) -> &mut [u8] {
422 self.as_bytes_mut()
423 }
424}
425
426#[repr(transparent)]
428pub struct TpmResponse([u8]);
429
430impl TpmResponse {
431 pub fn cast(buf: &[u8]) -> TpmResult<&Self> {
437 Self::validate_envelope(buf)?;
438
439 Ok(unsafe { Self::cast_unchecked(buf) })
442 }
443
444 pub fn cast_prefix(buf: &[u8]) -> TpmResult<(&Self, &[u8])> {
451 let frame_len = frame_prefix_size(buf)?;
452 let (frame, tail) = buf.split_at(frame_len);
453
454 Self::validate_envelope(frame)?;
455
456 Ok((unsafe { Self::cast_unchecked(frame) }, tail))
458 }
459
460 #[must_use]
467 pub unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
468 let ptr = core::ptr::from_ref(buf) as *const Self;
469
470 unsafe { &*ptr }
473 }
474
475 pub fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
481 Self::validate_envelope(buf)?;
482
483 Ok(unsafe { Self::cast_mut_unchecked(buf) })
487 }
488
489 pub fn cast_prefix_mut(buf: &mut [u8]) -> TpmResult<(&mut Self, &mut [u8])> {
496 let frame_len = frame_prefix_size(buf)?;
497 let (frame, tail) = buf.split_at_mut(frame_len);
498
499 Self::validate_envelope(frame)?;
500
501 Ok((unsafe { Self::cast_mut_unchecked(frame) }, tail))
503 }
504
505 #[must_use]
513 pub unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
514 let ptr = core::ptr::from_mut(buf) as *mut Self;
515
516 unsafe { &mut *ptr }
519 }
520
521 #[must_use]
523 pub const fn as_bytes(&self) -> &[u8] {
524 &self.0
525 }
526
527 #[must_use]
529 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
530 &mut self.0
531 }
532
533 pub fn tag(&self) -> TpmResult<TpmSt> {
540 let raw = read_u16(&self.0, TAG_OFFSET);
541
542 TpmSt::try_from(raw).map_err(|_| {
543 TpmError::InvalidTag(crate::TpmErrorValue::new(TAG_OFFSET).value(u64::from(raw)))
544 })
545 }
546
547 #[must_use]
549 pub fn size(&self) -> u32 {
550 read_u32(&self.0, SIZE_OFFSET)
551 }
552
553 pub fn rc(&self) -> TpmResult<TpmRc> {
559 let raw = read_u32(&self.0, CODE_OFFSET);
560
561 TpmRc::try_from(raw).map_err(|_| {
562 TpmError::InvalidRc(crate::TpmErrorValue::new(CODE_OFFSET).value(u64::from(raw)))
563 })
564 }
565
566 pub fn set_tag(&mut self, tag: TpmSt) {
568 write_u16(&mut self.0, TAG_OFFSET, tag.value());
569 }
570
571 pub fn set_rc(&mut self, rc: TpmRc) {
573 write_u32(&mut self.0, CODE_OFFSET, rc.value());
574 }
575
576 #[must_use]
578 pub fn body(&self) -> &[u8] {
579 &self.0[HEADER_SIZE..]
580 }
581
582 #[must_use]
584 pub fn body_mut(&mut self) -> &mut [u8] {
585 &mut self.0[HEADER_SIZE..]
586 }
587
588 pub fn validate(&self, cc: TpmCc) -> TpmResult<()> {
595 Self::validate_envelope(&self.0)?;
596 let dispatch = dispatch_for(cc)?;
597
598 if !matches!(self.rc()?, TpmRc::Fmt0(TpmRcBase::Success)) {
599 return Ok(());
600 }
601
602 if self.tag()? != TpmSt::Sessions {
603 return Ok(());
604 }
605
606 let handle_area_size = handle_area_size(dispatch.response_handles, HEADER_SIZE)?;
607 let body = self.body();
608 if body.len() < handle_area_size {
609 return Err(TpmError::UnexpectedEnd(
610 crate::TpmErrorValue::new(HEADER_SIZE).size(handle_area_size, body.len()),
611 ));
612 }
613
614 let after_handles = &body[handle_area_size..];
615 if after_handles.len() < size_of::<u32>() {
616 return Err(TpmError::UnexpectedEnd(
617 crate::TpmErrorValue::new(HEADER_SIZE + handle_area_size)
618 .size(size_of::<u32>(), after_handles.len()),
619 ));
620 }
621
622 let params_len = read_u32(after_handles, 0) as usize;
623 let sessions_start =
624 size_of::<u32>()
625 .checked_add(params_len)
626 .ok_or(TpmError::IntegerTooLarge(
627 crate::TpmErrorValue::new(HEADER_SIZE + handle_area_size)
628 .value_usize(params_len),
629 ))?;
630
631 if after_handles.len() < sessions_start {
632 return Err(TpmError::UnexpectedEnd(
633 crate::TpmErrorValue::new(HEADER_SIZE + handle_area_size + size_of::<u32>()).size(
634 params_len,
635 after_handles.len().saturating_sub(size_of::<u32>()),
636 ),
637 ));
638 }
639
640 validate_auth_responses(&self.0, &after_handles[sessions_start..])
641 }
642
643 #[must_use]
645 pub const fn is_empty(&self) -> bool {
646 self.0.is_empty()
647 }
648
649 #[must_use]
651 pub const fn len(&self) -> usize {
652 self.0.len()
653 }
654
655 fn validate_envelope(buf: &[u8]) -> TpmResult<()> {
656 validate_frame_size(buf)?;
657 let raw_tag = read_u16(buf, TAG_OFFSET);
658 let _ = TpmSt::try_from(raw_tag).map_err(|_| {
659 TpmError::InvalidTag(crate::TpmErrorValue::new(TAG_OFFSET).value(u64::from(raw_tag)))
660 })?;
661 let raw_rc = read_u32(buf, CODE_OFFSET);
662 let _ = TpmRc::try_from(raw_rc).map_err(|_| {
663 TpmError::InvalidRc(crate::TpmErrorValue::new(CODE_OFFSET).value(u64::from(raw_rc)))
664 })?;
665
666 Ok(())
667 }
668}
669
670impl TpmCast for TpmResponse {
671 fn cast(buf: &[u8]) -> TpmResult<&Self> {
672 Self::cast(buf)
673 }
674
675 fn cast_prefix(buf: &[u8]) -> TpmResult<(&Self, &[u8])> {
676 Self::cast_prefix(buf)
677 }
678
679 unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
680 unsafe { Self::cast_unchecked(buf) }
682 }
683}
684
685impl TpmCastMut for TpmResponse {
686 fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
687 Self::cast_mut(buf)
688 }
689
690 fn cast_prefix_mut(buf: &mut [u8]) -> TpmResult<(&mut Self, &mut [u8])> {
691 Self::cast_prefix_mut(buf)
692 }
693
694 unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
695 unsafe { Self::cast_mut_unchecked(buf) }
698 }
699}
700
701impl AsRef<[u8]> for TpmResponse {
702 fn as_ref(&self) -> &[u8] {
703 self.as_bytes()
704 }
705}
706
707impl AsMut<[u8]> for TpmResponse {
708 fn as_mut(&mut self) -> &mut [u8] {
709 self.as_bytes_mut()
710 }
711}
712
713fn command_code(buf: &[u8]) -> TpmResult<TpmCc> {
714 let raw = read_u32(buf, CODE_OFFSET);
715
716 TpmCc::try_from(raw).map_err(|_| {
717 TpmError::InvalidCc(crate::TpmErrorValue::new(CODE_OFFSET).value(u64::from(raw)))
718 })
719}
720
721fn dispatch_for(cc: TpmCc) -> TpmResult<&'static super::TpmDispatch> {
722 TPM_DISPATCH_TABLE
723 .binary_search_by_key(&cc, |d| d.cc)
724 .map(|index| &TPM_DISPATCH_TABLE[index])
725 .map_err(|_| TpmError::InvalidCc(crate::TpmErrorValue::new(0).value(u64::from(cc.value()))))
726}
727
728fn validate_frame_size(buf: &[u8]) -> TpmResult<()> {
729 let size = frame_prefix_size(buf)?;
730
731 if buf.len() > size {
732 return Err(TpmError::TrailingData(
733 crate::TpmErrorValue::new(size).actual(buf.len() - size),
734 ));
735 }
736
737 Ok(())
738}
739
740fn handle_area_size(handles: usize, offset: usize) -> TpmResult<usize> {
741 handles
742 .checked_mul(size_of::<u32>())
743 .ok_or(TpmError::IntegerTooLarge(
744 crate::TpmErrorValue::new(offset).value_usize(handles),
745 ))
746}
747
748fn frame_prefix_size(buf: &[u8]) -> TpmResult<usize> {
749 if buf.len() < HEADER_SIZE {
750 return Err(TpmError::UnexpectedEnd(
751 crate::TpmErrorValue::new(0).size(HEADER_SIZE, buf.len()),
752 ));
753 }
754
755 let size = read_u32(buf, SIZE_OFFSET) as usize;
756 if buf.len() < size {
757 return Err(TpmError::UnexpectedEnd(
758 crate::TpmErrorValue::new(buf.len()).size(size - buf.len(), 0),
759 ));
760 }
761
762 Ok(size)
763}
764
765fn read_u16(buf: &[u8], offset: usize) -> u16 {
766 u16::from_be_bytes([buf[offset], buf[offset + 1]])
767}
768
769fn read_u32(buf: &[u8], offset: usize) -> u32 {
770 u32::from_be_bytes([
771 buf[offset],
772 buf[offset + 1],
773 buf[offset + 2],
774 buf[offset + 3],
775 ])
776}
777
778fn write_u16(buf: &mut [u8], offset: usize, value: u16) {
779 buf[offset..offset + size_of::<u16>()].copy_from_slice(&value.to_be_bytes());
780}
781
782fn write_u32(buf: &mut [u8], offset: usize, value: u32) {
783 buf[offset..offset + size_of::<u32>()].copy_from_slice(&value.to_be_bytes());
784}
785
786fn validate_auth_commands(base: &[u8], mut buf: &[u8]) -> TpmResult<()> {
787 let mut count = 0;
788
789 while !buf.is_empty() {
790 if count >= MAX_SESSIONS {
791 return Err(TpmError::TooManyItems(
792 crate::TpmErrorValue::at(base, buf).limit(MAX_SESSIONS, count + 1),
793 ));
794 }
795
796 if buf.len() < size_of::<u32>() {
797 return Err(TpmError::UnexpectedEnd(
798 crate::TpmErrorValue::at(base, buf).size(size_of::<u32>(), buf.len()),
799 ));
800 }
801
802 buf = &buf[size_of::<u32>()..];
803 buf = skip_tpm2b(base, buf)?;
804
805 if buf.is_empty() {
806 return Err(TpmError::UnexpectedEnd(
807 crate::TpmErrorValue::at(base, buf).size(1, 0),
808 ));
809 }
810
811 buf = &buf[1..];
812 buf = skip_tpm2b(base, buf)?;
813 count += 1;
814 }
815
816 Ok(())
817}
818
819fn validate_auth_responses(base: &[u8], mut buf: &[u8]) -> TpmResult<()> {
820 let mut count = 0;
821
822 while !buf.is_empty() {
823 if count >= MAX_SESSIONS {
824 return Err(TpmError::TooManyItems(
825 crate::TpmErrorValue::at(base, buf).limit(MAX_SESSIONS, count + 1),
826 ));
827 }
828
829 buf = skip_tpm2b(base, buf)?;
830
831 if buf.is_empty() {
832 return Err(TpmError::UnexpectedEnd(
833 crate::TpmErrorValue::at(base, buf).size(1, 0),
834 ));
835 }
836
837 buf = &buf[1..];
838 buf = skip_tpm2b(base, buf)?;
839 count += 1;
840 }
841
842 Ok(())
843}
844
845fn skip_tpm2b<'a>(base: &[u8], buf: &'a [u8]) -> TpmResult<&'a [u8]> {
846 if buf.len() < size_of::<u16>() {
847 return Err(TpmError::UnexpectedEnd(
848 crate::TpmErrorValue::at(base, buf).size(size_of::<u16>(), buf.len()),
849 ));
850 }
851
852 let size = read_u16(buf, 0) as usize;
853 let end = size_of::<u16>()
854 .checked_add(size)
855 .ok_or(TpmError::IntegerTooLarge(
856 crate::TpmErrorValue::at(base, buf).value_usize(size),
857 ))?;
858
859 if buf.len() < end {
860 return Err(TpmError::UnexpectedEnd(
861 crate::TpmErrorValue::at(base, buf).size(end, buf.len()),
862 ));
863 }
864
865 Ok(&buf[end..])
866}