1 /*
2 * Copyright (C) 2025 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
17 //! AuthMgr BE server
18 use crate::authorization_service::{
19 AuthMgrAuthorizationRPCService, AuthMgrGlobalState, RawConnectionInformation,
20 };
21 use authmgr_common::{
22 signed_connection_request::TEMP_AUTHMGR_FE_TRANSPORT_ID, CMD_RAW, CMD_RPC, TOKEN_LENGTH,
23 };
24 use log::{debug, error};
25 use rpcbinder::{RpcServer, RpcServerConnection};
26 use std::ffi::CStr;
27 use std::sync::Mutex;
28 use std::sync::{Arc, Weak};
29 use tipc::raw::{EventLoop, HandleSetWrapper};
30 use tipc::{
31 ConnectResult, Deserialize, Handle, MessageResult, PortCfg, Serialize, Serializer, TipcError,
32 UnbufferedService, Uuid,
33 };
34 use trusty_std::alloc::TryAllocFrom;
35
36 /// Port for the AuthMgr main service
37 pub(crate) const AUTHMGR_SERVICE_PORT: &CStr = c"com.android.trusty.rust.authmgr.V1";
38
39 /// Maximum message size.
40 /// TODO: determine the size
41 const MAX_MSG_SIZE: usize = 4000;
42
43 /// Represents the main AuthMgr service encapsulating the global state which is also shared with the
44 /// `AuthMgrAuthorizationRPCService`.
45 pub struct AuthMgrService {
46 global_state: Arc<Mutex<AuthMgrGlobalState>>,
47 rpc_service: Arc<RpcServer>,
48 handle_set: Weak<HandleSetWrapper<AuthMgrServices>>,
49 }
50
51 impl AuthMgrService {
new( global_state: Arc<Mutex<AuthMgrGlobalState>>, rpc_service: Arc<RpcServer>, handle_set: Weak<HandleSetWrapper<AuthMgrServices>>, ) -> Self52 fn new(
53 global_state: Arc<Mutex<AuthMgrGlobalState>>,
54 rpc_service: Arc<RpcServer>,
55 handle_set: Weak<HandleSetWrapper<AuthMgrServices>>,
56 ) -> Self {
57 AuthMgrService { global_state, rpc_service, handle_set }
58 }
59 }
60
61 // SAFETY: Out of the three fields of `AuthMgrService`:
62 // `AuthMgrGlobalState` and `HandleSetWrapper` are heap allocated in the main_loop() of this TA and
63 // therefore, are not bound to any particular thread.
64 // `RpcServer` implements (unsafe) `Send`.
65 unsafe impl Send for AuthMgrService {}
66
67 pub struct AuthMgrConnection {
68 uuid: Uuid,
69 // In on_connect, we do not know whether this is a connection request for the RPC binder service
70 // or a raw connection request. Until the first message arrives, we mark the connection as
71 // pending_to_be_routed = true
72 pending_to_be_routed: Arc<Mutex<bool>>,
73 }
74
75 pub struct AuthMgrMessage(pub Vec<u8>);
76
77 impl Deserialize for AuthMgrMessage {
78 type Error = TipcError;
79 const MAX_SERIALIZED_SIZE: usize = MAX_MSG_SIZE;
80
deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, TipcError>81 fn deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, TipcError> {
82 Ok(AuthMgrMessage(Vec::try_alloc_from(bytes)?))
83 }
84 }
85
86 impl<'s> Serialize<'s> for AuthMgrMessage {
serialize<'a: 's, S: Serializer<'s>>( &'a self, serializer: &mut S, ) -> Result<S::Ok, S::Error>87 fn serialize<'a: 's, S: Serializer<'s>>(
88 &'a self,
89 serializer: &mut S,
90 ) -> Result<S::Ok, S::Error> {
91 serializer.serialize_bytes(self.0.as_slice())
92 }
93 }
94
95 impl UnbufferedService for AuthMgrService {
96 type Connection = AuthMgrConnection;
97
on_connect( &self, _port: &PortCfg, handle: &Handle, peer: &Uuid, ) -> Result<ConnectResult<Self::Connection>, TipcError>98 fn on_connect(
99 &self,
100 _port: &PortCfg,
101 handle: &Handle,
102 peer: &Uuid,
103 ) -> Result<ConnectResult<Self::Connection>, TipcError> {
104 debug!("Accepted AthMgr BE connection from uuid: {:?}, handle: {:?}", peer, handle);
105 Ok(ConnectResult::Accept(AuthMgrConnection {
106 uuid: peer.clone(),
107 pending_to_be_routed: Arc::new(Mutex::new(true)),
108 }))
109 }
110
on_message( &self, connection: &Self::Connection, handle: &Handle, _buffer: &mut [u8], ) -> Result<MessageResult, TipcError>111 fn on_message(
112 &self,
113 connection: &Self::Connection,
114 handle: &Handle,
115 _buffer: &mut [u8],
116 ) -> Result<MessageResult, TipcError> {
117 let mut connection_pending_to_be_routed = connection.pending_to_be_routed.lock().unwrap();
118 debug!(
119 "AuthMgr BE received a message from uuid: {:?} for a pending_to_be_routed: {:?}, handle: {:?}.",
120 connection.uuid,
121 connection_pending_to_be_routed,
122 handle
123 );
124 if *connection_pending_to_be_routed {
125 let mut temp_buffer = [0u8; MAX_MSG_SIZE];
126 let msg: AuthMgrMessage = handle.recv(&mut temp_buffer)?;
127 if msg.0.is_empty() {
128 error!("Expected a command byte, got an empty payload.");
129 return Err(TipcError::InvalidData);
130 }
131 match msg.0[0] {
132 CMD_RAW => {
133 debug!("It's a request for a new raw connection.");
134 if msg.0.len() != TOKEN_LENGTH + 1 {
135 error!(
136 "Expected a token of length: {:?}, got a payload of size: {:?}.",
137 TOKEN_LENGTH,
138 msg.0.len()
139 );
140 return Err(TipcError::InvalidData);
141 }
142 let token: [u8; TOKEN_LENGTH] =
143 (msg.0[1..TOKEN_LENGTH + 1]).try_into().map_err(|e| {
144 error!("Failed to read the token: {:?}", e);
145 TipcError::InvalidData
146 })?;
147 let client_connection = RawConnectionInformation::new(
148 handle.try_clone()?,
149 // TODO: b/392905377. This is temporary, until the VM-ID is available.
150 TEMP_AUTHMGR_FE_TRANSPORT_ID,
151 );
152 let mut global_state = self.global_state.lock().unwrap();
153 global_state
154 .authmgr_core
155 .init_connection_for_client(Box::new(client_connection), token)
156 .map_err(|e| {
157 error!("Failed to call init_connection_for_client: {:?}", e);
158 TipcError::UnknownError
159 })?;
160 *connection_pending_to_be_routed = false;
161 // Close the handle registered in the handle set
162 Ok(MessageResult::CloseConnection)
163 }
164 CMD_RPC => {
165 debug!("It's a request for a RPC binder connection.");
166 let authmgr_service_port_cfg = PortCfg::new_raw(AUTHMGR_SERVICE_PORT.into())
167 .allow_ta_connect()
168 .allow_ns_connect();
169 let rpc_connection = match self.rpc_service.on_connect(
170 &authmgr_service_port_cfg,
171 handle,
172 &connection.uuid,
173 )? {
174 ConnectResult::Accept(conn) => conn,
175 ConnectResult::CloseConnection => {
176 return Ok(MessageResult::CloseConnection)
177 }
178 };
179 debug!("AuthMgr RPC service.on_connect returned. Adding to the handle set.");
180 self.handle_set.upgrade().ok_or(TipcError::InvalidData)?.add_connection(
181 AuthMgrServicesConnection::RpcService(rpc_connection),
182 handle.try_clone()?,
183 Arc::new(AuthMgrServices::RpcService(Arc::clone(&self.rpc_service))),
184 )?;
185 *connection_pending_to_be_routed = false;
186 // Close the handle registered in the handle set
187 Ok(MessageResult::CloseConnection)
188 }
189 _ => {
190 error!("Unknown command.");
191 Err(TipcError::InvalidData)
192 }
193 }
194 } else {
195 error!(
196 "No messages are expected on the same connection
197 after the initial command byte is sent."
198 );
199 Err(TipcError::InvalidData)
200 }
201 }
202 // TODO: implement on_disconnect
203 }
204
205 enum AuthMgrServices {
206 InitService(Arc<AuthMgrService>),
207 RpcService(Arc<RpcServer>),
208 }
209
210 enum AuthMgrServicesConnection {
211 InitService(AuthMgrConnection),
212 RpcService(RpcServerConnection),
213 }
214
215 impl From<AuthMgrConnection> for AuthMgrServicesConnection {
from(v: AuthMgrConnection) -> AuthMgrServicesConnection216 fn from(v: AuthMgrConnection) -> AuthMgrServicesConnection {
217 AuthMgrServicesConnection::InitService(v)
218 }
219 }
220
221 impl From<RpcServerConnection> for AuthMgrServicesConnection {
from(v: RpcServerConnection) -> AuthMgrServicesConnection222 fn from(v: RpcServerConnection) -> AuthMgrServicesConnection {
223 AuthMgrServicesConnection::RpcService(v)
224 }
225 }
226
227 impl<'a> TryFrom<&'a AuthMgrServicesConnection> for &'a AuthMgrConnection {
228 type Error = TipcError;
try_from(v: &'a AuthMgrServicesConnection) -> Result<&'a AuthMgrConnection, Self::Error>229 fn try_from(v: &'a AuthMgrServicesConnection) -> Result<&'a AuthMgrConnection, Self::Error> {
230 match v {
231 AuthMgrServicesConnection::InitService(amgr_conn) => Ok(amgr_conn),
232 _ => Err(TipcError::InvalidData),
233 }
234 }
235 }
236
237 impl<'a> TryFrom<&'a AuthMgrServicesConnection> for &'a RpcServerConnection {
238 type Error = TipcError;
try_from(v: &'a AuthMgrServicesConnection) -> Result<&'a RpcServerConnection, Self::Error>239 fn try_from(v: &'a AuthMgrServicesConnection) -> Result<&'a RpcServerConnection, Self::Error> {
240 match v {
241 AuthMgrServicesConnection::RpcService(rpc_conn) => Ok(rpc_conn),
242 _ => Err(TipcError::InvalidData),
243 }
244 }
245 }
246
247 impl UnbufferedService for AuthMgrServices {
248 type Connection = AuthMgrServicesConnection;
249
on_connect( &self, port: &PortCfg, handle: &Handle, peer: &Uuid, ) -> Result<ConnectResult<Self::Connection>, TipcError>250 fn on_connect(
251 &self,
252 port: &PortCfg,
253 handle: &Handle,
254 peer: &Uuid,
255 ) -> Result<ConnectResult<Self::Connection>, TipcError> {
256 match self {
257 AuthMgrServices::InitService(authmgr_service) => {
258 match authmgr_service.on_connect(port, handle, peer) {
259 Ok(conn_result) => match conn_result {
260 ConnectResult::Accept(conn) => Ok(ConnectResult::Accept(conn.into())),
261 ConnectResult::CloseConnection => Ok(ConnectResult::CloseConnection),
262 },
263 Err(e) => Err(e),
264 }
265 }
266
267 AuthMgrServices::RpcService(authmgr_rpc_service) => {
268 match authmgr_rpc_service.on_connect(port, handle, peer) {
269 Ok(conn_result) => match conn_result {
270 ConnectResult::Accept(conn) => Ok(ConnectResult::Accept(conn.into())),
271 ConnectResult::CloseConnection => Ok(ConnectResult::CloseConnection),
272 },
273 Err(e) => Err(e),
274 }
275 }
276 }
277 }
278
on_message( &self, connection: &Self::Connection, handle: &Handle, buffer: &mut [u8], ) -> Result<MessageResult, TipcError>279 fn on_message(
280 &self,
281 connection: &Self::Connection,
282 handle: &Handle,
283 buffer: &mut [u8],
284 ) -> Result<MessageResult, TipcError> {
285 match self {
286 AuthMgrServices::InitService(authmgr_service) => authmgr_service.on_message(
287 connection.try_into().map_err(|_| TipcError::InvalidData)?,
288 handle,
289 buffer,
290 ),
291 AuthMgrServices::RpcService(authmgr_rpc_service) => authmgr_rpc_service.on_message(
292 connection.try_into().map_err(|_| TipcError::InvalidData)?,
293 handle,
294 buffer,
295 ),
296 }
297 }
298 }
299
main_loop() -> Result<(), TipcError>300 pub fn main_loop() -> Result<(), TipcError> {
301 let handle_set_wrapper = Arc::new(HandleSetWrapper::<AuthMgrServices>::new()?);
302 let global_state = AuthMgrGlobalState::new().map_err(|e| {
303 error!("Could not create AuthMgr global state due to: {:?}", e);
304 TipcError::UnknownError
305 })?;
306 let global_state = Arc::new(Mutex::new(global_state));
307 let gs_clone = Arc::clone(&global_state);
308 let authmgr_service_port_cfg =
309 PortCfg::new_raw(AUTHMGR_SERVICE_PORT.into()).allow_ta_connect().allow_ns_connect();
310
311 let cb_per_session = move |_uuid| {
312 AuthMgrAuthorizationRPCService::new_authorization_session(Arc::clone(&global_state))
313 };
314 let authmgr_authorization_rpc_server = RpcServer::new_per_session(cb_per_session);
315 let authmgr_service = AuthMgrService::new(
316 gs_clone,
317 Arc::new(authmgr_authorization_rpc_server),
318 Arc::downgrade(&handle_set_wrapper),
319 );
320
321 let _port_wrapper = handle_set_wrapper.add_port(
322 &authmgr_service_port_cfg,
323 Arc::new(AuthMgrServices::InitService(Arc::new(authmgr_service))),
324 )?;
325 let event_loop = EventLoop::new(handle_set_wrapper.clone());
326 event_loop.run()
327 }
328