use std::sync::Arc;
use bytes::BytesMut;
use quinn_proto::{
ConnectionId, PathId, Side, TransportError,
crypto::{
self, CryptoError,
rustls::{QuicClientConfig, QuicServerConfig},
},
transport_parameters,
};
struct NoProtectionSession {
inner: Box<dyn crypto::Session>,
}
impl NoProtectionSession {
fn new(tls: Box<dyn crypto::Session>) -> Self {
Self { inner: tls }
}
fn wrap_packet_keys(
keys: crypto::KeyPair<Box<dyn crypto::PacketKey>>,
) -> crypto::KeyPair<Box<dyn crypto::PacketKey>> {
crypto::KeyPair {
local: Box::new(NoProtectionPacketKey::new(keys.local)),
remote: Box::new(NoProtectionPacketKey::new(keys.remote)),
}
}
}
struct NoProtectionPacketKey {
inner: Box<dyn crypto::PacketKey>,
}
impl NoProtectionPacketKey {
fn new(key: Box<dyn crypto::PacketKey>) -> Self {
Self { inner: key }
}
}
pub struct NoProtectionClientConfig {
inner: Arc<QuicClientConfig>,
}
impl NoProtectionClientConfig {
pub fn new(config: Arc<QuicClientConfig>) -> Self {
Self { inner: config }
}
}
pub struct NoProtectionServerConfig {
inner: Arc<QuicServerConfig>,
}
impl NoProtectionServerConfig {
pub fn new(config: Arc<QuicServerConfig>) -> Self {
Self { inner: config }
}
}
impl crypto::Session for NoProtectionSession {
fn initial_keys(&self, dst_cid: ConnectionId, side: Side) -> crypto::Keys {
self.inner.initial_keys(dst_cid, side)
}
fn handshake_data(&self) -> Option<Box<dyn std::any::Any>> {
self.inner.handshake_data()
}
fn peer_identity(&self) -> Option<Box<dyn std::any::Any>> {
self.inner.peer_identity()
}
fn early_crypto(&self) -> Option<(Box<dyn crypto::HeaderKey>, Box<dyn crypto::PacketKey>)> {
let (hkey, pkey) = self.inner.early_crypto()?;
Some((hkey, Box::new(NoProtectionPacketKey::new(pkey))))
}
fn early_data_accepted(&self) -> Option<bool> {
self.inner.early_data_accepted()
}
fn is_handshaking(&self) -> bool {
self.inner.is_handshaking()
}
fn read_handshake(&mut self, buf: &[u8]) -> Result<bool, TransportError> {
self.inner.read_handshake(buf)
}
fn transport_parameters(
&self,
) -> Result<Option<transport_parameters::TransportParameters>, TransportError> {
self.inner.transport_parameters()
}
fn write_handshake(&mut self, buf: &mut Vec<u8>) -> Option<crypto::Keys> {
let keys = self.inner.write_handshake(buf)?;
Some(crypto::Keys {
header: keys.header,
packet: Self::wrap_packet_keys(keys.packet),
})
}
fn next_1rtt_keys(&mut self) -> Option<crypto::KeyPair<Box<dyn crypto::PacketKey>>> {
let keys = self.inner.next_1rtt_keys()?;
Some(Self::wrap_packet_keys(keys))
}
fn is_valid_retry(&self, orig_dst_cid: ConnectionId, header: &[u8], payload: &[u8]) -> bool {
self.inner.is_valid_retry(orig_dst_cid, header, payload)
}
fn export_keying_material(
&self,
output: &mut [u8],
label: &[u8],
context: &[u8],
) -> Result<(), crypto::ExportKeyingMaterialError> {
self.inner.export_keying_material(output, label, context)
}
}
impl crypto::ClientConfig for NoProtectionClientConfig {
fn start_session(
self: std::sync::Arc<Self>,
version: u32,
server_name: &str,
params: &transport_parameters::TransportParameters,
) -> Result<Box<dyn crypto::Session>, quinn::ConnectError> {
let tls = self
.inner
.clone()
.start_session(version, server_name, params)?;
Ok(Box::new(NoProtectionSession::new(tls)))
}
}
impl crypto::ServerConfig for NoProtectionServerConfig {
fn initial_keys(
&self,
version: u32,
dst_cid: ConnectionId,
) -> Result<crypto::Keys, crypto::UnsupportedVersion> {
self.inner.initial_keys(version, dst_cid)
}
fn retry_tag(&self, version: u32, orig_dst_cid: ConnectionId, packet: &[u8]) -> [u8; 16] {
self.inner.retry_tag(version, orig_dst_cid, packet)
}
fn start_session(
self: Arc<Self>,
version: u32,
params: &transport_parameters::TransportParameters,
) -> Box<dyn crypto::Session> {
let tls = self.inner.clone().start_session(version, params);
Box::new(NoProtectionSession::new(tls))
}
}
impl crypto::PacketKey for NoProtectionPacketKey {
fn encrypt(&self, _path_id: PathId, _packet: u64, buf: &mut [u8], header_len: usize) {
let (_header, payload_tag) = buf.split_at_mut(header_len);
let (_payload, tag_storage) =
payload_tag.split_at_mut(payload_tag.len() - self.inner.tag_len());
tag_storage.fill(42);
}
fn decrypt(
&self,
_path_id: PathId,
_packet: u64,
_header: &[u8],
payload: &mut BytesMut,
) -> Result<(), CryptoError> {
let plain_len = payload.len() - self.inner.tag_len();
payload.truncate(plain_len);
Ok(())
}
fn tag_len(&self) -> usize {
self.inner.tag_len()
}
fn confidentiality_limit(&self) -> u64 {
self.inner.confidentiality_limit()
}
fn integrity_limit(&self) -> u64 {
self.inner.integrity_limit()
}
}