#![cfg_attr(not(test), no_std)]
#![deny(unsafe_code)]
#![deny(clippy::all)]
#![deny(clippy::pedantic)]
#![recursion_limit = "256"]
pub mod basic;
pub mod constant;
pub mod data;
#[macro_use]
pub mod r#macro;
pub mod frame;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum TpmProtocolError {
BufferOverflow,
IntegerTooLarge,
InvalidBoolean,
InvalidCc,
InvalidMagicNumber,
InvalidTag,
TooManyBytes,
TooManyItems,
TrailingData,
UnexpectedEnd,
VariantNotAvailable,
}
impl core::fmt::Display for TpmProtocolError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::BufferOverflow => write!(f, "buffer overflow"),
Self::InvalidBoolean => write!(f, "invalid boolean value"),
Self::InvalidCc => write!(f, "invalid command code"),
Self::InvalidMagicNumber => write!(f, "invalid magic number"),
Self::InvalidTag => write!(f, "invalid tag"),
Self::IntegerTooLarge => write!(f, "integer overflow"),
Self::TooManyBytes => write!(f, "buffer capacity surpassed"),
Self::TooManyItems => write!(f, "list capaacity surpassed"),
Self::TrailingData => write!(f, "trailing data"),
Self::UnexpectedEnd => write!(f, "unexpected end"),
Self::VariantNotAvailable => write!(f, "enum variant is not available"),
}
}
}
impl core::error::Error for TpmProtocolError {}
pub type TpmResult<T> = Result<T, TpmProtocolError>;
pub struct TpmWriter<'a> {
buffer: &'a mut [u8],
cursor: usize,
}
impl<'a> TpmWriter<'a> {
#[must_use]
pub fn new(buffer: &'a mut [u8]) -> Self {
Self { buffer, cursor: 0 }
}
#[must_use]
pub fn len(&self) -> usize {
self.cursor
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.cursor == 0
}
pub fn write_bytes(&mut self, bytes: &[u8]) -> TpmResult<()> {
let end = self
.cursor
.checked_add(bytes.len())
.ok_or(TpmProtocolError::BufferOverflow)?;
if end > self.buffer.len() {
return Err(TpmProtocolError::BufferOverflow);
}
self.buffer[self.cursor..end].copy_from_slice(bytes);
self.cursor = end;
Ok(())
}
}
pub trait TpmSized {
const SIZE: usize;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub trait TpmMarshal {
fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()>;
}
pub trait TpmUnmarshal: Sized + TpmSized {
fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])>;
}
pub trait TpmTagged {
type Tag: TpmUnmarshal + TpmMarshal + Copy;
type Value;
}
pub trait TpmUnmarshalTagged: Sized {
fn unmarshal_tagged(tag: <Self as TpmTagged>::Tag, buf: &[u8]) -> TpmResult<(Self, &[u8])>
where
Self: TpmTagged,
<Self as TpmTagged>::Tag: TpmUnmarshal + TpmMarshal;
}