• 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 #![allow(clippy::indexing_slicing, clippy::unwrap_used)]
16 
17 use anyhow::anyhow;
18 use crypto_provider::aes::AesKey;
19 use crypto_provider_default::CryptoProviderImpl;
20 use np_hkdf::{v1_salt::ExtendedV1Salt, *};
21 use serde_json::json;
22 use std::{fs, io::Read as _};
23 use test_helper::extract_key_array;
24 use test_vector_hkdf::TestVectorHkdf;
25 
26 #[test]
hkdf_test_vectors() -> Result<(), anyhow::Error>27 fn hkdf_test_vectors() -> Result<(), anyhow::Error> {
28     let full_path =
29         test_helper::get_data_file("presence/np_hkdf/resources/test/hkdf-test-vectors.json");
30     let mut file = fs::File::open(full_path)?;
31     let mut data = String::new();
32     let _ = file.read_to_string(&mut data)?;
33     let test_cases = match serde_json::de::from_str(&data)? {
34         serde_json::Value::Array(a) => a,
35         _ => return Err(anyhow!("bad json")),
36     };
37 
38     for tc in test_cases {
39         {
40             let group = &tc["key_seed_hkdf"];
41             let key_seed = extract_key_array::<32>(group, "key_seed");
42             let hkdf = NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
43             assert_eq!(
44                 extract_key_array::<64>(group, "v0_ldt_key"),
45                 hkdf.v0_ldt_key().as_concatenated()
46             );
47             assert_eq!(
48                 &extract_key_array::<32>(group, "v0_identity_token_hmac_key"),
49                 hkdf.v0_identity_token_hmac_key().as_bytes()
50             );
51             assert_eq!(
52                 extract_key_array::<12>(group, "v0_metadata_nonce"),
53                 hkdf.v0_metadata_nonce()
54             );
55             assert_eq!(
56                 extract_key_array::<12>(group, "v1_metadata_nonce"),
57                 hkdf.v1_metadata_nonce()
58             );
59             assert_eq!(
60                 &extract_key_array::<32>(group, "v1_mic_short_salt_identity_token_hmac_key"),
61                 hkdf.v1_mic_short_salt_keys().identity_token_hmac_key().as_bytes()
62             );
63             assert_eq!(
64                 extract_key_array::<16>(group, "v1_mic_short_salt_aes_key"),
65                 *hkdf.v1_mic_short_salt_keys().aes_key().as_array()
66             );
67             assert_eq!(
68                 &extract_key_array::<32>(group, "v1_mic_short_salt_mic_hmac_key"),
69                 hkdf.v1_mic_short_salt_keys().mic_hmac_key().as_bytes()
70             );
71             assert_eq!(
72                 &extract_key_array::<32>(group, "v1_mic_extended_salt_identity_token_hmac_key"),
73                 hkdf.v1_mic_extended_salt_keys().identity_token_hmac_key().as_bytes()
74             );
75             assert_eq!(
76                 extract_key_array::<16>(group, "v1_mic_extended_salt_aes_key"),
77                 *hkdf.v1_mic_extended_salt_keys().aes_key().as_array()
78             );
79             assert_eq!(
80                 &extract_key_array::<32>(group, "v1_mic_extended_salt_mic_hmac_key"),
81                 hkdf.v1_mic_extended_salt_keys().mic_hmac_key().as_bytes()
82             );
83             assert_eq!(
84                 &extract_key_array::<32>(group, "v1_signature_identity_token_hmac_key"),
85                 hkdf.v1_signature_keys().identity_token_hmac_key().as_bytes()
86             );
87             assert_eq!(
88                 extract_key_array::<16>(group, "v1_signature_section_aes_key"),
89                 *hkdf.v1_signature_keys().aes_key().as_array()
90             );
91         }
92 
93         {
94             let group = &tc["v0_adv_salt_hkdf"];
95             let ikm = extract_key_array::<2>(group, "adv_salt");
96             assert_eq!(
97                 extract_key_array::<16>(group, "expanded_salt"),
98                 v0_ldt_expanded_salt::<CryptoProviderImpl>(&ikm)
99             )
100         }
101 
102         {
103             let group = &tc["v0_identity_token_hkdf"];
104             let ikm = extract_key_array::<14>(group, "v0_identity_token");
105             assert_eq!(
106                 extract_key_array::<16>(group, "expanded_key"),
107                 v0_metadata_expanded_key::<CryptoProviderImpl>(&ikm)
108             )
109         }
110 
111         {
112             let group = &tc["v1_section_extended_salt_hkdf"];
113             let ikm = extract_key_array::<16>(group, "section_extended_salt");
114             let salt = ExtendedV1Salt::from(ikm);
115             assert_eq!(
116                 extract_key_array::<16>(group, "derived_salt_nonce"),
117                 salt.derive::<16, CryptoProviderImpl>(None).unwrap(),
118             );
119             assert_eq!(
120                 extract_key_array::<16>(group, "derived_salt_first_de"),
121                 salt.derive::<16, CryptoProviderImpl>(Some(0.into())).unwrap(),
122             );
123             assert_eq!(
124                 extract_key_array::<16>(group, "derived_salt_third_de"),
125                 salt.derive::<16, CryptoProviderImpl>(Some(2.into())).unwrap(),
126             );
127         }
128 
129         {
130             let group = &tc["v1_mic_section_short_salt_hkdf"];
131             let ikm = extract_key_array::<2>(group, "section_short_salt");
132             assert_eq!(
133                 extract_key_array::<12>(group, "short_salt_nonce"),
134                 extended_mic_section_short_salt_nonce::<CryptoProviderImpl>(ikm),
135             );
136         }
137     }
138 
139     Ok(())
140 }
141 
142 // disable unless you want to print out a new set of test vectors
143 #[ignore]
144 #[allow(clippy::panic)]
145 #[test]
gen_test_vectors()146 fn gen_test_vectors() {
147     let mut array = Vec::<serde_json::Value>::new();
148 
149     for i in 0_u32..100 {
150         // build "random" things in a repeatable way so future changes don't
151         // rebuild unrelated things, with some /dev/random thrown in for good measure
152         let test_vector_seed_hkdf = TestVectorHkdf::<CryptoProviderImpl>::new(
153             "NP HKDF test vectors pb4qoNqM9aL/ezSC2FU5EQzu8JJoJ25B+rLqbU5kVN8",
154             &i.to_be_bytes(),
155         );
156 
157         let key_seed: [u8; 32] = test_vector_seed_hkdf.derive_array("key seed");
158         let v0_adv_salt: [u8; 2] = test_vector_seed_hkdf.derive_array("legacy adv salt");
159         let v0_identity_token: [u8; 14] = test_vector_seed_hkdf.derive_array("v0 identity token");
160         let extended_salt_bytes: [u8; 16] =
161             test_vector_seed_hkdf.derive_array("v1 section extended salt");
162         let v1_mic_short_salt: [u8; 2] =
163             test_vector_seed_hkdf.derive_array("v1 mic section short salt");
164         let v1_extended_salt = ExtendedV1Salt::from(extended_salt_bytes);
165 
166         let key_seed_hkdf = NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
167         array
168             .push(json!({
169                 "key_seed_hkdf": {
170                     "key_seed": hex::encode_upper(key_seed),
171                     "v0_ldt_key": hex::encode_upper(key_seed_hkdf.v0_ldt_key().as_concatenated()),
172                     "v0_identity_token_hmac_key":
173                         hex::encode_upper(key_seed_hkdf.v0_identity_token_hmac_key().as_bytes()),
174                     "v0_metadata_nonce": hex::encode_upper(key_seed_hkdf.v0_metadata_nonce()),
175                     "v1_metadata_nonce": hex::encode_upper(key_seed_hkdf.v1_metadata_nonce()),
176                     "v1_mic_short_salt_identity_token_hmac_key": hex::encode_upper(key_seed_hkdf.v1_mic_short_salt_keys().identity_token_hmac_key().as_bytes()),
177                     "v1_mic_short_salt_aes_key": hex::encode_upper(key_seed_hkdf.v1_mic_short_salt_keys().aes_key().as_array()),
178                     "v1_mic_short_salt_mic_hmac_key": hex::encode_upper(key_seed_hkdf.v1_mic_short_salt_keys().mic_hmac_key().as_bytes()),
179                     "v1_mic_extended_salt_identity_token_hmac_key": hex::encode_upper(key_seed_hkdf.v1_mic_extended_salt_keys().identity_token_hmac_key().as_bytes()),
180                     "v1_mic_extended_salt_aes_key": hex::encode_upper(key_seed_hkdf.v1_mic_extended_salt_keys().aes_key().as_array()),
181                     "v1_mic_extended_salt_mic_hmac_key": hex::encode_upper(key_seed_hkdf.v1_mic_extended_salt_keys().mic_hmac_key().as_bytes()),
182                     "v1_signature_identity_token_hmac_key": hex::encode_upper(key_seed_hkdf.v1_signature_keys().identity_token_hmac_key().as_bytes()),
183                     "v1_signature_section_aes_key": hex::encode_upper(key_seed_hkdf.v1_signature_keys().aes_key().as_array()),
184                 },
185                 "v0_adv_salt_hkdf": {
186                     "adv_salt": hex::encode_upper(v0_adv_salt),
187                     "expanded_salt": hex::encode_upper(v0_ldt_expanded_salt::<CryptoProviderImpl>(&v0_adv_salt))
188                 },
189                 "v0_identity_token_hkdf": {
190                     "v0_identity_token": hex::encode_upper(v0_identity_token),
191                     "expanded_key":
192                         hex::encode_upper(v0_metadata_expanded_key::<CryptoProviderImpl>(&v0_identity_token))
193                 },
194                 "v1_section_extended_salt_hkdf": {
195                     "section_extended_salt": hex::encode_upper(v1_extended_salt.bytes()),
196                     // 0-based offsets -> 1-based indexing
197                     "derived_salt_nonce": hex::encode_upper(v1_extended_salt.derive::<16, CryptoProviderImpl>(None).unwrap()),
198                     "derived_salt_first_de": hex::encode_upper(v1_extended_salt.derive::<16, CryptoProviderImpl>(Some(0.into())).unwrap()),
199                     "derived_salt_third_de": hex::encode_upper(v1_extended_salt.derive::<16, CryptoProviderImpl>(Some(2.into())).unwrap()),
200                 },
201                 "v1_mic_section_short_salt_hkdf": {
202                     "section_short_salt": hex::encode_upper(v1_mic_short_salt),
203                     "short_salt_nonce": hex::encode_upper(extended_mic_section_short_salt_nonce::<CryptoProviderImpl>(v1_mic_short_salt)),
204                 }
205             }));
206     }
207 
208     println!("{}", serde_json::ser::to_string_pretty(&array).unwrap());
209     panic!("Don't leave this test enabled. Meanwhile, enjoy the text output above.");
210 }
211