1use crate::{Error, ErrorKind, Result};
19use crate::{Identity, Uuid};
20use alloc::{ffi::CString, string::String, vec::Vec};
21use optee_utee_sys as raw;
22
23pub enum PropertySet {
28 TeeImplementation,
29 CurrentClient,
30 CurrentTa,
31}
32
33impl PropertySet {
34 fn as_raw(&self) -> raw::TEE_PropSetHandle {
35 match self {
36 PropertySet::TeeImplementation => raw::TEE_PROPSET_TEE_IMPLEMENTATION,
37 PropertySet::CurrentClient => raw::TEE_PROPSET_CURRENT_CLIENT,
38 PropertySet::CurrentTa => raw::TEE_PROPSET_CURRENT_TA,
39 }
40 }
41}
42
43pub trait PropertyValue: Sized {
49 unsafe fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self>;
54}
55
56impl PropertyValue for String {
59 unsafe fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
60 let mut out_size = 0;
61
62 let res = unsafe {
65 raw::TEE_GetPropertyAsString(
66 set,
67 key.as_ptr() as *const _,
68 core::ptr::null_mut(),
69 &mut out_size,
70 )
71 };
72 match res {
73 raw::TEE_SUCCESS => {
74 if out_size == 0 {
75 Ok(String::new())
77 } else {
78 Err(Error::new(ErrorKind::Generic))
79 }
80 }
81 raw::TEE_ERROR_SHORT_BUFFER => {
82 let mut out_buffer = vec![0; out_size];
84 let res = unsafe {
85 raw::TEE_GetPropertyAsString(
86 set,
87 key.as_ptr() as *const _,
88 out_buffer.as_mut_ptr() as *mut _,
89 &mut out_size,
90 )
91 };
92 if res != raw::TEE_SUCCESS {
93 return Err(Error::from_raw_error(res));
94 }
95
96 let c_str = core::ffi::CStr::from_bytes_with_nul(&out_buffer)
98 .map_err(|_| Error::new(ErrorKind::BadFormat))?;
99 let result = c_str.to_string_lossy().into_owned();
101
102 Ok(result)
103 }
104 _ => Err(Error::from_raw_error(res)),
105 }
106 }
107}
108
109impl PropertyValue for bool {
110 unsafe fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
111 let mut b: bool = false;
112
113 let res = unsafe { raw::TEE_GetPropertyAsBool(set, key.as_ptr() as *const _, &mut b) };
114 if res != 0 {
115 return Err(Error::from_raw_error(res));
116 }
117
118 Ok(b)
119 }
120}
121
122impl PropertyValue for u32 {
123 unsafe fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
124 let mut value = 0;
125
126 let res = unsafe { raw::TEE_GetPropertyAsU32(set, key.as_ptr() as *const _, &mut value) };
127 if res != 0 {
128 return Err(Error::from_raw_error(res));
129 }
130
131 Ok(value)
132 }
133}
134
135impl PropertyValue for u64 {
136 unsafe fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
137 let mut value = 0;
138
139 let res = unsafe { raw::TEE_GetPropertyAsU64(set, key.as_ptr() as *const _, &mut value) };
140 if res != 0 {
141 return Err(Error::from_raw_error(res));
142 }
143
144 Ok(value)
145 }
146}
147
148impl PropertyValue for Vec<u8> {
149 unsafe fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
150 let mut out_size = 0;
151
152 let res = unsafe {
155 raw::TEE_GetPropertyAsBinaryBlock(
156 set,
157 key.as_ptr() as *const _,
158 core::ptr::null_mut(),
159 &mut out_size,
160 )
161 };
162
163 match res {
164 raw::TEE_SUCCESS => {
165 if out_size == 0 {
166 Ok(vec![])
168 } else {
169 Err(Error::new(ErrorKind::Generic))
170 }
171 }
172 raw::TEE_ERROR_SHORT_BUFFER => {
173 let mut buf = vec![0; out_size];
174
175 let res = unsafe {
176 raw::TEE_GetPropertyAsBinaryBlock(
177 set,
178 key.as_ptr() as *const _,
179 buf.as_mut_ptr() as *mut _,
180 &mut out_size,
181 )
182 };
183 if res != raw::TEE_SUCCESS {
184 Err(Error::from_raw_error(res))
185 } else {
186 Ok(buf)
187 }
188 }
189 _ => Err(Error::from_raw_error(res)),
190 }
191 }
192}
193
194impl PropertyValue for Uuid {
195 unsafe fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
196 let mut raw_uuid = raw::TEE_UUID {
197 timeLow: 0,
198 timeMid: 0,
199 timeHiAndVersion: 0,
200 clockSeqAndNode: [0; 8],
201 };
202
203 let res =
204 unsafe { raw::TEE_GetPropertyAsUUID(set, key.as_ptr() as *const _, &mut raw_uuid) };
205 if res != 0 {
206 return Err(Error::from_raw_error(res));
207 }
208
209 Ok(Uuid::from(raw_uuid))
210 }
211}
212
213impl PropertyValue for Identity {
214 unsafe fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
215 let mut raw_id = raw::TEE_Identity {
217 login: 0,
218 uuid: raw::TEE_UUID {
219 timeLow: 0,
220 timeMid: 0,
221 timeHiAndVersion: 0,
222 clockSeqAndNode: [0; 8],
223 },
224 };
225
226 let res =
227 unsafe { raw::TEE_GetPropertyAsIdentity(set, key.as_ptr() as *const _, &mut raw_id) };
228 if res != 0 {
229 return Err(Error::from_raw_error(res));
230 }
231
232 Ok(Identity::from(raw_id))
233 }
234}
235
236pub trait PropertyKey {
243 type Output: PropertyValue;
244 fn key(&self) -> CString;
245 fn set(&self) -> PropertySet;
246
247 fn get(&self) -> Result<Self::Output> {
248 unsafe { Self::Output::from_raw(self.set().as_raw(), self.key()) }
249 }
250}
251
252macro_rules! define_property_key {
256 (
257 $name:ident,
258 $set:ident,
259 $key:literal,
260 $output:ty
261 ) => {
262 pub struct $name;
263
264 impl PropertyKey for $name {
265 type Output = $output;
266
267 fn key(&self) -> CString {
268 CString::new($key).unwrap_or_default()
269 }
270
271 fn set(&self) -> PropertySet {
272 PropertySet::$set
273 }
274 }
275 };
276}
277
278define_property_key!(TaAppId, CurrentTa, "gpd.ta.appID", Uuid);
294define_property_key!(TaSingleInstance, CurrentTa, "gpd.ta.singleInstance", bool);
295define_property_key!(TaMultiSession, CurrentTa, "gpd.ta.multiSession", bool);
296define_property_key!(
297 TaInstanceKeepAlive,
298 CurrentTa,
299 "gpd.ta.instanceKeepAlive",
300 bool
301);
302define_property_key!(
303 TaInstanceKeepCrashed,
304 CurrentTa,
305 "gpd.ta.instanceKeepCrashed",
306 bool
307);
308define_property_key!(TaDataSize, CurrentTa, "gpd.ta.dataSize", u32);
309define_property_key!(TaStackSize, CurrentTa, "gpd.ta.stackSize", u32);
310define_property_key!(TaVersion, CurrentTa, "gpd.ta.version", String);
311define_property_key!(TaDescription, CurrentTa, "gpd.ta.description", String);
312define_property_key!(TaEndian, CurrentTa, "gpd.ta.endian", u32);
313define_property_key!(
314 TaDoesNotCloseHandleOnCorruptObject,
315 CurrentTa,
316 "gpd.ta.doesNotCloseHandleOnCorruptObject",
317 bool
318);
319define_property_key!(
320 ClientIdentity,
321 CurrentClient,
322 "gpd.client.identity",
323 Identity
324);
325define_property_key!(ClientEndian, CurrentClient, "gpd.client.endian", u32);
326define_property_key!(
327 TeeApiVersion,
328 TeeImplementation,
329 "gpd.tee.apiversion",
330 String
331);
332define_property_key!(
333 TeeInternalCoreVersion,
334 TeeImplementation,
335 "gpd.tee.internalCore.version",
336 u32
337);
338define_property_key!(
339 TeeDescription,
340 TeeImplementation,
341 "gpd.tee.description",
342 String
343);
344define_property_key!(TeeDeviceId, TeeImplementation, "gpd.tee.deviceID", Uuid);
345define_property_key!(
346 TeeSystemTimeProtectionLevel,
347 TeeImplementation,
348 "gpd.tee.systemTime.protectionLevel",
349 u32
350);
351define_property_key!(
352 TeeTaPersistentTimeProtectionLevel,
353 TeeImplementation,
354 "gpd.tee.TAPersistentTime.protectionLevel",
355 u32
356);
357define_property_key!(
358 TeeArithMaxBigIntSize,
359 TeeImplementation,
360 "gpd.tee.arith.maxBigIntSize",
361 u32
362);
363define_property_key!(
364 TeeCryptographyEcc,
365 TeeImplementation,
366 "gpd.tee.cryptography.ecc",
367 bool
368);
369define_property_key!(
370 TeeCryptographyNist,
371 TeeImplementation,
372 "gpd.tee.cryptography.nist",
373 bool
374);
375define_property_key!(
376 TeeCryptographyBsiR,
377 TeeImplementation,
378 "gpd.tee.cryptography.bsi-r",
379 bool
380);
381define_property_key!(
382 TeeCryptographyBsiT,
383 TeeImplementation,
384 "gpd.tee.cryptography.bsi-t",
385 bool
386);
387define_property_key!(
388 TeeCryptographyIetf,
389 TeeImplementation,
390 "gpd.tee.cryptography.ietf",
391 bool
392);
393define_property_key!(
394 TeeCryptographyOcta,
395 TeeImplementation,
396 "gpd.tee.cryptography.octa",
397 bool
398);
399define_property_key!(
400 TeeTrustedStoragePrivateRollbackProtection,
401 TeeImplementation,
402 "gpd.tee.trustedStorage.private.rollbackProtection",
403 u32
404);
405define_property_key!(
406 TeeTrustedStoragePersoRollbackProtection,
407 TeeImplementation,
408 "gpd.tee.trustedStorage.perso.rollbackProtection",
409 u32
410);
411define_property_key!(
412 TeeTrustedStorageProtectedRollbackProtection,
413 TeeImplementation,
414 "gpd.tee.trustedStorage.protected.rollbackProtection",
415 u32
416);
417define_property_key!(
418 TeeTrustedStorageAntiRollbackProtectionLevel,
419 TeeImplementation,
420 "gpd.tee.trustedStorage.antiRollback.protectionLevel",
421 u32
422);
423define_property_key!(
424 TeeTrustedStorageRollbackDetectionProtectionLevel,
425 TeeImplementation,
426 "gpd.tee.trustedStorage.rollbackDetection.protectionLevel",
427 u32
428);
429define_property_key!(
430 TeeTrustedOsImplementationVersion,
431 TeeImplementation,
432 "gpd.tee.trustedos.implementation.version",
433 String
434);
435define_property_key!(
436 TeeTrustedOsImplementationBinaryVersion,
437 TeeImplementation,
438 "gpd.tee.trustedos.implementation.binaryversion",
439 u32
440);
441define_property_key!(
442 TeeTrustedOsManufacturer,
443 TeeImplementation,
444 "gpd.tee.trustedos.manufacturer",
445 String
446);
447define_property_key!(
448 TeeFirmwareImplementationVersion,
449 TeeImplementation,
450 "gpd.tee.firmware.implementation.version",
451 String
452);
453define_property_key!(
454 TeeFirmwareImplementationBinaryVersion,
455 TeeImplementation,
456 "gpd.tee.firmware.implementation.binaryversion",
457 u32
458);
459define_property_key!(
460 TeeFirmwareManufacturer,
461 TeeImplementation,
462 "gpd.tee.firmware.manufacturer",
463 String
464);
465define_property_key!(
466 TeeEventMaxSources,
467 TeeImplementation,
468 "gpd.tee.event.maxSources",
469 u32
470);