Skip to content

Commit

Permalink
Move crypto wrapper types back into quinn-proto
Browse files Browse the repository at this point in the history
This is the second time we flip-flop on this. Previously in
4fd4868 (#351) we moved these types from
quinn into quinn-proto so that they could be used as part of the low-level
configuration API.

Then in 9522b44 (#511) we moved them back
into quinn after some discussion, making the point that the configuration
API at the quinn-proto was not in a great place.

Here, we keep the existing quinn-proto configuration API and merely offer
an abstracted API relying on the wrapper types for use in quinn internals.
  • Loading branch information
djc committed Feb 26, 2020
1 parent 7122eab commit 0ca79eb
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 21 deletions.
3 changes: 3 additions & 0 deletions quinn-proto/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub(crate) mod ring;
/// TLS interface based on rustls
#[cfg(feature = "rustls")]
pub(crate) mod rustls;
/// Public interface TLS types
#[cfg(feature = "rustls")]
pub mod types;

/// A cryptographic session (commonly TLS)
pub trait Session: Sized {
Expand Down
10 changes: 8 additions & 2 deletions quinn/src/tls.rs → quinn-proto/src/crypto/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ impl Certificate {
}
}

impl From<rustls::Certificate> for Certificate {
fn from(inner: rustls::Certificate) -> Self {
Certificate { inner }
}
}

/// A chain of signed TLS certificates ending the one to be used by a server
#[derive(Debug, Clone)]
pub struct CertificateChain {
Expand All @@ -33,7 +39,7 @@ impl CertificateChain {
///
/// ```no_run
/// let pem = std::fs::read("fullchain.pem").expect("error reading certificates");
/// let cert_chain = quinn::PrivateKey::from_pem(&pem).expect("error parsing certificates");
/// let cert_chain = quinn_proto::PrivateKey::from_pem(&pem).expect("error parsing certificates");
/// ```
pub fn from_pem(pem: &[u8]) -> Result<Self, ParseError> {
Ok(Self {
Expand Down Expand Up @@ -70,7 +76,7 @@ impl PrivateKey {
///
/// ```no_run
/// let pem = std::fs::read("key.pem").expect("error reading key");
/// let key = quinn::PrivateKey::from_pem(&pem).expect("error parsing key");
/// let key = quinn_proto::PrivateKey::from_pem(&pem).expect("error parsing key");
/// ```
pub fn from_pem(pem: &[u8]) -> Result<Self, ParseError> {
let pkcs8 = pemfile::pkcs8_private_keys(&mut &pem[..])
Expand Down
2 changes: 1 addition & 1 deletion quinn-proto/src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ enum ConnectionOpts<S: crypto::Session> {
/// Errors in the parameters being used to create a new connection
///
/// These arise before any I/O has been performed.
#[derive(Debug, Error, Clone, PartialEq, Eq)]
#[derive(Debug, Error, Clone, PartialEq)]
pub enum ConnectError {
/// The endpoint can no longer create new connections
///
Expand Down
2 changes: 2 additions & 0 deletions quinn-proto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ mod connection;
pub use crate::connection::{ConnectionError, Event, SendDatagramError};

pub mod crypto;
#[cfg(feature = "rustls")]
pub use crypto::types::*;

mod frame;
use crate::frame::Frame;
Expand Down
32 changes: 31 additions & 1 deletion quinn-proto/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use bytes::BytesMut;
use err_derive::Error;
use rand::{Rng, RngCore};

#[cfg(feature = "rustls")]
use crate::crypto::types::{Certificate, CertificateChain, PrivateKey};
use crate::{
crypto::{self, ClientConfig as _, HmacKey as _, ServerConfig as _},
packet::PartialDecode,
Expand Down Expand Up @@ -459,6 +461,19 @@ where
}
}

#[cfg(feature = "rustls")]
impl ServerConfig<crypto::rustls::TlsSession> {
/// Set the certificate chain that will be presented to clients
pub fn certificate(
&mut self,
cert_chain: CertificateChain,
key: PrivateKey,
) -> Result<&mut Self, rustls::TLSError> {
Arc::make_mut(&mut self.crypto).set_single_cert(cert_chain.certs, key.inner)?;
Ok(self)
}
}

impl<S> fmt::Debug for ServerConfig<S>
where
S: crypto::Session,
Expand Down Expand Up @@ -524,6 +539,21 @@ where
pub crypto: S::ClientConfig,
}

#[cfg(feature = "rustls")]
impl ClientConfig<crypto::rustls::TlsSession> {
/// Add a trusted certificate authority
pub fn add_certificate_authority(
&mut self,
cert: Certificate,
) -> Result<&mut Self, webpki::Error> {
let anchor = webpki::trust_anchor_util::cert_der_as_trust_anchor(&cert.inner.0)?;
Arc::make_mut(&mut self.crypto)
.root_store
.add_server_trust_anchors(&webpki::TLSServerTrustAnchors(&[anchor]));
Ok(self)
}
}

impl<S> Default for ClientConfig<S>
where
S: crypto::Session,
Expand Down Expand Up @@ -562,7 +592,7 @@ where
}

/// Errors in the configuration of an endpoint
#[derive(Debug, Error, Clone, PartialEq, Eq)]
#[derive(Debug, Error, Clone, PartialEq)]
#[non_exhaustive]
pub enum ConfigError {
/// Value exceeds supported bounds
Expand Down
10 changes: 3 additions & 7 deletions quinn/src/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::{io, net::SocketAddr, str, sync::Arc};

use err_derive::Error;
use proto::{ClientConfig, EndpointConfig, ServerConfig};
use rustls::TLSError;
use tracing::error;

use crate::{
Expand Down Expand Up @@ -132,8 +131,8 @@ impl ServerConfigBuilder {
&mut self,
cert_chain: CertificateChain,
key: PrivateKey,
) -> Result<&mut Self, TLSError> {
Arc::make_mut(&mut self.config.crypto).set_single_cert(cert_chain.certs, key.inner)?;
) -> Result<&mut Self, rustls::TLSError> {
self.config.certificate(cert_chain, key)?;
Ok(self)
}

Expand Down Expand Up @@ -194,10 +193,7 @@ impl ClientConfigBuilder {
&mut self,
cert: Certificate,
) -> Result<&mut Self, webpki::Error> {
let anchor = webpki::trust_anchor_util::cert_der_as_trust_anchor(&cert.inner.0)?;
Arc::make_mut(&mut self.config.crypto)
.root_store
.add_server_trust_anchors(&webpki::TLSServerTrustAnchors(&[anchor]));
self.config.add_certificate_authority(cert)?;
Ok(self)
}

Expand Down
12 changes: 4 additions & 8 deletions quinn/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ use futures::{
channel::{mpsc, oneshot},
FutureExt, StreamExt,
};
use proto::crypto::types::Certificate;
use proto::{ConnectionError, ConnectionHandle, Dir, StreamId};
use tokio::time::{delay_until, Delay, Instant as TokioInstant};
use tracing::info_span;

use crate::{
broadcast::{self, Broadcast},
streams::{RecvStream, SendStream, WriteError},
tls, ConnectionEvent, EndpointEvent, SendDatagramError, VarInt,
ConnectionEvent, EndpointEvent, SendDatagramError, VarInt,
};

/// In-progress connection attempt future
Expand Down Expand Up @@ -315,19 +316,14 @@ impl Connection {
/// For clients, this is the certificate chain of the server. For servers,
/// it is the certificate chain of the client, or [`None`] if client
/// authentication was not requested.
pub fn presented_certs(&self) -> Option<Vec<tls::Certificate>> {
pub fn presented_certs(&self) -> Option<Vec<Certificate>> {
self.0
.lock()
.unwrap()
.inner
.crypto_session()
.get_peer_certificates()
.map(|certs| {
certs
.into_iter()
.map(|cert| tls::Certificate { inner: cert })
.collect()
})
.map(|certs| certs.into_iter().map(|cert| cert.into()).collect())
}

// Update traffic keys spontaneously for testing purposes.
Expand Down
3 changes: 1 addition & 2 deletions quinn/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ pub use streams::{
WriteError,
};

mod tls;
pub use tls::{Certificate, CertificateChain, ParseError, PrivateKey};
pub use proto::crypto::types::{Certificate, CertificateChain, ParseError, PrivateKey};

#[cfg(test)]
mod tests;
Expand Down

0 comments on commit 0ca79eb

Please sign in to comment.