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 Secretkeeper in Trusty.
17 use authgraph_hal::channel::SerializedChannel;
18 use authgraph_wire::fragmentation::{Fragmenter, Reassembler};
19 use secretkeeper_hal::SecretkeeperService;
20 use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::ISecretkeeper::{
21 ISecretkeeper, BpSecretkeeper,
22 };
23 use log::{error, info};
24 use std::{
25 ffi::CString,
26 fmt::Debug,
27 panic,
28 sync::{Arc, Mutex},
29 };
30 use trusty::DEFAULT_DEVICE;
31
32 const SK_TIPC_SERVICE_PORT: &str = "com.android.trusty.secretkeeper";
33 const AG_TIPC_SERVICE_PORT: &str = "com.android.trusty.secretkeeper.authgraph";
34 const TIPC_MAX_SIZE: usize = 4000;
35
36 static SERVICE_INSTANCE: &str = "default";
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 {
44 channel: Arc<Mutex<trusty::TipcChannel>>,
45 }
46
47 impl TipcChannel {
new(channel: trusty::TipcChannel) -> Self48 fn new(channel: trusty::TipcChannel) -> Self {
49 Self { channel: Arc::new(Mutex::new(channel)) }
50 }
51 }
52
binderr<E: Debug>(msg: &str, e: E) -> binder::Status53 fn binderr<E: Debug>(msg: &str, e: E) -> binder::Status {
54 binder::Status::new_exception(
55 binder::ExceptionCode::TRANSACTION_FAILED,
56 Some(&CString::new(format!("Failed to {msg} via tipc channel: {e:?}",)).unwrap()),
57 )
58 }
59
60 impl SerializedChannel for TipcChannel {
61 // No maximum size for messages passed to `execute()` because it performs fragmentation
62 // and reassembly internally.
63 const MAX_SIZE: usize = usize::MAX;
64
execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>>65 fn execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
66 // Hold lock across both request and response.
67 let mut channel = self.channel.lock().unwrap();
68 let mut pending_rsp = Reassembler::default();
69
70 // Break request message into fragments to send.
71 for req_frag in Fragmenter::new(req_data, TIPC_MAX_SIZE) {
72 channel.send(&req_frag).map_err(|e| binderr("send request", e))?;
73
74 // Every request gets a response.
75 let mut rsp_frag = Vec::new();
76 channel.recv(&mut rsp_frag).map_err(|e| binderr("receive response", e))?;
77
78 if let Some(full_rsp) = pending_rsp.accumulate(&rsp_frag) {
79 return Ok(full_rsp.to_vec());
80 }
81 }
82 // There may be additional response fragments to receive.
83 loop {
84 let mut rsp_frag = Vec::new();
85 channel.recv(&mut rsp_frag).map_err(|e| binderr("receive response", e))?;
86 if let Some(full_rsp) = pending_rsp.accumulate(&rsp_frag) {
87 return Ok(full_rsp.to_vec());
88 }
89 }
90 }
91 }
92
main()93 fn main() {
94 if let Err(HalServiceError(e)) = inner_main() {
95 panic!("HAL service failed: {:?}", e);
96 }
97 }
98
inner_main() -> Result<(), HalServiceError>99 fn inner_main() -> Result<(), HalServiceError> {
100 // Initialize Android logging.
101 android_logger::init_once(
102 android_logger::Config::default()
103 .with_tag("secretkeeper-hal-trusty")
104 .with_max_level(log::LevelFilter::Info)
105 .with_log_buffer(android_logger::LogId::System),
106 );
107 // Redirect panic messages to logcat.
108 panic::set_hook(Box::new(|panic_info| {
109 error!("{}", panic_info);
110 }));
111
112 info!("Trusty Secretkeeper HAL service is starting.");
113
114 info!("Starting thread pool now.");
115 binder::ProcessState::start_thread_pool();
116
117 // Create connections to the TA.
118 let ag_connection = trusty::TipcChannel::connect(DEFAULT_DEVICE, AG_TIPC_SERVICE_PORT)
119 .map_err(|e| {
120 HalServiceError(format!(
121 "Failed to connect to Trusty port {AG_TIPC_SERVICE_PORT} because of {:?}.",
122 e
123 ))
124 })?;
125 let ag_tipc_channel = TipcChannel::new(ag_connection);
126
127 let sk_connection = trusty::TipcChannel::connect(DEFAULT_DEVICE, SK_TIPC_SERVICE_PORT)
128 .map_err(|e| {
129 HalServiceError(format!(
130 "Failed to connect to Trusty port {SK_TIPC_SERVICE_PORT} because of {:?}.",
131 e
132 ))
133 })?;
134 let sk_tipc_channel = TipcChannel::new(sk_connection);
135
136 // Register the AIDL service
137 let service = SecretkeeperService::new_as_binder(sk_tipc_channel, ag_tipc_channel);
138 let service_name =
139 format!("{}/{}", <BpSecretkeeper as ISecretkeeper>::get_descriptor(), SERVICE_INSTANCE);
140 binder::add_service(&service_name, service.as_binder()).map_err(|e| {
141 HalServiceError(format!("Failed to register service {} because of {:?}.", service_name, e))
142 })?;
143
144 info!("Successfully registered Secretkeeper HAL service.");
145 info!("Joining thread pool now.");
146 binder::ProcessState::join_thread_pool();
147 info!("Secretkeeper HAL service is terminating."); // should not reach here
148 Ok(())
149 }
150