Skip to content

Commit

Permalink
Remove generic crypto code
Browse files Browse the repository at this point in the history
  • Loading branch information
kpp committed Nov 9, 2021
1 parent 25ee1fe commit f35fde1
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 265 deletions.
4 changes: 0 additions & 4 deletions transports/quic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ description = "TLS based QUIC transport implementation for libp2p"
repository = "https://github.com/libp2p/rust-libp2p"
license = "MIT"

[features]
tls = []
default = ["tls"]

[dependencies]
async-global-executor = "2.0.2"
async-io = "1.6.0"
Expand Down
83 changes: 16 additions & 67 deletions transports/quic/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,76 +18,36 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use libp2p_core::PeerId;
use libp2p_core::identity::{PublicKey, Keypair};
use quinn_proto::crypto::Session;
use quinn_proto::TransportConfig;
use std::sync::Arc;

pub struct CryptoConfig<C: Crypto> {
pub keypair: C::Keypair,
pub keylogger: Option<C::Keylogger>,
pub struct CryptoConfig {
pub keypair: Keypair,
pub keylogger: Option<Arc<dyn rustls::KeyLog>>,
pub transport: Arc<TransportConfig>,
}

pub trait ToLibp2p {
fn to_public(&self) -> libp2p_core::identity::PublicKey;
fn to_peer_id(&self) -> PeerId {
self.to_public().to_peer_id()
}
}

#[cfg(feature = "tls")]
impl ToLibp2p for libp2p_core::identity::Keypair {
fn to_public(&self) -> libp2p_core::identity::PublicKey {
self.public()
}
}

pub trait Crypto: std::fmt::Debug + Clone + 'static {
type Session: Session + Unpin;
type Keylogger: Send + Sync;
type Keypair: Send + Sync + ToLibp2p;
type PublicKey: Send + std::fmt::Debug + PartialEq<Self::PublicKey>;

fn new_server_config(
config: &CryptoConfig<Self>,
) -> <Self::Session as Session>::ServerConfig;
fn new_client_config(
config: &CryptoConfig<Self>,
remote_public: Self::PublicKey,
) -> <Self::Session as Session>::ClientConfig;
fn supported_quic_versions() -> Vec<u32>;
fn default_quic_version() -> u32;
fn peer_id(session: &Self::Session) -> Option<PeerId>;
fn extract_public_key(generic_key: libp2p_core::PublicKey) -> Option<Self::PublicKey>;
fn keylogger() -> Self::Keylogger;
}

#[cfg(feature = "tls")]
#[derive(Clone, Copy, Debug)]
pub struct TlsCrypto;
pub(crate) struct TlsCrypto;

#[cfg(feature = "tls")]
impl Crypto for TlsCrypto {
type Session = quinn_proto::crypto::rustls::TlsSession;
type Keylogger = Arc<dyn rustls::KeyLog>;
type Keypair = libp2p_core::identity::Keypair;
type PublicKey = libp2p_core::identity::PublicKey;
impl TlsCrypto {

fn new_server_config(
config: &CryptoConfig<Self>,
) -> <Self::Session as Session>::ServerConfig {
pub fn new_server_config(
config: &CryptoConfig,
) -> <quinn_proto::crypto::rustls::TlsSession as Session>::ServerConfig {
let mut server = crate::tls::make_server_config(&config.keypair).expect("invalid config");
if let Some(key_log) = config.keylogger.clone() {
server.key_log = key_log;
}
Arc::new(server)
}

fn new_client_config(
config: &CryptoConfig<Self>,
remote_public: Self::PublicKey,
) -> <Self::Session as Session>::ClientConfig {
pub fn new_client_config(
config: &CryptoConfig,
remote_public: PublicKey,
) -> <quinn_proto::crypto::rustls::TlsSession as Session>::ClientConfig {
let mut client =
crate::tls::make_client_config(&config.keypair, remote_public.to_peer_id())
.expect("invalid config");
Expand All @@ -97,26 +57,15 @@ impl Crypto for TlsCrypto {
Arc::new(client)
}

fn supported_quic_versions() -> Vec<u32> {
pub fn supported_quic_versions() -> Vec<u32> {
quinn_proto::DEFAULT_SUPPORTED_VERSIONS.to_vec()
}

fn default_quic_version() -> u32 {
pub fn default_quic_version() -> u32 {
quinn_proto::DEFAULT_SUPPORTED_VERSIONS[0]
}

fn peer_id(session: &Self::Session) -> Option<PeerId> {
let certificate = session.get_peer_certificates()?.into_iter().next()?;
Some(crate::tls::extract_peerid_or_panic(
quinn_proto::Certificate::from(certificate).as_der(),
))
}

fn extract_public_key(generic_key: libp2p_core::PublicKey) -> Option<Self::PublicKey> {
Some(generic_key)
}

fn keylogger() -> Self::Keylogger {
pub fn keylogger() -> Arc<dyn rustls::KeyLog> {
Arc::new(rustls::KeyLogFile::new())
}
}
99 changes: 46 additions & 53 deletions transports/quic/src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use crate::crypto::{Crypto, CryptoConfig};
use crate::crypto::{CryptoConfig, TlsCrypto};
use crate::muxer::QuicMuxer;
use crate::{QuicConfig, QuicError};
use futures::channel::{mpsc, oneshot};
use futures::prelude::*;
use quinn_proto::crypto::Session;
use quinn_proto::generic::{ClientConfig, ServerConfig};
use quinn_proto::{ServerConfig as QuinnServerConfig};
use quinn_proto::generic::{ClientConfig as QuinnClientConfig};
use quinn_proto::{
ConnectionEvent, ConnectionHandle, DatagramEvent, EcnCodepoint, EndpointEvent, Transmit,
};
use libp2p_core::identity::PublicKey;
use std::collections::{HashMap, VecDeque};
use std::io::IoSliceMut;
use std::mem::MaybeUninit;
Expand All @@ -40,15 +41,15 @@ use udp_socket::{RecvMeta, SocketType, UdpCapabilities, UdpSocket, BATCH_SIZE};

/// Message sent to the endpoint background task.
#[derive(Debug)]
enum ToEndpoint<C: Crypto> {
enum ToEndpoint {
/// Instructs the endpoint to start connecting to the given address.
Dial {
/// UDP address to connect to.
addr: SocketAddr,
/// The remotes public key.
public_key: C::PublicKey,
public_key: PublicKey,
/// Channel to return the result of the dialing to.
tx: oneshot::Sender<Result<QuicMuxer<C>, QuicError>>,
tx: oneshot::Sender<Result<QuicMuxer, QuicError>>,
},
/// Sent by a `quinn_proto` connection when the endpoint needs to process an event generated
/// by a connection. The event itself is opaque to us.
Expand All @@ -61,19 +62,19 @@ enum ToEndpoint<C: Crypto> {
}

#[derive(Debug)]
pub struct TransportChannel<C: Crypto> {
tx: mpsc::UnboundedSender<ToEndpoint<C>>,
rx: mpsc::Receiver<Result<QuicMuxer<C>, QuicError>>,
pub struct TransportChannel {
tx: mpsc::UnboundedSender<ToEndpoint>,
rx: mpsc::Receiver<Result<QuicMuxer, QuicError>>,
port: u16,
ty: SocketType,
}

impl<C: Crypto> TransportChannel<C> {
impl TransportChannel {
pub fn dial(
&mut self,
addr: SocketAddr,
public_key: C::PublicKey,
) -> oneshot::Receiver<Result<QuicMuxer<C>, QuicError>> {
public_key: PublicKey,
) -> oneshot::Receiver<Result<QuicMuxer, QuicError>> {
let (tx, rx) = oneshot::channel();
let msg = ToEndpoint::Dial {
addr,
Expand All @@ -87,7 +88,7 @@ impl<C: Crypto> TransportChannel<C> {
pub fn poll_incoming(
&mut self,
cx: &mut Context,
) -> Poll<Option<Result<QuicMuxer<C>, QuicError>>> {
) -> Poll<Option<Result<QuicMuxer, QuicError>>> {
Pin::new(&mut self.rx).poll_next(cx)
}

Expand All @@ -101,15 +102,15 @@ impl<C: Crypto> TransportChannel<C> {
}

#[derive(Debug)]
pub struct ConnectionChannel<C: Crypto> {
pub struct ConnectionChannel {
id: ConnectionHandle,
tx: mpsc::UnboundedSender<ToEndpoint<C>>,
tx: mpsc::UnboundedSender<ToEndpoint>,
rx: mpsc::Receiver<ConnectionEvent>,
port: u16,
max_datagrams: usize,
}

impl<C: Crypto> ConnectionChannel<C> {
impl ConnectionChannel {
pub fn poll_channel_events(&mut self, cx: &mut Context) -> Poll<ConnectionEvent> {
match Pin::new(&mut self.rx).poll_next(cx) {
Poll::Ready(Some(event)) => Poll::Ready(event),
Expand Down Expand Up @@ -141,23 +142,23 @@ impl<C: Crypto> ConnectionChannel<C> {
}

#[derive(Debug)]
struct EndpointChannel<C: Crypto> {
rx: mpsc::UnboundedReceiver<ToEndpoint<C>>,
tx: mpsc::Sender<Result<QuicMuxer<C>, QuicError>>,
struct EndpointChannel {
rx: mpsc::UnboundedReceiver<ToEndpoint>,
tx: mpsc::Sender<Result<QuicMuxer, QuicError>>,
port: u16,
max_datagrams: usize,
connection_tx: mpsc::UnboundedSender<ToEndpoint<C>>,
connection_tx: mpsc::UnboundedSender<ToEndpoint>,
}

impl<C: Crypto> EndpointChannel<C> {
pub fn poll_next_event(&mut self, cx: &mut Context) -> Poll<Option<ToEndpoint<C>>> {
impl EndpointChannel {
pub fn poll_next_event(&mut self, cx: &mut Context) -> Poll<Option<ToEndpoint>> {
Pin::new(&mut self.rx).poll_next(cx)
}

pub fn create_connection(
&self,
id: ConnectionHandle,
) -> (ConnectionChannel<C>, mpsc::Sender<ConnectionEvent>) {
) -> (ConnectionChannel, mpsc::Sender<ConnectionEvent>) {
let (tx, rx) = mpsc::channel(12);
let channel = ConnectionChannel {
id,
Expand All @@ -170,19 +171,19 @@ impl<C: Crypto> EndpointChannel<C> {
}
}

type QuinnEndpointConfig<S> = quinn_proto::generic::EndpointConfig<S>;
type QuinnEndpoint<S> = quinn_proto::generic::Endpoint<S>;
type QuinnEndpointConfig = quinn_proto::EndpointConfig;
type QuinnEndpoint = quinn_proto::Endpoint;

pub struct EndpointConfig<C: Crypto> {
pub struct EndpointConfig {
socket: UdpSocket,
endpoint: QuinnEndpoint<C::Session>,
endpoint: QuinnEndpoint,
port: u16,
crypto_config: Arc<CryptoConfig<C>>,
crypto_config: Arc<CryptoConfig>,
capabilities: UdpCapabilities,
}

impl<C: Crypto> EndpointConfig<C> {
pub fn new(mut config: QuicConfig<C>, addr: SocketAddr) -> Result<Self, QuicError> {
impl EndpointConfig {
pub fn new(mut config: QuicConfig, addr: SocketAddr) -> Result<Self, QuicError> {
config.transport.max_concurrent_uni_streams(0)?;
config.transport.datagram_receive_buffer_size(None);
let transport = Arc::new(config.transport);
Expand All @@ -193,13 +194,13 @@ impl<C: Crypto> EndpointConfig<C> {
transport: transport.clone(),
});

let mut server_config = ServerConfig::<C::Session>::default();
let mut server_config = QuinnServerConfig::default();
server_config.transport = transport;
server_config.crypto = C::new_server_config(&crypto_config);
server_config.crypto = TlsCrypto::new_server_config(&crypto_config);

let mut endpoint_config = QuinnEndpointConfig::default();
endpoint_config
.supported_versions(C::supported_quic_versions(), C::default_quic_version())?;
.supported_versions(TlsCrypto::supported_quic_versions(), TlsCrypto::default_quic_version())?;

let socket = UdpSocket::bind(addr)?;
let port = socket.local_addr()?.port();
Expand All @@ -217,11 +218,7 @@ impl<C: Crypto> EndpointConfig<C> {
})
}

pub fn spawn(self) -> TransportChannel<C>
where
<C::Session as Session>::ClientConfig: Send + Unpin,
<C::Session as Session>::HeaderKey: Unpin,
<C::Session as Session>::PacketKey: Unpin,
pub fn spawn(self) -> TransportChannel
{
let (tx1, rx1) = mpsc::unbounded();
let (tx2, rx2) = mpsc::channel(1);
Expand All @@ -243,20 +240,20 @@ impl<C: Crypto> EndpointConfig<C> {
}
}

struct Endpoint<C: Crypto> {
channel: EndpointChannel<C>,
endpoint: QuinnEndpoint<C::Session>,
struct Endpoint {
channel: EndpointChannel,
endpoint: QuinnEndpoint,
socket: UdpSocket,
crypto_config: Arc<CryptoConfig<C>>,
crypto_config: Arc<CryptoConfig>,
connections: HashMap<ConnectionHandle, mpsc::Sender<ConnectionEvent>>,
outgoing: VecDeque<udp_socket::Transmit>,
recv_buf: Box<[u8]>,
incoming_slot: Option<QuicMuxer<C>>,
incoming_slot: Option<QuicMuxer>,
event_slot: Option<(ConnectionHandle, ConnectionEvent)>,
}

impl<C: Crypto> Endpoint<C> {
pub fn new(channel: EndpointChannel<C>, config: EndpointConfig<C>) -> Self {
impl Endpoint {
pub fn new(channel: EndpointChannel, config: EndpointConfig) -> Self {
let max_udp_payload_size = config
.endpoint
.config()
Expand Down Expand Up @@ -291,7 +288,7 @@ impl<C: Crypto> Endpoint<C> {
self.outgoing.push_back(transmit);
}

fn send_incoming(&mut self, muxer: QuicMuxer<C>, cx: &mut Context) -> bool {
fn send_incoming(&mut self, muxer: QuicMuxer, cx: &mut Context) -> bool {
assert!(self.incoming_slot.is_none());
match self.channel.tx.poll_ready(cx) {
Poll::Pending => {
Expand Down Expand Up @@ -328,11 +325,7 @@ impl<C: Crypto> Endpoint<C> {
}
}

impl<C: Crypto> Future for Endpoint<C>
where
<C::Session as Session>::ClientConfig: Unpin,
<C::Session as Session>::HeaderKey: Unpin,
<C::Session as Session>::PacketKey: Unpin,
impl Future for Endpoint
{
type Output = ();

Expand Down Expand Up @@ -363,8 +356,8 @@ where
public_key,
tx,
}) => {
let crypto = C::new_client_config(&me.crypto_config, public_key);
let client_config = ClientConfig {
let crypto = TlsCrypto::new_client_config(&me.crypto_config, public_key);
let client_config = QuinnClientConfig {
transport: me.crypto_config.transport.clone(),
crypto,
};
Expand Down
Loading

0 comments on commit f35fde1

Please sign in to comment.