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 buffer;
28pub mod constant;
29pub mod data;
30pub mod list;
31#[macro_use]
32pub mod r#macro;
33pub mod message;
34
35pub use buffer::TpmBuffer;
36pub use list::TpmList;
37
38use core::{convert::From, mem::size_of, result::Result};
39
40#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
42#[repr(transparent)]
43pub struct TpmHandle(pub u32);
44
45impl From<u32> for TpmHandle {
46 fn from(val: u32) -> Self {
47 Self(val)
48 }
49}
50
51impl From<TpmHandle> for u32 {
52 fn from(val: TpmHandle) -> Self {
53 val.0
54 }
55}
56
57impl TpmBuild for TpmHandle {
58 fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
59 TpmBuild::build(&self.0, writer)
60 }
61}
62
63impl TpmParse for TpmHandle {
64 fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
65 let (val, buf) = u32::parse(buf)?;
66 Ok((Self(val), buf))
67 }
68}
69
70impl TpmSized for TpmHandle {
71 const SIZE: usize = size_of::<u32>();
72 fn len(&self) -> usize {
73 Self::SIZE
74 }
75}
76
77impl core::fmt::Display for TpmHandle {
78 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79 core::fmt::Display::fmt(&self.0, f)
80 }
81}
82
83impl core::fmt::LowerHex for TpmHandle {
84 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
85 core::fmt::LowerHex::fmt(&self.0, f)
86 }
87}
88
89impl core::fmt::UpperHex for TpmHandle {
90 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
91 core::fmt::UpperHex::fmt(&self.0, f)
92 }
93}
94
95#[derive(Debug, PartialEq, Eq)]
96pub enum TpmDiscriminant {
97 Signed(i64),
98 Unsigned(u64),
99}
100
101impl core::fmt::LowerHex for TpmDiscriminant {
102 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
103 match self {
104 TpmDiscriminant::Signed(v) => write!(f, "{v:x}"),
105 TpmDiscriminant::Unsigned(v) => write!(f, "{v:x}"),
106 }
107 }
108}
109
110#[derive(Debug, PartialEq, Eq)]
111pub enum TpmError {
113 CapacityExceeded,
115 DataTruncated,
117 MalformedData,
119 TrailingData,
121 UnknownDiscriminant(&'static str, TpmDiscriminant),
123}
124
125impl core::fmt::Display for TpmError {
126 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
127 match self {
128 Self::CapacityExceeded => write!(f, "capacity exceeded"),
129 Self::DataTruncated => write!(f, "data truncated"),
130 Self::MalformedData => write!(f, "malformed data"),
131 Self::TrailingData => write!(f, "trailing data"),
132 Self::UnknownDiscriminant(type_name, value) => {
133 write!(f, "unknown discriminant: {type_name}: 0x{value:x}")
134 }
135 }
136 }
137}
138
139impl From<core::num::TryFromIntError> for TpmError {
140 fn from(_: core::num::TryFromIntError) -> Self {
141 Self::CapacityExceeded
142 }
143}
144
145pub type TpmResult<T> = Result<T, TpmError>;
146
147pub struct TpmWriter<'a> {
149 buffer: &'a mut [u8],
150 cursor: usize,
151}
152
153impl<'a> TpmWriter<'a> {
154 #[must_use]
156 pub fn new(buffer: &'a mut [u8]) -> Self {
157 Self { buffer, cursor: 0 }
158 }
159
160 #[must_use]
162 pub fn len(&self) -> usize {
163 self.cursor
164 }
165
166 #[must_use]
168 pub fn is_empty(&self) -> bool {
169 self.cursor == 0
170 }
171
172 pub fn write_bytes(&mut self, bytes: &[u8]) -> TpmResult<()> {
179 let end = self.cursor + bytes.len();
180 if end > self.buffer.len() {
181 return Err(TpmError::CapacityExceeded);
182 }
183 self.buffer[self.cursor..end].copy_from_slice(bytes);
184 self.cursor = end;
185 Ok(())
186 }
187}
188
189pub trait TpmSized {
192 const SIZE: usize;
195
196 fn len(&self) -> usize;
198
199 fn is_empty(&self) -> bool {
201 self.len() == 0
202 }
203}
204
205pub trait TpmBuild: TpmSized {
206 fn build(&self, writer: &mut TpmWriter) -> TpmResult<()>;
212}
213
214pub trait TpmParse: Sized + TpmSized {
215 fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])>;
223}
224
225pub trait TpmTagged {
227 type Tag: TpmParse + TpmBuild + Copy;
229 type Value;
231}
232
233pub trait TpmParseTagged: Sized {
235 fn parse_tagged(tag: <Self as TpmTagged>::Tag, buf: &[u8]) -> TpmResult<(Self, &[u8])>
243 where
244 Self: TpmTagged,
245 <Self as TpmTagged>::Tag: TpmParse + TpmBuild;
246}
247
248tpm_integer!(u8, Unsigned);
249tpm_integer!(i8, Signed);
250tpm_integer!(i32, Signed);
251tpm_integer!(u16, Unsigned);
252tpm_integer!(u32, Unsigned);
253tpm_integer!(u64, Unsigned);