Skip to content

Commit

Permalink
Only permit X25519 based QUIC-TLS key exchanges
Browse files Browse the repository at this point in the history
  • Loading branch information
riptl committed Dec 5, 2024
1 parent eb40511 commit acc6022
Show file tree
Hide file tree
Showing 12 changed files with 60 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ reqwest = { version = "0.11.27", default-features = false }
reqwest-middleware = "0.2.5"
rolling-file = "0.2.0"
rpassword = "7.3"
rustls = { version = "0.23.19", default-features = false }
rustls = { version = "0.23.19", features = ["std"], default-features = false }
scopeguard = "1.2.0"
semver = "1.0.23"
seqlock = "0.2.0"
Expand Down
11 changes: 3 additions & 8 deletions core/src/repair/quic_endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use {
solana_runtime::bank_forks::BankForks,
solana_sdk::{pubkey::Pubkey, signature::Keypair},
solana_tls_utils::{
new_dummy_x509_certificate, SkipClientVerification, SkipServerVerification,
new_dummy_x509_certificate, tls_client_config_builder, tls_server_config_builder,
},
std::{
cmp::Reverse,
Expand Down Expand Up @@ -300,9 +300,7 @@ fn new_server_config(
cert: CertificateDer<'static>,
key: PrivateKeyDer<'static>,
) -> Result<ServerConfig, rustls::Error> {
let mut config = rustls::ServerConfig::builder()
.with_client_cert_verifier(SkipClientVerification::new())
.with_single_cert(vec![cert], key)?;
let mut config = tls_server_config_builder().with_single_cert(vec![cert], key)?;
config.alpn_protocols = vec![ALPN_REPAIR_PROTOCOL_ID.to_vec()];
config.key_log = Arc::new(KeyLogFile::new());
let Ok(config) = QuicServerConfig::try_from(config) else {
Expand All @@ -321,10 +319,7 @@ fn new_client_config(
cert: CertificateDer<'static>,
key: PrivateKeyDer<'static>,
) -> Result<ClientConfig, rustls::Error> {
let mut config = rustls::ClientConfig::builder()
.dangerous()
.with_custom_certificate_verifier(SkipServerVerification::new())
.with_client_auth_cert(vec![cert], key)?;
let mut config = tls_client_config_builder().with_client_auth_cert(vec![cert], key)?;
config.enable_early_data = true;
config.alpn_protocols = vec![ALPN_REPAIR_PROTOCOL_ID.to_vec()];
let mut config = ClientConfig::new(Arc::new(QuicClientConfig::try_from(config).unwrap()));
Expand Down
8 changes: 4 additions & 4 deletions quic-client/src/nonblocking/quic_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ use {
},
solana_rpc_client_api::client_error::ErrorKind as ClientErrorKind,
solana_streamer::nonblocking::quic::ALPN_TPU_PROTOCOL_ID,
solana_tls_utils::{new_dummy_x509_certificate, QuicClientCertificate, SkipServerVerification},
solana_tls_utils::{
new_dummy_x509_certificate, tls_client_config_builder, QuicClientCertificate,
},
solana_transaction_error::TransportResult,
std::{
net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket},
Expand Down Expand Up @@ -85,9 +87,7 @@ impl QuicLazyInitializedEndpoint {
QuicNewConnection::create_endpoint(EndpointConfig::default(), client_socket)
};

let mut crypto = rustls::ClientConfig::builder()
.dangerous()
.with_custom_certificate_verifier(SkipServerVerification::new())
let mut crypto = tls_client_config_builder()
.with_client_auth_cert(
vec![self.client_certificate.certificate.clone()],
self.client_certificate.key.clone_key(),
Expand Down
6 changes: 2 additions & 4 deletions streamer/src/nonblocking/testing_utilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use {
solana_net_utils::bind_to_localhost,
solana_perf::packet::PacketBatch,
solana_quic_definitions::{QUIC_KEEP_ALIVE, QUIC_MAX_TIMEOUT},
solana_tls_utils::{new_dummy_x509_certificate, SkipServerVerification},
solana_tls_utils::{new_dummy_x509_certificate, tls_client_config_builder},
std::{
net::{SocketAddr, UdpSocket},
sync::{atomic::AtomicBool, Arc, RwLock},
Expand All @@ -32,9 +32,7 @@ use {
pub fn get_client_config(keypair: &Keypair) -> ClientConfig {
let (cert, key) = new_dummy_x509_certificate(keypair);

let mut crypto = rustls::ClientConfig::builder()
.dangerous()
.with_custom_certificate_verifier(SkipServerVerification::new())
let mut crypto = tls_client_config_builder()
.with_client_auth_cert(vec![cert], key)
.expect("Failed to use client certificate");

Expand Down
7 changes: 3 additions & 4 deletions streamer/src/quic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use {
solana_quic_definitions::{
NotifyKeyUpdate, QUIC_MAX_TIMEOUT, QUIC_MAX_UNSTAKED_CONCURRENT_STREAMS,
},
solana_tls_utils::{new_dummy_x509_certificate, SkipClientVerification},
solana_tls_utils::{new_dummy_x509_certificate, tls_server_config_builder},
std::{
net::UdpSocket,
sync::{
Expand Down Expand Up @@ -58,9 +58,8 @@ pub(crate) fn configure_server(
}];
let cert_chain_pem = pem::encode_many(&cert_chain_pem_parts);

let mut server_tls_config = rustls::ServerConfig::builder()
.with_client_cert_verifier(SkipClientVerification::new())
.with_single_cert(vec![cert], priv_key)?;
let mut server_tls_config =
tls_server_config_builder().with_single_cert(vec![cert], priv_key)?;
server_tls_config.alpn_protocols = vec![ALPN_TPU_PROTOCOL_ID.to_vec()];
server_tls_config.key_log = Arc::new(KeyLogFile::new());
let quic_server_config = QuicServerConfig::try_from(server_tls_config)?;
Expand Down
21 changes: 21 additions & 0 deletions tls-utils/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use {
rustls::{
client::WantsClientCert, server::WantsServerCert, ClientConfig, ConfigBuilder, ServerConfig,
},
std::sync::Arc,
};

pub fn tls_client_config_builder() -> ConfigBuilder<ClientConfig, WantsClientCert> {
ClientConfig::builder_with_provider(Arc::new(crate::crypto_provider()))
.with_safe_default_protocol_versions()
.unwrap()
.dangerous()
.with_custom_certificate_verifier(crate::SkipServerVerification::new())
}

pub fn tls_server_config_builder() -> ConfigBuilder<ServerConfig, WantsServerCert> {
ServerConfig::builder_with_provider(Arc::new(crate::crypto_provider()))
.with_safe_default_protocol_versions()
.unwrap()
.with_client_cert_verifier(crate::SkipClientVerification::new())
}
10 changes: 10 additions & 0 deletions tls-utils/src/crypto_provider.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use rustls::{crypto::CryptoProvider, NamedGroup};

pub fn crypto_provider() -> CryptoProvider {
let mut provider = rustls::crypto::ring::default_provider();
// Disable all key exchange algorithms except X25519
provider
.kx_groups
.retain(|kx| kx.name() == NamedGroup::X25519);
provider
}
6 changes: 6 additions & 0 deletions tls-utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
//! Collection of TLS related code fragments that end up popping up everywhere where quic is used.
//! Aggregated here to avoid bugs due to conflicting implementations of the same functionality.
mod config;
pub use config::*;

mod crypto_provider;
pub use crypto_provider::*;

mod tls_certificates;
pub use tls_certificates::*;

Expand Down
3 changes: 2 additions & 1 deletion tls-utils/src/skip_client_verification.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use {
crate::crypto_provider,
rustls::{
pki_types::{CertificateDer, UnixTime},
server::danger::ClientCertVerified,
Expand All @@ -14,7 +15,7 @@ pub struct SkipClientVerification(Arc<rustls::crypto::CryptoProvider>);

impl SkipClientVerification {
pub fn new() -> Arc<Self> {
Arc::new(Self(Arc::new(rustls::crypto::ring::default_provider())))
Arc::new(Self(Arc::new(crypto_provider())))
}
}
impl rustls::server::danger::ClientCertVerifier for SkipClientVerification {
Expand Down
5 changes: 3 additions & 2 deletions tls-utils/src/skip_server_verification.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use {
crate::crypto_provider,
rustls::{
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
crypto::{ring, verify_tls12_signature, verify_tls13_signature, CryptoProvider},
crypto::{verify_tls12_signature, verify_tls13_signature, CryptoProvider},
pki_types::{CertificateDer, ServerName, UnixTime},
DigitallySignedStruct, Error, SignatureScheme,
},
Expand All @@ -19,7 +20,7 @@ pub struct SkipServerVerification(Arc<CryptoProvider>);

impl SkipServerVerification {
pub fn new() -> Arc<Self> {
Arc::new(Self(Arc::new(ring::default_provider())))
Arc::new(Self(Arc::new(crypto_provider())))
}
}

Expand Down
6 changes: 2 additions & 4 deletions tpu-client-next/src/quic_networking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use {
},
solana_sdk::quic::{QUIC_KEEP_ALIVE, QUIC_MAX_TIMEOUT},
solana_streamer::nonblocking::quic::ALPN_TPU_PROTOCOL_ID,
solana_tls_utils::SkipServerVerification,
solana_tls_utils::tls_client_config_builder,
std::{net::SocketAddr, sync::Arc},
};

Expand All @@ -20,9 +20,7 @@ pub use {

pub(crate) fn create_client_config(client_certificate: QuicClientCertificate) -> ClientConfig {
// adapted from QuicLazyInitializedEndpoint::create_endpoint
let mut crypto = rustls::ClientConfig::builder()
.dangerous()
.with_custom_certificate_verifier(SkipServerVerification::new())
let mut crypto = tls_client_config_builder()
.with_client_auth_cert(
vec![client_certificate.certificate.clone()],
client_certificate.key.clone_key(),
Expand Down
11 changes: 3 additions & 8 deletions turbine/src/quic_endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use {
solana_runtime::bank_forks::BankForks,
solana_sdk::{pubkey::Pubkey, signature::Keypair},
solana_tls_utils::{
new_dummy_x509_certificate, SkipClientVerification, SkipServerVerification,
new_dummy_x509_certificate, tls_client_config_builder, tls_server_config_builder,
},
std::{
cmp::Reverse,
Expand Down Expand Up @@ -157,9 +157,7 @@ fn new_server_config(
cert: CertificateDer<'static>,
key: PrivateKeyDer<'static>,
) -> Result<ServerConfig, rustls::Error> {
let mut config = rustls::ServerConfig::builder()
.with_client_cert_verifier(SkipClientVerification::new())
.with_single_cert(vec![cert], key)?;
let mut config = tls_server_config_builder().with_single_cert(vec![cert], key)?;
config.alpn_protocols = vec![ALPN_TURBINE_PROTOCOL_ID.to_vec()];
config.key_log = Arc::new(KeyLogFile::new());
let quic_server_config = QuicServerConfig::try_from(config)
Expand All @@ -176,10 +174,7 @@ fn new_client_config(
cert: CertificateDer<'static>,
key: PrivateKeyDer<'static>,
) -> Result<ClientConfig, rustls::Error> {
let mut config = rustls::ClientConfig::builder()
.dangerous()
.with_custom_certificate_verifier(SkipServerVerification::new())
.with_client_auth_cert(vec![cert], key)?;
let mut config = tls_client_config_builder().with_client_auth_cert(vec![cert], key)?;
config.enable_early_data = true;
config.alpn_protocols = vec![ALPN_TURBINE_PROTOCOL_ID.to_vec()];
let mut config = ClientConfig::new(Arc::new(QuicClientConfig::try_from(config).unwrap()));
Expand Down

0 comments on commit acc6022

Please sign in to comment.