@@ -1380,6 +1380,14 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
1380
1380
return __iwl_mvm_suspend (hw , wowlan , false);
1381
1381
}
1382
1382
1383
+ struct iwl_multicast_key_data {
1384
+ u8 key [WOWLAN_KEY_MAX_SIZE ];
1385
+ u8 len ;
1386
+ u8 flags ;
1387
+ u8 id ;
1388
+ u8 ipn [6 ];
1389
+ };
1390
+
1383
1391
/* converted data from the different status responses */
1384
1392
struct iwl_wowlan_status_data {
1385
1393
u64 replay_ctr ;
@@ -1429,12 +1437,7 @@ struct iwl_wowlan_status_data {
1429
1437
} tkip , aes ;
1430
1438
} ptk ;
1431
1439
1432
- struct {
1433
- u64 ipn ;
1434
- u8 key [WOWLAN_KEY_MAX_SIZE ];
1435
- u8 len ;
1436
- u8 flags ;
1437
- } igtk ;
1440
+ struct iwl_multicast_key_data igtk ;
1438
1441
1439
1442
u8 * wake_packet ;
1440
1443
};
@@ -1778,8 +1781,8 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
1778
1781
struct iwl_mvm_d3_gtk_iter_data {
1779
1782
struct iwl_mvm * mvm ;
1780
1783
struct iwl_wowlan_status_data * status ;
1781
- u32 gtk_cipher ;
1782
- bool unhandled_cipher ;
1784
+ u32 gtk_cipher , igtk_cipher ;
1785
+ bool unhandled_cipher , igtk_support ;
1783
1786
int num_keys ;
1784
1787
};
1785
1788
@@ -1806,6 +1809,19 @@ static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw,
1806
1809
/* we support these */
1807
1810
data -> gtk_cipher = key -> cipher ;
1808
1811
break ;
1812
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128 :
1813
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256 :
1814
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256 :
1815
+ case WLAN_CIPHER_SUITE_AES_CMAC :
1816
+ /* we support these */
1817
+ if (data -> igtk_support &&
1818
+ (key -> keyidx == 4 || key -> keyidx == 5 )) {
1819
+ data -> igtk_cipher = key -> cipher ;
1820
+ } else {
1821
+ data -> unhandled_cipher = true;
1822
+ return ;
1823
+ }
1824
+ break ;
1809
1825
default :
1810
1826
/* everything else - disconnect from AP */
1811
1827
data -> unhandled_cipher = true;
@@ -1815,6 +1831,23 @@ static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw,
1815
1831
data -> num_keys ++ ;
1816
1832
}
1817
1833
1834
+ static void
1835
+ iwl_mvm_d3_set_igtk_bigtk_ipn (const struct iwl_multicast_key_data * key ,
1836
+ struct ieee80211_key_seq * seq , u32 cipher )
1837
+ {
1838
+ switch (cipher ) {
1839
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128 :
1840
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256 :
1841
+ BUILD_BUG_ON (sizeof (seq -> aes_gmac .pn ) != sizeof (key -> ipn ));
1842
+ memcpy (seq -> aes_gmac .pn , key -> ipn , sizeof (seq -> aes_gmac .pn ));
1843
+ break ;
1844
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256 :
1845
+ BUILD_BUG_ON (sizeof (seq -> aes_cmac .pn ) != sizeof (key -> ipn ));
1846
+ memcpy (seq -> aes_cmac .pn , key -> ipn , sizeof (seq -> aes_cmac .pn ));
1847
+ break ;
1848
+ }
1849
+ }
1850
+
1818
1851
static void iwl_mvm_d3_update_keys (struct ieee80211_hw * hw ,
1819
1852
struct ieee80211_vif * vif ,
1820
1853
struct ieee80211_sta * sta ,
@@ -1861,6 +1894,24 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
1861
1894
} else {
1862
1895
iwl_mvm_set_key_rx_seq (key , data -> status , false);
1863
1896
}
1897
+ break ;
1898
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128 :
1899
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256 :
1900
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256 :
1901
+ case WLAN_CIPHER_SUITE_AES_CMAC :
1902
+ if (key -> keyidx == 4 || key -> keyidx == 5 ) {
1903
+ /* remove rekeyed key */
1904
+ if (status -> num_of_gtk_rekeys ) {
1905
+ ieee80211_remove_key (key );
1906
+ } else {
1907
+ struct ieee80211_key_seq seq ;
1908
+
1909
+ iwl_mvm_d3_set_igtk_bigtk_ipn (& status -> igtk ,
1910
+ & seq ,
1911
+ key -> cipher );
1912
+ ieee80211_set_key_rx_seq (key , 0 , & seq );
1913
+ }
1914
+ }
1864
1915
}
1865
1916
}
1866
1917
@@ -1918,6 +1969,70 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
1918
1969
return true;
1919
1970
}
1920
1971
1972
+ static bool
1973
+ iwl_mvm_d3_igtk_bigtk_rekey_add (struct iwl_wowlan_status_data * status ,
1974
+ struct ieee80211_vif * vif , u32 cipher ,
1975
+ struct iwl_multicast_key_data * key_data )
1976
+ {
1977
+ struct ieee80211_key_conf * key_config ;
1978
+ struct {
1979
+ struct ieee80211_key_conf conf ;
1980
+ u8 key [WOWLAN_KEY_MAX_SIZE ];
1981
+ } conf = {
1982
+ .conf .cipher = cipher ,
1983
+ .conf .keyidx = key_data -> id ,
1984
+ };
1985
+ struct ieee80211_key_seq seq ;
1986
+
1987
+ if (!key_data -> len )
1988
+ return true;
1989
+
1990
+ iwl_mvm_d3_set_igtk_bigtk_ipn (key_data , & seq , conf .conf .cipher );
1991
+
1992
+ switch (cipher ) {
1993
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128 :
1994
+ conf .conf .keylen = WLAN_KEY_LEN_BIP_GMAC_128 ;
1995
+ break ;
1996
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256 :
1997
+ conf .conf .keylen = WLAN_KEY_LEN_BIP_GMAC_256 ;
1998
+ break ;
1999
+ case WLAN_CIPHER_SUITE_AES_CMAC :
2000
+ conf .conf .keylen = WLAN_KEY_LEN_AES_CMAC ;
2001
+ break ;
2002
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256 :
2003
+ conf .conf .keylen = WLAN_KEY_LEN_BIP_CMAC_256 ;
2004
+ break ;
2005
+ default :
2006
+ WARN_ON (1 );
2007
+ }
2008
+ BUILD_BUG_ON (sizeof (conf .key ) < sizeof (key_data -> key ));
2009
+ memcpy (conf .conf .key , key_data -> key , conf .conf .keylen );
2010
+
2011
+ key_config = ieee80211_gtk_rekey_add (vif , & conf .conf );
2012
+ if (IS_ERR (key_config ))
2013
+ return false;
2014
+ ieee80211_set_key_rx_seq (key_config , 0 , & seq );
2015
+ return true;
2016
+ }
2017
+
2018
+ static int iwl_mvm_lookup_wowlan_status_ver (struct iwl_mvm * mvm )
2019
+ {
2020
+ u8 notif_ver ;
2021
+
2022
+ if (!fw_has_api (& mvm -> fw -> ucode_capa ,
2023
+ IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL ))
2024
+ return 6 ;
2025
+
2026
+ /* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */
2027
+ notif_ver = iwl_fw_lookup_notif_ver (mvm -> fw , LONG_GROUP ,
2028
+ WOWLAN_GET_STATUSES , 0 );
2029
+ if (!notif_ver )
2030
+ notif_ver = iwl_fw_lookup_notif_ver (mvm -> fw , LEGACY_GROUP ,
2031
+ WOWLAN_GET_STATUSES , 7 );
2032
+
2033
+ return notif_ver ;
2034
+ }
2035
+
1921
2036
static bool iwl_mvm_setup_connection_keep (struct iwl_mvm * mvm ,
1922
2037
struct ieee80211_vif * vif ,
1923
2038
struct iwl_wowlan_status_data * status )
@@ -1937,6 +2052,12 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
1937
2052
if (status -> wakeup_reasons & disconnection_reasons )
1938
2053
return false;
1939
2054
2055
+ if (iwl_mvm_lookup_wowlan_status_ver (mvm ) > 6 ||
2056
+ iwl_fw_lookup_notif_ver (mvm -> fw , PROT_OFFLOAD_GROUP ,
2057
+ WOWLAN_INFO_NOTIFICATION ,
2058
+ 0 ))
2059
+ gtkdata .igtk_support = true;
2060
+
1940
2061
/* find last GTK that we used initially, if any */
1941
2062
ieee80211_iter_keys (mvm -> hw , vif ,
1942
2063
iwl_mvm_d3_find_last_keys , & gtkdata );
@@ -1961,6 +2082,12 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
1961
2082
1962
2083
if (!iwl_mvm_gtk_rekey (status , vif , mvm , gtkdata .gtk_cipher ))
1963
2084
return false;
2085
+
2086
+ if (!iwl_mvm_d3_igtk_bigtk_rekey_add (status , vif ,
2087
+ gtkdata .igtk_cipher ,
2088
+ & status -> igtk ))
2089
+ return false;
2090
+
1964
2091
ieee80211_gtk_rekey_notify (vif , vif -> bss_conf .bssid ,
1965
2092
(void * )& replay_ctr , GFP_KERNEL );
1966
2093
}
@@ -2030,21 +2157,19 @@ static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status,
2030
2157
static void iwl_mvm_convert_igtk (struct iwl_wowlan_status_data * status ,
2031
2158
struct iwl_wowlan_igtk_status * data )
2032
2159
{
2033
- const u8 * ipn = data -> ipn ;
2034
-
2035
2160
BUILD_BUG_ON (sizeof (status -> igtk .key ) < sizeof (data -> key ));
2036
2161
2162
+ if (!data -> key_len )
2163
+ return ;
2164
+
2037
2165
status -> igtk .len = data -> key_len ;
2038
2166
status -> igtk .flags = data -> key_flags ;
2167
+ status -> igtk .id = u32_get_bits (data -> key_flags ,
2168
+ IWL_WOWLAN_IGTK_BIGTK_IDX_MASK )
2169
+ + WOWLAN_IGTK_MIN_INDEX ;
2039
2170
2040
2171
memcpy (status -> igtk .key , data -> key , sizeof (data -> key ));
2041
-
2042
- status -> igtk .ipn = ((u64 )ipn [5 ] << 0 ) |
2043
- ((u64 )ipn [4 ] << 8 ) |
2044
- ((u64 )ipn [3 ] << 16 ) |
2045
- ((u64 )ipn [2 ] << 24 ) |
2046
- ((u64 )ipn [1 ] << 32 ) |
2047
- ((u64 )ipn [0 ] << 40 );
2172
+ memcpy (status -> igtk .ipn , data -> ipn , sizeof (data -> ipn ));
2048
2173
}
2049
2174
2050
2175
static void iwl_mvm_parse_wowlan_info_notif (struct iwl_mvm * mvm ,
@@ -2175,14 +2300,9 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
2175
2300
len = iwl_rx_packet_payload_len (cmd .resp_pkt );
2176
2301
2177
2302
/* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */
2178
- notif_ver = iwl_fw_lookup_notif_ver (mvm -> fw , LONG_GROUP ,
2179
- WOWLAN_GET_STATUSES , 0 );
2180
- if (!notif_ver )
2181
- notif_ver = iwl_fw_lookup_notif_ver (mvm -> fw , LEGACY_GROUP ,
2182
- WOWLAN_GET_STATUSES , 7 );
2303
+ notif_ver = iwl_mvm_lookup_wowlan_status_ver (mvm );
2183
2304
2184
- if (!fw_has_api (& mvm -> fw -> ucode_capa ,
2185
- IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL )) {
2305
+ if (notif_ver < 7 ) {
2186
2306
struct iwl_wowlan_status_v6 * v6 = (void * )cmd .resp_pkt -> data ;
2187
2307
2188
2308
status = iwl_mvm_parse_wowlan_status_common_v6 (mvm , v6 , len );
0 commit comments