This is an automated email from the ASF dual-hosted git repository.

yuanz pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/incubator-teaclave-trustzone-sdk.git


The following commit(s) were added to refs/heads/main by this push:
     new 7daee91  optee-utee: support TEE_GetProperty API
7daee91 is described below

commit 7daee9178955ff9727b3577b3a7f2a0b5a50f9d9
Author: Yuan Zhuang <[email protected]>
AuthorDate: Wed Apr 16 08:43:58 2025 +0000

    optee-utee: support TEE_GetProperty API
    
    This commit introduces support for accessing TEE properties, as
    specified in the
    GlobalPlatform TEE Internal Core API Specification v1.3.1.
    
    It also provide the `property-rs` example for demostration.
    
    Signed-off-by: Yuan Zhuang <[email protected]>
    Reviewed-by: Zehui Chen <[email protected]>
---
 ci/ci.sh                                           |   1 +
 examples/property-rs/Makefile                      |  39 ++
 .../property-rs/host}/Cargo.toml                   |  29 +-
 examples/property-rs/host/Makefile                 |  37 ++
 examples/property-rs/host/src/main.rs              |  32 ++
 .../property-rs/proto}/Cargo.toml                  |  26 +-
 examples/property-rs/proto/src/lib.rs              |  32 ++
 {optee-utee => examples/property-rs/ta}/Cargo.toml |  33 +-
 examples/property-rs/ta/Makefile                   |  45 ++
 examples/property-rs/ta/Xargo.toml                 |  24 +
 examples/property-rs/ta/build.rs                   |  24 +
 examples/property-rs/ta/src/main.rs                | 114 +++++
 examples/property-rs/uuid.txt                      |   1 +
 optee-utee/Cargo.toml                              |   1 +
 optee-utee/optee-utee-sys/src/tee_api_types.rs     |   1 +
 optee-utee/src/identity.rs                         |  62 +++
 optee-utee/src/lib.rs                              |   3 +
 optee-utee/src/property.rs                         | 487 +++++++++++++++++++++
 optee-utee/src/uuid.rs                             |   8 +-
 ci/ci.sh => tests/test_property.sh                 |  52 +--
 20 files changed, 949 insertions(+), 102 deletions(-)

diff --git a/ci/ci.sh b/ci/ci.sh
index 2b1501d..fbd1ccc 100755
--- a/ci/ci.sh
+++ b/ci/ci.sh
@@ -54,6 +54,7 @@ fi
 ./test_udp_socket.sh
 ./test_client_pool.sh
 ./test_inter_ta.sh
+./test_property.sh
 
 
 popd
diff --git a/examples/property-rs/Makefile b/examples/property-rs/Makefile
new file mode 100644
index 0000000..a7a3dec
--- /dev/null
+++ b/examples/property-rs/Makefile
@@ -0,0 +1,39 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# If _HOST or _TA specific compiler/target are not specified, then use common
+# compiler/target for both
+CROSS_COMPILE_HOST ?= aarch64-linux-gnu-
+CROSS_COMPILE_TA ?= aarch64-linux-gnu-
+TARGET_HOST ?= aarch64-unknown-linux-gnu
+TARGET_TA ?= aarch64-unknown-linux-gnu
+
+.PHONY: host ta all clean
+
+all: host ta
+
+host:
+       $(q)make -C host TARGET=$(TARGET_HOST) \
+               CROSS_COMPILE=$(CROSS_COMPILE_HOST)
+
+ta:
+       $(q)make -C ta TARGET=$(TARGET_TA) \
+               CROSS_COMPILE=$(CROSS_COMPILE_TA)
+
+clean:
+       $(q)make -C host clean
+       $(q)make -C ta clean
diff --git a/optee-utee/Cargo.toml b/examples/property-rs/host/Cargo.toml
similarity index 59%
copy from optee-utee/Cargo.toml
copy to examples/property-rs/host/Cargo.toml
index 0bc7a9d..bfa5ea0 100644
--- a/optee-utee/Cargo.toml
+++ b/examples/property-rs/host/Cargo.toml
@@ -16,33 +16,18 @@
 # under the License.
 
 [package]
-name = "optee-utee"
+name = "property-rs"
 version = "0.4.0"
 authors = ["Teaclave Contributors <[email protected]>"]
 license = "Apache-2.0"
 repository = "https://github.com/apache/incubator-teaclave-trustzone-sdk.git";
-description = "TEE internal core API."
+description = "An example of Rust OP-TEE TrustZone SDK."
 edition = "2018"
 
 [dependencies]
-optee-utee-sys = { version = "0.4.0", path = "optee-utee-sys" }
-optee-utee-macros = { version = "0.4.0", path = "macros" }
-bitflags = "1.0.4"
-uuid = { version = "0.8", default-features = false }
-hex = { version = "0.4", default-features = false, features = ["alloc"] }
-libc_alloc = "1.0.5"
+libc = "0.2.48"
+proto = { path = "../proto" }
+optee-teec = { path = "../../../optee-teec" }
 
-[dev-dependencies]
-rand = "0.8.5"
-once_cell = "1.20.2"
-serde = { version = "1.0.215" }
-serde_json = { version = "1.0.133" }
-# disable linking when running unit tests
-optee-utee-sys = { version = "0.4.0", path = "optee-utee-sys", features = 
["no_link"] }
-
-[features]
-no_panic_handler = []
-
-[workspace]
-resolver = "2"
-members = ['systest']
+[profile.release]
+lto = true
diff --git a/examples/property-rs/host/Makefile 
b/examples/property-rs/host/Makefile
new file mode 100644
index 0000000..0166655
--- /dev/null
+++ b/examples/property-rs/host/Makefile
@@ -0,0 +1,37 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+NAME := property-rs
+
+TARGET ?= aarch64-unknown-linux-gnu
+CROSS_COMPILE ?= aarch64-linux-gnu-
+OBJCOPY := $(CROSS_COMPILE)objcopy
+LINKER_CFG := target.$(TARGET).linker=\"$(CROSS_COMPILE)gcc\"
+
+OUT_DIR := $(CURDIR)/target/$(TARGET)/release
+
+
+all: host strip
+
+host:
+       @cargo build --target $(TARGET_HOST) --release --config $(LINKER_CFG)
+
+strip: host
+       @$(OBJCOPY) --strip-unneeded $(OUT_DIR)/$(NAME) $(OUT_DIR)/$(NAME)
+
+clean:
+       @cargo clean
diff --git a/examples/property-rs/host/src/main.rs 
b/examples/property-rs/host/src/main.rs
new file mode 100644
index 0000000..1647efd
--- /dev/null
+++ b/examples/property-rs/host/src/main.rs
@@ -0,0 +1,32 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use optee_teec::{Context, ErrorKind, Operation, ParamNone, Uuid};
+use proto::{Command, UUID};
+
+fn main() -> optee_teec::Result<()> {
+    let mut ctx = Context::new()?;
+    let uuid =
+        Uuid::parse_str(UUID).map_err(|_| 
optee_teec::Error::from(ErrorKind::BadParameters))?;
+    let mut session = ctx.open_session(uuid)?;
+    let mut operation = Operation::new(0, ParamNone, ParamNone, ParamNone, 
ParamNone);
+
+    // Nothing to send, just invoke the Test command
+    session.invoke_command(Command::Test as u32, &mut operation)?;
+    println!("Success");
+    Ok(())
+}
diff --git a/optee-utee/Cargo.toml b/examples/property-rs/proto/Cargo.toml
similarity index 59%
copy from optee-utee/Cargo.toml
copy to examples/property-rs/proto/Cargo.toml
index 0bc7a9d..91066a3 100644
--- a/optee-utee/Cargo.toml
+++ b/examples/property-rs/proto/Cargo.toml
@@ -16,33 +16,13 @@
 # under the License.
 
 [package]
-name = "optee-utee"
+name = "proto"
 version = "0.4.0"
 authors = ["Teaclave Contributors <[email protected]>"]
 license = "Apache-2.0"
 repository = "https://github.com/apache/incubator-teaclave-trustzone-sdk.git";
-description = "TEE internal core API."
+description = "Data structures and functions shared by host and TA."
 edition = "2018"
 
 [dependencies]
-optee-utee-sys = { version = "0.4.0", path = "optee-utee-sys" }
-optee-utee-macros = { version = "0.4.0", path = "macros" }
-bitflags = "1.0.4"
-uuid = { version = "0.8", default-features = false }
-hex = { version = "0.4", default-features = false, features = ["alloc"] }
-libc_alloc = "1.0.5"
-
-[dev-dependencies]
-rand = "0.8.5"
-once_cell = "1.20.2"
-serde = { version = "1.0.215" }
-serde_json = { version = "1.0.133" }
-# disable linking when running unit tests
-optee-utee-sys = { version = "0.4.0", path = "optee-utee-sys", features = 
["no_link"] }
-
-[features]
-no_panic_handler = []
-
-[workspace]
-resolver = "2"
-members = ['systest']
+num_enum = { version = "0.7.3", default-features = false }
diff --git a/examples/property-rs/proto/src/lib.rs 
b/examples/property-rs/proto/src/lib.rs
new file mode 100644
index 0000000..98090b9
--- /dev/null
+++ b/examples/property-rs/proto/src/lib.rs
@@ -0,0 +1,32 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#![no_std]
+use num_enum::{FromPrimitive, IntoPrimitive};
+
+#[derive(FromPrimitive, IntoPrimitive)]
+#[repr(u32)]
+pub enum Command {
+    Test,
+    #[default]
+    Unknown,
+}
+
+// If Uuid::parse_str() returns an InvalidLength error, there may be an extra
+// newline in your uuid.txt file. You can remove it by running
+// `truncate -s 36 uuid.txt`.
+pub const UUID: &str = &include_str!("../../uuid.txt");
\ No newline at end of file
diff --git a/optee-utee/Cargo.toml b/examples/property-rs/ta/Cargo.toml
similarity index 59%
copy from optee-utee/Cargo.toml
copy to examples/property-rs/ta/Cargo.toml
index 0bc7a9d..4a0f9d2 100644
--- a/optee-utee/Cargo.toml
+++ b/examples/property-rs/ta/Cargo.toml
@@ -16,33 +16,24 @@
 # under the License.
 
 [package]
-name = "optee-utee"
+name = "ta"
 version = "0.4.0"
 authors = ["Teaclave Contributors <[email protected]>"]
 license = "Apache-2.0"
 repository = "https://github.com/apache/incubator-teaclave-trustzone-sdk.git";
-description = "TEE internal core API."
+description = "An example of Rust OP-TEE TrustZone SDK."
 edition = "2018"
 
 [dependencies]
-optee-utee-sys = { version = "0.4.0", path = "optee-utee-sys" }
-optee-utee-macros = { version = "0.4.0", path = "macros" }
-bitflags = "1.0.4"
-uuid = { version = "0.8", default-features = false }
-hex = { version = "0.4", default-features = false, features = ["alloc"] }
-libc_alloc = "1.0.5"
+proto = { path = "../proto" }
+optee-utee-sys = { path = "../../../optee-utee/optee-utee-sys" }
+optee-utee = { path = "../../../optee-utee" }
 
-[dev-dependencies]
-rand = "0.8.5"
-once_cell = "1.20.2"
-serde = { version = "1.0.215" }
-serde_json = { version = "1.0.133" }
-# disable linking when running unit tests
-optee-utee-sys = { version = "0.4.0", path = "optee-utee-sys", features = 
["no_link"] }
+[build-dependencies]
+proto = { path = "../proto" }
+optee-utee-build = { path = "../../../optee-utee-build" }
 
-[features]
-no_panic_handler = []
-
-[workspace]
-resolver = "2"
-members = ['systest']
+[profile.release]
+panic = "abort"
+lto = true
+opt-level = 1
diff --git a/examples/property-rs/ta/Makefile b/examples/property-rs/ta/Makefile
new file mode 100644
index 0000000..029e66d
--- /dev/null
+++ b/examples/property-rs/ta/Makefile
@@ -0,0 +1,45 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+UUID ?= $(shell cat "../uuid.txt")
+
+TARGET ?= aarch64-unknown-linux-gnu
+CROSS_COMPILE ?= aarch64-linux-gnu-
+OBJCOPY := $(CROSS_COMPILE)objcopy
+# Configure the linker to use GCC, which works on both cross-compilation and 
ARM machines
+LINKER_CFG := target.$(TARGET).linker=\"$(CROSS_COMPILE)gcc\"
+
+TA_SIGN_KEY ?= $(TA_DEV_KIT_DIR)/keys/default_ta.pem
+SIGN := $(TA_DEV_KIT_DIR)/scripts/sign_encrypt.py
+OUT_DIR := $(CURDIR)/target/$(TARGET)/release
+
+BUILDER = $(if $(STD),xargo,cargo)
+
+all: ta strip sign
+
+ta:
+       @$(BUILDER) build --target $(TARGET) --release --config $(LINKER_CFG)
+
+strip: ta
+       @$(OBJCOPY) --strip-unneeded $(OUT_DIR)/ta $(OUT_DIR)/stripped_ta
+
+sign: strip
+       @$(SIGN) --uuid $(UUID) --key $(TA_SIGN_KEY) --in 
$(OUT_DIR)/stripped_ta --out $(OUT_DIR)/$(UUID).ta
+       @echo "SIGN =>  ${UUID}"
+
+clean:
+       @cargo clean
diff --git a/examples/property-rs/ta/Xargo.toml 
b/examples/property-rs/ta/Xargo.toml
new file mode 100644
index 0000000..1b1a113
--- /dev/null
+++ b/examples/property-rs/ta/Xargo.toml
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[dependencies.std]
+path = "../../../rust/rust/library/std"
+
+[patch.crates-io]
+libc =  { path = "../../../rust/libc" }
+rustc-std-workspace-core = { path = 
"../../../rust/rust/library/rustc-std-workspace-core" }
+rustc-std-workspace-alloc = { path = 
"../../../rust/rust/library/rustc-std-workspace-alloc" }
diff --git a/examples/property-rs/ta/build.rs b/examples/property-rs/ta/build.rs
new file mode 100644
index 0000000..c6d585f
--- /dev/null
+++ b/examples/property-rs/ta/build.rs
@@ -0,0 +1,24 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use optee_utee_build::{Error, RustEdition, TaConfig};
+use proto;
+
+fn main() -> Result<(), Error> {
+    let config = TaConfig::new_default_with_cargo_env(proto::UUID)?;
+    optee_utee_build::build(RustEdition::Before2024, config)
+}
diff --git a/examples/property-rs/ta/src/main.rs 
b/examples/property-rs/ta/src/main.rs
new file mode 100644
index 0000000..df9fc83
--- /dev/null
+++ b/examples/property-rs/ta/src/main.rs
@@ -0,0 +1,114 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#![no_std]
+#![no_main]
+
+extern crate alloc;
+use alloc::string::ToString;
+
+use optee_utee::property::{
+    ClientIdentity, PropertyKey, TaDescription, TaMultiSession, 
TeeInternalCoreVersion,
+};
+use optee_utee::LoginType;
+use optee_utee::{
+    ta_close_session, ta_create, ta_destroy, ta_invoke_command, 
ta_open_session, trace_println,
+};
+use optee_utee::{Error, ErrorKind, Parameters, Result};
+use proto::Command;
+
+#[ta_create]
+fn create() -> Result<()> {
+    trace_println!("[+] TA create");
+    Ok(())
+}
+
+#[ta_open_session]
+fn open_session(_params: &mut Parameters) -> Result<()> {
+    trace_println!("[+] TA open session");
+    Ok(())
+}
+
+#[ta_close_session]
+fn close_session() {
+    trace_println!("[+] TA close session");
+}
+
+#[ta_destroy]
+fn destroy() {
+    trace_println!("[+] TA destroy");
+}
+
+fn get_properties() -> Result<()> {
+    // check caller
+    let client_identity = ClientIdentity.get()?;
+    trace_println!(
+        "[+] TA get caller identity: login: {}, uuid: {}",
+        client_identity.login_type(),
+        client_identity.uuid()
+    );
+    // login type should be Public
+    if client_identity.login_type() != LoginType::Public {
+        return Err(Error::new(ErrorKind::BadParameters));
+    }
+    // uuid should be all zero
+    if client_identity.uuid().to_string() != 
"00000000-0000-0000-0000-000000000000" {
+        return Err(Error::new(ErrorKind::BadParameters));
+    }
+
+    // test the other property:
+    let core_version = TeeInternalCoreVersion.get()?;
+    trace_println!("[+] TA get core version: {}", core_version);
+    // core version should not be zero
+    if core_version == 0 {
+        return Err(Error::new(ErrorKind::BadParameters));
+    }
+
+    let ta_multi_session = TaMultiSession.get()?;
+    trace_println!("[+] TA get multi session: {}", ta_multi_session);
+    // multi session should be false
+    if ta_multi_session {
+        return Err(Error::new(ErrorKind::BadParameters));
+    }
+
+    let ta_description = TaDescription.get()?;
+    trace_println!("[+] TA get description: {}", ta_description);
+    // description should be the specified string
+    if ta_description != "An example of Rust OP-TEE TrustZone SDK." {
+        return Err(Error::new(ErrorKind::BadParameters));
+    }
+
+    Ok(())
+}
+
+#[ta_invoke_command]
+fn invoke_command(cmd_id: u32, _params: &mut Parameters) -> Result<()> {
+    trace_println!("[+] TA invoke command");
+    match Command::from(cmd_id) {
+        Command::Test => {
+            get_properties()?;
+
+            trace_println!("[+] Test passed");
+            Ok(())
+        }
+        _ => {
+            return Err(Error::new(ErrorKind::NotSupported));
+        }
+    }
+}
+
+include!(concat!(env!("OUT_DIR"), "/user_ta_header.rs"));
diff --git a/examples/property-rs/uuid.txt b/examples/property-rs/uuid.txt
new file mode 100644
index 0000000..870c3f7
--- /dev/null
+++ b/examples/property-rs/uuid.txt
@@ -0,0 +1 @@
+a3859d33-b540-4a69-8d29-696dde9115cc
\ No newline at end of file
diff --git a/optee-utee/Cargo.toml b/optee-utee/Cargo.toml
index 0bc7a9d..3ad0bf3 100644
--- a/optee-utee/Cargo.toml
+++ b/optee-utee/Cargo.toml
@@ -31,6 +31,7 @@ bitflags = "1.0.4"
 uuid = { version = "0.8", default-features = false }
 hex = { version = "0.4", default-features = false, features = ["alloc"] }
 libc_alloc = "1.0.5"
+strum_macros = "0.26"
 
 [dev-dependencies]
 rand = "0.8.5"
diff --git a/optee-utee/optee-utee-sys/src/tee_api_types.rs 
b/optee-utee/optee-utee-sys/src/tee_api_types.rs
index da95338..f925204 100644
--- a/optee-utee/optee-utee-sys/src/tee_api_types.rs
+++ b/optee-utee/optee-utee-sys/src/tee_api_types.rs
@@ -32,6 +32,7 @@ pub struct TEE_UUID {
     pub clockSeqAndNode: [u8; 8],
 }
 
+#[derive(Copy, Clone)]
 #[repr(C)]
 pub struct TEE_Identity {
     pub login: u32,
diff --git a/optee-utee/src/identity.rs b/optee-utee/src/identity.rs
new file mode 100644
index 0000000..ae3e3f8
--- /dev/null
+++ b/optee-utee/src/identity.rs
@@ -0,0 +1,62 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::Uuid;
+use optee_utee_sys as raw;
+use strum_macros::Display;
+
+#[derive(Copy, Clone)]
+pub struct Identity {
+    raw: raw::TEE_Identity,
+}
+
+impl Identity {
+    pub fn login_type(&self) -> LoginType {
+        match self.raw.login {
+            raw::TEE_LOGIN_PUBLIC => LoginType::Public,
+            raw::TEE_LOGIN_USER => LoginType::User,
+            raw::TEE_LOGIN_GROUP => LoginType::Group,
+            raw::TEE_LOGIN_APPLICATION => LoginType::Application,
+            raw::TEE_LOGIN_APPLICATION_USER => LoginType::ApplicationUser,
+            raw::TEE_LOGIN_APPLICATION_GROUP => LoginType::ApplicationGroup,
+            raw::TEE_LOGIN_TRUSTED_APP => LoginType::TrustedApp,
+            _ => panic!("Invalid login type"),
+        }
+    }
+
+    pub fn uuid(&self) -> Uuid {
+        Uuid::from(self.raw.uuid)
+    }
+}
+
+impl From<raw::TEE_Identity> for Identity {
+    fn from(raw: raw::TEE_Identity) -> Self {
+        Self { raw }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Display)]
+#[repr(u32)]
+pub enum LoginType {
+    Public = raw::TEE_LOGIN_PUBLIC,
+    User = raw::TEE_LOGIN_USER,
+    Group = raw::TEE_LOGIN_GROUP,
+    Application = raw::TEE_LOGIN_APPLICATION,
+    ApplicationUser = raw::TEE_LOGIN_APPLICATION_USER,
+    ApplicationGroup = raw::TEE_LOGIN_APPLICATION_GROUP,
+    TrustedApp = raw::TEE_LOGIN_TRUSTED_APP,
+}
diff --git a/optee-utee/src/lib.rs b/optee-utee/src/lib.rs
index 795c5ca..c1fc00a 100644
--- a/optee-utee/src/lib.rs
+++ b/optee-utee/src/lib.rs
@@ -47,6 +47,7 @@ pub use self::arithmetical::*;
 pub use self::crypto_op::*;
 pub use self::error::{Error, ErrorKind, Result};
 pub use self::extension::*;
+pub use self::identity::{Identity, LoginType};
 pub use self::object::*;
 pub use self::parameter::{ParamType, ParamTypes, Parameter, Parameters};
 pub use self::ta_session::{TaSession, TaSessionBuilder};
@@ -64,9 +65,11 @@ pub mod arithmetical;
 pub mod crypto_op;
 mod error;
 pub mod extension;
+pub mod identity;
 pub mod net;
 pub mod object;
 mod parameter;
+pub mod property;
 mod ta_session;
 mod tee_parameter;
 pub mod time;
diff --git a/optee-utee/src/property.rs b/optee-utee/src/property.rs
new file mode 100644
index 0000000..2a033a1
--- /dev/null
+++ b/optee-utee/src/property.rs
@@ -0,0 +1,487 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::{Error, ErrorKind, Result};
+use crate::{Identity, Uuid};
+use alloc::{ffi::CString, string::String, vec::Vec};
+use optee_utee_sys as raw;
+
+/// Represents a TEE property set according to the TEE Internal API.
+/// The property set is a collection of properties that can be
+/// queried from the TEE. The property set is identified by a
+/// handle, which is a pointer to a TEE_PropSetHandle structure.
+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,
+        }
+    }
+}
+
+/// Represents a TEE property value.
+/// The property value can be of different types, such as
+/// string, bool, u32, TEE_UUID, TEE_Identity, etc.
+/// The property value is obtained from the TEE
+/// property set using the TEE_GetPropertyAs* functions.
+pub trait PropertyValue: Sized {
+    fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self>;
+}
+
+/// Implements the PropertyValue trait for all return types:
+/// String, Bool, u32, u64, BinaryBlock, UUID, Identity.
+impl PropertyValue for String {
+    fn from_raw(set: raw::TEE_PropSetHandle, key: CString) -> Result<Self> {
+        let mut out_size = 0;
+
+        // The first call is to get the size of the string
+        // So we pass a null pointer and a size of 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 an empty string
+                    return Ok(String::new());
+                }
+                else {
+                    return Err(Error::new(ErrorKind::Generic));
+                }
+            }
+            raw::TEE_ERROR_SHORT_BUFFER => {
+                // Resize the string to the actual size
+                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));
+                }
+
+                // Convert the char buffer with null terminator to a C string
+                let c_str = core::ffi::CStr::from_bytes_with_nul(&out_buffer)
+                    .map_err(|_| Error::new(ErrorKind::BadFormat))?;
+                // Convert the C string to a Rust string
+                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;
+
+        // The first call is to get the size of the binary block
+        // So we pass a null pointer and a size of 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 an empty buffer
+                    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> {
+        // Allocate a buffer for the raw identity
+        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))
+    }
+}
+
+/// Represents a TEE property key.
+/// The property key is used to identify a specific property
+/// within a property set. The property key is a string that
+/// is used to query the property value from the TEE property
+/// set. The property key is defined in the TEE Internal API,
+/// such as "gpd.client.identity" or "gpd.tee.apiversion".
+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 to define a property key.
+/// This macro generates a struct that implements the
+/// PropertyKey trait.
+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 all existing property keys for the TEE property set.
+// The format is:
+// `define_property_key!(Name, Set, "key", OutputType);`
+// The `Set` is one of the PropertySet it belongs to.
+// The `key` is the raw property key string.
+// The `OutputType` is the type of the property value.
+// 
+// To get the property value, use the `get` method.
+// Example usage:
+// 
+// ``` no_run
+// use optee_utee::{PropertyKey, TaAppId};
+// 
+// let my_property = TaAppId.get()?;
+// ```
+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
+);
diff --git a/optee-utee/src/uuid.rs b/optee-utee/src/uuid.rs
index 4017943..99c4930 100644
--- a/optee-utee/src/uuid.rs
+++ b/optee-utee/src/uuid.rs
@@ -79,7 +79,7 @@ impl Uuid {
         ))
     }
 
-    /// Crates a raw TEE client uuid object with specified parameters.
+    /// Creates a raw TEE client uuid object with specified parameters.
     pub fn new_raw(
         time_low: u32,
         time_mid: u16,
@@ -115,6 +115,12 @@ impl fmt::Display for Uuid {
     }
 }
 
+impl From<raw::TEE_UUID> for Uuid {
+    fn from(raw: raw::TEE_UUID) -> Self {
+        Uuid { raw }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     extern crate alloc;
diff --git a/ci/ci.sh b/tests/test_property.sh
similarity index 50%
copy from ci/ci.sh
copy to tests/test_property.sh
index 2b1501d..588c903 100755
--- a/ci/ci.sh
+++ b/tests/test_property.sh
@@ -19,41 +19,23 @@
 
 set -xe
 
-pushd ../tests
+# Include base script
+source setup.sh
 
-# Prioritize running specialized test suites first, as they have a higher
-# probability of detecting failures early in the pipeline.
-# Run std only tests
-if [ "$STD" ]; then
-    ./test_serde.sh
-    ./test_message_passing_interface.sh
-    ./test_tls_client.sh
-    ./test_tls_server.sh
-    ./test_eth_wallet.sh
-    ./test_secure_db_abstraction.sh
-else
-    ./test_mnist_rs.sh
-    ./test_build_with_optee_utee_sys.sh
-fi
+# Copy TA and host binary
+cp ../examples/property-rs/host/target/$TARGET_HOST/release/property-rs shared
+cp ../examples/property-rs/ta/target/$TARGET_TA/release/*.ta shared
 
-./test_hello_world.sh
-./test_random.sh
-./test_secure_storage.sh
-./test_aes.sh
-./test_hotp.sh
-./test_acipher.sh
-./test_big_int.sh
-./test_diffie_hellman.sh
-./test_digest.sh
-./test_authentication.sh
-./test_time.sh
-./test_signature_verification.sh
-./test_supp_plugin.sh
-./test_error_handling.sh
-./test_tcp_client.sh
-./test_udp_socket.sh
-./test_client_pool.sh
-./test_inter_ta.sh
+# Run script specific commands in QEMU
+run_in_qemu "cp *.ta /lib/optee_armtz/\n"
+run_in_qemu "./property-rs\n"
+run_in_qemu "^C"
 
-
-popd
+# Script specific checks
+{
+    grep -q "Success" screenlog.0
+} || {
+    cat -v screenlog.0
+    cat -v /tmp/serial.log
+    false
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to