1use std::cmp::min;
8use std::collections::HashMap;
9use std::path::Path;
10use std::sync::atomic::{AtomicU64, Ordering};
11use std::sync::Arc;
12
13use tee_internal::{
14 Error, Identity, PropSetHandle, Result as TeeResult, Uuid, TEE_PROPSET_CURRENT_CLIENT,
15 TEE_PROPSET_CURRENT_TA, TEE_PROPSET_TEE_IMPLEMENTATION,
16};
17use tee_properties::{PropEnumerator, PropSet, PropertyError};
18
19fn write_c_string_to_buffer<'a>(string_val: &str, buffer: &'a mut [u8]) -> &'a str {
20 if buffer.len() == 0 {
21 return std::str::from_utf8(buffer).unwrap();
22 }
23 let bytes_to_write = min(buffer.len() - 1, string_val.len());
25 buffer[..bytes_to_write].clone_from_slice(&string_val.as_bytes()[..bytes_to_write]);
26 buffer[bytes_to_write] = 0;
27
28 std::str::from_utf8(&buffer[..bytes_to_write]).unwrap()
29}
30
31pub fn is_propset_pseudo_handle(handle: PropSetHandle) -> bool {
38 handle == TEE_PROPSET_TEE_IMPLEMENTATION
39 || handle == TEE_PROPSET_CURRENT_CLIENT
40 || handle == TEE_PROPSET_CURRENT_TA
41}
42
43pub struct GetStringError<'a> {
44 pub error: Error,
45 pub written: &'a str,
46 pub actual_length: usize,
47}
48
49pub struct GetBinaryBlockError<'a> {
50 pub error: Error,
51 pub written: &'a [u8],
52 pub actual_length: usize,
53}
54
55pub struct Properties {
56 prop_sets: PropSets,
57}
58
59impl Properties {
60 pub fn new() -> Self {
61 Self { prop_sets: PropSets::load_prop_sets() }
62 }
63
64 pub fn get_property_as_string<'a>(
65 &self,
66 handle: PropSetHandle,
67 name: &str,
68 buffer: &'a mut [u8],
69 ) -> Result<&'a str, GetStringError<'a>> {
70 let string_val = self
71 .prop_sets
72 .get_string_property(handle, name)
73 .map_err(|error| GetStringError { error, written: "", actual_length: 0 })?;
74 let buffer_len = buffer.len();
75 let string_written = write_c_string_to_buffer(string_val.as_str(), buffer);
76 if buffer_len < string_val.len() + 1 {
78 return Err(GetStringError {
79 error: Error::ShortBuffer,
80 written: string_written,
81 actual_length: string_val.len(),
82 });
83 }
84 Ok(string_written)
85 }
86
87 pub fn get_property_as_bool(&self, handle: PropSetHandle, name: &str) -> TeeResult<bool> {
88 self.prop_sets.get_bool_property(handle, name)
89 }
90
91 pub fn get_property_as_u32(&self, handle: PropSetHandle, name: &str) -> TeeResult<u32> {
92 self.prop_sets.get_uint32_property(handle, name)
93 }
94
95 pub fn get_property_as_u64(&self, handle: PropSetHandle, name: &str) -> TeeResult<u64> {
96 self.prop_sets.get_uint64_property(handle, name)
97 }
98
99 pub fn get_property_as_binary_block<'a>(
100 &self,
101 handle: PropSetHandle,
102 name: &str,
103 buffer: &'a mut [u8],
104 ) -> Result<&'a [u8], GetBinaryBlockError<'a>> {
105 let bytes = self
106 .prop_sets
107 .get_binary_block_property(handle, name)
108 .map_err(|error| GetBinaryBlockError { error, written: &[], actual_length: 0 })?;
109
110 let buffer_len = buffer.len();
111 let bytes_to_write = min(buffer.len(), bytes.len());
112 let written = &mut buffer[..bytes_to_write];
113 written.clone_from_slice(&bytes[..bytes_to_write]);
114
115 if buffer_len < bytes.len() {
116 return Err(GetBinaryBlockError {
117 error: Error::ShortBuffer,
118 written,
119 actual_length: bytes.len(),
120 });
121 }
122 Ok(written)
123 }
124
125 pub fn get_property_as_uuid(&self, handle: PropSetHandle, name: &str) -> TeeResult<Uuid> {
126 self.prop_sets.get_uuid_property(handle, name)
127 }
128
129 pub fn get_property_as_identity(
130 &self,
131 handle: PropSetHandle,
132 name: &str,
133 ) -> TeeResult<Identity> {
134 self.prop_sets.get_identity_property(handle, name)
135 }
136
137 pub fn allocate_property_enumerator(&mut self) -> PropSetHandle {
138 self.prop_sets.allocate_property_enumerator()
139 }
140
141 pub fn free_property_enumerator(&mut self, handle: PropSetHandle) {
142 self.prop_sets.free_property_enumerator(handle);
143 }
144
145 pub fn start_property_enumerator(&mut self, handle: PropSetHandle, prop_set: PropSetHandle) {
146 self.prop_sets.start_property_enumerator(handle, prop_set);
147 }
148
149 pub fn reset_property_enumerator(&mut self, handle: PropSetHandle) {
150 self.prop_sets.reset_property_enumerator(handle);
151 }
152
153 pub fn get_property_name<'a>(
154 &self,
155 handle: PropSetHandle,
156 buffer: &'a mut [u8],
157 ) -> Result<&'a str, GetStringError<'a>> {
158 let string_val = self
159 .prop_sets
160 .get_property_name(handle)
161 .map_err(|error| GetStringError { error, written: "", actual_length: 0 })?;
162
163 let buffer_len = buffer.len();
164 let string_written = write_c_string_to_buffer(string_val.as_str(), buffer);
165 if buffer_len < string_val.len() + 1 {
167 return Err(GetStringError {
168 error: Error::ShortBuffer,
169 written: string_written,
170 actual_length: string_val.len(),
171 });
172 }
173 Ok(string_written)
174 }
175
176 pub fn get_next_property(&mut self, handle: PropSetHandle) -> TeeResult<()> {
177 self.prop_sets.get_next_property(handle)
178 }
179}
180
181struct PropSets {
182 tee_implementation_props: Arc<PropSet>,
183 ta_props: Arc<PropSet>,
184 client_props: Arc<PropSet>,
185 prop_enums: HashMap<u64, PropEnumerator>,
187 enumerator_handle_id_counter: AtomicU64,
188}
189
190impl PropSets {
191 fn load_prop_sets() -> Self {
192 let tee_impl_props_path = Path::new("/properties/system_properties");
193 let tee_impl_props = PropSet::from_config_file(&tee_impl_props_path)
194 .expect("TEE prop set loads successfully");
195
196 let ta_props_path = Path::new("/pkg/data/ta_properties");
197 let ta_props =
198 PropSet::from_config_file(&ta_props_path).expect("TA prop set loads successfully");
199
200 let fake_client_props_str: &str = r#"
202 [
203 {
204 name: "gpd.client.identity",
205 prop_type: "identity",
206 value: "0:9cccff19-13b5-4d4c-aa9e-5c8901a52e2f",
207 },
208 ]
209 "#;
210 let client_props = PropSet::from_config_string(fake_client_props_str)
211 .expect("load fake client props successfully");
212
213 Self {
214 tee_implementation_props: Arc::new(tee_impl_props),
215 ta_props: Arc::new(ta_props),
216 client_props: Arc::new(client_props),
217 prop_enums: HashMap::new(),
218 enumerator_handle_id_counter: AtomicU64::new(1),
221 }
222 }
223
224 fn get_prop_set_from_pseudo_handle(
225 &self,
226 maybe_pseudo_handle: PropSetHandle,
227 ) -> Option<Arc<PropSet>> {
228 match maybe_pseudo_handle {
229 TEE_PROPSET_TEE_IMPLEMENTATION => Some(self.tee_implementation_props.clone()),
230 TEE_PROPSET_CURRENT_CLIENT => Some(self.client_props.clone()),
231 TEE_PROPSET_CURRENT_TA => Some(self.ta_props.clone()),
232 _ => None,
233 }
234 }
235
236 fn get_string_property(
238 &self,
239 handle: PropSetHandle,
240 name: &str,
241 ) -> Result<String, tee_internal::Error> {
242 assert!(!handle.is_null());
243 let string_val = if let Some(prop_set) = self.get_prop_set_from_pseudo_handle(handle) {
244 prop_set
245 .get_string_property(name.to_string())
246 .map_err(|_| tee_internal::Error::ItemNotFound)?
247 } else {
248 self.prop_enums
249 .get(&handle)
250 .expect("enumerator handle must be valid")
251 .get_property_as_string()
252 .map_err(|_| tee_internal::Error::ItemNotFound)?
253 };
254 Ok(string_val)
255 }
256
257 fn get_bool_property(
258 &self,
259 handle: PropSetHandle,
260 name: &str,
261 ) -> Result<bool, tee_internal::Error> {
262 assert!(!handle.is_null());
263 let bool_val = if let Some(prop_set) = self.get_prop_set_from_pseudo_handle(handle) {
264 prop_set
265 .get_boolean_property(name.to_string())
266 .map_err(|_| tee_internal::Error::ItemNotFound)?
267 } else {
268 self.prop_enums
269 .get(&handle)
270 .expect("enumerator handle must be valid")
271 .get_property_as_bool()
272 .map_err(|_| tee_internal::Error::ItemNotFound)?
273 };
274 Ok(bool_val)
275 }
276
277 fn get_uint32_property(
278 &self,
279 handle: PropSetHandle,
280 name: &str,
281 ) -> Result<u32, tee_internal::Error> {
282 assert!(!handle.is_null());
283 let u32_val = if let Some(prop_set) = self.get_prop_set_from_pseudo_handle(handle) {
284 prop_set
285 .get_uint32_property(name.to_string())
286 .map_err(|_| tee_internal::Error::ItemNotFound)?
287 } else {
288 self.prop_enums
289 .get(&handle)
290 .expect("enumerator handle must be valid")
291 .get_property_as_u32()
292 .map_err(|_| tee_internal::Error::ItemNotFound)?
293 };
294 Ok(u32_val)
295 }
296
297 fn get_uint64_property(
298 &self,
299 handle: PropSetHandle,
300 name: &str,
301 ) -> Result<u64, tee_internal::Error> {
302 assert!(!handle.is_null());
303 let u64_val = if let Some(prop_set) = self.get_prop_set_from_pseudo_handle(handle) {
304 prop_set
305 .get_uint64_property(name.to_string())
306 .map_err(|_| tee_internal::Error::ItemNotFound)?
307 } else {
308 self.prop_enums
309 .get(&handle)
310 .expect("enumerator handle must be valid")
311 .get_property_as_u64()
312 .map_err(|_| tee_internal::Error::ItemNotFound)?
313 };
314 Ok(u64_val)
315 }
316
317 fn get_binary_block_property(
319 &self,
320 handle: PropSetHandle,
321 name: &str,
322 ) -> Result<Vec<u8>, tee_internal::Error> {
323 assert!(!handle.is_null());
324 let bytes = if let Some(prop_set) = self.get_prop_set_from_pseudo_handle(handle) {
325 prop_set.get_binary_block_property(name.to_string()).map_err(
326 |error: PropertyError| match error {
327 PropertyError::BadFormat { .. } => tee_internal::Error::BadFormat,
328 PropertyError::ItemNotFound { .. } => return tee_internal::Error::ItemNotFound,
329 PropertyError::Generic { msg } => {
330 panic!("Error getting property as binary block: {:?}", msg)
331 }
332 },
333 )?
334 } else {
335 self.prop_enums
336 .get(&handle)
337 .expect("enumerator handle must be valid")
338 .get_property_as_binary_block()
339 .map_err(|error: PropertyError| match error {
340 PropertyError::BadFormat { .. } => tee_internal::Error::BadFormat,
341 PropertyError::ItemNotFound { .. } => return tee_internal::Error::ItemNotFound,
342 PropertyError::Generic { msg } => {
343 panic!("Error getting property as binary block: {:?}", msg)
344 }
345 })?
346 };
347
348 Ok(bytes)
349 }
350
351 fn get_uuid_property(
352 &self,
353 handle: PropSetHandle,
354 name: &str,
355 ) -> Result<Uuid, tee_internal::Error> {
356 assert!(!handle.is_null());
357 let uuid = if let Some(prop_set) = self.get_prop_set_from_pseudo_handle(handle) {
358 prop_set.get_uuid_property(name.to_string()).map_err(|error| match error {
359 PropertyError::BadFormat { .. } => tee_internal::Error::BadFormat,
360 PropertyError::ItemNotFound { .. } => return tee_internal::Error::ItemNotFound,
361 PropertyError::Generic { msg } => {
362 panic!("Error getting property as uuid: {:?}", msg)
363 }
364 })?
365 } else {
366 self.prop_enums
367 .get(&handle)
368 .expect("enumerator handle must be valid")
369 .get_property_as_uuid()
370 .map_err(|error| match error {
371 PropertyError::BadFormat { .. } => tee_internal::Error::BadFormat,
372 PropertyError::ItemNotFound { .. } => return tee_internal::Error::ItemNotFound,
373 PropertyError::Generic { msg } => {
374 panic!("Error getting property as uuid: {:?}", msg)
375 }
376 })?
377 };
378
379 Ok(uuid)
380 }
381
382 fn get_identity_property(
383 &self,
384 handle: PropSetHandle,
385 name: &str,
386 ) -> Result<Identity, tee_internal::Error> {
387 assert!(!handle.is_null());
388 let identity = if let Some(prop_set) = self.get_prop_set_from_pseudo_handle(handle) {
389 prop_set.get_identity_property(name.to_string()).map_err(|error: PropertyError| {
390 match error {
391 PropertyError::BadFormat { .. } => tee_internal::Error::BadFormat,
392 PropertyError::ItemNotFound { .. } => return tee_internal::Error::ItemNotFound,
393 PropertyError::Generic { msg } => {
394 panic!("Error getting property as identity: {:?}", msg)
395 }
396 }
397 })?
398 } else {
399 self.prop_enums
400 .get(&handle)
401 .expect("enumerator handle must be valid")
402 .get_property_as_identity()
403 .map_err(|error| match error {
404 PropertyError::BadFormat { .. } => tee_internal::Error::BadFormat,
405 PropertyError::ItemNotFound { .. } => return tee_internal::Error::ItemNotFound,
406 PropertyError::Generic { msg } => {
407 panic!("Error getting property as identity: {:?}", msg)
408 }
409 })?
410 };
411
412 Ok(identity)
413 }
414
415 fn new_enumerator_handle(&mut self) -> u64 {
416 assert!(
417 self.enumerator_handle_id_counter.load(Ordering::Relaxed)
418 <= *TEE_PROPSET_TEE_IMPLEMENTATION
419 );
420 self.enumerator_handle_id_counter.fetch_add(1, Ordering::Relaxed)
421 }
422
423 fn allocate_property_enumerator(&mut self) -> PropSetHandle {
424 let handle = self.new_enumerator_handle();
426 let _ = self.prop_enums.insert(handle, PropEnumerator::new());
427 PropSetHandle::from_value(handle)
428 }
429
430 fn free_property_enumerator(&mut self, handle: PropSetHandle) {
431 assert!(!handle.is_null());
432 let _ = self.prop_enums.remove_entry(&handle);
433 }
434
435 fn start_property_enumerator(&mut self, handle: PropSetHandle, prop_set: PropSetHandle) {
436 assert!(!handle.is_null());
437 let Some(prop_set) = self.get_prop_set_from_pseudo_handle(prop_set) else {
438 panic!("Invalid TEE_PropSetHandle pseudo-handle provided");
439 };
440
441 let Some(prop_enumerator) = self.prop_enums.get_mut(&handle) else {
442 panic!("Invalid enumerator handle provided");
443 };
444
445 prop_enumerator.start(prop_set);
446 }
447
448 fn reset_property_enumerator(&mut self, handle: PropSetHandle) {
449 assert!(!handle.is_null());
450 let Some(prop_enumerator) = self.prop_enums.get_mut(&handle) else {
451 panic!("Invalid enumerator handle provided");
452 };
453 prop_enumerator.reset();
454 }
455
456 fn get_property_name(&self, handle: PropSetHandle) -> Result<String, tee_internal::Error> {
457 assert!(!handle.is_null());
458 let Some(prop_enumerator) = self.prop_enums.get(&handle) else {
459 panic!("Invalid enumerator handle provided");
460 };
461 prop_enumerator.get_property_name().map_err(|_| tee_internal::Error::ItemNotFound)
462 }
463
464 fn get_next_property(&mut self, handle: PropSetHandle) -> Result<(), tee_internal::Error> {
465 assert!(!handle.is_null());
466 let Some(prop_enumerator) = self.prop_enums.get_mut(&handle) else {
467 panic!("Invalid enumerator handle provided");
468 };
469
470 prop_enumerator.next().map_err(|_| tee_internal::Error::ItemNotFound)
471 }
472}
473
474#[cfg(test)]
475pub mod tests {
476 use super::*;
477
478 const TEST_TEE_IMPL_PROPS_STR: &str = r#"[
480 {
481 name: "gpd.tee.test.string",
482 prop_type: "string",
483 value: "asdf",
484 },
485 {
486 name: "gpd.tee.test.bool",
487 prop_type: "boolean",
488 value: "true",
489 },
490 {
491 name: "gpd.tee.test.u32",
492 prop_type: "unsigned_int32",
493 value: "57",
494 },
495 {
496 name: "gpd.tee.test.u64",
497 prop_type: "unsigned_int64",
498 value: "4294967296",
499 },
500 {
501 name: "gpd.tee.test.binaryBlock",
502 prop_type: "binary_block",
503 value: "ZnVjaHNpYQ==",
504 },
505 {
506 name: "gpd.tee.test.uuid",
507 prop_type: "uuid",
508 value: "9cccff19-13b5-4d4c-aa9e-5c8901a52e2f",
509 },
510 {
511 name: "gpd.tee.test.identity",
512 prop_type: "identity",
513 value: "4026531840:9cccff19-13b5-4d4c-aa9e-5c8901a52e2f",
514 },
515 ]
516 "#;
517
518 const TEST_TA_PROPS_STR: &str = r#"[
519 {
520 name: "gpd.ta.appID",
521 prop_type: "uuid",
522 value: "9cccff19-13b5-4d4c-aa9e-5c8901a52e2f",
523 },
524 {
525 name: "gpd.ta.singleInstance",
526 prop_type: "boolean",
527 value: "true",
528 },
529 {
530 name: "gpd.ta.multiSession",
531 prop_type: "boolean",
532 value: "true",
533 },
534 {
535 name: "gpd.ta.instanceKeepAlive",
536 prop_type: "boolean",
537 value: "false",
538 },
539 ]
540 "#;
541
542 const TEST_CLIENT_PROPS_STR: &str = r#"
543 [
544 {
545 name: "gpd.client.identity",
546 prop_type: "identity",
547 value: "0:9cccff19-13b5-4d4c-aa9e-5c8901a52e2f",
548 },
549 ]
550 "#;
551
552 fn init_test_tee_impl_props() -> PropSets {
553 let test_props = PropSet::from_config_string(TEST_TEE_IMPL_PROPS_STR)
554 .expect("load fake tee props successfully");
555 let ta_props = PropSet::from_config_string(TEST_TA_PROPS_STR)
556 .expect("load fake ta props successfully");
557 let client_props = PropSet::from_config_string(TEST_CLIENT_PROPS_STR)
558 .expect("load fake client props successfully");
559
560 PropSets {
561 tee_implementation_props: Arc::new(test_props),
562 ta_props: Arc::new(ta_props),
563 client_props: Arc::new(client_props),
564 prop_enums: HashMap::new(),
565 enumerator_handle_id_counter: AtomicU64::new(1),
566 }
567 }
568
569 #[fuchsia::test]
570 pub fn test_get_string_property() {
571 let prop_sets = init_test_tee_impl_props();
572 let value = prop_sets
573 .get_string_property(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.test.string")
574 .unwrap();
575 assert_eq!("asdf".to_string(), value);
576 }
577
578 #[fuchsia::test]
579 pub fn test_get_string_property_not_found() {
580 let prop_sets = init_test_tee_impl_props();
581 let value =
582 prop_sets.get_string_property(TEE_PROPSET_TEE_IMPLEMENTATION, "name_not_in_set");
583 assert_eq!(tee_internal::Error::ItemNotFound, value.err().unwrap());
584 }
585
586 #[fuchsia::test]
587 pub fn test_get_bool_property() {
588 let prop_sets = init_test_tee_impl_props();
589 let value = prop_sets
590 .get_bool_property(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.test.bool")
591 .unwrap();
592 assert!(value);
593 }
594
595 #[fuchsia::test]
596 pub fn test_get_bool_property_not_found() {
597 let prop_sets = init_test_tee_impl_props();
598 let value = prop_sets.get_bool_property(TEE_PROPSET_TEE_IMPLEMENTATION, "name_not_in_set");
599 assert_eq!(tee_internal::Error::ItemNotFound, value.err().unwrap());
600 }
601
602 #[fuchsia::test]
603 pub fn test_get_u32_property() {
604 let prop_sets = init_test_tee_impl_props();
605 let value = prop_sets
606 .get_uint32_property(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.test.u32")
607 .unwrap();
608 assert_eq!(57, value);
609 }
610
611 #[fuchsia::test]
612 pub fn test_get_u32_property_not_found() {
613 let prop_sets = init_test_tee_impl_props();
614 let value =
615 prop_sets.get_uint32_property(TEE_PROPSET_TEE_IMPLEMENTATION, "name_not_in_set");
616 assert_eq!(tee_internal::Error::ItemNotFound, value.err().unwrap());
617 }
618
619 #[fuchsia::test]
620 pub fn test_get_u64_property() {
621 let prop_sets = init_test_tee_impl_props();
622 let value = prop_sets
623 .get_uint64_property(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.test.u64")
624 .unwrap();
625 assert_eq!(4294967296, value);
626 }
627
628 #[fuchsia::test]
629 pub fn test_get_u64_property_not_found() {
630 let prop_sets = init_test_tee_impl_props();
631 let value =
632 prop_sets.get_uint64_property(TEE_PROPSET_TEE_IMPLEMENTATION, "name_not_in_set");
633 assert_eq!(tee_internal::Error::ItemNotFound, value.err().unwrap());
634 }
635
636 #[fuchsia::test]
637 pub fn test_get_binary_block_property() {
638 let prop_sets = init_test_tee_impl_props();
639 let value = prop_sets
640 .get_binary_block_property(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.test.binaryBlock")
641 .unwrap();
642
643 let expected_val_as_u8: Vec<u8> = vec![102, 117, 99, 104, 115, 105, 97];
646 assert_eq!(7, value.len());
647 assert_eq!(expected_val_as_u8, value);
648 }
649
650 #[fuchsia::test]
651 pub fn test_get_binary_block_property_not_found() {
652 let prop_sets = init_test_tee_impl_props();
653 let value =
654 prop_sets.get_binary_block_property(TEE_PROPSET_TEE_IMPLEMENTATION, "name_not_in_set");
655 assert_eq!(tee_internal::Error::ItemNotFound, value.err().unwrap());
656 }
657
658 #[fuchsia::test]
659 pub fn test_get_binary_block_property_bad_format() {
660 let prop_sets = init_test_tee_impl_props();
661 let value =
662 prop_sets.get_binary_block_property(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.test.u32");
663 assert_eq!(tee_internal::Error::BadFormat, value.err().unwrap());
664 }
665
666 #[fuchsia::test]
667 pub fn test_get_uuid_property() {
668 let prop_sets = init_test_tee_impl_props();
669 let value = prop_sets
670 .get_uuid_property(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.test.uuid")
671 .unwrap();
672
673 assert_eq!(0x9cccff19, value.time_low);
674 assert_eq!(0x13b5, value.time_mid);
675 assert_eq!(0x4d4c, value.time_hi_and_version);
676 assert_eq!([0xaa, 0x9e, 0x5c, 0x89, 0x01, 0xa5, 0x2e, 0x2f], value.clock_seq_and_node);
677 }
678
679 #[fuchsia::test]
680 pub fn test_get_uuid_property_not_found() {
681 let prop_sets = init_test_tee_impl_props();
682 let value = prop_sets.get_uuid_property(TEE_PROPSET_TEE_IMPLEMENTATION, "name_not_in_set");
683 assert_eq!(tee_internal::Error::ItemNotFound, value.err().unwrap());
684 }
685
686 #[fuchsia::test]
687 pub fn test_get_uuid_property_bad_format() {
688 let prop_sets = init_test_tee_impl_props();
689 let value = prop_sets.get_uuid_property(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.test.u32");
690 assert_eq!(tee_internal::Error::BadFormat, value.err().unwrap());
691 }
692
693 #[fuchsia::test]
694 pub fn test_get_identity_property() {
695 let prop_sets = init_test_tee_impl_props();
696 let value = prop_sets
697 .get_identity_property(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.test.identity")
698 .unwrap();
699
700 assert_eq!(tee_internal::Login::TrustedApp, value.login);
702
703 assert_eq!(0x9cccff19, value.uuid.time_low);
704 assert_eq!(0x13b5, value.uuid.time_mid);
705 assert_eq!(0x4d4c, value.uuid.time_hi_and_version);
706 assert_eq!([0xaa, 0x9e, 0x5c, 0x89, 0x01, 0xa5, 0x2e, 0x2f], value.uuid.clock_seq_and_node);
707 }
708
709 #[fuchsia::test]
710 pub fn test_get_identity_property_not_found() {
711 let prop_sets = init_test_tee_impl_props();
712 let value =
713 prop_sets.get_identity_property(TEE_PROPSET_TEE_IMPLEMENTATION, "name_not_in_set");
714 assert_eq!(tee_internal::Error::ItemNotFound, value.err().unwrap());
715 }
716
717 #[fuchsia::test]
718 pub fn test_get_identity_property_bad_format() {
719 let prop_sets = init_test_tee_impl_props();
720 let value =
721 prop_sets.get_identity_property(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.test.uuid");
722 assert_eq!(tee_internal::Error::BadFormat, value.err().unwrap());
723 }
724
725 #[fuchsia::test]
726 pub fn test_enumerator_allocate() {
727 let mut prop_sets = init_test_tee_impl_props();
728 assert_eq!(0, prop_sets.prop_enums.len());
729 let handle = prop_sets.allocate_property_enumerator();
730 assert!(prop_sets.prop_enums.get(&handle).is_some());
731 }
732
733 #[fuchsia::test]
734 pub fn test_enumerator_free() {
735 let mut prop_sets = init_test_tee_impl_props();
736 assert_eq!(0, prop_sets.prop_enums.len());
737 let handle = prop_sets.allocate_property_enumerator();
738 assert!(prop_sets.prop_enums.get(&handle).is_some());
739 prop_sets.free_property_enumerator(handle);
740 assert_eq!(0, prop_sets.prop_enums.len());
741 }
742
743 #[fuchsia::test]
744 pub fn test_enumerator_start() {
745 let mut prop_sets = init_test_tee_impl_props();
746 let handle = prop_sets.allocate_property_enumerator();
747 prop_sets.start_property_enumerator(handle, TEE_PROPSET_TEE_IMPLEMENTATION);
749 }
750
751 #[fuchsia::test]
752 #[should_panic]
753 pub fn test_enumerator_start_bad_handle() {
754 let mut prop_sets = init_test_tee_impl_props();
755 let _handle = prop_sets.allocate_property_enumerator();
756 let bad_handle = PropSetHandle::from_value(0);
758 prop_sets.start_property_enumerator(bad_handle, TEE_PROPSET_TEE_IMPLEMENTATION);
759 }
760
761 #[fuchsia::test]
762 #[should_panic(expected = "Invalid TEE_PropSetHandle pseudo-handle provided")]
763 pub fn test_enumerator_start_bad_prop_set_pseudo_handle() {
764 let mut prop_sets = init_test_tee_impl_props();
765 let handle = prop_sets.allocate_property_enumerator();
766 prop_sets.start_property_enumerator(handle, PropSetHandle::from_value(0));
768 }
769
770 #[fuchsia::test]
771 pub fn test_enumerator_get_name() {
772 let mut prop_sets = init_test_tee_impl_props();
773 let handle = prop_sets.allocate_property_enumerator();
774
775 prop_sets.start_property_enumerator(handle, TEE_PROPSET_TEE_IMPLEMENTATION);
776 let name = prop_sets.get_property_name(handle).unwrap();
777 assert_eq!("gpd.tee.test.string".to_string(), name);
778 }
779
780 #[fuchsia::test]
781 pub fn test_enumerator_next_property() {
782 let mut prop_sets = init_test_tee_impl_props();
783 let handle = prop_sets.allocate_property_enumerator();
784
785 prop_sets.start_property_enumerator(handle, TEE_PROPSET_TEE_IMPLEMENTATION);
786 let name = prop_sets.get_property_name(handle).unwrap();
787 assert_eq!("gpd.tee.test.string".to_string(), name);
788
789 prop_sets.get_next_property(handle).unwrap();
790 let name = prop_sets.get_property_name(handle).unwrap();
791 assert_eq!("gpd.tee.test.bool".to_string(), name);
792 }
793
794 #[fuchsia::test]
795 pub fn test_enumerator_reset() {
796 let mut prop_sets = init_test_tee_impl_props();
797 let handle = prop_sets.allocate_property_enumerator();
798
799 prop_sets.start_property_enumerator(handle, TEE_PROPSET_TEE_IMPLEMENTATION);
800 let name = prop_sets.get_property_name(handle).unwrap();
801 assert_eq!("gpd.tee.test.string".to_string(), name);
802
803 prop_sets.get_next_property(handle).unwrap();
804 let name = prop_sets.get_property_name(handle).unwrap();
805 assert_eq!("gpd.tee.test.bool".to_string(), name);
806
807 prop_sets.reset_property_enumerator(handle);
808 let name = prop_sets.get_property_name(handle).unwrap();
809 assert_eq!("gpd.tee.test.string".to_string(), name);
810 }
811
812 #[fuchsia::test]
813 pub fn test_enumerator_get_name_ta_prop_set() {
814 let mut prop_sets = init_test_tee_impl_props();
815 let handle = prop_sets.allocate_property_enumerator();
816
817 prop_sets.start_property_enumerator(handle, TEE_PROPSET_CURRENT_TA);
818 let name = prop_sets.get_property_name(handle).unwrap();
819 assert_eq!("gpd.ta.appID".to_string(), name);
820 }
821
822 #[fuchsia::test]
823 pub fn test_enumerator_get_name_client_prop_set() {
824 let mut prop_sets = init_test_tee_impl_props();
825 let handle = prop_sets.allocate_property_enumerator();
826
827 prop_sets.start_property_enumerator(handle, TEE_PROPSET_CURRENT_CLIENT);
828 let name = prop_sets.get_property_name(handle).unwrap();
829 assert_eq!("gpd.client.identity".to_string(), name);
830 }
831
832 #[fuchsia::test]
833 pub fn test_enumerator_all_prop_types() {
834 let mut prop_sets = init_test_tee_impl_props();
837 let handle = prop_sets.allocate_property_enumerator();
838
839 prop_sets.start_property_enumerator(handle, TEE_PROPSET_TEE_IMPLEMENTATION);
840 let string_val = prop_sets.get_string_property(handle, "").unwrap();
841 assert_eq!("asdf".to_string(), string_val);
842
843 prop_sets.get_next_property(handle).unwrap();
844 let bool_val = prop_sets.get_bool_property(handle, "").unwrap();
845 assert!(bool_val);
846
847 prop_sets.get_next_property(handle).unwrap();
848 let u32_val = prop_sets.get_uint32_property(handle, "").unwrap();
849 assert_eq!(57, u32_val);
850
851 prop_sets.get_next_property(handle).unwrap();
852 let u64_val = prop_sets.get_uint64_property(handle, "").unwrap();
853 assert_eq!(4294967296, u64_val);
854
855 prop_sets.get_next_property(handle).unwrap();
856 let binary_block = prop_sets.get_binary_block_property(handle, "").unwrap();
857 let expected_val_as_u8: Vec<u8> = vec![102, 117, 99, 104, 115, 105, 97];
858 assert_eq!(7, binary_block.len());
859 assert_eq!(expected_val_as_u8, binary_block);
860
861 prop_sets.get_next_property(handle).unwrap();
862 let uuid_val = prop_sets.get_uuid_property(handle, "").unwrap();
863 assert_eq!(0x9cccff19, uuid_val.time_low);
864 assert_eq!(0x13b5, uuid_val.time_mid);
865 assert_eq!(0x4d4c, uuid_val.time_hi_and_version);
866 assert_eq!([0xaa, 0x9e, 0x5c, 0x89, 0x01, 0xa5, 0x2e, 0x2f], uuid_val.clock_seq_and_node);
867
868 prop_sets.get_next_property(handle).unwrap();
869 let identity_val = prop_sets.get_identity_property(handle, "").unwrap();
870 assert_eq!(tee_internal::Login::TrustedApp, identity_val.login);
871 assert_eq!(0x9cccff19, identity_val.uuid.time_low);
872 assert_eq!(0x13b5, identity_val.uuid.time_mid);
873 assert_eq!(0x4d4c, identity_val.uuid.time_hi_and_version);
874 assert_eq!(
875 [0xaa, 0x9e, 0x5c, 0x89, 0x01, 0xa5, 0x2e, 0x2f],
876 identity_val.uuid.clock_seq_and_node
877 );
878
879 let res = prop_sets.get_next_property(handle);
880 assert_eq!(tee_internal::Error::ItemNotFound, res.err().unwrap())
881 }
882}