git: 1116e8b95c60 - main - net80211: add a new field specifically for announcing specific ciphers

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Thu, 09 May 2024 00:49:41 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=1116e8b95c601ddaac2feb4ab0904f77801a520f

commit 1116e8b95c601ddaac2feb4ab0904f77801a520f
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2024-04-17 01:53:52 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2024-05-09 00:48:40 +0000

    net80211: add a new field specifically for announcing specific ciphers
    
    This dates way, way back with the original net80211 support w/ atheros chips.
    
    The earliest chip (AR5210) had limitations supporting software encryption.
    It only had the four WEP slots, and not any keycache entries.  So when
    trying to do CCMP/TKIP encryption would be enabled and the key slots
    would have nothing useful in them, resulting in garbage encryption/decryption.
    
    I changed this back in 2012 to disable supporting hardware WEP for AR5210
    so if_ath(4) / net80211 crypto is all done in software and yes,
    I could do CCMP/TKIP on AR5210 in software.
    
    Fast-forward to newer-ish hardware - the Qualcomm 11ac hardware.
    Those also don't support pass-through keycache slots! Well, the hardware
    does at that layer, but then there's a whole offload data path encap/decap
    layer that's turning the frames from raw wifi into ethernet frames (for
    "dumb" AP behaviours) or "wifi direct" frames (ie, "windows".)
    This hides a bunch of header frame contents required for doing the software
    encryption / decryption path.
    
    But then if you enable the raw transmit/receive frame format it ALSO
    bypasses the hardware encryption/decryption engine!
    
    So for those NICs:
    
    * If you want to do encryption, you can only use the firmware supported
      ciphers w/ wifi direct or ethernet;
    * If you want to use software encrypt/decrypt, you MUST disable all encryption
      and instead use 100% software encryption.
    
    The wpa_supplicant bsd driver code has a specific comment about this and
    flips on supporting WEP/TKIP/CCMP, which is understandable but it doesn't
    fix the ACTUAL intention of all of this stuff.
    
    So:
    
    * create a new field, ic_sw_cryptocaps
    * populate it with the default supported set of ciphers for net80211
      (right now wep, tkip, ccmp)
    * Communicate the combination of both ic_sw_cryptocaps and ic_cryptocaps
      to wpa_supplicant via the relevant devcap ioctl.
    * Update manpage.
    
    I'll follow this up with a driver_bsd.c change in wpa_supplicant to
    trust this again, and then start adding the other cipher support there.
    
    Differential Revision:  https://reviews.freebsd.org/D44820
---
 share/man/man9/ieee80211.9      |  4 +++-
 sys/net80211/ieee80211_crypto.c | 12 ++++++++++++
 sys/net80211/ieee80211_ioctl.c  |  6 +++++-
 sys/net80211/ieee80211_ioctl.h  |  4 ++--
 sys/net80211/ieee80211_var.h    |  4 +++-
 5 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/share/man/man9/ieee80211.9 b/share/man/man9/ieee80211.9
index 100b4e7540a5..40c8c243a77c 100644
--- a/share/man/man9/ieee80211.9
+++ b/share/man/man9/ieee80211.9
@@ -25,7 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd January 26, 2021
+.Dd April 24, 2024
 .Dt IEEE80211 9
 .Os
 .Sh NAME
@@ -514,6 +514,8 @@ General capabilities are specified by
 .Vt ic_caps .
 Hardware cryptographic capabilities are specified by
 .Vt ic_cryptocaps .
+Software cryptographic capabilities are specified by
+.Vt ic_sw_cryptocaps .
 802.11n capabilities, if any, are specified by
 .Vt ic_htcaps .
 The
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index 6a1182b52480..ff78600e2f0e 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -142,6 +142,18 @@ ieee80211_crypto_attach(struct ieee80211com *ic)
 {
 	/* NB: we assume everything is pre-zero'd */
 	ciphers[IEEE80211_CIPHER_NONE] = &ieee80211_cipher_none;
+
+	/*
+	 * Default set of net80211 supported ciphers.
+	 *
+	 * These are the default set that all drivers are expected to
+	 * support, either/or in hardware and software.
+	 *
+	 * Drivers can add their own support to this and the
+	 * hardware cipher list (ic_cryptocaps.)
+	 */
+	ic->ic_sw_cryptocaps = IEEE80211_CRYPTO_WEP |
+	    IEEE80211_CRYPTO_TKIP | IEEE80211_CRYPTO_AES_CCM;
 }
 
 /*
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index d5b242b679d0..c0ba19b5db89 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -709,7 +709,11 @@ ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
 	if (dc == NULL)
 		return ENOMEM;
 	dc->dc_drivercaps = ic->ic_caps;
-	dc->dc_cryptocaps = ic->ic_cryptocaps;
+	/*
+	 * Announce the set of both hardware and software supported
+	 * ciphers.
+	 */
+	dc->dc_cryptocaps = ic->ic_cryptocaps | ic->ic_sw_cryptocaps;
 	dc->dc_htcaps = ic->ic_htcaps;
 	dc->dc_vhtcaps = ic->ic_vht_cap.vht_cap_info;
 	ci = &dc->dc_chaninfo;
diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h
index 58080025b5a9..18152495c499 100644
--- a/sys/net80211/ieee80211_ioctl.h
+++ b/sys/net80211/ieee80211_ioctl.h
@@ -551,13 +551,13 @@ struct ieee80211_regdomain_req {
 	IEEE80211_REGDOMAIN_SIZE((_req)->chaninfo.ic_nchans)
 
 /*
- * Get driver capabilities.  Driver, hardware crypto, and
+ * Get driver capabilities.  Driver, hardware/software crypto, and
  * HT/802.11n capabilities, and a table that describes what
  * the radio can do.
  */
 struct ieee80211_devcaps_req {
 	uint32_t	dc_drivercaps;		/* general driver caps */
-	uint32_t	dc_cryptocaps;		/* hardware crypto support */
+	uint32_t	dc_cryptocaps;		/* software + hardware crypto support */
 	uint32_t	dc_htcaps;		/* HT/802.11n support */
 	uint32_t	dc_vhtcaps;		/* VHT/802.11ac capabilities */
 	struct ieee80211req_chaninfo dc_chaninfo;
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index 4c9cdcbfccd9..2c13113b92a1 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -163,7 +163,9 @@ struct ieee80211com {
 	uint32_t		ic_caps;	/* capabilities */
 	uint32_t		ic_htcaps;	/* HT capabilities */
 	uint32_t		ic_htextcaps;	/* HT extended capabilities */
-	uint32_t		ic_cryptocaps;	/* crypto capabilities */
+				/* driver-supported software crypto caps */
+	uint32_t		ic_sw_cryptocaps;
+	uint32_t		ic_cryptocaps;	/* hardware crypto caps */
 						/* set of mode capabilities */
 	uint8_t			ic_modecaps[IEEE80211_MODE_BYTES];
 	uint8_t			ic_promisc;	/* vap's needing promisc mode */