Skip to content

Commit

Permalink
Always use ed25519_dalek for the QUIC-TLS cert verification
Browse files Browse the repository at this point in the history
- Ban use of other TLS signature algorithms such as RSA
- Add boilerplate to replace ring's Ed25519 verifier with Dalek
  • Loading branch information
riptl committed Sep 13, 2024
1 parent 43112d8 commit 4cdb880
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 58 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 12 additions & 19 deletions quic-client/src/nonblocking/quic_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ use {
transport::Result as TransportResult,
},
solana_streamer::{
nonblocking::quic::ALPN_TPU_PROTOCOL_ID, tls_certificates::new_dummy_x509_certificate,
nonblocking::quic::ALPN_TPU_PROTOCOL_ID, quic::TLS_SIGVERIFY_SCHEMES,
tls_certificates::new_dummy_x509_certificate,
},
std::{
net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket},
Expand All @@ -40,27 +41,24 @@ use {
};

#[derive(Debug)]
pub struct SkipServerVerification(Arc<rustls::crypto::CryptoProvider>);
pub struct SkipServerVerification;

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

impl rustls::client::danger::ServerCertVerifier for SkipServerVerification {
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
_message: &[u8],
_cert: &rustls::pki_types::CertificateDer<'_>,
_dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls12_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
Err(rustls::Error::PeerIncompatible(
rustls::PeerIncompatible::Tls13RequiredForQuic,
))
}

fn verify_tls13_signature(
Expand All @@ -69,16 +67,11 @@ impl rustls::client::danger::ServerCertVerifier for SkipServerVerification {
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls13_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
rustls::crypto::verify_tls13_signature(message, cert, dss, &TLS_SIGVERIFY_SCHEMES)
}

fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
self.0.signature_verification_algorithms.supported_schemes()
TLS_SIGVERIFY_SCHEMES.supported_schemes()
}

fn verify_server_cert(
Expand Down
1 change: 1 addition & 0 deletions streamer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ edition = { workspace = true }
async-channel = { workspace = true }
bytes = { workspace = true }
crossbeam-channel = { workspace = true }
ed25519-dalek = { workspace = true }
dashmap = { workspace = true }
futures = { workspace = true }
futures-util = { workspace = true }
Expand Down
32 changes: 13 additions & 19 deletions streamer/src/nonblocking/testing_utilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use {
DEFAULT_MAX_CONNECTIONS_PER_IPADDR_PER_MINUTE, DEFAULT_MAX_STREAMS_PER_MS,
},
crate::{
quic::{StreamerStats, MAX_STAKED_CONNECTIONS, MAX_UNSTAKED_CONNECTIONS},
quic::{
StreamerStats, MAX_STAKED_CONNECTIONS, MAX_UNSTAKED_CONNECTIONS, TLS_SIGVERIFY_SCHEMES,
},
streamer::StakedNodes,
tls_certificates::new_dummy_x509_certificate,
},
Expand All @@ -29,27 +31,24 @@ use {
};

#[derive(Debug)]
pub struct SkipServerVerification(Arc<rustls::crypto::CryptoProvider>);
pub struct SkipServerVerification;

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

impl rustls::client::danger::ServerCertVerifier for SkipServerVerification {
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
_message: &[u8],
_cert: &rustls::pki_types::CertificateDer<'_>,
_dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls12_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
Err(rustls::Error::PeerIncompatible(
rustls::PeerIncompatible::Tls13RequiredForQuic,
))
}

fn verify_tls13_signature(
Expand All @@ -58,16 +57,11 @@ impl rustls::client::danger::ServerCertVerifier for SkipServerVerification {
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls13_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
rustls::crypto::verify_tls13_signature(message, cert, dss, &TLS_SIGVERIFY_SCHEMES)
}

fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
self.0.signature_verification_algorithms.supported_schemes()
TLS_SIGVERIFY_SCHEMES.supported_schemes()
}

fn verify_server_cert(
Expand Down
72 changes: 52 additions & 20 deletions streamer/src/quic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ use {
Endpoint, IdleTimeout, ServerConfig,
},
rustls::{
pki_types::{CertificateDer, UnixTime},
crypto::WebPkiSupportedAlgorithms,
pki_types::{
AlgorithmIdentifier, CertificateDer, InvalidSignature, SignatureVerificationAlgorithm,
UnixTime,
},
server::danger::ClientCertVerified,
DistinguishedName, KeyLogFile,
DistinguishedName, KeyLogFile, SignatureScheme,
},
solana_perf::packet::PacketBatch,
solana_sdk::{
Expand All @@ -38,12 +42,48 @@ pub const MAX_UNSTAKED_CONNECTIONS: usize = 500;
// This will be adjusted and parameterized in follow-on PRs.
pub const DEFAULT_QUIC_ENDPOINTS: usize = 1;

// Boilerplate required to use ed25519_dalek for signature verification.
#[derive(Debug)]
struct DalekEd25519;
static DALEK_ED25519: &dyn SignatureVerificationAlgorithm = &DalekEd25519;
const ED25519_ALG_ID: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(&[0x06, 0x03, 0x2b, 0x65, 0x70]);
impl SignatureVerificationAlgorithm for DalekEd25519 {
fn public_key_alg_id(&self) -> AlgorithmIdentifier {
ED25519_ALG_ID
}

fn signature_alg_id(&self) -> AlgorithmIdentifier {
ED25519_ALG_ID
}

fn verify_signature(
&self,
public_key: &[u8],
message: &[u8],
signature: &[u8],
) -> Result<(), InvalidSignature> {
let publickey =
ed25519_dalek::PublicKey::from_bytes(public_key).map_err(|_| InvalidSignature)?;
let signature =
ed25519_dalek::Signature::try_from(signature).map_err(|_| InvalidSignature)?;
publickey
.verify(message, &signature)
.map_err(|_| InvalidSignature)
}
}

pub static TLS_SIGVERIFY_SCHEMES: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
all: &[DALEK_ED25519],
mapping: &[(SignatureScheme::ED25519, &[DALEK_ED25519])],
};

#[derive(Debug)]
pub struct SkipClientVerification(Arc<rustls::crypto::CryptoProvider>);
pub struct SkipClientVerification;

impl SkipClientVerification {
pub fn new() -> Arc<Self> {
Arc::new(Self(Arc::new(rustls::crypto::ring::default_provider())))
Arc::new(Self)
}
}

Expand All @@ -69,16 +109,13 @@ impl rustls::server::danger::ClientCertVerifier for SkipClientVerification {

fn verify_tls12_signature(
&self,
message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
_message: &[u8],
_cert: &rustls::pki_types::CertificateDer<'_>,
_dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls12_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
Err(rustls::Error::PeerIncompatible(
rustls::PeerIncompatible::Tls13RequiredForQuic,
))
}

fn verify_tls13_signature(
Expand All @@ -87,16 +124,11 @@ impl rustls::server::danger::ClientCertVerifier for SkipClientVerification {
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls13_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
rustls::crypto::verify_tls13_signature(message, cert, dss, &TLS_SIGVERIFY_SCHEMES)
}

fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
self.0.signature_verification_algorithms.supported_schemes()
TLS_SIGVERIFY_SCHEMES.supported_schemes()
}

fn offer_client_auth(&self) -> bool {
Expand Down

0 comments on commit 4cdb880

Please sign in to comment.