[wlan][mlme] Adds validation for SAE auth frames
Maintains the old c-binding interface for compatibility with the legacy C++
MLME.
Bug: 40006
Test: Update unit tests
Change-Id: I595406401906676807850fefeb35729edb102232
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/339304
Commit-Queue: Dylan Swiggett <swiggett@google.com>
Reviewed-by: Eric Wang <eyw@google.com>
Testability-Review: Eric Wang <eyw@google.com>
diff --git a/src/connectivity/wlan/lib/mlme/rust/c-binding/bindings.h b/src/connectivity/wlan/lib/mlme/rust/c-binding/bindings.h
index afbeae4..ea6ae6db 100644
--- a/src/connectivity/wlan/lib/mlme/rust/c-binding/bindings.h
+++ b/src/connectivity/wlan/lib/mlme/rust/c-binding/bindings.h
@@ -241,8 +241,6 @@
extern "C" int32_t client_mlme_handle_eth_frame(wlan_client_mlme_t *mlme, wlan_span_t frame);
-extern "C" int32_t mlme_is_valid_open_auth_resp(wlan_span_t auth_resp);
-
extern "C" void mlme_sequence_manager_delete(mlme_sequence_manager_t *mgr);
extern "C" mlme_sequence_manager_t *mlme_sequence_manager_new(void);
diff --git a/src/connectivity/wlan/lib/mlme/rust/c-binding/src/auth.rs b/src/connectivity/wlan/lib/mlme/rust/c-binding/src/auth.rs
deleted file mode 100644
index 09f1bb7e..0000000
--- a/src/connectivity/wlan/lib/mlme/rust/c-binding/src/auth.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2019 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use {
- fuchsia_zircon::sys as zx, log::error, wlan_common::mac, wlan_mlme::auth,
- zerocopy::LayoutVerified,
-};
-
-#[no_mangle]
-pub extern "C" fn mlme_is_valid_open_auth_resp(auth_resp: wlan_span::CSpan<'_>) -> i32 {
- // `slice` does not outlive `auth_resp`.
- let slice: &[u8] = auth_resp.into();
- match LayoutVerified::<_, mac::AuthHdr>::new_unaligned_from_prefix(slice) {
- Some((auth_hdr, _)) => {
- unwrap_or_bail!(auth::is_valid_open_ap_resp(&auth_hdr), zx::ZX_ERR_IO_REFUSED);
- zx::ZX_OK
- }
- None => zx::ZX_ERR_IO_REFUSED,
- }
-}
diff --git a/src/connectivity/wlan/lib/mlme/rust/c-binding/src/lib.rs b/src/connectivity/wlan/lib/mlme/rust/c-binding/src/lib.rs
index 5c79839..356ecf03 100644
--- a/src/connectivity/wlan/lib/mlme/rust/c-binding/src/lib.rs
+++ b/src/connectivity/wlan/lib/mlme/rust/c-binding/src/lib.rs
@@ -6,10 +6,6 @@
// Explicitly declare usage for cbindgen.
-#[macro_use]
-pub mod utils;
-
pub mod ap;
-pub mod auth;
pub mod client;
pub mod sequence;
diff --git a/src/connectivity/wlan/lib/mlme/rust/c-binding/src/utils.rs b/src/connectivity/wlan/lib/mlme/rust/c-binding/src/utils.rs
deleted file mode 100644
index fa70df1..0000000
--- a/src/connectivity/wlan/lib/mlme/rust/c-binding/src/utils.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2019 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/// Unwraps a given `Result` yielding content of `Ok`.
-/// If Result carries an `Err` its content will be logged and the function will early return with
-/// the raw value of the given `zx::Status`.
-/// This macro is comparable to Rust's try macro.
-macro_rules! unwrap_or_bail {
- ($result:expr, $e:expr) => {
- match $result {
- Ok(x) => x,
- Err(e) => {
- error!("error: {}", e);
- return $e.into();
- }
- }
- };
-}
diff --git a/src/connectivity/wlan/lib/mlme/rust/src/auth.rs b/src/connectivity/wlan/lib/mlme/rust/src/auth.rs
index 4edfd38..82c3aff 100644
--- a/src/connectivity/wlan/lib/mlme/rust/src/auth.rs
+++ b/src/connectivity/wlan/lib/mlme/rust/src/auth.rs
@@ -3,7 +3,7 @@
// found in the LICENSE file.
use {
- anyhow::{ensure, Error},
+ anyhow::{bail, ensure, Error},
wlan_common::mac,
};
@@ -15,52 +15,91 @@
}
}
-/// Validates whether a given authentication header is a valid response to an open authentication
+#[derive(Debug)]
+pub enum ValidFrame {
+ Open,
+ SaeCommit,
+ SaeConfirm,
+}
+
+/// Validates whether a given authentication header is a valid response to an authentication
/// request.
-pub fn is_valid_open_ap_resp(auth: &mac::AuthHdr) -> Result<(), Error> {
- ensure!(
- { auth.auth_alg_num } == mac::AuthAlgorithmNumber::OPEN,
- "invalid auth_alg_num: {}",
- { auth.auth_alg_num }.0
- );
- ensure!(auth.auth_txn_seq_num == 2, "invalid auth_txn_seq_num: {}", { auth.auth_txn_seq_num });
+pub fn validate_ap_resp(auth: &mac::AuthHdr) -> Result<ValidFrame, Error> {
ensure!(
{ auth.status_code } == mac::StatusCode::SUCCESS,
"invalid status_code: {}",
{ auth.status_code }.0
);
- Ok(())
+ match auth.auth_alg_num {
+ mac::AuthAlgorithmNumber::OPEN => {
+ ensure!(auth.auth_txn_seq_num == 2, "invalid auth_txn_seq_num: {}", {
+ auth.auth_txn_seq_num
+ });
+ Ok(ValidFrame::Open)
+ }
+ mac::AuthAlgorithmNumber::SAE => match auth.auth_txn_seq_num {
+ 1 => Ok(ValidFrame::SaeCommit),
+ 2 => Ok(ValidFrame::SaeConfirm),
+ _ => bail!("invalid auth_txn_seq_num: {}", { auth.auth_txn_seq_num }),
+ },
+ _ => bail!("invalid auth_alg_num: {}", { auth.auth_alg_num }.0),
+ }
}
#[cfg(test)]
mod tests {
- use super::*;
+ use {super::*, wlan_common::assert_variant};
- fn make_valid_auth_resp() -> mac::AuthHdr {
+ fn make_valid_auth_resp(frame_type: ValidFrame) -> mac::AuthHdr {
mac::AuthHdr {
- auth_alg_num: mac::AuthAlgorithmNumber::OPEN,
- auth_txn_seq_num: 2,
+ auth_alg_num: match frame_type {
+ ValidFrame::Open => mac::AuthAlgorithmNumber::OPEN,
+ ValidFrame::SaeCommit | ValidFrame::SaeConfirm => mac::AuthAlgorithmNumber::SAE,
+ },
+ auth_txn_seq_num: match frame_type {
+ ValidFrame::SaeCommit => 1,
+ ValidFrame::Open | ValidFrame::SaeConfirm => 2,
+ },
status_code: mac::StatusCode::SUCCESS,
}
}
#[test]
- fn valid_open_auth_resp() {
- assert!(is_valid_open_ap_resp(&make_valid_auth_resp()).is_ok());
+ fn valid_auth_resp() {
+ assert_variant!(
+ validate_ap_resp(&make_valid_auth_resp(ValidFrame::Open)),
+ Ok(ValidFrame::Open)
+ );
+ assert_variant!(
+ validate_ap_resp(&make_valid_auth_resp(ValidFrame::SaeCommit)),
+ Ok(ValidFrame::SaeCommit)
+ );
+ assert_variant!(
+ validate_ap_resp(&make_valid_auth_resp(ValidFrame::SaeConfirm)),
+ Ok(ValidFrame::SaeConfirm)
+ );
}
#[test]
- fn invalid_open_auth_resp() {
- let mut auth_hdr = make_valid_auth_resp();
+ fn invalid_auth_resp() {
+ let mut auth_hdr = make_valid_auth_resp(ValidFrame::Open);
auth_hdr.auth_alg_num = mac::AuthAlgorithmNumber::FAST_BSS_TRANSITION;
- assert!(is_valid_open_ap_resp(&auth_hdr).is_err());
+ assert_variant!(validate_ap_resp(&auth_hdr), Err(_));
- let mut auth_hdr = make_valid_auth_resp();
+ let mut auth_hdr = make_valid_auth_resp(ValidFrame::Open);
auth_hdr.auth_txn_seq_num = 1;
- assert!(is_valid_open_ap_resp(&auth_hdr).is_err());
+ assert_variant!(validate_ap_resp(&auth_hdr), Err(_));
- let mut auth_hdr = make_valid_auth_resp();
+ let mut auth_hdr = make_valid_auth_resp(ValidFrame::Open);
auth_hdr.status_code = mac::StatusCode::REFUSED;
- assert!(is_valid_open_ap_resp(&auth_hdr).is_err());
+ assert_variant!(validate_ap_resp(&auth_hdr), Err(_));
+
+ let mut auth_hdr = make_valid_auth_resp(ValidFrame::SaeCommit);
+ auth_hdr.auth_txn_seq_num = 4;
+ assert_variant!(validate_ap_resp(&auth_hdr), Err(_));
+
+ let mut auth_hdr = make_valid_auth_resp(ValidFrame::SaeCommit);
+ auth_hdr.status_code = mac::StatusCode::REFUSED;
+ assert_variant!(validate_ap_resp(&auth_hdr), Err(_));
}
}
diff --git a/src/connectivity/wlan/lib/mlme/rust/src/client/state.rs b/src/connectivity/wlan/lib/mlme/rust/src/client/state.rs
index 01533f5..5fdc490 100644
--- a/src/connectivity/wlan/lib/mlme/rust/src/client/state.rs
+++ b/src/connectivity/wlan/lib/mlme/rust/src/client/state.rs
@@ -97,13 +97,17 @@
fn on_auth_frame(&self, sta: &mut BoundClient<'_>, auth_hdr: &mac::AuthHdr) -> Result<(), ()> {
sta.ctx.timer.cancel_event(self.timeout);
- match auth::is_valid_open_ap_resp(auth_hdr) {
- Ok(()) => {
+ let frame_type = auth::validate_ap_resp(auth_hdr).map_err(|e| {
+ error!("authentication with BSS failed: {}", e);
+ sta.send_authenticate_conf(fidl_mlme::AuthenticateResultCodes::AuthenticationRejected);
+ })?;
+ match frame_type {
+ auth::ValidFrame::Open => {
sta.send_authenticate_conf(fidl_mlme::AuthenticateResultCodes::Success);
Ok(())
}
- Err(e) => {
- error!("authentication with BSS failed: {}", e);
+ _ => {
+ error!("authentication with BSS failed: unhandled auth type {:?}", frame_type);
sta.send_authenticate_conf(
fidl_mlme::AuthenticateResultCodes::AuthenticationRejected,
);
@@ -746,6 +750,9 @@
Authenticated => Associating,
Associating => Associated,
+ // Multi-step authentication (SAE):
+ Authenticating => Authenticating,
+
// Timeout:
Authenticating => Joined,
Associating => Authenticated,