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