• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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