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

commit e12359b9612a4a9bf1bd345fe3d34cf49eac2a6b
Author: Yuan Zhuang <[email protected]>
AuthorDate: Thu Feb 27 10:25:40 2025 +0000

    examples: Add secure_db_abstraction (std-only)
    
    Add reference implementation for TA that simplifies interaction
    with secure storage. It provides basic methods for database
    operations, including `get()`, `put()`, `delete_entries()`, and
    `list_entries()`, making it easier for developers to store and
    retrieve data based on Rust Type constraints.
    
    The example is std-only for now.
    
    Signed-off-by: Yuan Zhuang <[email protected]>
    Reviewed-by: Zehui Chen <[email protected]>
---
 ci/ci.sh                                           |   1 +
 .../secure_db_abstraction-rs/Makefile              |  47 ++++----
 .../secure_db_abstraction-rs/host/Cargo.toml       |  44 +++-----
 .../secure_db_abstraction-rs/host/Makefile         |  59 +++++-----
 examples/secure_db_abstraction-rs/host/src/main.rs |  32 ++++++
 .../secure_db_abstraction-rs/proto/Cargo.toml      |  42 ++------
 examples/secure_db_abstraction-rs/proto/src/lib.rs |  31 ++++++
 .../secure_db_abstraction-rs/ta/Cargo.toml         |  52 ++++-----
 examples/secure_db_abstraction-rs/ta/Makefile      |  50 +++++++++
 .../secure_db_abstraction-rs/ta/Xargo.toml         |  38 ++-----
 examples/secure_db_abstraction-rs/ta/build.rs      |  24 +++++
 examples/secure_db_abstraction-rs/ta/src/main.rs   | 120 +++++++++++++++++++++
 .../ta/src/secure_db/backend.rs                    |  86 +++++++++++++++
 .../ta/src/secure_db/client.rs                     | 102 ++++++++++++++++++
 .../ta/src/secure_db/db.rs                         | 113 +++++++++++++++++++
 .../ta/src/secure_db/mod.rs                        |  25 +++++
 .../ta/src/secure_db/storable.rs                   |  52 +++++++++
 examples/secure_db_abstraction-rs/uuid.txt         |   1 +
 ci/ci.sh => tests/test_secure_db_abstraction.sh    |  45 ++++----
 19 files changed, 751 insertions(+), 213 deletions(-)

diff --git a/ci/ci.sh b/ci/ci.sh
index e10916f..7556757 100755
--- a/ci/ci.sh
+++ b/ci/ci.sh
@@ -45,6 +45,7 @@ if [ "$STD" ]; then
     ./test_tls_client.sh
     ./test_tls_server.sh
     ./test_eth_wallet.sh
+    ./test_secure_db_abstraction.sh
 fi
 
 popd
diff --git a/ci/ci.sh b/examples/secure_db_abstraction-rs/Makefile
old mode 100755
new mode 100644
similarity index 58%
copy from ci/ci.sh
copy to examples/secure_db_abstraction-rs/Makefile
index e10916f..a7a3dec
--- a/ci/ci.sh
+++ b/examples/secure_db_abstraction-rs/Makefile
@@ -1,5 +1,3 @@
-#!/bin/bash
-
 # 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
@@ -17,34 +15,25 @@
 # specific language governing permissions and limitations
 # under the License.
 
-set -xe
+# 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
 
-pushd ../tests
+all: host ta
 
-./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
+host:
+       $(q)make -C host TARGET=$(TARGET_HOST) \
+               CROSS_COMPILE=$(CROSS_COMPILE_HOST)
 
-# 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
-fi
+ta:
+       $(q)make -C ta TARGET=$(TARGET_TA) \
+               CROSS_COMPILE=$(CROSS_COMPILE_TA)
 
-popd
+clean:
+       $(q)make -C host clean
+       $(q)make -C ta clean
diff --git a/ci/ci.sh b/examples/secure_db_abstraction-rs/host/Cargo.toml
old mode 100755
new mode 100644
similarity index 58%
copy from ci/ci.sh
copy to examples/secure_db_abstraction-rs/host/Cargo.toml
index e10916f..c199ce8
--- a/ci/ci.sh
+++ b/examples/secure_db_abstraction-rs/host/Cargo.toml
@@ -1,5 +1,3 @@
-#!/bin/bash
-
 # 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
@@ -17,34 +15,18 @@
 # specific language governing permissions and limitations
 # under the License.
 
-set -xe
-
-pushd ../tests
-
-./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
+[package]
+name = "secure_db_abstraction-rs"
+version = "0.1.0"
+authors = ["Teaclave Contributors <[email protected]>"]
+license = "Apache-2.0"
+repository = "https://github.com/apache/incubator-teaclave-trustzone-sdk.git";
+description = "An example of Rust OP-TEE TrustZone SDK."
+edition = "2018"
 
-# 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
-fi
+[dependencies]
+proto = { path = "../proto" }
+optee-teec = { path = "../../../optee-teec" }
 
-popd
+[profile.release]
+lto = true
diff --git a/ci/ci.sh b/examples/secure_db_abstraction-rs/host/Makefile
old mode 100755
new mode 100644
similarity index 57%
copy from ci/ci.sh
copy to examples/secure_db_abstraction-rs/host/Makefile
index e10916f..c8b90ce
--- a/ci/ci.sh
+++ b/examples/secure_db_abstraction-rs/host/Makefile
@@ -1,5 +1,3 @@
-#!/bin/bash
-
 # 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
@@ -17,34 +15,29 @@
 # specific language governing permissions and limitations
 # under the License.
 
-set -xe
-
-pushd ../tests
-
-./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
-
-# 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
-fi
-
-popd
+# STD-ONLY example
+
+NAME := secure_db_abstraction-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
+
+ifeq ($(STD),)
+all:
+       @echo "Please \`export STD=y\` then rerun \`source environment\` to 
build the STD version"
+else
+all: host strip
+endif
+
+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/secure_db_abstraction-rs/host/src/main.rs 
b/examples/secure_db_abstraction-rs/host/src/main.rs
new file mode 100644
index 0000000..1647efd
--- /dev/null
+++ b/examples/secure_db_abstraction-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/ci/ci.sh b/examples/secure_db_abstraction-rs/proto/Cargo.toml
old mode 100755
new mode 100644
similarity index 58%
copy from ci/ci.sh
copy to examples/secure_db_abstraction-rs/proto/Cargo.toml
index e10916f..e30aef8
--- a/ci/ci.sh
+++ b/examples/secure_db_abstraction-rs/proto/Cargo.toml
@@ -1,5 +1,3 @@
-#!/bin/bash
-
 # 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
@@ -17,34 +15,14 @@
 # specific language governing permissions and limitations
 # under the License.
 
-set -xe
-
-pushd ../tests
-
-./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
-
-# 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
-fi
+[package]
+name = "proto"
+version = "0.1.0"
+authors = ["Teaclave Contributors <[email protected]>"]
+license = "Apache-2.0"
+repository = "https://github.com/apache/incubator-teaclave-trustzone-sdk.git";
+description = "Data structures and functions shared by host and TA."
+edition = "2018"
 
-popd
+[dependencies]
+num_enum = { version = "0.7.3", default-features = false }
diff --git a/examples/secure_db_abstraction-rs/proto/src/lib.rs 
b/examples/secure_db_abstraction-rs/proto/src/lib.rs
new file mode 100644
index 0000000..76bf57f
--- /dev/null
+++ b/examples/secure_db_abstraction-rs/proto/src/lib.rs
@@ -0,0 +1,31 @@
+// 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 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");
diff --git a/ci/ci.sh b/examples/secure_db_abstraction-rs/ta/Cargo.toml
old mode 100755
new mode 100644
similarity index 53%
copy from ci/ci.sh
copy to examples/secure_db_abstraction-rs/ta/Cargo.toml
index e10916f..40e2e9d
--- a/ci/ci.sh
+++ b/examples/secure_db_abstraction-rs/ta/Cargo.toml
@@ -1,5 +1,3 @@
-#!/bin/bash
-
 # 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
@@ -17,34 +15,28 @@
 # specific language governing permissions and limitations
 # under the License.
 
-set -xe
-
-pushd ../tests
+[package]
+name = "ta"
+version = "0.1.0"
+authors = ["Teaclave Contributors <[email protected]>"]
+license = "Apache-2.0"
+repository = "https://github.com/apache/incubator-teaclave-trustzone-sdk.git";
+description = "An example of Rust OP-TEE TrustZone SDK."
+edition = "2018"
 
-./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
+[dependencies]
+proto = { path = "../proto" }
+optee-utee-sys = { path = "../../../optee-utee/optee-utee-sys" }
+optee-utee = { path = "../../../optee-utee" }
+bincode = "1.3.3"
+anyhow = "1.0"
+serde = { version = "1.0", features = ["derive"] }
 
-# 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
-fi
+[build-dependencies]
+proto = { path = "../proto" }
+optee-utee-build = { path = "../../../optee-utee-build" }
 
-popd
+[profile.release]
+panic = "abort"
+lto = true
+opt-level = 1
diff --git a/examples/secure_db_abstraction-rs/ta/Makefile 
b/examples/secure_db_abstraction-rs/ta/Makefile
new file mode 100644
index 0000000..42d9236
--- /dev/null
+++ b/examples/secure_db_abstraction-rs/ta/Makefile
@@ -0,0 +1,50 @@
+# 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.
+
+# STD-ONLY example
+
+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
+
+ifeq ($(STD),)
+all:
+       @echo "Please \`export STD=y\` then rerun \`source environment\` to 
build the STD version"
+else
+all: ta strip sign
+endif
+
+ta:
+       @xargo 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/ci/ci.sh b/examples/secure_db_abstraction-rs/ta/Xargo.toml
old mode 100755
new mode 100644
similarity index 58%
copy from ci/ci.sh
copy to examples/secure_db_abstraction-rs/ta/Xargo.toml
index e10916f..1b1a113
--- a/ci/ci.sh
+++ b/examples/secure_db_abstraction-rs/ta/Xargo.toml
@@ -1,5 +1,3 @@
-#!/bin/bash
-
 # 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
@@ -17,34 +15,10 @@
 # specific language governing permissions and limitations
 # under the License.
 
-set -xe
-
-pushd ../tests
-
-./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
-
-# 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
-fi
+[dependencies.std]
+path = "../../../rust/rust/library/std"
 
-popd
+[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/secure_db_abstraction-rs/ta/build.rs 
b/examples/secure_db_abstraction-rs/ta/build.rs
new file mode 100644
index 0000000..34ae5fa
--- /dev/null
+++ b/examples/secure_db_abstraction-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 ta_config = TaConfig::new_default_with_cargo_env(proto::UUID)?;
+    optee_utee_build::build(RustEdition::Before2024, ta_config)
+}
diff --git a/examples/secure_db_abstraction-rs/ta/src/main.rs 
b/examples/secure_db_abstraction-rs/ta/src/main.rs
new file mode 100644
index 0000000..adc61bf
--- /dev/null
+++ b/examples/secure_db_abstraction-rs/ta/src/main.rs
@@ -0,0 +1,120 @@
+// 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_main]
+
+mod secure_db;
+
+extern crate alloc;
+
+use alloc::vec;
+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;
+use secure_db::{SecureStorageClient, Storable};
+use serde::{Deserialize, Serialize};
+
+#[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");
+}
+
+#[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 => match test() {
+            Ok(_) => {
+                trace_println!("[+] Test passed");
+                Ok(())
+            }
+            Err(e) => {
+                trace_println!("[-] Test failed: {:?}", e);
+                Err(Error::new(ErrorKind::Generic))
+            }
+        },
+        _ => {
+            return Err(Error::new(ErrorKind::NotSupported));
+        }
+    }
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
+pub struct ExampleData {
+    pub id: String,
+    pub data: Vec<u8>,
+}
+
+// Any structure that implements Storable can be stored in the secure db.
+// Any Key type can be used as unique id as long as it implements
+// TryFrom<String> + Into<String> + Clone
+impl Storable for ExampleData {
+    type Key = String;
+
+    fn unique_id(&self) -> Self::Key {
+        self.id.clone()
+    }
+}
+
+pub fn test() -> anyhow::Result<()> {
+    // Assume this is the data that we want to store
+    let example_data = ExampleData {
+        id: "example_data".to_string(),
+        data: vec![1, 2, 3, 4, 5],
+    };
+
+    // Initialize secure storage db client with a db name
+    let db_client = SecureStorageClient::open("secure_db")?;
+
+    // Now, we can do common db interactions using the db_client:
+    // Store data in db using put()
+    db_client.put(&example_data)?;
+    // Load data from db using get()
+    let loaded_example_data = db_client.get::<ExampleData>(&example_data.id)?;
+    anyhow::ensure!(
+        loaded_example_data == example_data,
+        "Loaded example_data is not equal to the original example_data"
+    );
+    // List all entries in db
+    let entries = db_client.list_entries::<ExampleData>()?;
+    trace_println!("Entries: {:?}", entries);
+    // Delete entry from db
+    db_client.delete_entry::<ExampleData>(&example_data.id)?;
+
+    Ok(())
+}
+
+include!(concat!(env!("OUT_DIR"), "/user_ta_header.rs"));
diff --git a/examples/secure_db_abstraction-rs/ta/src/secure_db/backend.rs 
b/examples/secure_db_abstraction-rs/ta/src/secure_db/backend.rs
new file mode 100644
index 0000000..ab40dcd
--- /dev/null
+++ b/examples/secure_db_abstraction-rs/ta/src/secure_db/backend.rs
@@ -0,0 +1,86 @@
+// 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 anyhow::{anyhow, bail, Result};
+use optee_utee::{DataFlag, ObjectStorageConstants, PersistentObject};
+
+// Wrapper functions for OP-TEE raw API
+
+pub fn save_in_secure_storage(obj_id: &[u8], data: &[u8]) -> Result<()> {
+    let obj_data_flag = DataFlag::ACCESS_READ
+        | DataFlag::ACCESS_WRITE
+        | DataFlag::ACCESS_WRITE_META
+        | DataFlag::OVERWRITE;
+
+    PersistentObject::create(
+        ObjectStorageConstants::Private,
+        obj_id,
+        obj_data_flag,
+        None,
+        data,
+    )
+    .map_err(|e| anyhow!("[-] {:?}: failed to create object: {:?}", &obj_id, 
e))?;
+
+    Ok(())
+}
+
+pub fn load_from_secure_storage(obj_id: &[u8]) -> Result<Option<Vec<u8>>> {
+    match PersistentObject::open(
+        ObjectStorageConstants::Private,
+        obj_id,
+        DataFlag::ACCESS_READ | DataFlag::SHARE_READ,
+    ) {
+        Err(e) => match e.kind() {
+            optee_utee::ErrorKind::ItemNotFound => {
+                return Ok(None);
+            }
+            _ => {
+                bail!("[-] {:?}: failed to open object: {:?}", &obj_id, e);
+            }
+        },
+
+        Ok(object) => {
+            let obj_info = object.info()?;
+            let mut buf = vec![0u8; obj_info.data_size() as usize];
+
+            let read_bytes = object.read(&mut buf)?;
+            if read_bytes != obj_info.data_size() as u32 {
+                bail!("[-] {:?}: failed to read data", &obj_id);
+            }
+
+            return Ok(Some(buf));
+        }
+    }
+}
+
+pub fn delete_from_secure_storage(obj_id: &[u8]) -> Result<()> {
+    match PersistentObject::open(
+        ObjectStorageConstants::Private,
+        &obj_id,
+        DataFlag::ACCESS_READ | DataFlag::ACCESS_WRITE_META,
+    ) {
+        Err(e) => {
+            bail!("[-] {:?}: failed to open object: {:?}", &obj_id, e);
+        }
+
+        Ok(mut object) => {
+            object.close_and_delete()?;
+            std::mem::forget(object);
+            return Ok(());
+        }
+    }
+}
diff --git a/examples/secure_db_abstraction-rs/ta/src/secure_db/client.rs 
b/examples/secure_db_abstraction-rs/ta/src/secure_db/client.rs
new file mode 100644
index 0000000..d6d649e
--- /dev/null
+++ b/examples/secure_db_abstraction-rs/ta/src/secure_db/client.rs
@@ -0,0 +1,102 @@
+// 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::secure_db::SecureStorageDb;
+use crate::Storable;
+use anyhow::{anyhow, Result};
+use std::{
+    collections::HashMap,
+    convert::TryFrom,
+    hash::Hash,
+    sync::{Arc, RwLock},
+};
+
+// SecureStorageClient is a client to interact with SecureStorageDb.
+// Bound operations to Structure that implements Storable trait.
+
+pub struct SecureStorageClient {
+    db: Arc<RwLock<SecureStorageDb>>,
+}
+
+impl SecureStorageClient {
+    pub fn open(db_name: &str) -> Result<Self> {
+        Ok(Self {
+            db: 
Arc::new(RwLock::new(SecureStorageDb::open(db_name.to_string())?)),
+        })
+    }
+
+    pub fn get<V>(&self, key: &V::Key) -> Result<V>
+    where
+        V: Storable + serde::de::DeserializeOwned,
+        V::Key: Into<String> + Clone,
+    {
+        let key: String = key.clone().into();
+        let storage_key = V::concat_key(&key);
+        let value = self
+            .db
+            .read()
+            .map_err(|_| anyhow!("Failed to acquire read lock"))?
+            .get(&storage_key)?;
+        Ok(bincode::deserialize(&value)?)
+    }
+
+    pub fn put<V>(&self, value: &V) -> Result<()>
+    where
+        V: Storable + serde::Serialize,
+    {
+        let key = value.storage_key();
+        let value = bincode::serialize(value)?;
+        self.db
+            .write()
+            .map_err(|_| anyhow!("Failed to acquire write lock"))?
+            .put(key, value)?;
+        Ok(())
+    }
+
+    pub fn delete_entry<V>(&self, key: &V::Key) -> Result<()>
+    where
+        V: Storable,
+        V::Key: Into<String> + Clone,
+    {
+        let key: String = key.clone().into();
+        let storage_key = V::concat_key(&key);
+        self.db
+            .write()
+            .map_err(|_| anyhow!("Failed to acquire write lock"))?
+            .delete(&storage_key)?;
+        Ok(())
+    }
+
+    pub fn list_entries<V>(&self) -> Result<HashMap<V::Key, V>>
+    where
+        V: Storable + serde::de::DeserializeOwned,
+        V::Key: TryFrom<String> + Eq + Hash,
+    {
+        let map = self
+            .db
+            .read()
+            .map_err(|_| anyhow!("Failed to acquire read lock"))?
+            .list_entries_with_prefix(V::table_name())?;
+        let mut result = HashMap::new();
+        for (_k, v) in map {
+            let value: V = bincode::deserialize(&v)?;
+            let key = value.unique_id();
+            result.insert(key, value);
+        }
+        Ok(result)
+    }
+}
diff --git a/examples/secure_db_abstraction-rs/ta/src/secure_db/db.rs 
b/examples/secure_db_abstraction-rs/ta/src/secure_db/db.rs
new file mode 100644
index 0000000..580601a
--- /dev/null
+++ b/examples/secure_db_abstraction-rs/ta/src/secure_db/db.rs
@@ -0,0 +1,113 @@
+// 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::secure_db::{
+    delete_from_secure_storage, load_from_secure_storage, 
save_in_secure_storage,
+};
+use anyhow::{bail, ensure, Result};
+use std::collections::{HashMap, HashSet};
+
+// SecureStorageDb is a key-value storage for TA to easily store and retrieve 
data.
+// First we store the key list in the secure storage, named as db_name.
+// Then we store the each key-value pairs in the secure storage.
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct SecureStorageDb {
+    name: String,
+    key_list: HashSet<String>,
+}
+
+impl SecureStorageDb {
+    pub fn open(name: String) -> Result<Self> {
+        match load_from_secure_storage(name.as_bytes())? {
+            Some(data) => {
+                let key_list = bincode::deserialize(&data)?;
+                Ok(Self { name, key_list })
+            }
+            None => {
+                // create new db
+                Ok(Self {
+                    name,
+                    key_list: HashSet::new(),
+                })
+            }
+        }
+    }
+
+    pub fn put(&mut self, key: String, value: Vec<u8>) -> Result<()> {
+        match save_in_secure_storage(key.as_bytes(), &value) {
+            Ok(_) => {
+                self.key_list.insert(key);
+                self.store_key_list()?;
+            }
+            Err(e) => {
+                bail!("[+] SecureStorage::insert(): save error: {}", e);
+            }
+        };
+        Ok(())
+    }
+
+    pub fn get(&self, key: &str) -> Result<Vec<u8>> {
+        ensure!(self.key_list.contains(key), "Key not found in key list");
+        match load_from_secure_storage(key.as_bytes()) {
+            Ok(Some(data)) => Ok(data),
+            Ok(None) => bail!("[+] SecureStorage::get(): object not found in 
db"),
+            Err(e) => {
+                bail!("[+] SecureStorage::get(): load error: {}", e);
+            }
+        }
+    }
+
+    pub fn delete(&mut self, key: &str) -> Result<()> {
+        // ensure key must exist
+        ensure!(self.key_list.contains(key), "Key not found in key list");
+        match delete_from_secure_storage(key.as_bytes()) {
+            Ok(_) => {
+                self.key_list.remove(key);
+                self.store_key_list()?;
+            }
+            Err(e) => {
+                bail!("[+] SecureStorage::delete(): delete error: {}", e);
+            }
+        };
+        Ok(())
+    }
+
+    pub fn clear(&mut self) -> Result<()> {
+        for key in self.key_list.clone() {
+            self.delete(&key)?;
+        }
+        Ok(())
+    }
+
+    pub fn list_entries_with_prefix(&self, prefix: &str) -> 
Result<HashMap<String, Vec<u8>>> {
+        let mut result = HashMap::new();
+        for key in &self.key_list {
+            if key.starts_with(prefix) {
+                let value = self.get(key)?;
+                result.insert(key.clone(), value);
+            }
+        }
+        Ok(result)
+    }
+
+    fn store_key_list(&self) -> Result<()> {
+        let key_list = bincode::serialize(&self.key_list)?;
+        save_in_secure_storage(self.name.as_bytes(), &key_list)?;
+        Ok(())
+    }
+}
diff --git a/examples/secure_db_abstraction-rs/ta/src/secure_db/mod.rs 
b/examples/secure_db_abstraction-rs/ta/src/secure_db/mod.rs
new file mode 100644
index 0000000..7b34551
--- /dev/null
+++ b/examples/secure_db_abstraction-rs/ta/src/secure_db/mod.rs
@@ -0,0 +1,25 @@
+// 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.
+
+mod backend;
+pub use backend::*;
+mod client;
+pub use client::*;
+mod db;
+pub use db::*;
+mod storable;
+pub use storable::*;
diff --git a/examples/secure_db_abstraction-rs/ta/src/secure_db/storable.rs 
b/examples/secure_db_abstraction-rs/ta/src/secure_db/storable.rs
new file mode 100644
index 0000000..afe063b
--- /dev/null
+++ b/examples/secure_db_abstraction-rs/ta/src/secure_db/storable.rs
@@ -0,0 +1,52 @@
+// 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 std::{convert::TryFrom, hash::Hash};
+
+// For each key-value data, the storage key is "$TABLE_NAME#$KEY"
+// For example, if we store the Data whose type is Structure named
+// ExampleData, with id "123",
+// the storage key will be "ExampleData#123"
+
+const CONCAT: &str = "#";
+
+pub trait Storable {
+    type Key: Into<String> + Clone + TryFrom<String> + Eq + Hash; // 
Associated type `Key`
+
+    fn unique_id(&self) -> Self::Key;
+
+    fn table_name() -> &'static str {
+        // keeps the last part of the path
+        std::any::type_name::<Self>()
+            .split("::")
+            .last()
+            .unwrap_or("WRONG_TABLE_NAME")
+    }
+
+    fn storage_key(&self) -> String {
+        format!(
+            "{}{}{}",
+            Self::table_name(),
+            CONCAT,
+            Into::<String>::into(self.unique_id())
+        )
+    }
+
+    fn concat_key(key: &str) -> String {
+        format!("{}{}{}", Self::table_name(), CONCAT, key)
+    }
+}
diff --git a/examples/secure_db_abstraction-rs/uuid.txt 
b/examples/secure_db_abstraction-rs/uuid.txt
new file mode 100644
index 0000000..8467254
--- /dev/null
+++ b/examples/secure_db_abstraction-rs/uuid.txt
@@ -0,0 +1 @@
+e55291e1-521c-4dca-aa24-51e34ab32ad9
\ No newline at end of file
diff --git a/ci/ci.sh b/tests/test_secure_db_abstraction.sh
similarity index 60%
copy from ci/ci.sh
copy to tests/test_secure_db_abstraction.sh
index e10916f..6bb0637 100755
--- a/ci/ci.sh
+++ b/tests/test_secure_db_abstraction.sh
@@ -19,32 +19,25 @@
 
 set -xe
 
-pushd ../tests
+# Include base script
+source setup.sh
 
-./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
+# Copy TA and host binary
+cp ../examples/secure_db_abstraction-rs/ta/target/$TARGET_TA/release/*.ta 
shared
+cp 
../examples/secure_db_abstraction-rs/host/target/$TARGET_HOST/release/secure_db_abstraction-rs
 shared
 
-# 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
-fi
+# Run script specific commands in QEMU
+run_in_qemu "cp *.ta /lib/optee_armtz/\n"
+run_in_qemu "./secure_db_abstraction-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
+}
+
+rm screenlog.0
\ No newline at end of file


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


Reply via email to