@@ -1776,7 +1776,8 @@ static const struct {
17761776 { "EAP-SUITE-B-192" , 4 , IWINFO_KMGMT_8021x },
17771777 { "EAP-SUITE-B" , 4 , IWINFO_KMGMT_8021x },
17781778 { "EAP-SHA384" , 4 , IWINFO_KMGMT_8021x },
1779- { "EAP-SHA256" , 0 , IWINFO_KMGMT_8021x },
1779+ /* SHA256 counts as WPA3 as long as pmf is enabled; we check this below. */
1780+ { "EAP-SHA256" , 4 , IWINFO_KMGMT_8021x },
17801781 { "PSK-SHA256" , 0 , IWINFO_KMGMT_PSK },
17811782 { "NONE" , 0 , IWINFO_KMGMT_NONE },
17821783 { "None" , 0 , IWINFO_KMGMT_NONE },
@@ -1787,7 +1788,7 @@ static const struct {
17871788};
17881789
17891790static void parse_wpa_suites (const char * str , int defversion ,
1790- uint8_t * versions , uint8_t * suites )
1791+ uint8_t * versions , uint8_t * suites , int pmf )
17911792{
17921793 size_t l ;
17931794 int i , version ;
@@ -1822,6 +1823,35 @@ static void parse_wpa_suites(const char *str, int defversion,
18221823
18231824 p = q + strspn (q , sep );
18241825 }
1826+
1827+ /* Handle ieee80211w/pmf (management frame protection).
1828+ *
1829+ * Strictly:
1830+ * ieee80211w=2 && wpa_key_mgmt=WPA-EAP-SHA256
1831+ * => WPA3-Enterprise
1832+ * ieee80211w=1 && wpa_key_mgmt=WPA-EAP WPA-EAP-SHA256
1833+ * => WPA3-Enterprise transition
1834+ *
1835+ * Here we just try to aggressively downgrade (i.e. if no pmf,
1836+ * not WPA3-Enterprise, and if not required then WPA2/WPA3).
1837+ * This _will_ allow some invalid configurations through
1838+ * and count certain undefined configurations as WPA2/WPA3
1839+ * (e.g. WPA-EAP-SHA256 only and ieee80211=1).
1840+ */
1841+ if ((* suites & IWINFO_KMGMT_8021x ) && (* versions & 4 ))
1842+ switch (pmf )
1843+ {
1844+ case 0 : /* if disabled, it's not WPA3 */
1845+ * versions &= ~4 ;
1846+ * versions |= defversion ;
1847+ break ;
1848+ case 1 : /* if not required, not only WPA3 */
1849+ * versions |= defversion ;
1850+ break ;
1851+ case 2 : /* pmf required */
1852+ default : /* if no pmf info - e.g. from scan */
1853+ break ;
1854+ }
18251855}
18261856
18271857static const struct {
@@ -1876,6 +1906,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
18761906 uint8_t wpa_version = 0 ;
18771907 char wpa [2 ], wpa_key_mgmt [64 ], wpa_pairwise [16 ], wpa_groupwise [16 ];
18781908 char auth_algs [2 ], wep_key0 [27 ], wep_key1 [27 ], wep_key2 [27 ], wep_key3 [27 ];
1909+ char ieee80211w [2 ], pmf [2 ];
18791910 char mode [16 ];
18801911
18811912 struct iwinfo_crypto_entry * c = (struct iwinfo_crypto_entry * )buf ;
@@ -1885,6 +1916,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
18851916 "pairwise_cipher" , wpa_pairwise , sizeof (wpa_pairwise ),
18861917 "group_cipher" , wpa_groupwise , sizeof (wpa_groupwise ),
18871918 "key_mgmt" , wpa_key_mgmt , sizeof (wpa_key_mgmt ),
1919+ "pmf" , pmf , sizeof (pmf ),
18881920 "mode" , mode , sizeof (mode )))
18891921 {
18901922 /* WEP or Open */
@@ -1933,7 +1965,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
19331965 wpa_version = 1 ;
19341966 }
19351967
1936- parse_wpa_suites (p , wpa_version , & c -> wpa_version , & c -> auth_suites );
1968+ parse_wpa_suites (p , wpa_version , & c -> wpa_version , & c -> auth_suites , atoi ( pmf ) );
19371969
19381970 c -> enabled = !!(c -> wpa_version && c -> auth_suites );
19391971 }
@@ -1946,6 +1978,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
19461978 "wpa" , wpa , sizeof (wpa ),
19471979 "wpa_key_mgmt" , wpa_key_mgmt , sizeof (wpa_key_mgmt ),
19481980 "wpa_pairwise" , wpa_pairwise , sizeof (wpa_pairwise ),
1981+ "ieee80211w" , ieee80211w , sizeof (ieee80211w ),
19491982 "auth_algs" , auth_algs , sizeof (auth_algs ),
19501983 "wep_key0" , wep_key0 , sizeof (wep_key0 ),
19511984 "wep_key1" , wep_key1 , sizeof (wep_key1 ),
@@ -1964,7 +1997,7 @@ static int nl80211_get_encryption(const char *ifname, char *buf)
19641997 if (!strncmp (p , "FT-" , 3 ))
19651998 p += 3 ;
19661999
1967- parse_wpa_suites (p , atoi (wpa ), & c -> wpa_version , & c -> auth_suites );
2000+ parse_wpa_suites (p , atoi (wpa ), & c -> wpa_version , & c -> auth_suites , atoi ( ieee80211w ) );
19682001 }
19692002
19702003 c -> enabled = c -> wpa_version ? 1 : 0 ;
@@ -2536,7 +2569,7 @@ static void nl80211_get_scancrypto(char *spec, struct iwinfo_crypto_entry *c)
25362569
25372570 c -> enabled = 1 ;
25382571
2539- parse_wpa_suites (suites , wpa_version , & c -> wpa_version , & c -> auth_suites );
2572+ parse_wpa_suites (suites , wpa_version , & c -> wpa_version , & c -> auth_suites , -1 );
25402573 parse_wpa_ciphers (suites , & c -> pair_ciphers );
25412574 }
25422575}
@@ -4194,6 +4227,7 @@ static int dot11ah_get_encryption(const char *ifname, char *buf)
41944227 uint8_t wpa_version = 0 ;
41954228 char wpa [2 ], wpa_key_mgmt [64 ], wpa_pairwise [16 ], wpa_groupwise [16 ];
41964229 char auth_algs [2 ], wep_key0 [27 ], wep_key1 [27 ], wep_key2 [27 ], wep_key3 [27 ];
4230+ char ieee80211w [2 ], pmf [2 ];
41974231 char mode [16 ];
41984232
41994233 struct iwinfo_crypto_entry * c = (struct iwinfo_crypto_entry * )buf ;
@@ -4203,6 +4237,7 @@ static int dot11ah_get_encryption(const char *ifname, char *buf)
42034237 "pairwise_cipher" , wpa_pairwise , sizeof (wpa_pairwise ),
42044238 "group_cipher" , wpa_groupwise , sizeof (wpa_groupwise ),
42054239 "key_mgmt" , wpa_key_mgmt , sizeof (wpa_key_mgmt ),
4240+ "pmf" , pmf , sizeof (pmf ),
42064241 "mode" , mode , sizeof (mode )))
42074242 {
42084243 /* WEP or Open */
@@ -4251,7 +4286,7 @@ static int dot11ah_get_encryption(const char *ifname, char *buf)
42514286 wpa_version = 1 ;
42524287 }
42534288
4254- parse_wpa_suites (p , wpa_version , & c -> wpa_version , & c -> auth_suites );
4289+ parse_wpa_suites (p , wpa_version , & c -> wpa_version , & c -> auth_suites , atoi ( pmf ) );
42554290
42564291 c -> enabled = !!(c -> wpa_version && c -> auth_suites );
42574292 }
@@ -4264,6 +4299,7 @@ static int dot11ah_get_encryption(const char *ifname, char *buf)
42644299 "wpa" , wpa , sizeof (wpa ),
42654300 "wpa_key_mgmt" , wpa_key_mgmt , sizeof (wpa_key_mgmt ),
42664301 "wpa_pairwise" , wpa_pairwise , sizeof (wpa_pairwise ),
4302+ "ieee80211w" , ieee80211w , sizeof (ieee80211w ),
42674303 "auth_algs" , auth_algs , sizeof (auth_algs ),
42684304 "wep_key0" , wep_key0 , sizeof (wep_key0 ),
42694305 "wep_key1" , wep_key1 , sizeof (wep_key1 ),
@@ -4279,7 +4315,10 @@ static int dot11ah_get_encryption(const char *ifname, char *buf)
42794315 if (!strncmp (p , "WPA-" , 4 ))
42804316 p += 4 ;
42814317
4282- parse_wpa_suites (p , atoi (wpa ), & c -> wpa_version , & c -> auth_suites );
4318+ if (!strncmp (p , "FT-" , 3 ))
4319+ p += 3 ;
4320+
4321+ parse_wpa_suites (p , atoi (wpa ), & c -> wpa_version , & c -> auth_suites , atoi (ieee80211w ));
42834322 }
42844323
42854324 c -> enabled = c -> wpa_version ? 1 : 0 ;
0 commit comments