Skip to content

Commit

Permalink
Revert "feat(s2n-quic-rustls): update rustls from 0.21 to 0.23 (#2143)…
Browse files Browse the repository at this point in the history
…" (#2174)

* Revert "feat(s2n-quic-rustls): update rustls from 0.21 to 0.23 (#2143)"

This reverts commit 15f234c.

* parse ec keys

---------

Co-authored-by: Apoorv Kothari <[email protected]>
  • Loading branch information
camshaft and toidiu authored Apr 5, 2024
1 parent 52ec5a2 commit 343fa0d
Show file tree
Hide file tree
Showing 12 changed files with 165 additions and 324 deletions.
2 changes: 1 addition & 1 deletion examples/rustls-mtls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authors = ["Rick Richardson <[email protected]>", "AWS s2n"]
[dependencies]
# Remove the `provider-tls-default` feature and add `provider-tls-rustls` in order to use the rustls backend
s2n-quic = { version = "1", path = "../../quic/s2n-quic", default-features = false, features = ["provider-address-token-default", "provider-tls-rustls", "provider-event-tracing"] }
rustls-pemfile = "2"
rustls-pemfile = "1"
tokio = { version = "1", features = ["full"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["ansi"] }
Expand Down
151 changes: 68 additions & 83 deletions examples/rustls-mtls/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use s2n_quic::provider::tls::{
self as s2n_quic_tls_provider,
rustls::rustls::{
// types from the external rustls crate
pki_types::{CertificateDer, PrivateKeyDer},
server::WebPkiClientVerifier,
Error as RustlsError,
RootCertStore,
},
use rustls::{
cipher_suite, ClientConfig, Error, RootCertStore, ServerConfig, SupportedCipherSuite,
};
use s2n_quic::provider::{tls, tls::rustls::rustls};
use std::{io::Cursor, path::Path, sync::Arc};
use tokio::{fs::File, io::AsyncReadExt};
use tracing::Level;

static PROTOCOL_VERSIONS: &[&rustls::SupportedProtocolVersion] = &[&rustls::version::TLS13];

pub static DEFAULT_CIPHERSUITES: &[SupportedCipherSuite] = &[
cipher_suite::TLS13_AES_128_GCM_SHA256,
cipher_suite::TLS13_AES_256_GCM_SHA384,
cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,
];

pub fn initialize_logger(endpoint: &str) {
use std::sync::Once;

Expand All @@ -38,26 +40,23 @@ pub fn initialize_logger(endpoint: &str) {
}

pub struct MtlsProvider {
root_store: RootCertStore,
my_cert_chain: Vec<CertificateDer<'static>>,
my_private_key: PrivateKeyDer<'static>,
root_store: rustls::RootCertStore,
my_cert_chain: Vec<rustls::Certificate>,
my_private_key: rustls::PrivateKey,
}

impl s2n_quic_tls_provider::Provider for MtlsProvider {
type Server = s2n_quic_tls_provider::rustls::Server;
type Client = s2n_quic_tls_provider::rustls::Client;
type Error = RustlsError;
impl tls::Provider for MtlsProvider {
type Server = tls::rustls::Server;
type Client = tls::rustls::Client;
type Error = rustls::Error;

fn start_server(self) -> Result<Self::Server, Self::Error> {
let default_crypto_provider = s2n_quic_tls_provider::rustls::default_crypto_provider()?;
let verifier = WebPkiClientVerifier::builder_with_provider(
Arc::new(self.root_store),
default_crypto_provider.into(),
)
.build()
.unwrap();
let mut cfg = s2n_quic_tls_provider::rustls::server_config_builder()?
.with_client_cert_verifier(verifier)
let verifier = rustls::server::AllowAnyAuthenticatedClient::new(self.root_store);
let mut cfg = ServerConfig::builder()
.with_cipher_suites(DEFAULT_CIPHERSUITES)
.with_safe_default_kx_groups()
.with_protocol_versions(PROTOCOL_VERSIONS)?
.with_client_cert_verifier(Arc::new(verifier))
.with_single_cert(self.my_cert_chain, self.my_private_key)?;

cfg.ignore_client_order = true;
Expand All @@ -67,7 +66,10 @@ impl s2n_quic_tls_provider::Provider for MtlsProvider {
}

fn start_client(self) -> Result<Self::Client, Self::Error> {
let mut cfg = s2n_quic_tls_provider::rustls::client_config_builder()?
let mut cfg = ClientConfig::builder()
.with_cipher_suites(DEFAULT_CIPHERSUITES)
.with_safe_default_kx_groups()
.with_protocol_versions(PROTOCOL_VERSIONS)?
.with_root_certificates(self.root_store)
.with_client_auth_cert(self.my_cert_chain, self.my_private_key)?;

Expand All @@ -82,88 +84,71 @@ impl MtlsProvider {
ca_cert_pem: A,
my_cert_pem: B,
my_key_pem: C,
) -> Result<Self, RustlsError> {
) -> Result<Self, Error> {
let root_store = into_root_store(ca_cert_pem.as_ref()).await?;
let cert_chain = into_certificate(my_cert_pem.as_ref()).await?;
let private_key = into_private_key(my_key_pem.as_ref()).await?;
Ok(MtlsProvider {
root_store,
my_cert_chain: cert_chain.into_iter().map(CertificateDer::from).collect(),
my_private_key: private_key,
my_cert_chain: cert_chain.into_iter().map(rustls::Certificate).collect(),
my_private_key: rustls::PrivateKey(private_key),
})
}
}

async fn read_file(path: &Path) -> Result<Vec<u8>, RustlsError> {
async fn into_certificate(path: &Path) -> Result<Vec<Vec<u8>>, Error> {
let mut f = File::open(path)
.await
.map_err(|e| RustlsError::General(format!("Failed to load file: {}", e)))?;
.map_err(|e| Error::General(format!("Failed to load file: {}", e)))?;
let mut buf = Vec::new();
f.read_to_end(&mut buf)
.await
.map_err(|e| RustlsError::General(format!("Failed to read file: {}", e)))?;
Ok(buf)
}

async fn into_certificate(path: &Path) -> Result<Vec<CertificateDer<'static>>, RustlsError> {
let buf = &read_file(path).await?;
.map_err(|e| Error::General(format!("Failed to read file: {}", e)))?;
let mut cursor = Cursor::new(buf);
rustls_pemfile::certs(&mut cursor)
.map(|cert| {
cert.map_err(|_| RustlsError::General("Could not read certificate".to_string()))
})
.collect()
let certs = rustls_pemfile::certs(&mut cursor)
.map(|certs| certs.into_iter().collect())
.map_err(|_| Error::General("Could not read certificate".to_string()))?;
Ok(certs)
}

async fn into_root_store(path: &Path) -> Result<RootCertStore, RustlsError> {
let ca_certs: Vec<CertificateDer<'static>> = into_certificate(path)
.await
.map(|certs| certs.into_iter().map(CertificateDer::from))?
.collect();
async fn into_root_store(path: &Path) -> Result<RootCertStore, Error> {
let ca_certs = into_certificate(path).await?;
let mut cert_store = RootCertStore::empty();
cert_store.add_parsable_certificates(ca_certs);
cert_store.add_parsable_certificates(ca_certs.as_slice());
Ok(cert_store)
}

async fn into_private_key(path: &Path) -> Result<PrivateKeyDer<'static>, RustlsError> {
let buf = &read_file(path).await?;
async fn into_private_key(path: &Path) -> Result<Vec<u8>, Error> {
let mut f = File::open(path)
.await
.map_err(|e| Error::General(format!("Failed to load file: {}", e)))?;
let mut buf = Vec::new();
f.read_to_end(&mut buf)
.await
.map_err(|e| Error::General(format!("Failed to read file: {}", e)))?;
let mut cursor = Cursor::new(buf);

macro_rules! parse_key {
($parser:ident, $key_type:expr) => {
cursor.set_position(0);

let keys: Result<Vec<_>, RustlsError> = rustls_pemfile::$parser(&mut cursor)
.map(|key| {
key.map_err(|_| {
RustlsError::General("Could not load any private keys".to_string())
})
})
.collect();
match keys {
// try the next parser
Err(_) => (),
// try the next parser
Ok(keys) if keys.is_empty() => (),
Ok(mut keys) if keys.len() == 1 => {
return Ok($key_type(keys.pop().unwrap()));
}
Ok(keys) => {
return Err(RustlsError::General(format!(
"Unexpected number of keys: {} (only 1 supported)",
keys.len()
)));
}
let parsers = [
rustls_pemfile::rsa_private_keys,
rustls_pemfile::pkcs8_private_keys,
];
for parser in parsers.iter() {
cursor.set_position(0);

match parser(&mut cursor) {
Ok(keys) if keys.is_empty() => continue,
Ok(mut keys) if keys.len() == 1 => return Ok(rustls::PrivateKey(keys.pop().unwrap()).0),
Ok(keys) => {
return Err(Error::General(format!(
"Unexpected number of keys: {} (only 1 supported)",
keys.len()
)));
}
};
// try the next parser
Err(_) => continue,
}
}

// attempt to parse PKCS8 encoded key. Returns early if a key is found
parse_key!(pkcs8_private_keys, PrivateKeyDer::Pkcs8);
// attempt to parse RSA key. Returns early if a key is found
parse_key!(rsa_private_keys, PrivateKeyDer::Pkcs1);

Err(RustlsError::General(
Err(Error::General(
"could not load any valid private keys".to_string(),
))
}
2 changes: 2 additions & 0 deletions quic/s2n-quic-qns/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ http = "1.0"
humansize = "2"
lru = "0.10"
rand = "0.8"
# dangerous_configuration is used to allow for cert verification to be disabled for the amplification limit interop test
rustls = { version = "0.21", features = ["dangerous_configuration", "quic"] }
s2n-codec = { path = "../../common/s2n-codec" }
s2n-quic-core = { path = "../s2n-quic-core", features = ["testing"] }
s2n-quic-h3 = { path = "../s2n-quic-h3" }
Expand Down
70 changes: 16 additions & 54 deletions quic/s2n-quic-qns/src/tls.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{tls::rustls::DisabledVerifier, Result};
use s2n_quic::provider::tls::{self as s2n_quic_tls_provider, rustls::rustls as rustls_crate};
use crate::Result;
use std::{path::PathBuf, str::FromStr};
use structopt::StructOpt;

Expand Down Expand Up @@ -114,12 +113,14 @@ impl Client {

pub fn build_rustls(&self, alpns: &[String]) -> Result<rustls::Client> {
let tls = if self.disable_cert_verification {
use rustls_crate::KeyLogFile;
use ::rustls::{version, ClientConfig, KeyLogFile};
use std::sync::Arc;

let mut config = s2n_quic_tls_provider::rustls::client_config_builder()?
.dangerous()
.with_custom_certificate_verifier(Arc::new(DisabledVerifier))
let mut config = ClientConfig::builder()
.with_cipher_suites(rustls::DEFAULT_CIPHERSUITES)
.with_safe_default_kx_groups()
.with_protocol_versions(&[&version::TLS13])?
.with_custom_certificate_verifier(Arc::new(rustls::DisabledVerifier))
.with_no_client_auth();
config.max_fragment_size = None;
config.alpn_protocols = alpns.iter().map(|p| p.as_bytes().to_vec()).collect();
Expand Down Expand Up @@ -264,13 +265,9 @@ pub mod s2n_tls {

pub mod rustls {
use super::*;
use rustls_crate::{
client::danger,
pki_types::{CertificateDer, ServerName, UnixTime},
};
pub use s2n_quic::provider::tls::rustls::{
certificate::{Certificate, IntoCertificate, IntoPrivateKey, PrivateKey},
default_crypto_provider, Client, Server,
Client, Server, DEFAULT_CIPHERSUITES,
};

pub fn ca(ca: Option<&PathBuf>) -> Result<Certificate> {
Expand All @@ -289,54 +286,19 @@ pub mod rustls {
})
}

#[derive(Debug)]
pub struct DisabledVerifier;

impl danger::ServerCertVerifier for DisabledVerifier {
impl ::rustls::client::ServerCertVerifier for DisabledVerifier {
fn verify_server_cert(
&self,
_end_entity: &CertificateDer<'_>,
_intermediates: &[CertificateDer<'_>],
_server_name: &ServerName,
_end_entity: &::rustls::Certificate,
_intermediates: &[::rustls::Certificate],
_server_name: &::rustls::ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
_now: UnixTime,
) -> Result<danger::ServerCertVerified, rustls_crate::Error> {
Ok(danger::ServerCertVerified::assertion())
}

fn verify_tls12_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &rustls_crate::DigitallySignedStruct,
) -> Result<danger::HandshakeSignatureValid, rustls_crate::Error> {
rustls_crate::crypto::verify_tls12_signature(
message,
cert,
dss,
&default_crypto_provider()?.signature_verification_algorithms,
)
}

fn verify_tls13_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &rustls_crate::DigitallySignedStruct,
) -> Result<danger::HandshakeSignatureValid, rustls_crate::Error> {
rustls_crate::crypto::verify_tls13_signature(
message,
cert,
dss,
&default_crypto_provider()?.signature_verification_algorithms,
)
}

fn supported_verify_schemes(&self) -> Vec<rustls_crate::SignatureScheme> {
default_crypto_provider()
.unwrap()
.signature_verification_algorithms
.supported_schemes()
_now: std::time::SystemTime,
) -> Result<::rustls::client::ServerCertVerified, ::rustls::Error> {
Ok(::rustls::client::ServerCertVerified::assertion())
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions quic/s2n-quic-rustls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ exclude = ["corpus.tar.gz"]

[dependencies]
bytes = { version = "1", default-features = false }
rustls = "0.23"
rustls-pemfile = "2"
rustls = { version = "0.21", features = ["quic"] }
rustls-pemfile = "1"
s2n-codec = { version = "=0.35.0", path = "../../common/s2n-codec", default-features = false, features = ["alloc"] }
s2n-quic-core = { version = "=0.35.0", path = "../s2n-quic-core", default-features = false, features = ["alloc"] }
s2n-quic-crypto = { version = "=0.35.0", path = "../s2n-quic-crypto", default-features = false }
Expand Down
Loading

0 comments on commit 343fa0d

Please sign in to comment.