• 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 //! 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