upgrade ratls to latest

This commit is contained in:
Valentyn Faychuk 2024-08-20 16:08:33 +02:00
parent 682d8ddd6e
commit e36329c4be
Signed by: valy
GPG Key ID: F1AB995E20FEADC5
8 changed files with 220 additions and 153 deletions

@ -1,31 +1,28 @@
# Copyright (c) 2024 DeTEE, LLC.
# All rights reserved.
[package] [package]
name = "occlum-ratls" name = "occlum-ratls"
version = "0.4.5" version = "0.1.0"
edition = "2021" edition = "2021"
authors = ["Ivan Chirkin <chirkin.ivan@gmail.com>"] authors = ["Valentyn Faychuk <faitchouk.valentyn@gmail.com>", "Ivan Chirkin <chirkin.ivan@gmail.com>"]
description = "Lib for remote attestation between occlum instances" description = "Remote attestation for Intel SGX"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
repository = "https://github.com/aggregion/occlum-ratls"
keywords = ["occlum", "rustls", "ratls"] keywords = ["occlum", "rustls", "ratls"]
# Inspired by https://github.com/aggregion/occlum-ratls
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
x509-parser = "0.15.0" rustls = "0.23"
#rustls = { version = "0.21", features = [ x509-parser = "0.16"
rustls = { version = "0.20.9", features = [ occlum-sgx = "0.1" # get/verify quote
"dangerous_configuration", ring = "0.17" # hash256
"logging" rcgen = "0.13"
] } log = "0.4"
log = "0.4.17"
rcgen = "0.12.1"
occlum-sgx = "^0.1.12"
ring = "0.17.8"
hex = "0.4" hex = "0.4"
[dependencies.actix-web] [dependencies.actix-web]
version = "4.3.1" version = "4.3"
features = ["rustls-0_20"] features = ["rustls-0_23"]
optional = true optional = true
[dependencies.actix-http] [dependencies.actix-http]
@ -38,13 +35,13 @@ version = "2"
optional = true optional = true
[dependencies.reqwest] [dependencies.reqwest]
version = "=0.11.10" version = "0.12"
default-features = false default-features = false
features = ["__rustls"] features = ["__rustls"]
optional = true optional = true
[dev-dependencies.env_logger] [dev-dependencies.env_logger]
version = "0.10.0" version = "0.11"
[dev-dependencies.tokio] [dev-dependencies.tokio]
version = "1" version = "1"

@ -4,40 +4,76 @@ use crate::{
racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder}, racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder},
RaTlsConfig, RaTlsConfigBuilder, RaTlsError, RaTlsConfig, RaTlsConfigBuilder, RaTlsError,
}; };
use rustls::client::danger::HandshakeSignatureValid;
use rustls::crypto::{aws_lc_rs, verify_tls12_signature, verify_tls13_signature, CryptoProvider};
use rustls::pki_types::{CertificateDer, ServerName, UnixTime};
use rustls::{ use rustls::{
client::{ResolvesClientCert, ServerCertVerified, ServerCertVerifier}, client::{danger::ServerCertVerified, danger::ServerCertVerifier, ResolvesClientCert},
sign::CertifiedKey, sign::CertifiedKey,
ClientConfig, ClientConfig, DigitallySignedStruct, Error, SignatureScheme,
}; };
#[derive(Debug)]
pub struct RaTlsServerCertVerifier { pub struct RaTlsServerCertVerifier {
config: RaTlsConfig, config: RaTlsConfig,
provider: CryptoProvider,
} }
impl RaTlsServerCertVerifier { impl RaTlsServerCertVerifier {
pub fn new(config: RaTlsConfig) -> Self { pub fn new(config: RaTlsConfig) -> Self {
Self { config } Self {
config,
provider: aws_lc_rs::default_provider(), // FIPS certified provider
}
} }
} }
impl ServerCertVerifier for RaTlsServerCertVerifier { impl ServerCertVerifier for RaTlsServerCertVerifier {
fn verify_server_cert( fn verify_server_cert(
&self, &self,
end_entity: &rustls::Certificate, end_entity: &CertificateDer,
_intermediates: &[rustls::Certificate], _intermediates: &[CertificateDer],
_server_name: &rustls::ServerName, _server_name: &ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8], _ocsp_response: &[u8],
_now: std::time::SystemTime, _now: UnixTime,
) -> Result<ServerCertVerified, rustls::Error> { ) -> Result<ServerCertVerified, Error> {
end_entity end_entity
.verify_quote(&self.config) .verify_quote(&self.config)
.map_err(|e| rustls::Error::General(e.to_string()))?; .map_err(|e| Error::General(e.to_string()))?;
Ok(ServerCertVerified::assertion()) Ok(ServerCertVerified::assertion())
} }
// TLS 1.2 signature verification from the AWS libcrypto
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
let supported_schemes = self.provider.signature_verification_algorithms;
verify_tls12_signature(message, cert, dss, &supported_schemes)
}
// TLS 1.3 signature verification from the AWS libcrypto
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
let supported_schemes = self.provider.signature_verification_algorithms;
verify_tls13_signature(message, cert, dss, &supported_schemes)
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
self.provider
.signature_verification_algorithms
.supported_schemes()
}
} }
#[derive(Debug)]
pub struct RaTlsClientCertResolver { pub struct RaTlsClientCertResolver {
cert: Arc<CertifiedKey>, cert: Arc<CertifiedKey>,
} }
@ -67,7 +103,7 @@ impl ResolvesClientCert for RaTlsClientCertResolver {
impl RaTlsConfigBuilder<ClientConfig> for ClientConfig { impl RaTlsConfigBuilder<ClientConfig> for ClientConfig {
fn from_ratls_config(config: RaTlsConfig) -> Result<Self, RaTlsError> { fn from_ratls_config(config: RaTlsConfig) -> Result<Self, RaTlsError> {
Ok(Self::builder() Ok(Self::builder()
.with_safe_defaults() .dangerous()
.with_custom_certificate_verifier(Arc::new(RaTlsServerCertVerifier::new(config))) .with_custom_certificate_verifier(Arc::new(RaTlsServerCertVerifier::new(config)))
.with_client_cert_resolver(Arc::new(RaTlsClientCertResolver::new()?))) .with_client_cert_resolver(Arc::new(RaTlsClientCertResolver::new()?)))
} }

@ -3,17 +3,19 @@ use crate::{RaTlsConfigBuilder, RaTlsError};
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
use occlum_sgx::SGXQuote; use occlum_sgx::SGXQuote;
// FIXME: this only suppresses the warnings
#[allow(unused_imports)]
pub use occlum_sgx::SGXMeasurement; pub use occlum_sgx::SGXMeasurement;
use rustls::{ClientConfig, ServerConfig}; use rustls::{ClientConfig, ServerConfig};
#[derive(Default)] #[derive(Default, Debug)]
pub struct RaTlsConfig { pub struct RaTlsConfig {
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
pub(crate) allowed_instances: Vec<InstanceMeasurement>, pub(crate) allowed_instances: Vec<InstanceMeasurement>,
} }
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
#[derive(Default, Clone)] #[derive(Default, Debug, Clone)]
pub struct InstanceMeasurement { pub struct InstanceMeasurement {
pub(crate) mrsigners: Option<Vec<SGXMeasurement>>, pub(crate) mrsigners: Option<Vec<SGXMeasurement>>,
pub(crate) mrenclaves: Option<Vec<SGXMeasurement>>, pub(crate) mrenclaves: Option<Vec<SGXMeasurement>>,

@ -40,9 +40,8 @@ where
addr: A, addr: A,
config: RaTlsConfig, config: RaTlsConfig,
) -> Result<Self, std::io::Error> { ) -> Result<Self, std::io::Error> {
let config = ServerConfig::from_ratls_config(config).map_err(|e| let config = ServerConfig::from_ratls_config(config)
std::io::Error::new(std::io::ErrorKind::Other, format!("{}", e)) .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("{}", e)))?;
)?; self.bind_rustls_0_23(addr, config)
self.bind_rustls(addr, config)
} }
} }

@ -7,14 +7,10 @@ use log::error;
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
use occlum_sgx::SGXQuote; use occlum_sgx::SGXQuote;
use rustls::{ use rcgen::{CertificateParams, CustomExtension, DistinguishedName, KeyPair};
sign::{any_supported_type, CertifiedKey}, use rustls::crypto::aws_lc_rs::sign::any_supported_type;
Certificate, PrivateKey, use rustls::pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer};
}; use rustls::{pki_types::CertificateDer, sign::CertifiedKey};
use rcgen::{
Certificate as GenCertificate, CertificateParams, CustomExtension, DistinguishedName, KeyPair,
};
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
use x509_parser::{nom::Parser, oid_registry::Oid, prelude::X509CertificateParser, public_key}; use x509_parser::{nom::Parser, oid_registry::Oid, prelude::X509CertificateParser, public_key};
@ -55,27 +51,21 @@ impl RaTlsCertificateBuilder {
fn build_internal(&self) -> Result<RaTlsCertifiedKey, Box<dyn Error>> { fn build_internal(&self) -> Result<RaTlsCertifiedKey, Box<dyn Error>> {
let mut distinguished_name = DistinguishedName::new(); let mut distinguished_name = DistinguishedName::new();
distinguished_name.push(rcgen::DnType::CommonName, self.common_name.clone()); distinguished_name.push(rcgen::DnType::CommonName, self.common_name.clone());
distinguished_name.push(rcgen::DnType::CountryName, "US"); distinguished_name.push(rcgen::DnType::CountryName, "EU");
distinguished_name.push(rcgen::DnType::OrganizationName, "DeTEE"); distinguished_name.push(rcgen::DnType::OrganizationName, "DeTEE");
let mut params = CertificateParams::default(); let key_pair = KeyPair::generate()?;
let key_pair = KeyPair::generate(params.alg)?;
let quote = self.get_quote(&key_pair)?; let quote = self.get_quote(&key_pair)?;
params.key_pair = Some(key_pair); let mut params = CertificateParams::default();
params.distinguished_name = distinguished_name; params.distinguished_name = distinguished_name;
params.custom_extensions = vec![CustomExtension::from_oid_content(&REPORT_OID, quote)]; params.custom_extensions = vec![CustomExtension::from_oid_content(&REPORT_OID, quote)];
let crt = params.self_signed(&key_pair)?;
let crt = GenCertificate::from_params(params)?; let cert_der = crt.der().to_vec();
let key_der = key_pair.serialize_der();
Ok(RaTlsCertifiedKey { Ok(RaTlsCertifiedKey { cert_der, key_der })
cert_der: crt.serialize_der()?,
key_der: crt.serialize_private_key_der(),
})
} }
#[cfg(not(feature = "occlum"))] #[cfg(not(feature = "occlum"))]
@ -95,17 +85,23 @@ impl RaTlsCertificateBuilder {
impl CertificateBuilder for RaTlsCertificateBuilder { impl CertificateBuilder for RaTlsCertificateBuilder {
fn build(&self) -> Result<CertifiedKey, RaTlsError> { fn build(&self) -> Result<CertifiedKey, RaTlsError> {
self.build_internal() let cert_key = self.build_internal().map_err(|e| {
.map(|k| { let err = RaTlsError::CertificateBuildError(e.to_string());
let sign_key = any_supported_type(&PrivateKey(k.key_der)).unwrap(); error!("{}", err);
err
})?;
CertifiedKey::new(vec![Certificate(k.cert_der)], sign_key) let private_key_der = PrivateKeyDer::from(PrivatePkcs8KeyDer::from(cert_key.key_der));
}) let signing_key = any_supported_type(&private_key_der).map_err(|e| {
.map_err(|e| { let err = RaTlsError::CertificateBuildError(e.to_string());
let err = RaTlsError::CertificateBuildError(e.to_string()); error!("{}", err);
error!("{}", err); err
err })?;
})
Ok(CertifiedKey::new(
vec![CertificateDer::from(cert_key.cert_der)],
signing_key,
))
} }
} }
@ -113,7 +109,7 @@ pub trait RaTlsCertificate {
fn verify_quote(&self, config: &RaTlsConfig) -> Result<(), Box<dyn Error>>; fn verify_quote(&self, config: &RaTlsConfig) -> Result<(), Box<dyn Error>>;
} }
impl RaTlsCertificate for rustls::Certificate { impl RaTlsCertificate for CertificateDer<'_> {
#[cfg(not(feature = "occlum"))] #[cfg(not(feature = "occlum"))]
fn verify_quote(&self, _: &RaTlsConfig) -> Result<(), Box<dyn Error>> { fn verify_quote(&self, _: &RaTlsConfig) -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())
@ -151,4 +147,4 @@ impl RaTlsCertificate for rustls::Certificate {
Err("Not found quote extension".into()) Err("Not found quote extension".into())
} }
} }
} }

@ -1,41 +1,81 @@
use rustls::{server::{ClientCertVerified, ClientCertVerifier, ResolvesServerCert}, sign::CertifiedKey, Certificate, Error, ServerConfig, DistinguishedNames};
use std::{sync::Arc, time::SystemTime};
use crate::{ use crate::{
racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder}, racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder},
RaTlsConfig, RaTlsConfigBuilder, RaTlsError, RaTlsConfig, RaTlsConfigBuilder, RaTlsError,
}; };
use rustls::client::danger::HandshakeSignatureValid;
use rustls::crypto::{aws_lc_rs, verify_tls12_signature, verify_tls13_signature, CryptoProvider};
use rustls::pki_types::{CertificateDer, UnixTime};
use rustls::{
server::{danger::ClientCertVerified, danger::ClientCertVerifier, ResolvesServerCert},
sign::CertifiedKey,
DigitallySignedStruct, DistinguishedName, Error, ServerConfig, SignatureScheme,
};
use std::sync::Arc;
#[derive(Debug)]
pub struct RaTlsClientCertVerifier { pub struct RaTlsClientCertVerifier {
config: RaTlsConfig, config: RaTlsConfig,
provider: CryptoProvider,
} }
impl RaTlsClientCertVerifier { impl RaTlsClientCertVerifier {
pub fn new(config: RaTlsConfig) -> Self { pub fn new(config: RaTlsConfig) -> Self {
Self { config } Self {
config,
provider: aws_lc_rs::default_provider(), // FIPS certified provider
}
} }
} }
impl ClientCertVerifier for RaTlsClientCertVerifier { impl ClientCertVerifier for RaTlsClientCertVerifier {
fn root_hint_subjects(&self) -> &[DistinguishedName] {
&[] // TODO: check if any names are needed
}
fn verify_client_cert( fn verify_client_cert(
&self, &self,
end_entity: &Certificate, end_entity: &CertificateDer,
_intermediates: &[Certificate], _intermediates: &[CertificateDer],
_now: SystemTime, _now: UnixTime,
) -> Result<ClientCertVerified, Error> { ) -> Result<ClientCertVerified, Error> {
end_entity.verify_quote(&self.config).map_err(|e| { end_entity.verify_quote(&self.config).map_err(|e| {
println!("{:?}", e); log::log!(log::Level::Error, "{}", e);
rustls::Error::General(e.to_string()) Error::General(e.to_string())
})?; })?;
Ok(ClientCertVerified::assertion()) Ok(ClientCertVerified::assertion())
} }
fn client_auth_root_subjects(&self) -> Option<DistinguishedNames> { // TLS 1.2 signature verification from the AWS libcrypto
Some(DistinguishedNames::new()) fn verify_tls12_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
let supported_schemes = self.provider.signature_verification_algorithms;
verify_tls12_signature(message, cert, dss, &supported_schemes)
}
// TLS 1.3 signature verification from the AWS libcrypto
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
let supported_schemes = self.provider.signature_verification_algorithms;
verify_tls13_signature(message, cert, dss, &supported_schemes)
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
self.provider
.signature_verification_algorithms
.supported_schemes()
} }
} }
#[derive(Debug)]
pub struct RaTlsServerCertResolver { pub struct RaTlsServerCertResolver {
cert: Arc<CertifiedKey>, cert: Arc<CertifiedKey>,
} }
@ -49,10 +89,7 @@ impl RaTlsServerCertResolver {
} }
impl ResolvesServerCert for RaTlsServerCertResolver { impl ResolvesServerCert for RaTlsServerCertResolver {
fn resolve( fn resolve(&self, _client_hello: rustls::server::ClientHello) -> Option<Arc<CertifiedKey>> {
&self,
_client_hello: rustls::server::ClientHello,
) -> Option<std::sync::Arc<CertifiedKey>> {
Some(self.cert.clone()) Some(self.cert.clone())
} }
} }
@ -60,7 +97,6 @@ impl ResolvesServerCert for RaTlsServerCertResolver {
impl RaTlsConfigBuilder<ServerConfig> for ServerConfig { impl RaTlsConfigBuilder<ServerConfig> for ServerConfig {
fn from_ratls_config(config: RaTlsConfig) -> Result<Self, RaTlsError> { fn from_ratls_config(config: RaTlsConfig) -> Result<Self, RaTlsError> {
Ok(Self::builder() Ok(Self::builder()
.with_safe_defaults()
.with_client_cert_verifier(Arc::new(RaTlsClientCertVerifier::new(config))) .with_client_cert_verifier(Arc::new(RaTlsClientCertVerifier::new(config)))
.with_cert_resolver(Arc::new(RaTlsServerCertResolver::new()?))) .with_cert_resolver(Arc::new(RaTlsServerCertResolver::new()?)))
} }

@ -1,67 +1,67 @@
use rustls::{server::{ClientCertVerified, ClientCertVerifier, ResolvesServerCert}, sign::CertifiedKey, Certificate, Error, ServerConfig, DistinguishedNames}; // use rustls::{server::{ClientCertVerified, ClientCertVerifier, ResolvesServerCert}, sign::CertifiedKey, Certificate, Error, ServerConfig, DistinguishedNames};
use std::{sync::Arc, time::SystemTime}; // use std::{sync::Arc, time::SystemTime};
//
use crate::{ // use crate::{
racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder}, // racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder},
RaTlsConfig, RaTlsConfigBuilder, RaTlsError, // RaTlsConfig, RaTlsConfigBuilder, RaTlsError,
}; // };
//
pub struct RaTlsClientCertVerifier { // pub struct RaTlsClientCertVerifier {
config: RaTlsConfig, // config: RaTlsConfig,
} // }
//
impl RaTlsClientCertVerifier { // impl RaTlsClientCertVerifier {
pub fn new(config: RaTlsConfig) -> Self { // pub fn new(config: RaTlsConfig) -> Self {
Self { config } // Self { config }
} // }
} // }
//
impl ClientCertVerifier for RaTlsClientCertVerifier { // impl ClientCertVerifier for RaTlsClientCertVerifier {
fn verify_client_cert( // fn verify_client_cert(
&self, // &self,
end_entity: &Certificate, // end_entity: &Certificate,
_intermediates: &[Certificate], // _intermediates: &[Certificate],
_now: SystemTime, // _now: SystemTime,
) -> Result<ClientCertVerified, Error> { // ) -> Result<ClientCertVerified, Error> {
end_entity.verify_quote(&self.config).map_err(|e| { // end_entity.verify_quote(&self.config).map_err(|e| {
println!("{:?}", e); // println!("{:?}", e);
rustls::Error::General(e.to_string()) // rustls::Error::General(e.to_string())
})?; // })?;
//
Ok(ClientCertVerified::assertion()) // Ok(ClientCertVerified::assertion())
} // }
//
fn client_auth_root_subjects(&self) -> Option<DistinguishedNames> { // fn client_auth_root_subjects(&self) -> Option<DistinguishedNames> {
Some(DistinguishedNames::new()) // Some(DistinguishedNames::new())
} // }
} // }
//
pub struct RaTlsServerCertResolver { // pub struct RaTlsServerCertResolver {
cert: Arc<CertifiedKey>, // cert: Arc<CertifiedKey>,
} // }
//
impl RaTlsServerCertResolver { // impl RaTlsServerCertResolver {
pub fn new() -> Result<Self, RaTlsError> { // pub fn new() -> Result<Self, RaTlsError> {
let builder = RaTlsCertificateBuilder::new().with_common_name("Client".to_string()); // let builder = RaTlsCertificateBuilder::new().with_common_name("Client".to_string());
let cert = builder.build().map(Arc::new)?; // let cert = builder.build().map(Arc::new)?;
Ok(Self { cert }) // Ok(Self { cert })
} // }
} // }
//
impl ResolvesServerCert for RaTlsServerCertResolver { // impl ResolvesServerCert for RaTlsServerCertResolver {
fn resolve( // fn resolve(
&self, // &self,
_client_hello: rustls::server::ClientHello, // _client_hello: rustls::server::ClientHello,
) -> Option<std::sync::Arc<CertifiedKey>> { // ) -> Option<std::sync::Arc<CertifiedKey>> {
Some(self.cert.clone()) // Some(self.cert.clone())
} // }
} // }
//
impl RaTlsConfigBuilder<ServerConfig> for ServerConfig { // impl RaTlsConfigBuilder<ServerConfig> for ServerConfig {
fn from_ratls_config(config: RaTlsConfig) -> Result<Self, RaTlsError> { // fn from_ratls_config(config: RaTlsConfig) -> Result<Self, RaTlsError> {
Ok(Self::builder() // Ok(Self::builder()
.with_safe_defaults() // .with_safe_defaults()
.with_client_cert_verifier(Arc::new(RaTlsClientCertVerifier::new(config))) // .with_client_cert_verifier(Arc::new(RaTlsClientCertVerifier::new(config)))
.with_cert_resolver(Arc::new(RaTlsServerCertResolver::new()?))) // .with_cert_resolver(Arc::new(RaTlsServerCertResolver::new()?)))
} // }
} // }

@ -1,5 +1,6 @@
use ring::digest::{Context, SHA512}; use ring::digest::{Context, SHA512};
// TODO: make sure this function is correct
pub fn hash_sha512(input: Vec<u8>) -> [u8; 64] { pub fn hash_sha512(input: Vec<u8>) -> [u8; 64] {
let mut context = Context::new(&SHA512); let mut context = Context::new(&SHA512);
context.update(input.as_ref()); context.update(input.as_ref());