Skip to content

Commit 619da83

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 619da83

2 files changed

Lines changed: 176 additions & 13 deletions

File tree

src/cyw43_ll.c

Lines changed: 152 additions & 5 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

@@ -535,6 +542,148 @@ static inline uint16_t cyw43_be16toh(uint16_t x) {
535542
return (x >> 8) | (x << 8);
536543
}
537544

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

586733
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[3];
226240
int16_t rssi; ///< signal strength
241+
uint8_t _4[7];
242+
uint32_t auth_mode; ///< security and authentication flags
227243
} cyw43_ev_scan_result_t;
228244
//!\}
229245

0 commit comments

Comments
 (0)