1#![cfg_attr(not(test), no_std)]
22#![deny(unsafe_code)]
23#![deny(clippy::all)]
24#![deny(clippy::pedantic)]
25#![recursion_limit = "256"]
26
27pub mod basic;
28pub mod constant;
29pub mod data;
30#[macro_use]
31pub mod r#macro;
32pub mod frame;
33
34#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
36#[repr(transparent)]
37pub struct TpmHandle(pub u32);
38
39impl core::convert::From<u32> for TpmHandle {
40 fn from(val: u32) -> Self {
41 Self(val)
42 }
43}
44
45impl core::convert::From<TpmHandle> for u32 {
46 fn from(val: TpmHandle) -> Self {
47 val.0
48 }
49}
50
51impl TpmMarshal for TpmHandle {
52 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
53 TpmMarshal::marshal(&self.0, writer)
54 }
55}
56
57impl TpmUnmarshal for TpmHandle {
58 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
59 let (val, buf) = u32::unmarshal(buf)?;
60 Ok((Self(val), buf))
61 }
62}
63
64impl TpmSized for TpmHandle {
65 const SIZE: usize = size_of::<u32>();
66 fn len(&self) -> usize {
67 Self::SIZE
68 }
69}
70
71impl core::fmt::Display for TpmHandle {
72 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73 core::fmt::Display::fmt(&self.0, f)
74 }
75}
76
77impl core::fmt::LowerHex for TpmHandle {
78 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79 core::fmt::LowerHex::fmt(&self.0, f)
80 }
81}
82
83impl core::fmt::UpperHex for TpmHandle {
84 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
85 core::fmt::UpperHex::fmt(&self.0, f)
86 }
87}
88
89#[derive(Debug, PartialEq, Eq)]
92pub enum TpmProtocolError {
93 BufferTooLarge,
95 InvalidAttestMagic,
98 InvalidBoolean,
100 InvalidCc,
102 InvalidTag,
105 OperationFailed,
107 TooManyItems,
109 TrailingData,
111 UnexpectedEnd,
113 VariantNotAvailable,
115}
116
117impl core::fmt::Display for TpmProtocolError {
118 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
119 match self {
120 Self::BufferTooLarge => write!(f, "buffer is too large"),
121 Self::InvalidAttestMagic => write!(f, "invalid attestation magic"),
122 Self::InvalidBoolean => write!(f, "invalid boolean value"),
123 Self::InvalidCc => write!(f, "invalid command code"),
124 Self::InvalidTag => write!(f, "invalid tag"),
125 Self::OperationFailed => write!(f, "operation failed"),
126 Self::TooManyItems => write!(f, "list has too many items"),
127 Self::TrailingData => write!(f, "trailing data"),
128 Self::UnexpectedEnd => write!(f, "unexpected end"),
129 Self::VariantNotAvailable => write!(f, "variant is not available"),
130 }
131 }
132}
133
134impl core::error::Error for TpmProtocolError {}
135
136pub type TpmResult<T> = Result<T, TpmProtocolError>;
137
138pub struct TpmWriter<'a> {
140 buffer: &'a mut [u8],
141 cursor: usize,
142}
143
144impl<'a> TpmWriter<'a> {
145 #[must_use]
147 pub fn new(buffer: &'a mut [u8]) -> Self {
148 Self { buffer, cursor: 0 }
149 }
150
151 #[must_use]
153 pub fn len(&self) -> usize {
154 self.cursor
155 }
156
157 #[must_use]
159 pub fn is_empty(&self) -> bool {
160 self.cursor == 0
161 }
162
163 pub fn write_bytes(&mut self, bytes: &[u8]) -> TpmResult<()> {
170 let end = self.cursor + bytes.len();
171 if end > self.buffer.len() {
172 return Err(TpmProtocolError::BufferTooLarge);
173 }
174 self.buffer[self.cursor..end].copy_from_slice(bytes);
175 self.cursor = end;
176 Ok(())
177 }
178}
179
180pub trait TpmSized {
183 const SIZE: usize;
186
187 fn len(&self) -> usize;
189
190 fn is_empty(&self) -> bool {
192 self.len() == 0
193 }
194}
195
196pub trait TpmMarshal: TpmSized {
197 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()>;
203}
204
205pub trait TpmUnmarshal: Sized + TpmSized {
206 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])>;
214}
215
216pub trait TpmTagged {
218 type Tag: TpmUnmarshal + TpmMarshal + Copy;
220 type Value;
222}
223
224pub trait TpmUnmarshalTagged: Sized {
226 fn unmarshal_tagged(tag: <Self as TpmTagged>::Tag, buf: &[u8]) -> TpmResult<(Self, &[u8])>
234 where
235 Self: TpmTagged,
236 <Self as TpmTagged>::Tag: TpmUnmarshal + TpmMarshal;
237}
238
239tpm_integer!(u8, Unsigned);
240tpm_integer!(i8, Signed);
241tpm_integer!(i32, Signed);
242tpm_integer!(u16, Unsigned);
243tpm_integer!(u32, Unsigned);
244tpm_integer!(u64, Unsigned);