Skip to content

Commit 474fad0

Browse files
committed
Suggestions from @martinthomson
1 parent 5be89e1 commit 474fad0

2 files changed

Lines changed: 30 additions & 30 deletions

File tree

src/hp.rs

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,33 +49,21 @@ fn make_aes_ctx(key: &SymKey) -> Res<Context> {
4949
SECItemBorrowed::make_empty().as_ref(),
5050
)
5151
})
52-
.or(Err(Error::CipherInit))
52+
.map_err(|_| Error::CipherInit)
5353
}
5454

5555
pub enum Key {
5656
/// AES-ECB header-protection context. `PK11_CloneContext` is not supported for
57-
/// AES-ECB, so we store the `SymKey` and recreate `ctx` lazily: `mask` initialises
58-
/// it on first use when `ctx` is `None`.
57+
/// AES-ECB, so the `SymKey` is stored alongside `ctx` to enable duplication via
58+
/// `try_clone`.
5959
#[non_exhaustive]
60-
Aes { ctx: Option<Context>, key: SymKey },
60+
Aes { ctx: Context, key: SymKey },
6161
/// The `ChaCha20` mask invokes `PK11_Encrypt` on each call because the counter
6262
/// and nonce change per invocation.
6363
#[non_exhaustive]
6464
Chacha(SymKey),
6565
}
6666

67-
impl Clone for Key {
68-
fn clone(&self) -> Self {
69-
match self {
70-
Self::Aes { key, .. } => Self::Aes {
71-
ctx: None,
72-
key: key.clone(),
73-
},
74-
Self::Chacha(k) => Self::Chacha(k.clone()),
75-
}
76-
}
77-
}
78-
7967
impl Debug for Key {
8068
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8169
write!(f, "hp::Key")
@@ -125,7 +113,7 @@ impl Key {
125113

126114
let res = match cipher {
127115
TLS_AES_128_GCM_SHA256 | TLS_AES_256_GCM_SHA384 => {
128-
let ctx = Some(make_aes_ctx(&key)?);
116+
let ctx = make_aes_ctx(&key)?;
129117
Self::Aes { ctx, key }
130118
}
131119
TLS_CHACHA20_POLY1305_SHA256 => Self::Chacha(key),
@@ -146,6 +134,22 @@ impl Key {
146134
}
147135
}
148136

137+
/// Duplicate this key, creating a new independent instance.
138+
///
139+
/// # Errors
140+
///
141+
/// Errors if NSS context creation fails for AES keys.
142+
pub fn try_clone(&self) -> Res<Self> {
143+
match self {
144+
Self::Aes { key, .. } => {
145+
let key = key.clone();
146+
let ctx = make_aes_ctx(&key)?;
147+
Ok(Self::Aes { ctx, key })
148+
}
149+
Self::Chacha(k) => Ok(Self::Chacha(k.clone())),
150+
}
151+
}
152+
149153
/// Generate a header protection mask for QUIC.
150154
///
151155
/// # Errors
@@ -154,21 +158,17 @@ impl Key {
154158
///
155159
/// # Panics
156160
///
157-
/// When the mechanism for our key is not supported.
158-
pub fn mask(&mut self, sample: &[u8; Self::SAMPLE_SIZE]) -> Res<[u8; Self::SAMPLE_SIZE]> {
161+
/// In debug builds, if NSS returns an unexpected output length.
162+
pub fn mask(&self, sample: &[u8; Self::SAMPLE_SIZE]) -> Res<[u8; Self::SAMPLE_SIZE]> {
159163
let mut output = [0; Self::SAMPLE_SIZE];
160164

161165
match self {
162-
Self::Aes { ctx, key } => {
163-
let ctx = if let Some(c) = ctx {
164-
c
165-
} else {
166-
ctx.insert(make_aes_ctx(key)?)
167-
};
166+
Self::Aes { ctx, .. } => {
168167
let mut output_len: c_int = 0;
169-
// SAFETY: `Deref` on `Context` yields a copy of the raw `*mut PK11Context`;
170-
// no Rust reference to the pointee is created, and `&mut self` guarantees
171-
// exclusive access to this `Key`.
168+
// SAFETY: `Deref` on `Context` copies the raw `*mut PK11Context` pointer
169+
// value; no Rust reference to the pointee is created. `Key` contains raw
170+
// pointers (`!Sync`), so concurrent invocations are impossible, and
171+
// AES-ECB full-block operations retain no inter-call state in the context.
172172
secstatus_to_res(unsafe {
173173
PK11_CipherOp(
174174
**ctx,

tests/hp.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ fn make_hp(cipher: Cipher) -> hp::Key {
2121
}
2222

2323
fn hp_test(cipher: Cipher, expected: &[u8]) {
24-
let mut hp = make_hp(cipher);
24+
let hp = make_hp(cipher);
2525
let mask = hp.mask(&[0; 16]).expect("should produce a mask");
2626
assert_eq!(mask, expected, "first invocation should be correct");
2727

28-
let mut hp2 = hp.clone();
28+
let hp2 = hp.try_clone().expect("try_clone succeeds");
2929
let mask = hp2.mask(&[0; 16]).expect("clone produces mask");
3030
assert_eq!(mask, expected, "clone should produce the same mask");
3131

0 commit comments

Comments
 (0)