#![allow(non_snake_case)]
use crate::{
tlcl::{tpm12::constants::*, tpm_exchange, unmarshal::unmarshal_response_code},
LOG_DBG,
};
#[rustfmt::skip]
const NV_DEFINESPACE_TEMPLATE: [u8; 101] = [
0x00, 0xc1,
0x00, 0x00, 0x00, 0x65,
0x00, 0x00, 0x00, 0xcc,
0x00, 0x18,
0x00, 0x00, 0x00, 0x00,
0x00, 0x03,
0x00, 0x00, 0x00,
0x1f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03,
0x00, 0x00, 0x00,
0x1f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x17,
0x00, 0x00, 0x00, 0x00,
0x00,
0x00,
0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
#[rustfmt::skip]
const GET_SPACE_INFO_CMD: [u8; 22] = [
0x00, 0xc1,
0x00, 0x00, 0x00, 0x16,
0x00, 0x00, 0x00, 0x65,
0x00, 0x00, 0x00, 0x11,
0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00,
];
const MAIN_OFFSET_INDEX: usize = 12;
const MAIN_OFFSET_PERM: usize = 70;
const MAIN_OFFSET_SIZE: usize = 77;
const SPACEINFO_OFFSET_INDEX: usize = 18;
fn patch_u32(buf: &mut [u8], offset: usize, val: u32) {
buf[offset] = (val >> 24) as u8;
buf[offset + 1] = (val >> 16) as u8;
buf[offset + 2] = (val >> 8) as u8;
buf[offset + 3] = (val & 0xFF) as u8;
}
pub fn TlclGetPermissions(index: u32) -> u32 {
let mut cmd_buf: [u8; 512] = [0; 512];
let mut resp_buf: [u8; 4096] = [0; 4096];
cmd_buf[..22].copy_from_slice(&GET_SPACE_INFO_CMD);
patch_u32(&mut cmd_buf, SPACEINFO_OFFSET_INDEX, index);
match tpm_exchange(&mut cmd_buf, &mut resp_buf) {
Ok(_) => {
let rc = unmarshal_response_code(&resp_buf);
if rc != TPM_SUCCESS {
LOG_DBG!("rc=0x{:x}", rc);
return 0xFFFFFFFF;
}
let mut off = 14usize;
off += 2;
off += 4;
let sos_r = u16::from_be_bytes([resp_buf[off], resp_buf[off + 1]]) as usize;
off += 2 + sos_r + 1 + 20;
let sos_w = u16::from_be_bytes([resp_buf[off], resp_buf[off + 1]]) as usize;
off += 2 + sos_w + 1 + 20;
off += 2;
u32::from_be_bytes([
resp_buf[off],
resp_buf[off + 1],
resp_buf[off + 2],
resp_buf[off + 3],
])
}
Err(e) => {
LOG_DBG!("tpm_exchange failed: {}", e);
0xFFFFFFFF
}
}
}
pub fn TlclDefineSpace(index: u32, perm: u32, size: u32) -> u32 {
TlclDefineSpaceEx(None, 0, index, perm, size, (), 0)
}
pub fn TlclDefineSpaceEx(
_owner_auth: Option<&[u8]>,
_owner_auth_size: u32,
index: u32,
perm: u32,
size: u32,
_auth_policy: (),
_auth_policy_size: u32,
) -> u32 {
let mut cmd_buf: [u8; 512] = [0; 512];
let mut resp_buf: [u8; 4096] = [0; 4096];
cmd_buf[..101].copy_from_slice(&NV_DEFINESPACE_TEMPLATE);
patch_u32(&mut cmd_buf, MAIN_OFFSET_INDEX, index);
patch_u32(&mut cmd_buf, MAIN_OFFSET_PERM, perm);
patch_u32(&mut cmd_buf, MAIN_OFFSET_SIZE, size);
LOG_DBG!("index=0x{:x}, perm=0x{:x}, size={}", index, perm, size);
match tpm_exchange(&mut cmd_buf, &mut resp_buf) {
Ok(_) => {
let rc = unmarshal_response_code(&resp_buf);
LOG_DBG!("rc=0x{:x}", rc);
rc
}
Err(e) => {
LOG_DBG!("tpm_exchange failed: {}", e);
0xFFFFFFFF
}
}
}
pub fn TlclUndefineSpace(index: u32) -> u32 {
TlclUndefineSpaceEx(None, 0, index)
}
pub fn TlclUndefineSpaceEx(owner_auth: Option<&[u8]>, owner_auth_size: u32, index: u32) -> u32 {
let perm = TlclGetPermissions(index);
if perm == 0xFFFFFFFF {
LOG_DBG!(
"space 0x{:x} does not exist or query failed",
index
);
return 0xFFFFFFFF;
}
TlclDefineSpaceEx(owner_auth, owner_auth_size, index, perm, 0, (), 0)
}