// // 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::{ extract_rsp, 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 { const MAX_SIZE: usize = 4000; fn execute(&mut self, serialized_req: &[u8]) -> binder::Result> { 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 expect_more_msgs = true; let mut full_rsp = Vec::new(); while expect_more_msgs { let mut recv_buf = Vec::new(); 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(), ), ) })?; let current_rsp_content; (expect_more_msgs, current_rsp_content) = extract_rsp(&recv_buf)?; full_rsp.extend_from_slice(current_rsp_content); } Ok(full_rsp) } } 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(()) }