Skip to content
This repository has been archived by the owner on Jul 27, 2022. It is now read-only.

Problem: no tx-validation enclave attested TLS listener for receiving secrets from TDBE (fixes #1994) #2189

Merged
merged 1 commit into from
Aug 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jobs:
NETWORK_ID: "ab"
MRSIGNER: "0000000000000000000000000000000000000000000000000000000000000000"
TQE_MRENCLAVE: "0000000000000000000000000000000000000000000000000000000000000000"
TDBE_MRENCLAVE: "0000000000000000000000000000000000000000000000000000000000000000"

security_audit:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -89,6 +90,7 @@ jobs:
NETWORK_ID: "ab"
MRSIGNER: "0000000000000000000000000000000000000000000000000000000000000000"
TQE_MRENCLAVE: "0000000000000000000000000000000000000000000000000000000000000000"
TDBE_MRENCLAVE: "0000000000000000000000000000000000000000000000000000000000000000"
- name: test-stable
uses: actions-rs/cargo@v1
with:
Expand All @@ -98,6 +100,7 @@ jobs:
NETWORK_ID: "ab"
MRSIGNER: "0000000000000000000000000000000000000000000000000000000000000000"
TQE_MRENCLAVE: "0000000000000000000000000000000000000000000000000000000000000000"
TDBE_MRENCLAVE: "0000000000000000000000000000000000000000000000000000000000000000"

test-nightly-coverage:
runs-on: ubuntu-latest
Expand All @@ -121,6 +124,7 @@ jobs:
NETWORK_ID: "ab"
MRSIGNER: "0000000000000000000000000000000000000000000000000000000000000000"
TQE_MRENCLAVE: "0000000000000000000000000000000000000000000000000000000000000000"
TDBE_MRENCLAVE: "0000000000000000000000000000000000000000000000000000000000000000"
- uses: actions-rs/[email protected]
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ rust: &rust
- SGX_SDK=/opt/sgxsdk
- MRSIGNER=0000000000000000000000000000000000000000000000000000000000000000
- TQE_MRENCLAVE=0000000000000000000000000000000000000000000000000000000000000000
- TDBE_MRENCLAVE=0000000000000000000000000000000000000000000000000000000000000000
- NETWORK_ID=ab
before_install: # versions from https://github.com/erickt/rust-zmq/blob/master/.travis.yml
- |
Expand Down
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 55 additions & 18 deletions chain-abci/src/enclave_bridge/edp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,55 @@ use tokio::net::{TcpListener, TcpStream};

use std::os::unix::net::UnixStream;

const REMOTE_ATTESTATION_PROXY: &str = "ra-sp-server";

/// pair of unix domain sockets
/// enclave_stream is only needed / passed in `connect_stream`
/// enclave_stream / tdbe_stream is only needed / passed in `connect_stream`
/// `runner_stream` is shared in chain-abci app
/// TODO: separate out the "chain-abci-side" runner_stream and "usercall extensions"-side
/// (enclave_stream / tdbe_stream)
#[derive(Debug)]
pub struct TxValidationApp {
enclave_stream: Option<UnixStream>,
runner_stream: Arc<Mutex<UnixStream>>,
/// `ra-sp-server` address for remote attestation. E.g. `0.0.0.0:8989`
/// FIXME: enclave direct connection -- not via TCP proxy
sp_address: Option<String>,
tdbe_stream: Option<UnixStream>,
tomtau marked this conversation as resolved.
Show resolved Hide resolved
}

impl Clone for TxValidationApp {
fn clone(&self) -> Self {
impl TxValidationApp {
/// only used for `TxValidationServer`/`chain-abci` having access to "runner_stream",
/// _not for enclave launching_
pub fn get_comm_only(&self) -> Self {
Self {
enclave_stream: None,
runner_stream: self.runner_stream.clone(),
sp_address: None,
tdbe_stream: None,
}
}
}

impl Default for TxValidationApp {
fn default() -> Self {
let (sender, receiver) = UnixStream::pair().expect("init tx validation socket");
Self {
enclave_stream: Some(receiver),
runner_stream: Arc::new(Mutex::new(sender)),
}
fn new(sp_address: String) -> (Self, UnixStream) {
let (sender, receiver) = UnixStream::pair().expect("init chain-abci<->tve socket");
let (from_tdbe_to_tve, from_tve_to_tdbe) =
UnixStream::pair().expect("init tve<->tdbe socket");

(
Self {
enclave_stream: Some(receiver),
runner_stream: Arc::new(Mutex::new(sender)),
sp_address: Some(sp_address),
tdbe_stream: Some(from_tve_to_tdbe),
},
from_tdbe_to_tve,
)
}
}

type UserCallStream = io::Result<Option<Box<dyn AsyncStream>>>;
type UserCallListener = io::Result<Option<Box<dyn AsyncListener>>>;
/// type aliases for outputs in UsercallExtension async return types
pub type UserCallStream = io::Result<Option<Box<dyn AsyncStream>>>;
pub type UserCallListener = io::Result<Option<Box<dyn AsyncListener>>>;

impl UsercallExtension for TxValidationApp {
fn connect_stream<'future>(
Expand All @@ -70,6 +89,22 @@ impl UsercallExtension for TxValidationApp {
Ok(None)
}
}
REMOTE_ATTESTATION_PROXY => {
if let Some(ra_address) = this.sp_address.as_ref() {
let stream = TcpStream::connect(ra_address).await?;
Ok(Some(Box::new(stream)))
} else {
Ok(None)
}
}
"tdbe" => {
if let Some(enclave_stream) = this.tdbe_stream.as_ref() {
let stream = tokio::net::UnixStream::from_std(enclave_stream.try_clone()?)?;
Ok(Some(Box::new(stream)))
} else {
Ok(None)
}
}
_ => Ok(None),
}
}
Expand Down Expand Up @@ -113,9 +148,11 @@ impl EnclaveProxy for TxValidationApp {
/// Launches tx-validation enclave --
/// it expects "tx-validation-next.sgxs" (+ signature)
/// to be in the same directory as chain-abci
pub fn launch_tx_validation() -> TxValidationApp {
let app = TxValidationApp::default();
let app2 = app.clone();
/// it returns the "copied" app (for `TxValidationServer` / chain-abci)
/// + the unix stream for transaction data bootstrapping enclave
pub fn launch_tx_validation(ra_proxy_address: String) -> (TxValidationApp, UnixStream) {
let (app, from_tdbe_to_tve) = TxValidationApp::new(ra_proxy_address);
let app2 = app.get_comm_only();
let mut device = Device::new()
.expect("SGX device was not found")
.einittoken_provider(AesmClient::new())
Expand All @@ -134,7 +171,7 @@ pub fn launch_tx_validation() -> TxValidationApp {
log::info!("starting tx validation enclave");
enclave.run().expect("Failed to start enclave")
});
app2
(app2, from_tdbe_to_tve)
}

/// Temporary tx query launching options
Expand Down Expand Up @@ -167,7 +204,7 @@ impl UsercallExtension for TempTxQueryOptions {
tokio::net::UnixStream::from_std(this.chain_abci_data.try_clone()?)?;
Ok(Some(Box::new(stream)))
}
"ra-sp-server" => {
REMOTE_ATTESTATION_PROXY => {
let stream = TcpStream::connect(&this.sp_address).await?;
Ok(Some(Box::new(stream)))
}
Expand Down
58 changes: 34 additions & 24 deletions chain-abci/src/enclave_bridge/edp/tdbe.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
use std::{
collections::HashMap,
future::Future,
io::{self, Cursor, Seek, SeekFrom},
io::{Cursor, Seek, SeekFrom},
os::unix::net::UnixStream,
pin::Pin,
sync::Arc,
thread,
thread::JoinHandle,
};

use aesm_client::AesmClient;
use enclave_runner::{
usercalls::{AsyncListener, AsyncStream, UsercallExtension},
EnclaveBuilder,
};
use enclave_runner::{usercalls::UsercallExtension, EnclaveBuilder};
use kvdb::KeyValueDB;
use sgxs_loaders::isgx::Device;
use tdbe_common::TdbeStartupConfig;
Expand All @@ -27,7 +25,10 @@ use enclave_protocol::{
};
use ra_sp_server::config::SpRaConfig;

use crate::enclave_bridge::TdbeConfig;
use crate::enclave_bridge::{
edp::{UserCallListener, UserCallStream},
TdbeConfig,
};

#[derive(Debug)]
pub struct TdbeApp {
Expand All @@ -42,38 +43,43 @@ pub struct TdbeApp {
remote_rpc_address: Option<String>,
/// Local TDBE server address to listen on. E.g. `127.0.0.1:3445`
local_listen_address: String,
/// UDS to push secrets to tx-validation enclave
tve_stream: UnixStream,
}

impl TdbeApp {
/// Creates a new instance of TDBE app
pub fn new(
tdbe_config: &TdbeConfig,
ra_config: &SpRaConfig,
storage: Arc<dyn KeyValueDB>,
_storage: Arc<dyn KeyValueDB>,
tve_stream: UnixStream,
) -> std::io::Result<Self> {
// - `chain_abci_stream` is passed to enclave. Encalve can send requests to chain-abci
// using this
// - `chain_abci_receiver` listens to the requests sent by enclave and responds to them
let (chain_abci_stream, chain_abci_receiver) = UnixStream::pair()?;
let (chain_abci_stream, _chain_abci_receiver) = UnixStream::pair()?;

// - `persistence_stream` is passed to enclave. Encalve can send requests to chain-storage
// using this
// - `persistence_receiver` listens to the requests sent by enclave and responds to them
let (persistence_stream, persistence_receiver) = UnixStream::pair()?;
let (persistence_stream, _persistence_receiver) = UnixStream::pair()?;

spawn_chain_abci_thread(chain_abci_receiver, storage.clone());
spawn_persistence_thread(persistence_receiver, storage);
// FIXME: spawn these when they actually do something
// spawn_chain_abci_thread(chain_abci_receiver, storage.clone());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is chain_abci_thread removed? Isn't it supposed to spawn a new thread?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not removed, it's commented out, as it's unused in this step

// spawn_persistence_thread(persistence_receiver, storage);

Ok(Self {
chain_abci_stream,
persistence_stream,
sp_address: ra_config.address.clone(),
remote_rpc_address: tdbe_config.remote_rpc_address.clone(),
local_listen_address: tdbe_config.local_listen_address.clone(),
tve_stream,
})
}

pub fn spawn(self) {
pub fn spawn(self) -> JoinHandle<()> {
thread::spawn(move || {
let mut device = Device::new()
.expect("SGX device was not found")
Expand All @@ -90,10 +96,11 @@ impl TdbeApp {
.build(&mut device)
.expect("Failed to build enclave");
enclave.run().expect("Failed to start enclave")
});
})
}
}

#[allow(dead_code)]
fn spawn_chain_abci_thread(mut receiver: UnixStream, storage: Arc<dyn KeyValueDB>) {
let _ = thread::spawn(move || {
let storage = chain_storage::ReadOnlyStorage::new_db(storage);
Expand Down Expand Up @@ -127,6 +134,8 @@ fn get_sealed_tx_data(txids: Vec<TxId>, storage: &ReadOnlyStorage) -> Option<Vec
Some(result)
}

/// FIXME: should this start a background thread if this is one-off and the main thread needs to wait for its completion?
#[allow(dead_code)]
fn spawn_persistence_thread(mut receiver: UnixStream, storage: Arc<dyn KeyValueDB>) {
let _ = thread::spawn(move || {
let mut storage = chain_storage::Storage::new_db(storage);
Expand All @@ -143,6 +152,9 @@ fn spawn_persistence_thread(mut receiver: UnixStream, storage: Arc<dyn KeyValueD
chain_storage::set_last_fetched_block(&mut kvdb, last_fetched_block);
break;
}
_ => {
// FIXME
}
}
}

Expand All @@ -151,23 +163,20 @@ fn spawn_persistence_thread(mut receiver: UnixStream, storage: Arc<dyn KeyValueD
});
}

#[allow(clippy::type_complexity)]
impl UsercallExtension for TdbeApp {
fn connect_stream<'future>(
&'future self,
addr: &'future str,
_local_addr: Option<&'future mut String>,
_peer_addr: Option<&'future mut String>,
) -> Pin<Box<dyn Future<Output = io::Result<Option<Box<dyn AsyncStream>>>> + 'future>> {
async fn connect_stream_inner(
this: &TdbeApp,
addr: &str,
) -> io::Result<Option<Box<dyn AsyncStream>>> {
) -> Pin<Box<dyn Future<Output = UserCallStream> + 'future>> {
async fn connect_stream_inner(this: &TdbeApp, addr: &str) -> UserCallStream {
match addr {
// Passes initial startup configuration to enclave
"init" => {
let tdbe_startup_config = TdbeStartupConfig {
remote_rpc_address: this.remote_rpc_address.clone(),
temp_mock_feature: true,
};

let mut stream = Cursor::new(Vec::new());
Expand All @@ -192,6 +201,10 @@ impl UsercallExtension for TdbeApp {
let stream = TcpStream::connect(&this.sp_address).await?;
Ok(Some(Box::new(stream)))
}
"tx-validation" => {
let stream = tokio::net::UnixStream::from_std(this.tve_stream.try_clone()?)?;
Ok(Some(Box::new(stream)))
}
_ => Ok(None),
}
}
Expand All @@ -203,11 +216,8 @@ impl UsercallExtension for TdbeApp {
&'future self,
addr: &'future str,
_local_addr: Option<&'future mut String>,
) -> Pin<Box<dyn Future<Output = io::Result<Option<Box<dyn AsyncListener>>>> + 'future>> {
async fn bind_stream_inner(
this: &TdbeApp,
addr: &str,
) -> io::Result<Option<Box<dyn AsyncListener>>> {
) -> Pin<Box<dyn Future<Output = UserCallListener> + 'future>> {
async fn bind_stream_inner(this: &TdbeApp, addr: &str) -> UserCallListener {
match addr {
// Binds TCP listener for TDBE server
"tdbe" => {
Expand Down
4 changes: 4 additions & 0 deletions chain-abci/src/enclave_bridge/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ impl Clone for MockClient {
}

impl MockClient {
pub fn get_comm_only(&self) -> Self {
self.clone()
}

pub fn new(chain_hex_id: u8) -> Self {
MockClient {
chain_hex_id,
Expand Down
2 changes: 1 addition & 1 deletion chain-abci/src/enclave_bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct TdbeConfig {
}

/// Abstracts over communication with an external part that does enclave calls
pub trait EnclaveProxy: Sync + Send + Sized + Clone {
pub trait EnclaveProxy: Sync + Send + Sized {
// sanity check for checking enclave initialization
fn check_chain(&mut self, network_id: u8) -> Result<(), ()>;
fn process_request(&mut self, request: IntraEnclaveRequest) -> IntraEnclaveResponse;
Expand Down
Loading