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

feat(s2n-quic-dc): import 7/18 version #2275

Merged
merged 1 commit into from
Jul 18, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading