From d2f6ce5afd9f6d2587b6b78d82dbe06437a7c96c Mon Sep 17 00:00:00 2001
From: Cirrus <cirrus.neptune@protonmail.com>
Date: Sun, 28 Apr 2024 15:22:11 -0700
Subject: [PATCH 1/3] cyw43: Add function to join WPA2 network with precomputed
 PSK.

With flags = 0 in PassphraseInfo, CYW firmware skips the PBKDF2 PSK
derivation. This makes it possible avoid storing unhashed passwords.

The wpa_passphrase utility may be used to generate this PSK.
---
 cyw43/src/control.rs | 45 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 35 insertions(+), 10 deletions(-)

diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs
index a3808f56f..0b7123eb9 100644
--- a/cyw43/src/control.rs
+++ b/cyw43/src/control.rs
@@ -228,8 +228,12 @@ impl<'a> Control<'a> {
         self.wait_for_join(i).await
     }
 
-    /// Join an protected network with the provided ssid and passphrase.
-    pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> {
+    /// Join a protected network with the provided ssid and [`PassphraseInfo`].
+    pub async fn join_wpa2_passphrase_info(
+        &mut self,
+        ssid: &str,
+        passphrase_info: &mut PassphraseInfo,
+    ) -> Result<(), Error> {
         self.set_iovar_u32("ampdu_ba_wsize", 8).await;
 
         self.ioctl_set_u32(134, 0, 4).await; // wsec = wpa2
@@ -239,14 +243,13 @@ impl<'a> Control<'a> {
 
         Timer::after_millis(100).await;
 
-        let mut pfi = PassphraseInfo {
-            len: passphrase.len() as _,
-            flags: 1,
-            passphrase: [0; 64],
-        };
-        pfi.passphrase[..passphrase.len()].copy_from_slice(passphrase.as_bytes());
-        self.ioctl(IoctlType::Set, IOCTL_CMD_SET_PASSPHRASE, 0, &mut pfi.to_bytes())
-            .await; // WLC_SET_WSEC_PMK
+        self.ioctl(
+            IoctlType::Set,
+            IOCTL_CMD_SET_PASSPHRASE,
+            0,
+            &mut passphrase_info.to_bytes(),
+        )
+        .await; // WLC_SET_WSEC_PMK
 
         self.ioctl_set_u32(20, 0, 1).await; // set_infra = 1
         self.ioctl_set_u32(22, 0, 0).await; // set_auth = 0 (open)
@@ -261,6 +264,28 @@ impl<'a> Control<'a> {
         self.wait_for_join(i).await
     }
 
+    /// Join a protected network with the provided ssid and passphrase.
+    pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> {
+        let mut pfi = PassphraseInfo {
+            len: passphrase.len() as _,
+            flags: 1,
+            passphrase: [0; 64],
+        };
+        pfi.passphrase[..passphrase.len()].copy_from_slice(passphrase.as_bytes());
+        self.join_wpa2_passphrase_info(ssid, &mut pfi).await
+    }
+
+    /// Join a protected network with the provided ssid and precomputed PSK.
+    pub async fn join_wpa2_psk(&mut self, ssid: &str, psk: &[u8; 32]) -> Result<(), Error> {
+        let mut pfi = PassphraseInfo {
+            len: psk.len() as _,
+            flags: 0,
+            passphrase: [0; 64],
+        };
+        pfi.passphrase[..psk.len()].copy_from_slice(psk);
+        self.join_wpa2_passphrase_info(ssid, &mut pfi).await
+    }
+
     async fn wait_for_join(&mut self, i: SsidInfo) -> Result<(), Error> {
         self.events.mask.enable(&[Event::SET_SSID, Event::AUTH]);
         let mut subscriber = self.events.queue.subscriber().unwrap();

From 7432c4069bc5c8d91799a1a4f9c220ec8ffab475 Mon Sep 17 00:00:00 2001
From: Cirrus <cirrus.neptune@protonmail.com>
Date: Sun, 28 Apr 2024 15:34:54 -0700
Subject: [PATCH 2/3] passphrase_info does not have to be passed &mut

---
 cyw43/src/control.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs
index 0b7123eb9..50ef34367 100644
--- a/cyw43/src/control.rs
+++ b/cyw43/src/control.rs
@@ -232,7 +232,7 @@ impl<'a> Control<'a> {
     pub async fn join_wpa2_passphrase_info(
         &mut self,
         ssid: &str,
-        passphrase_info: &mut PassphraseInfo,
+        passphrase_info: &PassphraseInfo,
     ) -> Result<(), Error> {
         self.set_iovar_u32("ampdu_ba_wsize", 8).await;
 
@@ -272,7 +272,7 @@ impl<'a> Control<'a> {
             passphrase: [0; 64],
         };
         pfi.passphrase[..passphrase.len()].copy_from_slice(passphrase.as_bytes());
-        self.join_wpa2_passphrase_info(ssid, &mut pfi).await
+        self.join_wpa2_passphrase_info(ssid, &pfi).await
     }
 
     /// Join a protected network with the provided ssid and precomputed PSK.
@@ -283,7 +283,7 @@ impl<'a> Control<'a> {
             passphrase: [0; 64],
         };
         pfi.passphrase[..psk.len()].copy_from_slice(psk);
-        self.join_wpa2_passphrase_info(ssid, &mut pfi).await
+        self.join_wpa2_passphrase_info(ssid, &pfi).await
     }
 
     async fn wait_for_join(&mut self, i: SsidInfo) -> Result<(), Error> {

From 3db771f4b69c8cc0c6a3a6f19632119bec70cdf4 Mon Sep 17 00:00:00 2001
From: Cirrus <cirrus.neptune@protonmail.com>
Date: Sun, 28 Apr 2024 16:04:52 -0700
Subject: [PATCH 3/3] Make join_wpa2_passphrase_info private

---
 cyw43/src/control.rs | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs
index 50ef34367..cd890c982 100644
--- a/cyw43/src/control.rs
+++ b/cyw43/src/control.rs
@@ -229,11 +229,7 @@ impl<'a> Control<'a> {
     }
 
     /// Join a protected network with the provided ssid and [`PassphraseInfo`].
-    pub async fn join_wpa2_passphrase_info(
-        &mut self,
-        ssid: &str,
-        passphrase_info: &PassphraseInfo,
-    ) -> Result<(), Error> {
+    async fn join_wpa2_passphrase_info(&mut self, ssid: &str, passphrase_info: &PassphraseInfo) -> Result<(), Error> {
         self.set_iovar_u32("ampdu_ba_wsize", 8).await;
 
         self.ioctl_set_u32(134, 0, 4).await; // wsec = wpa2