libcros 0.6.6

A Rust library that provides easy-to-use functions for interacting with a Chrome device
Documentation
#![allow(non_snake_case)]

use crate::tlcl::{
  commands::tpm20::TlclNVReadPublic,
  constants::{TPM_E_BUFFER_SIZE, TPM_SUCCESS},
  tpm20::{
    constants::{
      HR_NV_INDEX, TPM_ALG_SHA256, TPM2_NV_DefineSpace, TPM2_NV_UndefineSpace, TPMA_NV_AUTHREAD,
      TPMA_NV_AUTHWRITE, TPMA_NV_MASK_READ, TPMA_NV_MASK_WRITE, TPMA_NV_PLATFORMCREATE,
      nv_read_public_response, tpm2_nv_define_space_cmd, tpm2_nv_undefine_space_cmd,
    },
    tpm_get_response_code,
  },
};

pub fn TlclGetPermissions(index: u32, permissions: &mut u32) -> u32 {
  let mut pub_resp: nv_read_public_response = unsafe { core::mem::zeroed() };
  let rv = TlclNVReadPublic(index, &mut pub_resp as *mut _ as *mut core::ffi::c_void);
  if rv != TPM_SUCCESS {
    return rv;
  }

  *permissions =
    unsafe { core::ptr::read_unaligned(core::ptr::addr_of!(pub_resp.nvPublic.attributes)) };
  TPM_SUCCESS
}

pub fn TlclDefineSpaceEx(
  owner_auth: *const u8,
  owner_auth_size: u32,
  index: u32,
  perm: u32,
  size: u32,
  auth_policy: *const core::ffi::c_void,
  auth_policy_size: u32,
) -> u32 {
  let mut define_space: tpm2_nv_define_space_cmd = unsafe { core::mem::zeroed() };
  let mut perm = perm;

  if (perm & TPMA_NV_MASK_WRITE) == 0 {
    perm |= TPMA_NV_AUTHWRITE;
  }
  if (perm & TPMA_NV_MASK_READ) == 0 {
    perm |= TPMA_NV_AUTHREAD;
  }

  define_space.publicInfo.nvIndex = HR_NV_INDEX + index;
  define_space.publicInfo.dataSize = size as u16;
  define_space.publicInfo.attributes = perm;
  define_space.publicInfo.nameAlg = TPM_ALG_SHA256;

  if !owner_auth.is_null() && owner_auth_size > 0 {
    define_space.auth.size = owner_auth_size as u16;
    define_space.auth.buffer = owner_auth;
  }

  if !auth_policy.is_null() && auth_policy_size > 0 {
    define_space.publicInfo.authPolicy.size = auth_policy_size as u16;
    define_space.publicInfo.authPolicy.buffer = auth_policy as *const u8;
  }

  tpm_get_response_code(
    TPM2_NV_DefineSpace,
    &define_space as *const tpm2_nv_define_space_cmd as *const core::ffi::c_void,
  )
}

pub fn TlclUndefineSpaceEx(_owner_auth: *const u8, _owner_auth_size: u32, index: u32) -> u32 {
  let mut undefine_space: tpm2_nv_undefine_space_cmd = unsafe { core::mem::zeroed() };
  let mut permissions: u32 = 0;
  let rv: u32;

  rv = TlclGetPermissions(index, &mut permissions);
  if rv != TPM_SUCCESS {
    return rv;
  }
  undefine_space.nvIndex = HR_NV_INDEX + index;
  undefine_space.use_platform_auth = ((permissions & TPMA_NV_PLATFORMCREATE) > 0) as u8;

  tpm_get_response_code(
    TPM2_NV_UndefineSpace,
    &undefine_space as *const tpm2_nv_undefine_space_cmd as *const core::ffi::c_void,
  )
}

pub fn TlclDefineSpace(index: u32, perm: u32, size: u32) -> u32 {
  TlclDefineSpaceEx(
    core::ptr::null(),
    0,
    index,
    perm,
    size,
    core::ptr::null(),
    0,
  )
}

pub fn TlclUndefineSpace(index: u32) -> u32 {
  TlclUndefineSpaceEx(core::ptr::null(), 0, index)
}

pub fn TlclInitNvAuthPolicy(
  _pcr_selection_bitmap: u32,
  _pcr_values: *const u8,
  _auth_policy: *mut core::ffi::c_void,
  auth_policy_size: &mut u32,
) -> u32 {
  *auth_policy_size = 0;
  TPM_SUCCESS
}

pub fn TlclGetSpaceInfo(
  index: u32,
  attributes: &mut u32,
  size: &mut u32,
  auth_policy: *mut core::ffi::c_void,
  auth_policy_size: &mut u32,
) -> u32 {
  let mut resp: nv_read_public_response = unsafe { core::mem::zeroed() };
  let rv = TlclNVReadPublic(index, &mut resp as *mut _ as *mut core::ffi::c_void);
  if rv != TPM_SUCCESS {
    return rv;
  }

  *attributes = unsafe { core::ptr::read_unaligned(core::ptr::addr_of!(resp.nvPublic.attributes)) };
  *size = unsafe { core::ptr::read_unaligned(core::ptr::addr_of!(resp.nvPublic.dataSize)) } as u32;

  let policy_size =
    unsafe { core::ptr::read_unaligned(core::ptr::addr_of!(resp.nvPublic.authPolicy.size)) } as u32;
  if policy_size > *auth_policy_size {
    return TPM_E_BUFFER_SIZE;
  }
  if policy_size > 0 && auth_policy.is_null() {
    return TPM_E_BUFFER_SIZE;
  }

  *auth_policy_size = policy_size;
  if policy_size > 0 {
    unsafe {
      core::ptr::copy_nonoverlapping(
        resp.nvPublic.authPolicy.buffer,
        auth_policy as *mut u8,
        policy_size as usize,
      );
    }
  }

  TPM_SUCCESS
}