| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| use anyhow::{anyhow, bail, Result}; |
| use log::debug; |
| #[cfg(feature = "mesalock_sgx")] |
| use std::prelude::v1::*; |
| #[cfg(not(feature = "mesalock_sgx"))] |
| use std::sync::RwLock; |
| #[cfg(feature = "mesalock_sgx")] |
| use std::sync::SgxRwLock as RwLock; |
| |
| use std::sync::Arc; |
| use std::time::SystemTime; |
| |
| #[cfg(feature = "mesalock_sgx")] |
| use std::untrusted::time::SystemTimeEx; |
| |
| use teaclave_attestation::report::AttestationReport; |
| use teaclave_attestation::verifier::AttestationReportVerifier; |
| use teaclave_attestation::AttestedTlsConfig; |
| use teaclave_types::EnclaveAttr; |
| |
| #[derive(Clone)] |
| pub struct SgxTrustedTlsServerConfig { |
| server_config: rustls::ServerConfig, |
| attested_tls_config: Option<Arc<RwLock<AttestedTlsConfig>>>, |
| time: std::time::SystemTime, |
| validity: std::time::Duration, |
| } |
| |
| impl Default for SgxTrustedTlsServerConfig { |
| fn default() -> Self { |
| let client_cert_verifier = rustls::NoClientAuth::new(); |
| let server_config = rustls::ServerConfig::new(client_cert_verifier); |
| let time = SystemTime::now(); |
| let validity = std::time::Duration::from_secs(u64::max_value()); |
| |
| Self { |
| server_config, |
| attested_tls_config: None, |
| time, |
| validity, |
| } |
| } |
| } |
| |
| impl SgxTrustedTlsServerConfig { |
| pub fn new() -> Self { |
| Self::default() |
| } |
| |
| pub fn server_cert(mut self, cert: &[u8], key_der: &[u8]) -> Result<Self> { |
| let cert_chain = vec![rustls::Certificate(cert.to_vec())]; |
| let key_der = rustls::PrivateKey(key_der.to_vec()); |
| self.server_config.set_single_cert(cert_chain, key_der)?; |
| |
| Ok(Self { ..self }) |
| } |
| |
| pub fn from_attested_tls_config( |
| attested_tls_config: Arc<RwLock<AttestedTlsConfig>>, |
| ) -> Result<Self> { |
| let lock = attested_tls_config.clone(); |
| let tls_config = lock.read().map_err(|_| anyhow!("lock error"))?; |
| let mut config = Self::new().server_cert(&tls_config.cert, &tls_config.private_key)?; |
| config.attested_tls_config = Some(attested_tls_config); |
| config.time = tls_config.time; |
| config.validity = tls_config.validity; |
| Ok(config) |
| } |
| |
| // Disable this function for non-SGX targets. |
| #[cfg(feature = "mesalock_sgx")] |
| pub fn attestation_report_verifier( |
| mut self, |
| accepted_enclave_attrs: Vec<EnclaveAttr>, |
| root_ca: &[u8], |
| verifier: fn(&AttestationReport) -> bool, |
| ) -> Result<Self> { |
| let verifier = Arc::new(AttestationReportVerifier::new( |
| accepted_enclave_attrs, |
| root_ca, |
| verifier, |
| )); |
| |
| self.server_config.set_client_certificate_verifier(verifier); |
| Ok(Self { ..self }) |
| } |
| |
| pub fn server_config(&self) -> Arc<rustls::ServerConfig> { |
| Arc::new(self.server_config.clone()) |
| } |
| |
| pub fn need_refresh(&self) -> bool { |
| let current_time = SystemTime::now(); |
| let elapsed_time = current_time |
| .duration_since(self.time) |
| .unwrap_or(self.validity); |
| debug!( |
| "current_time: {:?}, self.time: {:?}, elapsed time: {:?}, self.validity: {:?}", |
| current_time, self.time, elapsed_time, self.validity |
| ); |
| |
| elapsed_time >= self.validity |
| } |
| |
| pub fn refresh_server_config(&mut self) -> Result<()> { |
| let lock = match &self.attested_tls_config { |
| Some(config) => config, |
| None => bail!("Attestation TLS Config is not set"), |
| }; |
| let attested_tls_config = lock.read().map_err(|_| anyhow!("lock error"))?; |
| let cert_chain = vec![rustls::Certificate(attested_tls_config.cert.to_vec())]; |
| let key_der = rustls::PrivateKey(attested_tls_config.private_key.to_vec()); |
| |
| let mut new_server_config = self.server_config.clone(); |
| new_server_config.set_single_cert(cert_chain, key_der)?; |
| |
| self.server_config = new_server_config; |
| self.time = attested_tls_config.time; |
| self.validity = attested_tls_config.validity; |
| |
| Ok(()) |
| } |
| } |
| |
| pub struct SgxTrustedTlsClientConfig { |
| pub client_config: rustls::ClientConfig, |
| pub attested_tls_config: Option<Arc<RwLock<AttestedTlsConfig>>>, |
| pub validity: std::time::Duration, |
| } |
| |
| struct NoServerAuth; |
| |
| impl NoServerAuth { |
| // Allow new_ret_no_self, make it consistent with rustls definition of |
| // `NoClientAuth::new()`. |
| #[allow(clippy::new_ret_no_self)] |
| pub fn new() -> Arc<dyn rustls::ServerCertVerifier> { |
| Arc::new(NoServerAuth) |
| } |
| } |
| |
| impl rustls::ServerCertVerifier for NoServerAuth { |
| fn verify_server_cert( |
| &self, |
| _roots: &rustls::RootCertStore, |
| _certs: &[rustls::Certificate], |
| _hostname: webpki::DNSNameRef<'_>, |
| _ocsp: &[u8], |
| ) -> Result<rustls::ServerCertVerified, rustls::TLSError> { |
| Ok(rustls::ServerCertVerified::assertion()) |
| } |
| } |
| |
| impl Default for SgxTrustedTlsClientConfig { |
| fn default() -> Self { |
| let mut client_config = rustls::ClientConfig::new(); |
| |
| client_config |
| .dangerous() |
| .set_certificate_verifier(NoServerAuth::new()); |
| client_config.versions.clear(); |
| client_config |
| .versions |
| .push(rustls::ProtocolVersion::TLSv1_2); |
| |
| Self { |
| client_config, |
| attested_tls_config: None, |
| validity: std::time::Duration::default(), |
| } |
| } |
| } |
| |
| impl SgxTrustedTlsClientConfig { |
| pub fn new() -> Self { |
| Self::default() |
| } |
| |
| pub fn attestation_report_verifier( |
| mut self, |
| accepted_enclave_attrs: Vec<EnclaveAttr>, |
| root_ca: &[u8], |
| verifier: fn(&AttestationReport) -> bool, |
| ) -> Self { |
| let verifier = Arc::new(AttestationReportVerifier::new( |
| accepted_enclave_attrs, |
| root_ca, |
| verifier, |
| )); |
| self.client_config |
| .dangerous() |
| .set_certificate_verifier(verifier); |
| |
| Self { ..self } |
| } |
| |
| pub fn client_cert(mut self, cert: &[u8], key_der: &[u8]) -> Self { |
| let cert_chain = vec![rustls::Certificate(cert.to_vec())]; |
| let key_der = rustls::PrivateKey(key_der.to_vec()); |
| self.client_config |
| .set_single_client_cert(cert_chain, key_der); |
| |
| Self { ..self } |
| } |
| |
| pub fn from_attested_tls_config( |
| attested_tls_config: Arc<RwLock<AttestedTlsConfig>>, |
| ) -> Result<Self> { |
| let lock = attested_tls_config.clone(); |
| let tls_config = lock.read().map_err(|_| anyhow!("lock error"))?; |
| let mut config = Self::new().client_cert(&tls_config.cert, &tls_config.private_key); |
| config.attested_tls_config = Some(attested_tls_config); |
| Ok(config) |
| } |
| } |