Skip to main content

wlan_rsn/rsna/
esssa.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::key::exchange::handshake::fourway::Fourway;
6use crate::key::exchange::handshake::group_key::GroupKey;
7use crate::key::exchange::{self, Key};
8use crate::key::gtk::Gtk;
9use crate::key::igtk::Igtk;
10use crate::key::pmk::Pmk;
11use crate::key::ptk::Ptk;
12use crate::rsna::{
13    Dot11VerifiedKeyFrame, NegotiatedProtection, Role, SecAssocStatus, SecAssocUpdate, UpdateSink,
14};
15use crate::{Error, ProtectionInfo};
16use fidl_fuchsia_wlan_mlme::EapolResultCode;
17use log::{error, info};
18use std::collections::HashSet;
19use wlan_statemachine::StateMachine;
20
21use zerocopy::SplitByteSlice;
22
23const MAX_KEY_FRAME_RETRIES: u32 = 3;
24
25#[derive(Debug)]
26enum Pmksa {
27    Initialized { pmk: Option<Pmk> },
28    Established { pmk: Pmk },
29}
30
31impl Pmksa {
32    fn reset(self) -> Self {
33        match self {
34            Pmksa::Established { pmk } | Pmksa::Initialized { pmk: Some(pmk) } => {
35                Pmksa::Initialized { pmk: Some(pmk) }
36            }
37            _ => Pmksa::Initialized { pmk: None },
38        }
39    }
40}
41
42#[derive(Debug, PartialEq)]
43enum Ptksa {
44    Uninitialized { cfg: exchange::Config },
45    Initialized { method: exchange::Method },
46    Established { method: exchange::Method, ptk: Ptk },
47}
48
49impl Ptksa {
50    fn initialize(self, pmk: Pmk) -> Self {
51        match self {
52            Ptksa::Uninitialized { cfg } => match cfg {
53                exchange::Config::FourWayHandshake(mut method_cfg) => {
54                    if method_cfg.pmksa_caching_supported {
55                        if let Some(ref pmkid) = pmk.pmkid {
56                            if let ProtectionInfo::Rsne(ref mut s_rsne) = method_cfg.s_protection {
57                                s_rsne.pmkids = vec![bytes::Bytes::copy_from_slice(pmkid)];
58                            }
59                        }
60                    }
61                    match Fourway::new(method_cfg.clone(), pmk.pmk) {
62                        Err(e) => {
63                            error!("error creating 4-Way Handshake from config: {}", e);
64                            Ptksa::Uninitialized {
65                                cfg: exchange::Config::FourWayHandshake(method_cfg),
66                            }
67                        }
68                        Ok(method) => Ptksa::Initialized {
69                            method: exchange::Method::FourWayHandshake(Box::new(method)),
70                        },
71                    }
72                }
73                _ => {
74                    panic!("unsupported method for PTKSA: {:?}", cfg);
75                }
76            },
77            other => other,
78        }
79    }
80
81    fn reset(self) -> Self {
82        match self {
83            Ptksa::Uninitialized { cfg } => Ptksa::Uninitialized { cfg },
84            Ptksa::Initialized { method } | Ptksa::Established { method, .. } => {
85                Ptksa::Uninitialized { cfg: method.destroy() }
86            }
87        }
88    }
89}
90
91/// A GTKSA is composed of a GTK and a key exchange method.
92/// While a key is required for successfully establishing a GTKSA, the key exchange method is
93/// optional as it's used only for re-keying the GTK.
94#[derive(Debug, PartialEq)]
95enum Gtksa {
96    Uninitialized {
97        cfg: Option<exchange::Config>,
98    },
99    Initialized {
100        method: Option<exchange::Method>,
101    },
102    Established {
103        method: Option<exchange::Method>,
104        // A key history of previously installed group keys.
105        // Keys which have been previously installed must never be re-installed.
106        installed_gtks: HashSet<Gtk>,
107    },
108}
109
110impl Gtksa {
111    fn initialize(self, kck: &[u8], kek: &[u8]) -> Self {
112        match self {
113            Gtksa::Uninitialized { cfg } => match cfg {
114                None => Gtksa::Initialized { method: None },
115                Some(exchange::Config::GroupKeyHandshake(method_cfg)) => {
116                    match GroupKey::new(method_cfg.clone(), kck, kek) {
117                        Err(e) => {
118                            error!("error creating Group KeyHandshake from config: {}", e);
119                            Gtksa::Uninitialized {
120                                cfg: Some(exchange::Config::GroupKeyHandshake(method_cfg)),
121                            }
122                        }
123                        Ok(method) => Gtksa::Initialized {
124                            method: Some(exchange::Method::GroupKeyHandshake(method)),
125                        },
126                    }
127                }
128                _ => {
129                    panic!("unsupported method for GTKSA: {:?}", cfg);
130                }
131            },
132            other => other,
133        }
134    }
135
136    fn reset(self) -> Self {
137        match self {
138            Gtksa::Uninitialized { cfg } => Gtksa::Uninitialized { cfg },
139            Gtksa::Initialized { method } | Gtksa::Established { method, .. } => {
140                Gtksa::Uninitialized { cfg: method.map(|m| m.destroy()) }
141            }
142        }
143    }
144}
145
146/// Igtksa is super simple because there's currently no method for populating it other than an adjacent Gtksa.
147#[derive(Debug)]
148enum Igtksa {
149    Uninitialized,
150    Established { installed_igtks: HashSet<Igtk> },
151}
152
153impl Igtksa {
154    fn reset(self) -> Self {
155        Igtksa::Uninitialized
156    }
157}
158
159/// An ESS Security Association is composed of three security associations, namely, PMKSA, PTKSA and
160/// GTKSA. The individual security associations have dependencies on each other. For example, the
161/// PMKSA must be established first as it yields the PMK used in the PTK and GTK key hierarchy.
162/// Depending on the selected PTKSA, it can yield not just the PTK but also GTK, and thus leaving
163/// the GTKSA's key exchange method only useful for re-keying.
164///
165/// Each association should spawn one ESSSA instance only.
166/// The security association correctly tracks and handles replays for robustness and
167/// prevents key re-installation to mitigate attacks such as described in KRACK.
168#[derive(Debug)]
169pub(crate) struct EssSa {
170    // Determines the device's role (Supplicant or Authenticator).
171    role: Role,
172    // The protection used for this association.
173    pub negotiated_protection: NegotiatedProtection,
174    // The last valid key replay counter. Messages with a key replay counter lower than this counter
175    // value will be dropped.
176    key_replay_counter: u64,
177    // A retry counter and key frame to resend if a timeout is received while waiting for a response.
178    last_key_frame_buf: Option<(u32, eapol::KeyFrameBuf)>,
179    // Updates to send after we receive an eapol send confirmation. This will contain an empty update
180    // sink if we're awaiting a confirm but do not have any subsequent updates to send.
181    updates_awaiting_confirm: Option<UpdateSink>,
182
183    // Individual Security Associations.
184    pmksa: StateMachine<Pmksa>,
185    ptksa: StateMachine<Ptksa>,
186    gtksa: StateMachine<Gtksa>,
187    igtksa: StateMachine<Igtksa>,
188}
189
190// IEEE Std 802.11-2016, 12.6.1.3.2
191impl EssSa {
192    pub fn new(
193        role: Role,
194        pmk: Option<Pmk>,
195        negotiated_protection: NegotiatedProtection,
196        ptk_exch_cfg: exchange::Config,
197        gtk_exch_cfg: Option<exchange::Config>,
198    ) -> Result<EssSa, anyhow::Error> {
199        info!("spawned ESSSA for: {:?}", role);
200
201        let rsna = EssSa {
202            role,
203            negotiated_protection,
204            key_replay_counter: 0,
205            last_key_frame_buf: None,
206            updates_awaiting_confirm: None,
207            pmksa: StateMachine::new(Pmksa::Initialized { pmk }),
208            ptksa: StateMachine::new(Ptksa::Uninitialized { cfg: ptk_exch_cfg }),
209            gtksa: StateMachine::new(Gtksa::Uninitialized { cfg: gtk_exch_cfg }),
210            igtksa: StateMachine::new(Igtksa::Uninitialized),
211        };
212        Ok(rsna)
213    }
214
215    #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
216    /// This function will not succeed unless called on a new Esssa or one that was reset.
217    pub fn initiate(&mut self, update_sink: &mut UpdateSink) -> Result<(), Error> {
218        // TODO(https://fxbug.dev/42148516): Ptksa starts in Initialized when the EssSa
219        // computes the PMKSA from a PSK. When an EssSa is not initialized with a PSK,
220        // Ptksa start in Uninitialized since the PMKSA cannot be computed. For example,
221        // when using SAE for authentication, Ptksa starts in Uninitialized.
222        match (self.ptksa.as_ref(), self.gtksa.as_ref(), self.igtksa.as_ref()) {
223            (Ptksa::Uninitialized { .. }, Gtksa::Uninitialized { .. }, Igtksa::Uninitialized) => (),
224
225            (Ptksa::Initialized { .. }, Gtksa::Uninitialized { .. }, Igtksa::Uninitialized) => (),
226            _ => return Err(Error::UnexpectedEsssaInitiation),
227        };
228        info!("establishing ESSSA...");
229
230        // Immediately establish the PMKSA if the key is available. The PMK may be provided
231        // during ESSSA construction, or generated by a subsequent auth handshake such as SAE.
232        let pmk = match self.pmksa.as_ref() {
233            Pmksa::Initialized { pmk: Some(pmk) } => Some(pmk.clone()),
234            _ => None,
235        };
236        if let Some(pmk) = pmk { self.on_pmk_available(update_sink, pmk) } else { Ok(()) }
237    }
238
239    pub fn reset_replay_counter(&mut self) {
240        info!("resetting ESSSA replay counter");
241        self.key_replay_counter = 0;
242    }
243
244    pub fn reset_security_associations(&mut self) {
245        info!("resetting ESSSA security associations");
246        self.pmksa.replace_state(|state| state.reset());
247        self.ptksa.replace_state(|state| state.reset());
248        self.gtksa.replace_state(|state| state.reset());
249        self.igtksa.replace_state(|state| state.reset());
250    }
251
252    fn is_established(&self) -> bool {
253        match (self.ptksa.as_ref(), self.gtksa.as_ref()) {
254            (Ptksa::Established { .. }, Gtksa::Established { .. }) => true,
255            _ => false,
256        }
257    }
258
259    #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
260    fn on_key_confirmed(&mut self, update_sink: &mut UpdateSink, key: Key) -> Result<(), Error> {
261        let was_esssa_established = self.is_established();
262        match key {
263            Key::Pmk(pmk) => {
264                self.pmksa.replace_state(|state| match state {
265                    Pmksa::Initialized { .. } => {
266                        info!("established PMKSA");
267                        update_sink.push(SecAssocUpdate::Status(SecAssocStatus::PmkSaEstablished));
268                        Pmksa::Established { pmk: pmk.clone() }
269                    }
270                    other => {
271                        error!("received PMK with PMK already being established");
272                        other
273                    }
274                });
275
276                self.ptksa.replace_state(|state| state.initialize(pmk));
277                if let Ptksa::Initialized { method: exchange::Method::FourWayHandshake(hs) } =
278                    self.ptksa.as_mut()
279                {
280                    if let Fourway::Authenticator(authenticator_state_machine) = &mut **hs {
281                        authenticator_state_machine
282                            .try_replace_state(|state| {
283                                state.initiate(update_sink, self.key_replay_counter.into())
284                            })
285                            // Discard the mutable reference to the state machine since
286                            // this scope already has one.
287                            .map(|_state_machine| ())?;
288                    }
289                }
290            }
291            Key::Ptk(ptk) => {
292                // The PTK carries KEK and KCK which is used in the Group Key Handshake, thus,
293                // reset GTKSA whenever the PTK changed.
294                self.gtksa.replace_state(|state| state.reset().initialize(ptk.kck(), ptk.kek()));
295
296                self.ptksa.replace_state(|state| match state {
297                    Ptksa::Initialized { method } => {
298                        info!("established PTKSA");
299                        update_sink.push(SecAssocUpdate::Key(Key::Ptk(ptk.clone())));
300                        Ptksa::Established { method, ptk }
301                    }
302                    Ptksa::Established { method, .. } => {
303                        // PTK was already initialized.
304                        info!("re-established new PTKSA; invalidating previous one");
305                        info!("(this is likely a result of using a wrong password)");
306                        // Key can be re-established in two cases:
307                        // 1. Message gets replayed
308                        // 2. Key is being rotated
309                        // Checking that ESSSA is already established eliminates the first case.
310                        if was_esssa_established {
311                            update_sink.push(SecAssocUpdate::Key(Key::Ptk(ptk.clone())));
312                        }
313                        Ptksa::Established { method, ptk }
314                    }
315                    other @ Ptksa::Uninitialized { .. } => {
316                        error!("received PTK in unexpected PTKSA state");
317                        other
318                    }
319                });
320            }
321            Key::Gtk(gtk) => {
322                self.gtksa.replace_state(|state| match state {
323                    Gtksa::Initialized { method } => {
324                        info!("established GTKSA");
325
326                        let mut installed_gtks = HashSet::default();
327                        installed_gtks.insert(gtk.clone());
328                        update_sink.push(SecAssocUpdate::Key(Key::Gtk(gtk)));
329                        Gtksa::Established { method, installed_gtks }
330                    }
331                    Gtksa::Established { method, mut installed_gtks } => {
332                        info!("re-established new GTKSA; invalidating previous one");
333
334                        if !installed_gtks.contains(&gtk) {
335                            installed_gtks.insert(gtk.clone());
336                            update_sink.push(SecAssocUpdate::Key(Key::Gtk(gtk)));
337                        }
338                        Gtksa::Established { method, installed_gtks }
339                    }
340                    Gtksa::Uninitialized { cfg } => {
341                        error!("received GTK in unexpected GTKSA state");
342                        Gtksa::Uninitialized { cfg }
343                    }
344                });
345            }
346            Key::Igtk(igtk) => {
347                self.igtksa.replace_state(|state| match state {
348                    Igtksa::Uninitialized => {
349                        info!("established IGTKSA");
350                        let mut installed_igtks = HashSet::default();
351                        installed_igtks.insert(igtk.clone());
352                        update_sink.push(SecAssocUpdate::Key(Key::Igtk(igtk)));
353                        Igtksa::Established { installed_igtks }
354                    }
355                    Igtksa::Established { mut installed_igtks } => {
356                        info!("re-established new IGTKSA; invalidating previous one");
357
358                        if !installed_igtks.contains(&igtk) {
359                            installed_igtks.insert(igtk.clone());
360                            update_sink.push(SecAssocUpdate::Key(Key::Igtk(igtk)));
361                        }
362                        Igtksa::Established { installed_igtks }
363                    }
364                });
365            }
366            _ => {}
367        };
368        Ok(())
369    }
370
371    #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
372    pub fn on_pmk_available(
373        &mut self,
374        update_sink: &mut UpdateSink,
375        pmk: Pmk,
376    ) -> Result<(), Error> {
377        let mut new_updates = UpdateSink::default();
378        let result = self.on_key_confirmed(&mut new_updates, Key::Pmk(pmk));
379        self.push_updates(update_sink, new_updates);
380        result
381    }
382
383    // Do any necessary final processing before passing updates to the higher layer.
384    fn push_updates(&mut self, update_sink: &mut UpdateSink, mut new_updates: UpdateSink) {
385        if let Some(updates_awaiting_confirm) = &mut self.updates_awaiting_confirm {
386            // We're still waiting on a previous eapol confirm, and are not ready
387            // to do anything with these new updates. This can happen if we receive
388            // 4-way message 3 before we've received a confirm for message 2, in which
389            // case we defer all updates. We'll go through the logic below after we
390            // receive the expected confirm.
391            updates_awaiting_confirm.append(&mut new_updates);
392            return;
393        }
394        for update in new_updates {
395            if let SecAssocUpdate::Key(_) = update {
396                // Always install keys immediately to avoid race conditions after the eapol
397                // exchange completes. This is a particular issue for WPA1, where we may miss
398                // the first PTK-encrypted frame of the group key handshake.
399                // TODO(https://fxbug.dev/42051016): Preemptively requesting the key to be set before
400                //                         receiving eapol confirm may not be necessary.
401                update_sink.push(update);
402            } else if let Some(updates_awaiting_confirm) = &mut self.updates_awaiting_confirm {
403                // If we've sent an eapol frame, buffer all other non-key
404                // updates until we receive a confirm.
405                updates_awaiting_confirm.push(update);
406            } else {
407                if let SecAssocUpdate::TxEapolKeyFrame { frame, expect_response } = &update {
408                    if *expect_response {
409                        self.last_key_frame_buf = Some((1, frame.clone()));
410                    } else {
411                        // We don't expect a response, so we don't need to keep the frame around.
412                        self.last_key_frame_buf = None;
413                    }
414                    // Subsequent non-key updates should be buffered until this frame is confirmed.
415                    self.updates_awaiting_confirm.replace(Default::default());
416                }
417                update_sink.push(update);
418            }
419        }
420    }
421
422    #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
423    pub fn on_eapol_conf(
424        &mut self,
425        update_sink: &mut UpdateSink,
426        result: EapolResultCode,
427    ) -> Result<(), Error> {
428        match self.updates_awaiting_confirm.take() {
429            Some(updates) => match result {
430                EapolResultCode::Success => {
431                    // We successfully sent a frame. Now send the resulting ESSSA updates.
432                    self.push_updates(update_sink, updates);
433                    Ok(())
434                }
435                EapolResultCode::TransmissionFailure => Err(Error::KeyFrameTransmissionFailed),
436            },
437            None => {
438                error!("Ignored unexpected eapol send confirm");
439                Ok(())
440            }
441        }
442    }
443
444    #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
445    pub fn on_rsna_retransmission_timeout(
446        &mut self,
447        update_sink: &mut UpdateSink,
448    ) -> Result<(), Error> {
449        // IEEE Std 802.11-2016 6.3.22.2.4: We should always receive a confirm in response to an eapol tx.
450        // If we never received an eapol conf, treat this as a fatal error.
451        if let Some(updates) = &self.updates_awaiting_confirm {
452            return Err(Error::NoKeyFrameTransmissionConfirm(updates.len()));
453        }
454        // Resend the last key frame if appropriate
455        if let Some((attempt, key_frame)) = self.last_key_frame_buf.as_mut() {
456            *attempt += 1;
457            if *attempt > MAX_KEY_FRAME_RETRIES {
458                // Only retry a limited number of times before going idle
459                return Ok(());
460            }
461            update_sink.push(SecAssocUpdate::TxEapolKeyFrame {
462                frame: key_frame.clone(),
463                expect_response: true,
464            });
465            // Always expect a confirm for a keyframe retransmission.
466            self.updates_awaiting_confirm = Some(Default::default());
467        }
468        Ok(())
469    }
470
471    pub fn incomplete_reason(&self) -> Error {
472        if let Some(updates) = &self.updates_awaiting_confirm {
473            return Error::NoKeyFrameTransmissionConfirm(updates.len());
474        }
475        match self.ptksa.as_ref() {
476            Ptksa::Uninitialized { .. } => {
477                return Error::EapolHandshakeIncomplete("PTKSA never initialized".to_string());
478            }
479            Ptksa::Initialized { method } | Ptksa::Established { method, .. } => {
480                if let Err(error) = method.on_rsna_response_timeout() {
481                    return error;
482                }
483            }
484        }
485        if !matches!(self.gtksa.as_ref(), Gtksa::Established { .. }) {
486            return Error::EapolHandshakeIncomplete("GTKSA never established".to_string());
487        }
488
489        // Unclear how we'd get an establishing RSNA timeout without hitting any of
490        // the previous cases.
491        Error::EapolHandshakeIncomplete("Unexpected timeout while establishing RSNA".to_string())
492    }
493
494    #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
495    pub fn on_eapol_frame<B: SplitByteSlice>(
496        &mut self,
497        update_sink: &mut UpdateSink,
498        frame: eapol::Frame<B>,
499    ) -> Result<(), Error> {
500        // Only processes EAPOL Key frames. Drop all other frames silently.
501        let on_eapol_key_frame_updates = match frame {
502            eapol::Frame::Key(key_frame) => {
503                let mut on_eapol_key_frame_updates = UpdateSink::default();
504                self.on_eapol_key_frame(&mut on_eapol_key_frame_updates, key_frame)?;
505                // Frame received. Don't retransmit the last one.
506                self.last_key_frame_buf.take();
507
508                // Authenticator updates its key replay counter with every outbound EAPOL frame.
509                if let Role::Authenticator = self.role {
510                    for update in &on_eapol_key_frame_updates {
511                        if let SecAssocUpdate::TxEapolKeyFrame { frame, .. } = update {
512                            let key_replay_counter =
513                                frame.keyframe().key_frame_fields.key_replay_counter.get();
514
515                            if key_replay_counter <= self.key_replay_counter {
516                                error!(
517                                    "tx EAPOL Key frame uses invalid key replay counter: {:?} ({:?})",
518                                    key_replay_counter, self.key_replay_counter
519                                );
520                            }
521                            self.key_replay_counter = key_replay_counter;
522                        }
523                    }
524                }
525
526                on_eapol_key_frame_updates
527            }
528            _ => UpdateSink::default(),
529        };
530
531        // Check if ESSSA established before processing key updates.
532        let was_esssa_established = self.is_established();
533
534        // Process and filter Key updates internally to correctly track security associations.
535        let mut new_updates = UpdateSink::default();
536        for update in on_eapol_key_frame_updates {
537            match update {
538                SecAssocUpdate::Key(key) => {
539                    if let Err(e) = self.on_key_confirmed(&mut new_updates, key) {
540                        error!("error while processing key: {}", e);
541                    };
542                }
543                // Forward all other updates.
544                _ => new_updates.push(update),
545            }
546        }
547
548        // Report if this EAPOL frame established the ESSSA.
549        if !was_esssa_established && self.is_established() {
550            info!("established ESSSA");
551            new_updates.push(SecAssocUpdate::Status(SecAssocStatus::EssSaEstablished));
552        }
553
554        self.push_updates(update_sink, new_updates);
555        Ok(())
556    }
557
558    #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
559    fn on_eapol_key_frame<B: SplitByteSlice>(
560        &mut self,
561        update_sink: &mut UpdateSink,
562        frame: eapol::KeyFrameRx<B>,
563    ) -> Result<(), Error> {
564        // Verify the frame complies with IEEE Std 802.11-2016, 12.7.2.
565        let verified_frame = match Dot11VerifiedKeyFrame::from_frame(
566            frame,
567            &self.role,
568            &self.negotiated_protection,
569            self.key_replay_counter,
570        ) {
571            // An invalid key replay counter means we should skip the frame, but may happen under
572            // normal circumstances and should not be logged as an error.
573            Err(e @ Error::InvalidKeyReplayCounter(_, _)) => {
574                info!("Ignoring eapol frame: {}", e);
575                return Ok(());
576            }
577            result => result?,
578        };
579
580        // Safe: frame was just verified.
581        let raw_frame = verified_frame.unsafe_get_raw();
582        let frame_has_mic = raw_frame.key_frame_fields.key_info().key_mic();
583        let frame_key_replay_counter = raw_frame.key_frame_fields.key_replay_counter.get();
584
585        // Forward frame to correct security association.
586        // PMKSA must be established before any other security association can be established. Because
587        // the PMKSA is handled outside our ESSSA this is just an early return.
588        match self.pmksa.as_mut() {
589            Pmksa::Initialized { .. } => return Ok(()),
590            Pmksa::Established { .. } => {}
591        };
592
593        // Once PMKSA was established PTKSA and GTKSA can process frames.
594        // IEEE Std 802.11-2016, 12.7.2 b.2)
595        let result = if raw_frame.key_frame_fields.key_info().key_type() == eapol::KeyType::PAIRWISE
596        {
597            match self.ptksa.as_mut() {
598                Ptksa::Uninitialized { .. } => Ok(()),
599                Ptksa::Initialized { method } | Ptksa::Established { method, .. } => {
600                    method.on_eapol_key_frame(update_sink, verified_frame)
601                }
602            }
603        } else if raw_frame.key_frame_fields.key_info().key_type() == eapol::KeyType::GROUP_SMK {
604            match self.gtksa.as_mut() {
605                Gtksa::Uninitialized { .. } => Ok(()),
606                Gtksa::Initialized { method } | Gtksa::Established { method, .. } => match method {
607                    Some(method) => method.on_eapol_key_frame(update_sink, verified_frame),
608                    None => {
609                        error!("received group key EAPOL Key frame with GTK re-keying disabled");
610                        Ok(())
611                    }
612                },
613            }
614        } else {
615            error!(
616                "unsupported EAPOL Key frame key type: {:?}",
617                raw_frame.key_frame_fields.key_info().key_type()
618            );
619            Ok(())
620        };
621
622        // IEEE Std 802.11-2016, 12.7.2, d)
623        // Update key replay counter if MIC was set and is valid. Only applicable for Supplicant.
624        // Eapol key frame being TX'd implies that MIC is valid.
625        if frame_has_mic {
626            if let Role::Supplicant = self.role {
627                for update in update_sink {
628                    if let SecAssocUpdate::TxEapolKeyFrame { .. } = update {
629                        self.key_replay_counter = frame_key_replay_counter;
630                        break;
631                    }
632                }
633            }
634        }
635
636        result
637    }
638}
639
640#[cfg(test)]
641mod tests {
642    use super::*;
643    use crate::key::exchange::compute_mic;
644    use crate::rsna::test_util::expect_eapol_resp;
645    use crate::rsna::{AuthStatus, test_util};
646    use crate::{Authenticator, Supplicant};
647    use assert_matches::assert_matches;
648    use wlan_common::ie::get_rsn_ie_bytes;
649    use wlan_common::ie::rsn::fake_wpa2_s_rsne;
650    use zerocopy::byteorder::big_endian::U64;
651
652    const ANONCE: [u8; 32] = [0x1A; 32];
653    const GTK: [u8; 16] = [0x1B; 16];
654    const GTK_REKEY: [u8; 16] = [0x1F; 16];
655    const GTK_REKEY_2: [u8; 16] = [0x2F; 16];
656
657    #[test]
658    fn test_supplicant_with_wpa3_authenticator() {
659        let mut supplicant = test_util::get_wpa3_supplicant();
660        let mut authenticator = test_util::get_wpa3_authenticator();
661        let mut s_updates = vec![];
662        supplicant.start(&mut s_updates).expect("Failed starting Supplicant");
663        assert!(s_updates.is_empty(), "{:?}", s_updates);
664
665        // Send Supplicant SAE commit
666        let result = supplicant.on_sae_handshake_ind(&mut s_updates);
667        assert!(result.is_ok(), "Supplicant failed to ind SAE handshake");
668        let s_sae_frame_vec = test_util::expect_sae_frame_vec(&s_updates[..]);
669        test_util::expect_schedule_sae_timeout(&s_updates[..]);
670        assert_eq!(s_updates.len(), 2, "{:?}", s_updates);
671
672        // Respond to Supplicant SAE commit
673        let mut a_updates = vec![];
674        for s_sae_frame in s_sae_frame_vec {
675            let result = authenticator.on_sae_frame_rx(&mut a_updates, s_sae_frame);
676            assert!(result.is_ok(), "Authenticator failed to rx SAE handshake message");
677        }
678        let a_sae_frame_vec = test_util::expect_sae_frame_vec(&a_updates[..]);
679        test_util::expect_schedule_sae_timeout(&a_updates[..]);
680        assert_eq!(a_updates.len(), 3, "{:?}", a_updates);
681
682        // Receive Authenticator SAE confirm
683        let mut s_updates = vec![];
684        for a_sae_frame in a_sae_frame_vec {
685            let result = supplicant.on_sae_frame_rx(&mut s_updates, a_sae_frame);
686            assert!(result.is_ok(), "Supplicant failed to rx SAE handshake message");
687        }
688        let s_sae_frame_vec = test_util::expect_sae_frame_vec(&s_updates[..]);
689        test_util::expect_schedule_sae_timeout(&s_updates[..]);
690        test_util::expect_reported_pmk(&s_updates[..]);
691        test_util::expect_reported_sae_auth_status(&s_updates[..], AuthStatus::Success);
692        test_util::expect_reported_status(&s_updates[..], SecAssocStatus::PmkSaEstablished);
693        assert_eq!(s_updates.len(), 5, "{:?}", s_updates);
694
695        // Receive Supplicant SAE confirm
696        let mut a_updates = vec![];
697        for s_sae_frame in s_sae_frame_vec {
698            let result = authenticator.on_sae_frame_rx(&mut a_updates, s_sae_frame);
699            assert!(result.is_ok(), "Authenticator failed to rx SAE handshake message");
700        }
701        test_util::expect_reported_pmk(&a_updates[..]);
702        test_util::expect_reported_sae_auth_status(&a_updates[..], AuthStatus::Success);
703        test_util::expect_reported_status(&a_updates[..], SecAssocStatus::PmkSaEstablished);
704        let msg1 = test_util::expect_eapol_resp(&a_updates[..]);
705        authenticator
706            .on_eapol_conf(&mut a_updates, EapolResultCode::Success)
707            .expect("Failed eapol conf");
708        assert_eq!(a_updates.len(), 4, "{:?}", a_updates);
709
710        test_eapol_exchange(&mut supplicant, &mut authenticator, Some(msg1), true);
711    }
712
713    #[test]
714    fn test_supplicant_with_wpa2_authenticator() {
715        let mut supplicant = test_util::get_wpa2_supplicant();
716        let mut authenticator = test_util::get_wpa2_authenticator();
717        let mut updates = vec![];
718        supplicant.start(&mut updates).expect("Failed starting Supplicant");
719        assert_eq!(updates.len(), 1, "{:?}", updates);
720        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
721        test_eapol_exchange(&mut supplicant, &mut authenticator, None, false);
722    }
723
724    #[test]
725    fn test_replay_first_message() {
726        let mut supplicant = test_util::get_wpa2_supplicant();
727        let mut updates = vec![];
728        supplicant.start(&mut updates).expect("Failed starting Supplicant");
729        assert_eq!(updates.len(), 1, "{:?}", updates);
730        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
731
732        // Send first message of handshake.
733        let (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
734            msg1.key_frame_fields.key_replay_counter.set(1);
735        });
736        assert!(result.is_ok());
737        let first_msg2 = expect_eapol_resp(&updates[..]);
738        let first_fields = first_msg2.keyframe().key_frame_fields;
739
740        // Replay first message which should restart the entire handshake.
741        // Verify the second message of the handshake was received.
742        let (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
743            msg1.key_frame_fields.key_replay_counter = U64::new(3);
744        });
745        assert!(result.is_ok());
746        let second_msg2 = expect_eapol_resp(&updates[..]);
747        let second_fields = second_msg2.keyframe().key_frame_fields;
748
749        // Verify Supplicant responded to the replayed first message and didn't change SNonce.
750        assert_eq!(second_fields.key_replay_counter.get(), 3);
751        assert_eq!(first_fields.key_nonce, second_fields.key_nonce);
752    }
753
754    #[test]
755    fn test_first_message_does_not_change_replay_counter() {
756        let mut supplicant = test_util::get_wpa2_supplicant();
757        let mut updates = vec![];
758        supplicant.start(&mut updates).expect("Failed starting Supplicant");
759        assert_eq!(updates.len(), 1, "{:?}", updates);
760        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
761
762        assert_eq!(0, supplicant.esssa.key_replay_counter);
763
764        // Send first message of handshake.
765        let (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
766            msg1.key_frame_fields.key_replay_counter.set(0);
767        });
768        assert!(result.is_ok());
769        expect_eapol_resp(&updates[..]);
770        assert_eq!(0, supplicant.esssa.key_replay_counter);
771
772        // Raise the replay counter of message 1.
773        let (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
774            msg1.key_frame_fields.key_replay_counter.set(1);
775        });
776        assert!(result.is_ok());
777        expect_eapol_resp(&updates[..]);
778        assert_eq!(0, supplicant.esssa.key_replay_counter);
779
780        // Lower the replay counter of message 1.
781        let (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
782            msg1.key_frame_fields.key_replay_counter.set(0);
783        });
784        assert!(result.is_ok());
785        assert_eq!(0, supplicant.esssa.key_replay_counter);
786        expect_eapol_resp(&updates[..]);
787    }
788
789    #[test]
790    fn test_zero_key_replay_counter_msg1() {
791        let mut supplicant = test_util::get_wpa2_supplicant();
792        let mut updates = vec![];
793        supplicant.start(&mut updates).expect("Failed starting Supplicant");
794        assert_eq!(updates.len(), 1, "{:?}", updates);
795        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
796
797        let (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
798            msg1.key_frame_fields.key_replay_counter.set(0);
799        });
800        assert!(result.is_ok());
801        expect_eapol_resp(&updates[..]);
802    }
803
804    #[test]
805    fn test_nonzero_key_replay_counter_msg1() {
806        let mut supplicant = test_util::get_wpa2_supplicant();
807        let mut updates = vec![];
808        supplicant.start(&mut updates).expect("Failed starting Supplicant");
809        assert_eq!(updates.len(), 1, "{:?}", updates);
810        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
811
812        let (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
813            msg1.key_frame_fields.key_replay_counter.set(1);
814        });
815        assert!(result.is_ok());
816        expect_eapol_resp(&updates[..]);
817    }
818
819    #[test]
820    fn test_zero_key_replay_counter_lower_msg3_counter() {
821        let mut supplicant = test_util::get_wpa2_supplicant();
822        let mut updates = vec![];
823        supplicant.start(&mut updates).expect("Failed starting Supplicant");
824        assert_eq!(updates.len(), 1, "{:?}", updates);
825        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
826        assert_eq!(0, supplicant.esssa.key_replay_counter);
827
828        let (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
829            msg1.key_frame_fields.key_replay_counter.set(1);
830        });
831        assert!(result.is_ok());
832        assert_eq!(0, supplicant.esssa.key_replay_counter);
833
834        let msg2 = expect_eapol_resp(&updates[..]);
835        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
836        let ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
837
838        // Intuitively, this should not succeed because the replay
839        // counter in message 3 is lower than in message 1. It is a
840        // quirk of IEEE 802.11-2016 12.7.2 that the replay counter in
841        // message 1 is in fact meaningless because replay counters
842        // are only updated when there is a MIC to verify. There is no
843        // MIC to verify in message 1, and so the replay counter
844        // doesn't matter.
845        let (result, updates) = send_fourway_msg3(&mut supplicant, &ptk, |msg3| {
846            msg3.key_frame_fields.key_replay_counter = U64::new(0);
847        });
848        assert!(result.is_ok());
849        assert_eq!(0, supplicant.esssa.key_replay_counter);
850        test_util::expect_reported_ptk(&updates[..]);
851    }
852
853    #[test]
854    fn test_key_replay_counter_updated_after_msg3() {
855        let mut supplicant = test_util::get_wpa2_supplicant();
856        let mut updates = vec![];
857        let mut result;
858        supplicant.start(&mut updates).expect("Failed starting Supplicant");
859        assert_eq!(updates.len(), 1, "{:?}", updates);
860        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
861
862        (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
863            msg1.key_frame_fields.key_replay_counter.set(1);
864        });
865        assert!(result.is_ok());
866        let msg2 = expect_eapol_resp(&updates[..]);
867        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
868        let ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
869
870        (result, updates) = send_fourway_msg3(&mut supplicant, &ptk, |msg3| {
871            msg3.key_frame_fields.key_replay_counter = U64::new(5);
872        });
873        assert!(result.is_ok());
874        assert_eq!(5, supplicant.esssa.key_replay_counter);
875        test_util::expect_reported_ptk(&updates[..]);
876
877        // First message should be dropped if replay counter too low.
878        (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
879            msg1.key_frame_fields.key_replay_counter.set(0);
880        });
881        assert!(result.is_ok());
882        assert_eq!(5, supplicant.esssa.key_replay_counter);
883        assert!(updates.is_empty(), "{:?}", updates);
884
885        // After reset, first message should not be dropped.
886        supplicant.reset();
887        updates = vec![];
888        supplicant.start(&mut updates).expect("Failed starting Supplicant");
889        assert_eq!(updates.len(), 1, "{:?}", updates);
890        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
891        assert_eq!(0, supplicant.esssa.key_replay_counter);
892        let (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
893            msg1.key_frame_fields.key_replay_counter.set(0);
894        });
895        assert!(result.is_ok());
896        expect_eapol_resp(&updates[..]);
897    }
898
899    #[test]
900    fn test_key_replay_counter_not_updated_for_invalid_mic_msg3() {
901        let mut supplicant = test_util::get_wpa2_supplicant();
902        let mut updates = vec![];
903        let mut result: Result<(), Error>;
904        supplicant.start(&mut updates).expect("Failed starting Supplicant");
905        assert_eq!(updates.len(), 1, "{:?}", updates);
906        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
907
908        (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
909            msg1.key_frame_fields.key_replay_counter.set(1);
910        });
911        assert!(result.is_ok());
912        assert_eq!(0, supplicant.esssa.key_replay_counter);
913
914        let msg2 = expect_eapol_resp(&updates[..]);
915        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
916        let ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
917
918        let msg3 = test_util::get_wpa2_4whs_msg3_with_mic_modifier(
919            &ptk,
920            &ANONCE[..],
921            &GTK,
922            |msg3| {
923                msg3.key_frame_fields.key_replay_counter = U64::new(5);
924            },
925            |mic| {
926                mic[0] = mic[0].wrapping_add(1);
927            },
928        );
929        updates = UpdateSink::default();
930        result = supplicant.on_eapol_frame(&mut updates, eapol::Frame::Key(msg3.keyframe()));
931        assert!(result.is_ok());
932        // The key replay counter should not be updated
933        assert_eq!(0, supplicant.esssa.key_replay_counter);
934    }
935
936    #[test]
937    fn test_zero_key_replay_counter_valid_msg3() {
938        let mut supplicant = test_util::get_wpa2_supplicant();
939        let mut updates = vec![];
940        let mut result;
941        supplicant.start(&mut updates).expect("Failed starting Supplicant");
942        assert_eq!(updates.len(), 1, "{:?}", updates);
943        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
944
945        (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
946            msg1.key_frame_fields.key_replay_counter.set(0);
947        });
948        assert!(result.is_ok());
949        let msg2 = expect_eapol_resp(&updates[..]);
950        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
951        let ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
952
953        (result, updates) = send_fourway_msg3(&mut supplicant, &ptk, |msg3| {
954            msg3.key_frame_fields.key_replay_counter = U64::new(1);
955        });
956        assert!(result.is_ok());
957        test_util::expect_reported_ptk(&updates[..]);
958    }
959
960    #[test]
961    fn test_zero_key_replay_counter_replayed_msg3() {
962        let mut supplicant = test_util::get_wpa2_supplicant();
963        let mut updates = vec![];
964        let mut result;
965        supplicant.start(&mut updates).expect("Failed starting Supplicant");
966        assert_eq!(updates.len(), 1, "{:?}", updates);
967        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
968        assert_eq!(0, supplicant.esssa.key_replay_counter);
969
970        (result, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
971            msg1.key_frame_fields.key_replay_counter.set(0);
972        });
973        assert!(result.is_ok());
974        let msg2 = expect_eapol_resp(&updates[..]);
975        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
976        let ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
977
978        (result, updates) = send_fourway_msg3(&mut supplicant, &ptk, |msg3| {
979            msg3.key_frame_fields.key_replay_counter.set(2);
980        });
981        assert!(result.is_ok());
982        assert_eq!(2, supplicant.esssa.key_replay_counter);
983        test_util::expect_reported_ptk(&updates[..]);
984
985        // The just sent third message increased the key replay counter.
986        // All successive EAPOL frames are required to have a larger key replay counter.
987
988        // Send an invalid message.
989        (result, updates) = send_fourway_msg3(&mut supplicant, &ptk, |msg3| {
990            msg3.key_frame_fields.key_replay_counter.set(2);
991        });
992        assert!(result.is_ok());
993        assert_eq!(2, supplicant.esssa.key_replay_counter);
994        assert!(updates.is_empty(), "{:?}", updates);
995
996        // Send a valid message.
997        (result, updates) = send_fourway_msg3(&mut supplicant, &ptk, |msg3| {
998            msg3.key_frame_fields.key_replay_counter = U64::new(3);
999        });
1000        assert!(result.is_ok());
1001        assert_eq!(3, supplicant.esssa.key_replay_counter);
1002        assert!(!updates.is_empty());
1003    }
1004
1005    // Replays the first message of the 4-Way Handshake with an altered ANonce to verify that
1006    // (1) the Supplicant discards the first derived PTK in favor of a new one, and
1007    // (2) the Supplicant is not reusing a nonce from its previous message,
1008    // (3) the Supplicant only reports a new PTK if the 4-Way Handshake was completed successfully.
1009    #[test]
1010    fn test_replayed_msg1_ptk_installation_different_anonces() {
1011        let mut supplicant = test_util::get_wpa2_supplicant();
1012        let mut updates = vec![];
1013        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1014        assert_eq!(updates.len(), 1, "{:?}", updates);
1015        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1016
1017        // Send 1st message of 4-Way Handshake for the first time and derive PTK.
1018        let (_, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
1019            msg1.key_frame_fields.key_replay_counter.set(1);
1020        });
1021        assert_eq!(test_util::get_reported_ptk(&updates[..]), None);
1022        let msg2 = expect_eapol_resp(&updates[..]);
1023        let msg2_frame = msg2.keyframe();
1024        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
1025        let first_ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
1026        let first_nonce = msg2_frame.key_frame_fields.key_nonce;
1027
1028        // Send 1st message of 4-Way Handshake a second time and derive PTK.
1029        // Use a different ANonce than initially used.
1030        let (_, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
1031            msg1.key_frame_fields.key_replay_counter.set(2);
1032            msg1.key_frame_fields.key_nonce = [99; 32];
1033        });
1034        assert_eq!(test_util::get_reported_ptk(&updates[..]), None);
1035        let msg2 = expect_eapol_resp(&updates[..]);
1036        let msg2_frame = msg2.keyframe();
1037        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
1038        let second_ptk = test_util::get_ptk(&[99; 32][..], &snonce[..]);
1039        let second_nonce = msg2_frame.key_frame_fields.key_nonce;
1040
1041        // Send 3rd message of 4-Way Handshake.
1042        // The Supplicant now finished the 4-Way Handshake and should report its PTK.
1043        // Use the same ANonce which was used in the replayed 1st message.
1044        let (_, updates) = send_fourway_msg3(&mut supplicant, &second_ptk, |msg3| {
1045            msg3.key_frame_fields.key_replay_counter.set(3);
1046            msg3.key_frame_fields.key_nonce = [99; 32];
1047        });
1048
1049        let installed_ptk = test_util::expect_reported_ptk(&updates[..]);
1050        assert_ne!(first_nonce, second_nonce);
1051        assert_ne!(&first_ptk, &second_ptk);
1052        assert_eq!(installed_ptk, second_ptk);
1053    }
1054
1055    // Replays the first message of the 4-Way Handshake without altering its ANonce to verify that
1056    // (1) the Supplicant derives the same PTK for the replayed message, and
1057    // (2) the Supplicant is reusing the nonce from its previous message,
1058    // (3) the Supplicant only reports a PTK if the 4-Way Handshake was completed successfully.
1059    // Regression test for: https://fxbug.dev/42104495
1060    #[test]
1061    fn test_replayed_msg1_ptk_installation_same_anonces() {
1062        let mut supplicant = test_util::get_wpa2_supplicant();
1063        let mut updates = vec![];
1064        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1065        assert_eq!(updates.len(), 1, "{:?}", updates);
1066        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1067
1068        // Send 1st message of 4-Way Handshake for the first time and derive PTK.
1069        let (_, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
1070            msg1.key_frame_fields.key_replay_counter.set(1);
1071        });
1072        assert_eq!(test_util::get_reported_ptk(&updates[..]), None);
1073        let msg2 = expect_eapol_resp(&updates[..]);
1074        let msg2_frame = msg2.keyframe();
1075        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
1076        let first_ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
1077        let first_nonce = msg2_frame.key_frame_fields.key_nonce;
1078
1079        // Send 1st message of 4-Way Handshake a second time and derive PTK.
1080        let (_, updates) = send_fourway_msg1(&mut supplicant, |msg1| {
1081            msg1.key_frame_fields.key_replay_counter.set(2);
1082        });
1083        assert_eq!(test_util::get_reported_ptk(&updates[..]), None);
1084        let msg2 = expect_eapol_resp(&updates[..]);
1085        let msg2_frame = msg2.keyframe();
1086        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
1087        let second_ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
1088        let second_nonce = msg2_frame.key_frame_fields.key_nonce;
1089
1090        // Send 3rd message of 4-Way Handshake.
1091        // The Supplicant now finished the 4-Way Handshake and should report its PTK.
1092        let (_, updates) = send_fourway_msg3(&mut supplicant, &second_ptk, |msg3| {
1093            msg3.key_frame_fields.key_replay_counter.set(3);
1094        });
1095
1096        let installed_ptk = test_util::expect_reported_ptk(&updates[..]);
1097        assert_eq!(first_nonce, second_nonce);
1098        assert_eq!(&first_ptk, &second_ptk);
1099        assert_eq!(installed_ptk, second_ptk);
1100    }
1101
1102    // Test for WPA2-Personal (PSK CCMP-128) with a Supplicant role.
1103    #[test]
1104    fn test_supplicant_wpa2_ccmp128_psk() {
1105        // Create ESS Security Association
1106        let mut supplicant = test_util::get_wpa2_supplicant();
1107        let mut updates = vec![];
1108        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1109        assert_eq!(updates.len(), 1, "{:?}", updates);
1110        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1111
1112        // Send first message
1113        let (result, updates) = send_fourway_msg1(&mut supplicant, |_| {});
1114        assert!(result.is_ok());
1115
1116        // Verify 2nd message.
1117        let msg2_buf = expect_eapol_resp(&updates[..]);
1118        let msg2 = msg2_buf.keyframe();
1119        let s_rsne = fake_wpa2_s_rsne();
1120        let s_rsne_data = get_rsn_ie_bytes(&s_rsne);
1121        assert_eq!({ msg2.eapol_fields.version }, eapol::ProtocolVersion::IEEE802DOT1X2001);
1122        assert_eq!({ msg2.eapol_fields.packet_type }, eapol::PacketType::KEY);
1123        let buf = msg2.to_bytes(false);
1124        assert_eq!(msg2.eapol_fields.packet_body_len.get() as usize, buf.len() - 4);
1125        assert_eq!({ msg2.key_frame_fields.descriptor_type }, eapol::KeyDescriptor::IEEE802DOT11);
1126        assert_eq!(msg2.key_frame_fields.key_info(), eapol::KeyInformation(0x010A));
1127        assert_eq!(msg2.key_frame_fields.key_len.get(), 0);
1128        assert_eq!(msg2.key_frame_fields.key_replay_counter.get(), 1);
1129        assert!(!test_util::is_zero(&msg2.key_frame_fields.key_nonce[..]));
1130        assert!(test_util::is_zero(&msg2.key_frame_fields.key_iv[..]));
1131        assert_eq!(msg2.key_frame_fields.key_rsc.get(), 0);
1132        assert!(!test_util::is_zero(&msg2.key_mic[..]));
1133        assert_eq!(msg2.key_mic.len(), test_util::mic_len());
1134        assert_eq!(msg2.key_data.len(), 20);
1135        assert_eq!(&msg2.key_data[..], &s_rsne_data[..]);
1136
1137        // Send 3rd message.
1138        let snonce = msg2.key_frame_fields.key_nonce;
1139        let ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
1140        let (result, updates) = send_fourway_msg3(&mut supplicant, &ptk, |_| {});
1141        assert!(result.is_ok());
1142
1143        // Verify 4th message was received and is correct.
1144        let msg4_buf = expect_eapol_resp(&updates[..]);
1145        let msg4 = msg4_buf.keyframe();
1146        assert_eq!({ msg4.eapol_fields.version }, eapol::ProtocolVersion::IEEE802DOT1X2001);
1147        assert_eq!({ msg4.eapol_fields.packet_type }, eapol::PacketType::KEY);
1148        assert_eq!(msg4.eapol_fields.packet_body_len.get() as usize, &msg4_buf[..].len() - 4);
1149        assert_eq!({ msg4.key_frame_fields.descriptor_type }, eapol::KeyDescriptor::IEEE802DOT11);
1150        assert_eq!(msg4.key_frame_fields.key_info(), eapol::KeyInformation(0x030A));
1151        assert_eq!(msg4.key_frame_fields.key_len.get(), 0);
1152        assert_eq!(msg4.key_frame_fields.key_replay_counter.get(), 2);
1153        assert!(test_util::is_zero(&msg4.key_frame_fields.key_nonce[..]));
1154        assert!(test_util::is_zero(&msg4.key_frame_fields.key_iv[..]));
1155        assert_eq!(msg4.key_frame_fields.key_rsc.get(), 0);
1156        assert!(!test_util::is_zero(&msg4.key_mic[..]));
1157        assert_eq!(msg4.key_mic.len(), test_util::mic_len());
1158        assert_eq!(msg4.key_data.len(), 0);
1159        assert!(test_util::is_zero(&msg4.key_data[..]));
1160        // Verify the message's MIC.
1161        let mic = compute_mic(ptk.kck(), &test_util::get_rsne_protection(), &msg4)
1162            .expect("error computing MIC");
1163        assert_eq!(&msg4.key_mic[..], &mic[..]);
1164
1165        // Verify PTK was reported.
1166        let reported_ptk = test_util::expect_reported_ptk(&updates[..]);
1167        assert_eq!(ptk.ptk, reported_ptk.ptk);
1168
1169        // Verify GTK was reported.
1170        let reported_gtk = test_util::expect_reported_gtk(&updates[..]);
1171        assert_eq!(&GTK[..], &reported_gtk.bytes[..]);
1172
1173        // Verify ESS was reported to be established.
1174        let reported_status =
1175            test_util::expect_reported_status(&updates[..], SecAssocStatus::EssSaEstablished);
1176        assert_eq!(reported_status, SecAssocStatus::EssSaEstablished);
1177
1178        // Cause re-keying of GTK via Group-Key Handshake.
1179
1180        let (result, updates) = send_group_key_msg1(&mut supplicant, &ptk, GTK_REKEY, 3, 3);
1181        assert!(result.is_ok());
1182
1183        // Verify 2th message was received and is correct.
1184        let msg2_buf = expect_eapol_resp(&updates[..]);
1185        let msg2 = msg2_buf.keyframe();
1186        assert_eq!({ msg2.eapol_fields.version }, eapol::ProtocolVersion::IEEE802DOT1X2001);
1187        assert_eq!({ msg2.eapol_fields.packet_type }, eapol::PacketType::KEY);
1188        assert_eq!(msg2.eapol_fields.packet_body_len.get() as usize, &msg2_buf[..].len() - 4);
1189        assert_eq!({ msg2.key_frame_fields.descriptor_type }, eapol::KeyDescriptor::IEEE802DOT11);
1190        assert_eq!(msg2.key_frame_fields.key_info(), eapol::KeyInformation(0x0302));
1191        assert_eq!(msg2.key_frame_fields.key_len.get(), 0);
1192        assert_eq!(msg2.key_frame_fields.key_replay_counter.get(), 3);
1193        assert!(test_util::is_zero(&msg2.key_frame_fields.key_nonce[..]));
1194        assert!(test_util::is_zero(&msg2.key_frame_fields.key_iv[..]));
1195        assert_eq!(msg2.key_frame_fields.key_rsc.get(), 0);
1196        assert!(!test_util::is_zero(&msg2.key_mic[..]));
1197        assert_eq!(msg2.key_mic.len(), test_util::mic_len());
1198        assert_eq!(msg2.key_data.len(), 0);
1199        assert!(test_util::is_zero(&msg2.key_data[..]));
1200        // Verify the message's MIC.
1201        let mic = compute_mic(ptk.kck(), &test_util::get_rsne_protection(), &msg2)
1202            .expect("error computing MIC");
1203        assert_eq!(&msg2.key_mic[..], &mic[..]);
1204
1205        // Verify PTK was NOT re-installed.
1206        assert_eq!(test_util::get_reported_ptk(&updates[..]), None);
1207
1208        // Verify GTK was installed.
1209        let reported_gtk = test_util::expect_reported_gtk(&updates[..]);
1210        assert_eq!(&GTK_REKEY[..], &reported_gtk.bytes[..]);
1211    }
1212
1213    // Test to verify that GTKs derived in the 4-Way Handshake are not being re-installed
1214    // through Group Key Handshakes.
1215    #[test]
1216    fn test_supplicant_no_gtk_reinstallation_from_4way() {
1217        // Create ESS Security Association
1218        let mut supplicant = test_util::get_wpa2_supplicant();
1219        let mut updates = vec![];
1220        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1221        assert_eq!(updates.len(), 1, "{:?}", updates);
1222        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1223
1224        // Complete 4-Way Handshake.
1225        let updates = send_fourway_msg1(&mut supplicant, |_| {}).1;
1226        let msg2 = test_util::expect_eapol_resp(&updates[..]);
1227        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
1228        let ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
1229        let _ = send_fourway_msg3(&mut supplicant, &ptk, |_| {});
1230
1231        // Cause re-keying of GTK via Group-Key Handshake.
1232        // Rekey same GTK which has been already installed via the 4-Way Handshake.
1233        // This GTK should not be re-installed.
1234        let (result, updates) = send_group_key_msg1(&mut supplicant, &ptk, GTK, 2, 3);
1235        assert!(result.is_ok());
1236
1237        // Verify 2th message was received and is correct.
1238        let msg2 = test_util::expect_eapol_resp(&updates[..]);
1239        let keyframe = msg2.keyframe();
1240        assert_eq!(keyframe.eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2001);
1241        assert_eq!(keyframe.eapol_fields.packet_type, eapol::PacketType::KEY);
1242        assert_eq!(keyframe.eapol_fields.packet_body_len.get() as usize, msg2.len() - 4);
1243        assert_eq!(keyframe.key_frame_fields.descriptor_type, eapol::KeyDescriptor::IEEE802DOT11);
1244        assert_eq!(keyframe.key_frame_fields.key_info().0, 0x0302);
1245        assert_eq!(keyframe.key_frame_fields.key_len.get(), 0);
1246        assert_eq!(keyframe.key_frame_fields.key_replay_counter.get(), 3);
1247        assert!(test_util::is_zero(&keyframe.key_frame_fields.key_nonce[..]));
1248        assert!(test_util::is_zero(&keyframe.key_frame_fields.key_iv[..]));
1249        assert_eq!(keyframe.key_frame_fields.key_rsc.get(), 0);
1250        assert!(!test_util::is_zero(&keyframe.key_mic[..]));
1251        assert_eq!(keyframe.key_mic.len(), test_util::mic_len());
1252        assert_eq!(keyframe.key_data.len(), 0);
1253        assert!(test_util::is_zero(&keyframe.key_data[..]));
1254        // Verify the message's MIC.
1255        let mic = compute_mic(ptk.kck(), &test_util::get_rsne_protection(), &keyframe)
1256            .expect("error computing MIC");
1257        assert_eq!(&keyframe.key_mic[..], &mic[..]);
1258
1259        // Verify neither PTK nor GTK were re-installed.
1260        assert_eq!(test_util::get_reported_ptk(&updates[..]), None);
1261        assert_eq!(test_util::get_reported_gtk(&updates[..]), None);
1262    }
1263
1264    // Test to verify that already rotated GTKs are not being re-installed.
1265    #[test]
1266    fn test_supplicant_no_gtk_reinstallation() {
1267        // Create ESS Security Association
1268        let mut supplicant = test_util::get_wpa2_supplicant();
1269        let mut updates = vec![];
1270        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1271        assert_eq!(updates.len(), 1, "{:?}", updates);
1272        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1273
1274        // Complete 4-Way Handshake.
1275        let updates = send_fourway_msg1(&mut supplicant, |_| {}).1;
1276        let msg2 = test_util::expect_eapol_resp(&updates[..]);
1277        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
1278        let ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
1279        let _ = send_fourway_msg3(&mut supplicant, &ptk, |_| {});
1280
1281        // Cause re-keying of GTK via Group-Key Handshake.
1282        // Rekey same GTK which has been already installed via the 4-Way Handshake.
1283        // This GTK should not be re-installed.
1284
1285        // Rotate GTK.
1286        let (result, updates) = send_group_key_msg1(&mut supplicant, &ptk, GTK_REKEY, 3, 3);
1287        assert!(result.is_ok());
1288        let reported_gtk = test_util::expect_reported_gtk(&updates[..]);
1289        assert_eq!(&reported_gtk.bytes[..], &GTK_REKEY[..]);
1290
1291        let (result, updates) = send_group_key_msg1(&mut supplicant, &ptk, GTK_REKEY_2, 1, 4);
1292        assert!(result.is_ok(), "{:?}", result);
1293        let reported_gtk = test_util::expect_reported_gtk(&updates[..]);
1294        assert_eq!(&reported_gtk.bytes[..], &GTK_REKEY_2[..]);
1295
1296        // Rotate GTK to already installed key. Verify GTK was not re-installed.
1297        let (result, updates) = send_group_key_msg1(&mut supplicant, &ptk, GTK_REKEY, 3, 5);
1298        assert!(result.is_ok());
1299        assert_eq!(test_util::get_reported_gtk(&updates[..]), None);
1300    }
1301
1302    #[test]
1303    fn test_rsna_retransmission_timeout() {
1304        // Create ESS Security Association
1305        let mut supplicant = test_util::get_wpa2_supplicant();
1306        let mut updates = vec![];
1307        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1308        assert_eq!(updates.len(), 1, "{:?}", updates);
1309        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1310
1311        // Send the first frame.
1312        updates = send_fourway_msg1(&mut supplicant, |_| {}).1;
1313        let msg2 = test_util::expect_eapol_resp(&updates[..]);
1314
1315        // Acknowledge the second frame sent.
1316        updates = vec![];
1317        supplicant
1318            .on_eapol_conf(&mut updates, EapolResultCode::Success)
1319            .expect("Failed to send eapol conf");
1320        assert!(updates.is_empty());
1321
1322        // Timeout several times.
1323        for _ in 1..MAX_KEY_FRAME_RETRIES {
1324            updates = vec![];
1325            supplicant
1326                .on_rsna_retransmission_timeout(&mut updates)
1327                .expect("Failed to send key frame timeout");
1328            let msg2_retry = test_util::expect_eapol_resp(&updates[..]);
1329            supplicant
1330                .on_eapol_conf(&mut updates, EapolResultCode::Success)
1331                .expect("Failed to send eapol conf");
1332            assert_eq!(msg2, msg2_retry);
1333        }
1334
1335        // Go idle on the last retry.
1336        updates = vec![];
1337        assert_matches!(supplicant.on_rsna_retransmission_timeout(&mut updates), Ok(()));
1338        assert!(updates.is_empty(), "{:?}", updates);
1339    }
1340
1341    #[test]
1342    fn test_rsna_retransmission_timeout_retries_reset() {
1343        // Create ESS Security Association
1344        let mut supplicant = test_util::get_wpa2_supplicant();
1345        let mut updates = vec![];
1346        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1347        assert_eq!(updates.len(), 1, "{:?}", updates);
1348        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1349
1350        for _ in 0..3 {
1351            // Send the first frame.
1352            updates = send_fourway_msg1(&mut supplicant, |_| {}).1;
1353            let msg2 = test_util::expect_eapol_resp(&updates[..]);
1354            updates = vec![];
1355            supplicant
1356                .on_eapol_conf(&mut updates, EapolResultCode::Success)
1357                .expect("Failed to send eapol conf");
1358            assert!(updates.is_empty(), "{:?}", updates);
1359
1360            // Timeout several times.
1361            for _ in 1..MAX_KEY_FRAME_RETRIES {
1362                updates = vec![];
1363                supplicant
1364                    .on_rsna_retransmission_timeout(&mut updates)
1365                    .expect("Failed to send key frame timeout");
1366                let msg2_retry = test_util::expect_eapol_resp(&updates[..]);
1367                supplicant
1368                    .on_eapol_conf(&mut updates, EapolResultCode::Success)
1369                    .expect("Failed to send eapol conf");
1370                assert_eq!(msg2, msg2_retry);
1371            }
1372
1373            // Go idle on the last retry.
1374            updates = vec![];
1375            assert_matches!(supplicant.on_rsna_retransmission_timeout(&mut updates), Ok(()));
1376            assert!(updates.is_empty(), "{:?}", updates);
1377        }
1378    }
1379
1380    #[test]
1381    fn test_overall_timeout_before_msg1() {
1382        // Create ESS Security Association
1383        let mut supplicant = test_util::get_wpa2_supplicant();
1384        let mut updates = vec![];
1385        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1386        assert_eq!(updates.len(), 1, "{:?}", updates);
1387        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1388
1389        assert_matches!(supplicant.incomplete_reason(), Error::EapolHandshakeNotStarted);
1390    }
1391
1392    #[test]
1393    fn test_overall_timeout_after_msg2() {
1394        // Create ESS Security Association
1395        let mut supplicant = test_util::get_wpa2_supplicant();
1396        let mut updates = vec![];
1397        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1398        assert_eq!(updates.len(), 1, "{:?}", updates);
1399        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1400
1401        // Send the first frame.
1402        (_, updates) = send_fourway_msg1(&mut supplicant, |_| {});
1403        let _msg2 = test_util::expect_eapol_resp(&updates[..]);
1404
1405        // Acknowledge second frame sent
1406        updates = vec![];
1407        supplicant
1408            .on_eapol_conf(&mut updates, EapolResultCode::Success)
1409            .expect("Failed to send eapol conf");
1410        assert!(updates.is_empty(), "{:?}", updates);
1411
1412        assert_matches!(supplicant.incomplete_reason(), Error::LikelyWrongCredential);
1413    }
1414
1415    #[test]
1416    fn test_overall_timeout_before_conf() {
1417        // Create ESS Security Association
1418        let mut supplicant = test_util::get_wpa2_supplicant();
1419        let mut updates = UpdateSink::default();
1420        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1421        assert_eq!(updates.len(), 1, "{:?}", updates);
1422        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1423
1424        // Send the first frame but don't send a conf in response.
1425        let msg = test_util::get_wpa2_4whs_msg1(&ANONCE[..], |_| {});
1426        supplicant
1427            .on_eapol_frame(&mut updates, eapol::Frame::Key(msg.keyframe()))
1428            .expect("Failed to send eapol frame");
1429        let _msg2 = test_util::expect_eapol_resp(&updates[..]);
1430
1431        assert_matches!(supplicant.incomplete_reason(), Error::NoKeyFrameTransmissionConfirm(0));
1432    }
1433
1434    #[test]
1435    fn test_rsna_retransmission_timeout_retry_without_conf() {
1436        // Create ESS Security Association
1437        let mut supplicant = test_util::get_wpa2_supplicant();
1438        let mut updates = vec![];
1439        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1440        assert_eq!(updates.len(), 1, "{:?}", updates);
1441        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1442
1443        // Send the first frame.
1444        updates = send_fourway_msg1(&mut supplicant, |_| {}).1;
1445        let msg2 = test_util::expect_eapol_resp(&updates[..]);
1446
1447        // Acknowledge second frame sent.
1448        updates = vec![];
1449        supplicant
1450            .on_eapol_conf(&mut updates, EapolResultCode::Success)
1451            .expect("Failed to send eapol conf");
1452        assert!(updates.is_empty(), "{:?}", updates);
1453
1454        // Respond to one timeout, but don't confirm the retry.
1455        updates = vec![];
1456        supplicant
1457            .on_rsna_retransmission_timeout(&mut updates)
1458            .expect("Failed to send key frame timeout");
1459        let msg2_retry = test_util::expect_eapol_resp(&updates[..]);
1460        assert_eq!(msg2, msg2_retry);
1461
1462        // Failure on the next timeout.
1463        updates = vec![];
1464        assert_matches!(
1465            supplicant.on_rsna_retransmission_timeout(&mut updates),
1466            Err(Error::NoKeyFrameTransmissionConfirm(0))
1467        );
1468    }
1469
1470    #[test]
1471    fn test_msg2_out_of_order_conf() {
1472        // Create ESS Security Association
1473        let mut supplicant = test_util::get_wpa2_supplicant();
1474        let mut updates = UpdateSink::default();
1475        let result: Result<(), Error>;
1476        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1477        assert_eq!(updates.len(), 1, "{:?}", updates);
1478        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1479
1480        // Send the first frame but don't send a conf in response.
1481        let msg = test_util::get_wpa2_4whs_msg1(&ANONCE[..], |_| {});
1482        supplicant
1483            .on_eapol_frame(&mut updates, eapol::Frame::Key(msg.keyframe()))
1484            .expect("Failed to send eapol frame");
1485        let msg2 = test_util::expect_eapol_resp(&updates[..]);
1486
1487        // No key frame confirm means that we will buffer updates until the confirm is received.
1488        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
1489        let ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
1490        (result, updates) = send_fourway_msg3(&mut supplicant, &ptk, |_| {});
1491        result.expect("Failed to send msg3");
1492        assert!(updates.is_empty(), "{:?}", updates);
1493
1494        // When confirm is received we receive updates through msg4
1495        updates = UpdateSink::default();
1496        supplicant
1497            .on_eapol_conf(&mut updates, EapolResultCode::Success)
1498            .expect("Failed to send eapol conf");
1499        assert_eq!(updates.len(), 3);
1500        test_util::expect_eapol_resp(&updates[..]);
1501        test_util::expect_reported_ptk(&updates[..]);
1502        test_util::expect_reported_gtk(&updates[..]);
1503
1504        // On another confirm, we receive the remaining updates.
1505        supplicant
1506            .on_eapol_conf(&mut updates, EapolResultCode::Success)
1507            .expect("Failed to send eapol conf");
1508        test_util::expect_reported_status(&updates[..], SecAssocStatus::EssSaEstablished);
1509    }
1510
1511    #[test]
1512    fn test_msg2_no_conf() {
1513        // Create ESS Security Association
1514        let mut supplicant = test_util::get_wpa2_supplicant();
1515        let mut updates = UpdateSink::default();
1516        let result: Result<(), Error>;
1517        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1518        assert_eq!(updates.len(), 1, "{:?}", updates);
1519        test_util::expect_reported_status(&updates[..], SecAssocStatus::PmkSaEstablished);
1520
1521        // Send the first frame but don't send a conf in response.
1522        let msg = test_util::get_wpa2_4whs_msg1(&ANONCE[..], |_| {});
1523        supplicant
1524            .on_eapol_frame(&mut updates, eapol::Frame::Key(msg.keyframe()))
1525            .expect("Failed to send eapol frame");
1526        let msg2 = test_util::expect_eapol_resp(&updates[..]);
1527
1528        // No key frame confirm means that we will buffer updates until the confirm is received.
1529        let snonce = msg2.keyframe().key_frame_fields.key_nonce;
1530        let ptk = test_util::get_ptk(&ANONCE[..], &snonce[..]);
1531        (result, updates) = send_fourway_msg3(&mut supplicant, &ptk, |_| {});
1532        result.expect("Failed to send msg3");
1533        assert!(updates.is_empty(), "{:?}", updates);
1534
1535        // We never receive a confirm, and report this on timeout.
1536        // There are 4 pending updates that we drop after this timeout:
1537        //   * EAPOL message 4
1538        //   * PTK
1539        //   * GTK
1540        //   * ESSSA Established
1541        updates = vec![];
1542        assert_matches!(
1543            supplicant.on_rsna_retransmission_timeout(&mut updates),
1544            Err(Error::NoKeyFrameTransmissionConfirm(4))
1545        );
1546    }
1547
1548    // TODO(hahnr): Add additional tests:
1549    // Invalid messages from Authenticator
1550    // Timeouts
1551    // Nonce reuse
1552    // (in)-compatible protocol and RSNE versions
1553
1554    fn test_eapol_exchange(
1555        supplicant: &mut Supplicant,
1556        authenticator: &mut Authenticator,
1557        msg1: Option<eapol::KeyFrameBuf>,
1558        wpa3: bool,
1559    ) {
1560        // Initiate Authenticator.
1561        let mut a_updates = vec![];
1562        let mut result: Result<(), Error>;
1563        result = authenticator.initiate(&mut a_updates);
1564        assert!(result.is_ok(), "Authenticator failed initiating: {}", result.unwrap_err());
1565
1566        if wpa3 {
1567            assert!(
1568                msg1.is_some(),
1569                "WPA3 EAPOL exchange starting without message constructed immediately after SAE"
1570            );
1571        }
1572        // If msg1 is provided, we expect no updates from the Authenticator. Otherwise, we
1573        // expect the Authenticator to establish the PmkSa and produce msg1.
1574        let msg1 = match msg1 {
1575            Some(msg1) => {
1576                assert_eq!(a_updates.len(), 0, "{:?}", a_updates);
1577                msg1
1578            }
1579            None => {
1580                assert_eq!(a_updates.len(), 2);
1581                test_util::expect_reported_status(&a_updates, SecAssocStatus::PmkSaEstablished);
1582                let resp = test_util::expect_eapol_resp(&a_updates[..]);
1583                authenticator
1584                    .on_eapol_conf(&mut a_updates, EapolResultCode::Success)
1585                    .expect("Failed eapol conf");
1586                resp
1587            }
1588        };
1589
1590        // Send msg #1 to Supplicant and wait for response.
1591        let mut s_updates = vec![];
1592        result = supplicant.on_eapol_frame(&mut s_updates, eapol::Frame::Key(msg1.keyframe()));
1593        assert!(result.is_ok(), "Supplicant failed processing msg #1: {}", result.unwrap_err());
1594        let msg2 = test_util::expect_eapol_resp(&s_updates[..]);
1595        supplicant
1596            .on_eapol_conf(&mut s_updates, EapolResultCode::Success)
1597            .expect("Failed eapol conf");
1598        assert_eq!(s_updates.len(), 1, "{:?}", s_updates);
1599
1600        // Send msg #2 to Authenticator and wait for response.
1601        let mut a_updates = vec![];
1602        result = authenticator.on_eapol_frame(&mut a_updates, eapol::Frame::Key(msg2.keyframe()));
1603        assert!(result.is_ok(), "Authenticator failed processing msg #2: {}", result.unwrap_err());
1604        let msg3 = test_util::expect_eapol_resp(&a_updates[..]);
1605        authenticator
1606            .on_eapol_conf(&mut a_updates, EapolResultCode::Success)
1607            .expect("Failed eapol conf");
1608        assert_eq!(a_updates.len(), 1, "{:?}", a_updates);
1609
1610        // Send msg #3 to Supplicant and wait for response.
1611        let mut s_updates = vec![];
1612        result = supplicant.on_eapol_frame(&mut s_updates, eapol::Frame::Key(msg3.keyframe()));
1613        assert!(result.is_ok(), "Supplicant failed processing msg #3: {}", result.unwrap_err());
1614
1615        let msg4 = test_util::expect_eapol_resp(&s_updates[..]);
1616        let s_ptk = test_util::expect_reported_ptk(&s_updates[..]);
1617        let s_gtk = test_util::expect_reported_gtk(&s_updates[..]);
1618        let s_igtk = if wpa3 {
1619            assert_eq!(s_updates.len(), 4, "{:?}", s_updates);
1620            Some(test_util::expect_reported_igtk(&s_updates[..]))
1621        } else {
1622            assert_eq!(s_updates.len(), 3, "{:?}", s_updates);
1623            None
1624        };
1625
1626        // We shouldn't see the esssa established until a confirm is received.
1627        supplicant
1628            .on_eapol_conf(&mut s_updates, EapolResultCode::Success)
1629            .expect("Failed eapol conf");
1630        test_util::expect_reported_status(&s_updates, SecAssocStatus::EssSaEstablished);
1631
1632        // Send msg #4 to Authenticator.
1633        let mut a_updates = vec![];
1634        result = authenticator.on_eapol_frame(&mut a_updates, eapol::Frame::Key(msg4.keyframe()));
1635        assert!(result.is_ok(), "Authenticator failed processing msg #4: {}", result.unwrap_err());
1636        let a_ptk = test_util::expect_reported_ptk(&a_updates[..]);
1637        let a_gtk = test_util::expect_reported_gtk(&a_updates[..]);
1638
1639        let a_igtk = if wpa3 {
1640            assert_eq!(a_updates.len(), 4, "{:?}", a_updates);
1641            Some(test_util::expect_reported_igtk(&a_updates[..]))
1642        } else {
1643            assert_eq!(a_updates.len(), 3, "{:?}", a_updates);
1644            None
1645        };
1646
1647        test_util::expect_reported_status(&a_updates, SecAssocStatus::EssSaEstablished);
1648
1649        // Verify derived keys match and status reports ESS-SA as established.
1650        assert_eq!(a_ptk, s_ptk);
1651        assert_eq!(a_gtk, s_gtk);
1652        assert_eq!(a_igtk, s_igtk);
1653    }
1654
1655    fn send_eapol_conf(supplicant: &mut Supplicant, updates: &mut UpdateSink) -> Result<(), Error> {
1656        let mut sent_frame = false;
1657        for update in &updates[..] {
1658            if let SecAssocUpdate::TxEapolKeyFrame { .. } = update {
1659                sent_frame = true;
1660            }
1661        }
1662        if sent_frame {
1663            supplicant.on_eapol_conf(updates, EapolResultCode::Success)
1664        } else {
1665            Ok(())
1666        }
1667    }
1668
1669    fn send_fourway_msg1<F>(
1670        supplicant: &mut Supplicant,
1671        msg_modifier: F,
1672    ) -> (Result<(), Error>, UpdateSink)
1673    where
1674        F: Fn(&mut eapol::KeyFrameTx),
1675    {
1676        let msg = test_util::get_wpa2_4whs_msg1(&ANONCE[..], msg_modifier);
1677        let mut updates = UpdateSink::default();
1678        let result = supplicant.on_eapol_frame(&mut updates, eapol::Frame::Key(msg.keyframe()));
1679        let result = result.and_then(|_| send_eapol_conf(supplicant, &mut updates));
1680        (result, updates)
1681    }
1682
1683    fn send_fourway_msg3<F>(
1684        supplicant: &mut Supplicant,
1685        ptk: &Ptk,
1686        msg_modifier: F,
1687    ) -> (Result<(), Error>, UpdateSink)
1688    where
1689        F: Fn(&mut eapol::KeyFrameTx),
1690    {
1691        let msg = test_util::get_wpa2_4whs_msg3(ptk, &ANONCE[..], &GTK, msg_modifier);
1692        let mut updates = UpdateSink::default();
1693        let result = supplicant.on_eapol_frame(&mut updates, eapol::Frame::Key(msg.keyframe()));
1694        let result = result.and_then(|_| send_eapol_conf(supplicant, &mut updates));
1695        (result, updates)
1696    }
1697
1698    fn send_group_key_msg1(
1699        supplicant: &mut Supplicant,
1700        ptk: &Ptk,
1701        gtk: [u8; 16],
1702        key_id: u8,
1703        key_replay_counter: u64,
1704    ) -> (Result<(), Error>, UpdateSink) {
1705        let msg = test_util::get_group_key_hs_msg1(ptk, &gtk[..], key_id, key_replay_counter);
1706        let mut updates = UpdateSink::default();
1707        let result = supplicant.on_eapol_frame(&mut updates, eapol::Frame::Key(msg.keyframe()));
1708        let result = result.and_then(|_| send_eapol_conf(supplicant, &mut updates));
1709        (result, updates)
1710    }
1711
1712    #[test]
1713    fn test_key_confirmed_gtk_replay_prevention() {
1714        let mut supplicant = test_util::get_wpa2_supplicant();
1715        let mut authenticator = test_util::get_wpa2_authenticator();
1716        let mut updates = vec![];
1717        supplicant.start(&mut updates).expect("Failed starting Supplicant");
1718
1719        // Run handshake to install initial GTK.
1720        test_eapol_exchange(&mut supplicant, &mut authenticator, None, false);
1721
1722        // Clear updates from the handshake.
1723        updates.clear();
1724
1725        // Extract the installed GTK from supplicant's ESSSA to get the correct bytes and key ID.
1726        let installed_gtk = match &*supplicant.esssa.gtksa {
1727            Gtksa::Established { installed_gtks, .. } => {
1728                installed_gtks.iter().next().expect("no GTK installed").clone()
1729            }
1730            _ => panic!("GTKSA not established"),
1731        };
1732
1733        // Try to install the SAME GTK but with a DIFFERENT RSC.
1734        let gtk_reinstall = Gtk::from_bytes(
1735            installed_gtk.bytes.clone(),
1736            installed_gtk.cipher().clone(),
1737            installed_gtk.key_id(),
1738            installed_gtk.key_rsc() + 10, // Different RSC
1739        )
1740        .expect("failed to create GTK");
1741
1742        // Call on_key_confirmed.
1743        let result = supplicant.esssa.on_key_confirmed(&mut updates, Key::Gtk(gtk_reinstall));
1744        assert!(result.is_ok());
1745
1746        // Expect NO key update to be yielded because the key is already installed (RSC ignored in equality).
1747        assert!(
1748            updates.is_empty(),
1749            "Expected no key update for reinstalled GTK with different RSC, got: {:?}",
1750            updates
1751        );
1752    }
1753
1754    #[test]
1755    fn test_key_confirmed_igtk_replay_prevention() {
1756        let mut supplicant = test_util::get_wpa3_supplicant();
1757
1758        // Construct an IGTK.
1759        let igtk_bytes = vec![0x11; 16];
1760        let ipn1 = [0xaa; 6];
1761        let cipher = wlan_common::ie::rsn::cipher::CIPHER_BIP_CMAC_128;
1762
1763        let igtk1 = Igtk { igtk: igtk_bytes.clone(), key_id: 4, ipn: ipn1, cipher: cipher.clone() };
1764
1765        let mut updates = vec![];
1766
1767        // First installation should succeed and yield a Key update.
1768        let result = supplicant.esssa.on_key_confirmed(&mut updates, Key::Igtk(igtk1));
1769        assert!(result.is_ok());
1770        assert_eq!(updates.len(), 1);
1771        assert_matches!(updates[0], SecAssocUpdate::Key(Key::Igtk(_)));
1772
1773        updates.clear();
1774
1775        // Second installation with SAME key bytes but DIFFERENT IPN should be ignored
1776        // (no Key update yielded) because we omit IPN from Igtk equality.
1777        let ipn2 = [0xbb; 6];
1778        let igtk2 = Igtk { igtk: igtk_bytes, key_id: 4, ipn: ipn2, cipher };
1779
1780        let result = supplicant.esssa.on_key_confirmed(&mut updates, Key::Igtk(igtk2));
1781        assert!(result.is_ok());
1782        assert!(
1783            updates.is_empty(),
1784            "Expected no key update for reinstalled IGTK with different IPN, got: {:?}",
1785            updates
1786        );
1787    }
1788}