Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use dynamic dispatch for CryptoProvider #1448

Merged
merged 6 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 4 additions & 5 deletions ci-bench/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use itertools::Itertools;
use rayon::iter::Either;
use rayon::prelude::*;
use rustls::client::Resumption;
use rustls::crypto::ring::Ring;
use rustls::server::{NoServerSessionStorage, ServerSessionMemoryCache, WebPkiClientVerifier};
use rustls::{
ClientConfig, ClientConnection, ProtocolVersion, RootCertStore, ServerConfig, ServerConnection,
Expand Down Expand Up @@ -345,11 +344,11 @@ struct StepperIO<'a> {
struct ClientSideStepper<'a> {
io: StepperIO<'a>,
resumption_kind: ResumptionKind,
config: Arc<ClientConfig<Ring>>,
config: Arc<ClientConfig>,
ctz marked this conversation as resolved.
Show resolved Hide resolved
}

impl ClientSideStepper<'_> {
fn make_config(params: &BenchmarkParams, resume: ResumptionKind) -> Arc<ClientConfig<Ring>> {
fn make_config(params: &BenchmarkParams, resume: ResumptionKind) -> Arc<ClientConfig> {
assert_eq!(params.ciphersuite.version(), params.version);
let mut root_store = RootCertStore::empty();
let mut rootbuf =
Expand Down Expand Up @@ -422,11 +421,11 @@ impl BenchStepper for ClientSideStepper<'_> {
/// A benchmark stepper for the server-side of the connection
struct ServerSideStepper<'a> {
io: StepperIO<'a>,
config: Arc<ServerConfig<Ring>>,
config: Arc<ServerConfig>,
}

impl ServerSideStepper<'_> {
fn make_config(params: &BenchmarkParams, resume: ResumptionKind) -> Arc<ServerConfig<Ring>> {
fn make_config(params: &BenchmarkParams, resume: ResumptionKind) -> Arc<ServerConfig> {
assert_eq!(params.ciphersuite.version(), params.version);

let mut cfg = ServerConfig::builder()
Expand Down
6 changes: 2 additions & 4 deletions examples/src/bin/limitedclient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ use std::io::{stdout, Read, Write};
use std::net::TcpStream;
use std::sync::Arc;

use rustls::crypto::ring::Ring;

fn main() {
let mut root_store = rustls::RootCertStore::empty();
root_store.extend(
Expand All @@ -16,9 +14,9 @@ fn main() {
.cloned(),
);

let config = rustls::ClientConfig::<Ring>::builder()
let config = rustls::ClientConfig::builder()
.with_cipher_suites(&[rustls::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256])
.with_kx_groups(&[&rustls::kx_group::X25519])
.with_kx_groups(&[rustls::kx_group::X25519])
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap()
.with_root_certificates(root_store)
Expand Down
10 changes: 2 additions & 8 deletions examples/src/bin/server_acceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use docopt::Docopt;
use pki_types::{CertificateDer, CertificateRevocationListDer, PrivateKeyDer, PrivatePkcs8KeyDer};
use serde_derive::Deserialize;

use rustls::crypto::CryptoProvider;
use rustls::server::{Acceptor, ClientHello, ServerConfig, WebPkiClientVerifier};
use rustls::RootCertStore;

Expand Down Expand Up @@ -123,8 +122,7 @@ fn main() {

// Generate a server config for the accepted connection, optionally customizing the
// configuration based on the client hello.
let config = test_pki
.server_config::<rustls::crypto::ring::Ring>(&crl_path, accepted.client_hello());
let config = test_pki.server_config(&crl_path, accepted.client_hello());
let mut conn = accepted
.into_connection(config)
.unwrap();
Expand Down Expand Up @@ -210,11 +208,7 @@ impl TestPki {
///
/// Since the presented client certificate is not available in the `ClientHello` the server
/// must know ahead of time which CRLs it cares about.
fn server_config<C: CryptoProvider>(
&self,
crl_path: &str,
_hello: ClientHello,
) -> Arc<ServerConfig<C>> {
fn server_config(&self, crl_path: &str, _hello: ClientHello) -> Arc<ServerConfig> {
// Read the latest CRL from disk. The CRL is being periodically updated by the crl_updater
// thread.
let mut crl_file = File::open(crl_path).unwrap();
Expand Down
6 changes: 2 additions & 4 deletions examples/src/bin/simple_0rtt_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ use std::io::{BufRead, BufReader, Write};
use std::net::TcpStream;
use std::sync::Arc;

use rustls::crypto::ring::Ring;
use rustls::crypto::CryptoProvider;
use rustls::RootCertStore;

fn start_connection(config: &Arc<rustls::ClientConfig<impl CryptoProvider>>, domain_name: &str) {
fn start_connection(config: &Arc<rustls::ClientConfig>, domain_name: &str) {
let server_name = domain_name
.try_into()
.expect("invalid DNS name");
Expand Down Expand Up @@ -65,7 +63,7 @@ fn main() {
.cloned(),
);

let mut config = rustls::ClientConfig::<Ring>::builder()
let mut config = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth();
Expand Down
3 changes: 1 addition & 2 deletions examples/src/bin/simpleclient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use std::io::{stdout, Read, Write};
use std::net::TcpStream;
use std::sync::Arc;

use rustls::crypto::ring::Ring;
use rustls::RootCertStore;

fn main() {
Expand All @@ -22,7 +21,7 @@ fn main() {
.iter()
.cloned(),
);
let mut config = rustls::ClientConfig::<Ring>::builder()
let mut config = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth();
Expand Down
10 changes: 4 additions & 6 deletions examples/src/bin/tlsclient-mio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ use mio::net::TcpStream;
use pki_types::{CertificateDer, PrivateKeyDer};
use serde::Deserialize;

use rustls::crypto::ring::Ring;
use rustls::crypto::CryptoProvider;
use rustls::RootCertStore;

const CLIENT: mio::Token = mio::Token(0);
Expand All @@ -27,7 +25,7 @@ impl TlsClient {
fn new(
sock: TcpStream,
server_name: rustls::ServerName,
cfg: Arc<rustls::ClientConfig<impl CryptoProvider>>,
cfg: Arc<rustls::ClientConfig>,
) -> Self {
Self {
socket: sock,
Expand Down Expand Up @@ -356,22 +354,22 @@ mod danger {
}

#[cfg(feature = "dangerous_configuration")]
fn apply_dangerous_options(args: &Args, cfg: &mut rustls::ClientConfig<impl CryptoProvider>) {
fn apply_dangerous_options(args: &Args, cfg: &mut rustls::ClientConfig) {
if args.flag_insecure {
cfg.dangerous()
.set_certificate_verifier(Arc::new(danger::NoCertificateVerification {}));
}
}

#[cfg(not(feature = "dangerous_configuration"))]
fn apply_dangerous_options(args: &Args, _: &mut rustls::ClientConfig<impl CryptoProvider>) {
fn apply_dangerous_options(args: &Args, _: &mut rustls::ClientConfig) {
if args.flag_insecure {
panic!("This build does not support --insecure.");
}
}

/// Build a `ClientConfig` from our arguments
fn make_config(args: &Args) -> Arc<rustls::ClientConfig<Ring>> {
fn make_config(args: &Args) -> Arc<rustls::ClientConfig> {
let mut root_store = RootCertStore::empty();

if args.flag_cafile.is_some() {
Expand Down
7 changes: 3 additions & 4 deletions examples/src/bin/tlsserver-mio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use mio::net::{TcpListener, TcpStream};
use pki_types::{CertificateDer, CertificateRevocationListDer, PrivateKeyDer};
use serde::Deserialize;

use rustls::crypto::ring::Ring;
use rustls::server::WebPkiClientVerifier;
use rustls::{self, RootCertStore};

Expand All @@ -36,12 +35,12 @@ struct TlsServer {
server: TcpListener,
connections: HashMap<mio::Token, OpenConnection>,
next_id: usize,
tls_config: Arc<rustls::ServerConfig<Ring>>,
tls_config: Arc<rustls::ServerConfig>,
mode: ServerMode,
}

impl TlsServer {
fn new(server: TcpListener, mode: ServerMode, cfg: Arc<rustls::ServerConfig<Ring>>) -> Self {
fn new(server: TcpListener, mode: ServerMode, cfg: Arc<rustls::ServerConfig>) -> Self {
Self {
server,
connections: HashMap::new(),
Expand Down Expand Up @@ -557,7 +556,7 @@ fn load_crls(filenames: &[String]) -> Vec<CertificateRevocationListDer<'static>>
.collect()
}

fn make_config(args: &Args) -> Arc<rustls::ServerConfig<Ring>> {
fn make_config(args: &Args) -> Arc<rustls::ServerConfig> {
let client_auth = if args.flag_auth.is_some() {
let roots = load_certs(args.flag_auth.as_ref().unwrap());
let mut client_auth_roots = RootCertStore::empty();
Expand Down
3 changes: 1 addition & 2 deletions fuzz/fuzzers/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ extern crate libfuzzer_sys;
extern crate rustls;
extern crate webpki;

use rustls::crypto::ring::Ring;
use rustls::{ClientConfig, ClientConnection, RootCertStore};
use std::io;
use std::sync::Arc;

fuzz_target!(|data: &[u8]| {
let root_store = RootCertStore::empty();
let config = Arc::new(
ClientConfig::<Ring>::builder()
ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth(),
Expand Down
3 changes: 1 addition & 2 deletions fuzz/fuzzers/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
extern crate libfuzzer_sys;
extern crate rustls;

use rustls::crypto::ring::Ring;
use rustls::server::ResolvesServerCert;
use rustls::{ServerConfig, ServerConnection};

Expand All @@ -23,7 +22,7 @@ impl ResolvesServerCert for Fail {

fuzz_target!(|data: &[u8]| {
let config = Arc::new(
ServerConfig::<Ring>::builder()
ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_cert_resolver(Arc::new(Fail)),
Expand Down
6 changes: 3 additions & 3 deletions provider-example/examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::io::{stdout, Read, Write};
use std::net::TcpStream;
use std::sync::Arc;

use rustls_provider_example::Provider;
use rustls_provider_example::{certificate_verifier, PROVIDER};

fn main() {
env_logger::init();
Expand All @@ -14,9 +14,9 @@ fn main() {
.cloned(),
);

let config = rustls::ClientConfig::<Provider>::builder()
let config = rustls::ClientConfig::builder_with_provider(PROVIDER)
.with_safe_defaults()
.with_custom_certificate_verifier(Provider::certificate_verifier(root_store))
.with_custom_certificate_verifier(certificate_verifier(root_store))
.with_no_client_auth();

let server_name = "www.rust-lang.org".try_into().unwrap();
Expand Down
47 changes: 17 additions & 30 deletions provider-example/src/kx.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,22 @@
use crypto::SupportedGroup;
use crypto::SupportedKxGroup;
use rustls::crypto;

pub struct KeyExchange {
priv_key: x25519_dalek::EphemeralSecret,
pub_key: x25519_dalek::PublicKey,
}

impl crypto::KeyExchange for KeyExchange {
type SupportedGroup = X25519;

fn start(
name: rustls::NamedGroup,
_: &[&'static Self::SupportedGroup],
) -> Result<Self, crypto::KeyExchangeError> {
if name == rustls::NamedGroup::X25519 {
let priv_key = x25519_dalek::EphemeralSecret::random_from_rng(rand_core::OsRng);
let pub_key = (&priv_key).into();
Ok(KeyExchange { priv_key, pub_key })
} else {
Err(crypto::KeyExchangeError::UnsupportedGroup)
}
}

fn complete<T>(
self,
impl crypto::ActiveKeyExchange for KeyExchange {
fn complete(
self: Box<KeyExchange>,
peer: &[u8],
f: impl FnOnce(&[u8]) -> Result<T, ()>,
) -> Result<T, rustls::Error> {
) -> Result<crypto::SharedSecret, rustls::Error> {
let peer_array: [u8; 32] = peer
.try_into()
.map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?;
let their_pub = x25519_dalek::PublicKey::from(peer_array);
let shared_secret = self.priv_key.diffie_hellman(&their_pub);
f(shared_secret.as_bytes())
.map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))
Ok(crypto::SharedSecret::from(&shared_secret.as_bytes()[..]))
}

fn pub_key(&self) -> &[u8] {
Expand All @@ -43,19 +26,23 @@ impl crypto::KeyExchange for KeyExchange {
fn group(&self) -> rustls::NamedGroup {
X25519.name()
}

fn all_kx_groups() -> &'static [&'static Self::SupportedGroup] {
ALL_KX_GROUPS
}
}

pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[&X25519 as &dyn SupportedKxGroup];

#[derive(Debug)]
pub struct X25519;

impl crypto::SupportedGroup for X25519 {
impl crypto::SupportedKxGroup for X25519 {
fn start(&self) -> Result<Box<dyn crypto::ActiveKeyExchange>, rustls::crypto::GetRandomFailed> {
let priv_key = x25519_dalek::EphemeralSecret::random_from_rng(rand_core::OsRng);
ctz marked this conversation as resolved.
Show resolved Hide resolved
Ok(Box::new(KeyExchange {
pub_key: (&priv_key).into(),
priv_key,
}))
}

fn name(&self) -> rustls::NamedGroup {
rustls::NamedGroup::X25519
}
}

const ALL_KX_GROUPS: &[&X25519] = &[&X25519];
33 changes: 18 additions & 15 deletions provider-example/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,26 @@ mod hmac;
mod kx;
mod verify;

pub struct Provider;
pub static PROVIDER: &'static dyn rustls::crypto::CryptoProvider = &Provider;

impl Provider {
pub fn certificate_verifier(
roots: rustls::RootCertStore,
) -> Arc<dyn rustls::client::ServerCertVerifier> {
Arc::new(rustls::client::WebPkiServerVerifier::new_with_algorithms(
roots,
verify::ALGORITHMS,
))
}
}
#[derive(Debug)]
struct Provider;

impl rustls::crypto::CryptoProvider for Provider {
type KeyExchange = kx::KeyExchange;

fn fill_random(bytes: &mut [u8]) -> Result<(), rustls::crypto::GetRandomFailed> {
fn fill_random(&self, bytes: &mut [u8]) -> Result<(), rustls::crypto::GetRandomFailed> {
use rand_core::RngCore;
rand_core::OsRng
.try_fill_bytes(bytes)
.map_err(|_| rustls::crypto::GetRandomFailed)
}

fn default_cipher_suites() -> &'static [rustls::SupportedCipherSuite] {
fn default_cipher_suites(&self) -> &'static [rustls::SupportedCipherSuite] {
ALL_CIPHER_SUITES
}

fn default_kx_groups(&self) -> &'static [&'static dyn rustls::SupportedKxGroup] {
kx::ALL_KX_GROUPS
ctz marked this conversation as resolved.
Show resolved Hide resolved
}
}

static ALL_CIPHER_SUITES: &[rustls::SupportedCipherSuite] = &[
ctz marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -63,3 +57,12 @@ pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: rustls::SupportedCipherS
hmac_provider: &hmac::Sha256Hmac,
aead_alg: &aead::Chacha20Poly1305,
});

pub fn certificate_verifier(
roots: rustls::RootCertStore,
) -> Arc<dyn rustls::client::ServerCertVerifier> {
Arc::new(rustls::client::WebPkiServerVerifier::new_with_algorithms(
roots,
verify::ALGORITHMS,
))
}