1mod frame;
6mod state;
7
8use crate::boringssl::EcGroupId;
9use crate::ecc;
10use crate::fcg::FiniteCyclicGroup;
11use crate::hmac_utils::{HmacUtils, HmacUtilsImpl};
12
13use anyhow::{Error, bail};
14use fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211;
15pub use frame::{AntiCloggingTokenMsg, CommitMsg, ConfirmMsg};
16use ieee80211::{MacAddr, Ssid};
17use log::warn;
18use mundane::hash::Sha256;
19use num::FromPrimitive;
20use wlan_common::ie::rsn::akm::{self, Akm};
21
22const MAX_RETRIES_PER_EXCHANGE: u16 = 3;
24
25#[derive(Clone, PartialEq, Debug)]
27pub struct Key {
28 pub pmk: Vec<u8>,
29 pub pmkid: Vec<u8>,
30}
31
32#[derive(Debug, Copy, Clone, PartialEq)]
35pub enum PweMethod {
36 Loop = 0,
39
40 Direct = 1,
43}
44
45#[derive(Debug, Clone, PartialEq)]
48pub enum Timeout {
49 Retransmission,
51 KeyExpiration,
53}
54
55#[derive(Debug)]
56pub enum RejectReason {
57 InternalError(Error),
60 AuthFailed,
62 TooManyRetries,
64 KeyExpiration,
66}
67
68impl From<Error> for RejectReason {
69 fn from(e: Error) -> Self {
70 Self::InternalError(e)
71 }
72}
73
74#[derive(Debug)]
75pub struct AuthFrameRx<'a> {
76 pub seq: u16,
77 pub status_code: fidl_ieee80211::StatusCode,
78 pub body: &'a [u8],
79}
80
81#[derive(Debug, Clone, Eq, PartialEq)]
82pub struct AuthFrameTx {
83 pub seq: u16,
84 pub status_code: fidl_ieee80211::StatusCode,
85 pub body: Vec<u8>,
86}
87
88#[derive(Debug)]
91pub enum SaeUpdate {
92 SendFrame(AuthFrameTx),
94 Success(Key),
96 Reject(RejectReason),
98 ResetTimeout(Timeout),
101 CancelTimeout(Timeout),
103}
104
105pub type SaeUpdateSink = Vec<SaeUpdate>;
106
107pub trait SaeHandshake: Send {
121 fn initiate_sae(&mut self, sink: &mut SaeUpdateSink);
124
125 fn handle_commit(&mut self, sink: &mut SaeUpdateSink, commit_msg: &CommitMsg<'_>);
126 fn handle_confirm(&mut self, sink: &mut SaeUpdateSink, confirm_msg: &ConfirmMsg<'_>);
127 fn handle_anti_clogging_token(
128 &mut self,
129 sink: &mut SaeUpdateSink,
130 act_msg: &AntiCloggingTokenMsg<'_>,
131 );
132 fn handle_timeout(&mut self, sink: &mut SaeUpdateSink, timeout: Timeout);
133
134 fn handle_frame(&mut self, sink: &mut SaeUpdateSink, frame: &AuthFrameRx<'_>) {
135 match frame::parse(frame) {
136 Ok(parse) => match parse {
137 frame::ParseSuccess::Commit(commit) => self.handle_commit(sink, &commit),
138 frame::ParseSuccess::Confirm(confirm) => self.handle_confirm(sink, &confirm),
139 frame::ParseSuccess::AntiCloggingToken(act_msg) => {
140 self.handle_anti_clogging_token(sink, &act_msg)
141 }
142 },
143 Err(e) => warn!("Failed to parse SAE auth frame: {}", e),
144 }
145 }
146}
147
148pub fn new_sae_handshake(
150 group_id: u16,
151 akm: Akm,
152 pwe_method: PweMethod,
153 ssid: Ssid,
154 password: Vec<u8>,
155 password_id: Option<Vec<u8>>,
156 mac: MacAddr,
157 peer_mac: MacAddr,
158) -> Result<Box<dyn SaeHandshake>, Error> {
159 match akm.suite_type {
160 akm::SAE | akm::FT_SAE => (),
161 _ => bail!("Cannot construct SAE handshake with AKM {:?}", akm),
162 };
163 let (hmac, group_constructor) = match EcGroupId::from_u16(group_id) {
164 Some(EcGroupId::P256) => {
165 let hmac = Box::new(HmacUtilsImpl::<Sha256>::new());
168 let group_constructor = Box::new(|| {
169 ecc::Group::new(EcGroupId::P256).map(|group| {
170 Box::new(group)
171 as Box<
172 dyn FiniteCyclicGroup<
173 Element = <ecc::Group as FiniteCyclicGroup>::Element,
174 >,
175 >
176 })
177 });
178 (hmac, group_constructor)
179 }
180 _ => bail!("Unsupported SAE group id: {}", group_id),
181 };
182 Ok(Box::new(state::SaeHandshakeImpl::new(
183 group_constructor,
184 SaeParameters {
185 hmac,
186 pwe_method,
187 ssid,
188 password,
189 password_id,
190 sta_a_mac: mac,
191 sta_b_mac: peer_mac,
192 },
193 )?))
194}
195
196pub fn join_sae_handshake(
200 sink: &mut SaeUpdateSink,
201 first_frame: &AuthFrameRx<'_>,
202 akm: Akm,
203 ssid: Ssid,
204 password: Vec<u8>,
205 mac: MacAddr,
206 peer_mac: MacAddr,
207) -> Result<Box<dyn SaeHandshake>, Error> {
208 let parsed_frame = frame::parse(first_frame)?;
209 let pwe_method = match first_frame.status_code {
213 fidl_ieee80211::StatusCode::Success => PweMethod::Loop,
214 fidl_ieee80211::StatusCode::SaeHashToElement => PweMethod::Direct,
215 other => bail!("Unexpected status code {:?} in first frame", other),
216 };
217 match parsed_frame {
218 frame::ParseSuccess::Commit(commit) => {
219 let mut handshake = new_sae_handshake(
220 commit.group_id,
221 akm,
222 pwe_method,
223 ssid,
224 password,
225 None,
226 mac,
227 peer_mac,
228 )?;
229 handshake.handle_commit(sink, &commit);
230 Ok(handshake)
231 }
232 _ => bail!("Recieved incorrect first frame of SAE handshake"),
233 }
234}
235
236pub(crate) struct SaeParameters {
237 pub hmac: Box<dyn HmacUtils + Send>,
238 pub pwe_method: PweMethod,
239 pub ssid: Ssid,
242 pub password: Vec<u8>,
244 pub password_id: Option<Vec<u8>>,
245 pub sta_a_mac: MacAddr,
247 pub sta_b_mac: MacAddr,
248}
249
250#[cfg(test)]
251mod tests {
252 #![allow(unused_variables)] use super::*;
254 use assert_matches::assert_matches;
255 use std::convert::TryFrom;
256 use std::sync::LazyLock;
257 use test_case::test_case;
258 use wlan_common::ie::rsn::akm::{AKM_PSK, AKM_SAE};
259
260 const TEST_SSID: &'static str = "SSID not in 802.11-2016";
262 const TEST_PWD: &'static str = "thisisreallysecret";
263
264 pub(crate) static TEST_STA_A: LazyLock<MacAddr> =
265 LazyLock::new(|| MacAddr::from([0x7b, 0x88, 0x56, 0x20, 0x2d, 0x8d]));
266 pub(crate) static TEST_STA_B: LazyLock<MacAddr> =
267 LazyLock::new(|| MacAddr::from([0xe2, 0x47, 0x1c, 0x0a, 0x5a, 0xcb]));
268
269 #[test]
270 fn bad_akm() {
271 let akm = AKM_PSK;
272 let res = new_sae_handshake(
273 19,
274 akm,
275 PweMethod::Loop,
276 Ssid::try_from(TEST_SSID).unwrap(),
277 Vec::from(TEST_PWD),
278 None, *TEST_STA_A,
280 *TEST_STA_B,
281 );
282 assert!(res.is_err());
283 assert!(
284 format!("{}", res.err().unwrap())
285 .contains("Cannot construct SAE handshake with AKM 00-0F-AC:2")
286 );
287 }
288
289 #[test]
290 fn bad_fcg() {
291 let akm = AKM_SAE;
292 let res = new_sae_handshake(
293 200,
294 akm,
295 PweMethod::Loop,
296 Ssid::try_from(TEST_SSID).unwrap(),
297 Vec::from(TEST_PWD),
298 None, *TEST_STA_A,
300 *TEST_STA_B,
301 );
302 assert!(res.is_err());
303 assert!(format!("{}", res.err().unwrap()).contains("Unsupported SAE group id: 200"));
304 }
305
306 struct TestHandshake {
307 sta1: Box<dyn SaeHandshake>,
308 sta2: Box<dyn SaeHandshake>,
309 }
310
311 #[derive(Clone, Eq, PartialEq, Debug)]
314 struct CommitTx(AuthFrameTx);
315 #[derive(Clone, Eq, PartialEq, Debug)]
316 struct ConfirmTx(AuthFrameTx);
317 struct CommitRx<'a>(AuthFrameRx<'a>);
318 struct ConfirmRx<'a>(AuthFrameRx<'a>);
319
320 fn to_rx(frame: &AuthFrameTx) -> AuthFrameRx<'_> {
321 AuthFrameRx { seq: frame.seq, status_code: frame.status_code, body: &frame.body[..] }
322 }
323
324 impl CommitTx {
325 fn to_rx(&self) -> CommitRx<'_> {
326 CommitRx(to_rx(&self.0))
327 }
328 }
329
330 impl ConfirmTx {
331 fn to_rx(&self) -> ConfirmRx<'_> {
332 ConfirmRx(to_rx(&self.0))
333 }
334 }
335
336 impl<'a> CommitRx<'a> {
337 fn msg(&'a self) -> CommitMsg<'a> {
338 assert_matches!(frame::parse(&self.0),
339 Ok(frame::ParseSuccess::Commit(commit)) => commit)
340 }
341 }
342
343 impl<'a> ConfirmRx<'a> {
344 fn msg(&'a self) -> ConfirmMsg<'a> {
345 assert_matches!(frame::parse(&self.0),
346 Ok(frame::ParseSuccess::Confirm(confirm)) => confirm)
347 }
348 }
349
350 fn expect_commit(sink: &mut Vec<SaeUpdate>) -> CommitTx {
351 let commit = assert_matches!(sink.remove(0), SaeUpdate::SendFrame(frame) => frame);
352 assert_matches!(frame::parse(&to_rx(&commit)), Ok(frame::ParseSuccess::Commit(msg)));
353 CommitTx(commit)
354 }
355
356 fn expect_confirm(sink: &mut Vec<SaeUpdate>) -> ConfirmTx {
357 let confirm = assert_matches!(sink.remove(0), SaeUpdate::SendFrame(frame) => frame);
358 assert_matches!(frame::parse(&to_rx(&confirm)), Ok(frame::ParseSuccess::Confirm(msg)));
359 ConfirmTx(confirm)
360 }
361
362 fn expect_reset_timeout(sink: &mut Vec<SaeUpdate>, timeout: Timeout) {
363 assert_matches!(sink.remove(0), SaeUpdate::ResetTimeout(timeout));
364 }
365
366 fn expect_cancel_timeout(sink: &mut Vec<SaeUpdate>, timeout: Timeout) {
367 assert_matches!(sink.remove(0), SaeUpdate::CancelTimeout(timeout));
368 }
369
370 struct TestHandshakeConfig {
371 pwe_method: PweMethod,
372 }
373
374 impl TestHandshakeConfig {
375 fn direct() -> Self {
376 Self { pwe_method: PweMethod::Direct }
377 }
378
379 fn looping() -> Self {
380 Self { pwe_method: PweMethod::Loop }
381 }
382 }
383
384 impl TestHandshake {
386 fn new(cfg: TestHandshakeConfig) -> Self {
387 let akm = AKM_SAE;
388 let sta1 = new_sae_handshake(
389 19,
390 akm.clone(),
391 cfg.pwe_method,
392 Ssid::try_from(TEST_SSID).unwrap(),
393 Vec::from(TEST_PWD),
394 None, *TEST_STA_A,
396 *TEST_STA_B,
397 )
398 .unwrap();
399 let sta2 = new_sae_handshake(
400 19,
401 akm,
402 cfg.pwe_method,
403 Ssid::try_from(TEST_SSID).unwrap(),
404 Vec::from(TEST_PWD),
405 None, *TEST_STA_B,
407 *TEST_STA_A,
408 )
409 .unwrap();
410 Self { sta1, sta2 }
411 }
412
413 fn sta1_init(&mut self) -> CommitTx {
414 let mut sink = vec![];
415 self.sta1.initiate_sae(&mut sink);
416 assert_eq!(sink.len(), 2);
417 let commit = expect_commit(&mut sink);
418 expect_reset_timeout(&mut sink, Timeout::Retransmission);
419 commit
420 }
421
422 fn sta2_handle_commit(&mut self, commit1: CommitRx<'_>) -> (CommitTx, ConfirmTx) {
423 let mut sink = vec![];
424 self.sta2.handle_commit(&mut sink, &commit1.msg());
425 assert_eq!(sink.len(), 3);
426 let commit2 = expect_commit(&mut sink);
427 let confirm2 = expect_confirm(&mut sink);
428 expect_reset_timeout(&mut sink, Timeout::Retransmission);
429 (commit2, confirm2)
430 }
431
432 fn sta1_handle_commit(&mut self, commit2: CommitRx<'_>) -> ConfirmTx {
433 let mut sink = vec![];
434 self.sta1.handle_commit(&mut sink, &commit2.msg());
435 assert_eq!(sink.len(), 2);
436 let confirm1 = expect_confirm(&mut sink);
437 expect_reset_timeout(&mut sink, Timeout::Retransmission);
438 confirm1
439 }
440
441 fn sta1_handle_confirm(&mut self, confirm2: ConfirmRx<'_>) -> Key {
442 Self::__internal_handle_confirm(&mut self.sta1, confirm2.msg())
443 }
444
445 fn sta2_handle_confirm(&mut self, confirm1: ConfirmRx<'_>) -> Key {
446 Self::__internal_handle_confirm(&mut self.sta2, confirm1.msg())
447 }
448
449 fn __internal_handle_confirm(
450 sta: &mut Box<dyn SaeHandshake>,
451 confirm: ConfirmMsg<'_>,
452 ) -> Key {
453 let mut sink = vec![];
454 sta.handle_confirm(&mut sink, &confirm);
455 assert_eq!(sink.len(), 3);
456 expect_cancel_timeout(&mut sink, Timeout::Retransmission);
457 expect_reset_timeout(&mut sink, Timeout::KeyExpiration);
458 assert_matches!(sink.remove(0), SaeUpdate::Success(key) => key)
459 }
460 }
461
462 #[test_case(TestHandshakeConfig::looping(); "looping")]
463 #[test_case(TestHandshakeConfig::direct(); "direct")]
464 fn sae_handshake_success(cfg: TestHandshakeConfig) {
465 let mut handshake = TestHandshake::new(cfg);
466 let commit1 = handshake.sta1_init();
467 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.to_rx());
468 let confirm1 = handshake.sta1_handle_commit(commit2.to_rx());
469 let key1 = handshake.sta1_handle_confirm(confirm2.to_rx());
470 let key2 = handshake.sta2_handle_confirm(confirm1.to_rx());
471 assert_eq!(key1, key2);
472 }
473
474 #[test]
475 fn password_mismatch() {
476 let akm = AKM_SAE;
477 let sta1 = new_sae_handshake(
478 19,
479 akm.clone(),
480 PweMethod::Loop,
481 Ssid::try_from(TEST_SSID).unwrap(),
482 Vec::from(TEST_PWD),
483 None, *TEST_STA_A,
485 *TEST_STA_B,
486 )
487 .unwrap();
488 let sta2 = new_sae_handshake(
489 19,
490 akm,
491 PweMethod::Loop,
492 Ssid::try_from(TEST_SSID).unwrap(),
493 Vec::from("other_pwd"),
494 None, *TEST_STA_B,
496 *TEST_STA_A,
497 )
498 .unwrap();
499 let mut handshake = TestHandshake { sta1, sta2 };
500
501 let commit1 = handshake.sta1_init();
502 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.to_rx());
503 let confirm1 = handshake.sta1_handle_commit(commit2.to_rx());
504
505 let mut sink1 = vec![];
506 handshake.sta1.handle_confirm(&mut sink1, &confirm2.to_rx().msg());
507 let mut sink2 = vec![];
508 handshake.sta2.handle_confirm(&mut sink2, &confirm1.to_rx().msg());
509 assert_eq!(sink1.len(), 0);
511 assert_eq!(sink2.len(), 0);
512 }
513
514 #[test]
515 fn retry_commit_on_unexpected_confirm() {
516 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
517
518 let commit1 = handshake.sta1_init();
519 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.clone().to_rx());
520 let mut sink = vec![];
521 handshake.sta1.handle_confirm(&mut sink, &confirm2.to_rx().msg());
522 assert_eq!(sink.len(), 2);
523 let commit1_retry = expect_commit(&mut sink);
524 assert_matches!(sink.remove(0), SaeUpdate::ResetTimeout(Timeout::Retransmission));
525
526 assert_eq!(commit1, commit1_retry);
528 }
529
530 #[test]
531 fn retry_commit_on_anti_clogging_token() {
532 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
533
534 let commit1 = handshake.sta1_init();
535
536 let mut sink = vec![];
538 let anti_clogging_token = "anticloggingtokentext";
539 let act_msg = AntiCloggingTokenMsg {
540 group_id: 19,
541 anti_clogging_token: anti_clogging_token.as_bytes(),
542 };
543 handshake.sta1.handle_anti_clogging_token(&mut sink, &act_msg);
544 let commit1_retry = expect_commit(&mut sink);
545 assert_eq!(
546 commit1_retry.clone().to_rx().msg().anti_clogging_token,
547 Some(anti_clogging_token.as_bytes())
548 );
549
550 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1_retry.to_rx());
552 let confirm1 = handshake.sta1_handle_commit(commit2.to_rx());
553 let key1 = handshake.sta1_handle_confirm(confirm2.to_rx());
554 let key2 = handshake.sta2_handle_confirm(confirm1.to_rx());
555 assert_eq!(key1, key2);
556 }
557
558 #[test]
559 fn ignore_wrong_confirm() {
560 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
561
562 let commit1 = handshake.sta1_init();
563 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.to_rx());
564 let confirm1 = handshake.sta1_handle_commit(commit2.to_rx());
565
566 let mut sink = vec![];
567 let confirm2_wrong = ConfirmTx(frame::write_confirm(1, &[1; 32][..]));
568 handshake.sta1.handle_confirm(&mut sink, &confirm2_wrong.to_rx().msg());
569 assert_eq!(sink.len(), 0); handshake.sta1_handle_confirm(confirm2.to_rx());
573 }
574
575 #[test]
576 fn handle_resent_commit() {
577 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
578 let commit1 = handshake.sta1_init();
579 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.clone().to_rx());
580 let (commit2_retry, confirm2_retry) = handshake.sta2_handle_commit(commit1.to_rx());
581
582 assert_eq!(commit2, commit2_retry);
585 assert_eq!(confirm2.to_rx().msg().send_confirm, 1);
586 assert_eq!(confirm2_retry.to_rx().msg().send_confirm, 2);
587 assert!(confirm2.to_rx().msg().confirm != confirm2_retry.to_rx().msg().confirm);
588
589 let confirm1 = handshake.sta1_handle_commit(commit2_retry.to_rx());
591 let key1 = handshake.sta1_handle_confirm(confirm2_retry.to_rx());
592 let key2 = handshake.sta2_handle_confirm(confirm1.to_rx());
593 assert_eq!(key1, key2);
594 }
595
596 #[test]
597 fn completed_handshake_handles_resent_confirm() {
598 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
599 let commit1 = handshake.sta1_init();
600 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.clone().to_rx());
601 let (commit2_retry, confirm2_retry) = handshake.sta2_handle_commit(commit1.to_rx());
602 let confirm1 = handshake.sta1_handle_commit(commit2.to_rx());
604 let key1 = handshake.sta1_handle_confirm(confirm2.clone().to_rx());
605
606 let mut sink = vec![];
608 handshake.sta1.handle_confirm(&mut sink, &confirm2_retry.to_rx().msg());
609 assert_eq!(sink.len(), 1);
610 let confirm1_retry = expect_confirm(&mut sink);
611 assert!(confirm1.to_rx().msg().confirm != confirm1_retry.to_rx().msg().confirm);
612 assert_eq!(confirm1_retry.to_rx().msg().send_confirm, u16::max_value());
613
614 let key2 = handshake.sta2_handle_confirm(confirm1_retry.to_rx());
616 assert_eq!(key1, key2);
617
618 handshake.sta1.handle_confirm(&mut sink, &confirm2_retry.to_rx().msg());
620 assert!(sink.is_empty());
621 handshake.sta1.handle_confirm(&mut sink, &confirm2.to_rx().msg());
622 assert!(sink.is_empty());
623
624 let confirm2_wrong = ConfirmMsg { send_confirm: 10, confirm: &[0xab; 32][..] };
626 handshake.sta1.handle_confirm(&mut sink, &confirm2_wrong);
627 assert!(sink.is_empty());
628 }
629
630 #[test]
631 fn completed_handshake_ignores_commit() {
632 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
633 let commit1 = handshake.sta1_init();
634 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.to_rx());
635 handshake.sta1_handle_commit(commit2.to_rx());
636 handshake.sta1_handle_confirm(confirm2.clone().to_rx());
637
638 let mut sink = vec![];
640 handshake.sta1.handle_confirm(&mut sink, &confirm2.to_rx().msg());
641 assert!(sink.is_empty());
642 }
643
644 #[test]
645 fn bad_first_commit_rejects_auth() {
646 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
647 let commit1_wrong = CommitMsg {
648 group_id: 19,
649 scalar: &[0xab; 32][..],
650 element: &[0xcd; 64][..],
651 anti_clogging_token: None,
652 };
653
654 let mut sink = vec![];
655 handshake.sta1.handle_commit(&mut sink, &commit1_wrong);
656 assert_eq!(sink.len(), 1);
657 assert_matches!(sink.remove(0), SaeUpdate::Reject(RejectReason::AuthFailed));
658 }
659
660 #[test]
661 fn bad_second_commit_ignored() {
662 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
663 let commit1 = handshake.sta1_init();
664 let (_commit1, _confirm2) = handshake.sta2_handle_commit(commit1.to_rx());
665 let commit2_wrong = CommitMsg {
666 group_id: 19,
667 scalar: &[0xab; 32][..],
668 element: &[0xcd; 64][..],
669 anti_clogging_token: None,
670 };
671 let mut sink = vec![];
672 handshake.sta1.handle_commit(&mut sink, &commit2_wrong);
673 assert_eq!(sink.len(), 0);
674 }
675
676 #[test]
677 fn reflected_commit_discarded() {
678 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
679 let commit1 = handshake.sta1_init();
680
681 let mut sink = vec![];
682 handshake.sta1.handle_commit(&mut sink, &commit1.to_rx().msg());
683 assert_eq!(sink.len(), 1);
684 assert_matches!(sink.remove(0), SaeUpdate::ResetTimeout(Timeout::Retransmission));
685 }
686
687 #[test]
688 fn maximum_commit_retries() {
689 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
690 let commit1 = handshake.sta1_init();
691 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.clone().to_rx());
692
693 for i in 0..MAX_RETRIES_PER_EXCHANGE {
695 let (commit2_retry, confirm2_retry) =
696 handshake.sta2_handle_commit(commit1.clone().to_rx());
697 assert_eq!(commit2, commit2_retry);
698 assert_eq!(confirm2_retry.to_rx().msg().send_confirm, i + 2);
699 }
700
701 let mut sink = vec![];
703 handshake.sta2.handle_commit(&mut sink, &commit1.to_rx().msg());
704 assert_eq!(sink.len(), 1);
705 assert_matches!(sink.remove(0), SaeUpdate::Reject(RejectReason::TooManyRetries));
706 }
707
708 #[test]
709 fn completed_exchange_fails_after_retries() {
710 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
711 let commit1 = handshake.sta1_init();
712 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.clone().to_rx());
713
714 for i in 0..(MAX_RETRIES_PER_EXCHANGE - 1) {
717 let (commit2_retry, confirm2_retry) =
718 handshake.sta2_handle_commit(commit1.clone().to_rx());
719 assert_eq!(commit2, commit2_retry);
720 assert_eq!(confirm2_retry.to_rx().msg().send_confirm, i + 2);
721 }
722
723 let mut sink = vec![];
724
725 let confirm1_sc1 = handshake.sta1_handle_commit(commit2.clone().to_rx());
727 handshake.sta1.handle_commit(&mut sink, &commit2.to_rx().msg());
728 assert_eq!(sink.len(), 3);
729 sink.remove(0);
730 let confirm1_sc2 = expect_confirm(&mut sink);
731 sink.clear();
732 let confirm1_invalid = ConfirmMsg { send_confirm: 3, confirm: &[0xab; 32][..] };
733
734 handshake.sta2_handle_confirm(confirm1_sc1.clone().to_rx());
737
738 handshake.sta2.handle_commit(&mut sink, &commit1.to_rx().msg());
745 handshake.sta2.handle_commit(&mut sink, &commit1.to_rx().msg());
746 assert_eq!(sink.len(), 0);
747
748 handshake.sta2.handle_confirm(&mut sink, &confirm1_invalid);
750 handshake.sta2.handle_confirm(&mut sink, &confirm1_invalid);
751 assert_eq!(sink.len(), 0);
752
753 handshake.sta2.handle_confirm(&mut sink, &confirm1_sc1.to_rx().msg());
755 handshake.sta2.handle_confirm(&mut sink, &confirm1_sc1.to_rx().msg());
756 assert_eq!(sink.len(), 0);
757
758 handshake.sta2.handle_confirm(&mut sink, &confirm1_sc2.to_rx().msg());
760 assert_eq!(sink.len(), 1);
761 expect_confirm(&mut sink);
762 handshake.sta2.handle_confirm(&mut sink, &confirm1_sc2.to_rx().msg());
763 assert_eq!(sink.len(), 1);
764 assert_matches!(sink.remove(0), SaeUpdate::Reject(RejectReason::TooManyRetries));
765 }
766
767 #[test]
768 fn resend_commit_after_retransmission_timeout() {
769 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
770 let commit1 = handshake.sta1_init();
771
772 let mut sink = vec![];
773 handshake.sta1.handle_timeout(&mut sink, Timeout::Retransmission);
774 let commit1_retry = expect_commit(&mut sink);
775 expect_reset_timeout(&mut sink, Timeout::Retransmission);
776 assert_eq!(commit1, commit1_retry);
777 }
778
779 #[test]
780 fn resend_confirm_after_retransmission_timeout() {
781 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
782 let commit1 = handshake.sta1_init();
783 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.clone().to_rx());
784
785 let mut sink = vec![];
786 handshake.sta2.handle_timeout(&mut sink, Timeout::Retransmission);
787 let confirm2_retry = expect_confirm(&mut sink);
789 expect_reset_timeout(&mut sink, Timeout::Retransmission);
790 assert_eq!(
791 confirm2.to_rx().msg().send_confirm + 1,
792 confirm2_retry.to_rx().msg().send_confirm
793 );
794 }
795
796 #[test]
797 fn abort_commit_after_too_many_timeouts() {
798 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
799 let commit1 = handshake.sta1_init();
800
801 let mut sink = vec![];
802 for i in 0..MAX_RETRIES_PER_EXCHANGE {
803 handshake.sta1.handle_timeout(&mut sink, Timeout::Retransmission);
804 let commit1_retry = expect_commit(&mut sink);
805 expect_reset_timeout(&mut sink, Timeout::Retransmission);
806 assert_eq!(commit1, commit1_retry);
807 }
808
809 handshake.sta1.handle_timeout(&mut sink, Timeout::Retransmission);
811 assert_eq!(sink.len(), 1);
812 assert_matches!(sink.remove(0), SaeUpdate::Reject(RejectReason::TooManyRetries));
813 }
814
815 #[test]
816 fn abort_confirm_after_too_many_timeouts() {
817 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
818 let commit1 = handshake.sta1_init();
819 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.clone().to_rx());
820
821 let mut sink = vec![];
822 for i in 0..MAX_RETRIES_PER_EXCHANGE {
823 handshake.sta2.handle_timeout(&mut sink, Timeout::Retransmission);
824 let confirm2_retry = expect_confirm(&mut sink);
826 expect_reset_timeout(&mut sink, Timeout::Retransmission);
827 assert_eq!(
828 confirm2.to_rx().msg().send_confirm + i + 1,
829 confirm2_retry.to_rx().msg().send_confirm
830 );
831 }
832
833 handshake.sta2.handle_timeout(&mut sink, Timeout::Retransmission);
834 assert_eq!(sink.len(), 1);
835 assert_matches!(sink.remove(0), SaeUpdate::Reject(RejectReason::TooManyRetries));
836 }
837
838 #[test]
839 fn ignore_unexpected_retransmit_timeout() {
840 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
841 let mut sink = vec![];
842 handshake.sta1.handle_timeout(&mut sink, Timeout::Retransmission);
844 assert!(sink.is_empty());
845
846 let commit1 = handshake.sta1_init();
847 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.to_rx());
848 let confirm1 = handshake.sta1_handle_commit(commit2.to_rx());
849 let key1 = handshake.sta1_handle_confirm(confirm2.to_rx());
850
851 handshake.sta1.handle_timeout(&mut sink, Timeout::Retransmission);
853 assert!(sink.is_empty());
854 }
855
856 #[test]
857 fn fail_on_early_key_expiration() {
858 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
859 handshake.sta1_init();
860
861 let mut sink = vec![];
863 handshake.sta1.handle_timeout(&mut sink, Timeout::KeyExpiration);
864 assert_eq!(sink.len(), 1);
865 assert_matches!(sink.remove(0), SaeUpdate::Reject(RejectReason::InternalError(_)));
866 }
867
868 #[test]
869 fn key_expiration_timeout() {
870 let mut handshake = TestHandshake::new(TestHandshakeConfig::looping());
871 let commit1 = handshake.sta1_init();
873 let (commit2, confirm2) = handshake.sta2_handle_commit(commit1.to_rx());
874 let confirm1 = handshake.sta1_handle_commit(commit2.to_rx());
875 let key1 = handshake.sta1_handle_confirm(confirm2.to_rx());
876
877 let mut sink = vec![];
878 handshake.sta1.handle_timeout(&mut sink, Timeout::KeyExpiration);
879 assert_eq!(sink.len(), 1);
880 assert_matches!(sink.remove(0), SaeUpdate::Reject(RejectReason::KeyExpiration));
881 }
882}