1 /*
2  * Copyright (C) 2023 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 //! Common functionality for non-secure/testing instance of AuthGraph.
18 
19 use authgraph_boringssl as boring;
20 use authgraph_core::{
21     error, keyexchange,
22     ta::{AuthGraphTa, Role},
23 };
24 use authgraph_hal::channel::SerializedChannel;
25 use log::error;
26 use std::cell::RefCell;
27 use std::rc::Rc;
28 use std::sync::{mpsc, Mutex};
29 
30 /// Implementation of the AuthGraph TA that runs locally in-process (and which is therefore
31 /// insecure).
32 pub struct LocalTa {
33     channels: Mutex<Channels>,
34 }
35 
36 struct Channels {
37     in_tx: mpsc::Sender<Vec<u8>>,
38     out_rx: mpsc::Receiver<Vec<u8>>,
39 }
40 
41 impl LocalTa {
42     /// Create a new instance.
new() -> Result<Self, error::Error>43     pub fn new() -> Result<Self, error::Error> {
44         // Create a pair of channels to communicate with the TA thread.
45         let (in_tx, in_rx) = mpsc::channel();
46         let (out_tx, out_rx) = mpsc::channel();
47 
48         // The TA code expects to run single threaded, so spawn a thread to run it in.
49         std::thread::spawn(move || {
50             let mut ta = AuthGraphTa::new(
51                 keyexchange::AuthGraphParticipant::new(
52                     boring::crypto_trait_impls(),
53                     Rc::new(RefCell::new(boring::test_device::AgDevice::default())),
54                     keyexchange::MAX_OPENED_SESSIONS,
55                 )
56                 .expect("failed to create AG participant"),
57                 Role::Both,
58             );
59             // Loop forever processing request messages.
60             loop {
61                 let req_data: Vec<u8> = match in_rx.recv() {
62                     Ok(data) => data,
63                     Err(_) => {
64                         error!("local TA failed to receive request!");
65                         break;
66                     }
67                 };
68                 let rsp_data = ta.process(&req_data);
69                 match out_tx.send(rsp_data) {
70                     Ok(_) => {}
71                     Err(_) => {
72                         error!("local TA failed to send out response");
73                         break;
74                     }
75                 }
76             }
77             error!("local TA terminating!");
78         });
79         Ok(Self {
80             channels: Mutex::new(Channels { in_tx, out_rx }),
81         })
82     }
83 }
84 
85 impl SerializedChannel for LocalTa {
86     const MAX_SIZE: usize = usize::MAX;
87 
execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>>88     fn execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
89         // Serialize across both request and response.
90         let channels = self.channels.lock().unwrap();
91         channels
92             .in_tx
93             .send(req_data.to_vec())
94             .expect("failed to send in request");
95         Ok(channels.out_rx.recv().expect("failed to receive response"))
96     }
97 }
98