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