1use crate::algorithm::Algorithm;
2
3#[cfg(not(feature = "ring"))]
4use hkdf::Hkdf;
5
6#[cfg(feature = "ring")]
7use ring::hkdf;
8
9pub struct HkdfWrapper {
10 algo: Algorithm,
11}
12
13#[cfg(not(feature = "ring"))]
14macro_rules! hkdf_expand {
15 ($self:ident, $ikm:ident, $salt:ident, $info:ident, $D:ty) => {{
16 let hk = Hkdf::<$D>::new(Some($salt), $ikm);
17 let mut okm = vec![0u8; $self.algo.output_length()];
18 hk.expand($info, &mut okm)
19 .expect("could not expand key due to possibly invalid length");
20 okm
21 }};
22}
23
24impl HkdfWrapper {
25 pub fn new(algo: Algorithm) -> Self {
26 Self { algo }
27 }
28
29 #[cfg(not(feature = "ring"))]
30 pub fn expand(&self, ikm: &[u8], salt: &[u8], info: &[u8]) -> Vec<u8> {
31 match self.algo {
32 Algorithm::SHA1 => hkdf_expand!(self, ikm, salt, info, sha1::Sha1),
33 Algorithm::SHA256 => hkdf_expand!(self, ikm, salt, info, sha2::Sha256),
34 Algorithm::SHA384 => hkdf_expand!(self, ikm, salt, info, sha2::Sha384),
35 Algorithm::SHA512 => hkdf_expand!(self, ikm, salt, info, sha2::Sha512),
36 }
37 }
38
39 #[cfg(feature = "ring")]
40 pub fn expand(&self, ikm: &[u8], salt: &[u8], info: &[u8]) -> Vec<u8> {
41 let hkdf_algo = self.algo.to_hkdf();
42 let prk = hkdf::Salt::new(hkdf_algo, salt).extract(ikm);
43
44 let mut okm = vec![0u8; self.algo.output_length()];
45 let okm_slice = &mut okm[..];
46 prk.expand(&[info], self.algo.to_hmac())
47 .expect("could not expand key due to possibly invalid length")
48 .fill(okm_slice)
49 .expect("could not fill key due to possibly invalid length");
50 okm
51 }
52}