Skip to content

Commit 9df77b4

Browse files
committed
double-pipeline support
1 parent 013eec6 commit 9df77b4

File tree

1 file changed

+134
-35
lines changed

1 file changed

+134
-35
lines changed

kbkdf/src/lib.rs

Lines changed: 134 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ where
9393
/// Derives `key` from `kin` and other parameters.
9494
fn derive(
9595
&self,
96-
kin: &GenericArray<u8, Prf::KeySize>,
96+
//kin: &GenericArray<u8, Prf::KeySize>,
97+
kin: &[u8],
9798
use_l: bool,
9899
use_separator: bool,
99100
label: &[u8],
@@ -116,23 +117,42 @@ where
116117

117118
let mut ki = None;
118119
self.input_iv(&mut ki);
120+
let mut a = {
121+
let mut h = <Prf as Mac>::new_from_slice(kin).unwrap();
122+
h.update(label);
123+
h.update(&[0]);
124+
h.update(context);
125+
h.finalize().into_bytes()
126+
};
119127

120128
for counter in 1..=n {
121-
let mut h = <Prf as Mac>::new(kin);
129+
if counter > 1 {
130+
a = {
131+
let mut h = <Prf as Mac>::new_from_slice(kin).unwrap();
132+
h.update(a.as_slice());
133+
h.finalize().into_bytes()
134+
};
135+
}
136+
137+
let mut h = <Prf as Mac>::new_from_slice(kin).unwrap();
122138

123139
if Self::FEEDBACK_KI {
124140
if let Some(ki) = ki {
125141
h.update(ki.as_slice());
126142
}
127143
}
128144

129-
// counter encoded as big endian u32
130-
// Type parameter R encodes how large the value is to be (either U8, U16, U24, or U32)
131-
//
132-
// counter = 1u32 ([0, 0, 0, 1])
133-
// \-------/
134-
// R = u24
135-
h.update(&counter.to_be_bytes()[(4 - R::USIZE / 8)..]);
145+
if Self::DOUBLE_PIPELINE {
146+
h.update(a.as_slice());
147+
} else {
148+
// counter encoded as big endian u32
149+
// Type parameter R encodes how large the value is to be (either U8, U16, U24, or U32)
150+
//
151+
// counter = 1u32 ([0, 0, 0, 1])
152+
// \-------/
153+
// R = u24
154+
h.update(&counter.to_be_bytes()[(4 - R::USIZE / 8)..]);
155+
}
136156

137157
// Fixed input data
138158
h.update(label);
@@ -166,6 +186,8 @@ where
166186

167187
/// Whether the KI should be reinjected every round.
168188
const FEEDBACK_KI: bool = false;
189+
190+
const DOUBLE_PIPELINE: bool = false;
169191
}
170192

171193
pub struct Counter<Prf, K, R = U32> {
@@ -231,10 +253,41 @@ where
231253
const FEEDBACK_KI: bool = true;
232254
}
233255

256+
pub struct DoublePipeline<Prf, K, R = U32>
257+
where
258+
Prf: Mac,
259+
{
260+
_marker: PhantomData<(Prf, K, R)>,
261+
}
262+
263+
impl<Prf, K, R> Default for DoublePipeline<Prf, K, R>
264+
where
265+
Prf: Mac,
266+
{
267+
fn default() -> Self {
268+
Self {
269+
_marker: PhantomData,
270+
}
271+
}
272+
}
273+
274+
impl<Prf, K, R> Kbkdf<Prf, K, R> for DoublePipeline<Prf, K, R>
275+
where
276+
Prf: Mac + KeyInit,
277+
K: KeySizeUser,
278+
K::KeySize: ArrayLength<u8> + Mul<U8>,
279+
<K::KeySize as Mul<U8>>::Output: Unsigned,
280+
Prf::OutputSize: ArrayLength<u8> + Mul<U8>,
281+
<Prf::OutputSize as Mul<U8>>::Output: Unsigned,
282+
R: sealed::R,
283+
{
284+
const DOUBLE_PIPELINE: bool = true;
285+
}
286+
234287
#[cfg(test)]
235288
mod tests {
236-
use super::{Counter, Feedback, GenericArray, Kbkdf};
237-
use digest::consts::*;
289+
use super::{Counter, DoublePipeline, Feedback, GenericArray, Kbkdf};
290+
use digest::{consts::*, crypto_common::KeySizeUser};
238291
use hex_literal::hex;
239292

240293
#[derive(Debug)]
@@ -293,6 +346,44 @@ mod tests {
293346
},
294347
];
295348

349+
#[test]
350+
fn test_static_values_counter() {
351+
type HmacSha256 = hmac::Hmac<sha2::Sha256>;
352+
type HmacSha512 = hmac::Hmac<sha2::Sha512>;
353+
354+
let counter = Counter::<HmacSha256, HmacSha512>::default();
355+
for (v, i) in KNOWN_VALUES_COUNTER_HMAC_SHA256.iter().zip(0..) {
356+
assert_eq!(
357+
counter.derive(v.key, v.use_l, v.use_separator, v.label, v.context,),
358+
Ok(GenericArray::<_, _>::from_slice(v.expected).clone()),
359+
"key derivation failed for (index: {i}):\n{v:x?}"
360+
);
361+
}
362+
}
363+
364+
#[test]
365+
fn test_counter_kbkdfvs() {
366+
type HmacSha256 = hmac::Hmac<sha2::Sha256>;
367+
struct MockOutput;
368+
369+
impl KeySizeUser for MockOutput {
370+
type KeySize = U32;
371+
}
372+
373+
let counter = Counter::<HmacSha256, MockOutput>::default();
374+
// KDFCTR_gen.txt count 15
375+
assert_eq!(
376+
counter.derive(
377+
&hex!("43eef6d824fd820405626ab9b6d79f1fd04e126ab8e17729e3afc7cb5af794f8"),
378+
false,
379+
false,
380+
&hex!("5e269b5a7bdedcc3e875e2725693a257fc60011af7dcd68a3358507fe29b0659ca66951daa05a15032033650bc58a27840f8fbe9f4088b9030738f68"),
381+
&[],
382+
),
383+
Ok(GenericArray::<_, _>::from_slice(&hex!("f0a339ecbcae6add1afb27da3ba40a1320c6427a58afb9dc366b219b7eb29ecf")).clone()),
384+
);
385+
}
386+
296387
static KNOWN_VALUES_FEEDBACK_HMAC_SHA256: &[KnownValue] = &[
297388
KnownValue {
298389
iv: Some(b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
@@ -339,43 +430,51 @@ mod tests {
339430
];
340431

341432
#[test]
342-
fn test_static_values_counter() {
433+
fn test_static_values_feedback() {
343434
type HmacSha256 = hmac::Hmac<sha2::Sha256>;
344435
type HmacSha512 = hmac::Hmac<sha2::Sha512>;
345436

346-
let counter = Counter::<HmacSha256, HmacSha512>::default();
347-
for (v, i) in KNOWN_VALUES_COUNTER_HMAC_SHA256.iter().zip(0..) {
437+
for (v, i) in KNOWN_VALUES_FEEDBACK_HMAC_SHA256.iter().zip(0..) {
438+
let feedback =
439+
Feedback::<HmacSha256, HmacSha512>::new(v.iv.map(GenericArray::from_slice));
348440
assert_eq!(
349-
counter.derive(
350-
GenericArray::from_slice(v.key),
351-
v.use_l,
352-
v.use_separator,
353-
v.label,
354-
v.context,
355-
),
356-
Ok(GenericArray::<_, U128>::from_slice(v.expected).clone()),
441+
feedback.derive(v.key, v.use_l, v.use_separator, v.label, v.context,),
442+
Ok(GenericArray::<_, _>::from_slice(v.expected).clone()),
357443
"key derivation failed for (index: {i}):\n{v:x?}"
358444
);
359445
}
360446
}
361447

448+
static KNOWN_VALUES_DOUBLE_PIPELINE_HMAC_SHA256: &[KnownValue] = &[KnownValue {
449+
iv: None,
450+
use_l: false, //true,
451+
use_separator: true,
452+
label: &hex!("921ab061920b191de12f746ac9de08"),
453+
context: &hex!("4f2c20f01775e27bcacdc21ee4a5ff0387758f36d8ec71c7a8c8208284f650b611837e"),
454+
key: &hex!("7d4f86fdfd1c4ba04c674a68d60316d12c99c1b1f44f0a8e02bd2601377ebcd9"),
455+
expected: &hex!(
456+
"
457+
506bc2ba51410b2a6e7c05d33891520d dd5f702ad3d6203d76d8dae1216d0783
458+
d8c59fae2e821d8eff2d8ddd93a6741c 8f144fb96e9ca7d7c532468f213f5efe
459+
"
460+
),
461+
}];
462+
362463
#[test]
363-
fn test_static_values_feedback() {
464+
fn test_static_values_double_pipeline() {
364465
type HmacSha256 = hmac::Hmac<sha2::Sha256>;
365-
type HmacSha512 = hmac::Hmac<sha2::Sha512>;
366466

367-
for (v, i) in KNOWN_VALUES_FEEDBACK_HMAC_SHA256.iter().zip(0..) {
368-
let feedback =
369-
Feedback::<HmacSha256, HmacSha512>::new(v.iv.map(GenericArray::from_slice));
467+
struct MockOutput;
468+
469+
impl KeySizeUser for MockOutput {
470+
type KeySize = U64;
471+
}
472+
473+
for (v, i) in KNOWN_VALUES_DOUBLE_PIPELINE_HMAC_SHA256.iter().zip(0..) {
474+
let dbl_pipeline = DoublePipeline::<HmacSha256, MockOutput>::default();
370475
assert_eq!(
371-
feedback.derive(
372-
GenericArray::from_slice(v.key),
373-
v.use_l,
374-
v.use_separator,
375-
v.label,
376-
v.context,
377-
),
378-
Ok(GenericArray::<_, U128>::from_slice(v.expected).clone()),
476+
dbl_pipeline.derive(v.key, v.use_l, v.use_separator, v.label, v.context,),
477+
Ok(GenericArray::<_, _>::from_slice(v.expected).clone()),
379478
"key derivation failed for (index: {i}):\n{v:x?}"
380479
);
381480
}

0 commit comments

Comments
 (0)