Remove default certificate verifier trait functions

This is a breaking change.

These introduced an implicit dependency on the `webpki` crate
for anyone who wanted to implement these traits.

Instead, someone who wants to benefit from the `webpki`-backed
implementations should dispatch to `WebPkiServerVerifier` themselves.

Expose these defaults explicitly, and dispatch to them in our
various bits of example and test code.
This commit is contained in:
Joseph Birr-Pixton 2023-06-22 15:27:55 +01:00 committed by ctz
parent 77ad069312
commit e9c15abe06
6 changed files with 195 additions and 51 deletions

View File

@ -338,6 +338,9 @@ fn load_private_key(filename: &str) -> rustls::PrivateKey {
#[cfg(feature = "dangerous_configuration")]
mod danger {
use rustls::client::{HandshakeSignatureValid, WebPkiServerVerifier};
use rustls::DigitallySignedStruct;
pub struct NoCertificateVerification {}
impl rustls::client::ServerCertVerifier for NoCertificateVerification {
@ -351,6 +354,28 @@ mod danger {
) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
Ok(rustls::client::ServerCertVerified::assertion())
}
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &rustls::Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
WebPkiServerVerifier::default_verify_tls12_signature(message, cert, dss)
}
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &rustls::Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
WebPkiServerVerifier::default_verify_tls13_signature(message, cert, dss)
}
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
WebPkiServerVerifier::default_supported_verify_schemes()
}
}
}

View File

@ -4,7 +4,9 @@
// https://boringssl.googlesource.com/boringssl/+/master/ssl/test
//
use rustls::client::{ClientConfig, ClientConnection, Resumption};
use rustls::client::{
ClientConfig, ClientConnection, HandshakeSignatureValid, Resumption, WebPkiServerVerifier,
};
use rustls::crypto::ring::Ring;
use rustls::crypto::CryptoProvider;
use rustls::internal::msgs::codec::Codec;
@ -12,9 +14,10 @@ use rustls::internal::msgs::persist;
use rustls::server::{ClientHello, ServerConfig, ServerConnection};
use rustls::{
self, client, kx_group, server, sign, version, AlertDescription, Certificate, CertificateError,
Connection, DistinguishedName, Error, InvalidMessage, NamedGroup, PeerIncompatible,
PeerMisbehaved, PrivateKey, ProtocolVersion, ServerName, Side, SignatureAlgorithm,
SignatureScheme, SupportedKxGroup, SupportedProtocolVersion, Ticketer, ALL_KX_GROUPS,
Connection, DigitallySignedStruct, DistinguishedName, Error, InvalidMessage, NamedGroup,
PeerIncompatible, PeerMisbehaved, PrivateKey, ProtocolVersion, ServerName, Side,
SignatureAlgorithm, SignatureScheme, SupportedKxGroup, SupportedProtocolVersion, Ticketer,
ALL_KX_GROUPS,
};
use base64::prelude::{Engine, BASE64_STANDARD};
@ -211,6 +214,28 @@ impl server::ClientCertVerifier for DummyClientAuth {
) -> Result<server::ClientCertVerified, Error> {
Ok(server::ClientCertVerified::assertion())
}
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &rustls::Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
WebPkiServerVerifier::default_verify_tls12_signature(message, cert, dss)
}
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &rustls::Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
WebPkiServerVerifier::default_verify_tls13_signature(message, cert, dss)
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
WebPkiServerVerifier::default_supported_verify_schemes()
}
}
struct DummyServerAuth {}
@ -226,6 +251,28 @@ impl client::ServerCertVerifier for DummyServerAuth {
) -> Result<client::ServerCertVerified, Error> {
Ok(client::ServerCertVerified::assertion())
}
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &rustls::Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
WebPkiServerVerifier::default_verify_tls12_signature(message, cert, dss)
}
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &rustls::Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
WebPkiServerVerifier::default_verify_tls13_signature(message, cert, dss)
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
WebPkiServerVerifier::default_supported_verify_schemes()
}
}
struct FixedSignatureSchemeSigningKey {

View File

@ -135,17 +135,12 @@ pub trait ServerCertVerifier: Send + Sync {
/// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2,
/// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not
/// in fact bound to the specific curve implied in their name.
///
/// This trait method has a default implementation that uses webpki to verify
/// the signature.
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
verify_signed_struct(message, cert, dss)
}
) -> Result<HandshakeSignatureValid, Error>;
/// Verify a signature allegedly by the given server certificate.
///
@ -161,28 +156,18 @@ pub trait ServerCertVerifier: Send + Sync {
/// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`.
/// Otherwise, return an error -- rustls will send an alert and abort the
/// connection.
///
/// This trait method has a default implementation that uses webpki to verify
/// the signature.
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
verify_tls13(message, cert, dss)
}
) -> Result<HandshakeSignatureValid, Error>;
/// Return the list of SignatureSchemes that this verifier will handle,
/// in `verify_tls12_signature` and `verify_tls13_signature` calls.
///
/// This should be in priority order, with the most preferred first.
///
/// This trait method has a default implementation that reflects the schemes
/// supported by webpki.
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
WebPkiServerVerifier::verification_schemes()
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme>;
}
impl fmt::Debug for dyn ServerCertVerifier {
@ -258,17 +243,12 @@ pub trait ClientCertVerifier: Send + Sync {
/// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2,
/// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not
/// in fact bound to the specific curve implied in their name.
///
/// This trait method has a default implementation that uses webpki to verify
/// the signature.
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
verify_signed_struct(message, cert, dss)
}
) -> Result<HandshakeSignatureValid, Error>;
/// Verify a signature allegedly by the given client certificate.
///
@ -279,28 +259,18 @@ pub trait ClientCertVerifier: Send + Sync {
/// `SignatureScheme::ECDSA_NISTP256_SHA256`
/// must only validate signatures using public keys on the right curve --
/// rustls does not enforce this requirement for you.
///
/// This trait method has a default implementation that uses webpki to verify
/// the signature.
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
verify_tls13(message, cert, dss)
}
) -> Result<HandshakeSignatureValid, Error>;
/// Return the list of SignatureSchemes that this verifier will handle,
/// in `verify_tls12_signature` and `verify_tls13_signature` calls.
///
/// This should be in priority order, with the most preferred first.
///
/// This trait method has a default implementation that reflects the schemes
/// supported by webpki.
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
WebPkiServerVerifier::verification_schemes()
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme>;
}
impl fmt::Debug for dyn ClientCertVerifier {
@ -394,6 +364,28 @@ impl ServerCertVerifier for WebPkiServerVerifier {
verify_server_name(&cert, server_name)?;
Ok(ServerCertVerified::assertion())
}
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
Self::default_verify_tls12_signature(message, cert, dss)
}
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
Self::default_verify_tls13_signature(message, cert, dss)
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
Self::default_supported_verify_schemes()
}
}
/// Default `ServerCertVerifier`, see the trait impl for more information.
@ -405,16 +397,15 @@ pub struct WebPkiServerVerifier {
#[allow(unreachable_pub)]
impl WebPkiServerVerifier {
/// Constructs a new `WebPkiVerifier`.
/// Constructs a new `WebPkiServerVerifier`.
///
/// `roots` is the set of trust anchors to trust for issuing server certs.
pub fn new(roots: RootCertStore) -> Self {
Self { roots }
}
/// Returns the signature verification methods supported by
/// webpki.
pub fn verification_schemes() -> Vec<SignatureScheme> {
/// Which signature verification schemes the `webpki` crate supports.
pub fn default_supported_verify_schemes() -> Vec<SignatureScheme> {
vec![
SignatureScheme::ECDSA_NISTP384_SHA384,
SignatureScheme::ECDSA_NISTP256_SHA256,
@ -427,6 +418,26 @@ impl WebPkiServerVerifier {
SignatureScheme::RSA_PKCS1_SHA256,
]
}
/// An full implementation of `ServerCertVerifier::verify_tls12_signature` or
/// `ClientCertVerifier::verify_tls12_signature`.
pub fn default_verify_tls12_signature(
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
verify_signed_struct(message, cert, dss)
}
/// An full implementation of `ServerCertVerifier::verify_tls13_signature` or
/// `ClientCertVerifier::verify_tls13_signature`.
pub fn default_verify_tls13_signature(
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
verify_tls13(message, cert, dss)
}
}
fn intermediate_chain(intermediates: &[Certificate]) -> Vec<&[u8]> {
@ -619,6 +630,28 @@ impl ClientCertVerifier for WebPkiClientVerifier {
.map_err(pki_error)
.map(|_| ClientCertVerified::assertion())
}
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
WebPkiServerVerifier::default_verify_tls12_signature(message, cert, dss)
}
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
WebPkiServerVerifier::default_verify_tls13_signature(message, cert, dss)
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
WebPkiServerVerifier::default_supported_verify_schemes()
}
}
/// Controls how the [WebPkiClientVerifier] handles anonymous clients.
@ -678,6 +711,28 @@ impl ClientCertVerifier for NoClientAuth {
) -> Result<ClientCertVerified, Error> {
unimplemented!();
}
fn verify_tls12_signature(
&self,
_message: &[u8],
_cert: &Certificate,
_dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
unimplemented!();
}
fn verify_tls13_signature(
&self,
_message: &[u8],
_cert: &Certificate,
_dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
unimplemented!();
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
unimplemented!();
}
}
/// This type combines a [`SignatureScheme`] and a signature payload produced with that scheme.

View File

@ -474,8 +474,7 @@ fn test_config_builders_debug() {
/// Test that the server handles combination of `offer_client_auth()` returning true
/// and `client_auth_mandatory` returning `Some(false)`. This exercises both the
/// client's and server's ability to "recover" from the server asking for a client
/// certificate and not being given one. This also covers the implementation
/// of `AllowAnyAnonymousOrAuthenticatedClient`.
/// certificate and not being given one.
#[test]
fn server_allow_any_anonymous_or_authenticated_client() {
let kt = KeyType::Rsa;

View File

@ -9,13 +9,13 @@ use crate::common::{
make_client_config_with_versions, make_client_config_with_versions_with_auth,
make_pair_for_arc_configs, server_name, ErrorFromPeer, KeyType, ALL_KEY_TYPES,
};
use rustls::client::WebPkiServerVerifier;
use rustls::client::{HandshakeSignatureValid, WebPkiServerVerifier};
use rustls::crypto::ring::Ring;
use rustls::internal::msgs::handshake::DistinguishedName;
use rustls::server::{ClientCertVerified, ClientCertVerifier};
use rustls::{
AlertDescription, Certificate, ClientConnection, Error, InvalidMessage, ServerConfig,
ServerConnection, SignatureScheme,
AlertDescription, Certificate, ClientConnection, DigitallySignedStruct, Error, InvalidMessage,
ServerConfig, ServerConnection, SignatureScheme,
};
use std::sync::Arc;
@ -200,11 +200,29 @@ impl ClientCertVerifier for MockClientVerifier {
(self.verified)()
}
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
WebPkiServerVerifier::default_verify_tls12_signature(message, cert, dss)
}
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &Certificate,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
WebPkiServerVerifier::default_verify_tls13_signature(message, cert, dss)
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
if let Some(schemes) = &self.offered_schemes {
schemes.clone()
} else {
WebPkiServerVerifier::verification_schemes()
WebPkiServerVerifier::default_supported_verify_schemes()
}
}
}

View File

@ -262,7 +262,7 @@ impl Default for MockServerVerifier {
cert_rejection_error: None,
tls12_signature_error: None,
tls13_signature_error: None,
signature_schemes: WebPkiServerVerifier::verification_schemes(),
signature_schemes: WebPkiServerVerifier::default_supported_verify_schemes(),
}
}
}