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 //! BoringSSL based HKDF implementation. Unfortunately, because the OpenSSL and BoringSSL APIs 16 //! diverged for HKDF, we have to have separate implementations. 17 //! 18 //! See the _Using BoringSSL_ section in `crypto/README.md` for instructions on 19 //! how to test against BoringSSL, or see the subcommands in the top level crate. 20 21 use bssl_crypto::digest::Algorithm; 22 use bssl_crypto::hkdf::Salt; 23 use core::marker::PhantomData; 24 use crypto_provider::hkdf::InvalidLength; 25 26 /// Struct providing BoringSSL implemented Hkdf operations. 27 pub struct Hkdf<M: Algorithm>(bssl_crypto::hkdf::Prk, PhantomData<M>); 28 29 impl<M: Algorithm> crypto_provider::hkdf::Hkdf for Hkdf<M> { new(salt: Option<&[u8]>, ikm: &[u8]) -> Self30 fn new(salt: Option<&[u8]>, ikm: &[u8]) -> Self { 31 let bssl_salt = match salt { 32 None => Salt::None, 33 Some(raw_salt) => Salt::NonEmpty(raw_salt), 34 }; 35 Self(bssl_crypto::hkdf::Hkdf::<M>::extract(ikm, bssl_salt), PhantomData) 36 } 37 expand_multi_info( &self, info_components: &[&[u8]], okm: &mut [u8], ) -> Result<(), InvalidLength>38 fn expand_multi_info( 39 &self, 40 info_components: &[&[u8]], 41 okm: &mut [u8], 42 ) -> Result<(), InvalidLength> { 43 if okm.is_empty() { 44 return Ok(()); 45 } 46 self.0.expand_into(&info_components.concat(), okm).map_err(|_| InvalidLength) 47 } 48 expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), InvalidLength>49 fn expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), InvalidLength> { 50 if okm.is_empty() { 51 return Ok(()); 52 } 53 self.0.expand_into(info, okm).map_err(|_| InvalidLength) 54 } 55 } 56 57 #[cfg(test)] 58 mod tests { 59 use crate::Boringssl; 60 use core::marker::PhantomData; 61 use crypto_provider_test::hkdf::*; 62 63 #[apply(hkdf_test_cases)] hkdf_tests(testcase: CryptoProviderTestCase<Boringssl>)64 fn hkdf_tests(testcase: CryptoProviderTestCase<Boringssl>) { 65 testcase(PhantomData); 66 } 67 } 68