Skip to content

Commit b8eb4fb

Browse files
committed
src/cyw43_ll: parse RSN/WPA IEs in wifi scans results
Add a function (cyw43_ll_wifi_parse_ie_auth) to parse the vendor-specific WPA IEs and RSN IEs received during wifi scans. Define a more complete set of security and authentication flags and redefine the CYW43_AUTH_ macros in terms of these new flags. Return the AP security and authentication capabilities as a 32 bit field in cyw43_ev_scan_result_t.auth_mode (previously an 8 bit field). Note that this change may break compatibility with drivers that use the scan feature. Signed-off-by: Ricardo Cañuelo Navarro <rcn@igalia.com>
1 parent 055d642 commit b8eb4fb

2 files changed

Lines changed: 182 additions & 14 deletions

File tree

src/cyw43_ll.c

Lines changed: 158 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,13 @@ static void cyw43_xxd(size_t len, const uint8_t *buf) {
263263
#define DOT11_IE_ID_RSN (48)
264264
#define DOT11_IE_ID_VENDOR_SPECIFIC (221)
265265
#define WPA_OUI_TYPE1 "\x00\x50\xF2\x01"
266+
#define IEEE_802_11_OUI "\x00\x0F\xAC"
267+
#define IEEE_802_11_OUI_LEN 3
268+
269+
// Field offsets for authentication (RSN/WPA) IEs
270+
#define IE_AUTH_GROUP_CIPHER_OUI_OFFSET 4
271+
#define IE_AUTH_GROUP_CIPHER_OFFSET 7
272+
#define IE_AUTH_PAIRWISE_CIPHER_COUNT_OFFSET 8
266273

267274
#define SLEEP_MAX (50)
268275

@@ -508,21 +515,26 @@ typedef struct _cyw43_scan_result_internal_t {
508515
uint16_t capability;
509516
uint8_t ssid_len;
510517
uint8_t ssid[32];
518+
uint8_t pad1[1];
511519
uint32_t rateset_count;
512520
uint8_t rateset_rates[16];
513521
uint16_t chanspec;
514522
uint16_t atim_window;
515523
uint8_t dtim_period;
524+
uint8_t pad2[1];
516525
int16_t rssi;
517526
int8_t phy_noise;
518527
uint8_t n_cap;
528+
uint8_t pad3[2];
519529
uint32_t nbss_cap;
520530
uint8_t ctl_ch;
531+
uint8_t pad4[3];
521532
uint32_t reserved32[1];
522533
uint8_t flags;
523-
uint8_t reserved[3];
534+
uint8_t pad5[3];
524535
uint8_t basic_mcs[16];
525536
uint16_t ie_offset;
537+
uint8_t pad6[2];
526538
uint32_t ie_length;
527539
int16_t SNR;
528540
} cyw43_scan_result_internal_t;
@@ -535,6 +547,148 @@ static inline uint16_t cyw43_be16toh(uint16_t x) {
535547
return (x >> 8) | (x << 8);
536548
}
537549

550+
/* IEEE 802.11 AKM suites */
551+
typedef enum
552+
{
553+
AKM_RESERVED,
554+
AKM_8021X, /* WPA2 enterprise */
555+
AKM_PSK, /* WPA2 PSK */
556+
AKM_FT_8021X, /* 802.11r Fast Roaming enterprise */
557+
AKM_FT_PSK, /* 802.11r Fast Roaming PSK */
558+
AKM_8021X_SHA256,
559+
AKM_PSK_SHA256,
560+
AKM_TDLS, /* Tunneled Direct Link Setup */
561+
AKM_SAE_SHA256,
562+
AKM_FT_SAE_SHA256,
563+
AKM_AP_PEER_KEY_SHA256,
564+
AKM_SUITEB_8021X_HMAC_SHA256,
565+
AKM_SUITEB_8021X_HMAC_SHA384,
566+
AKM_SUITEB_FT_8021X_HMAC_SHA384,
567+
} akm_suite_t;
568+
569+
/* IEEE 802.11 Cipher suites */
570+
typedef enum
571+
{
572+
CIPHER_GROUP, /* Use group cipher suite */
573+
CIPHER_WEP_40, /* WEP-40 */
574+
CIPHER_TKIP, /* TKIP */
575+
CIPHER_RESERVED, /* Reserved */
576+
CIPHER_CCMP_128, /* CCMP-128 - default pairwise and group cipher suite */
577+
CIPHER_WEP_104, /* WEP-104 - also known as WEP-128 */
578+
CIPHER_BIP_CMAC_128, /* BIP-CMAC-128 - default management frame cipher suite */
579+
CIPHER_GROUP_DISALLOWED, /* Group address traffic not allowed */
580+
CIPHER_GCMP_128, /* GCMP-128 - default for 60 GHz STAs */
581+
CIPHER_GCMP_256, /* GCMP-256 - introduced for Suite B */
582+
CIPHER_CCMP_256, /* CCMP-256 - introduced for suite B */
583+
CIPHER_BIP_GMAC_128, /* BIP-GMAC-128 - introduced for suite B */
584+
CIPHER_BIP_GMAC_256, /* BIP-GMAC-256 - introduced for suite B */
585+
CIPHER_BIP_CMAC_256, /* BIP-CMAC-256 - introduced for suite B */
586+
} cipher_t;
587+
588+
/*
589+
* Parses an RSN or vendor-specific WPA IE.
590+
*
591+
* Parameters:
592+
* ie: the buffer containing the Information Element.
593+
* wpa: 1 if the IE is a vendor-specific WPA IE, 0 if it's an RSN IE.
594+
*
595+
* Returns the security and authentication capabilities encoded in a
596+
* 32-bit field (see the CYW43_AUTH_ macros), or 0 if it found an error
597+
* parsing the IE.
598+
*/
599+
static uint32_t cyw43_ll_wifi_parse_ie_auth(uint8_t *ie, int wpa) {
600+
uint32_t security = 0;
601+
char *oui;
602+
int pairwise_cipher_cnt;
603+
int akm_cnt;
604+
int idx;
605+
606+
if (wpa) {
607+
security = WPA_SECURITY;
608+
oui = WPA_OUI_TYPE1;
609+
} else {
610+
oui = IEEE_802_11_OUI;
611+
}
612+
613+
/* Group cipher suite */
614+
if (memcmp(&ie[IE_AUTH_GROUP_CIPHER_OUI_OFFSET], oui, IEEE_802_11_OUI_LEN)) {
615+
return 0;
616+
}
617+
switch (ie[IE_AUTH_GROUP_CIPHER_OFFSET]) {
618+
case CIPHER_TKIP:
619+
security |= TKIP_ENABLED;
620+
break;
621+
case CIPHER_CCMP_128:
622+
security |= AES_ENABLED;
623+
break;
624+
default:
625+
CYW43_WARN("Unsupported group cipher %d\n", ie[IE_AUTH_GROUP_CIPHER_OFFSET]);
626+
}
627+
628+
/* Pairwise cipher suites */
629+
pairwise_cipher_cnt = *(uint16_t*)(&ie[IE_AUTH_PAIRWISE_CIPHER_COUNT_OFFSET]);
630+
idx = IE_AUTH_PAIRWISE_CIPHER_COUNT_OFFSET + 2;
631+
for (int i = 0; i < pairwise_cipher_cnt; i++) {
632+
if (memcmp(&ie[idx], oui, IEEE_802_11_OUI_LEN)) {
633+
CYW43_WARN("Error parsing management IE: wrong OUI in pairwise cipher\n");
634+
return 0;
635+
}
636+
idx += IEEE_802_11_OUI_LEN;
637+
switch (ie[idx]) {
638+
case CIPHER_TKIP:
639+
security |= TKIP_ENABLED;
640+
break;
641+
case CIPHER_CCMP_128:
642+
security |= AES_ENABLED;
643+
break;
644+
default:
645+
CYW43_WARN("Unsupported pairwise cipher %d\n", ie[idx]);
646+
}
647+
idx++;
648+
}
649+
650+
/* AKM suites */
651+
akm_cnt = *(uint16_t*)(&ie[idx]);
652+
idx += 2;
653+
for (int i = 0; i < akm_cnt; i++) {
654+
if (memcmp(&ie[idx], oui, IEEE_802_11_OUI_LEN)) {
655+
CYW43_WARN("Error parsing management IE: wrong OUI in AKM suite\n");
656+
return 0;
657+
}
658+
idx += IEEE_802_11_OUI_LEN;
659+
switch (ie[idx]) {
660+
case AKM_PSK:
661+
security |= WPA2_SECURITY;
662+
break;
663+
case AKM_PSK_SHA256:
664+
security |= WPA2_SECURITY | WPA2_SHA256_SECURITY;
665+
break;
666+
case AKM_SAE_SHA256:
667+
security |= WPA3_SECURITY;
668+
break;
669+
case AKM_8021X:
670+
if (wpa) {
671+
security |= ENTERPRISE_ENABLED;
672+
} else {
673+
security |= WPA2_SECURITY | ENTERPRISE_ENABLED;
674+
}
675+
break;
676+
case AKM_FT_8021X:
677+
security |= WPA2_SECURITY | FBT_ENABLED | ENTERPRISE_ENABLED;
678+
break;
679+
case AKM_FT_PSK:
680+
security |= WPA2_SECURITY | FBT_ENABLED;
681+
break;
682+
default:
683+
CYW43_WARN("Unsupported group cipher %d\n", ie_rsn[idx]);
684+
}
685+
idx++;
686+
}
687+
688+
return security;
689+
}
690+
691+
538692
static void cyw43_ll_wifi_parse_scan_result(cyw43_async_event_t *ev) {
539693
struct _scan_result_t {
540694
uint32_t buflen;
@@ -572,15 +726,13 @@ static void cyw43_ll_wifi_parse_scan_result(cyw43_async_event_t *ev) {
572726
}
573727
int security = 0;// OPEN
574728
if (ie_rsn != NULL) {
575-
// TODO need to parse the IE to check for TKIP, AES and enterprise modes
576-
security |= 4;// WPA2;
729+
security = cyw43_ll_wifi_parse_ie_auth(ie_rsn, 0);
577730
}
578731
if (ie_wpa != NULL) {
579-
// TODO need to parse the IE to check for TKIP, AES and enterprise modes
580-
security |= 2;// WPA;
732+
security = cyw43_ll_wifi_parse_ie_auth(ie_wpa, 1);
581733
}
582734
if (scan_res->bss.capability & DOT11_CAP_PRIVACY) {
583-
security |= 1;// WEP_PSK;
735+
security |= WEP_ENABLED;
584736
}
585737

586738
ev->u.scan_result.channel &= 0xff;

src/cyw43_ll.h

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,18 +161,33 @@
161161
#define CYW43_REASON_SUP_DEAUTH (14) // received FC_DEAUTH
162162
#define CYW43_REASON_SUP_WPA_PSK_TMO (15) // WPA PSK 4-way handshake timeout
163163

164+
// Security and authentication flags
165+
#define WEP_ENABLED 0x0001
166+
#define TKIP_ENABLED 0x0002
167+
#define AES_ENABLED 0x0004
168+
#define SHARED_ENABLED 0x00008000
169+
#define WPA_SECURITY 0x00200000
170+
#define WPA2_SECURITY 0x00400000
171+
#define WPA2_SHA256_SECURITY 0x00800000
172+
#define WPA3_SECURITY 0x01000000
173+
#define ENTERPRISE_ENABLED 0x02000000
174+
#define WPS_ENABLED 0x10000000
175+
#define IBSS_ENABLED 0x20000000
176+
#define FBT_ENABLED 0x40000000
177+
164178
/**
165179
* \name Authorization types
166180
* \brief Used when setting up an access point, or connecting to an access point
167181
* \anchor CYW43_AUTH_
168182
*/
169183
//!\{
170-
#define CYW43_AUTH_OPEN (0) ///< No authorisation required (open)
171-
#define CYW43_AUTH_WPA_TKIP_PSK (0x00200002) ///< WPA authorisation
172-
#define CYW43_AUTH_WPA2_AES_PSK (0x00400004) ///< WPA2 authorisation (preferred)
173-
#define CYW43_AUTH_WPA2_MIXED_PSK (0x00400006) ///< WPA2/WPA mixed authorisation
174-
#define CYW43_AUTH_WPA3_SAE_AES_PSK (0x01000004) ///< WPA3 AES authorisation
175-
#define CYW43_AUTH_WPA3_WPA2_AES_PSK (0x01400004) ///< WPA2/WPA3 authorisation
184+
#define CYW43_AUTH_OPEN (0) ///< No authorisation required (open)
185+
#define CYW43_AUTH_WEP_PSK (WEP_ENABLED) ///< WEP PSK Security with open authentication
186+
#define CYW43_AUTH_WPA_TKIP_PSK (WPA_SECURITY | TKIP_ENABLED) ///< WPA authorisation
187+
#define CYW43_AUTH_WPA2_AES_PSK (WPA2_SECURITY | AES_ENABLED) ///< WPA2 authorisation (preferred)
188+
#define CYW43_AUTH_WPA2_MIXED_PSK (WPA2_SECURITY | AES_ENABLED | TKIP_ENABLED) ///< WPA2/WPA mixed authorisation
189+
#define CYW43_AUTH_WPA3_SAE_AES_PSK (WPA3_SECURITY | AES_ENABLED) ///< WPA3 AES authorisation
190+
#define CYW43_AUTH_WPA3_WPA2_AES_PSK (WPA3_SECURITY | WPA2_SECURITY | AES_ENABLED) ///< WPA2/WPA3 authorisation
176191
//!\}
177192

178193
/*!
@@ -221,9 +236,10 @@ typedef struct _cyw43_ev_scan_result_t {
221236
uint8_t ssid[32]; ///< wlan access point name
222237
uint32_t _2[5];
223238
uint16_t channel; ///< wifi channel
224-
uint16_t _3;
225-
uint8_t auth_mode; ///< wifi auth mode \ref CYW43_AUTH_
239+
uint8_t _3[4];
226240
int16_t rssi; ///< signal strength
241+
uint8_t _4[12];
242+
uint32_t auth_mode; ///< security and authentication flags
227243
} cyw43_ev_scan_result_t;
228244
//!\}
229245

0 commit comments

Comments
 (0)