@@ -1771,7 +1771,8 @@ static const struct {
17711771 { "EAP-SUITE-B-192" , 4 , IWINFO_KMGMT_8021x },
17721772 { "EAP-SUITE-B" , 4 , IWINFO_KMGMT_8021x },
17731773 { "EAP-SHA384" , 4 , IWINFO_KMGMT_8021x },
1774- { "EAP-SHA256" , 0 , IWINFO_KMGMT_8021x },
1774+ /* SHA256 counts as WPA3 as long as pmf is enabled; we check this below. */
1775+ { "EAP-SHA256" , 4 , IWINFO_KMGMT_8021x },
17751776 { "PSK-SHA256" , 0 , IWINFO_KMGMT_PSK },
17761777 { "NONE" , 0 , IWINFO_KMGMT_NONE },
17771778 { "None" , 0 , IWINFO_KMGMT_NONE },
@@ -1782,7 +1783,7 @@ static const struct {
17821783};
17831784
17841785static void parse_wpa_suites (const char * str , int defversion ,
1785- uint8_t * versions , uint8_t * suites )
1786+ uint8_t * versions , uint8_t * suites , int pmf )
17861787{
17871788 size_t l ;
17881789 int i , version ;
@@ -1817,6 +1818,35 @@ static void parse_wpa_suites(const char *str, int defversion,
18171818
18181819 p = q + strspn (q , sep );
18191820 }
1821+
1822+ /* Handle ieee80211w/pmf (management frame protection).
1823+ *
1824+ * Strictly:
1825+ * ieee80211w=2 && wpa_key_mgmt=WPA-EAP-SHA256
1826+ * => WPA3-Enterprise
1827+ * ieee80211w=1 && wpa_key_mgmt=WPA-EAP WPA-EAP-SHA256
1828+ * => WPA3-Enterprise transition
1829+ *
1830+ * Here we just try to aggressively downgrade (i.e. if no pmf,
1831+ * not WPA3-Enterprise, and if not required then WPA2/WPA3).
1832+ * This _will_ allow some invalid configurations through
1833+ * and count certain undefined configurations as WPA2/WPA3
1834+ * (e.g. WPA-EAP-SHA256 only and ieee80211=1).
1835+ */
1836+ if ((* suites & IWINFO_KMGMT_8021x ) && (* versions & 4 ))
1837+ switch (pmf )
1838+ {
1839+ case 0 : /* if disabled, it's not WPA3 */
1840+ * versions &= ~4 ;
1841+ * versions |= defversion ;
1842+ break ;
1843+ case 1 : /* if not required, not only WPA3 */
1844+ * versions |= defversion ;
1845+ break ;
1846+ case 2 : /* pmf required */
1847+ default : /* if no pmf info - e.g. from scan */
1848+ break ;
1849+ }
18201850}
18211851
18221852static const struct {
@@ -1871,6 +1901,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
18711901 uint8_t wpa_version = 0 ;
18721902 char wpa [2 ], wpa_key_mgmt [64 ], wpa_pairwise [16 ], wpa_groupwise [16 ];
18731903 char auth_algs [2 ], wep_key0 [27 ], wep_key1 [27 ], wep_key2 [27 ], wep_key3 [27 ];
1904+ char ieee80211w [2 ], pmf [2 ];
18741905 char mode [16 ];
18751906
18761907 struct iwinfo_crypto_entry * c = (struct iwinfo_crypto_entry * )buf ;
@@ -1880,6 +1911,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
18801911 "pairwise_cipher" , wpa_pairwise , sizeof (wpa_pairwise ),
18811912 "group_cipher" , wpa_groupwise , sizeof (wpa_groupwise ),
18821913 "key_mgmt" , wpa_key_mgmt , sizeof (wpa_key_mgmt ),
1914+ "pmf" , pmf , sizeof (pmf ),
18831915 "mode" , mode , sizeof (mode )))
18841916 {
18851917 /* WEP or Open */
@@ -1928,7 +1960,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
19281960 wpa_version = 1 ;
19291961 }
19301962
1931- parse_wpa_suites (p , wpa_version , & c -> wpa_version , & c -> auth_suites );
1963+ parse_wpa_suites (p , wpa_version , & c -> wpa_version , & c -> auth_suites , atoi ( pmf ) );
19321964
19331965 c -> enabled = !!(c -> wpa_version && c -> auth_suites );
19341966 }
@@ -1941,6 +1973,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
19411973 "wpa" , wpa , sizeof (wpa ),
19421974 "wpa_key_mgmt" , wpa_key_mgmt , sizeof (wpa_key_mgmt ),
19431975 "wpa_pairwise" , wpa_pairwise , sizeof (wpa_pairwise ),
1976+ "ieee80211w" , ieee80211w , sizeof (ieee80211w ),
19441977 "auth_algs" , auth_algs , sizeof (auth_algs ),
19451978 "wep_key0" , wep_key0 , sizeof (wep_key0 ),
19461979 "wep_key1" , wep_key1 , sizeof (wep_key1 ),
@@ -1959,7 +1992,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
19591992 if (!strncmp (p , "FT-" , 3 ))
19601993 p += 3 ;
19611994
1962- parse_wpa_suites (p , atoi (wpa ), & c -> wpa_version , & c -> auth_suites );
1995+ parse_wpa_suites (p , atoi (wpa ), & c -> wpa_version , & c -> auth_suites , atoi ( ieee80211w ) );
19631996 }
19641997
19651998 c -> enabled = c -> wpa_version ? 1 : 0 ;
@@ -2531,7 +2564,7 @@ static void nl80211_get_scancrypto(char *spec, struct iwinfo_crypto_entry *c)
25312564
25322565 c -> enabled = 1 ;
25332566
2534- parse_wpa_suites (suites , wpa_version , & c -> wpa_version , & c -> auth_suites );
2567+ parse_wpa_suites (suites , wpa_version , & c -> wpa_version , & c -> auth_suites , -1 );
25352568 parse_wpa_ciphers (suites , & c -> pair_ciphers );
25362569 }
25372570}
0 commit comments