Initial Secretkeeper HAL service for Trusty
Disabled by default; enable with `export SECRETKEEPER_ENABLED=y` before
building.
Also needs the Secretkeeper TA to be present in Trusty; if the TA is
absent, the HAL service will (repeatedly) fail to connect.
Test: build, VtsSecretkeeperTargetTest
Bug: 306364873
Change-Id: I529013395d0e3afbff4a24b663088adce2a23805
diff --git a/trusty/secretkeeper/Android.bp b/trusty/secretkeeper/Android.bp
new file mode 100644
index 0000000..84db8c2
--- /dev/null
+++ b/trusty/secretkeeper/Android.bp
@@ -0,0 +1,42 @@
+//
+// 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_binary {
+ name: "android.hardware.security.secretkeeper.trusty",
+ relative_install_path: "hw",
+ vendor: true,
+ init_rc: ["android.hardware.security.secretkeeper.trusty.rc"],
+ vintf_fragments: ["android.hardware.security.secretkeeper.trusty.xml"],
+ srcs: [
+ "src/hal_main.rs",
+ ],
+ rustlibs: [
+ "libandroid_logger",
+ "libbinder_rs",
+ "libauthgraph_hal",
+ "libtrusty-rs",
+ "liblibc",
+ "liblog_rust",
+ "libsecretkeeper_hal",
+ ],
+ defaults: [
+ "secretkeeper_use_latest_hal_aidl_rust",
+ ],
+ prefer_rlib: true,
+}
diff --git a/trusty/secretkeeper/android.hardware.security.secretkeeper.trusty.rc b/trusty/secretkeeper/android.hardware.security.secretkeeper.trusty.rc
new file mode 100644
index 0000000..3be03ad
--- /dev/null
+++ b/trusty/secretkeeper/android.hardware.security.secretkeeper.trusty.rc
@@ -0,0 +1,4 @@
+service vendor.secretkeeper.trusty /vendor/bin/hw/android.hardware.security.secretkeeper.trusty
+ class hal
+ user nobody
+ group drmrpc
\ No newline at end of file
diff --git a/trusty/secretkeeper/android.hardware.security.secretkeeper.trusty.xml b/trusty/secretkeeper/android.hardware.security.secretkeeper.trusty.xml
new file mode 100644
index 0000000..2ac152b
--- /dev/null
+++ b/trusty/secretkeeper/android.hardware.security.secretkeeper.trusty.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.security.secretkeeper</name>
+ <version>1</version>
+ <fqname>ISecretkeeper/default</fqname>
+ </hal>
+</manifest>
diff --git a/trusty/secretkeeper/src/hal_main.rs b/trusty/secretkeeper/src/hal_main.rs
new file mode 100644
index 0000000..9439c36
--- /dev/null
+++ b/trusty/secretkeeper/src/hal_main.rs
@@ -0,0 +1,141 @@
+//
+// 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 module implements the HAL service for Secretkeeper in Trusty.
+use authgraph_hal::{channel::SerializedChannel};
+use secretkeeper_hal::SecretkeeperService;
+use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::ISecretkeeper::{
+ ISecretkeeper, BpSecretkeeper,
+};
+use log::{error, info};
+use std::{
+ ffi::CString,
+ panic,
+ sync::{Arc, Mutex},
+};
+use trusty::DEFAULT_DEVICE;
+
+const SK_TIPC_SERVICE_PORT: &str = "com.android.trusty.secretkeeper";
+const AG_TIPC_SERVICE_PORT: &str = "com.android.trusty.secretkeeper.authgraph";
+
+static SERVICE_INSTANCE: &str = "default";
+
+/// Local error type for failures in the HAL service.
+#[derive(Debug, Clone)]
+struct HalServiceError(String);
+
+#[derive(Debug)]
+struct TipcChannel {
+ channel: Arc<Mutex<trusty::TipcChannel>>,
+}
+
+impl TipcChannel {
+ fn new(channel: trusty::TipcChannel) -> Self {
+ Self { channel: Arc::new(Mutex::new(channel)) }
+ }
+}
+
+impl SerializedChannel for TipcChannel {
+ const MAX_SIZE: usize = 4000;
+ fn execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
+ // Hold lock across both request and response.
+ let mut channel = self.channel.lock().unwrap();
+ channel.send(req_data).map_err(|e| {
+ binder::Status::new_exception(
+ binder::ExceptionCode::TRANSACTION_FAILED,
+ Some(
+ &CString::new(format!(
+ "Failed to send the request via tipc channel because of {:?}",
+ e
+ ))
+ .unwrap(),
+ ),
+ )
+ })?;
+ // TODO: cope with fragmentation and reassembly
+ let mut rsp_data = Vec::new();
+ channel.recv(&mut rsp_data).map_err(|e| {
+ binder::Status::new_exception(
+ binder::ExceptionCode::TRANSACTION_FAILED,
+ Some(
+ &CString::new(format!(
+ "Failed to receive the response via tipc channel because of {:?}",
+ e
+ ))
+ .unwrap(),
+ ),
+ )
+ })?;
+ Ok(rsp_data)
+ }
+}
+
+fn main() {
+ if let Err(e) = inner_main() {
+ panic!("HAL service failed: {:?}", e);
+ }
+}
+
+fn inner_main() -> Result<(), HalServiceError> {
+ // Initialize Android logging.
+ android_logger::init_once(
+ android_logger::Config::default()
+ .with_tag("secretkeeper-hal-trusty")
+ .with_min_level(log::Level::Info)
+ .with_log_id(android_logger::LogId::System),
+ );
+ // Redirect panic messages to logcat.
+ panic::set_hook(Box::new(|panic_info| {
+ error!("{}", panic_info);
+ }));
+
+ info!("Trusty Secretkeeper HAL service is starting.");
+
+ info!("Starting thread pool now.");
+ binder::ProcessState::start_thread_pool();
+
+ // Create connections to the TA.
+ let ag_connection = trusty::TipcChannel::connect(DEFAULT_DEVICE, AG_TIPC_SERVICE_PORT)
+ .map_err(|e| {
+ HalServiceError(format!(
+ "Failed to connect to Trusty port {AG_TIPC_SERVICE_PORT} because of {:?}.",
+ e
+ ))
+ })?;
+ let ag_tipc_channel = TipcChannel::new(ag_connection);
+
+ let sk_connection = trusty::TipcChannel::connect(DEFAULT_DEVICE, SK_TIPC_SERVICE_PORT)
+ .map_err(|e| {
+ HalServiceError(format!(
+ "Failed to connect to Trusty port {SK_TIPC_SERVICE_PORT} because of {:?}.",
+ e
+ ))
+ })?;
+ let sk_tipc_channel = TipcChannel::new(sk_connection);
+
+ // Register the AIDL service
+ let service = SecretkeeperService::new_as_binder(sk_tipc_channel, ag_tipc_channel);
+ let service_name =
+ format!("{}/{}", <BpSecretkeeper as ISecretkeeper>::get_descriptor(), SERVICE_INSTANCE);
+ binder::add_service(&service_name, service.as_binder()).map_err(|e| {
+ HalServiceError(format!("Failed to register service {} because of {:?}.", service_name, e))
+ })?;
+
+ info!("Successfully registered Secretkeeper HAL service.");
+ info!("Joining thread pool now.");
+ binder::ProcessState::join_thread_pool();
+ info!("Secretkeeper HAL service is terminating."); // should not reach here
+ Ok(())
+}
diff --git a/trusty/trusty-base.mk b/trusty/trusty-base.mk
index 1986c73..d645c3e 100644
--- a/trusty/trusty-base.mk
+++ b/trusty/trusty-base.mk
@@ -35,8 +35,16 @@
LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.trusty
endif
+# TODO(b/306364873): move this to be flag-controlled?
+ifeq ($(SECRETKEEPER_ENABLED),)
+ LOCAL_SECRETKEEPER_PRODUCT_PACKAGE :=
+else
+ LOCAL_SECRETKEEPER_PRODUCT_PACKAGE := android.hardware.security.secretkeeper.trusty
+endif
+
PRODUCT_PACKAGES += \
$(LOCAL_KEYMINT_PRODUCT_PACKAGE) \
+ $(LOCAL_SECRETKEEPER_PRODUCT_PACKAGE) \
android.hardware.gatekeeper-service.trusty \
trusty_apploader \