use crate::device::Device;
use crate::key::auth_ptr;
use crate::{check_rc, sys, Result};
use alloc::vec;
use alloc::vec::Vec;
use zeroize::Zeroize;
pub struct NvSlot<'d> {
nv: sys::WOLFTPM2_NV,
index: u32,
_marker: core::marker::PhantomData<&'d Device>,
}
impl<'d> NvSlot<'d> {
pub fn index(&self) -> u32 {
self.index
}
}
fn owner_handle() -> sys::WOLFTPM2_HANDLE {
let mut h: sys::WOLFTPM2_HANDLE = unsafe { core::mem::zeroed() };
h.hndl = sys::TPM_RH_T_TPM_RH_OWNER as sys::TPM_HANDLE;
h
}
impl Device {
pub fn nv_create(&self, index: u32, size: u32, auth: Option<&[u8]>) -> Result<NvSlot<'_>> {
let attrs = sys::TPMA_NV_AUTHREAD | sys::TPMA_NV_AUTHWRITE;
let mut nv: sys::WOLFTPM2_NV = unsafe { core::mem::zeroed() };
let mut parent = owner_handle();
let (authp, authsz) = auth_ptr(auth)?;
let rc = unsafe {
sys::wolfTPM2_NVCreateAuth(
self.ptr(),
&mut parent,
&mut nv,
index,
attrs,
size,
authp,
authsz,
)
};
check_rc(rc)?;
Ok(NvSlot {
nv,
index,
_marker: core::marker::PhantomData,
})
}
pub fn nv_write(&self, slot: &mut NvSlot<'_>, data: &[u8], offset: u32) -> Result<()> {
let mut buf = data.to_vec();
let n = crate::checked_u32(buf.len())?;
let rc = unsafe {
sys::wolfTPM2_NVWriteAuth(
self.ptr(),
&mut slot.nv,
slot.index,
buf.as_mut_ptr(),
n,
offset,
)
};
buf.zeroize();
check_rc(rc)
}
pub fn nv_read(&self, slot: &mut NvSlot<'_>, buf: &mut [u8], offset: u32) -> Result<usize> {
let mut sz = crate::checked_u32(buf.len())?;
let rc = unsafe {
sys::wolfTPM2_NVReadAuth(
self.ptr(),
&mut slot.nv,
slot.index,
buf.as_mut_ptr(),
&mut sz,
offset,
)
};
check_rc(rc)?;
Ok(sz as usize)
}
pub fn nv_delete(&self, index: u32) -> Result<()> {
let mut parent = owner_handle();
let rc = unsafe { sys::wolfTPM2_NVDeleteAuth(self.ptr(), &mut parent, index) };
check_rc(rc)
}
#[cfg(nvcert)]
pub fn read_cert(&self, nv_handle: u32) -> Result<Vec<u8>> {
let mut buf = vec![0u8; 2048];
let mut len = buf.len() as u32;
let rc =
unsafe { sys::wolfTPM2_NVReadCert(self.ptr(), nv_handle, buf.as_mut_ptr(), &mut len) };
check_rc(rc)?;
buf.truncate(len as usize);
Ok(buf)
}
}
impl<'d> Drop for NvSlot<'d> {
fn drop(&mut self) {
unsafe { crate::zeroize_raw(&mut self.nv) };
}
}