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