• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use crypto_provider::hmac::{InvalidLength, MacError};
16 use hmac::digest::block_buffer::Eager;
17 use hmac::digest::consts::U256;
18 use hmac::digest::core_api::{
19     BlockSizeUser, BufferKindUser, CoreProxy, FixedOutputCore, UpdateCore,
20 };
21 use hmac::digest::typenum::{IsLess, Le, NonZero};
22 use hmac::digest::{HashMarker, OutputSizeUser};
23 use hmac::Mac;
24 
25 /// RustCrypto based hmac implementation
26 pub struct Hmac<D>(hmac::Hmac<D>)
27 where
28     D: OutputSizeUser,
29     D: CoreProxy,
30     D::Core: HashMarker
31         + UpdateCore
32         + FixedOutputCore
33         + BufferKindUser<BufferKind = Eager>
34         + Default
35         + Clone,
36     <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
37     Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero;
38 
39 impl crypto_provider::hmac::Hmac<32> for Hmac<sha2::Sha256> {
40     #[allow(clippy::expect_used)]
41     fn new_from_key(key: [u8; 32]) -> Self {
42         hmac::Hmac::new_from_slice(&key)
43             .map(Self)
44             .expect("length will always be valid because input key is of fixed size")
45     }
46 
47     fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
48         hmac::Hmac::new_from_slice(key).map(Self).map_err(|_| InvalidLength)
49     }
50 
51     fn update(&mut self, data: &[u8]) {
52         self.0.update(data);
53     }
54 
55     fn finalize(self) -> [u8; 32] {
56         self.0.finalize().into_bytes().into()
57     }
58 
59     fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
60         self.0.verify_slice(tag).map_err(|_| MacError)
61     }
62 
63     fn verify(self, tag: [u8; 32]) -> Result<(), MacError> {
64         self.0.verify(&tag.into()).map_err(|_| MacError)
65     }
66 
67     fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
68         self.0.verify_truncated_left(tag).map_err(|_| MacError)
69     }
70 }
71 
72 impl crypto_provider::hmac::Hmac<64> for Hmac<sha2::Sha512> {
73     #[allow(clippy::expect_used)]
74     fn new_from_key(key: [u8; 64]) -> Self {
75         hmac::Hmac::new_from_slice(&key)
76             .map(Self)
77             .expect("length will always be valid because input key is of fixed size")
78     }
79 
80     fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
81         hmac::Hmac::new_from_slice(key).map(Self).map_err(|_| InvalidLength)
82     }
83 
84     fn update(&mut self, data: &[u8]) {
85         self.0.update(data);
86     }
87 
88     fn finalize(self) -> [u8; 64] {
89         self.0.finalize().into_bytes().into()
90     }
91 
92     fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
93         self.0.verify_slice(tag).map_err(|_| MacError)
94     }
95 
96     fn verify(self, tag: [u8; 64]) -> Result<(), MacError> {
97         self.0.verify(&tag.into()).map_err(|_| MacError)
98     }
99 
100     fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
101         self.0.verify_truncated_left(tag).map_err(|_| MacError)
102     }
103 }
104 
105 #[cfg(test)]
106 mod tests {
107     use crate::RustCrypto;
108     use core::marker::PhantomData;
109     use crypto_provider_test::hmac::*;
110 
111     #[apply(hmac_test_cases)]
112     fn hmac_tests(testcase: CryptoProviderTestCase<RustCrypto>) {
113         testcase(PhantomData);
114     }
115 }
116