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