blob: 412ad45ddb2ec9c40ee7b8bd86fb317b0ba05872 [file] [log] [blame]
David Drysdalec3aa4422023-12-18 16:29:18 +00001/*
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//! Non-secure implementation of a local Secretkeeper TA.
18
19use authgraph_boringssl as boring;
20use authgraph_core::keyexchange::{AuthGraphParticipant, MAX_OPENED_SESSIONS};
21use authgraph_core::ta::{AuthGraphTa, Role};
22use authgraph_hal::channel::SerializedChannel;
23use log::error;
24use secretkeeper_core::ta::SecretkeeperTa;
25use std::cell::RefCell;
26use std::rc::Rc;
27use std::sync::mpsc;
28use std::sync::{Arc, Mutex};
29
30mod store;
31
32/// Implementation of the Secrekeeper TA that runs locally in-process (and which is therefore
33/// insecure).
34pub struct LocalTa {
35 in_tx: mpsc::Sender<Vec<u8>>,
36 out_rx: mpsc::Receiver<Vec<u8>>,
37}
38
39/// Prefix byte for messages intended for the AuthGraph TA.
40const AG_MESSAGE_PREFIX: u8 = 0x00;
41/// Prefix byte for messages intended for the Secretkeeper TA.
42const SK_MESSAGE_PREFIX: u8 = 0x01;
43
44impl LocalTa {
45 /// Create a new instance.
46 pub fn new() -> Self {
47 // Create a pair of channels to communicate with the TA thread.
48 let (in_tx, in_rx) = mpsc::channel();
49 let (out_tx, out_rx) = mpsc::channel();
50
51 // The TA code expects to run single threaded, so spawn a thread to run it in.
52 std::thread::spawn(move || {
53 let mut crypto_impls = boring::crypto_trait_impls();
54 let storage_impl = Box::new(store::InMemoryStore::default());
55 let sk_ta = Rc::new(RefCell::new(
56 SecretkeeperTa::new(&mut crypto_impls, storage_impl)
57 .expect("Failed to create local Secretkeeper TA"),
58 ));
59 let mut ag_ta = AuthGraphTa::new(
60 AuthGraphParticipant::new(crypto_impls, sk_ta.clone(), MAX_OPENED_SESSIONS)
61 .expect("Failed to create local AuthGraph TA"),
62 Role::Sink,
63 );
64
65 // Loop forever processing request messages.
66 loop {
67 let req_data: Vec<u8> = match in_rx.recv() {
68 Ok(data) => data,
69 Err(_) => {
70 error!("local TA failed to receive request!");
71 break;
72 }
73 };
74 let rsp_data = match req_data[0] {
75 AG_MESSAGE_PREFIX => ag_ta.process(&req_data[1..]),
76 SK_MESSAGE_PREFIX => {
77 // It's safe to `borrow_mut()` because this code is not a callback
78 // from AuthGraph (the only other holder of an `Rc`), and so there
79 // can be no live `borrow()`s in this (single) thread.
80 sk_ta.borrow_mut().process(&req_data[1..])
81 }
82 prefix => panic!("unexpected messageprefix {prefix}!"),
83 };
84 match out_tx.send(rsp_data) {
85 Ok(_) => {}
86 Err(_) => {
87 error!("local TA failed to send out response");
88 break;
89 }
90 }
91 }
92 error!("local TA terminating!");
93 });
94 Self { in_tx, out_rx }
95 }
96
97 fn execute_for(&mut self, prefix: u8, req_data: &[u8]) -> Vec<u8> {
98 let mut prefixed_req = Vec::with_capacity(req_data.len() + 1);
99 prefixed_req.push(prefix);
100 prefixed_req.extend_from_slice(req_data);
101 self.in_tx
102 .send(prefixed_req)
103 .expect("failed to send in request");
104 self.out_rx.recv().expect("failed to receive response")
105 }
106}
107
108pub struct AuthGraphChannel(pub Arc<Mutex<LocalTa>>);
109
110impl SerializedChannel for AuthGraphChannel {
111 const MAX_SIZE: usize = usize::MAX;
112 fn execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
113 Ok(self
114 .0
115 .lock()
116 .unwrap()
117 .execute_for(AG_MESSAGE_PREFIX, req_data))
118 }
119}
120
121pub struct SecretkeeperChannel(pub Arc<Mutex<LocalTa>>);
122
123impl SerializedChannel for SecretkeeperChannel {
124 const MAX_SIZE: usize = usize::MAX;
125 fn execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
126 Ok(self
127 .0
128 .lock()
129 .unwrap()
130 .execute_for(SK_MESSAGE_PREFIX, req_data))
131 }
132}