• 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 //! The implementation of the `IAuthMgrAuthorization` AIDL interface.
18 //#![allow(dead_code)]
19 use android_hardware_security_see_authmgr::aidl::android::hardware::security::see::authmgr::{
20     DiceLeafArtifacts::DiceLeafArtifacts,
21     DicePolicy::DicePolicy,
22     ExplicitKeyDiceCertChain::ExplicitKeyDiceCertChain,
23     IAuthMgrAuthorization::{BnAuthMgrAuthorization, IAuthMgrAuthorization},
24     SignedConnectionRequest::SignedConnectionRequest,
25 };
26 use android_hardware_security_see_authmgr::binder;
27 use authgraph_core::key::{CertChain, InstanceIdentifier};
28 use authmgr_be::{
29     am_err,
30     authorization::AuthMgrBE,
31     data_structures::{AuthenticatedConnectionState, MemoryLimits},
32     error::{Error, ErrorCode},
33     traits::{Device, RawConnection, RpcConnection},
34 };
35 use authmgr_be_impl::mock_storage::MockPersistentStorage;
36 use authmgr_common::signed_connection_request::{
37     TransportID, TEMP_AUTHMGR_BE_TRANSPORT_ID, TEMP_AUTHMGR_FE_TRANSPORT_ID,
38 };
39 use authmgr_handover_aidl::aidl::android::trusty::handover::ITrustedServicesHandover::ITrustedServicesHandover;
40 use binder::ParcelFileDescriptor;
41 use binder::SpIBinder;
42 use binder::Strong;
43 use log::error;
44 use rpcbinder::{FileDescriptorTransportMode, RpcSession};
45 use std::ffi::CStr;
46 use std::os::fd::FromRawFd;
47 use std::os::fd::OwnedFd;
48 use std::sync::Arc;
49 use std::sync::Mutex;
50 use tipc::Handle;
51 
52 // TODO: b/400118241. Construct the handover service's port from the given service name.
53 // For now, hardcode the port for the handover service of the HelloWorld TA.
54 const HANDOVER_SERVICE_PORT: &CStr = c"com.android.trusty.rust.handover.hello.service.V1";
55 
56 /// Represents a per-session RPC binder object which implements the `IAuthMgrAuthorization`
57 /// interface. This encapsulates the connection information as well as the global state of the
58 /// AuthMgr Authorization service.
59 /// `global_state` is shared across the all the binder RPC root objects of
60 ///  `AuthMgrAuthorizationRPCService` and the AuthMgr main service of this TA.
61 /// `connection_information` is shared across multiple binder RPC sessions of the samme connection.
62 /// Therefore, we are not locking both mutexes together. In the usage of both mutexes (which is
63 /// in the below implementation of `AuthMgrAuthorizationRPCService`, the locks on them should be
64 /// grabbed in the same order as they are ordered in the struct below.
65 pub struct AuthMgrAuthorizationRPCService {
66     global_state: Arc<Mutex<AuthMgrGlobalState>>,
67     connection_information: Arc<Mutex<RpcConnectionInformation>>,
68 }
69 
70 impl binder::Interface for AuthMgrAuthorizationRPCService {}
71 
72 impl AuthMgrAuthorizationRPCService {
73     // TODO: b/392905377. Expect transport id (i.e. VM-ID) to be passed into this method
new_authorization_session( global_state: Arc<Mutex<AuthMgrGlobalState>>, ) -> Option<SpIBinder>74     pub fn new_authorization_session(
75         global_state: Arc<Mutex<AuthMgrGlobalState>>,
76     ) -> Option<SpIBinder> {
77         let connection_information =
78             RpcConnectionInformation::new(TEMP_AUTHMGR_FE_TRANSPORT_ID, None);
79         let authmgr_authorization = AuthMgrAuthorizationRPCService {
80             global_state,
81             connection_information: Arc::new(Mutex::new(connection_information)),
82         };
83         Some(
84             BnAuthMgrAuthorization::new_binder(
85                 authmgr_authorization,
86                 binder::BinderFeatures::default(),
87             )
88             .as_binder(),
89         )
90     }
91 }
92 
93 impl Drop for AuthMgrAuthorizationRPCService {
drop(&mut self)94     fn drop(&mut self) {
95         let mut global_state = self.global_state.lock().unwrap();
96         let mut connection_info = self.connection_information.lock().unwrap();
97         let _ = global_state
98             .authmgr_core
99             .clear_cache_upon_main_connection_close(&mut *connection_info)
100             .map_err(|e| {
101                 error!("Failed to clear cache: {:?}", e);
102                 errcode_to_binder_err(e.0)
103             });
104     }
105 }
106 
107 impl IAuthMgrAuthorization for AuthMgrAuthorizationRPCService {
initAuthentication( &self, dice_cert_chain: &ExplicitKeyDiceCertChain, instance_id: Option<&[u8]>, ) -> binder::Result<[u8; 32]>108     fn initAuthentication(
109         &self,
110         dice_cert_chain: &ExplicitKeyDiceCertChain,
111         instance_id: Option<&[u8]>,
112     ) -> binder::Result<[u8; 32]> {
113         let mut global_state = self.global_state.lock().unwrap();
114         let connection_info = self.connection_information.lock().unwrap();
115         global_state
116             .authmgr_core
117             .init_authentication(&*connection_info, &dice_cert_chain.diceCertChain, instance_id)
118             .map_err(|e| {
119                 error!("Failed step 1 of phase 1: {:?}", e);
120                 errcode_to_binder_err(e.0)
121             })
122     }
123 
completeAuthentication( &self, signed_response: &SignedConnectionRequest, dice_policy: &DicePolicy, ) -> binder::Result<()>124     fn completeAuthentication(
125         &self,
126         signed_response: &SignedConnectionRequest,
127         dice_policy: &DicePolicy,
128     ) -> binder::Result<()> {
129         let mut global_state = self.global_state.lock().unwrap();
130         let mut connection_info = self.connection_information.lock().unwrap();
131         global_state
132             .authmgr_core
133             .complete_authentication(
134                 &mut *connection_info,
135                 &signed_response.signedConnectionRequest,
136                 &dice_policy.dicePolicy,
137             )
138             .map_err(|e| {
139                 error!("Failed step 2 of phase 1: {:?}", e);
140                 errcode_to_binder_err(e.0)
141             })
142     }
143 
authorizeAndConnectClientToTrustedService( &self, client_id: &[u8], service_name: &str, token: &[u8; 32], client_dice_artifacts: &DiceLeafArtifacts, ) -> binder::Result<()>144     fn authorizeAndConnectClientToTrustedService(
145         &self,
146         client_id: &[u8],
147         service_name: &str,
148         token: &[u8; 32],
149         client_dice_artifacts: &DiceLeafArtifacts,
150     ) -> binder::Result<()> {
151         let mut global_state = self.global_state.lock().unwrap();
152         let mut connection_info = self.connection_information.lock().unwrap();
153         global_state
154             .authmgr_core
155             .authorize_and_connect_client_to_trusted_service(
156                 &mut *connection_info,
157                 client_id,
158                 service_name,
159                 *token,
160                 &client_dice_artifacts.diceLeaf.diceChainEntry,
161                 &client_dice_artifacts.diceLeafPolicy.dicePolicy,
162             )
163             .map_err(|e| {
164                 error!("Failed step 2 of phase 1: {:?}", e);
165                 errcode_to_binder_err(e.0)
166             })
167     }
168 }
169 
170 /// Convert an AuthMgr ErrorCode into a binder error.
errcode_to_binder_err(err: ErrorCode) -> binder::Status171 pub fn errcode_to_binder_err(err: ErrorCode) -> binder::Status {
172     // Translate the internal errors for `Unimplemented` and `InternalError` to their counterparts
173     // in binder errors
174     match err {
175         ErrorCode::Unimplemented => {
176             binder::Status::new_exception(binder::ExceptionCode::UNSUPPORTED_OPERATION, None)
177         }
178         ErrorCode::InternalError => {
179             binder::Status::new_exception(binder::ExceptionCode::SERVICE_SPECIFIC, None)
180         }
181         _ => binder::Status::new_service_specific_error(err as i32, None),
182     }
183 }
184 
185 /// The global state that needs to be maintained by the AuthMgr service.
186 pub struct AuthMgrGlobalState {
187     pub authmgr_core: AuthMgrBE,
188 }
189 
190 impl AuthMgrGlobalState {
new() -> Result<Self, Error>191     pub fn new() -> Result<Self, Error> {
192         // TODO: Here we use the default constants in the reference implementation. These should be
193         // adjusted appropriately.
194         let memory_limits = MemoryLimits::default();
195 
196         let authmgr_core = AuthMgrBE::new(
197             authmgr_be_impl::crypto_trait_impls(),
198             Box::new(DeviceInformation::new()?),
199             Box::new(MockPersistentStorage::new()),
200             memory_limits,
201         )?;
202 
203         Ok(AuthMgrGlobalState { authmgr_core })
204     }
205 }
206 
207 pub struct RpcConnectionInformation {
208     transport_id: TransportID,
209     connection_state: Option<AuthenticatedConnectionState>,
210 }
211 
212 impl RpcConnectionInformation {
213     /// Constructor
new( transport_id: TransportID, connection_state: Option<AuthenticatedConnectionState>, ) -> Self214     pub fn new(
215         transport_id: TransportID,
216         connection_state: Option<AuthenticatedConnectionState>,
217     ) -> Self {
218         RpcConnectionInformation { transport_id, connection_state }
219     }
220 }
221 
222 impl RpcConnection for RpcConnectionInformation {
get_peer_transport_id(&self) -> Result<TransportID, Error>223     fn get_peer_transport_id(&self) -> Result<TransportID, Error> {
224         Ok(self.transport_id)
225     }
226 
store_authenticated_state( &mut self, connection_state: AuthenticatedConnectionState, ) -> Result<(), Error>227     fn store_authenticated_state(
228         &mut self,
229         connection_state: AuthenticatedConnectionState,
230     ) -> Result<(), Error> {
231         self.connection_state = Some(connection_state);
232         Ok(())
233     }
234 
get_authenticated_state(&self) -> Result<Option<&AuthenticatedConnectionState>, Error>235     fn get_authenticated_state(&self) -> Result<Option<&AuthenticatedConnectionState>, Error> {
236         Ok(self.connection_state.as_ref())
237     }
238 
get_mutable_authenticated_state( &mut self, ) -> Result<Option<&mut AuthenticatedConnectionState>, Error>239     fn get_mutable_authenticated_state(
240         &mut self,
241     ) -> Result<Option<&mut AuthenticatedConnectionState>, Error> {
242         Ok((self.connection_state).as_mut())
243     }
244 
remove_authenticated_state(&mut self) -> Result<(), Error>245     fn remove_authenticated_state(&mut self) -> Result<(), Error> {
246         self.connection_state = None;
247         Ok(())
248     }
249 }
250 
251 pub struct RawConnectionInformation {
252     // Raw file descriptor
253     handle: Handle,
254     peer_transport_id: TransportID,
255 }
256 
257 impl RawConnectionInformation {
258     /// Constructor
new(handle: Handle, peer_transport_id: TransportID) -> Self259     pub fn new(handle: Handle, peer_transport_id: TransportID) -> Self {
260         RawConnectionInformation { handle, peer_transport_id }
261     }
262 }
263 
264 impl RawConnection for RawConnectionInformation {
get_peer_transport_id(&self) -> Result<TransportID, Error>265     fn get_peer_transport_id(&self) -> Result<TransportID, Error> {
266         Ok(self.peer_transport_id)
267     }
268 
into_raw_fd(self: Box<Self>) -> i32269     fn into_raw_fd(self: Box<Self>) -> i32 {
270         let fd = self.handle.as_raw_fd();
271         // Prevent the destructor of the handle from being called
272         core::mem::forget(self.handle);
273         fd
274     }
275 }
276 
277 #[derive(Default)]
278 struct DeviceInformation;
279 
280 impl DeviceInformation {
new() -> Result<Self, Error>281     fn new() -> Result<Self, Error> {
282         Ok(Self)
283     }
284 }
285 
286 impl Device for DeviceInformation {
get_self_transport_id(&self) -> Result<TransportID, Error>287     fn get_self_transport_id(&self) -> Result<TransportID, Error> {
288         // TODO: b/392905377. This is temporary, until we can integrate the transport ID from FFA.
289         Ok(TEMP_AUTHMGR_BE_TRANSPORT_ID)
290     }
291 
is_persistent_instance(&self, _instance_id: &InstanceIdentifier) -> Result<bool, Error>292     fn is_persistent_instance(&self, _instance_id: &InstanceIdentifier) -> Result<bool, Error> {
293         // TODO: 399707150
294         // In the scope of Android 16, we support only persistent instances created in the factory.
295         // Therefore, we can simply return true here.
296         Ok(true)
297     }
298 
handover_client_connection( &self, _service_name: &str, client_seq_number: i32, client_conn_handle: Box<dyn RawConnection>, _is_persistent: bool, ) -> Result<(), Error>299     fn handover_client_connection(
300         &self,
301         _service_name: &str,
302         client_seq_number: i32,
303         client_conn_handle: Box<dyn RawConnection>,
304         _is_persistent: bool,
305     ) -> Result<(), Error> {
306         // TODO: b/400118241.
307         // Currently we have the port of the hand over service hardcoded to that of the example TA.
308         // Instead the AuthMgr should construct the appropriate hand over service port based on the
309         // input `service_name`.
310         // TODO: We may be able to retrieve an already setup RPC session to a trusted service from
311         // the cache
312         let rpc_session = RpcSession::new();
313         rpc_session.set_file_descriptor_transport_mode(FileDescriptorTransportMode::Trusty);
314         let rpc_session: Strong<dyn ITrustedServicesHandover> =
315             rpc_session.setup_trusty_client(HANDOVER_SERVICE_PORT).map_err(|_e| {
316                 am_err!(
317                     ConnectionHandoverFailed,
318                     "Failed to setup connection to the handover service."
319                 )
320             })?;
321 
322         let raw_fd: i32 = client_conn_handle.into_raw_fd();
323         // SAFETY: As specified in the definition of the `RawConnection` trait (in system/see/
324         // authmgr/authmgr-be/src/traits.rs), `RawConnection` trait object should have the ownership
325         // of the underlying file descriptor. Therefore, the `raw_fd` passed into the `from_raw_fd`
326         // is an owned file descriptor.
327         let owned_fd = unsafe { OwnedFd::from_raw_fd(raw_fd) };
328         let fd = ParcelFileDescriptor::new(owned_fd);
329         rpc_session.handoverConnection(&fd, client_seq_number).map_err(|_e| {
330             am_err!(ConnectionHandoverFailed, "Failed to handover the connection.")
331         })?;
332         Ok(())
333     }
334 
is_persistent_instance_creation_allowed( &self, _instance_id: &InstanceIdentifier, _dice_chain: &CertChain, ) -> Result<bool, Error>335     fn is_persistent_instance_creation_allowed(
336         &self,
337         _instance_id: &InstanceIdentifier,
338         _dice_chain: &CertChain,
339     ) -> Result<bool, Error> {
340         // TODO: b/400116782. Check the system state and return true if the device is in factory
341         Ok(true)
342     }
343 }
344