1 // Copyright 2022 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 //! Various representations of salts for extended advertisements. 16 17 use nom::combinator; 18 19 use crypto_provider::{aes::ctr::AesCtrNonce, CryptoProvider, CryptoRng, FromCryptoRng}; 20 use np_hkdf::v1_salt::ExtendedV1Salt; 21 22 use crate::helpers::parse_byte_array; 23 24 /// Common behavior for V1 section salts. 25 pub trait V1Salt: Copy + Into<MultiSalt> { 26 /// Derive the nonce used for section encryption. 27 /// 28 /// Both kinds of salts can compute the nonce needed for de/encrypting a 29 /// section, but only extended salts can have data derived from them. compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce30 fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce; 31 } 32 33 impl V1Salt for ExtendedV1Salt { compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce34 fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce { 35 self.derive::<12, C>(None).expect("AES-CTR nonce is a valid HKDF size") 36 } 37 } 38 39 pub(crate) const SHORT_SALT_LEN: usize = 2; 40 41 /// A byte buffer the size of a V1 short salt 42 #[derive(Debug, PartialEq, Eq, Clone, Copy)] 43 pub struct ShortV1Salt([u8; SHORT_SALT_LEN]); 44 45 impl From<[u8; SHORT_SALT_LEN]> for ShortV1Salt { from(value: [u8; SHORT_SALT_LEN]) -> Self46 fn from(value: [u8; SHORT_SALT_LEN]) -> Self { 47 Self(value) 48 } 49 } 50 51 impl ShortV1Salt { bytes(&self) -> &[u8; SHORT_SALT_LEN]52 pub(crate) fn bytes(&self) -> &[u8; SHORT_SALT_LEN] { 53 &self.0 54 } 55 parse(input: &[u8]) -> nom::IResult<&[u8], Self>56 pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], Self> { 57 combinator::map(parse_byte_array::<SHORT_SALT_LEN>, Self)(input) 58 } 59 } 60 61 impl V1Salt for ShortV1Salt { compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce62 fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce { 63 np_hkdf::extended_mic_section_short_salt_nonce::<C>(self.0) 64 } 65 } 66 67 impl FromCryptoRng for ShortV1Salt { new_random<R: CryptoRng>(rng: &mut R) -> Self68 fn new_random<R: CryptoRng>(rng: &mut R) -> Self { 69 rng.gen::<[u8; SHORT_SALT_LEN]>().into() 70 } 71 } 72 73 /// Either a short or extended salt. 74 #[derive(Debug, PartialEq, Eq, Clone, Copy)] 75 pub enum MultiSalt { 76 /// A 2-byte salt 77 Short(ShortV1Salt), 78 /// A 16-byte salt 79 Extended(ExtendedV1Salt), 80 } 81 82 impl MultiSalt { 83 /// Salt bytes as a slice, for when variable-size access is sensible as_slice(&self) -> &[u8]84 pub fn as_slice(&self) -> &[u8] { 85 match self { 86 MultiSalt::Short(s) => s.bytes().as_slice(), 87 MultiSalt::Extended(s) => s.bytes().as_slice(), 88 } 89 } 90 } 91 92 impl From<ExtendedV1Salt> for MultiSalt { from(value: ExtendedV1Salt) -> Self93 fn from(value: ExtendedV1Salt) -> Self { 94 Self::Extended(value) 95 } 96 } 97 98 impl From<ShortV1Salt> for MultiSalt { from(value: ShortV1Salt) -> Self99 fn from(value: ShortV1Salt) -> Self { 100 Self::Short(value) 101 } 102 } 103 104 impl V1Salt for MultiSalt { 105 /// Both kinds of salts can compute the nonce needed for decrypting an 106 /// advertisement, but only extended salts can have data derived from them. compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce107 fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce { 108 match self { 109 Self::Short(s) => V1Salt::compute_nonce::<C>(s), 110 Self::Extended(s) => s.compute_nonce::<C>(), 111 } 112 } 113 } 114