• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2024 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 mod boot_params_svc;
18 
19 use alloc::vec::Vec;
20 use android_system_desktop_security_gsc::aidl::android::system::desktop::security::gsc::IGsc::BnGsc;
21 use android_system_desktop_security_gsc::aidl::android::system::desktop::security::gsc::IGsc::IGsc;
22 use binder::{BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status};
23 use log::{error, info};
24 use rpcbinder::RpcServer;
25 use std::borrow::Cow;
26 use std::rc::Rc;
27 use std::sync::Arc;
28 use std::sync::Mutex;
29 use tipc::TipcError;
30 use tipc::{
31     service_dispatcher, ConnectResult, Deserialize, Handle, Manager, MessageResult, PortCfg,
32     Serialize, Serializer, UnbufferedService, Uuid,
33 };
34 use trusty_sys::Error;
35 
36 const GSC_SERVICE_PORT: &str = "com.android.trusty.rust.GscAppService.V1";
37 const TUNNEL_SERVICE_PORT: &str = "com.android.trusty.rust.GscTunnelService.V1";
38 const BP_SERVICE_PORT: &str = "com.android.trusty.rust.BootParamsService.V1";
39 
40 /// A GscProxy implements the IGsc binder interface and forwards requests from trusty apps to the
41 /// GSC over a GscTunnel.
42 pub struct GscProxy {
43     tunnel: Arc<GscTunnelInner>,
44 }
45 
46 impl Interface for GscProxy {}
47 
48 impl IGsc for GscProxy {
transmit(&self, data: &[u8]) -> BinderResult<Vec<u8>>49     fn transmit(&self, data: &[u8]) -> BinderResult<Vec<u8>> {
50         self.tunnel
51             .transmit(data)
52             .map_err(|_| Status::new_exception(ExceptionCode::ILLEGAL_STATE, None))
53     }
54 }
55 
56 impl GscProxy {
new(tunnel: Arc<GscTunnelInner>) -> Self57     fn new(tunnel: Arc<GscTunnelInner>) -> Self {
58         Self { tunnel }
59     }
60 }
61 
62 /// GscTunnelInner satisfies GscProxy's requirement to be Sync + Send due to being a binder
63 /// interface.
64 pub struct GscTunnelInner {
65     handle: Mutex<Option<Handle>>,
66 }
67 
68 /// GscTunnel implements the tipc::UnbufferedService trait for an untrusted service (gscd) to
69 /// connect to and receive commands from.
70 pub struct GscTunnel {
71     inner: Arc<GscTunnelInner>,
72 }
73 
74 /// The content of a message is a TPM command and opaque to this service.
75 pub struct Message<'a>(Cow<'a, [u8]>);
76 
77 impl Deserialize for Message<'_> {
78     type Error = TipcError;
79     const MAX_SERIALIZED_SIZE: usize = 4096;
80 
deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> tipc::Result<Self>81     fn deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> tipc::Result<Self> {
82         Ok(Message(Cow::from(bytes.to_vec())))
83     }
84 }
85 
86 impl<'s> Serialize<'s> for Message<'_> {
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_ref())
92     }
93 }
94 
95 impl UnbufferedService for GscTunnel {
96     type Connection = ();
97 
98     /// on_connect stores the connection handle for later use.
on_connect( &self, _port: &PortCfg, handle: &Handle, _peer: &Uuid, ) -> tipc::Result<ConnectResult<Self::Connection>>99     fn on_connect(
100         &self,
101         _port: &PortCfg,
102         handle: &Handle,
103         _peer: &Uuid,
104     ) -> tipc::Result<ConnectResult<Self::Connection>> {
105         *self.inner.handle.lock().map_err(|_| TipcError::SystemError(Error::BadState))? =
106             Some(handle.try_clone()?);
107         info!("gscd connected to the Trusty gsc_svc");
108         Ok(ConnectResult::Accept(()))
109     }
110 
111     // on_message is never expected to be called since GscTunnel handles commands synchronously
on_message( &self, _connection: &Self::Connection, _handle: &Handle, _buffer: &mut [u8], ) -> tipc::Result<MessageResult>112     fn on_message(
113         &self,
114         _connection: &Self::Connection,
115         _handle: &Handle,
116         _buffer: &mut [u8],
117     ) -> tipc::Result<MessageResult> {
118         Ok(MessageResult::MaintainConnection)
119     }
120 
on_disconnect(&self, _connection: &Self::Connection)121     fn on_disconnect(&self, _connection: &Self::Connection) {
122         error!("gscd disconnected!");
123         *self.inner.handle.lock().unwrap_or_else(|e| e.into_inner()) = None;
124     }
125 }
126 
127 impl GscTunnelInner {
new() -> Self128     fn new() -> Self {
129         Self { handle: Mutex::new(None) }
130     }
131 
132     /// tipc does not design for trusty applications connection to untrusted apps. As a result,
133     /// it's possible the othe trusty apps will start sending messages before the connection from
134     /// gscd is made.
transmit(&self, data: &[u8]) -> tipc::Result<Vec<u8>>135     fn transmit(&self, data: &[u8]) -> tipc::Result<Vec<u8>> {
136         if let Some(handle) =
137             self.handle.lock().or(Err(TipcError::SystemError(Error::BadState)))?.as_ref()
138         {
139             handle.send(&Message(Cow::from(data)))?;
140             let mut buf = vec![0; Message::MAX_SERIALIZED_SIZE];
141             let msg: Message = handle.recv(buf.as_mut_slice())?;
142             Ok(msg.0.to_vec())
143         } else {
144             Err(TipcError::SystemError(Error::NotReady))
145         }
146     }
147 }
148 
149 impl GscTunnel {
new(inner: Arc<GscTunnelInner>) -> Self150     fn new(inner: Arc<GscTunnelInner>) -> Self {
151         Self { inner }
152     }
153 }
154 
155 service_dispatcher! {
156     enum GscDispatcher {
157         RpcServer,
158         GscTunnel,
159     }
160 }
161 
162 const PORT_COUNT: usize = 3;
163 const CONNECTION_COUNT: usize = 4;
164 
init_and_start_loop() -> Result<(), TipcError>165 pub fn init_and_start_loop() -> Result<(), TipcError> {
166     trusty_log::init();
167     let inner_tunnel = Arc::new(GscTunnelInner::new());
168     let tunnel = GscTunnel::new(inner_tunnel.clone());
169     let proxy = GscProxy::new(inner_tunnel);
170 
171     let mut dispatcher =
172         GscDispatcher::<PORT_COUNT>::new().expect("Could not create test dispatcher");
173     let gsc_service = BnGsc::new_binder(proxy, BinderFeatures::default());
174     let gsc_rpc_server = RpcServer::new_per_session(move |_uuid| Some(gsc_service.as_binder()));
175 
176     let app_cfg =
177         PortCfg::new(GSC_SERVICE_PORT).expect("Could not create port config").allow_ta_connect();
178     dispatcher
179         .add_service(Rc::new(gsc_rpc_server), app_cfg)
180         .expect("Could not add GSC service to dispatcher");
181 
182     let tunnel_cfg =
183         PortCfg::new(TUNNEL_SERVICE_PORT).expect("Could not create port config").allow_ns_connect();
184     dispatcher
185         .add_service(Rc::new(tunnel), tunnel_cfg)
186         .expect("Could not add tunnel service to dispatcher");
187 
188     let bp_cfg =
189         PortCfg::new(BP_SERVICE_PORT).expect("Could not create port config").allow_ta_connect();
190     let bp = boot_params_svc::create_boot_params_service()?;
191     let bp_rpc_server = RpcServer::new_per_session(move |_uuid| Some(bp.as_binder()));
192     dispatcher
193         .add_service(Rc::new(bp_rpc_server), bp_cfg)
194         .expect("Could not add bp service to dispatcher");
195 
196     Manager::<_, _, PORT_COUNT, CONNECTION_COUNT>::new_with_dispatcher(dispatcher, [])
197         .expect("Could not create service manager")
198         .run_event_loop()
199         .expect("GSC tunnel event loop failed");
200 
201     Ok(())
202 }
203