#![no_std]
extern crate alloc;
pub mod sys;
#[cfg(all(wrapper, caps))]
mod caps;
#[cfg(wrapper)]
mod certify;
#[cfg(all(wrapper, ek_policy))]
mod credential;
#[cfg(wrapper)]
mod device;
#[cfg(all(wrapper, ecdh))]
mod ecdh;
#[cfg(all(wrapper, hmac))]
mod hmac;
#[cfg(wrapper)]
mod key;
#[cfg(all(wrapper, nv))]
mod nv;
#[cfg(all(wrapper, pcr))]
mod pcr;
#[cfg(all(wrapper, persist))]
mod persist;
#[cfg(all(wrapper, rsa))]
mod rsa;
#[cfg(all(wrapper, seal))]
mod seal;
#[cfg(wrapper)]
mod session;
#[cfg(wrapper)]
mod sign;
#[cfg(all(wrapper, symmetric))]
mod symmetric;
#[cfg(all(wrapper, caps))]
pub use caps::Caps;
#[cfg(wrapper)]
pub use certify::Attestation;
#[cfg(all(wrapper, ek_policy))]
pub use credential::Credential;
#[cfg(wrapper)]
pub use device::Device;
#[cfg(all(wrapper, ecdh))]
pub use ecdh::EcdhResult;
#[cfg(wrapper)]
pub use key::{HashAlg, Hierarchy, Key, KeyAlg, KeyBlob, Template};
#[cfg(all(wrapper, nv))]
pub use nv::NvSlot;
#[cfg(wrapper)]
pub use session::Session;
use alloc::vec::Vec;
use core::ffi::{c_int, CStr};
use core::fmt;
use zeroize::Zeroize;
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct TpmError(pub c_int);
impl TpmError {
pub fn code(&self) -> c_int {
self.0
}
}
impl fmt::Display for TpmError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
E_DEVICE_IN_USE => return write!(f, "another wolfTPM Device is already open"),
E_SESSION_IN_USE => {
return write!(
f,
"an encrypted session is active and conflicts with this two-authorization operation"
);
}
BUFFER_E => return write!(f, "buffer size error (BUFFER_E)"),
_ => {}
}
#[cfg(rc_string)]
{
let p = unsafe { sys::TPM2_GetRCString(self.0) };
if !p.is_null() {
let s = unsafe { CStr::from_ptr(p) };
return write!(f, "{} (0x{:x})", s.to_string_lossy(), self.0);
}
}
write!(f, "TPM error 0x{:x}", self.0)
}
}
impl fmt::Debug for TpmError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TpmError(0x{:x})", self.0)
}
}
impl core::error::Error for TpmError {}
pub type Result<T> = core::result::Result<T, TpmError>;
pub struct Secret(Vec<u8>);
impl Secret {
pub(crate) fn new(v: Vec<u8>) -> Self {
Secret(v)
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl core::ops::Deref for Secret {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.0
}
}
impl Drop for Secret {
fn drop(&mut self) {
self.0.zeroize();
}
}
#[inline]
pub(crate) fn check_rc(rc: c_int) -> Result<()> {
if rc == 0 {
Ok(())
} else {
Err(TpmError(rc))
}
}
#[inline]
pub(crate) fn checked_u32(n: usize) -> Result<u32> {
u32::try_from(n).map_err(|_| TpmError(BUFFER_E))
}
#[inline]
pub(crate) fn checked_c_int(n: usize) -> Result<c_int> {
i32::try_from(n).map_err(|_| TpmError(BUFFER_E))
}
pub(crate) const BUFFER_E: c_int = -132;
pub(crate) const E_DEVICE_IN_USE: c_int = -900;
pub(crate) const E_SESSION_IN_USE: c_int = -901;
pub(crate) unsafe fn zeroize_raw<T>(value: &mut T) {
unsafe {
core::slice::from_raw_parts_mut(value as *mut T as *mut u8, core::mem::size_of_val(value))
.zeroize();
}
}