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 \