diff --git a/src/common.rs b/src/common.rs new file mode 100644 index 0000000..ea2c1aa --- /dev/null +++ b/src/common.rs @@ -0,0 +1,9 @@ +pub const PACKET_END_BYTE: u8 = 0x36; + +#[derive(Clone, Copy)] +#[repr(u8)] +pub enum PacketType { + Command = 0xC0, + Data = 0xDA, + Response = 0xAA, +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..f0108f0 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,5 @@ +#![no_std] + +mod common; + +pub mod tpm2; diff --git a/src/tpm2.rs b/src/tpm2.rs new file mode 100644 index 0000000..993f027 --- /dev/null +++ b/src/tpm2.rs @@ -0,0 +1,68 @@ +pub const PACKET_START_BYTE: u8 = 0xC9; + +pub use crate::common::{PacketType, PACKET_END_BYTE}; + +#[derive(PartialEq)] +#[non_exhaustive] +pub enum Tpm2Error { + InvalidPacket, +} + +pub struct Packet<'a> { + packet_type: PacketType, + payload: &'a [u8], +} + +impl<'a> Packet<'a> { + pub fn new(packet_type: PacketType) -> Self { + Packet { + packet_type, + payload: &[] as &[u8], + } + } + + pub fn with_payload(packet_type: PacketType, payload: &'a [u8]) -> Result { + if payload.len() > u16::MAX.into() { + return Err(Tpm2Error::InvalidPacket); + } + + Ok(Packet { + packet_type, + payload, + }) + } + + pub fn packet_type(&self) -> PacketType { + self.packet_type + } + + pub fn size(&self) -> usize { + self.payload.len() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn empty_packet() { + let packet = Packet::new(PacketType::Command); + assert_eq!(packet.size(), 0); + } + + #[test] + fn packet_with_payload() { + let payload: [u8; 4] = [0xca, 0xfe, 0xba, 0xbe]; + let result = Packet::with_payload(PacketType::Data, &payload); + assert!(result.is_ok()); + } + + #[test] + fn payload_too_large() { + let payload = [0u8; u16::MAX as usize + 1]; + let result = Packet::with_payload(PacketType::Response, &payload); + assert!(result.is_err()); + assert!(result.err().unwrap() == Tpm2Error::InvalidPacket); + } +}