use crate::{Error, ErrorKind, Result};
use crate::{Identity, Uuid};
use alloc::{ffi::CString, string::String, vec::Vec};
use optee_utee_sys as raw;
pub enum PropertySet {
TeeImplementation,
CurrentClient,
CurrentTa,
}
impl PropertySet {
fn as_raw(&self) -> raw::TEE_PropSetHandle {
match self {
PropertySet::TeeImplementation => raw::TEE_PROPSET_TEE_IMPLEMENTATION,
PropertySet::CurrentClient => raw::TEE_PROPSET_CURRENT_CLIENT,
PropertySet::CurrentTa => raw::TEE_PROPSET_CURRENT_TA,
}
}
}
pub trait PropertyValue: Sized {
fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self>;
}
impl PropertyValue for String {
fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
let mut out_size = 0;
let res = unsafe {
raw::TEE_GetPropertyAsString(
set,
key.as_ptr() as *const core::ffi::c_char,
core::ptr::null_mut(),
&mut out_size,
)
};
match res {
raw::TEE_SUCCESS => {
if out_size == 0 {
return Ok(String::new());
}
else {
return Err(Error::new(ErrorKind::Generic));
}
}
raw::TEE_ERROR_SHORT_BUFFER => {
let mut out_buffer = vec![0; out_size as usize];
let res = unsafe {
raw::TEE_GetPropertyAsString(
set,
key.as_ptr() as *const core::ffi::c_char,
out_buffer.as_mut_ptr() as *mut core::ffi::c_char,
&mut out_size,
)
};
if res != raw::TEE_SUCCESS {
return Err(Error::from_raw_error(res));
}
let c_str = core::ffi::CStr::from_bytes_with_nul(&out_buffer)
.map_err(|_| Error::new(ErrorKind::BadFormat))?;
let result = c_str.to_string_lossy().into_owned();
Ok(result)
}
_ => {
return Err(Error::from_raw_error(res));
}
}
}
}
impl PropertyValue for bool {
fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
let mut b: bool = false;
let res = unsafe { raw::TEE_GetPropertyAsBool(set, key.as_ptr() as *const core::ffi::c_char, &mut b) };
if res != 0 {
return Err(Error::from_raw_error(res));
}
Ok(b)
}
}
impl PropertyValue for u32 {
fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
let mut value = 0;
let res = unsafe { raw::TEE_GetPropertyAsU32(set, key.as_ptr() as *const core::ffi::c_char, &mut value) };
if res != 0 {
return Err(Error::from_raw_error(res));
}
Ok(value)
}
}
impl PropertyValue for u64 {
fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
let mut value = 0;
let res = unsafe { raw::TEE_GetPropertyAsU64(set, key.as_ptr() as *const core::ffi::c_char, &mut value) };
if res != 0 {
return Err(Error::from_raw_error(res));
}
Ok(value)
}
}
impl PropertyValue for Vec<u8> {
fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
let mut out_size = 0;
let res = unsafe {
raw::TEE_GetPropertyAsBinaryBlock(
set,
key.as_ptr() as *const core::ffi::c_char,
core::ptr::null_mut(),
&mut out_size,
)
};
match res {
raw::TEE_SUCCESS => {
if out_size == 0 {
return Ok(vec![]);
}
else {
return Err(Error::new(ErrorKind::Generic));
}
}
raw::TEE_ERROR_SHORT_BUFFER => {
let mut buf = vec![0; out_size as usize];
let res = unsafe {
raw::TEE_GetPropertyAsBinaryBlock(
set,
key.as_ptr() as *const core::ffi::c_char,
buf.as_mut_ptr() as *mut core::ffi::c_void,
&mut out_size,
)
};
if res != raw::TEE_SUCCESS {
return Err(Error::from_raw_error(res));
}
Ok(buf)
}
_ => {
return Err(Error::from_raw_error(res));
}
}
}
}
impl PropertyValue for Uuid {
fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
let mut raw_uuid = raw::TEE_UUID {
timeLow: 0,
timeMid: 0,
timeHiAndVersion: 0,
clockSeqAndNode: [0; 8],
};
let res =
unsafe { raw::TEE_GetPropertyAsUUID(set, key.as_ptr() as *const core::ffi::c_char, &mut raw_uuid) };
if res != 0 {
return Err(Error::from_raw_error(res));
}
Ok(Uuid::from(raw_uuid))
}
}
impl PropertyValue for Identity {
fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
let mut raw_id = raw::TEE_Identity {
login: 0,
uuid: raw::TEE_UUID {
timeLow: 0,
timeMid: 0,
timeHiAndVersion: 0,
clockSeqAndNode: [0; 8],
},
};
let res = unsafe {
raw::TEE_GetPropertyAsIdentity(set, key.as_ptr() as *const core::ffi::c_char, &mut raw_id)
};
if res != 0 {
return Err(Error::from_raw_error(res));
}
Ok(Identity::from(raw_id))
}
}
pub trait PropertyKey {
type Output: PropertyValue;
fn key(&self) -> CString;
fn set(&self) -> PropertySet;
fn get(&self) -> Result<Self::Output> {
Self::Output::from_raw(self.set().as_raw(), self.key())
}
}
macro_rules! define_property_key {
(
$name:ident,
$set:ident,
$key:literal,
$output:ty
) => {
pub struct $name;
impl PropertyKey for $name {
type Output = $output;
fn key(&self) -> CString {
CString::new($key).unwrap_or_default()
}
fn set(&self) -> PropertySet {
PropertySet::$set
}
}
};
}
define_property_key!(TaAppId, CurrentTa, "gpd.ta.appID", Uuid);
define_property_key!(
TaSingleInstance,
CurrentTa,
"gpd.ta.singleInstance",
bool
);
define_property_key!(
TaMultiSession,
CurrentTa,
"gpd.ta.multiSession",
bool
);
define_property_key!(
TaInstanceKeepAlive,
CurrentTa,
"gpd.ta.instanceKeepAlive",
bool
);
define_property_key!(TaDataSize, CurrentTa, "gpd.ta.dataSize", u32);
define_property_key!(TaStackSize, CurrentTa, "gpd.ta.stackSize", u32);
define_property_key!(TaVersion, CurrentTa, "gpd.ta.version", String);
define_property_key!(
TaDescription,
CurrentTa,
"gpd.ta.description",
String
);
define_property_key!(TaEndian, CurrentTa, "gpd.ta.endian", u32);
define_property_key!(
TaDoesNotCloseHandleOnCorruptObject,
CurrentTa,
"gpd.ta.doesNotCloseHandleOnCorruptObject",
bool
);
define_property_key!(
ClientIdentity,
CurrentClient,
"gpd.client.identity",
Identity
);
define_property_key!(ClientEndian, CurrentClient, "gpd.client.endian", u32);
define_property_key!(
TeeApiVersion,
TeeImplementation,
"gpd.tee.apiversion",
String
);
define_property_key!(
TeeInternalCoreVersion,
TeeImplementation,
"gpd.tee.internalCore.version",
u32
);
define_property_key!(
TeeDescription,
TeeImplementation,
"gpd.tee.description",
String
);
define_property_key!(
TeeDeviceId,
TeeImplementation,
"gpd.tee.deviceID",
Uuid
);
define_property_key!(
TeeSystemTimeProtectionLevel,
TeeImplementation,
"gpd.tee.systemTime.protectionLevel",
u32
);
define_property_key!(
TeeTaPersistentTimeProtectionLevel,
TeeImplementation,
"gpd.tee.TAPersistentTime.protectionLevel",
u32
);
define_property_key!(
TeeArithMaxBigIntSize,
TeeImplementation,
"gpd.tee.arith.maxBigIntSize",
u32
);
define_property_key!(
TeeCryptographyEcc,
TeeImplementation,
"gpd.tee.cryptography.ecc",
bool
);
define_property_key!(
TeeCryptographyNist,
TeeImplementation,
"gpd.tee.cryptography.nist",
bool
);
define_property_key!(
TeeCryptographyBsiR,
TeeImplementation,
"gpd.tee.cryptography.bsi-r",
bool
);
define_property_key!(
TeeCryptographyBsiT,
TeeImplementation,
"gpd.tee.cryptography.bsi-t",
bool
);
define_property_key!(
TeeCryptographyIetf,
TeeImplementation,
"gpd.tee.cryptography.ietf",
bool
);
define_property_key!(
TeeCryptographyOcta,
TeeImplementation,
"gpd.tee.cryptography.octa",
bool
);
define_property_key!(
TeeTrustedStoragePrivateRollbackProtection,
TeeImplementation,
"gpd.tee.trustedStorage.private.rollbackProtection",
u32
);
define_property_key!(
TeeTrustedStoragePersoRollbackProtection,
TeeImplementation,
"gpd.tee.trustedStorage.perso.rollbackProtection",
u32
);
define_property_key!(
TeeTrustedStorageProtectedRollbackProtection,
TeeImplementation,
"gpd.tee.trustedStorage.protected.rollbackProtection",
u32
);
define_property_key!(
TeeTrustedStorageAntiRollbackProtectionLevel,
TeeImplementation,
"gpd.tee.trustedStorage.antiRollback.protectionLevel",
u32
);
define_property_key!(
TeeTrustedStorageRollbackDetectionProtectionLevel,
TeeImplementation,
"gpd.tee.trustedStorage.rollbackDetection.protectionLevel",
u32
);
define_property_key!(
TeeTrustedOsImplementationVersion,
TeeImplementation,
"gpd.tee.trustedos.implementation.version",
String
);
define_property_key!(
TeeTrustedOsImplementationBinaryVersion,
TeeImplementation,
"gpd.tee.trustedos.implementation.binaryversion",
Vec<u8>
);
define_property_key!(
TeeTrustedOsManufacturer,
TeeImplementation,
"gpd.tee.trustedos.manufacturer",
String
);
define_property_key!(
TeeFirmwareImplementationVersion,
TeeImplementation,
"gpd.tee.firmware.implementation.version",
String
);
define_property_key!(
TeeFirmwareImplementationBinaryVersion,
TeeImplementation,
"gpd.tee.firmware.implementation.binaryversion",
Vec<u8>
);
define_property_key!(
TeeFirmwareManufacturer,
TeeImplementation,
"gpd.tee.firmware.manufacturer",
String
);
define_property_key!(
TeeEventMaxSources,
TeeImplementation,
"gpd.tee.event.maxSources",
u32
);