Add generic access policy for keymint Rust.

Bug: 266628746
Test: Mannual testing on the device and unit tests
Change-Id: Ifcff6ae8d4414138532f417247077530c67b01e5
diff --git a/app/rules.mk b/app/rules.mk
index defa731..9a3cb34 100644
--- a/app/rules.mk
+++ b/app/rules.mk
@@ -26,6 +26,7 @@
 
 MODULE_LIBRARY_DEPS += \
 	trusty/user/app/keymint \
+	trusty/user/app/keymint/unauthorized_test_app \
 	trusty/user/base/lib/keymint-rust/boringssl \
 	trusty/user/base/lib/keymint-rust/common \
 	trusty/user/base/lib/keymint-rust/ta \
diff --git a/generic_access_policy/lib.rs b/generic_access_policy/lib.rs
new file mode 100644
index 0000000..1e0f9e7
--- /dev/null
+++ b/generic_access_policy/lib.rs
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+//! The library implementing the generic access policy for Keymint Rust.
+//! This is a replication of `keymaster_generic_access_policy`.
+
+use tipc::Uuid;
+
+const ACCESSIBLE_UUIDS: [Uuid; 4] = [
+    /* gatekeeper uuid */
+    Uuid::new(0x38ba0cdc, 0xdf0e, 0x11e4, [0x98, 0x69, 0x23, 0x3f, 0xb6, 0xae, 0x47, 0x95]),
+    /* confirmation UI uuid */
+    Uuid::new(0x7dee2364, 0xc036, 0x425b, [0xb0, 0x86, 0xdf, 0x0f, 0x6c, 0x23, 0x3c, 0x1b]),
+    /* keymaster unit test uuid */
+    Uuid::new(0xf3ba7629, 0xe8cc, 0x44a0, [0x88, 0x4d, 0xf9, 0x16, 0xf7, 0x03, 0xa2, 0x00]),
+    /* keymint unit test uuid */
+    Uuid::new(0xd322eec9, 0x6d03, 0x49fa, [0x82, 0x1c, 0x1c, 0xcd, 0x27, 0x05, 0x71, 0x9c]),
+];
+
+pub fn keymint_check_target_access_policy(uuid: &Uuid) -> bool {
+    if ACCESSIBLE_UUIDS.contains(uuid) {
+        return true;
+    }
+    return false;
+}
+
+pub fn keymint_check_secure_target_access_policy_provisioning(_uuid: &Uuid) -> bool {
+    /* Not Supported */
+    return false;
+}
diff --git a/generic_access_policy/rules.mk b/generic_access_policy/rules.mk
new file mode 100644
index 0000000..cd07bee
--- /dev/null
+++ b/generic_access_policy/rules.mk
@@ -0,0 +1,29 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_SRCS += \
+	$(LOCAL_DIR)/lib.rs \
+
+MODULE_CRATE_NAME := keymint_access_policy
+
+MODULE_LIBRARY_DEPS += \
+	trusty/user/base/lib/tipc/rust \
+	trusty/user/base/lib/trusty-sys \
+
+include make/library.mk
\ No newline at end of file
diff --git a/ipc_manager.rs b/ipc_manager.rs
index 98cd2f9..85fc375 100644
--- a/ipc_manager.rs
+++ b/ipc_manager.rs
@@ -17,6 +17,9 @@
 use crate::secure_storage_manager;
 use alloc::{rc::Rc, vec::Vec};
 use core::{cell::RefCell, mem};
+use keymint_access_policy::{
+    keymint_check_secure_target_access_policy_provisioning, keymint_check_target_access_policy,
+};
 use kmr_common::{
     crypto, km_err,
     wire::legacy::{
@@ -51,7 +54,7 @@
 
 /// TIPC connection context information.
 struct Context {
-    _uuid: Uuid,
+    uuid: Uuid,
 }
 
 /// Newtype wrapper for opaque messages.
@@ -119,8 +122,8 @@
         _handle: &Handle,
         peer: &Uuid,
     ) -> Result<Option<Self::Connection>, TipcError> {
-        info!("Accepted connection from Uuid {:?}.", peer);
-        Ok(Some(Context { _uuid: peer.clone() }))
+        info!("Accepted connection from uuid {:?}.", peer);
+        Ok(Some(Context { uuid: peer.clone() }))
     }
 
     fn on_message(
@@ -368,8 +371,8 @@
         _handle: &Handle,
         peer: &Uuid,
     ) -> Result<Option<Self::Connection>, TipcError> {
-        info!("Accepted connection from Uuid {:?}.", peer);
-        Ok(Some(Context { _uuid: peer.clone() }))
+        info!("Accepted connection from uuid {:?}.", peer);
+        Ok(Some(Context { uuid: peer.clone() }))
     }
 
     fn on_message(
@@ -466,13 +469,17 @@
         _handle: &Handle,
         peer: &Uuid,
     ) -> Result<Option<Self::Connection>, TipcError> {
-        info!("Accepted connection from Uuid {:?}.", peer);
-        Ok(Some(Context { _uuid: peer.clone() }))
+        if !keymint_check_target_access_policy(peer) {
+            error!("access policy rejected the uuid: {:?}", peer);
+            return Ok(None);
+        }
+        info!("Accepted connection from uuid {:?}.", peer);
+        Ok(Some(Context { uuid: peer.clone() }))
     }
 
     fn on_message(
         &self,
-        _connection: &Self::Connection,
+        connection: &Self::Connection,
         handle: &Handle,
         msg: Self::Message,
     ) -> Result<bool, TipcError> {
@@ -483,6 +490,12 @@
             TipcError::InvalidData
         })?;
         let op = req_msg.code();
+        if matches!(&req_msg, TrustyPerformSecureOpReq::SetAttestationIds(_))
+            && !keymint_check_secure_target_access_policy_provisioning(&connection.uuid)
+        {
+            error!("access policy rejected the uuid: {:?}", &connection.uuid);
+            return Ok(false);
+        }
 
         let resp = match self.handle_message(req_msg) {
             Ok(resp_msg) => legacy::serialize_trusty_secure_rsp(resp_msg).map_err(|e| {
@@ -613,6 +626,22 @@
         let _session3 = Handle::connect(port3.as_c_str()).unwrap();
     }
 
+    // #[test]
+    fn test_access_policy() {
+        // Test whether the access policy is in action.
+        // Keymint unit test app should be able to connect to the KM secure service.
+        let port = CString::try_new(KM_SEC_TIPC_SRV_PORT).unwrap();
+        Handle::connect(port.as_c_str())
+            .expect("Keymint unit test app should be able to connect to the KM secure service");
+
+        // Keymint unit test app should not be able to call the attestation id provisioning API
+        // in the KM secure service.
+        let err = set_attestation_ids_secure().expect_err(
+            "An error is expected. Keymint unit test app shouldn't be able to provision",
+        );
+        assert_eq!(err, TipcError::SystemError(trusty_sys::Error::NoMsg));
+    }
+
     fn check_response_status(rsp: &KMMessage) -> Result<(), ErrorCode> {
         let error_code = legacy::deserialize_trusty_rsp_error_code(&rsp.0)
             .expect("Couldn't retrieve error code");
@@ -709,6 +738,38 @@
         expect!(km_error_code.is_ok(), "Should be able to call SetAttestatonKeys");
     }
 
+    fn set_attestation_ids_secure() -> Result<(), TipcError> {
+        let port = CString::try_new(KM_SEC_TIPC_SRV_PORT).unwrap();
+        let session = Handle::connect(port.as_c_str()).unwrap();
+
+        // Creating a SetAttestationIds message
+        let brand = b"no brand".to_vec();
+        let device = b"a new device".to_vec();
+        let product = b"p1".to_vec();
+        let serial = vec![b'5'; 64];
+        let imei = b"7654321".to_vec();
+        let meid = b"1234567".to_vec();
+        let manufacturer = b"a manufacturer".to_vec();
+        let model = b"the new one".to_vec();
+        let req = get_set_attestation_ids_message(
+            &brand,
+            &device,
+            &product,
+            &serial,
+            &imei,
+            &meid,
+            &manufacturer,
+            &model,
+        )
+        .expect("couldn't construct SetAttestatonIds request");
+        let set_attestation_ids_req = KMMessage(req);
+
+        // Sending SetAttestationIds
+        session.send(&set_attestation_ids_req).unwrap();
+        let buf = &mut [0; KEYMINT_MAX_BUFFER_LENGTH as usize];
+        session.recv(buf)
+    }
+
     //#[test]
     fn set_attestation_ids() {
         let port = CString::try_new(KM_NS_LEGACY_TIPC_SRV_PORT).unwrap();
diff --git a/rules.mk b/rules.mk
index e922a94..09bff8f 100644
--- a/rules.mk
+++ b/rules.mk
@@ -39,6 +39,12 @@
 	trusty/user/base/lib/trusty-log \
 	trusty/user/base/lib/trusty-std \
 
+ifdef TRUSTY_KM_RUST_ACCESS_POLICY
+    MODULE_LIBRARY_DEPS+= $(TRUSTY_KM_RUST_ACCESS_POLICY)
+else
+    MODULE_LIBRARY_DEPS+= trusty/user/app/keymint/generic_access_policy
+endif
+
 MODULE_RUSTFLAGS += \
 	--cfg 'feature="soft_attestation_fallback"' \
 
diff --git a/unauthorized_test_app/build-config-usertests b/unauthorized_test_app/build-config-usertests
new file mode 100644
index 0000000..8af4cfd
--- /dev/null
+++ b/unauthorized_test_app/build-config-usertests
@@ -0,0 +1,19 @@
+# Copyright (C) 2022 The Android Open Source Project
+#
+# Licensed 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.
+
+# This file lists userspace tests
+
+[
+    porttest("com.android.trusty.rust.keymint_unauthorized_test_app.test").needs(storage_boot=True),
+]
\ No newline at end of file
diff --git a/unauthorized_test_app/lib.rs b/unauthorized_test_app/lib.rs
new file mode 100644
index 0000000..a341db5
--- /dev/null
+++ b/unauthorized_test_app/lib.rs
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+#[cfg(test)]
+mod tests {
+    use tipc::{Handle, TipcError};
+    use trusty_std::ffi::{CString, FallibleCString};
+
+    test::init!();
+
+    /// Port that handles secure world messages
+    const KM_SEC_TIPC_SRV_PORT: &str = "com.android.trusty.keymaster.secure";
+    #[test]
+    fn test_access_policy_unauthorized() {
+        let port2 = CString::try_new(KM_SEC_TIPC_SRV_PORT).unwrap();
+        let err1 = Handle::connect(port2.as_c_str()).expect_err(
+            "An error is expected because the uuid of this test app is
+                          not in the allowed uuid list of the keymint access policy.",
+        );
+        assert_eq!(err1, TipcError::SystemError(trusty_sys::Error::ChannelClosed));
+    }
+}
diff --git a/unauthorized_test_app/manifest.json b/unauthorized_test_app/manifest.json
new file mode 100644
index 0000000..fb9f672
--- /dev/null
+++ b/unauthorized_test_app/manifest.json
@@ -0,0 +1,6 @@
+{
+    "app_name": "keymint_unauthorized_test_app",
+    "uuid": "bf6d54ae-a991-11ed-afa1-0242ac120002",
+    "min_heap": 118784,
+    "min_stack": 65536
+}
\ No newline at end of file
diff --git a/unauthorized_test_app/rules.mk b/unauthorized_test_app/rules.mk
new file mode 100644
index 0000000..0067782
--- /dev/null
+++ b/unauthorized_test_app/rules.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MANIFEST := $(LOCAL_DIR)/manifest.json
+
+MODULE_SRCS += \
+	$(LOCAL_DIR)/lib.rs \
+
+MODULE_CRATE_NAME := keymint_unauthorized_test_app
+
+MODULE_LIBRARY_DEPS += \
+	trusty/user/base/lib/tipc/rust \
+	trusty/user/base/lib/trusty-std \
+
+MODULE_RUST_TESTS := true
+
+include make/library.mk
\ No newline at end of file
diff --git a/usertests-inc.mk b/usertests-inc.mk
index 166d32a..de85f3a 100644
--- a/usertests-inc.mk
+++ b/usertests-inc.mk
@@ -15,4 +15,5 @@
 
 TRUSTY_RUST_USER_TESTS += \
 	trusty/user/app/keymint \
+	trusty/user/app/keymint/unauthorized_test_app \