Skip to content
Permalink
Browse files

[core] Optimize RPC tls config (#190)

  • Loading branch information
m4sterchain authored and mssun committed Dec 24, 2019
1 parent 2d43429 commit ead453f37702ac2a27d0341de77d097aa9da57cd
@@ -19,6 +19,8 @@ use std::sync::Arc;

use crate::rpc::sgx::EnclaveAttr;

#[cfg(feature = "mesalock_sgx")]
use sgx_types::sgx_sha256_hash_t;
#[cfg(not(feature = "mesalock_sgx"))]
use std::sync::RwLock;
#[cfg(feature = "mesalock_sgx")]
@@ -29,89 +31,92 @@ use std::collections::HashMap;
use lazy_static::lazy_static;

lazy_static! {
static ref CLIENTCONFIGCACHE: RwLock<HashMap<u64, Arc<rustls::ClientConfig>>> =
{ RwLock::new(HashMap::new()) };
static ref CLIENT_CONFIG_CACHE: RwLock<ClientConfigCache> =
{ RwLock::new(ClientConfigCache::default()) };
}

#[cfg(feature = "mesalock_sgx")]
#[derive(Default)]
struct ClientConfigCache {
private_key_sha256: sgx_sha256_hash_t,
target_configs: HashMap<Arc<EnclaveAttr>, Arc<rustls::ClientConfig>>,
}

#[cfg(not(feature = "mesalock_sgx"))]
pub(crate) fn get_tls_config(server_attr: EnclaveAttr) -> Arc<rustls::ClientConfig> {
// We believe a client from untrusted side do not change his tls cert
// during single execution.
let cattr_hash: u64 = server_attr.calculate_hash();
if let Ok(cfg_cache) = CLIENTCONFIGCACHE.try_read() {
if let Some(cfg) = cfg_cache.get(&cattr_hash) {
#[derive(Default)]
struct ClientConfigCache {
target_configs: HashMap<Arc<EnclaveAttr>, Arc<rustls::ClientConfig>>,
}

#[cfg(feature = "mesalock_sgx")]
pub(crate) fn get_tls_config(server_attr: Arc<EnclaveAttr>) -> Arc<rustls::ClientConfig> {
use crate::rpc::sgx::ra::get_ra_cert;

// To re-use existing TLS cache, we need to first check if the server has
// updated his RA cert
let cert_key = get_ra_cert();

// TODO: add wrapper function
if let Ok(cfg_cache) = CLIENT_CONFIG_CACHE.try_read() {
if let Some(cfg) = cfg_cache.target_configs.get(&server_attr) {
return cfg.clone();
}
}

let mut client_cfg = rustls::ClientConfig::new();
let certs = vec![rustls::Certificate(cert_key.cert)];
let privkey = rustls::PrivateKey(cert_key.private_key);

let mut client_cfg = rustls::ClientConfig::new();
client_cfg.set_single_client_cert(certs, privkey);
client_cfg
.dangerous()
.set_certificate_verifier(Arc::new(server_attr));
.set_certificate_verifier(server_attr.clone());
client_cfg.versions.clear();
client_cfg.versions.push(rustls::ProtocolVersion::TLSv1_2);

let final_arc = Arc::new(client_cfg);

if let Ok(mut cfg_cache) = CLIENTCONFIGCACHE.try_write() {
let _ = cfg_cache.insert(cattr_hash, final_arc.clone());
// TODO: add wrapper function
if let Ok(mut cfg_cache) = CLIENT_CONFIG_CACHE.try_write() {
if cfg_cache.private_key_sha256 != cert_key.private_key_sha256 {
*cfg_cache = ClientConfigCache {
private_key_sha256: cert_key.private_key_sha256,
target_configs: HashMap::new(),
}
}

let _ = cfg_cache
.target_configs
.insert(server_attr, final_arc.clone());
}

final_arc
}

#[cfg(feature = "mesalock_sgx")]
pub(crate) fn get_tls_config(server_attr: EnclaveAttr) -> Arc<rustls::ClientConfig> {
use super::calc_hash;
use crate::rpc::sgx::ra::get_ra_cert;

// To re-use existing TLS cache, we need to first check if the server has
// updated his RA cert
let (cert_key, invalidate_cache) = get_ra_cert();

// calc_hash generates a u64 for (EnclaveAttr, CertKeyPair)
// According to the below code, as long as cert_key is unchanged,
// the `client_cfg` would not change, because it only take two
// parameters: EnclaveAttr, and CertKeyPair
let stat_hash: u64 = calc_hash(&server_attr, &cert_key);

if !invalidate_cache {
if let Ok(cfg_cache) = CLIENTCONFIGCACHE.try_read() {
if let Some(cfg) = cfg_cache.get(&stat_hash) {
return cfg.clone();
}
}
} else {
match CLIENTCONFIGCACHE.write() {
Ok(mut cfg_cache) => {
info!("CLIENTCONFIGCACHE invalidate all config cache!");
cfg_cache.clear();
}
Err(_) => {
// Poisoned
// I don't think we should panic here.
error!("CLIENTCONFIGCACHE invalidate cache failed!");
}
#[cfg(not(feature = "mesalock_sgx"))]
pub(crate) fn get_tls_config(server_attr: Arc<EnclaveAttr>) -> Arc<rustls::ClientConfig> {
// We believe a client from untrusted side do not change his tls cert
// during single execution.
if let Ok(cfg_cache) = CLIENT_CONFIG_CACHE.try_read() {
if let Some(cfg) = cfg_cache.target_configs.get(&server_attr) {
return cfg.clone();
}
}

let mut certs = std::vec::Vec::new();
certs.push(rustls::Certificate(cert_key.cert));
let privkey = rustls::PrivateKey(cert_key.private_key);

let mut client_cfg = rustls::ClientConfig::new();
client_cfg.set_single_client_cert(certs, privkey);

client_cfg
.dangerous()
.set_certificate_verifier(Arc::new(server_attr));
.set_certificate_verifier(server_attr.clone());
client_cfg.versions.clear();
client_cfg.versions.push(rustls::ProtocolVersion::TLSv1_2);

let final_arc = Arc::new(client_cfg);

if let Ok(mut cfg_cache) = CLIENTCONFIGCACHE.try_write() {
let _ = cfg_cache.insert(stat_hash, final_arc.clone());
if let Ok(mut cfg_cache) = CLIENT_CONFIG_CACHE.try_write() {
let _ = cfg_cache
.target_configs
.insert(server_attr, final_arc.clone());
}

final_arc
@@ -25,6 +25,8 @@ use std::hash::{Hash, Hasher};
use std::io::{self, Read, Write};
use std::marker::PhantomData;
use std::net::TcpStream;
use std::sync::Arc;

#[cfg(feature = "mesalock_sgx")]
use std::prelude::v1::*;

@@ -82,24 +84,7 @@ impl Hash for EnclaveAttr {
}
}

#[cfg(feature = "mesalock_sgx")]
pub(crate) fn calc_hash(ea: &EnclaveAttr, crp: &ra::CertKeyPair) -> u64 {
use std::collections::hash_map::DefaultHasher;
let mut s = DefaultHasher::new();
ea.hash(&mut s);
crp.hash(&mut s);
s.finish()
}

impl EnclaveAttr {
#[cfg(not(feature = "mesalock_sgx"))]
fn calculate_hash(&self) -> u64 {
use std::collections::hash_map::DefaultHasher;
let mut s = DefaultHasher::new();
self.hash(&mut s);
s.finish()
}

fn check_in_cert_quote(&self, cert_der: &[u8]) -> bool {
if cfg!(sgx_sim) {
return true;
@@ -279,7 +264,7 @@ where
{
type Config = PipeClientConfig;
fn open(config: Self::Config) -> Result<Self> {
let rustls_client_cfg = client::get_tls_config(config.server_attr);
let rustls_client_cfg = client::get_tls_config(Arc::new(config.server_attr));
let sess = rustls::ClientSession::new(&rustls_client_cfg, config.hostname.as_ref());

Ok(PipeClient {

0 comments on commit ead453f

Please sign in to comment.
You can’t perform that action at this time.