Skip to content

Commit

Permalink
feat(s2n-quic-dc): import 7/18 version (#2275)
Browse files Browse the repository at this point in the history
  • Loading branch information
camshaft authored Jul 18, 2024
1 parent 2c95dd9 commit fcd9a1b
Show file tree
Hide file tree
Showing 65 changed files with 6,318 additions and 2,268 deletions.
6 changes: 4 additions & 2 deletions dc/s2n-quic-dc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ license = "Apache-2.0"
exclude = ["corpus.tar.gz"]

[features]
default = ["tokio"]
testing = ["bolero-generator", "s2n-quic-core/testing"]
tokio = ["tokio/io-util", "tokio/net", "tokio/rt-multi-thread", "tokio/time"]

[dependencies]
arrayvec = "0.7"
Expand All @@ -35,7 +37,7 @@ s2n-quic-core = { version = "=0.42.0", path = "../../quic/s2n-quic-core", defaul
s2n-quic-platform = { version = "=0.42.0", path = "../../quic/s2n-quic-platform" }
slotmap = "1"
thiserror = "1"
tokio = { version = "1", features = ["sync"] }
tokio = { version = "1", default-features = false, features = ["sync"] }
tracing = "0.1"
zerocopy = { version = "0.7", features = ["derive"] }
zeroize = "1"
Expand All @@ -46,4 +48,4 @@ bolero-generator = "0.11"
insta = "1"
s2n-codec = { path = "../../common/s2n-codec", features = ["testing"] }
s2n-quic-core = { path = "../../quic/s2n-quic-core", features = ["testing"] }
tokio = { version = "1", features = ["sync"] }
tokio = { version = "1", features = ["full"] }
1 change: 1 addition & 0 deletions dc/s2n-quic-dc/src/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use core::{fmt, pin::Pin, task::Poll, time::Duration};
use s2n_quic_core::{ensure, time};
use tracing::trace;

#[cfg(feature = "tokio")]
pub mod tokio;
pub use time::clock::Cached;

Expand Down
5 changes: 5 additions & 0 deletions dc/s2n-quic-dc/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub mod encrypt {
pub trait Key {
fn credentials(&self) -> &Credentials;

fn key_phase(&self) -> KeyPhase;

fn tag_len(&self) -> usize;

/// Encrypt a payload
Expand Down Expand Up @@ -75,6 +77,7 @@ pub mod decrypt {
/// Decrypt a payload
fn decrypt<N: IntoNonce>(
&self,
key_phase: KeyPhase,
nonce: N,
header: &[u8],
payload_in: &[u8],
Expand All @@ -85,13 +88,15 @@ pub mod decrypt {
/// Decrypt a payload
fn decrypt_in_place<N: IntoNonce>(
&self,
key_phase: KeyPhase,
nonce: N,
header: &[u8],
payload_and_tag: &mut [u8],
) -> Result;

fn retransmission_tag(
&self,
key_phase: KeyPhase,
original_packet_number: u64,
retransmission_packet_number: u64,
tag_out: &mut [u8],
Expand Down
10 changes: 9 additions & 1 deletion dc/s2n-quic-dc/src/crypto/awslc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use super::IntoNonce;
use crate::credentials::Credentials;
use aws_lc_rs::aead::{Aad, Algorithm, LessSafeKey, Nonce, UnboundKey, NONCE_LEN};
use s2n_quic_core::assume;
use s2n_quic_core::{assume, packet::KeyPhase};

pub use aws_lc_rs::aead::{AES_128_GCM, AES_256_GCM};

Expand Down Expand Up @@ -41,6 +41,11 @@ impl super::encrypt::Key for EncryptKey {
&self.credentials
}

#[inline]
fn key_phase(&self) -> KeyPhase {
KeyPhase::Zero
}

#[inline(always)]
fn tag_len(&self) -> usize {
debug_assert_eq!(TAG_LEN, self.key.algorithm().tag_len());
Expand Down Expand Up @@ -137,6 +142,7 @@ impl super::decrypt::Key for DecryptKey {
#[inline]
fn decrypt<N: IntoNonce>(
&self,
_key_phase: KeyPhase,
nonce: N,
header: &[u8],
payload_in: &[u8],
Expand All @@ -163,6 +169,7 @@ impl super::decrypt::Key for DecryptKey {
#[inline]
fn decrypt_in_place<N: IntoNonce>(
&self,
_key_phase: KeyPhase,
nonce: N,
header: &[u8],
payload_and_tag: &mut [u8],
Expand All @@ -180,6 +187,7 @@ impl super::decrypt::Key for DecryptKey {
#[inline]
fn retransmission_tag(
&self,
_key_phase: KeyPhase,
original_packet_number: u64,
retransmission_packet_number: u64,
tag_out: &mut [u8],
Expand Down
10 changes: 9 additions & 1 deletion dc/s2n-quic-dc/src/crypto/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use super::IntoNonce;
use crate::credentials::Credentials;
use s2n_quic_core::assume;
use s2n_quic_core::{assume, packet::KeyPhase};

#[derive(Clone, Debug)]
pub struct Key {
Expand All @@ -27,6 +27,11 @@ impl super::encrypt::Key for Key {
&self.credentials
}

#[inline]
fn key_phase(&self) -> KeyPhase {
KeyPhase::Zero
}

#[inline]
fn tag_len(&self) -> usize {
self.tag_len
Expand Down Expand Up @@ -77,6 +82,7 @@ impl super::decrypt::Key for Key {
#[inline]
fn decrypt<N: IntoNonce>(
&self,
_key_phase: KeyPhase,
_nonce: N,
_header: &[u8],
payload_in: &[u8],
Expand All @@ -90,6 +96,7 @@ impl super::decrypt::Key for Key {
#[inline]
fn decrypt_in_place<N: IntoNonce>(
&self,
_key_phase: KeyPhase,
_nonce: N,
_header: &[u8],
_payload_and_tag: &mut [u8],
Expand All @@ -100,6 +107,7 @@ impl super::decrypt::Key for Key {
#[inline]
fn retransmission_tag(
&self,
_key_phase: KeyPhase,
_original_packet_number: u64,
_retransmission_packet_number: u64,
_tag_out: &mut [u8],
Expand Down
1 change: 1 addition & 0 deletions dc/s2n-quic-dc/src/datagram/tunneled/recv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ impl<K: decrypt::Key> Receiver<K> {
debug_assert_eq!(packet.payload().len(), payload_out.len());

self.key.decrypt(
packet.tag().key_phase(),
packet.crypto_nonce(),
packet.header(),
packet.payload(),
Expand Down
3 changes: 3 additions & 0 deletions dc/s2n-quic-dc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ pub mod socket;
pub mod stream;
pub mod task;

#[cfg(any(test, feature = "testing"))]
pub mod testing;

pub use s2n_quic_core::dc::{Version, SUPPORTED_VERSIONS};
26 changes: 26 additions & 0 deletions dc/s2n-quic-dc/src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,25 @@ pub type PayloadLen = VarInt;

#[macro_use]
pub mod tag;
pub mod wire_version;

pub mod control;
pub mod datagram;
pub mod secret_control;
pub mod stream;

pub use tag::Tag;
pub use wire_version::WireVersion;

#[derive(Clone, Copy, Debug)]
pub enum Kind {
Stream,
Datagram,
Control,
StaleKey,
ReplayDetected,
UnknownPathSecret,
}

#[derive(Debug)]
pub enum Packet<'a> {
Expand All @@ -28,6 +40,20 @@ pub enum Packet<'a> {
UnknownPathSecret(secret_control::unknown_path_secret::Packet<'a>),
}

impl<'a> Packet<'a> {
#[inline]
pub fn kind(&self) -> Kind {
match self {
Packet::Stream(_) => Kind::Stream,
Packet::Datagram(_) => Kind::Datagram,
Packet::Control(_) => Kind::Control,
Packet::StaleKey(_) => Kind::StaleKey,
Packet::ReplayDetected(_) => Kind::ReplayDetected,
Packet::UnknownPathSecret(_) => Kind::UnknownPathSecret,
}
}
}

impl<'a> s2n_codec::DecoderParameterizedValueMut<'a> for Packet<'a> {
type Parameter = usize;

Expand Down
25 changes: 23 additions & 2 deletions dc/s2n-quic-dc/src/packet/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use super::tag::Common;
use core::fmt;
use s2n_quic_core::packet::KeyPhase;
use zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned};

const NONCE_MASK: u64 = 1 << 63;
Expand All @@ -28,13 +29,15 @@ impl fmt::Debug for Tag {
f.debug_struct("control::Tag")
.field("is_stream", &self.is_stream())
.field("has_application_header", &self.has_application_header())
.field("key_phase", &self.key_phase())
.finish()
}
}

impl Tag {
pub const IS_STREAM_MASK: u8 = 0b0010;
pub const HAS_APPLICATION_HEADER_MASK: u8 = 0b00_0001;
pub const IS_STREAM_MASK: u8 = 0b0100;
pub const HAS_APPLICATION_HEADER_MASK: u8 = 0b0010;
pub const KEY_PHASE_MASK: u8 = 0b0001;

pub const MIN: u8 = 0b0101_0000;
pub const MAX: u8 = 0b0101_1111;
Expand All @@ -59,6 +62,24 @@ impl Tag {
self.0.get(Self::HAS_APPLICATION_HEADER_MASK)
}

#[inline]
pub fn set_key_phase(&mut self, key_phase: KeyPhase) {
let v = match key_phase {
KeyPhase::Zero => false,
KeyPhase::One => true,
};
self.0.set(Self::KEY_PHASE_MASK, v)
}

#[inline]
pub fn key_phase(&self) -> KeyPhase {
if self.0.get(Self::KEY_PHASE_MASK) {
KeyPhase::One
} else {
KeyPhase::Zero
}
}

#[inline]
fn validate(&self) -> Result<(), s2n_codec::DecoderError> {
let range = Self::MIN..=Self::MAX;
Expand Down
13 changes: 12 additions & 1 deletion dc/s2n-quic-dc/src/packet/control/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
credentials::Credentials,
packet::{
control::{self, Tag},
stream,
stream, WireVersion,
},
};
use s2n_codec::{
Expand Down Expand Up @@ -50,6 +50,7 @@ where
#[derive(Debug)]
pub struct Packet<'a> {
tag: Tag,
wire_version: WireVersion,
credentials: Credentials,
source_control_port: u16,
stream_id: Option<stream::Id>,
Expand All @@ -66,6 +67,11 @@ impl<'a> Packet<'a> {
self.tag
}

#[inline]
pub fn wire_version(&self) -> WireVersion {
self.wire_version
}

#[inline]
pub fn credentials(&self) -> &Credentials {
&self.credentials
Expand Down Expand Up @@ -124,6 +130,7 @@ impl<'a> Packet<'a> {
) -> R<Packet> {
let (
tag,
wire_version,
credentials,
source_control_port,
stream_id,
Expand All @@ -147,6 +154,8 @@ impl<'a> Packet<'a> {
let (tag, buffer) = buffer.decode()?;
validator.validate_tag(tag)?;

let (wire_version, buffer) = buffer.decode()?;

let (credentials, buffer) = buffer.decode()?;

let (source_control_port, buffer) = buffer.decode()?;
Expand Down Expand Up @@ -181,6 +190,7 @@ impl<'a> Packet<'a> {

(
tag,
wire_version,
credentials,
source_control_port,
stream_id,
Expand Down Expand Up @@ -222,6 +232,7 @@ impl<'a> Packet<'a> {

let packet = Packet {
tag,
wire_version,
credentials,
source_control_port,
stream_id,
Expand Down
17 changes: 7 additions & 10 deletions dc/s2n-quic-dc/src/packet/control/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
crypto::encrypt,
packet::{
control::{Tag, NONCE_MASK},
stream,
stream, WireVersion,
},
};
use s2n_codec::{Encoder, EncoderBuffer, EncoderValue};
Expand All @@ -31,19 +31,16 @@ where
debug_assert_ne!(source_control_port, 0);

let mut tag = Tag::default();
tag.set_key_phase(crypto.key_phase());
tag.set_is_stream(stream_id.is_some());
tag.set_has_application_header(*header_len > 0);
encoder.encode(&tag);

if stream_id.is_some() {
tag.set_is_stream(true);
}

if *header_len > 0 {
tag.set_has_application_header(true);
}
// wire version - we only support `0` currently
encoder.encode(&WireVersion::ZERO);

let nonce = *packet_number | NONCE_MASK;

encoder.encode(&tag);

// encode the credentials being used
encoder.encode(crypto.credentials());
encoder.encode(&source_control_port);
Expand Down
Loading

0 comments on commit fcd9a1b

Please sign in to comment.