Skip to content

Commit

Permalink
[services] Support refresh attested server config based on validity
Browse files Browse the repository at this point in the history
  • Loading branch information
mssun committed Feb 26, 2020
1 parent c672cb1 commit d7e7790
Show file tree
Hide file tree
Showing 16 changed files with 253 additions and 80 deletions.
1 change: 1 addition & 0 deletions attestation/Cargo.toml
Expand Up @@ -38,6 +38,7 @@ url = { version = "2.1.1" }
yasna = { version = "0.3.0", features = ["bit-vec", "num-bigint", "chrono"] }

teaclave_types = { path = "../types" }
teaclave_config = { path = "../config" }
teaclave_test_utils = { path = "../tests/utils" }

sgx_rand = { version = "1.1.0", optional = true }
Expand Down
87 changes: 80 additions & 7 deletions attestation/src/attestation.rs
Expand Up @@ -2,23 +2,32 @@ use crate::key;
use crate::AttestationConfig;
use crate::AttestedTlsConfig;
use crate::EndorsedAttestationReport;
use anyhow::Result;
use anyhow::{anyhow, Result};
use log::debug;
use std::prelude::v1::*;
use std::sync::{Arc, SgxRwLock as RwLock};
use std::thread;
use std::time::Duration;
use std::time::{self, SystemTime};
use std::untrusted::time::SystemTimeEx;
use teaclave_config::BUILD_CONFIG;

const ATTESTATION_VALIDITY_SECS: u64 = 86400u64;
const ATTESTATION_VALIDITY_SECS: u64 = BUILD_CONFIG.attestation_validity_secs;
const CERT_ISSUER: &str = "Teaclave";
const CERT_SUBJECT: &str = "CN=Teaclave";

pub struct RemoteAttestation {
pub config: AttestationConfig,
pub attested_tls_config: Option<Arc<RwLock<AttestedTlsConfig>>>,
}

impl Default for RemoteAttestation {
fn default() -> Self {
let config = AttestationConfig::NoAttestation;
Self { config }
Self {
config,
attested_tls_config: None,
}
}
}

Expand All @@ -31,12 +40,32 @@ impl RemoteAttestation {
self.config = config;
Self {
config: self.config,
attested_tls_config: self.attested_tls_config,
}
}

pub fn generate_and_endorse(&self) -> Result<AttestedTlsConfig> {
pub fn generate_and_endorse(self) -> Result<Self> {
let attested_tls_config = Arc::new(RwLock::new(AttestedTlsConfig::new(&self.config)?));
let config = self.config.clone();
let attested_tls_config_ref = attested_tls_config.clone();
thread::spawn(move || {
AttestationFreshnessKeeper::new(config, attested_tls_config_ref).start()
});
Ok(Self {
config: self.config,
attested_tls_config: Some(attested_tls_config),
})
}

pub fn attested_tls_config(&self) -> Option<Arc<RwLock<AttestedTlsConfig>>> {
self.attested_tls_config.clone()
}
}

impl AttestedTlsConfig {
fn new(config: &AttestationConfig) -> Result<AttestedTlsConfig> {
let key_pair = key::Secp256k1KeyPair::new()?;
let report = match &self.config {
let report = match config {
AttestationConfig::NoAttestation => EndorsedAttestationReport::default(),
AttestationConfig::WithAttestation(config) => {
EndorsedAttestationReport::new(&config, key_pair.pub_k)?
Expand All @@ -51,11 +80,55 @@ impl RemoteAttestation {
let time = SystemTime::now();
let validity = time::Duration::from_secs(ATTESTATION_VALIDITY_SECS);

Ok(AttestedTlsConfig {
let attested_tls_config = AttestedTlsConfig {
cert: cert_der,
private_key: prv_key_der,
time,
validity,
})
};

debug!("{:?}", attested_tls_config);

Ok(attested_tls_config)
}
}

struct AttestationFreshnessKeeper {
config: AttestationConfig,
attested_tls_config: Arc<RwLock<AttestedTlsConfig>>,
}

impl AttestationFreshnessKeeper {
pub(crate) fn new(
config: AttestationConfig,
attested_tls_config: Arc<RwLock<AttestedTlsConfig>>,
) -> Self {
Self {
config,
attested_tls_config,
}
}

pub(crate) fn start(&self) {
debug!("AttestationFreshnessKeeper started");
loop {
thread::sleep(Duration::from_secs(ATTESTATION_VALIDITY_SECS));
match self.refresh() {
Ok(_) => debug!("Attestation report updated successfully"),
Err(e) => debug!("Failed to refresh attestation report: {:?}", e),
}
}
}

fn refresh(&self) -> Result<()> {
debug!("begin refresh");
let updated_attested_tls_config = AttestedTlsConfig::new(&self.config)?;
let lock = self.attested_tls_config.clone();
let mut config = lock
.write()
.map_err(|_| anyhow!("Failed to get write lock"))?;
*config = updated_attested_tls_config;
debug!("refresh done");
Ok(())
}
}
4 changes: 4 additions & 0 deletions attestation/src/lib.rs
Expand Up @@ -37,16 +37,19 @@ pub enum AttestationError {
ConnectionError,
}

#[derive(Clone)]
pub enum AttestationConfig {
NoAttestation,
WithAttestation(AttestationServiceConfig),
}

#[derive(Clone)]
pub(crate) enum AttestationAlgorithm {
SgxEpid,
SgxEcdsa,
}

#[derive(Clone)]
pub struct AttestationServiceConfig {
algo: AttestationAlgorithm,
as_url: url::Url,
Expand Down Expand Up @@ -98,6 +101,7 @@ pub(crate) struct EndorsedAttestationReport {
pub signing_cert: Vec<u8>,
}

#[derive(Debug)]
pub struct AttestedTlsConfig {
pub cert: Vec<u8>,
pub private_key: Vec<u8>,
Expand Down
3 changes: 3 additions & 0 deletions config/build.config.toml
Expand Up @@ -15,6 +15,9 @@ auditor_public_keys = [
# RPC max message size
rpc_max_message_size = 409600

# Validity in seconds for a remote attestation report and endorsed attested TLS config
attestation_validity_secs = 3600

# Specify accepted inbound services to enforce incoming connections via mutual
# attestation. Below figure illustrates current topology of Teaclave services.
#
Expand Down
7 changes: 5 additions & 2 deletions config/config_gen/main.rs
Expand Up @@ -13,7 +13,8 @@ use structopt::StructOpt;
struct BuildConfigToml {
as_root_ca_cert: ConfigSource,
auditor_public_keys: Vec<ConfigSource>,
rpc_max_message_size: u32,
rpc_max_message_size: u64,
attestation_validity_secs: u64,
inbound: Inbound,
}

Expand Down Expand Up @@ -52,7 +53,8 @@ fn display_config_source(config: &ConfigSource) -> String {
struct ConfigTemplate {
as_root_ca_cert: String,
auditor_public_keys: Vec<String>,
rpc_max_message_size: u32,
rpc_max_message_size: u64,
attestation_validity_secs: u64,
inbound: Inbound,
}

Expand All @@ -71,6 +73,7 @@ fn generate_build_config(toml: &Path, out: &Path) {
as_root_ca_cert,
auditor_public_keys,
rpc_max_message_size: config.rpc_max_message_size,
attestation_validity_secs: config.attestation_validity_secs,
inbound: config.inbound,
};
let mut f = File::create(out).expect(&format!("Failed to create file: {}", out.display()));
Expand Down
2 changes: 2 additions & 0 deletions config/config_gen/templates/config.j2
Expand Up @@ -3,6 +3,7 @@ pub struct BuildConfig {
pub as_root_ca_cert: &'static [u8],
pub auditor_public_keys: &'static [&'static [u8]; {{ auditor_public_keys.len() }}],
pub rpc_max_message_size: u64,
pub attestation_validity_secs: u64,
pub inbound: Inbounds,
}

Expand All @@ -22,6 +23,7 @@ pub const BUILD_CONFIG: BuildConfig = BuildConfig {
{%- endfor %}
],
rpc_max_message_size: {{ rpc_max_message_size }},
attestation_validity_secs: {{ attestation_validity_secs }},
inbound: Inbounds {
access_control: &[
{%- for s in inbound.access_control %}
Expand Down
3 changes: 2 additions & 1 deletion rpc/src/channel.rs
Expand Up @@ -29,7 +29,8 @@ where
let hostname = uri.host().ok_or_else(|| anyhow!("Invalid hostname."))?;
let stream = std::net::TcpStream::connect(address)?;
let hostname = webpki::DNSNameRef::try_from_ascii_str(hostname)?;
let session = rustls::ClientSession::new(&Arc::new(client_config.config.clone()), hostname);
let session =
rustls::ClientSession::new(&Arc::new(client_config.client_config.clone()), hostname);
let tls_stream = rustls::StreamOwned::new(session, stream);
let transport = SgxTrustedTlsTransport::new(tls_stream);

Expand Down

0 comments on commit d7e7790

Please sign in to comment.