Skip to content

Commit cbbd2af

Browse files
Merge pull request #17 from 10d9e/security/hazmat-feature-names
Rename test-harness features to hazmat-* to flag secret exposure
2 parents c9e2b03 + ec1c6b2 commit cbbd2af

9 files changed

Lines changed: 36 additions & 31 deletions

File tree

.github/workflows/ci.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ jobs:
2929
run: cargo fmt --check
3030
- name: cargo clippy (default)
3131
run: cargo clippy --all-targets -- -D warnings
32-
- name: cargo clippy (pq + kat-internals)
33-
run: cargo clippy --all-targets --features pq,kat-internals -- -D warnings
32+
- name: cargo clippy (pq + hazmat-kat-internals)
33+
run: cargo clippy --all-targets --features pq,hazmat-kat-internals -- -D warnings
3434
- name: cargo test
3535
run: cargo test
36-
- name: cargo test (pq + kat-internals)
37-
run: cargo test --features pq,kat-internals
38-
- name: cargo test (pq + differential + kat-internals)
39-
run: cargo test --features pq,differential,kat-internals
36+
- name: cargo test (pq + hazmat-kat-internals)
37+
run: cargo test --features pq,hazmat-kat-internals
38+
- name: cargo test (pq + hazmat-differential + hazmat-kat-internals)
39+
run: cargo test --features pq,hazmat-differential,hazmat-kat-internals
4040
- name: cargo build --release
4141
run: cargo build --release
4242

Cargo.toml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,14 @@ default = ["std"]
3636
std = ["subtle/std", "aes-gcm/std", "chacha20poly1305/std"]
3737
pq = ["dep:ml-kem", "dep:x-wing", "dep:shake"]
3838
serde = ["dep:serde"]
39-
differential = []
40-
comparative = ["pq"]
41-
kat-internals = []
39+
# The two `hazmat-*` features expose secret internals (raw AEAD keys,
40+
# exporter secrets, deterministic ephemeral-key injection) for the KAT and
41+
# differential test harnesses. Never enable them in production builds:
42+
# Cargo feature unification means any crate in the dependency graph that
43+
# turns them on enables them for every user of hpke-ng in that build.
44+
hazmat-differential = []
45+
comparative = ["pq"]
46+
hazmat-kat-internals = []
4247

4348
[dev-dependencies]
4449
hpke-rs = { version = "0.6", features = ["std", "rustcrypto", "hpke-test", "hpke-test-prng", "hazmat"] }
@@ -59,7 +64,7 @@ codegen-units = 1
5964

6065
[[test]]
6166
name = "kat"
62-
required-features = ["kat-internals"]
67+
required-features = ["hazmat-kat-internals"]
6368

6469
[[test]]
6570
name = "compile_fail"

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,14 @@ This crate composes RustCrypto primitives. Constant-time properties are inherite
159159
```bash
160160
cargo test # library + roundtrip
161161
cargo test --features pq # + post-quantum tests
162-
cargo test --features pq,kat-internals # + RFC 9180 KAT
163-
cargo test --features pq,kat-internals --test compile_fail # + compile-time invariant tests
164-
cargo test --features pq,differential,kat-internals # + cross-impl differential vs hpke-rs
162+
cargo test --features pq,hazmat-kat-internals # + RFC 9180 KAT
163+
cargo test --features pq,hazmat-kat-internals --test compile_fail # + compile-time invariant tests
164+
cargo test --features pq,hazmat-differential,hazmat-kat-internals # + cross-impl differential vs hpke-rs
165165
```
166166

167167
To regenerate the compile-fail `.stderr` fixtures after an intentional change (e.g. a toolchain bump), run:
168168
```bash
169-
TRYBUILD=overwrite cargo test --features pq,kat-internals --test compile_fail
169+
TRYBUILD=overwrite cargo test --features pq,hazmat-kat-internals --test compile_fail
170170
```
171171
This rewrites the fixtures unconditionally and should not be used as the normal test invocation.
172172

fuzz/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ libfuzzer-sys = "0.4"
1616

1717
[dependencies.hpke-ng]
1818
path = ".."
19-
features = ["pq", "kat-internals"]
19+
features = ["pq", "hazmat-kat-internals"]
2020

2121
# Keep optimisations on for libFuzzer; debug assertions remain enabled by
2222
# default (cargo-fuzz overrides `[profile.release].debug-assertions = true`).

src/context.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub struct Context<K: Kem, F: Kdf, A: Aead> {
2626
/// Raw AEAD key bytes — kept under cfg gate so the test/KAT/differential
2727
/// harnesses can assert on them. Production builds carry only the
2828
/// derived `cipher` state.
29-
#[cfg(any(test, feature = "kat-internals", feature = "differential"))]
29+
#[cfg(any(test, feature = "hazmat-kat-internals", feature = "hazmat-differential"))]
3030
raw_key: Zeroizing<Vec<u8>>,
3131
_kfa: PhantomData<(K, F, A)>,
3232
}
@@ -72,7 +72,7 @@ impl<K: Kem, F: Kdf, A: Aead> Context<K, F, A> {
7272
base_nonce: nonce_arr,
7373
exporter_secret: Zeroizing::new(exporter_secret),
7474
seq: 0,
75-
#[cfg(any(test, feature = "kat-internals", feature = "differential"))]
75+
#[cfg(any(test, feature = "hazmat-kat-internals", feature = "hazmat-differential"))]
7676
raw_key: Zeroizing::new(key_z.to_vec()),
7777
_kfa: PhantomData,
7878
})
@@ -113,7 +113,7 @@ impl<K: Kem, F: Kdf, A: Aead> Context<K, F, A> {
113113
}
114114
}
115115

116-
#[cfg(any(test, feature = "kat-internals", feature = "differential"))]
116+
#[cfg(any(test, feature = "hazmat-kat-internals", feature = "hazmat-differential"))]
117117
impl<K: Kem, F: Kdf, A: Aead> Context<K, F, A> {
118118
/// Test-only: expose the AEAD key.
119119
#[must_use]
@@ -213,7 +213,7 @@ impl<K: Kem, F: Kdf, A: Aead> SenderContext<K, F, A> {
213213
/// Test/KAT/differential-only: wrap a raw key-schedule [`Context`] as a
214214
/// sender context (the harnesses build contexts from injected shared
215215
/// secrets rather than through `setup_sender_*`).
216-
#[cfg(any(test, feature = "kat-internals", feature = "differential"))]
216+
#[cfg(any(test, feature = "hazmat-kat-internals", feature = "hazmat-differential"))]
217217
#[doc(hidden)]
218218
#[must_use]
219219
pub fn from_context(inner: Context<K, F, A>) -> Self {
@@ -252,7 +252,7 @@ impl<K: Kem, F: Kdf, A: SealingAead> ReceiverContext<K, F, A> {
252252
}
253253

254254
/// Test/KAT/differential accessors that delegate to the inner [`Context`].
255-
#[cfg(any(test, feature = "kat-internals", feature = "differential"))]
255+
#[cfg(any(test, feature = "hazmat-kat-internals", feature = "hazmat-differential"))]
256256
impl<K: Kem, F: Kdf, A: Aead> ReceiverContext<K, F, A> {
257257
/// Test-only: expose the AEAD key.
258258
#[must_use]

src/kem/dh.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ fn encap_with<D: DiffieHellman, H: Kdf, R: CryptoRng>(
490490

491491
/// Test-only API: encap with a caller-supplied IKM for the ephemeral key, used
492492
/// by KAT and differential test harnesses.
493-
#[cfg(any(test, feature = "kat-internals", feature = "differential"))]
493+
#[cfg(any(test, feature = "hazmat-kat-internals", feature = "hazmat-differential"))]
494494
#[allow(dead_code)]
495495
pub(crate) fn encap_with_ikm<D: DiffieHellman, H: Kdf>(
496496
pk_r: &DhPublicKey<D>,
@@ -506,7 +506,7 @@ pub(crate) fn encap_with_ikm<D: DiffieHellman, H: Kdf>(
506506
))
507507
}
508508

509-
#[cfg(any(test, feature = "kat-internals", feature = "differential"))]
509+
#[cfg(any(test, feature = "hazmat-kat-internals", feature = "hazmat-differential"))]
510510
#[allow(dead_code)]
511511
pub(crate) fn auth_encap_with_ikm<D: DiffieHellman, H: Kdf>(
512512
pk_r: &DhPublicKey<D>,
@@ -527,7 +527,7 @@ pub(crate) fn auth_encap_with_ikm<D: DiffieHellman, H: Kdf>(
527527
))
528528
}
529529

530-
#[cfg(any(test, feature = "kat-internals", feature = "differential"))]
530+
#[cfg(any(test, feature = "hazmat-kat-internals", feature = "hazmat-differential"))]
531531
impl<D: DiffieHellman, H: Kdf> DhKem<D, H> {
532532
/// Test-only: encap with a caller-supplied ephemeral IKM (deterministic).
533533
pub fn encap_with_ikm(

src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,15 +227,15 @@ fn key_schedule_psk_free_impl<M: PskFreeMode, K: Kem, F: Kdf, A: Aead>(
227227
}
228228

229229
// Public-facing wrapper — visibility changes with feature gate.
230-
#[cfg(not(feature = "kat-internals"))]
230+
#[cfg(not(feature = "hazmat-kat-internals"))]
231231
pub(crate) fn key_schedule_psk_free<M: PskFreeMode, K: Kem, F: Kdf, A: Aead>(
232232
shared_secret: &[u8],
233233
info: &[u8],
234234
) -> Result<Context<K, F, A>, HpkeError> {
235235
key_schedule_psk_free_impl::<M, K, F, A>(shared_secret, info)
236236
}
237237

238-
#[cfg(feature = "kat-internals")]
238+
#[cfg(feature = "hazmat-kat-internals")]
239239
#[doc(hidden)]
240240
pub fn key_schedule_psk_free<M: PskFreeMode, K: Kem, F: Kdf, A: Aead>(
241241
shared_secret: &[u8],
@@ -280,7 +280,7 @@ fn key_schedule_psk_impl<M: PskMode, K: Kem, F: Kdf, A: Aead>(
280280
}
281281

282282
// Public-facing wrapper — visibility changes with feature gate.
283-
#[cfg(not(feature = "kat-internals"))]
283+
#[cfg(not(feature = "hazmat-kat-internals"))]
284284
pub(crate) fn key_schedule_psk<M: PskMode, K: Kem, F: Kdf, A: Aead>(
285285
shared_secret: &[u8],
286286
info: &[u8],
@@ -290,7 +290,7 @@ pub(crate) fn key_schedule_psk<M: PskMode, K: Kem, F: Kdf, A: Aead>(
290290
key_schedule_psk_impl::<M, K, F, A>(shared_secret, info, psk, psk_id)
291291
}
292292

293-
#[cfg(feature = "kat-internals")]
293+
#[cfg(feature = "hazmat-kat-internals")]
294294
#[doc(hidden)]
295295
pub fn key_schedule_psk<M: PskMode, K: Kem, F: Kdf, A: Aead>(
296296
shared_secret: &[u8],
@@ -679,7 +679,7 @@ impl<K: AuthKem, F: Kdf, A: Aead> Hpke<K, F, A> {
679679
}
680680
}
681681

682-
#[cfg(feature = "kat-internals")]
682+
#[cfg(feature = "hazmat-kat-internals")]
683683
#[doc(hidden)]
684684
pub mod __test_only {
685685
pub use crate::key_schedule_psk;

tests/compile_fail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! To regenerate the compile-fail `.stderr` fixtures after
22
//! an intentional change (e.g. a toolchain bump), run:
33
//!
4-
//! `TRYBUILD=overwrite cargo test --features pq,kat-internals --test compile_fail`
4+
//! `TRYBUILD=overwrite cargo test --features pq,hazmat-kat-internals --test compile_fail`
55
//!
66
#[test]
77
fn compile_fail() {

tests/differential.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Cross-implementation differential test: feed identical inputs to `hpke-ng`
22
//! and `hpke-rs` and assert byte-equal outputs.
33
//!
4-
//! Run with: `cargo test --features differential,kat-internals --test differential`.
4+
//! Run with: `cargo test --features hazmat-differential,hazmat-kat-internals --test differential`.
55
//!
66
//! Strategy:
77
//! - Use `hpke-ng` as the *sender* with `encap_with_ikm` (deterministic ephemeral key).
@@ -15,7 +15,7 @@
1515
//! P-384 and P-521 are omitted because hpke-rs-rust-crypto 0.6 only supports
1616
//! X25519, P-256, and secp256k1 (the `supports_kem` gate rejects others).
1717
18-
#![cfg(feature = "differential")]
18+
#![cfg(feature = "hazmat-differential")]
1919
#![allow(non_snake_case)]
2020

2121
use hpke_ng as ng;

0 commit comments

Comments
 (0)