Skip to content

Commit 30d3e67

Browse files
committed
feat: add blapi feature to bypass PKCS#11 in RecordProtection
Calls freebl AES-GCM and ChaCha20-Poly1305 primitives directly instead of going through `PK11_AEADOp` → softoken, eliminating the `sftk_SessionFromHandle` mutex and hash-table overhead (~7.6% CPU on the hot path). `RecordProtection::new` takes a `Mode` so callers that know their direction (send vs. receive) create only the context they need. NOTE: bypasses softoken's FIPS self-test gate. Intentional for neqo (non-FIPS).
1 parent 07994e8 commit 30d3e67

17 files changed

Lines changed: 917 additions & 220 deletions

File tree

.github/actions/check-android/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ runs:
4747
with:
4848
version: stable
4949
targets: ${{ inputs.target }}
50-
tools: cargo-ndk@^4
50+
tools: cargo-ndk@^4, cargo-hack
5151
token: ${{ inputs.github-token }}
5252

5353
- uses: mozilla/actions/nss@27cbe8fb5d338c2861b787e5de10410559065db1 # v1.1.3
@@ -62,7 +62,7 @@ runs:
6262
TARGET: ${{ startsWith(inputs.target, 'arm') && 'arm64-v8a' || inputs.target }}
6363
API_LEVEL: ${{ inputs.api-level }}
6464
WD: ${{ inputs.working-directory }}
65-
run: cd "$WD" && cargo ndk --platform "$API_LEVEL" --target "$TARGET" test --no-run
65+
run: cd "$WD" && cargo hack --feature-powerset --exclude-features gecko,blapi ndk --platform "$API_LEVEL" --target "$TARGET" test --no-run
6666

6767
# FIXME: Enable emulator testing for aarch64 once Google ships Android
6868
# emulator binaries for ARM64 Linux hosts.

.github/actions/check-vm/action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,15 @@ runs:
102102
;;
103103
esac
104104
cargo fmt --all -- --check
105+
cargo install cargo-hack --locked
105106
case "$PLATFORM" in
106107
freebsd) cargo install cargo-llvm-cov --locked
107108
cargo llvm-cov test --locked --no-fail-fast --codecov --output-path codecov.json
109+
cargo hack test --locked --no-fail-fast --feature-powerset --exclude-features gecko,blapi
108110
;;
109111
*) # FIXME: No profiler support on other platforms, error is: cannot find crate for profiler_builtins
110112
cargo test --locked --no-fail-fast # We do this instead for now
113+
cargo hack test --locked --no-fail-fast --feature-powerset --exclude-features gecko,blapi
111114
;;
112115
esac
113116
cargo test --locked --no-fail-fast --release

.github/workflows/check.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ jobs:
8383
with:
8484
version: ${{ matrix.rust-toolchain }}
8585
components: ${{ matrix.rust-toolchain == 'stable' && 'llvm-tools' || '' }} ${{ matrix.rust-toolchain == 'nightly' && startsWith(matrix.os, 'ubuntu') && !endsWith(matrix.os, 'arm') && 'rust-src ' || '' }}
86-
tools: ${{ matrix.rust-toolchain == 'stable' && 'cargo-llvm-cov' || '' }} ${{ matrix.rust-toolchain == 'nightly' && startsWith(matrix.os, 'ubuntu') && !endsWith(matrix.os, 'arm') && 'cargo-careful ' || '' }}
86+
tools: ${{ matrix.rust-toolchain == 'stable' && 'cargo-llvm-cov' || '' }} ${{ matrix.rust-toolchain == 'nightly' && startsWith(matrix.os, 'ubuntu') && !endsWith(matrix.os, 'arm') && 'cargo-careful ' || '' }} cargo-hack
8787
token: ${{ secrets.GITHUB_TOKEN }}
8888

8989
- uses: mozilla/actions/nss@27cbe8fb5d338c2861b787e5de10410559065db1 # v1.1.3
@@ -96,6 +96,11 @@ jobs:
9696
# shellcheck disable=SC2086
9797
cargo check $BUILD_TYPE --locked --all-targets
9898
99+
- name: Check feature powerset
100+
run: |
101+
# shellcheck disable=SC2086
102+
cargo hack check $BUILD_TYPE --locked --feature-powerset --no-dev-deps --exclude-features gecko --mutually-exclusive-features blapi,disable-encryption
103+
99104
- name: Run tests and determine coverage
100105
env:
101106
RUST_LOG: trace
@@ -119,6 +124,11 @@ jobs:
119124
cargo $CAREFUL test $BUILD_TYPE --locked $TRIPLE
120125
fi
121126
127+
- name: Test feature powerset
128+
run: |
129+
# shellcheck disable=SC2086
130+
cargo hack test $BUILD_TYPE --locked --feature-powerset --exclude-features gecko --mutually-exclusive-features blapi,disable-encryption
131+
122132
- name: CodeCov Windows workaround
123133
if: ${{ startsWith(matrix.os, 'windows') && matrix.type == 'debug' && matrix.rust-toolchain == 'stable' }}
124134
run: |

.github/workflows/clippy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
# respective default features only. Can reveal warnings otherwise
6060
# hidden given that a plain cargo clippy combines all features of the
6161
# workspace. See e.g. https://github.com/mozilla/neqo/pull/1695.
62-
- run: cargo hack clippy --feature-powerset --no-dev-deps --exclude-features gecko -- -D warnings
62+
- run: cargo hack clippy --feature-powerset --no-dev-deps --exclude-features gecko --mutually-exclusive-features blapi,disable-encryption -- -D warnings
6363
- run: cargo clippy --locked --workspace --all-targets -- -D warnings
6464
- run: cargo doc --locked --workspace --no-deps --document-private-items
6565
env:

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "nss-rs"
3-
version = "0.11.0"
3+
version = "0.12.0"
44
authors = ["Martin Thomson <mt@lowentropy.net>", "Andy Leiserson <aleiserson@mozilla.com>", "John M. Schanck <jschanck@mozilla.com>", "Benjamin Beurdouche <beurdouche@mozilla.com>", "Anna Weine <anna.weine@mozilla.com>"]
55
categories = ["network-programming", "web-programming"]
66
keywords = ["nss", "crypto", "mozilla", "firefox"]
@@ -124,6 +124,9 @@ verbose_file_reads = "warn"
124124

125125
[features]
126126
bench = ["log/release_max_level_info"]
127+
# Bypass PKCS#11 session layer for RecordProtection AEAD operations by calling
128+
# freebl directly. Improves performance but skips softoken's FIPS self-test gate.
129+
blapi = []
127130
disable-encryption = []
128131
disable-random = []
129132
gecko = ["mozbuild"]

build.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ fn dynamic_link() {
229229
for lib in dynamic_libs {
230230
println!("cargo:rustc-link-lib=dylib={lib}");
231231
}
232+
if env::var("CARGO_FEATURE_BLAPI").is_ok() {
233+
println!("cargo:rustc-link-lib=static=freebl");
234+
}
232235
}
233236

234237
fn static_link() {
@@ -396,19 +399,59 @@ fn pkg_config() -> Result<Vec<String>, Box<dyn Error>> {
396399
let cfg_str = String::from_utf8(cfg)?;
397400

398401
let mut flags: Vec<String> = Vec::new();
402+
let mut lib_dirs: Vec<PathBuf> = Vec::new();
399403

400404
for f in cfg_str.split_whitespace() {
401405
if f.starts_with("-I") {
402406
flags.push(String::from(f));
403407
} else if let Some(path) = f.strip_prefix("-L") {
404408
println!("cargo:rustc-link-search=native={path}");
409+
lib_dirs.push(PathBuf::from(path));
405410
} else if let Some(lib) = f.strip_prefix("-l") {
406411
println!("cargo:rustc-link-lib=dylib={lib}");
407412
} else {
408413
println!("cargo:warning=Unknown flag from pkg-config: {f}");
409414
}
410415
}
411416

417+
if env::var("CARGO_FEATURE_BLAPI").is_ok() {
418+
// Probe for freebl in preference order. All dynamic libraries export
419+
// FREEBL_GetVector, which is the only stable ABI entry point used by
420+
// the blapi Rust bindings. The static libfreebl.a does NOT export
421+
// FREEBL_GetVector, so it is a last resort (NSS_DIR source builds
422+
// typically also produce the shared libraries and are found first).
423+
//
424+
// 1. libfreeblpriv3 — Ubuntu and some Linux distributions ship this as the "private API"
425+
// library that libsoftokn3 links against.
426+
//
427+
// 2. libfreebl3 — macOS (Homebrew), FreeBSD, NetBSD and most other systems; this is the
428+
// real implementation, exporting FREEBL_GetVector.
429+
//
430+
// 3. libfreebl.a — static fallback for NSS_DIR source builds.
431+
let has = |name: &str| lib_dirs.iter().any(|dir| dir.join(name).exists());
432+
let dylib_ext = if env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("macos") {
433+
"dylib"
434+
} else {
435+
"so"
436+
};
437+
let has_dylib = |stem: &str| has(&format!("{stem}.{dylib_ext}"));
438+
let link = [
439+
(has_dylib("libfreeblpriv3"), "dylib=freeblpriv3"),
440+
(has_dylib("libfreebl3"), "dylib=freebl3"),
441+
(has("libfreebl.a"), "static=freebl"),
442+
]
443+
.into_iter()
444+
.find_map(|(found, link)| found.then_some(link))
445+
.unwrap_or_else(|| {
446+
panic!(
447+
"blapi feature requires freebl: libfreeblpriv3, libfreebl3, \
448+
and libfreebl.a were all absent from the pkg-config library \
449+
paths. Set NSS_DIR to a standalone NSS source build."
450+
)
451+
});
452+
println!("cargo:rustc-link-lib={link}");
453+
}
454+
412455
Ok(flags)
413456
}
414457

0 commit comments

Comments
 (0)