Skip to content

Commit

Permalink
s2n-quic-dc: initial commit (#2185)
Browse files Browse the repository at this point in the history
* s2n-quic-dc: initial commit

* update version to match other crates

* add copyright notices

* remove empty lines

* commenting out bench code

* move dc to its own folder and set default workspace members

* fix dc crate location

* fix loom

* don't include s2n-quic-dc in qns

* fix dependabot

* remove unneeded files

* Remove NotTrusted encryption error

* re-apply copyright

* Update secret control packets

* add s2n-quic-tls back to aarch64
  • Loading branch information
WesleyRosenblum committed Apr 20, 2024
1 parent e0f224b commit b862ad9
Show file tree
Hide file tree
Showing 75 changed files with 8,463 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ updates:
directory: "/tools/xdp"
schedule:
interval: "daily"

- package-ecosystem: "cargo"
directory: "/dc"
schedule:
interval: "daily"
24 changes: 14 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
# find all child folders in the examples directory
# jq -R - raw content is passed in (not json, just strings)
# jq -s - slurp the content into an object
# jq '. += ' adds the s2n-quic-xdp crate to the list of crates we build
# jq '. += ' adds the s2n-quic-xdp and s2n-quic-dc crates to the list of crates we build
# Many of the xdp crates have much more complex build processes, so we
# don't try to build all of them.
# jq -c - output the object in (c)ompact mode on a single line, github
Expand All @@ -63,7 +63,7 @@ jobs:
export EXAMPLES=$(find examples/ -maxdepth 1 -mindepth 1 -type d | jq -R | jq -sc)
echo "examples=$EXAMPLES"
echo "examples=$EXAMPLES" >> $GITHUB_OUTPUT
export CRATES=$(find quic common -name *Cargo.toml | jq -R | jq -s | jq '. += ["tools/xdp/s2n-quic-xdp/Cargo.toml"]' | jq -c)
export CRATES=$(find quic common -name *Cargo.toml | jq -R | jq -s | jq '. += ["tools/xdp/s2n-quic-xdp/Cargo.toml","dc/s2n-quic-dc/Cargo.toml"]' | jq -c)
echo "crates=$CRATES"
echo "crates=$CRATES" >> $GITHUB_OUTPUT
Expand Down Expand Up @@ -115,7 +115,7 @@ jobs:
#
# manual_clamp will panic when min > max
# See https://github.com/rust-lang/rust-clippy/pull/10101
cargo clippy --all-features --all-targets -- -A clippy::derive_partial_eq_without_eq -A clippy::manual_clamp ${{ matrix.args }}
cargo clippy --all-features --all-targets --workspace -- -A clippy::derive_partial_eq_without_eq -A clippy::manual_clamp ${{ matrix.args }}
udeps:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -196,11 +196,13 @@ jobs:
env: [default]
include:
- os: windows-latest
# s2n-tls doesn't currently build on windows
exclude: --workspace --exclude s2n-quic-tls
# s2n-tls and s2n-quic-dc don't currently build on windows
exclude: --exclude s2n-quic-tls --exclude s2n-quic-dc
- rust: stable
os: ubuntu-latest
target: aarch64-unknown-linux-gnu
# s2n-quic-dc doesn't currently build on aarch64
exclude: --exclude s2n-quic-dc
- rust: stable
os: ubuntu-latest
target: i686-unknown-linux-gnu
Expand All @@ -213,6 +215,8 @@ jobs:
os: ubuntu-latest
target: native
env: S2N_QUIC_PLATFORM_FEATURES_OVERRIDE=""
# s2n-quic-dc requires platform features
exclude: --exclude s2n-quic-dc
- rust: stable
os: ubuntu-latest
target: native
Expand Down Expand Up @@ -259,11 +263,11 @@ jobs:
# Build the tests before running to improve cross compilation speed
- name: Run cargo/cross build
run: |
${{ matrix.target != 'native' && 'cross' || 'cargo' }} build --tests ${{ matrix.exclude }} ${{ matrix.target != 'native' && format('--target {0}', matrix.target) || '' }} ${{ matrix.args }}
${{ matrix.target != 'native' && 'cross' || 'cargo' }} build --tests --workspace ${{ matrix.exclude }} ${{ matrix.target != 'native' && format('--target {0}', matrix.target) || '' }} ${{ matrix.args }}
- name: Run cargo/cross test
run: |
${{ matrix.target != 'native' && 'cross' || 'cargo' }} test ${{ matrix.exclude }} ${{ matrix.target != 'native' && format('--target {0}', matrix.target) || '' }} ${{ matrix.args }}
${{ matrix.target != 'native' && 'cross' || 'cargo' }} test --workspace ${{ matrix.exclude }} ${{ matrix.target != 'native' && format('--target {0}', matrix.target) || '' }} ${{ matrix.args }}
miri:
# miri needs quite a bit of memory so use a larger instance
Expand Down Expand Up @@ -593,7 +597,7 @@ jobs:

- name: Run cargo insta test
run: |
cargo insta test --delete-unreferenced-snapshots
cargo insta test --all --delete-unreferenced-snapshots
- name: Check to make sure there are no unused snapshots
run: |
Expand All @@ -618,7 +622,7 @@ jobs:
- name: Run cargo build
run: |
cd examples/echo
cargo build --timings --release
cargo build --timings --release --workspace
- uses: aws-actions/[email protected]
if: github.event_name == 'push' || github.repository == github.event.pull_request.head.repo.full_name
Expand Down Expand Up @@ -698,7 +702,7 @@ jobs:

- name: Run cargo build
working-directory: tools/memory-report
run: cargo build --release
run: cargo build --release --workspace

- name: Run server
working-directory: tools/memory-report
Expand Down
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
members = [
"common/s2n-*",
"quic/s2n-*",
"dc/s2n-*",
]
default-members = [
"common/s2n-*",
"quic/s2n-*",
]
resolver = "2"
# don't include any workspaces outside of the main project
Expand Down
36 changes: 36 additions & 0 deletions dc/s2n-quic-dc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[package]
name = "s2n-quic-dc"
version = "0.36.0"
description = "Internal crate used by s2n-quic"
repository = "https://github.com/aws/s2n-quic"
authors = ["AWS s2n"]
edition = "2021"
rust-version = "1.71"
license = "Apache-2.0"
# Exclude corpus files when publishing to crates.io
exclude = ["corpus.tar.gz"]

[features]
testing = []

[dependencies]
atomic-waker = "1"
aws-lc-rs = "1"
bytes = "1"
crossbeam-channel = "0.5"
libc = "0.2"
num-rational = { version = "0.4", default-features = false }
once_cell = "1"
s2n-codec = { version = "=0.36.0", path = "../../common/s2n-codec", default-features = false }
s2n-quic-core = { version = "=0.36.0", path = "../../quic/s2n-quic-core", default-features = false }
s2n-quic-platform = { version = "=0.36.0", path = "../../quic/s2n-quic-platform" }
thiserror = "1"
tokio = { version = "1", features = ["io-util"], optional = true }
tracing = "0.1"
zerocopy = { version = "0.7", features = ["derive"] }

[dev-dependencies]
bolero = "0.10"
s2n-codec = { path = "../../common/s2n-codec", features = ["testing"] }
s2n-quic-core = { path = "../../quic/s2n-quic-core", features = ["testing"] }
tokio = { version = "1", features = ["io-util"] }
28 changes: 28 additions & 0 deletions dc/s2n-quic-dc/benches/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "benches"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
aws-lc-rs = "1"
criterion = { version = "0.4", features = ["html_reports"] }
s2n-codec = { path = "../../../common/s2n-codec" }
s2n-quic-dc = { path = "../../s2n-quic-dc", features = ["testing"] }

[[bench]]
name = "bench"
harness = false

[workspace]
members = ["."]

[profile.release]
lto = true
codegen-units = 1
incremental = false

[profile.bench]
lto = true
codegen-units = 1
incremental = false
7 changes: 7 additions & 0 deletions dc/s2n-quic-dc/benches/benches/bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use criterion::{criterion_group, criterion_main};

criterion_group!(benches, ::benches::benchmarks);
criterion_main!(benches);
12 changes: 12 additions & 0 deletions dc/s2n-quic-dc/benches/src/crypto.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use criterion::Criterion;

pub mod encrypt;
pub mod hkdf;

pub fn benchmarks(c: &mut Criterion) {
encrypt::benchmarks(c);
hkdf::benchmarks(c);
}
92 changes: 92 additions & 0 deletions dc/s2n-quic-dc/benches/src/crypto/encrypt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use criterion::{black_box, BenchmarkId, Criterion, Throughput};

pub fn benchmarks(c: &mut Criterion) {
let mut group = c.benchmark_group("crypto/encrypt");

let headers = [0, 16];

let payloads = [1, 100, 1000, 8900];

let inline = [
("aes_128_gcm", &aws_lc_rs::aead::AES_128_GCM),
("aes_256_gcm", &aws_lc_rs::aead::AES_256_GCM),
];

for payload_size in payloads {
let payload = black_box(vec![42u8; payload_size]);
for header_size in headers {
let header = black_box(vec![42u8; header_size]);

group.throughput(Throughput::Elements(1));

let input_name = format!("payload={payload_size},header={header_size}");

for (name, algo) in inline {
group.bench_with_input(
BenchmarkId::new(format!("{name}_reuse"), &input_name),
&(&header[..], &payload[..]),
|b, (header, payload)| {
let key = black_box(awslc::key(algo));
let mut payload = black_box(payload.to_vec());
let mut packet_number = 0u32;
b.iter(move || {
let _ = black_box(awslc::encrypt(
&key,
&mut packet_number,
header,
&mut payload,
));
});
},
);

group.bench_with_input(
BenchmarkId::new(format!("{name}_fresh"), &input_name),
&(&header[..], &payload[..]),
|b, (header, payload)| {
let mut payload = black_box(payload.to_vec());
let mut packet_number = 0u32;
b.iter(move || {
let key = black_box(awslc::key(algo));
let _ = black_box(awslc::encrypt(
&key,
&mut packet_number,
header,
&mut payload,
));
});
},
);
}
}
}
}

mod awslc {
use aws_lc_rs::aead::{Aad, Algorithm, LessSafeKey, Nonce, UnboundKey, NONCE_LEN};

#[inline(never)]
pub fn key(algo: &'static Algorithm) -> LessSafeKey {
let max_key = [42u8; 32];
let key = &max_key[..algo.key_len()];
let key = UnboundKey::new(algo, key).unwrap();
LessSafeKey::new(key)
}

#[inline(never)]
pub fn encrypt(key: &LessSafeKey, packet_number: &mut u32, header: &[u8], payload: &mut [u8]) {
let mut nonce = [0u8; NONCE_LEN];
nonce[NONCE_LEN - 8..].copy_from_slice(&(*packet_number as u64).to_be_bytes());
let nonce = Nonce::assume_unique_for_key(nonce);

let aad = Aad::from(header);
let mut tag = [0u8; 16];
key.seal_in_place_scatter(nonce, aad, payload, &[][..], &mut tag)
.unwrap();

*packet_number += 1;
}
}
92 changes: 92 additions & 0 deletions dc/s2n-quic-dc/benches/src/crypto/hkdf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use criterion::{black_box, BenchmarkId, Criterion, Throughput};

pub fn benchmarks(c: &mut Criterion) {
psk(c);
}

fn psk(c: &mut Criterion) {
let mut group = c.benchmark_group("crypto/hkdf/psk");

group.throughput(Throughput::Elements(1));

let prk_lens = [16, 32];
let key_lens = [16, 32, 64];
let label_lens = [1, 8, 16, 32, 64];
let algs = [
("sha256", awslc::HKDF_SHA256),
("sha384", awslc::HKDF_SHA384),
("sha512", awslc::HKDF_SHA512),
];

for prk_len in prk_lens {
for key_len in key_lens {
for label_len in label_lens {
for (alg_name, alg) in algs {
group.bench_with_input(
BenchmarkId::new(
format!("{alg_name}_reuse"),
format!("prk_len={prk_len},label_len={label_len},out_len={key_len}"),
),
&key_len,
|b, &key_len| {
let prk = black_box(awslc::prk(&vec![42u8; prk_len], alg));
let label = black_box(vec![42u8; label_len]);
let mut out = black_box(vec![0u8; key_len]);
b.iter(move || {
let _ = black_box(awslc::derive_psk(&prk, &label, &mut out));
});
},
);
group.bench_with_input(
BenchmarkId::new(
format!("{alg_name}_fresh"),
format!("prk_len={prk_len},label_len={label_len},out_len={key_len}"),
),
&key_len,
|b, &key_len| {
let key = black_box(vec![42u8; prk_len]);
let label = black_box(vec![42u8; label_len]);
let mut out = black_box(vec![0u8; key_len]);
b.iter(move || {
let prk = black_box(awslc::prk(&key, alg));
let _ = black_box(awslc::derive_psk(&prk, &label, &mut out));
});
},
);
}
}
}
}
}

mod awslc {
pub use aws_lc_rs::hkdf::*;

#[inline(never)]
pub fn prk(prk: &[u8], alg: Algorithm) -> Prk {
Prk::new_less_safe(alg, prk)
}

#[inline(never)]
pub fn derive_psk(prk: &Prk, label: &[u8], out: &mut [u8]) {
let out_len = out.len();
let out_len = OutLen(out_len);

prk.expand(&[&label], out_len)
.unwrap()
.fill(&mut out[..out_len.0])
.unwrap();
}

#[derive(Clone, Copy)]
struct OutLen(usize);

impl KeyType for OutLen {
fn len(&self) -> usize {
self.0
}
}
}
12 changes: 12 additions & 0 deletions dc/s2n-quic-dc/benches/src/datagram.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use criterion::Criterion;

mod recv;
mod send;

pub fn benchmarks(c: &mut Criterion) {
send::benches(c);
recv::benches(c);
}
Loading

0 comments on commit b862ad9

Please sign in to comment.