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 //! Cryptographic materials for v1 advertisement-format credentials.
16 
17 use crate::credential::{protocol_version_seal, DiscoveryMetadataCryptoMaterial, ProtocolVersion};
18 use crate::extended::V1IdentityToken;
19 use crypto_provider::{aead::Aead, aes, ed25519, CryptoProvider};
20 use np_hkdf::{DerivedSectionKeys, NpKeySeedHkdf};
21 
22 /// Cryptographic information about a particular V1 discovery credential
23 /// necessary to match and decrypt encrypted V1 sections.
24 #[derive(Clone, Debug, PartialEq, Eq)]
25 pub struct V1DiscoveryCredential {
26     /// The 32-byte key-seed used for generating other key material.
27     pub key_seed: [u8; 32],
28 
29     /// The MIC-short-salt variant of the HMAC of the identity token.
30     pub expected_mic_short_salt_identity_token_hmac: [u8; 32],
31 
32     /// The MIC-extended-salt variant of the HMAC of the identity token.
33     pub expected_mic_extended_salt_identity_token_hmac: [u8; 32],
34 
35     /// The signed-extended-salt variant of the HMAC of the identity token.
36     pub expected_signed_extended_salt_identity_token_hmac: [u8; 32],
37 
38     /// The ed25519 public key used for verification of signed sections.
39     pub public_key: ed25519::PublicKey,
40 }
41 
42 impl V1DiscoveryCredential {
43     /// Construct a V1 discovery credential from the provided identity data.
new( key_seed: [u8; 32], expected_mic_short_salt_identity_token_hmac: [u8; 32], expected_mic_extended_salt_identity_token_hmac: [u8; 32], expected_signed_extended_salt_identity_token_hmac: [u8; 32], public_key: ed25519::PublicKey, ) -> Self44     pub fn new(
45         key_seed: [u8; 32],
46         expected_mic_short_salt_identity_token_hmac: [u8; 32],
47         expected_mic_extended_salt_identity_token_hmac: [u8; 32],
48         expected_signed_extended_salt_identity_token_hmac: [u8; 32],
49         public_key: ed25519::PublicKey,
50     ) -> Self {
51         Self {
52             key_seed,
53             expected_mic_short_salt_identity_token_hmac,
54             expected_mic_extended_salt_identity_token_hmac,
55             expected_signed_extended_salt_identity_token_hmac,
56             public_key,
57         }
58     }
59 
60     /// Constructs pre-calculated crypto material from this discovery credential.
to_precalculated<C: CryptoProvider>( &self, ) -> PrecalculatedV1DiscoveryCryptoMaterial61     pub(crate) fn to_precalculated<C: CryptoProvider>(
62         &self,
63     ) -> PrecalculatedV1DiscoveryCryptoMaterial {
64         PrecalculatedV1DiscoveryCryptoMaterial {
65             signed_identity_resolution_material: self.signed_identity_resolution_material::<C>(),
66             mic_short_salt_identity_resolution_material: self
67                 .mic_short_salt_identity_resolution_material::<C>(),
68             mic_extended_salt_identity_resolution_material: self
69                 .mic_extended_salt_identity_resolution_material::<C>(),
70             signed_verification_material: self.signed_verification_material::<C>(),
71             mic_short_salt_verification_material: self.mic_short_salt_verification_material::<C>(),
72             mic_extended_salt_verification_material: self
73                 .mic_extended_salt_verification_material::<C>(),
74             metadata_nonce: self.metadata_nonce::<C>(),
75         }
76     }
77 }
78 
79 impl DiscoveryMetadataCryptoMaterial<V1> for V1DiscoveryCredential {
metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12]80     fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
81         np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed).v1_metadata_nonce()
82     }
83 }
84 
85 impl V1DiscoveryCryptoMaterial for V1DiscoveryCredential {
signed_identity_resolution_material<C: CryptoProvider>( &self, ) -> SignedSectionIdentityResolutionMaterial86     fn signed_identity_resolution_material<C: CryptoProvider>(
87         &self,
88     ) -> SignedSectionIdentityResolutionMaterial {
89         let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
90         SignedSectionIdentityResolutionMaterial::from_hkdf_and_expected_identity_token_hmac(
91             &hkdf,
92             self.expected_signed_extended_salt_identity_token_hmac,
93         )
94     }
95 
mic_short_salt_identity_resolution_material<C: CryptoProvider>( &self, ) -> MicShortSaltSectionIdentityResolutionMaterial96     fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
97         &self,
98     ) -> MicShortSaltSectionIdentityResolutionMaterial {
99         let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
100         MicShortSaltSectionIdentityResolutionMaterial::from_hkdf_and_expected_identity_token_hmac(
101             &hkdf,
102             self.expected_mic_short_salt_identity_token_hmac,
103         )
104     }
105 
mic_extended_salt_identity_resolution_material<C: CryptoProvider>( &self, ) -> MicExtendedSaltSectionIdentityResolutionMaterial106     fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
107         &self,
108     ) -> MicExtendedSaltSectionIdentityResolutionMaterial {
109         let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
110         MicExtendedSaltSectionIdentityResolutionMaterial::from_hkdf_and_expected_identity_token_hmac(
111             &hkdf,
112             self.expected_mic_extended_salt_identity_token_hmac,
113         )
114     }
115 
signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial116     fn signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial {
117         SignedSectionVerificationMaterial { public_key: self.public_key.clone() }
118     }
119 
mic_short_salt_verification_material<C: CryptoProvider>( &self, ) -> MicShortSaltSectionVerificationMaterial120     fn mic_short_salt_verification_material<C: CryptoProvider>(
121         &self,
122     ) -> MicShortSaltSectionVerificationMaterial {
123         let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
124         let mic_hmac_key = *hkdf.v1_mic_short_salt_keys().mic_hmac_key().as_bytes();
125         MicShortSaltSectionVerificationMaterial { mic_hmac_key }
126     }
127 
mic_extended_salt_verification_material<C: CryptoProvider>( &self, ) -> MicExtendedSaltSectionVerificationMaterial128     fn mic_extended_salt_verification_material<C: CryptoProvider>(
129         &self,
130     ) -> MicExtendedSaltSectionVerificationMaterial {
131         let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
132         let mic_hmac_key = *hkdf.v1_mic_extended_salt_keys().mic_hmac_key().as_bytes();
133         MicExtendedSaltSectionVerificationMaterial { mic_hmac_key }
134     }
135 }
136 
137 /// Type-level identifier for the V1 protocol version.
138 #[derive(Debug, Clone)]
139 pub enum V1 {}
140 
141 impl protocol_version_seal::ProtocolVersionSeal for V1 {}
142 
143 impl ProtocolVersion for V1 {
144     type DiscoveryCredential = V1DiscoveryCredential;
145     type IdentityToken = V1IdentityToken;
146 
metadata_nonce_from_key_seed<C: CryptoProvider>( hkdf: &NpKeySeedHkdf<C>, ) -> <C::Aes128Gcm as Aead>::Nonce147     fn metadata_nonce_from_key_seed<C: CryptoProvider>(
148         hkdf: &NpKeySeedHkdf<C>,
149     ) -> <C::Aes128Gcm as Aead>::Nonce {
150         hkdf.v1_metadata_nonce()
151     }
152 
extract_metadata_key<C: CryptoProvider>( identity_token: Self::IdentityToken, ) -> aes::Aes128Key153     fn extract_metadata_key<C: CryptoProvider>(
154         identity_token: Self::IdentityToken,
155     ) -> aes::Aes128Key {
156         identity_token.into_bytes().into()
157     }
158 }
159 
160 /// Trait which exists purely to be able to restrict the protocol
161 /// version of certain type-bounds to V1.
162 pub trait V1ProtocolVersion: ProtocolVersion {}
163 
164 impl V1ProtocolVersion for V1 {}
165 
166 /// Cryptographic materials necessary for determining whether or not
167 /// a given V1 advertisement section matches an identity.
168 /// Per the construction of the V1 specification, this is also
169 /// the information necessary to decrypt the raw byte contents
170 /// of an encrypted V1 section.
171 #[derive(Clone)]
172 pub(crate) struct SectionIdentityResolutionMaterial {
173     /// The AES key for decrypting section ciphertext
174     pub(crate) aes_key: aes::Aes128Key,
175     /// The identity token HMAC key for deriving and verifying the identity metadata
176     /// key HMAC against the expected value.
177     pub(crate) identity_token_hmac_key: [u8; 32],
178     /// The expected identity token HMAC to check against for an identity match.
179     pub(crate) expected_identity_token_hmac: [u8; 32],
180 }
181 
182 /// Cryptographic materials necessary for determining whether or not
183 /// a given V1 signed advertisement section matches an identity.
184 #[derive(Clone)]
185 pub struct SignedSectionIdentityResolutionMaterial(SectionIdentityResolutionMaterial);
186 
187 impl SignedSectionIdentityResolutionMaterial {
188     #[cfg(test)]
from_raw(raw: SectionIdentityResolutionMaterial) -> Self189     pub(crate) fn from_raw(raw: SectionIdentityResolutionMaterial) -> Self {
190         Self(raw)
191     }
192     /// Extracts the underlying section-identity resolution material carried around
193     /// within this wrapper for resolution of signed sections.
into_raw_resolution_material(self) -> SectionIdentityResolutionMaterial194     pub(crate) fn into_raw_resolution_material(self) -> SectionIdentityResolutionMaterial {
195         self.0
196     }
197     #[cfg(any(test, feature = "devtools"))]
198     /// Gets the underlying section-identity resolution material carried around
199     /// within this wrapper for resolution of signed sections.
as_raw_resolution_material(&self) -> &SectionIdentityResolutionMaterial200     pub(crate) fn as_raw_resolution_material(&self) -> &SectionIdentityResolutionMaterial {
201         &self.0
202     }
203 
204     /// Constructs identity-resolution material for a signed section whose
205     /// discovery credential leverages the provided HKDF and has the given
206     /// expected metadata-key HMAC.
from_hkdf_and_expected_identity_token_hmac<C: CryptoProvider>( hkdf: &np_hkdf::NpKeySeedHkdf<C>, expected_identity_token_hmac: [u8; 32], ) -> Self207     pub(crate) fn from_hkdf_and_expected_identity_token_hmac<C: CryptoProvider>(
208         hkdf: &np_hkdf::NpKeySeedHkdf<C>,
209         expected_identity_token_hmac: [u8; 32],
210     ) -> Self {
211         Self(SectionIdentityResolutionMaterial {
212             aes_key: hkdf.v1_signature_keys().aes_key(),
213             identity_token_hmac_key: *hkdf.v1_signature_keys().identity_token_hmac_key().as_bytes(),
214             expected_identity_token_hmac,
215         })
216     }
217 }
218 
219 /// Cryptographic materials necessary for determining whether or not
220 /// a given V1 MIC extended salt advertisement section matches an identity.
221 #[derive(Clone)]
222 pub struct MicExtendedSaltSectionIdentityResolutionMaterial(SectionIdentityResolutionMaterial);
223 
224 impl MicExtendedSaltSectionIdentityResolutionMaterial {
225     /// Extracts the underlying section-identity resolution material carried around
226     /// within this wrapper for resolution of MIC extended salt sections.
into_raw_resolution_material(self) -> SectionIdentityResolutionMaterial227     pub(crate) fn into_raw_resolution_material(self) -> SectionIdentityResolutionMaterial {
228         self.0
229     }
230     /// Gets the underlying section-identity resolution material carried around
231     /// within this wrapper for resolution of MIC extended salt sections.
232     #[cfg(any(test, feature = "devtools"))]
as_raw_resolution_material(&self) -> &SectionIdentityResolutionMaterial233     pub(crate) fn as_raw_resolution_material(&self) -> &SectionIdentityResolutionMaterial {
234         &self.0
235     }
236     #[cfg(test)]
as_mut_raw_resolution_material( &mut self, ) -> &mut SectionIdentityResolutionMaterial237     pub(crate) fn as_mut_raw_resolution_material(
238         &mut self,
239     ) -> &mut SectionIdentityResolutionMaterial {
240         &mut self.0
241     }
242     /// Constructs identity-resolution material for an MIC extended salt section whose
243     /// discovery credential leverages the provided HKDF and has the given
244     /// expected metadata-key HMAC.
from_hkdf_and_expected_identity_token_hmac<C: CryptoProvider>( hkdf: &np_hkdf::NpKeySeedHkdf<C>, expected_identity_token_hmac: [u8; 32], ) -> Self245     pub(crate) fn from_hkdf_and_expected_identity_token_hmac<C: CryptoProvider>(
246         hkdf: &np_hkdf::NpKeySeedHkdf<C>,
247         expected_identity_token_hmac: [u8; 32],
248     ) -> Self {
249         Self(SectionIdentityResolutionMaterial {
250             aes_key: hkdf.v1_mic_extended_salt_keys().aes_key(),
251             identity_token_hmac_key: *hkdf
252                 .v1_mic_extended_salt_keys()
253                 .identity_token_hmac_key()
254                 .as_bytes(),
255             expected_identity_token_hmac,
256         })
257     }
258 }
259 
260 /// Cryptographic materials necessary for determining whether
261 /// a given V1 MIC short salt advertisement section matches an identity.
262 #[derive(Clone)]
263 pub struct MicShortSaltSectionIdentityResolutionMaterial(SectionIdentityResolutionMaterial);
264 
265 impl MicShortSaltSectionIdentityResolutionMaterial {
266     /// Extracts the underlying section-identity resolution material carried around
267     /// within this wrapper for resolution of MIC short salt sections.
into_raw_resolution_material(self) -> SectionIdentityResolutionMaterial268     pub(crate) fn into_raw_resolution_material(self) -> SectionIdentityResolutionMaterial {
269         self.0
270     }
271     /// Gets the underlying section-identity resolution material carried around
272     /// within this wrapper for resolution of MIC short salt sections.
273     #[cfg(any(test, feature = "devtools"))]
as_raw_resolution_material(&self) -> &SectionIdentityResolutionMaterial274     pub(crate) fn as_raw_resolution_material(&self) -> &SectionIdentityResolutionMaterial {
275         &self.0
276     }
277     #[cfg(test)]
as_mut_raw_resolution_material( &mut self, ) -> &mut SectionIdentityResolutionMaterial278     pub(crate) fn as_mut_raw_resolution_material(
279         &mut self,
280     ) -> &mut SectionIdentityResolutionMaterial {
281         &mut self.0
282     }
283 
284     /// Constructs identity-resolution material for a MIC short salt section whose
285     /// discovery credential leverages the provided HKDF and has the given
286     /// expected metadata-key HMAC.
from_hkdf_and_expected_identity_token_hmac<C: CryptoProvider>( hkdf: &np_hkdf::NpKeySeedHkdf<C>, expected_identity_token_hmac: [u8; 32], ) -> Self287     pub(crate) fn from_hkdf_and_expected_identity_token_hmac<C: CryptoProvider>(
288         hkdf: &np_hkdf::NpKeySeedHkdf<C>,
289         expected_identity_token_hmac: [u8; 32],
290     ) -> Self {
291         Self(SectionIdentityResolutionMaterial {
292             aes_key: hkdf.v1_mic_short_salt_keys().aes_key(),
293             identity_token_hmac_key: *hkdf
294                 .v1_mic_short_salt_keys()
295                 .identity_token_hmac_key()
296                 .as_bytes(),
297             expected_identity_token_hmac,
298         })
299     }
300 }
301 
302 /// Crypto materials for V1 signed sections which are not employed in identity resolution,
303 /// but may be necessary to verify a signed section.
304 #[derive(Clone)]
305 pub struct SignedSectionVerificationMaterial {
306     /// The np_ed25519 public key to be
307     /// used for signature verification of signed sections.
308     pub(crate) public_key: ed25519::PublicKey,
309 }
310 
311 impl SignedSectionVerificationMaterial {
312     /// Gets the np_ed25519 public key for the given identity,
313     /// used for signature verification of signed sections.
signature_verification_public_key(&self) -> ed25519::PublicKey314     pub(crate) fn signature_verification_public_key(&self) -> ed25519::PublicKey {
315         self.public_key.clone()
316     }
317 }
318 
319 /// Crypto materials for V1 MIC short salt sections which are not employed in identity resolution,
320 /// but may be necessary to fully decrypt a MIC short salt section.
321 #[derive(Clone)]
322 pub struct MicShortSaltSectionVerificationMaterial {
323     /// The MIC HMAC key for verifying the integrity of MIC short salt sections.
324     pub(crate) mic_hmac_key: [u8; 32],
325 }
326 
327 impl MicSectionVerificationMaterial for MicShortSaltSectionVerificationMaterial {
mic_hmac_key(&self) -> np_hkdf::NpHmacSha256Key328     fn mic_hmac_key(&self) -> np_hkdf::NpHmacSha256Key {
329         self.mic_hmac_key.into()
330     }
331 }
332 
333 /// Crypto materials for V1 MIC extended salt sections which are not employed in identity
334 /// resolution, but may be necessary to fully decrypt a MIC extended salt section.
335 #[derive(Clone)]
336 pub struct MicExtendedSaltSectionVerificationMaterial {
337     /// The MIC HMAC key for verifying the integrity of MIC extended salt sections.
338     pub(crate) mic_hmac_key: [u8; 32],
339 }
340 
341 impl MicSectionVerificationMaterial for MicExtendedSaltSectionVerificationMaterial {
mic_hmac_key(&self) -> np_hkdf::NpHmacSha256Key342     fn mic_hmac_key(&self) -> np_hkdf::NpHmacSha256Key {
343         self.mic_hmac_key.into()
344     }
345 }
346 
347 pub(crate) trait MicSectionVerificationMaterial {
348     /// Returns the HMAC key for calculating the MIC of the sections
mic_hmac_key(&self) -> np_hkdf::NpHmacSha256Key349     fn mic_hmac_key(&self) -> np_hkdf::NpHmacSha256Key;
350 }
351 
352 // Space-time tradeoffs:
353 // - Calculating an HKDF from the key seed costs about 2us on a gLinux laptop, and occupies 80b.
354 // - Calculating an AES (16b) or HMAC (32b) key from the HKDF costs about 700ns.
355 // The right tradeoff may also vary by use case. For frequently used identities we should
356 // probably pre-calculate everything. For occasionally used ones, or ones that are loaded from
357 // disk, used once, and discarded, we might want to precalculate on a separate thread or the
358 // like.
359 // The AES key and metadata key HMAC key are the most frequently used ones, as the MIC HMAC key
360 // is only used on the matching identity, not all identities.
361 
362 /// Cryptographic material for an individual NP credential used to decrypt and verify v1 sections.
363 pub trait V1DiscoveryCryptoMaterial: DiscoveryMetadataCryptoMaterial<V1> {
364     /// Constructs or copies the identity resolution material for signed sections
signed_identity_resolution_material<C: CryptoProvider>( &self, ) -> SignedSectionIdentityResolutionMaterial365     fn signed_identity_resolution_material<C: CryptoProvider>(
366         &self,
367     ) -> SignedSectionIdentityResolutionMaterial;
368 
369     /// Constructs or copies the identity resolution material for MIC short salt sections
mic_short_salt_identity_resolution_material<C: CryptoProvider>( &self, ) -> MicShortSaltSectionIdentityResolutionMaterial370     fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
371         &self,
372     ) -> MicShortSaltSectionIdentityResolutionMaterial;
373 
374     /// Constructs or copies the identity resolution material for MIC extended salt sections
mic_extended_salt_identity_resolution_material<C: CryptoProvider>( &self, ) -> MicExtendedSaltSectionIdentityResolutionMaterial375     fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
376         &self,
377     ) -> MicExtendedSaltSectionIdentityResolutionMaterial;
378 
379     /// Constructs or copies non-identity-resolution deserialization material for signed
380     /// sections.
signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial381     fn signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial;
382 
383     /// Constructs or copies non-identity-resolution deserialization material for MIC short salt
384     /// sections.
mic_short_salt_verification_material<C: CryptoProvider>( &self, ) -> MicShortSaltSectionVerificationMaterial385     fn mic_short_salt_verification_material<C: CryptoProvider>(
386         &self,
387     ) -> MicShortSaltSectionVerificationMaterial;
388 
389     /// Constructs or copies non-identity-resolution deserialization material for MIC extended salt
390     /// sections.
mic_extended_salt_verification_material<C: CryptoProvider>( &self, ) -> MicExtendedSaltSectionVerificationMaterial391     fn mic_extended_salt_verification_material<C: CryptoProvider>(
392         &self,
393     ) -> MicExtendedSaltSectionVerificationMaterial;
394 }
395 
396 /// [`V1DiscoveryCryptoMaterial`] that minimizes CPU time when providing key material at
397 /// the expense of occupied memory
398 pub struct PrecalculatedV1DiscoveryCryptoMaterial {
399     pub(crate) signed_identity_resolution_material: SignedSectionIdentityResolutionMaterial,
400     pub(crate) mic_short_salt_identity_resolution_material:
401         MicShortSaltSectionIdentityResolutionMaterial,
402     pub(crate) mic_extended_salt_identity_resolution_material:
403         MicExtendedSaltSectionIdentityResolutionMaterial,
404     pub(crate) signed_verification_material: SignedSectionVerificationMaterial,
405     pub(crate) mic_short_salt_verification_material: MicShortSaltSectionVerificationMaterial,
406     pub(crate) mic_extended_salt_verification_material: MicExtendedSaltSectionVerificationMaterial,
407     pub(crate) metadata_nonce: [u8; 12],
408 }
409 
410 impl DiscoveryMetadataCryptoMaterial<V1> for PrecalculatedV1DiscoveryCryptoMaterial {
metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12]411     fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
412         self.metadata_nonce
413     }
414 }
415 
416 impl V1DiscoveryCryptoMaterial for PrecalculatedV1DiscoveryCryptoMaterial {
signed_identity_resolution_material<C: CryptoProvider>( &self, ) -> SignedSectionIdentityResolutionMaterial417     fn signed_identity_resolution_material<C: CryptoProvider>(
418         &self,
419     ) -> SignedSectionIdentityResolutionMaterial {
420         self.signed_identity_resolution_material.clone()
421     }
422 
mic_short_salt_identity_resolution_material<C: CryptoProvider>( &self, ) -> MicShortSaltSectionIdentityResolutionMaterial423     fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
424         &self,
425     ) -> MicShortSaltSectionIdentityResolutionMaterial {
426         self.mic_short_salt_identity_resolution_material.clone()
427     }
428 
mic_extended_salt_identity_resolution_material<C: CryptoProvider>( &self, ) -> MicExtendedSaltSectionIdentityResolutionMaterial429     fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
430         &self,
431     ) -> MicExtendedSaltSectionIdentityResolutionMaterial {
432         self.mic_extended_salt_identity_resolution_material.clone()
433     }
signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial434     fn signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial {
435         self.signed_verification_material.clone()
436     }
437 
mic_short_salt_verification_material<C: CryptoProvider>( &self, ) -> MicShortSaltSectionVerificationMaterial438     fn mic_short_salt_verification_material<C: CryptoProvider>(
439         &self,
440     ) -> MicShortSaltSectionVerificationMaterial {
441         self.mic_short_salt_verification_material.clone()
442     }
443 
mic_extended_salt_verification_material<C: CryptoProvider>( &self, ) -> MicExtendedSaltSectionVerificationMaterial444     fn mic_extended_salt_verification_material<C: CryptoProvider>(
445         &self,
446     ) -> MicExtendedSaltSectionVerificationMaterial {
447         self.mic_extended_salt_verification_material.clone()
448     }
449 }
450 
451 // Implementations for reference types -- we don't provide a blanket impl for references
452 // due to the potential to conflict with downstream crates' implementations.
453 
454 impl<'a> DiscoveryMetadataCryptoMaterial<V1> for &'a V1DiscoveryCredential {
metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12]455     fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
456         (*self).metadata_nonce::<C>()
457     }
458 }
459 
460 impl<'a> V1DiscoveryCryptoMaterial for &'a V1DiscoveryCredential {
signed_identity_resolution_material<C: CryptoProvider>( &self, ) -> SignedSectionIdentityResolutionMaterial461     fn signed_identity_resolution_material<C: CryptoProvider>(
462         &self,
463     ) -> SignedSectionIdentityResolutionMaterial {
464         (*self).signed_identity_resolution_material::<C>()
465     }
466 
mic_short_salt_identity_resolution_material<C: CryptoProvider>( &self, ) -> MicShortSaltSectionIdentityResolutionMaterial467     fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
468         &self,
469     ) -> MicShortSaltSectionIdentityResolutionMaterial {
470         (*self).mic_short_salt_identity_resolution_material::<C>()
471     }
472 
mic_extended_salt_identity_resolution_material<C: CryptoProvider>( &self, ) -> MicExtendedSaltSectionIdentityResolutionMaterial473     fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
474         &self,
475     ) -> MicExtendedSaltSectionIdentityResolutionMaterial {
476         (*self).mic_extended_salt_identity_resolution_material::<C>()
477     }
signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial478     fn signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial {
479         (*self).signed_verification_material::<C>()
480     }
481 
mic_short_salt_verification_material<C: CryptoProvider>( &self, ) -> MicShortSaltSectionVerificationMaterial482     fn mic_short_salt_verification_material<C: CryptoProvider>(
483         &self,
484     ) -> MicShortSaltSectionVerificationMaterial {
485         (*self).mic_short_salt_verification_material::<C>()
486     }
487 
mic_extended_salt_verification_material<C: CryptoProvider>( &self, ) -> MicExtendedSaltSectionVerificationMaterial488     fn mic_extended_salt_verification_material<C: CryptoProvider>(
489         &self,
490     ) -> MicExtendedSaltSectionVerificationMaterial {
491         (*self).mic_extended_salt_verification_material::<C>()
492     }
493 }
494 
495 impl<'a> DiscoveryMetadataCryptoMaterial<V1> for &'a PrecalculatedV1DiscoveryCryptoMaterial {
metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12]496     fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
497         (*self).metadata_nonce::<C>()
498     }
499 }
500 
501 impl<'a> V1DiscoveryCryptoMaterial for &'a PrecalculatedV1DiscoveryCryptoMaterial {
signed_identity_resolution_material<C: CryptoProvider>( &self, ) -> SignedSectionIdentityResolutionMaterial502     fn signed_identity_resolution_material<C: CryptoProvider>(
503         &self,
504     ) -> SignedSectionIdentityResolutionMaterial {
505         (*self).signed_identity_resolution_material::<C>()
506     }
507 
mic_short_salt_identity_resolution_material<C: CryptoProvider>( &self, ) -> MicShortSaltSectionIdentityResolutionMaterial508     fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
509         &self,
510     ) -> MicShortSaltSectionIdentityResolutionMaterial {
511         (*self).mic_short_salt_identity_resolution_material::<C>()
512     }
513 
mic_extended_salt_identity_resolution_material<C: CryptoProvider>( &self, ) -> MicExtendedSaltSectionIdentityResolutionMaterial514     fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
515         &self,
516     ) -> MicExtendedSaltSectionIdentityResolutionMaterial {
517         (*self).mic_extended_salt_identity_resolution_material::<C>()
518     }
signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial519     fn signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial {
520         (*self).signed_verification_material::<C>()
521     }
522 
mic_short_salt_verification_material<C: CryptoProvider>( &self, ) -> MicShortSaltSectionVerificationMaterial523     fn mic_short_salt_verification_material<C: CryptoProvider>(
524         &self,
525     ) -> MicShortSaltSectionVerificationMaterial {
526         (*self).mic_short_salt_verification_material::<C>()
527     }
528 
mic_extended_salt_verification_material<C: CryptoProvider>( &self, ) -> MicExtendedSaltSectionVerificationMaterial529     fn mic_extended_salt_verification_material<C: CryptoProvider>(
530         &self,
531     ) -> MicExtendedSaltSectionVerificationMaterial {
532         (*self).mic_extended_salt_verification_material::<C>()
533     }
534 }
535 
536 /// Crypto material for creating V1 sections.
537 #[derive(Clone)]
538 pub struct V1BroadcastCredential {
539     /// The 32-byte key-seed used for generating other key material.
540     pub key_seed: [u8; 32],
541 
542     /// The 16-byte identity-token which identifies the sender.
543     pub identity_token: V1IdentityToken,
544 
545     /// The ed25519 private key to be used for signing section contents.
546     pub private_key: ed25519::PrivateKey,
547 }
548 
549 impl V1BroadcastCredential {
550     /// Builds some simple V1 signed broadcast crypto-materials out of
551     /// the provided key-seed, metadata-key, and ed25519 private key.
new( key_seed: [u8; 32], identity_token: V1IdentityToken, private_key: ed25519::PrivateKey, ) -> Self552     pub fn new(
553         key_seed: [u8; 32],
554         identity_token: V1IdentityToken,
555         private_key: ed25519::PrivateKey,
556     ) -> Self {
557         Self { key_seed, identity_token, private_key }
558     }
559 
560     /// Key seed from which other keys are derived.
key_seed(&self) -> [u8; 32]561     pub(crate) fn key_seed(&self) -> [u8; 32] {
562         self.key_seed
563     }
564 
565     /// Identity token that will be incorporated into encrypted advertisements.
identity_token(&self) -> V1IdentityToken566     pub(crate) fn identity_token(&self) -> V1IdentityToken {
567         self.identity_token
568     }
569 
570     /// Derive a discovery credential with the data necessary to discover advertisements produced
571     /// by this broadcast credential.
derive_discovery_credential<C: CryptoProvider>(&self) -> V1DiscoveryCredential572     pub fn derive_discovery_credential<C: CryptoProvider>(&self) -> V1DiscoveryCredential {
573         let key_seed = self.key_seed();
574         let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
575 
576         V1DiscoveryCredential::new(
577             key_seed,
578             hkdf.v1_mic_short_salt_keys()
579                 .identity_token_hmac_key()
580                 .calculate_hmac::<C>(self.identity_token.as_slice()),
581             hkdf.v1_mic_extended_salt_keys()
582                 .identity_token_hmac_key()
583                 .calculate_hmac::<C>(self.identity_token.as_slice()),
584             hkdf.v1_signature_keys()
585                 .identity_token_hmac_key()
586                 .calculate_hmac::<C>(self.identity_token.as_slice()),
587             self.signing_key().derive_public_key::<C::Ed25519>(),
588         )
589     }
590 
591     /// Key used for signature-protected sections
signing_key(&self) -> ed25519::PrivateKey592     pub(crate) fn signing_key(&self) -> ed25519::PrivateKey {
593         self.private_key.clone()
594     }
595 }
596