blob: cfa859f6315bf6c3f5bee880f321f5b8c2b601b3 [file] [log] [blame]
//
// 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<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 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(())
}