diff --git a/.github/actions/nss/action.yml b/.github/actions/nss/action.yml index 23232ebc13..ec6f13eaf8 100644 --- a/.github/actions/nss/action.yml +++ b/.github/actions/nss/action.yml @@ -16,16 +16,46 @@ inputs: runs: using: composite steps: + - name: Check system NSS version + shell: bash + run: | + if ! command -v pkg-config &> /dev/null; then + echo "BUILD_NSS=1" >> "$GITHUB_ENV" + exit 0 + fi + if ! pkg-config --exists nss; then + echo "BUILD_NSS=1" >> "$GITHUB_ENV" + exit 0 + fi + NSS_VERSION="$(pkg-config --modversion nss)" + if [ "$?" -ne 0 ]; then + echo "BUILD_NSS=1" >> "$GITHUB_ENV" + exit 0 + fi + NSS_MAJOR=$(echo "$NSS_VERSION" | cut -d. -f1) + NSS_MINOR=$(echo "$NSS_VERSION" | cut -d. -f2) + REQ_NSS_MAJOR=$(cat neqo-crypto/min_version.txt | cut -d. -f1) + REQ_NSS_MINOR=$(cat neqo-crypto/min_version.txt | cut -d. -f2) + if [ "$NSS_MAJOR" -lt "REQ_NSS_MAJOR" ] || [ "$NSS_MAJOR" -eq "REQ_NSS_MAJOR" -a "$NSS_MINOR" -lt "REQ_NSS_MINOR"]; then + echo "System NSS is too old: $NSS_VERSION" + echo "BUILD_NSS=1" >> "$GITHUB_ENV" + exit 0 + fi + echo "System NSS is suitable: $NSS_VERSION" + echo "BUILD_NSS=0" >> "$GITHUB_ENV" + # Ideally, we'd use this. But things are sufficiently flaky that we're better off # trying both hg and git. Leaving this here in case we want to re-try in the future. # # - name: Checkout NSPR + # if: env.BUILD_NSS == '1' # uses: actions/checkout@v4 # with: # repository: "nss-dev/nspr" # path: ${{ github.workspace }}/nspr # - name: Checkout NSS + # if: env.BUILD_NSS == '1' # uses: actions/checkout@v4 # with: # repository: "nss-dev/nss" @@ -33,18 +63,21 @@ runs: - name: Checkout NSPR shell: bash + if: env.BUILD_NSS == '1' run: | hg clone https://hg.mozilla.org/projects/nspr "${{ github.workspace }}/nspr" || \ git clone --depth=1 https://github.com/nss-dev/nspr "${{ github.workspace }}/nspr" - name: Checkout NSS shell: bash + if: env.BUILD_NSS == '1' run: | hg clone https://hg.mozilla.org/projects/nss "${{ github.workspace }}/nss" || \ git clone --depth=1 https://github.com/nss-dev/nss "${{ github.workspace }}/nss" - name: Build shell: bash + if: env.BUILD_NSS == '1' run: | if [ "${{ inputs.type }}" != "Debug" ]; then # We want to do an optimized build for accurate CPU profiling, but diff --git a/.github/actions/quic-interop-runner/action.yml b/.github/actions/quic-interop-runner/action.yml index ef4865bde6..30c7f0d8d6 100644 --- a/.github/actions/quic-interop-runner/action.yml +++ b/.github/actions/quic-interop-runner/action.yml @@ -92,8 +92,8 @@ runs: run: | echo '[**QUIC Interop Runner**](https://github.com/quic-interop/quic-interop-runner)' >> comment echo '' >> comment - # Ignore all, but table, which starts with "|:--". - cat quic-interop-runner/summary | awk '/^\|:--/{flag=1} flag' >> comment + # Ignore all, but table, which starts with "|". + grep -E '^\|' quic-interop-runner/summary >> comment echo '' >> comment shell: bash diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 9dc8ff2b7f..4e47961d8e 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -49,33 +49,21 @@ jobs: sudo apt-get install -y --no-install-recommends gyp mercurial ninja-build lld echo "RUSTFLAGS=-C link-arg=-fuse-ld=lld" >> "$GITHUB_ENV" - # In addition to installing dependencies, first make sure System Integrity Protection (SIP) - # is disabled on this MacOS runner. This is needed to allow the NSS libraries to be loaded - # from the build directory and avoid various other test failures. This seems to always be - # the case on any macos-13 runner, but not consistently on macos-latest (which is currently - # macos-12, FWIW). - name: Install dependencies (MacOS) if: runner.os == 'MacOS' run: | - csrutil status | grep disabled - brew install ninja mercurial llvm + brew update + brew install llvm nss echo "/opt/homebrew/opt/llvm/bin" >> "$GITHUB_PATH" - ln -s /opt/homebrew/bin/python3 /opt/homebrew/bin/python - # python3 -m pip install gyp-next - # Above does not work, since pypi only has gyp 0.15.0, which is too old - # for the homebrew python3. Install from source instead. - python3 -m pip install git+https://github.com/nodejs/gyp-next - python3 -m pip install packaging - echo "$(python3 -m site --user-base)/bin" >> "$GITHUB_PATH" echo "RUSTFLAGS=-C link-arg=-fuse-ld=lld" >> "$GITHUB_ENV" - - name: Use MSYS2 environment and install more dependencies (Windows) + - name: Install dependencies (Windows) if: runner.os == 'Windows' run: | # shellcheck disable=SC2028 { - echo "C:\\msys64\\usr\\bin" - echo "C:\\msys64\\mingw64\\bin" + echo C:/msys64/usr/bin + echo C:/msys64/mingw64/bin } >> "$GITHUB_PATH" /c/msys64/usr/bin/pacman -S --noconfirm nsinstall python3 -m pip install git+https://github.com/nodejs/gyp-next diff --git a/README.md b/README.md index 31d6ab9e94..beadf22ecf 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,102 @@ -# Neqo, an Implementation of QUIC written in Rust +# Neqo, an Implementation of QUIC in Rust ![neqo logo](https://github.com/mozilla/neqo/raw/main/neqo.png "neqo logo") -To run test HTTP/3 programs (neqo-client and neqo-server): +To build Neqo: -* `cargo build` -* `./target/debug/neqo-server '[::]:12345' --db ./test-fixture/db` -* `./target/debug/neqo-client http://127.0.0.1:12345/` - -If a "Failure to load dynamic library" error happens at runtime, do ```shell -export LD_LIBRARY_PATH="$(dirname "$(find . -name libssl3.so -print | head -1)")" +cargo build ``` -On a macOS, do +This will use a system-installed [NSS][NSS] library if it is new enough. (See "Build with Separate NSS/NSPR" below if NSS is not installed or it is deemed too old.) + +To run test HTTP/3 programs (`neqo-client` and `neqo-server`): + ```shell -export DYLD_LIBRARY_PATH="$(dirname "$(find . -name libssl3.dylib -print | head -1)")" +./target/debug/neqo-server '[::]:12345' +./target/debug/neqo-client 'https://[::]:12345/' ``` -## Faster Builds with Separate NSS/NSPR +## Build with separate NSS/NSPR -You can clone NSS (https://hg.mozilla.org/projects/nss) and NSPR -(https://hg.mozilla.org/projects/nspr) into the same directory and export an +You can clone [NSS][NSS] and [NSPR][NSPR] into the same directory and export an environment variable called `NSS_DIR` pointing to NSS. This causes the build to use the existing NSS checkout. However, in order to run anything that depends -on NSS, you need to set `$\[DY]LD\_LIBRARY\_PATH` to point to -`$NSS_DIR/../dist/Debug/lib`. +on NSS, you need to set an environment as follows: + +### Linux + +```shell +export LD_LIBRARY_PATH="$(dirname "$(find . -name libssl3.so -print | head -1)")" +``` + +### macOS + +```shell +export DYLD_LIBRARY_PATH="$(dirname "$(find . -name libssl3.dylib -print | head -1)")" +``` -Note: If you did not compile NSS separately, you need to have mercurial (hg), installed. -NSS builds require gyp, and ninja (or ninja-build) to be present also. +Note: If you did not already compile NSS separately, you need to have +[Mercurial (hg)][HG], installed. NSS builds require [GYP][GYP] and +[Ninja][NINJA] to be installed. ## Debugging Neqo -### QUIC Logging +### QUIC logging -Enable [QLOG](https://datatracker.ietf.org/doc/draft-ietf-quic-qlog-main-schema/) with: +Enable generation of [QLOG][QLOG] logs with: -``` -$ mkdir "$logdir" -$ ./target/debug/neqo-server '[::]:12345' --db ./test-fixture/db --qlog-dir "$logdir" -$ ./target/debug/neqo-client 'https://[::]:12345/' --qlog-dir "$logdir" +```shell +target/debug/neqo-server '[::]:12345' --qlog-dir . +target/debug/neqo-client 'https://[::]:12345/' --qlog-dir . ``` -You may use https://qvis.quictools.info/ by uploading the QLOG files and visualize the flows. +You can of course specify a different directory for the QLOG files. +You can upload QLOG files to [qvis][QVIS] to visualize the flows. -### Using SSLKEYLOGFILE to decrypt Wireshark logs +### Using `SSLKEYLOGFILE` to decrypt Wireshark logs -[Info here](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format) - -TODO: What is the minimum Wireshark version needed? -TODO: Above link may be incorrect, protocol now called TLS instead of SSL? +You can export TLS keys by setting the `SSLKEYLOGFILE` environment variable +to a filename to instruct NSS to dump keys in the +[standard format](https://datatracker.ietf.org/doc/draft-ietf-tls-keylogfile/) +to enable decryption by [Wireshark](https://wiki.wireshark.org/TLS) and other tools. ### Using RUST_LOG effectively As documented in the [env_logger documentation](https://docs.rs/env_logger/), the `RUST_LOG` environment variable can be used to selectively enable log messages -from Rust code. This works for Neqo's cmdline tools, as well as for when Neqo is +from Rust code. This works for Neqo's command line tools, as well as for when Neqo is incorporated into Gecko, although [Gecko needs to be built in debug mode](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Configuring_Build_Options). Some examples: -1. `RUST_LOG=neqo_transport::dump ./mach run` lists sent and received QUIC - packets and their frames' contents only. -1. `RUST_LOG=neqo_transport=debug,neqo_http3=trace,info ./mach run` sets a - 'debug' log level for transport, 'trace' level for http3, and 'info' log + +1. ```shell + RUST_LOG=neqo_transport::dump ./mach run + ``` + + lists sent and received QUIC packets and their frames' contents only. + +1. ```shell + RUST_LOG=neqo_transport=debug,neqo_http3=trace,info ./mach run + ``` + + sets a `debug` log level for `transport`, `trace` level for `http3`, and `info` log level for all other Rust crates, both Neqo and others used by Gecko. -1. `RUST_LOG=neqo=trace,error ./mach run` sets `trace` level for all modules - starting with "neqo", and sets `error` as minimum log level for other - unrelated Rust log messages. +1. ```shell + RUST_LOG=neqo=trace,error ./mach run + ``` + + sets `trace` level for all modules starting with `neqo`, and sets `error` as minimum log level for other unrelated Rust log messages. -### Trying In-development Neqo code in Gecko +### Trying in-development Neqo code in Gecko In a checked-out copy of Gecko source, set `[patches.*]` values for the four Neqo crates to local versions in the root `Cargo.toml`. For example, if Neqo was checked out to `/home/alice/git/neqo`, add the following lines to the root `Cargo.toml`. -``` +```toml [patch."https://github.com/mozilla/neqo"] neqo-http3 = { path = "/home/alice/git/neqo/neqo-http3" } neqo-transport = { path = "/home/alice/git/neqo/neqo-transport" } @@ -87,11 +107,23 @@ neqo-crypto = { path = "/home/alice/git/neqo/neqo-crypto" } Then run the following: -``` +```shell ./mach vendor rust ``` -Compile Gecko as usual with `./mach build`. +Compile Gecko as usual with + +```shell +./mach build +``` Note: Using newer Neqo code with Gecko may also require changes (likely to `neqo_glue`) if something has changed. + +[NSS]: https://hg.mozilla.org/projects/nss +[NSPR]: https://hg.mozilla.org/projects/nspr +[GYP]: https://github.com/nodejs/gyp-next +[HG]: https://www.mercurial-scm.org/ +[NINJA]: https://ninja-build.org/ +[QLOG]: https://datatracker.ietf.org/doc/draft-ietf-quic-qlog-main-schema/ +[QVIS]: https://qvis.quictools.info/ diff --git a/neqo-bin/src/bin/server/main.rs b/neqo-bin/src/bin/server/main.rs index c3470c4c72..d7cad45fc0 100644 --- a/neqo-bin/src/bin/server/main.rs +++ b/neqo-bin/src/bin/server/main.rs @@ -5,6 +5,7 @@ // except according to those terms. use std::{ + borrow::Cow, cell::RefCell, cmp::min, collections::HashMap, @@ -196,7 +197,7 @@ trait HttpServer: Display { } struct ResponseData { - data: Vec, + data: Cow<'static, [u8]>, offset: usize, remaining: usize, } @@ -211,7 +212,7 @@ impl From> for ResponseData { fn from(data: Vec) -> Self { let remaining = data.len(); Self { - data, + data: Cow::Owned(data), offset: 0, remaining, } @@ -219,9 +220,9 @@ impl From> for ResponseData { } impl ResponseData { - fn repeat(buf: &[u8], total: usize) -> Self { + fn repeat(buf: &'static [u8], total: usize) -> Self { Self { - data: buf.to_owned(), + data: Cow::Borrowed(buf), offset: 0, remaining: total, } @@ -260,14 +261,7 @@ struct SimpleServer { } impl SimpleServer { - const MESSAGE: &'static [u8] = b"I am the very model of a modern Major-General,\n\ - I've information vegetable, animal, and mineral,\n\ - I know the kings of England, and I quote the fights historical\n\ - From Marathon to Waterloo, in order categorical;\n\ - I'm very well acquainted, too, with matters mathematical,\n\ - I understand equations, both the simple and quadratical,\n\ - About binomial theorem, I'm teeming with a lot o' news,\n\ - With many cheerful facts about the square of the hypotenuse.\n"; + const MESSAGE: &'static [u8] = &[0; 4096]; pub fn new( args: &Args, diff --git a/neqo-common/src/datagram.rs b/neqo-common/src/datagram.rs index c286b79e12..2f2bb53766 100644 --- a/neqo-common/src/datagram.rs +++ b/neqo-common/src/datagram.rs @@ -54,12 +54,6 @@ impl Datagram { self.ttl } - #[cfg(feature = "udp")] - #[must_use] - pub(crate) fn into_data(self) -> Vec { - self.d - } - pub fn set_tos(&mut self, tos: IpTos) { self.tos = tos; } diff --git a/neqo-crypto/Cargo.toml b/neqo-crypto/Cargo.toml index 588d084741..47337d99c0 100644 --- a/neqo-crypto/Cargo.toml +++ b/neqo-crypto/Cargo.toml @@ -21,6 +21,7 @@ neqo-common = { path = "../neqo-common" } # Sync with https://searchfox.org/mozilla-central/source/Cargo.lock 2024-02-08 bindgen = { version = "0.69", default-features = false, features = ["runtime"] } mozbuild = { version = "0.1", default-features = false, optional = true } +semver = { version = "1.0", default-features = false } serde = { version = "1.0", default-features = false } serde_derive = { version = "1.0", default-features = false } toml = { version = "0.5", default-features = false } @@ -30,7 +31,7 @@ test-fixture = { path = "../test-fixture" } [features] gecko = ["mozbuild"] -fuzzing = [] +disable-encryption = [] [lib] # See https://github.com/bheisler/criterion.rs/blob/master/book/src/faq.md#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options diff --git a/neqo-crypto/bindings/bindings.toml b/neqo-crypto/bindings/bindings.toml index 3e5c1fdf7d..72c6d524d5 100644 --- a/neqo-crypto/bindings/bindings.toml +++ b/neqo-crypto/bindings/bindings.toml @@ -265,8 +265,3 @@ enums = [ [nspr_time] types = ["PRTime"] functions = ["PR_Now"] - -[mozpkix] -cplusplus = true -types = ["mozilla::pkix::ErrorCode"] -enums = ["mozilla::pkix::ErrorCode"] diff --git a/neqo-crypto/bindings/mozpkix.hpp b/neqo-crypto/bindings/mozpkix.hpp deleted file mode 100644 index d0a6cb5861..0000000000 --- a/neqo-crypto/bindings/mozpkix.hpp +++ /dev/null @@ -1 +0,0 @@ -#include "mozpkix/pkixnss.h" \ No newline at end of file diff --git a/neqo-crypto/build.rs b/neqo-crypto/build.rs index c4c2a73e75..2dd4543797 100644 --- a/neqo-crypto/build.rs +++ b/neqo-crypto/build.rs @@ -12,8 +12,13 @@ use std::{ }; use bindgen::Builder; +use semver::{Version, VersionReq}; use serde_derive::Deserialize; +#[path = "src/min_version.rs"] +mod min_version; +use min_version::MINIMUM_NSS_VERSION; + const BINDINGS_DIR: &str = "bindings"; const BINDINGS_CONFIG: &str = "bindings.toml"; @@ -90,46 +95,6 @@ fn setup_clang() { } } -fn nss_dir() -> PathBuf { - let dir = if let Ok(dir) = env::var("NSS_DIR") { - let path = PathBuf::from(dir.trim()); - assert!( - !path.is_relative(), - "The NSS_DIR environment variable is expected to be an absolute path." - ); - path - } else { - let out_dir = env::var("OUT_DIR").unwrap(); - let dir = Path::new(&out_dir).join("nss"); - if !dir.exists() { - Command::new("hg") - .args([ - "clone", - "https://hg.mozilla.org/projects/nss", - dir.to_str().unwrap(), - ]) - .status() - .expect("can't clone nss"); - } - let nspr_dir = Path::new(&out_dir).join("nspr"); - if !nspr_dir.exists() { - Command::new("hg") - .args([ - "clone", - "https://hg.mozilla.org/projects/nspr", - nspr_dir.to_str().unwrap(), - ]) - .status() - .expect("can't clone nspr"); - } - dir - }; - assert!(dir.is_dir(), "NSS_DIR {dir:?} doesn't exist"); - // Note that this returns a relative path because UNC - // paths on windows cause certain tools to explode. - dir -} - fn get_bash() -> PathBuf { // If BASH is set, use that. if let Ok(bash) = env::var("BASH") { @@ -295,11 +260,63 @@ fn build_bindings(base: &str, bindings: &Bindings, flags: &[String], gecko: bool .expect("couldn't write bindings"); } -fn setup_standalone() -> Vec { +fn pkg_config() -> Vec { + let modversion = Command::new("pkg-config") + .args(["--modversion", "nss"]) + .output() + .expect("pkg-config reports NSS as absent") + .stdout; + let modversion = String::from_utf8(modversion).expect("non-UTF8 from pkg-config"); + let modversion = modversion.trim(); + // The NSS version number does not follow semver numbering, because it omits the patch version + // when that's 0. Deal with that. + let modversion_for_cmp = if modversion.chars().filter(|c| *c == '.').count() == 1 { + modversion.to_owned() + ".0" + } else { + modversion.to_owned() + }; + let modversion_for_cmp = + Version::parse(&modversion_for_cmp).expect("NSS version not in semver format"); + let version_req = VersionReq::parse(&format!(">={}", MINIMUM_NSS_VERSION.trim())).unwrap(); + assert!( + version_req.matches(&modversion_for_cmp), + "neqo has NSS version requirement {version_req}, found {modversion}" + ); + + let cfg = Command::new("pkg-config") + .args(["--cflags", "--libs", "nss"]) + .output() + .expect("NSS flags not returned by pkg-config") + .stdout; + let cfg_str = String::from_utf8(cfg).expect("non-UTF8 from pkg-config"); + + let mut flags: Vec = Vec::new(); + for f in cfg_str.split(' ') { + if let Some(include) = f.strip_prefix("-I") { + flags.push(String::from(f)); + println!("cargo:include={include}"); + } else if let Some(path) = f.strip_prefix("-L") { + println!("cargo:rustc-link-search=native={path}"); + } else if let Some(lib) = f.strip_prefix("-l") { + println!("cargo:rustc-link-lib=dylib={lib}"); + } else { + println!("Warning: Unknown flag from pkg-config: {f}"); + } + } + + flags +} + +fn setup_standalone(nss: &str) -> Vec { setup_clang(); println!("cargo:rerun-if-env-changed=NSS_DIR"); - let nss = nss_dir(); + let nss = PathBuf::from(nss); + assert!( + !nss.is_relative(), + "The NSS_DIR environment variable is expected to be an absolute path." + ); + build_nss(nss.clone()); // $NSS_DIR/../dist/ @@ -406,8 +423,10 @@ fn setup_for_gecko() -> Vec { fn main() { let flags = if cfg!(feature = "gecko") { setup_for_gecko() + } else if let Ok(nss_dir) = env::var("NSS_DIR") { + setup_standalone(nss_dir.trim()) } else { - setup_standalone() + pkg_config() }; let config_file = PathBuf::from(BINDINGS_DIR).join(BINDINGS_CONFIG); diff --git a/neqo-crypto/min_version.txt b/neqo-crypto/min_version.txt new file mode 100644 index 0000000000..422c9c7093 --- /dev/null +++ b/neqo-crypto/min_version.txt @@ -0,0 +1 @@ +3.98 diff --git a/neqo-crypto/src/aead.rs b/neqo-crypto/src/aead.rs index bf7d7fe9d7..21027d55b2 100644 --- a/neqo-crypto/src/aead.rs +++ b/neqo-crypto/src/aead.rs @@ -63,13 +63,7 @@ impl RealAead { /// # Errors /// /// Returns `Error` when the supporting NSS functions fail. - pub fn new( - _fuzzing: bool, - version: Version, - cipher: Cipher, - secret: &SymKey, - prefix: &str, - ) -> Res { + pub fn new(version: Version, cipher: Cipher, secret: &SymKey, prefix: &str) -> Res { let s: *mut PK11SymKey = **secret; unsafe { Self::from_raw(version, cipher, s, prefix) } } diff --git a/neqo-crypto/src/aead_fuzzing.rs b/neqo-crypto/src/aead_null.rs similarity index 55% rename from neqo-crypto/src/aead_fuzzing.rs rename to neqo-crypto/src/aead_null.rs index 1f3bfb14bd..2d5656de73 100644 --- a/neqo-crypto/src/aead_fuzzing.rs +++ b/neqo-crypto/src/aead_null.rs @@ -4,87 +4,63 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![cfg(feature = "disable-encryption")] + use std::fmt; use crate::{ constants::{Cipher, Version}, err::{sec::SEC_ERROR_BAD_DATA, Error, Res}, p11::SymKey, - RealAead, }; -pub const FIXED_TAG_FUZZING: &[u8] = &[0x0a; 16]; +pub const AEAD_NULL_TAG: &[u8] = &[0x0a; 16]; -pub struct FuzzingAead { - real: Option, -} +pub struct AeadNull {} -impl FuzzingAead { +impl AeadNull { #[allow(clippy::missing_errors_doc)] - pub fn new( - fuzzing: bool, - version: Version, - cipher: Cipher, - secret: &SymKey, - prefix: &str, - ) -> Res { - let real = if fuzzing { - None - } else { - Some(RealAead::new(false, version, cipher, secret, prefix)?) - }; - Ok(Self { real }) + pub fn new(_version: Version, _cipher: Cipher, _secret: &SymKey, _prefix: &str) -> Res { + Ok(Self {}) } #[must_use] pub fn expansion(&self) -> usize { - if let Some(aead) = &self.real { - aead.expansion() - } else { - FIXED_TAG_FUZZING.len() - } + AEAD_NULL_TAG.len() } #[allow(clippy::missing_errors_doc)] pub fn encrypt<'a>( &self, - count: u64, - aad: &[u8], + _count: u64, + _aad: &[u8], input: &[u8], output: &'a mut [u8], ) -> Res<&'a [u8]> { - if let Some(aead) = &self.real { - return aead.encrypt(count, aad, input, output); - } - let l = input.len(); output[..l].copy_from_slice(input); - output[l..l + 16].copy_from_slice(FIXED_TAG_FUZZING); + output[l..l + 16].copy_from_slice(AEAD_NULL_TAG); Ok(&output[..l + 16]) } #[allow(clippy::missing_errors_doc)] pub fn decrypt<'a>( &self, - count: u64, - aad: &[u8], + _count: u64, + _aad: &[u8], input: &[u8], output: &'a mut [u8], ) -> Res<&'a [u8]> { - if let Some(aead) = &self.real { - return aead.decrypt(count, aad, input, output); - } - - if input.len() < FIXED_TAG_FUZZING.len() { + if input.len() < AEAD_NULL_TAG.len() { return Err(Error::from(SEC_ERROR_BAD_DATA)); } - let len_encrypted = input.len() - FIXED_TAG_FUZZING.len(); + let len_encrypted = input.len() - AEAD_NULL_TAG.len(); // Check that: // 1) expansion is all zeros and // 2) if the encrypted data is also supplied that at least some values are no zero // (otherwise padding will be interpreted as a valid packet) - if &input[len_encrypted..] == FIXED_TAG_FUZZING + if &input[len_encrypted..] == AEAD_NULL_TAG && (len_encrypted == 0 || input[..len_encrypted].iter().any(|x| *x != 0x0)) { output[..len_encrypted].copy_from_slice(&input[..len_encrypted]); @@ -95,12 +71,8 @@ impl FuzzingAead { } } -impl fmt::Debug for FuzzingAead { +impl fmt::Debug for AeadNull { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(a) = &self.real { - a.fmt(f) - } else { - write!(f, "[FUZZING AEAD]") - } + write!(f, "[NULL AEAD]") } } diff --git a/neqo-crypto/src/err.rs b/neqo-crypto/src/err.rs index 187303d2a9..8d4f239a0b 100644 --- a/neqo-crypto/src/err.rs +++ b/neqo-crypto/src/err.rs @@ -16,13 +16,39 @@ mod codes { #![allow(non_snake_case)] include!(concat!(env!("OUT_DIR"), "/nss_secerr.rs")); include!(concat!(env!("OUT_DIR"), "/nss_sslerr.rs")); - include!(concat!(env!("OUT_DIR"), "/mozpkix.rs")); } -pub use codes::{mozilla_pkix_ErrorCode as mozpkix, SECErrorCodes as sec, SSLErrorCodes as ssl}; +pub use codes::{SECErrorCodes as sec, SSLErrorCodes as ssl}; pub mod nspr { include!(concat!(env!("OUT_DIR"), "/nspr_err.rs")); } +pub mod mozpkix { + // These are manually extracted from the many bindings generated + // by bindgen when provided with the simple header: + // #include "mozpkix/pkixnss.h" + + #[allow(non_camel_case_types)] + pub type mozilla_pkix_ErrorCode = ::std::os::raw::c_int; + pub const MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE: mozilla_pkix_ErrorCode = -16384; + pub const MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY: mozilla_pkix_ErrorCode = -16383; + pub const MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE: mozilla_pkix_ErrorCode = -16382; + pub const MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA: mozilla_pkix_ErrorCode = -16381; + pub const MOZILLA_PKIX_ERROR_NO_RFC822NAME_MATCH: mozilla_pkix_ErrorCode = -16380; + pub const MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE: mozilla_pkix_ErrorCode = -16379; + pub const MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE: mozilla_pkix_ErrorCode = -16378; + pub const MOZILLA_PKIX_ERROR_SIGNATURE_ALGORITHM_MISMATCH: mozilla_pkix_ErrorCode = -16377; + pub const MOZILLA_PKIX_ERROR_OCSP_RESPONSE_FOR_CERT_MISSING: mozilla_pkix_ErrorCode = -16376; + pub const MOZILLA_PKIX_ERROR_VALIDITY_TOO_LONG: mozilla_pkix_ErrorCode = -16375; + pub const MOZILLA_PKIX_ERROR_REQUIRED_TLS_FEATURE_MISSING: mozilla_pkix_ErrorCode = -16374; + pub const MOZILLA_PKIX_ERROR_INVALID_INTEGER_ENCODING: mozilla_pkix_ErrorCode = -16373; + pub const MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME: mozilla_pkix_ErrorCode = -16372; + pub const MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED: mozilla_pkix_ErrorCode = + -16371; + pub const MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT: mozilla_pkix_ErrorCode = -16370; + pub const MOZILLA_PKIX_ERROR_MITM_DETECTED: mozilla_pkix_ErrorCode = -16369; + pub const END_OF_LIST: mozilla_pkix_ErrorCode = -16368; +} + pub type Res = Result; #[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)] diff --git a/neqo-crypto/src/lib.rs b/neqo-crypto/src/lib.rs index 45f61f6127..b82b225d40 100644 --- a/neqo-crypto/src/lib.rs +++ b/neqo-crypto/src/lib.rs @@ -8,8 +8,8 @@ #![allow(clippy::unseparated_literal_suffix, clippy::used_underscore_binding)] // For bindgen code. mod aead; -#[cfg(feature = "fuzzing")] -pub mod aead_fuzzing; +#[cfg(feature = "disable-encryption")] +pub mod aead_null; pub mod agent; mod agentio; mod auth; @@ -33,12 +33,12 @@ mod time; use std::{ffi::CString, path::PathBuf, ptr::null, sync::OnceLock}; -#[cfg(not(feature = "fuzzing"))] +#[cfg(not(feature = "disable-encryption"))] pub use self::aead::RealAead as Aead; -#[cfg(feature = "fuzzing")] +#[cfg(feature = "disable-encryption")] pub use self::aead::RealAead; -#[cfg(feature = "fuzzing")] -pub use self::aead_fuzzing::FuzzingAead as Aead; +#[cfg(feature = "disable-encryption")] +pub use self::aead_null::AeadNull as Aead; pub use self::{ agent::{ Agent, AllowZeroRtt, Client, HandshakeState, Record, RecordList, ResumptionToken, @@ -59,7 +59,8 @@ pub use self::{ ssl::Opt, }; -const MINIMUM_NSS_VERSION: &str = "3.97"; +mod min_version; +use min_version::MINIMUM_NSS_VERSION; #[allow(non_upper_case_globals, clippy::redundant_static_lifetimes)] #[allow(clippy::upper_case_acronyms)] diff --git a/neqo-crypto/src/min_version.rs b/neqo-crypto/src/min_version.rs new file mode 100644 index 0000000000..4386371b1b --- /dev/null +++ b/neqo-crypto/src/min_version.rs @@ -0,0 +1,9 @@ +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// The minimum version of NSS that is required by this version of neqo. +/// Note that the string may contain whitespace at the beginning and/or end. +pub(crate) const MINIMUM_NSS_VERSION: &str = include_str!("../min_version.txt"); diff --git a/neqo-crypto/src/selfencrypt.rs b/neqo-crypto/src/selfencrypt.rs index 1130c35250..d0a85830b0 100644 --- a/neqo-crypto/src/selfencrypt.rs +++ b/neqo-crypto/src/selfencrypt.rs @@ -47,7 +47,7 @@ impl SelfEncrypt { debug_assert_eq!(salt.len(), Self::SALT_LENGTH); let salt = hkdf::import_key(self.version, salt)?; let secret = hkdf::extract(self.version, self.cipher, Some(&salt), k)?; - Aead::new(false, self.version, self.cipher, &secret, "neqo self") + Aead::new(self.version, self.cipher, &secret, "neqo self") } /// Rotate keys. This causes any previous key that is being held to be replaced by the current diff --git a/neqo-crypto/tests/aead.rs b/neqo-crypto/tests/aead.rs index 5cf0034aec..f8416ed9a7 100644 --- a/neqo-crypto/tests/aead.rs +++ b/neqo-crypto/tests/aead.rs @@ -5,7 +5,7 @@ // except according to those terms. #![warn(clippy::pedantic)] -#![cfg(not(feature = "fuzzing"))] +#![cfg(not(feature = "disable-encryption"))] use neqo_crypto::{ constants::{Cipher, TLS_AES_128_GCM_SHA256, TLS_VERSION_1_3}, @@ -40,7 +40,6 @@ fn make_aead(cipher: Cipher) -> Aead { ) .expect("make a secret"); Aead::new( - false, TLS_VERSION_1_3, cipher, &secret, diff --git a/neqo-crypto/tests/selfencrypt.rs b/neqo-crypto/tests/selfencrypt.rs index 4c574a3ae9..b20aa27ee6 100644 --- a/neqo-crypto/tests/selfencrypt.rs +++ b/neqo-crypto/tests/selfencrypt.rs @@ -4,7 +4,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg(not(feature = "fuzzing"))] +#![cfg(not(feature = "disable-encryption"))] use neqo_crypto::{ constants::{TLS_AES_128_GCM_SHA256, TLS_VERSION_1_3}, diff --git a/neqo-http3/Cargo.toml b/neqo-http3/Cargo.toml index 32e3ae7e35..27f43fd93f 100644 --- a/neqo-http3/Cargo.toml +++ b/neqo-http3/Cargo.toml @@ -28,7 +28,7 @@ url = { version = "2.5", default-features = false } test-fixture = { path = "../test-fixture" } [features] -fuzzing = ["neqo-transport/fuzzing", "neqo-crypto/fuzzing"] +disable-encryption = ["neqo-transport/disable-encryption", "neqo-crypto/disable-encryption"] [lib] # See https://github.com/bheisler/criterion.rs/blob/master/book/src/faq.md#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options diff --git a/neqo-transport/Cargo.toml b/neqo-transport/Cargo.toml index f2e20ad360..29c8046870 100644 --- a/neqo-transport/Cargo.toml +++ b/neqo-transport/Cargo.toml @@ -27,7 +27,7 @@ test-fixture = { path = "../test-fixture" } [features] bench = [] -fuzzing = ["neqo-crypto/fuzzing"] +disable-encryption = ["neqo-crypto/disable-encryption"] [lib] # See https://github.com/bheisler/criterion.rs/blob/master/book/src/faq.md#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options diff --git a/neqo-transport/src/connection/mod.rs b/neqo-transport/src/connection/mod.rs index 14a7271229..9baa583cd2 100644 --- a/neqo-transport/src/connection/mod.rs +++ b/neqo-transport/src/connection/mod.rs @@ -19,7 +19,7 @@ use std::{ use neqo_common::{ event::Provider as EventProvider, hex, hex_snip_middle, hrtime, qdebug, qerror, qinfo, - qlog::NeqoQlog, qtrace, qwarn, Datagram, Decoder, Encoder, Role, + qlog::NeqoQlog, qtrace, qwarn, Datagram, Decoder, Encoder, IpTos, Role, }; use neqo_crypto::{ agent::CertificateInfo, Agent, AntiReplay, AuthenticationStatus, Cipher, Client, Group, @@ -384,7 +384,6 @@ impl Connection { agent, protocols.iter().map(P::as_ref).map(String::from).collect(), Rc::clone(&tphandler), - conn_params.is_fuzzing(), )?; let stats = StatsCell::default(); diff --git a/neqo-transport/src/connection/params.rs b/neqo-transport/src/connection/params.rs index 72d1efa3ee..d8aa617024 100644 --- a/neqo-transport/src/connection/params.rs +++ b/neqo-transport/src/connection/params.rs @@ -77,7 +77,6 @@ pub struct ConnectionParameters { outgoing_datagram_queue: usize, incoming_datagram_queue: usize, fast_pto: u8, - fuzzing: bool, grease: bool, pacing: bool, } @@ -100,7 +99,6 @@ impl Default for ConnectionParameters { outgoing_datagram_queue: MAX_QUEUED_DATAGRAMS_DEFAULT, incoming_datagram_queue: MAX_QUEUED_DATAGRAMS_DEFAULT, fast_pto: FAST_PTO_SCALE, - fuzzing: false, grease: true, pacing: true, } @@ -324,17 +322,6 @@ impl ConnectionParameters { self } - #[must_use] - pub fn is_fuzzing(&self) -> bool { - self.fuzzing - } - - #[must_use] - pub fn fuzzing(mut self, enable: bool) -> Self { - self.fuzzing = enable; - self - } - #[must_use] pub fn is_greasing(&self) -> bool { self.grease diff --git a/neqo-transport/src/connection/tests/handshake.rs b/neqo-transport/src/connection/tests/handshake.rs index 4b2a18642f..f2103523ec 100644 --- a/neqo-transport/src/connection/tests/handshake.rs +++ b/neqo-transport/src/connection/tests/handshake.rs @@ -16,7 +16,7 @@ use neqo_common::{event::Provider, qdebug, Datagram}; use neqo_crypto::{ constants::TLS_CHACHA20_POLY1305_SHA256, generate_ech_keys, AuthenticationStatus, }; -#[cfg(not(feature = "fuzzing"))] +#[cfg(not(feature = "disable-encryption"))] use test_fixture::datagram; use test_fixture::{ assertions, assertions::assert_coalesced_0rtt, fixture_init, now, split_datagram, DEFAULT_ADDR, @@ -606,7 +606,7 @@ fn reorder_1rtt() { } } -#[cfg(not(feature = "fuzzing"))] +#[cfg(not(feature = "disable-encryption"))] #[test] fn corrupted_initial() { let mut client = default_client(); @@ -809,7 +809,7 @@ fn anti_amplification() { assert_eq!(*server.state(), State::Confirmed); } -#[cfg(not(feature = "fuzzing"))] +#[cfg(not(feature = "disable-encryption"))] #[test] fn garbage_initial() { let mut client = default_client(); diff --git a/neqo-transport/src/connection/tests/mod.rs b/neqo-transport/src/connection/tests/mod.rs index 84ea15fbee..bf712f83fe 100644 --- a/neqo-transport/src/connection/tests/mod.rs +++ b/neqo-transport/src/connection/tests/mod.rs @@ -38,11 +38,11 @@ mod cc; mod close; mod datagram; mod ecn; -mod fuzzing; mod handshake; mod idle; mod keys; mod migration; +mod null; mod priority; mod recovery; mod resumption; @@ -171,13 +171,17 @@ impl crate::connection::test_internal::FrameWriter for PingWriter { } } +trait DatagramModifier: FnMut(Datagram) -> Option {} + +impl DatagramModifier for T where T: FnMut(Datagram) -> Option {} + /// Drive the handshake between the client and server. fn handshake_with_modifier( client: &mut Connection, server: &mut Connection, now: Instant, rtt: Duration, - mut modifier: impl FnMut(&mut Datagram), + mut modifier: impl DatagramModifier, ) -> Instant { let mut a = client; let mut b = server; @@ -214,9 +218,8 @@ fn handshake_with_modifier( did_ping[a.role()] = true; } assert!(had_input || output.is_some()); - if let Some(mut d) = output { - modifier(&mut d); - input = Some(d); + if let Some(d) = output { + input = modifier(d); } else { input = output; } @@ -236,7 +239,7 @@ fn handshake( now: Instant, rtt: Duration, ) -> Instant { - handshake_with_modifier(client, server, now, rtt, |_| {}) + handshake_with_modifier(client, server, now, rtt, Some) } fn connect_fail( @@ -255,7 +258,7 @@ fn connect_with_rtt_and_modifier( server: &mut Connection, now: Instant, rtt: Duration, - modifier: impl FnMut(&mut Datagram), + modifier: impl DatagramModifier, ) -> Instant { fn check_rtt(stats: &Stats, rtt: Duration) { assert_eq!(stats.rtt, rtt); @@ -278,7 +281,7 @@ fn connect_with_rtt( now: Instant, rtt: Duration, ) -> Instant { - connect_with_rtt_and_modifier(client, server, now, rtt, |_| {}) + connect_with_rtt_and_modifier(client, server, now, rtt, Some) } fn connect(client: &mut Connection, server: &mut Connection) { @@ -331,7 +334,7 @@ fn connect_rtt_idle_with_modifier( client: &mut Connection, server: &mut Connection, rtt: Duration, - modifier: impl FnMut(&mut Datagram), + modifier: impl DatagramModifier, ) -> Instant { let now = connect_with_rtt_and_modifier(client, server, now(), rtt, modifier); assert_idle(client, server, rtt, now); @@ -343,19 +346,19 @@ fn connect_rtt_idle_with_modifier( } fn connect_rtt_idle(client: &mut Connection, server: &mut Connection, rtt: Duration) -> Instant { - connect_rtt_idle_with_modifier(client, server, rtt, |_| {}) + connect_rtt_idle_with_modifier(client, server, rtt, Some) } fn connect_force_idle_with_modifier( client: &mut Connection, server: &mut Connection, - modifier: impl FnMut(&mut Datagram), + modifier: impl DatagramModifier, ) { connect_rtt_idle_with_modifier(client, server, Duration::new(0, 0), modifier); } fn connect_force_idle(client: &mut Connection, server: &mut Connection) { - connect_force_idle_with_modifier(client, server, |_| {}); + connect_force_idle_with_modifier(client, server, Some); } fn fill_stream(c: &mut Connection, stream: StreamId) { @@ -567,13 +570,14 @@ fn assert_full_cwnd(packets: &[Datagram], cwnd: usize) { } /// Send something on a stream from `sender` to `receiver`, maybe allowing for pacing. +/// Takes a modifier function that can be used to modify the datagram before it is sent. /// Return the resulting datagram and the new time. #[must_use] fn send_something_paced_with_modifier( sender: &mut Connection, mut now: Instant, allow_pacing: bool, - mut modifier: impl FnMut(&mut Datagram), + mut modifier: impl DatagramModifier, ) -> (Datagram, Instant) { let stream_id = sender.stream_create(StreamType::UniDi).unwrap(); assert!(sender.stream_send(stream_id, DEFAULT_STREAM_DATA).is_ok()); @@ -588,10 +592,7 @@ fn send_something_paced_with_modifier( .dgram() .expect("send_something: should have something to send") } - Output::Datagram(mut d) => { - modifier(&mut d); - d - } + Output::Datagram(d) => modifier(d).unwrap(), Output::None => panic!("send_something: got Output::None"), }; (dgram, now) @@ -602,13 +603,21 @@ fn send_something_paced( now: Instant, allow_pacing: bool, ) -> (Datagram, Instant) { - send_something_paced_with_modifier(sender, now, allow_pacing, |_| {}) + send_something_paced_with_modifier(sender, now, allow_pacing, Some) +} + +fn send_something_with_modifier( + sender: &mut Connection, + now: Instant, + modifier: impl DatagramModifier, +) -> Datagram { + send_something_paced_with_modifier(sender, now, false, modifier).0 } /// Send something on a stream from `sender` to `receiver`. /// Return the resulting datagram. fn send_something(sender: &mut Connection, now: Instant) -> Datagram { - send_something_paced(sender, now, false).0 + send_something_with_modifier(sender, now, Some) } fn send_something_with_modifier( diff --git a/neqo-transport/src/connection/tests/fuzzing.rs b/neqo-transport/src/connection/tests/null.rs similarity index 84% rename from neqo-transport/src/connection/tests/fuzzing.rs rename to neqo-transport/src/connection/tests/null.rs index b12100f8ad..e4d60445c6 100644 --- a/neqo-transport/src/connection/tests/fuzzing.rs +++ b/neqo-transport/src/connection/tests/null.rs @@ -4,9 +4,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg(feature = "fuzzing")] +#![cfg(feature = "disable-encryption")] -use neqo_crypto::aead_fuzzing::FIXED_TAG_FUZZING; +use neqo_crypto::aead_null::AEAD_NULL_TAG; use test_fixture::now; use super::{connect_force_idle, default_client, default_server}; @@ -24,7 +24,7 @@ fn no_encryption() { client.stream_send(stream_id, DATA_CLIENT).unwrap(); let client_pkt = client.process_output(now()).dgram().unwrap(); - assert!(client_pkt[..client_pkt.len() - FIXED_TAG_FUZZING.len()].ends_with(DATA_CLIENT)); + assert!(client_pkt[..client_pkt.len() - AEAD_NULL_TAG.len()].ends_with(DATA_CLIENT)); server.process_input(&client_pkt, now()); let mut buf = vec![0; 100]; @@ -33,7 +33,7 @@ fn no_encryption() { assert_eq!(&buf[..len], DATA_CLIENT); server.stream_send(stream_id, DATA_SERVER).unwrap(); let server_pkt = server.process_output(now()).dgram().unwrap(); - assert!(server_pkt[..server_pkt.len() - FIXED_TAG_FUZZING.len()].ends_with(DATA_SERVER)); + assert!(server_pkt[..server_pkt.len() - AEAD_NULL_TAG.len()].ends_with(DATA_SERVER)); client.process_input(&server_pkt, now()); let (len, _) = client.stream_recv(stream_id, &mut buf).unwrap(); diff --git a/neqo-transport/src/crypto.rs b/neqo-transport/src/crypto.rs index acc02172d5..54bfe622cf 100644 --- a/neqo-transport/src/crypto.rs +++ b/neqo-transport/src/crypto.rs @@ -69,7 +69,6 @@ impl Crypto { mut agent: Agent, protocols: Vec, tphandler: TpHandler, - fuzzing: bool, ) -> Res { agent.set_version_range(TLS_VERSION_1_3, TLS_VERSION_1_3)?; agent.set_ciphers(&[ @@ -102,7 +101,6 @@ impl Crypto { tls: agent, streams: CryptoStreams::default(), states: CryptoStates { - fuzzing, ..CryptoStates::default() }, }) @@ -420,7 +418,6 @@ pub struct CryptoDxState { /// The total number of operations that are remaining before the keys /// become exhausted and can't be used any more. invocations: PacketNumber, - fuzzing: bool, } impl CryptoDxState { @@ -431,7 +428,6 @@ impl CryptoDxState { epoch: Epoch, secret: &SymKey, cipher: Cipher, - fuzzing: bool, ) -> Self { qdebug!( "Making {:?} {} CryptoDxState, v={:?} cipher={}", @@ -445,19 +441,11 @@ impl CryptoDxState { version, direction, epoch: usize::from(epoch), - aead: Aead::new( - fuzzing, - TLS_VERSION_1_3, - cipher, - secret, - version.label_prefix(), - ) - .unwrap(), + aead: Aead::new(TLS_VERSION_1_3, cipher, secret, version.label_prefix()).unwrap(), hpkey: HpKey::extract(TLS_VERSION_1_3, cipher, secret, &hplabel).unwrap(), used_pn: 0..0, min_pn: 0, invocations: Self::limit(direction, cipher), - fuzzing, } } @@ -466,7 +454,6 @@ impl CryptoDxState { direction: CryptoDxDirection, label: &str, dcid: &[u8], - fuzzing: bool, ) -> Self { qtrace!("new_initial {:?} {}", version, ConnectionIdRef::from(dcid)); let salt = version.initial_salt(); @@ -482,14 +469,7 @@ impl CryptoDxState { let secret = hkdf::expand_label(TLS_VERSION_1_3, cipher, &initial_secret, &[], label).unwrap(); - Self::new( - version, - direction, - TLS_EPOCH_INITIAL, - &secret, - cipher, - fuzzing, - ) + Self::new(version, direction, TLS_EPOCH_INITIAL, &secret, cipher) } /// Determine the confidentiality and integrity limits for the cipher. @@ -549,7 +529,6 @@ impl CryptoDxState { direction: self.direction, epoch: self.epoch + 1, aead: Aead::new( - self.fuzzing, TLS_VERSION_1_3, cipher, next_secret, @@ -560,7 +539,6 @@ impl CryptoDxState { used_pn: pn..pn, min_pn: pn, invocations, - fuzzing: self.fuzzing, } } @@ -696,7 +674,7 @@ impl CryptoDxState { Ok(res.to_vec()) } - #[cfg(all(test, not(feature = "fuzzing")))] + #[cfg(all(test, not(feature = "disable-encryption")))] pub(crate) fn test_default() -> Self { // This matches the value in packet.rs const CLIENT_CID: &[u8] = &[0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08]; @@ -705,7 +683,6 @@ impl CryptoDxState { CryptoDxDirection::Write, "server in", CLIENT_CID, - false, ) } @@ -759,7 +736,6 @@ pub(crate) struct CryptoDxAppData { cipher: Cipher, // Not the secret used to create `self.dx`, but the one needed for the next iteration. next_secret: SymKey, - fuzzing: bool, } impl CryptoDxAppData { @@ -768,20 +744,11 @@ impl CryptoDxAppData { dir: CryptoDxDirection, secret: &SymKey, cipher: Cipher, - fuzzing: bool, ) -> Res { Ok(Self { - dx: CryptoDxState::new( - version, - dir, - TLS_EPOCH_APPLICATION_DATA, - secret, - cipher, - fuzzing, - ), + dx: CryptoDxState::new(version, dir, TLS_EPOCH_APPLICATION_DATA, secret, cipher), cipher, next_secret: Self::update_secret(cipher, secret)?, - fuzzing, }) } @@ -800,7 +767,6 @@ impl CryptoDxAppData { dx: self.dx.next(&self.next_secret, self.cipher), cipher: self.cipher, next_secret, - fuzzing: self.fuzzing, }) } @@ -834,7 +800,6 @@ pub struct CryptoStates { // If this is set, then we have noticed a genuine update. // Once this time passes, we should switch in new keys. read_update_time: Option, - fuzzing: bool, } impl CryptoStates { @@ -989,20 +954,8 @@ impl CryptoStates { ); let mut initial = CryptoState { - tx: CryptoDxState::new_initial( - *v, - CryptoDxDirection::Write, - write, - dcid, - self.fuzzing, - ), - rx: CryptoDxState::new_initial( - *v, - CryptoDxDirection::Read, - read, - dcid, - self.fuzzing, - ), + tx: CryptoDxState::new_initial(*v, CryptoDxDirection::Write, write, dcid), + rx: CryptoDxState::new_initial(*v, CryptoDxDirection::Read, read, dcid), }; if let Some(prev) = self.initials.get(v) { qinfo!( @@ -1056,7 +1009,6 @@ impl CryptoStates { TLS_EPOCH_ZERO_RTT, secret, cipher, - self.fuzzing, )); } @@ -1097,7 +1049,6 @@ impl CryptoStates { TLS_EPOCH_HANDSHAKE, write_secret, cipher, - self.fuzzing, ), rx: CryptoDxState::new( version, @@ -1105,7 +1056,6 @@ impl CryptoStates { TLS_EPOCH_HANDSHAKE, read_secret, cipher, - self.fuzzing, ), }); } @@ -1113,13 +1063,7 @@ impl CryptoStates { pub fn set_application_write_key(&mut self, version: Version, secret: &SymKey) -> Res<()> { debug_assert!(self.app_write.is_none()); debug_assert_ne!(self.cipher, 0); - let mut app = CryptoDxAppData::new( - version, - CryptoDxDirection::Write, - secret, - self.cipher, - self.fuzzing, - )?; + let mut app = CryptoDxAppData::new(version, CryptoDxDirection::Write, secret, self.cipher)?; if let Some(z) = &self.zero_rtt { if z.direction == CryptoDxDirection::Write { app.dx.continuation(z)?; @@ -1138,13 +1082,7 @@ impl CryptoStates { ) -> Res<()> { debug_assert!(self.app_write.is_some(), "should have write keys installed"); debug_assert!(self.app_read.is_none()); - let mut app = CryptoDxAppData::new( - version, - CryptoDxDirection::Read, - secret, - self.cipher, - self.fuzzing, - )?; + let mut app = CryptoDxAppData::new(version, CryptoDxDirection::Read, secret, self.cipher)?; if let Some(z) = &self.zero_rtt { if z.direction == CryptoDxDirection::Read { app.dx.continuation(z)?; @@ -1286,7 +1224,7 @@ impl CryptoStates { } /// Make some state for removing protection in tests. - #[cfg(not(feature = "fuzzing"))] + #[cfg(not(feature = "disable-encryption"))] #[cfg(test)] pub(crate) fn test_default() -> Self { let read = |epoch| { @@ -1299,7 +1237,6 @@ impl CryptoStates { dx: read(epoch), cipher: TLS_AES_128_GCM_SHA256, next_secret: hkdf::import_key(TLS_VERSION_1_3, &[0xaa; 32]).unwrap(), - fuzzing: false, }; let mut initials = HashMap::new(); initials.insert( @@ -1319,11 +1256,10 @@ impl CryptoStates { app_read: Some(app_read(3)), app_read_next: Some(app_read(4)), read_update_time: None, - fuzzing: false, } } - #[cfg(all(not(feature = "fuzzing"), test))] + #[cfg(all(not(feature = "disable-encryption"), test))] pub(crate) fn test_chacha() -> Self { const SECRET: &[u8] = &[ 0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42, 0x27, 0x48, 0xad, @@ -1337,7 +1273,6 @@ impl CryptoStates { direction: CryptoDxDirection::Read, epoch, aead: Aead::new( - false, TLS_VERSION_1_3, TLS_CHACHA20_POLY1305_SHA256, &secret, @@ -1354,11 +1289,9 @@ impl CryptoStates { used_pn: 0..645_971_972, min_pn: 0, invocations: 10, - fuzzing: false, }, cipher: TLS_CHACHA20_POLY1305_SHA256, next_secret: secret.clone(), - fuzzing: false, }; Self { initials: HashMap::new(), @@ -1369,7 +1302,6 @@ impl CryptoStates { app_read: Some(app_read(3)), app_read_next: Some(app_read(4)), read_update_time: None, - fuzzing: false, } } } diff --git a/neqo-transport/src/packet/mod.rs b/neqo-transport/src/packet/mod.rs index d11b3423a4..552e50a1f9 100644 --- a/neqo-transport/src/packet/mod.rs +++ b/neqo-transport/src/packet/mod.rs @@ -868,7 +868,7 @@ impl Deref for DecryptedPacket { } } -#[cfg(all(test, not(feature = "fuzzing")))] +#[cfg(all(test, not(feature = "disable-encryption")))] mod tests { use neqo_common::Encoder; use test_fixture::{fixture_init, now}; diff --git a/neqo-transport/src/packet/retry.rs b/neqo-transport/src/packet/retry.rs index 72036d3b49..71193b9100 100644 --- a/neqo-transport/src/packet/retry.rs +++ b/neqo-transport/src/packet/retry.rs @@ -18,7 +18,6 @@ fn make_aead(version: Version) -> Aead { let secret = hkdf::import_key(TLS_VERSION_1_3, version.retry_secret()).unwrap(); Aead::new( - false, TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, diff --git a/neqo-transport/tests/common/mod.rs b/neqo-transport/tests/common/mod.rs index faff216eb9..e36e66f753 100644 --- a/neqo-transport/tests/common/mod.rs +++ b/neqo-transport/tests/common/mod.rs @@ -146,14 +146,7 @@ pub fn initial_aead_and_hp(dcid: &[u8], role: Role) -> (Aead, HpKey) { ) .unwrap(); ( - Aead::new( - false, - TLS_VERSION_1_3, - TLS_AES_128_GCM_SHA256, - &secret, - "quic ", - ) - .unwrap(), + Aead::new(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, "quic ").unwrap(), HpKey::extract(TLS_VERSION_1_3, TLS_AES_128_GCM_SHA256, &secret, "quic hp").unwrap(), ) } diff --git a/neqo-transport/tests/conn_vectors.rs b/neqo-transport/tests/conn_vectors.rs index f478883075..86fe9d36fc 100644 --- a/neqo-transport/tests/conn_vectors.rs +++ b/neqo-transport/tests/conn_vectors.rs @@ -6,7 +6,7 @@ // Tests with the test vectors from the spec. -#![cfg(not(feature = "fuzzing"))] +#![cfg(not(feature = "disable-encryption"))] use std::{cell::RefCell, rc::Rc}; diff --git a/neqo-transport/tests/retry.rs b/neqo-transport/tests/retry.rs index e583fcae0f..36eff71e7b 100644 --- a/neqo-transport/tests/retry.rs +++ b/neqo-transport/tests/retry.rs @@ -4,7 +4,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg(not(feature = "fuzzing"))] +#![cfg(not(feature = "disable-encryption"))] mod common;