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