@@ -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+
538692static 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 ;
0 commit comments