1 //
2 // Copyright (C) 2022 The Android Open-Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 //! This module implements the HAL service for Keymint (Rust) in Trusty.
17 use kmr_hal::{
18     extract_rsp, keymint, rpc, secureclock, send_hal_info, sharedsecret, SerializedChannel,
19 };
20 use log::{error, info};
21 use std::{
22     ffi::CString,
23     ops::DerefMut,
24     panic,
25     sync::{Arc, Mutex},
26 };
27 use trusty::DEFAULT_DEVICE;
28 
29 const TRUSTY_KEYMINT_RUST_SERVICE_NAME: &str = "com.android.trusty.keymint";
30 
31 static SERVICE_INSTANCE: &str = "default";
32 
33 static KM_SERVICE_NAME: &str = "android.hardware.security.keymint.IKeyMintDevice";
34 static RPC_SERVICE_NAME: &str = "android.hardware.security.keymint.IRemotelyProvisionedComponent";
35 static SECURE_CLOCK_SERVICE_NAME: &str = "android.hardware.security.secureclock.ISecureClock";
36 static SHARED_SECRET_SERVICE_NAME: &str = "android.hardware.security.sharedsecret.ISharedSecret";
37 
38 /// Local error type for failures in the HAL service.
39 #[derive(Debug, Clone)]
40 struct HalServiceError(String);
41 
42 #[derive(Debug)]
43 struct TipcChannel(trusty::TipcChannel);
44 
45 impl SerializedChannel for TipcChannel {
46     const MAX_SIZE: usize = 4000;
execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>>47     fn execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>> {
48         self.0.send(serialized_req).map_err(|e| {
49             binder::Status::new_exception(
50                 binder::ExceptionCode::TRANSACTION_FAILED,
51                 Some(
52                     &CString::new(format!(
53                         "Failed to send the request via tipc channel because of {:?}",
54                         e
55                     ))
56                     .unwrap(),
57                 ),
58             )
59         })?;
60         let mut expect_more_msgs = true;
61         let mut full_rsp = Vec::new();
62         while expect_more_msgs {
63             let mut recv_buf = Vec::new();
64             self.0.recv(&mut recv_buf).map_err(|e| {
65                 binder::Status::new_exception(
66                     binder::ExceptionCode::TRANSACTION_FAILED,
67                     Some(
68                         &CString::new(format!(
69                             "Failed to receive the response via tipc channel because of {:?}",
70                             e
71                         ))
72                         .unwrap(),
73                     ),
74                 )
75             })?;
76             let current_rsp_content;
77             (expect_more_msgs, current_rsp_content) = extract_rsp(&recv_buf)?;
78             full_rsp.extend_from_slice(current_rsp_content);
79         }
80         Ok(full_rsp)
81     }
82 }
83 
main()84 fn main() {
85     if let Err(e) = inner_main() {
86         panic!("HAL service failed: {:?}", e);
87     }
88 }
89 
inner_main() -> Result<(), HalServiceError>90 fn inner_main() -> Result<(), HalServiceError> {
91     // Initialize Android logging.
92     android_logger::init_once(
93         android_logger::Config::default()
94             .with_tag("keymint-hal-trusty")
95             .with_min_level(log::Level::Info)
96             .with_log_id(android_logger::LogId::System),
97     );
98     // Redirect panic messages to logcat.
99     panic::set_hook(Box::new(|panic_info| {
100         error!("{}", panic_info);
101     }));
102 
103     info!("Trusty KM HAL service is starting.");
104 
105     info!("Starting thread pool now.");
106     binder::ProcessState::start_thread_pool();
107 
108     // Create connection to the TA
109     let connection = trusty::TipcChannel::connect(DEFAULT_DEVICE, TRUSTY_KEYMINT_RUST_SERVICE_NAME)
110         .map_err(|e| {
111             HalServiceError(format!("Failed to connect to Trusty Keymint TA because of {:?}.", e))
112         })?;
113     let tipc_channel = Arc::new(Mutex::new(TipcChannel(connection)));
114 
115     // Register the Keymint service
116     let km_service = keymint::Device::new_as_binder(tipc_channel.clone());
117     let km_service_name = format!("{}/{}", KM_SERVICE_NAME, SERVICE_INSTANCE);
118     binder::add_service(&km_service_name, km_service.as_binder()).map_err(|e| {
119         HalServiceError(format!(
120             "Failed to register service {} because of {:?}.",
121             km_service_name, e
122         ))
123     })?;
124 
125     // Register the Remotely Provisioned Component service
126     let rpc_service = rpc::Device::new_as_binder(tipc_channel.clone());
127     let rpc_service_name = format!("{}/{}", RPC_SERVICE_NAME, SERVICE_INSTANCE);
128     binder::add_service(&rpc_service_name, rpc_service.as_binder()).map_err(|e| {
129         HalServiceError(format!(
130             "Failed to register service {} because of {:?}.",
131             rpc_service_name, e
132         ))
133     })?;
134 
135     // Register the Secure Clock service
136     let sclock_service = secureclock::Device::new_as_binder(tipc_channel.clone());
137     let sclock_service_name = format!("{}/{}", SECURE_CLOCK_SERVICE_NAME, SERVICE_INSTANCE);
138     binder::add_service(&sclock_service_name, sclock_service.as_binder()).map_err(|e| {
139         HalServiceError(format!(
140             "Failed to register service {} because of {:?}.",
141             sclock_service_name, e
142         ))
143     })?;
144 
145     // Register the Shared Secret service
146     let ssecret_service = sharedsecret::Device::new_as_binder(tipc_channel.clone());
147     let ssecret_service_name = format!("{}/{}", SHARED_SECRET_SERVICE_NAME, SERVICE_INSTANCE);
148     binder::add_service(&ssecret_service_name, ssecret_service.as_binder()).map_err(|e| {
149         HalServiceError(format!(
150             "Failed to register service {} because of {:?}.",
151             ssecret_service_name, e
152         ))
153     })?;
154 
155     // Send the HAL service information to the TA
156     send_hal_info(tipc_channel.lock().unwrap().deref_mut())
157         .map_err(|e| HalServiceError(format!("Failed to populate HAL info: {:?}", e)))?;
158 
159     info!("Successfully registered KeyMint HAL services.");
160     info!("Joining thread pool now.");
161     binder::ProcessState::join_thread_pool();
162     info!("KeyMint HAL service is terminating."); // should not reach here
163     Ok(())
164 }
165