• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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