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 ////////////////////////////////////////////////////////////////////////////////
16
17 //! Tests for BoringSSL-based implementations of AuthGraph traits.
18 use alloc::rc::Rc;
19 use authgraph_core::{
20 key::{
21 CertChain, EcSignKey, EcVerifyKey, Identity, EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION,
22 IDENTITY_VERSION,
23 },
24 keyexchange,
25 };
26 use authgraph_core_test as ag_test;
27 use core::cell::RefCell;
28 use coset::{cbor::value::Value, iana, CborOrdering, CborSerializable, Label};
29
30 #[test]
test_rng()31 fn test_rng() {
32 let mut rng = crate::BoringRng;
33 ag_test::test_rng(&mut rng);
34 }
35
36 #[test]
test_sha256()37 fn test_sha256() {
38 ag_test::test_sha256(&crate::BoringSha256);
39 }
40
41 #[test]
test_hmac()42 fn test_hmac() {
43 ag_test::test_hmac(&crate::BoringHmac);
44 }
45
46 #[test]
test_hkdf()47 fn test_hkdf() {
48 ag_test::test_hkdf(&crate::BoringHkdf);
49 }
50
51 #[test]
test_aes_gcm_keygen()52 fn test_aes_gcm_keygen() {
53 ag_test::test_aes_gcm_keygen(&crate::BoringAes, &mut crate::BoringRng);
54 }
55
56 #[test]
test_aes_gcm_roundtrip()57 fn test_aes_gcm_roundtrip() {
58 ag_test::test_aes_gcm_roundtrip(&crate::BoringAes, &mut crate::BoringRng);
59 }
60
61 #[test]
test_aes_gcm()62 fn test_aes_gcm() {
63 ag_test::test_aes_gcm(&crate::BoringAes);
64 }
65
66 #[test]
test_ecdh()67 fn test_ecdh() {
68 ag_test::test_ecdh(&crate::BoringEcDh);
69 }
70
71 #[test]
test_ecdsa()72 fn test_ecdsa() {
73 ag_test::test_ecdsa(&crate::BoringEcDsa);
74 }
75
76 #[test]
test_ed25519_round_trip()77 fn test_ed25519_round_trip() {
78 ag_test::test_ed25519_round_trip(&crate::BoringEcDsa);
79 }
80
81 #[test]
test_p256_round_trip()82 fn test_p256_round_trip() {
83 ag_test::test_p256_round_trip(&crate::BoringEcDsa);
84 }
85
86 #[test]
test_p384_round_trip()87 fn test_p384_round_trip() {
88 ag_test::test_p384_round_trip(&crate::BoringEcDsa);
89 }
90
91 #[test]
test_key_exchange_protocol()92 fn test_key_exchange_protocol() {
93 let mut source = keyexchange::AuthGraphParticipant::new(
94 crate::crypto_trait_impls(),
95 Rc::new(RefCell::new(crate::test_device::AgDevice::default())),
96 keyexchange::MAX_OPENED_SESSIONS,
97 )
98 .unwrap();
99 ag_test::test_key_exchange_create(&mut source);
100 let mut sink = keyexchange::AuthGraphParticipant::new(
101 crate::crypto_trait_impls(),
102 Rc::new(RefCell::new(crate::test_device::AgDevice::default())),
103 keyexchange::MAX_OPENED_SESSIONS,
104 )
105 .unwrap();
106 ag_test::test_key_exchange_init(&mut source, &mut sink);
107 ag_test::test_key_exchange_finish(&mut source, &mut sink);
108 ag_test::test_key_exchange_auth_complete(&mut source, &mut sink);
109 }
110
111 #[test]
test_ke_with_newer_source()112 fn test_ke_with_newer_source() {
113 let source_device = crate::test_device::AgDevice::default();
114 source_device.set_version(2);
115
116 let sink_device = crate::test_device::AgDevice::default();
117 sink_device.set_version(1);
118
119 let mut source = keyexchange::AuthGraphParticipant::new(
120 crate::crypto_trait_impls(),
121 Rc::new(RefCell::new(source_device)),
122 keyexchange::MAX_OPENED_SESSIONS,
123 )
124 .unwrap();
125
126 let mut sink = keyexchange::AuthGraphParticipant::new(
127 crate::crypto_trait_impls(),
128 Rc::new(RefCell::new(sink_device)),
129 keyexchange::MAX_OPENED_SESSIONS,
130 )
131 .unwrap();
132
133 ag_test::test_ke_with_newer_source(&mut source, &mut sink);
134 }
135
136 #[test]
test_ke_with_newer_sink()137 fn test_ke_with_newer_sink() {
138 let source_device = crate::test_device::AgDevice::default();
139 source_device.set_version(1);
140
141 let sink_device = crate::test_device::AgDevice::default();
142 sink_device.set_version(2);
143
144 let mut source = keyexchange::AuthGraphParticipant::new(
145 crate::crypto_trait_impls(),
146 Rc::new(RefCell::new(source_device)),
147 keyexchange::MAX_OPENED_SESSIONS,
148 )
149 .unwrap();
150
151 let mut sink = keyexchange::AuthGraphParticipant::new(
152 crate::crypto_trait_impls(),
153 Rc::new(RefCell::new(sink_device)),
154 keyexchange::MAX_OPENED_SESSIONS,
155 )
156 .unwrap();
157
158 ag_test::test_ke_with_newer_sink(&mut source, &mut sink);
159 }
160
161 #[test]
test_ke_for_protocol_downgrade()162 fn test_ke_for_protocol_downgrade() {
163 let source_device = crate::test_device::AgDevice::default();
164 source_device.set_version(2);
165
166 let sink_device = crate::test_device::AgDevice::default();
167 sink_device.set_version(2);
168
169 let mut source = keyexchange::AuthGraphParticipant::new(
170 crate::crypto_trait_impls(),
171 Rc::new(RefCell::new(source_device)),
172 keyexchange::MAX_OPENED_SESSIONS,
173 )
174 .unwrap();
175
176 let mut sink = keyexchange::AuthGraphParticipant::new(
177 crate::crypto_trait_impls(),
178 Rc::new(RefCell::new(sink_device)),
179 keyexchange::MAX_OPENED_SESSIONS,
180 )
181 .unwrap();
182
183 ag_test::test_ke_for_version_downgrade(&mut source, &mut sink);
184 }
185
186 #[test]
test_ke_for_replay()187 fn test_ke_for_replay() {
188 let mut source = keyexchange::AuthGraphParticipant::new(
189 crate::crypto_trait_impls(),
190 Rc::new(RefCell::new(crate::test_device::AgDevice::default())),
191 keyexchange::MAX_OPENED_SESSIONS,
192 )
193 .unwrap();
194 let mut sink = keyexchange::AuthGraphParticipant::new(
195 crate::crypto_trait_impls(),
196 Rc::new(RefCell::new(crate::test_device::AgDevice::default())),
197 keyexchange::MAX_OPENED_SESSIONS,
198 )
199 .unwrap();
200 ag_test::test_ke_for_replay(&mut source, &mut sink);
201 }
202
203 #[test]
test_identity_validation()204 fn test_identity_validation() {
205 ag_test::validate_identity(&crate::BoringEcDsa);
206 }
207
208 #[test]
test_example_identity_validate()209 fn test_example_identity_validate() {
210 ag_test::test_example_identity_validate(&crate::BoringEcDsa);
211 }
212
213 #[test]
test_key_exchange_with_non_empty_dice_chains()214 fn test_key_exchange_with_non_empty_dice_chains() {
215 // Both parties have identities containing a DICE certificate chains of non-zero length.
216 let source_device = crate::test_device::AgDevice::default();
217 let (source_pvt_sign_key, source_cbor_identity) = ag_test::create_identity(4).unwrap();
218 let source_identity = Identity::from_slice(&source_cbor_identity).unwrap();
219 source_device.set_identity((source_pvt_sign_key, source_identity), iana::Algorithm::EdDSA);
220 let mut source = keyexchange::AuthGraphParticipant::new(
221 crate::crypto_trait_impls(),
222 Rc::new(RefCell::new(source_device)),
223 keyexchange::MAX_OPENED_SESSIONS,
224 )
225 .unwrap();
226 ag_test::test_key_exchange_create(&mut source);
227 let sink_device = crate::test_device::AgDevice::default();
228 let (sink_pvt_sign_key, sink_cbor_identity) = ag_test::create_identity(5).unwrap();
229 let sink_identity = Identity::from_slice(&sink_cbor_identity).unwrap();
230 sink_device.set_identity((sink_pvt_sign_key, sink_identity), iana::Algorithm::EdDSA);
231 let mut sink = keyexchange::AuthGraphParticipant::new(
232 crate::crypto_trait_impls(),
233 Rc::new(RefCell::new(sink_device)),
234 keyexchange::MAX_OPENED_SESSIONS,
235 )
236 .unwrap();
237 ag_test::test_key_exchange_init(&mut source, &mut sink);
238 ag_test::test_key_exchange_finish(&mut source, &mut sink);
239 ag_test::test_key_exchange_auth_complete(&mut source, &mut sink);
240 }
241
242 #[test]
test_key_exchange_with_mixed_dice_chains()243 fn test_key_exchange_with_mixed_dice_chains() {
244 // One party has an identity with an empty DICE certificate chain and the other party has an
245 // identity with DICE certificate chainss of non-zero length.
246 let source_device = crate::test_device::AgDevice::default();
247 let (source_pvt_sign_key, source_cbor_identity) = ag_test::create_identity(0).unwrap();
248 let source_identity = Identity::from_slice(&source_cbor_identity).unwrap();
249 source_device.set_identity((source_pvt_sign_key, source_identity), iana::Algorithm::EdDSA);
250 let mut source = keyexchange::AuthGraphParticipant::new(
251 crate::crypto_trait_impls(),
252 Rc::new(RefCell::new(source_device)),
253 keyexchange::MAX_OPENED_SESSIONS,
254 )
255 .unwrap();
256 ag_test::test_key_exchange_create(&mut source);
257 let sink_device = crate::test_device::AgDevice::default();
258 let (sink_pvt_sign_key, sink_cbor_identity) = ag_test::create_identity(5).unwrap();
259 let sink_identity = Identity::from_slice(&sink_cbor_identity).unwrap();
260 sink_device.set_identity((sink_pvt_sign_key, sink_identity), iana::Algorithm::EdDSA);
261 let mut sink = keyexchange::AuthGraphParticipant::new(
262 crate::crypto_trait_impls(),
263 Rc::new(RefCell::new(sink_device)),
264 keyexchange::MAX_OPENED_SESSIONS,
265 )
266 .unwrap();
267 ag_test::test_key_exchange_init(&mut source, &mut sink);
268 ag_test::test_key_exchange_finish(&mut source, &mut sink);
269 ag_test::test_key_exchange_auth_complete(&mut source, &mut sink);
270 }
271
272 #[test]
273 #[should_panic(expected = "root key is not in the required canonical form")]
test_get_identity_with_root_key_in_incorrect_canonical_form()274 fn test_get_identity_with_root_key_in_incorrect_canonical_form() {
275 // Check that the `Identity` returned from `get_identity` in the `Device` trait fails the
276 // validation, given that the root key is in incorrect canonical form.
277 let test_device = crate::test_device::AgDevice::default();
278 let (priv_key, mut pub_key) = crate::ec::create_p256_key_pair(iana::Algorithm::ES256).unwrap();
279 let mut test_params = Vec::<(Label, Value)>::new();
280 for param in pub_key.params {
281 test_params.push(param);
282 }
283 test_params.push((Label::Int(23), Value::Text("test1".to_string())));
284 test_params.push((Label::Int(1234), Value::Text("test2".to_string())));
285 pub_key.params = test_params;
286 pub_key.canonicalize(CborOrdering::LengthFirstLexicographic);
287 let identity = Identity {
288 version: IDENTITY_VERSION,
289 cert_chain: CertChain {
290 version: EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION,
291 root_key: EcVerifyKey::P256(pub_key),
292 dice_cert_chain: None,
293 },
294 policy: None,
295 };
296 test_device.set_identity((EcSignKey::P256(priv_key), identity), iana::Algorithm::ES256);
297 ag_test::test_get_identity(&test_device, &crate::BoringEcDsa);
298 }
299
300 #[test]
test_get_identity_with_root_key_in_correct_canonical_form()301 fn test_get_identity_with_root_key_in_correct_canonical_form() {
302 // Check that the `Identity` returned from `get_identity` in the `Device` trait passes the
303 // validation, given that the root key is in correct canonical form.
304 let test_device = crate::test_device::AgDevice::default();
305 let (priv_key, mut pub_key) = crate::ec::create_p256_key_pair(iana::Algorithm::ES256).unwrap();
306 let mut test_params = Vec::<(Label, Value)>::new();
307 for param in pub_key.params {
308 test_params.push(param);
309 }
310 test_params.push((Label::Int(23), Value::Text("test1".to_string())));
311 test_params.push((Label::Int(1234), Value::Text("test2".to_string())));
312 pub_key.params = test_params;
313 pub_key.canonicalize(CborOrdering::Lexicographic);
314 let identity = Identity {
315 version: IDENTITY_VERSION,
316 cert_chain: CertChain {
317 version: EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION,
318 root_key: EcVerifyKey::P256(pub_key),
319 dice_cert_chain: None,
320 },
321 policy: None,
322 };
323 test_device.set_identity((EcSignKey::P256(priv_key), identity), iana::Algorithm::ES256);
324 ag_test::test_get_identity(&test_device, &crate::BoringEcDsa);
325 }
326