Merge "KeyMint HAL in Rust for Trusty"
diff --git a/trusty/keymint/Android.bp b/trusty/keymint/Android.bp
new file mode 100644
index 0000000..54aadaa
--- /dev/null
+++ b/trusty/keymint/Android.bp
@@ -0,0 +1,37 @@
+//
+// 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.
+
+rust_binary {
+    name: "android.hardware.security.keymint-service.rust.trusty",
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["android.hardware.security.keymint-service.rust.trusty.rc"],
+    vintf_fragments: ["android.hardware.security.keymint-service.rust.trusty.xml"],
+    srcs: [
+        "src/keymint_hal_main.rs"
+    ],
+    rustlibs: [
+        "libandroid_logger",
+        "libbinder_rs",
+        "libkmr_wire",
+        "libkmr_hal",
+        "libtrusty-rs",
+        "liblibc",
+        "liblog_rust",
+    ],
+    required: [
+        "android.hardware.hardware_keystore.xml",
+    ],
+}
diff --git a/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml b/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml
new file mode 100644
index 0000000..cd656b2
--- /dev/null
+++ b/trusty/keymint/android.hardware.hardware_keystore.rust.trusty-keymint.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 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.
+-->
+<permissions>
+  <feature name="android.hardware.hardware_keystore" version="300" />
+</permissions>
diff --git a/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.rc b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.rc
new file mode 100644
index 0000000..e3d94c6
--- /dev/null
+++ b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.rc
@@ -0,0 +1,7 @@
+service vendor.keymint.rust-trusty /vendor/bin/hw/android.hardware.security.keymint-service.rust.trusty
+    class early_hal
+    user nobody
+    group drmrpc
+    # The keymint service is not allowed to restart.
+    # If it crashes, a device restart is required.
+    oneshot
\ No newline at end of file
diff --git a/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.xml b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.xml
new file mode 100644
index 0000000..3dc9c88
--- /dev/null
+++ b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.xml
@@ -0,0 +1,20 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.security.keymint</name>
+        <version>3</version>
+        <fqname>IKeyMintDevice/default</fqname>
+    </hal>
+    <hal format="aidl">
+        <name>android.hardware.security.secureclock</name>
+        <fqname>ISecureClock/default</fqname>
+    </hal>
+    <hal format="aidl">
+        <name>android.hardware.security.sharedsecret</name>
+        <fqname>ISharedSecret/default</fqname>
+    </hal>
+    <hal format="aidl">
+        <name>android.hardware.security.keymint</name>
+        <version>3</version>
+        <fqname>IRemotelyProvisionedComponent/default</fqname>
+    </hal>
+</manifest>
diff --git a/trusty/keymint/src/keymint_hal_main.rs b/trusty/keymint/src/keymint_hal_main.rs
new file mode 100644
index 0000000..d2d5f27
--- /dev/null
+++ b/trusty/keymint/src/keymint_hal_main.rs
@@ -0,0 +1,155 @@
+//
+// 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 Keymint (Rust) in Trusty.
+use kmr_hal::{keymint, rpc, secureclock, send_hal_info, sharedsecret, SerializedChannel};
+use log::{error, info};
+use std::{
+    ffi::CString,
+    ops::DerefMut,
+    panic,
+    sync::{Arc, Mutex},
+};
+use trusty::DEFAULT_DEVICE;
+
+const TRUSTY_KEYMINT_RUST_SERVICE_NAME: &str = "com.android.trusty.keymint";
+
+static SERVICE_INSTANCE: &str = "default";
+
+static KM_SERVICE_NAME: &str = "android.hardware.security.keymint.IKeyMintDevice";
+static RPC_SERVICE_NAME: &str = "android.hardware.security.keymint.IRemotelyProvisionedComponent";
+static SECURE_CLOCK_SERVICE_NAME: &str = "android.hardware.security.secureclock.ISecureClock";
+static SHARED_SECRET_SERVICE_NAME: &str = "android.hardware.security.sharedsecret.ISharedSecret";
+
+/// Local error type for failures in the HAL service.
+#[derive(Debug, Clone)]
+struct HalServiceError(String);
+
+#[derive(Debug)]
+struct TipcChannel(trusty::TipcChannel);
+
+impl SerializedChannel for TipcChannel {
+    fn execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>> {
+        self.0.send(serialized_req).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(),
+                ),
+            )
+        })?;
+        let mut recv_buf = Vec::new();
+        // TODO(b/253501976): cope with fragmentation of responses
+        self.0.recv(&mut recv_buf).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(recv_buf)
+    }
+}
+
+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("keymint-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 KM HAL service is starting.");
+
+    info!("Starting thread pool now.");
+    binder::ProcessState::start_thread_pool();
+
+    // Create connection to the TA
+    let connection = trusty::TipcChannel::connect(DEFAULT_DEVICE, TRUSTY_KEYMINT_RUST_SERVICE_NAME)
+        .map_err(|e| {
+            HalServiceError(format!("Failed to connect to Trusty Keymint TA because of {:?}.", e))
+        })?;
+    let tipc_channel = Arc::new(Mutex::new(TipcChannel(connection)));
+
+    // Register the Keymint service
+    let km_service = keymint::Device::new_as_binder(tipc_channel.clone());
+    let km_service_name = format!("{}/{}", KM_SERVICE_NAME, SERVICE_INSTANCE);
+    binder::add_service(&km_service_name, km_service.as_binder()).map_err(|e| {
+        HalServiceError(format!(
+            "Failed to register service {} because of {:?}.",
+            km_service_name, e
+        ))
+    })?;
+
+    // Register the Remotely Provisioned Component service
+    let rpc_service = rpc::Device::new_as_binder(tipc_channel.clone());
+    let rpc_service_name = format!("{}/{}", RPC_SERVICE_NAME, SERVICE_INSTANCE);
+    binder::add_service(&rpc_service_name, rpc_service.as_binder()).map_err(|e| {
+        HalServiceError(format!(
+            "Failed to register service {} because of {:?}.",
+            rpc_service_name, e
+        ))
+    })?;
+
+    // Register the Secure Clock service
+    let sclock_service = secureclock::Device::new_as_binder(tipc_channel.clone());
+    let sclock_service_name = format!("{}/{}", SECURE_CLOCK_SERVICE_NAME, SERVICE_INSTANCE);
+    binder::add_service(&sclock_service_name, sclock_service.as_binder()).map_err(|e| {
+        HalServiceError(format!(
+            "Failed to register service {} because of {:?}.",
+            sclock_service_name, e
+        ))
+    })?;
+
+    // Register the Shared Secret service
+    let ssecret_service = sharedsecret::Device::new_as_binder(tipc_channel.clone());
+    let ssecret_service_name = format!("{}/{}", SHARED_SECRET_SERVICE_NAME, SERVICE_INSTANCE);
+    binder::add_service(&ssecret_service_name, ssecret_service.as_binder()).map_err(|e| {
+        HalServiceError(format!(
+            "Failed to register service {} because of {:?}.",
+            ssecret_service_name, e
+        ))
+    })?;
+
+    // Send the HAL service information to the TA
+    send_hal_info(tipc_channel.lock().unwrap().deref_mut())
+        .map_err(|e| HalServiceError(format!("Failed to populate HAL info: {:?}", e)))?;
+
+    info!("Successfully registered KeyMint HAL services.");
+    info!("Joining thread pool now.");
+    binder::ProcessState::join_thread_pool();
+    info!("KeyMint HAL service is terminating."); // should not reach here
+    Ok(())
+}