Coverage Report

Created: 2026-04-09 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/hmac-0.12.1/src/simple.rs
Line
Count
Source
1
use super::{get_der_key, IPAD, OPAD};
2
use core::fmt;
3
use digest::{
4
    crypto_common::{Block, BlockSizeUser, InvalidLength, Key, KeySizeUser},
5
    Digest, FixedOutput, KeyInit, MacMarker, Output, OutputSizeUser, Update,
6
};
7
#[cfg(feature = "reset")]
8
use digest::{FixedOutputReset, Reset};
9
10
/// Simplified HMAC instance able to operate over hash functions
11
/// which do not expose block-level API and hash functions which
12
/// process blocks lazily (e.g. BLAKE2).
13
#[derive(Clone)]
14
pub struct SimpleHmac<D: Digest + BlockSizeUser> {
15
    digest: D,
16
    opad_key: Block<D>,
17
    #[cfg(feature = "reset")]
18
    ipad_key: Block<D>,
19
}
20
21
impl<D: Digest + BlockSizeUser> KeySizeUser for SimpleHmac<D> {
22
    type KeySize = D::BlockSize;
23
}
24
25
impl<D: Digest + BlockSizeUser> MacMarker for SimpleHmac<D> {}
26
27
impl<D: Digest + BlockSizeUser> KeyInit for SimpleHmac<D> {
28
3.20k
    fn new(key: &Key<Self>) -> Self {
29
3.20k
        Self::new_from_slice(key.as_slice()).unwrap()
30
3.20k
    }
31
32
    #[inline]
33
12.8k
    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
34
12.8k
        let der_key = get_der_key::<D>(key);
35
12.8k
        let mut ipad_key = der_key.clone();
36
821k
        for b in ipad_key.iter_mut() {
37
821k
            *b ^= IPAD;
38
821k
        }
39
12.8k
        let mut digest = D::new();
40
12.8k
        digest.update(&ipad_key);
41
42
12.8k
        let mut opad_key = der_key;
43
821k
        for b in opad_key.iter_mut() {
44
821k
            *b ^= OPAD;
45
821k
        }
46
47
12.8k
        Ok(Self {
48
12.8k
            digest,
49
12.8k
            opad_key,
50
12.8k
            #[cfg(feature = "reset")]
51
12.8k
            ipad_key,
52
12.8k
        })
53
12.8k
    }
54
}
55
56
impl<D: Digest + BlockSizeUser> Update for SimpleHmac<D> {
57
    #[inline(always)]
58
51.3k
    fn update(&mut self, data: &[u8]) {
59
51.3k
        self.digest.update(data);
60
51.3k
    }
61
}
62
63
impl<D: Digest + BlockSizeUser> OutputSizeUser for SimpleHmac<D> {
64
    type OutputSize = D::OutputSize;
65
}
66
67
impl<D: Digest + BlockSizeUser> FixedOutput for SimpleHmac<D> {
68
6.41k
    fn finalize_into(self, out: &mut Output<Self>) {
69
6.41k
        let mut h = D::new();
70
6.41k
        h.update(&self.opad_key);
71
6.41k
        h.update(&self.digest.finalize());
72
6.41k
        h.finalize_into(out);
73
6.41k
    }
74
}
75
76
impl<D: Digest + BlockSizeUser + fmt::Debug> fmt::Debug for SimpleHmac<D> {
77
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78
        f.debug_struct("SimpleHmac")
79
            .field("digest", &self.digest)
80
            // TODO: replace with `finish_non_exhaustive` on MSRV
81
            // bump to 1.53
82
            .field("..", &"..")
83
            .finish()
84
    }
85
}
86
87
#[cfg(feature = "reset")]
88
#[cfg_attr(docsrs, doc(cfg(feature = "reset")))]
89
impl<D: Digest + BlockSizeUser + Reset> Reset for SimpleHmac<D> {
90
    fn reset(&mut self) {
91
        Reset::reset(&mut self.digest);
92
        self.digest.update(&self.ipad_key);
93
    }
94
}
95
96
#[cfg(feature = "reset")]
97
#[cfg_attr(docsrs, doc(cfg(feature = "reset")))]
98
impl<D: Digest + BlockSizeUser + FixedOutputReset> FixedOutputReset for SimpleHmac<D> {
99
16.0k
    fn finalize_into_reset(&mut self, out: &mut Output<Self>) {
100
16.0k
        let mut h = D::new();
101
16.0k
        Update::update(&mut h, &self.opad_key);
102
16.0k
        Update::update(&mut h, &self.digest.finalize_reset());
103
16.0k
        Update::update(&mut self.digest, &self.ipad_key);
104
16.0k
        Digest::finalize_into(h, out);
105
16.0k
    }
106
}