@@ -1398,7 +1398,8 @@ struct iwl_wowlan_status_data {
1398
1398
u8 key [WOWLAN_KEY_MAX_SIZE ];
1399
1399
u8 len ;
1400
1400
u8 flags ;
1401
- } gtk ;
1401
+ u8 id ;
1402
+ } gtk [WOWLAN_GTK_KEYS_NUM ];
1402
1403
1403
1404
struct {
1404
1405
/*
@@ -1758,7 +1759,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
1758
1759
s8 new_key_id = -1 ;
1759
1760
1760
1761
if (status -> num_of_gtk_rekeys )
1761
- new_key_id = status -> gtk .flags &
1762
+ new_key_id = status -> gtk [ 0 ] .flags &
1762
1763
IWL_WOWLAN_GTK_IDX_MASK ;
1763
1764
1764
1765
/* Don't install a new key's value to an old key */
@@ -1777,8 +1778,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
1777
1778
struct iwl_mvm_d3_gtk_iter_data {
1778
1779
struct iwl_mvm * mvm ;
1779
1780
struct iwl_wowlan_status_data * status ;
1780
- void * last_gtk ;
1781
- u32 cipher ;
1781
+ u32 gtk_cipher ;
1782
1782
bool unhandled_cipher ;
1783
1783
int num_keys ;
1784
1784
};
@@ -1804,8 +1804,7 @@ static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw,
1804
1804
case WLAN_CIPHER_SUITE_GCMP_256 :
1805
1805
case WLAN_CIPHER_SUITE_TKIP :
1806
1806
/* we support these */
1807
- data -> last_gtk = key ;
1808
- data -> cipher = key -> cipher ;
1807
+ data -> gtk_cipher = key -> cipher ;
1809
1808
break ;
1810
1809
default :
1811
1810
/* everything else - disconnect from AP */
@@ -1824,6 +1823,7 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
1824
1823
{
1825
1824
struct iwl_mvm_d3_gtk_iter_data * data = _data ;
1826
1825
struct iwl_wowlan_status_data * status = data -> status ;
1826
+ s8 keyidx ;
1827
1827
1828
1828
if (data -> unhandled_cipher )
1829
1829
return ;
@@ -1848,14 +1848,76 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
1848
1848
iwl_mvm_set_key_rx_seq_tids (key , status -> ptk .tkip .seq );
1849
1849
return ;
1850
1850
}
1851
- if (data -> status -> num_of_gtk_rekeys )
1851
+ keyidx = key -> keyidx ;
1852
+ /* The current key is always sent by the FW, even if it wasn't
1853
+ * rekeyed during D3.
1854
+ * We remove an existing key if it has the same index as
1855
+ * a new key
1856
+ */
1857
+ if (status -> num_of_gtk_rekeys &&
1858
+ ((status -> gtk [0 ].len && keyidx == status -> gtk [0 ].id ) ||
1859
+ (status -> gtk [1 ].len && keyidx == status -> gtk [1 ].id ))) {
1852
1860
ieee80211_remove_key (key );
1853
-
1854
- if (data -> last_gtk == key )
1861
+ } else {
1855
1862
iwl_mvm_set_key_rx_seq (key , data -> status , false);
1863
+ }
1856
1864
}
1857
1865
}
1858
1866
1867
+ static bool iwl_mvm_gtk_rekey (struct iwl_wowlan_status_data * status ,
1868
+ struct ieee80211_vif * vif ,
1869
+ struct iwl_mvm * mvm , u32 gtk_cipher )
1870
+ {
1871
+ int i ;
1872
+ struct ieee80211_key_conf * key ;
1873
+ struct {
1874
+ struct ieee80211_key_conf conf ;
1875
+ u8 key [32 ];
1876
+ } conf = {
1877
+ .conf .cipher = gtk_cipher ,
1878
+ };
1879
+
1880
+ BUILD_BUG_ON (WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP );
1881
+ BUILD_BUG_ON (sizeof (conf .key ) < WLAN_KEY_LEN_CCMP );
1882
+ BUILD_BUG_ON (sizeof (conf .key ) < WLAN_KEY_LEN_GCMP_256 );
1883
+ BUILD_BUG_ON (sizeof (conf .key ) < WLAN_KEY_LEN_TKIP );
1884
+ BUILD_BUG_ON (sizeof (conf .key ) < sizeof (status -> gtk [0 ].key ));
1885
+
1886
+ switch (gtk_cipher ) {
1887
+ case WLAN_CIPHER_SUITE_CCMP :
1888
+ case WLAN_CIPHER_SUITE_GCMP :
1889
+ conf .conf .keylen = WLAN_KEY_LEN_CCMP ;
1890
+ break ;
1891
+ case WLAN_CIPHER_SUITE_GCMP_256 :
1892
+ conf .conf .keylen = WLAN_KEY_LEN_GCMP_256 ;
1893
+ break ;
1894
+ case WLAN_CIPHER_SUITE_TKIP :
1895
+ conf .conf .keylen = WLAN_KEY_LEN_TKIP ;
1896
+ break ;
1897
+ default :
1898
+ WARN_ON (1 );
1899
+ }
1900
+
1901
+ for (i = 0 ; i < ARRAY_SIZE (status -> gtk ); i ++ ) {
1902
+ if (!status -> gtk [i ].len )
1903
+ continue ;
1904
+
1905
+ conf .conf .keyidx = status -> gtk [i ].id ;
1906
+ IWL_DEBUG_WOWLAN (mvm ,
1907
+ "Received from FW GTK cipher %d, key index %d\n" ,
1908
+ conf .conf .cipher , conf .conf .keyidx );
1909
+ memcpy (conf .conf .key , status -> gtk [i ].key ,
1910
+ sizeof (status -> gtk [i ].key ));
1911
+
1912
+ key = ieee80211_gtk_rekey_add (vif , & conf .conf );
1913
+ if (IS_ERR (key ))
1914
+ return false;
1915
+ iwl_mvm_set_key_rx_seq_idx (key , status , i );
1916
+ }
1917
+
1918
+ return true;
1919
+ }
1920
+
1859
1921
static bool iwl_mvm_setup_connection_keep (struct iwl_mvm * mvm ,
1860
1922
struct ieee80211_vif * vif ,
1861
1923
struct iwl_wowlan_status_data * status )
@@ -1883,8 +1945,6 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
1883
1945
return false;
1884
1946
if (!gtkdata .num_keys )
1885
1947
goto out ;
1886
- if (!gtkdata .last_gtk )
1887
- return false;
1888
1948
1889
1949
/*
1890
1950
* invalidate all other GTKs that might still exist and update
@@ -1893,52 +1953,14 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
1893
1953
ieee80211_iter_keys (mvm -> hw , vif ,
1894
1954
iwl_mvm_d3_update_keys , & gtkdata );
1895
1955
1896
- IWL_DEBUG_WOWLAN (mvm , "num of GTK rekeying %d\n" ,
1897
- status -> num_of_gtk_rekeys );
1898
1956
if (status -> num_of_gtk_rekeys ) {
1899
- struct ieee80211_key_conf * key ;
1900
- struct {
1901
- struct ieee80211_key_conf conf ;
1902
- u8 key [32 ];
1903
- } conf = {
1904
- .conf .cipher = gtkdata .cipher ,
1905
- .conf .keyidx =
1906
- status -> gtk .flags & IWL_WOWLAN_GTK_IDX_MASK ,
1907
- };
1908
- __be64 replay_ctr ;
1909
-
1910
- IWL_DEBUG_WOWLAN (mvm ,
1911
- "Received from FW GTK cipher %d, key index %d\n" ,
1912
- conf .conf .cipher , conf .conf .keyidx );
1957
+ __be64 replay_ctr = cpu_to_be64 (status -> replay_ctr );
1913
1958
1914
- BUILD_BUG_ON (WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP );
1915
- BUILD_BUG_ON (sizeof (conf .key ) < WLAN_KEY_LEN_CCMP );
1916
- BUILD_BUG_ON (sizeof (conf .key ) < WLAN_KEY_LEN_GCMP_256 );
1917
- BUILD_BUG_ON (sizeof (conf .key ) < WLAN_KEY_LEN_TKIP );
1918
- BUILD_BUG_ON (sizeof (conf .key ) < sizeof (status -> gtk .key ));
1959
+ IWL_DEBUG_WOWLAN (mvm , "num of GTK rekeying %d\n" ,
1960
+ status -> num_of_gtk_rekeys );
1919
1961
1920
- memcpy (conf .conf .key , status -> gtk .key , sizeof (status -> gtk .key ));
1921
-
1922
- switch (gtkdata .cipher ) {
1923
- case WLAN_CIPHER_SUITE_CCMP :
1924
- case WLAN_CIPHER_SUITE_GCMP :
1925
- conf .conf .keylen = WLAN_KEY_LEN_CCMP ;
1926
- break ;
1927
- case WLAN_CIPHER_SUITE_GCMP_256 :
1928
- conf .conf .keylen = WLAN_KEY_LEN_GCMP_256 ;
1929
- break ;
1930
- case WLAN_CIPHER_SUITE_TKIP :
1931
- conf .conf .keylen = WLAN_KEY_LEN_TKIP ;
1932
- break ;
1933
- }
1934
-
1935
- key = ieee80211_gtk_rekey_add (vif , & conf .conf );
1936
- if (IS_ERR (key ))
1962
+ if (!iwl_mvm_gtk_rekey (status , vif , mvm , gtkdata .gtk_cipher ))
1937
1963
return false;
1938
- iwl_mvm_set_key_rx_seq (key , status , true);
1939
-
1940
- replay_ctr = cpu_to_be64 (status -> replay_ctr );
1941
-
1942
1964
ieee80211_gtk_rekey_notify (vif , vif -> bss_conf .bssid ,
1943
1965
(void * )& replay_ctr , GFP_KERNEL );
1944
1966
}
@@ -1957,40 +1979,52 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
1957
1979
static void iwl_mvm_convert_gtk_v2 (struct iwl_wowlan_status_data * status ,
1958
1980
struct iwl_wowlan_gtk_status_v2 * data )
1959
1981
{
1960
- BUILD_BUG_ON (sizeof (status -> gtk .key ) < sizeof (data -> key ));
1982
+ BUILD_BUG_ON (sizeof (status -> gtk [ 0 ] .key ) < sizeof (data -> key ));
1961
1983
BUILD_BUG_ON (NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
1962
1984
sizeof (data -> tkip_mic_key ) >
1963
- sizeof (status -> gtk .key ));
1985
+ sizeof (status -> gtk [ 0 ] .key ));
1964
1986
1965
- status -> gtk .len = data -> key_len ;
1966
- status -> gtk .flags = data -> key_flags ;
1987
+ status -> gtk [ 0 ] .len = data -> key_len ;
1988
+ status -> gtk [ 0 ] .flags = data -> key_flags ;
1967
1989
1968
- memcpy (status -> gtk .key , data -> key , sizeof (data -> key ));
1990
+ memcpy (status -> gtk [ 0 ] .key , data -> key , sizeof (data -> key ));
1969
1991
1970
1992
/* if it's as long as the TKIP encryption key, copy MIC key */
1971
- if (status -> gtk .len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY )
1972
- memcpy (status -> gtk .key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY ,
1993
+ if (status -> gtk [ 0 ] .len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY )
1994
+ memcpy (status -> gtk [ 0 ] .key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY ,
1973
1995
data -> tkip_mic_key , sizeof (data -> tkip_mic_key ));
1974
1996
}
1975
1997
1976
1998
static void iwl_mvm_convert_gtk_v3 (struct iwl_wowlan_status_data * status ,
1977
1999
struct iwl_wowlan_gtk_status_v3 * data )
1978
2000
{
1979
- /* The parts we need are identical in v2 and v3 */
1980
- #define CHECK (_f ) do { \
1981
- BUILD_BUG_ON(offsetof(struct iwl_wowlan_gtk_status_v2, _f) != \
1982
- offsetof(struct iwl_wowlan_gtk_status_v3, _f)); \
1983
- BUILD_BUG_ON(offsetofend(struct iwl_wowlan_gtk_status_v2, _f) !=\
1984
- offsetofend(struct iwl_wowlan_gtk_status_v3, _f)); \
1985
- } while (0)
2001
+ int data_idx , status_idx = 0 ;
1986
2002
1987
- CHECK (key );
1988
- CHECK (key_len );
1989
- CHECK (key_flags );
1990
- CHECK (tkip_mic_key );
1991
- #undef CHECK
2003
+ BUILD_BUG_ON (sizeof (status -> gtk [0 ].key ) < sizeof (data [0 ].key ));
2004
+ BUILD_BUG_ON (NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
2005
+ sizeof (data [0 ].tkip_mic_key ) >
2006
+ sizeof (status -> gtk [0 ].key ));
2007
+ BUILD_BUG_ON (ARRAY_SIZE (status -> gtk ) < WOWLAN_GTK_KEYS_NUM );
2008
+ for (data_idx = 0 ; data_idx < ARRAY_SIZE (status -> gtk ); data_idx ++ ) {
2009
+ if (!(data [data_idx ].key_len ))
2010
+ continue ;
2011
+ status -> gtk [status_idx ].len = data [data_idx ].key_len ;
2012
+ status -> gtk [status_idx ].flags = data [data_idx ].key_flags ;
2013
+ status -> gtk [status_idx ].id = status -> gtk [status_idx ].flags &
2014
+ IWL_WOWLAN_GTK_IDX_MASK ;
2015
+
2016
+ memcpy (status -> gtk [status_idx ].key , data [data_idx ].key ,
2017
+ sizeof (data [data_idx ].key ));
1992
2018
1993
- iwl_mvm_convert_gtk_v2 (status , (void * )data );
2019
+ /* if it's as long as the TKIP encryption key, copy MIC key */
2020
+ if (status -> gtk [status_idx ].len ==
2021
+ NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY )
2022
+ memcpy (status -> gtk [status_idx ].key +
2023
+ NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY ,
2024
+ data [data_idx ].tkip_mic_key ,
2025
+ sizeof (data [data_idx ].tkip_mic_key ));
2026
+ status_idx ++ ;
2027
+ }
1994
2028
}
1995
2029
1996
2030
static void iwl_mvm_convert_igtk (struct iwl_wowlan_status_data * status ,
@@ -2033,7 +2067,7 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
2033
2067
}
2034
2068
2035
2069
iwl_mvm_convert_key_counters_v5 (status , & data -> gtk [0 ].sc );
2036
- iwl_mvm_convert_gtk_v3 (status , & data -> gtk [ 0 ] );
2070
+ iwl_mvm_convert_gtk_v3 (status , data -> gtk );
2037
2071
iwl_mvm_convert_igtk (status , & data -> igtk [0 ]);
2038
2072
2039
2073
status -> replay_ctr = le64_to_cpu (data -> replay_ctr );
@@ -2156,29 +2190,29 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
2156
2190
goto out_free_resp ;
2157
2191
2158
2192
BUILD_BUG_ON (sizeof (v6 -> gtk .decrypt_key ) >
2159
- sizeof (status -> gtk .key ));
2193
+ sizeof (status -> gtk [ 0 ] .key ));
2160
2194
BUILD_BUG_ON (NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
2161
2195
sizeof (v6 -> gtk .tkip_mic_key ) >
2162
- sizeof (status -> gtk .key ));
2196
+ sizeof (status -> gtk [ 0 ] .key ));
2163
2197
2164
2198
/* copy GTK info to the right place */
2165
- memcpy (status -> gtk .key , v6 -> gtk .decrypt_key ,
2199
+ memcpy (status -> gtk [ 0 ] .key , v6 -> gtk .decrypt_key ,
2166
2200
sizeof (v6 -> gtk .decrypt_key ));
2167
- memcpy (status -> gtk .key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY ,
2201
+ memcpy (status -> gtk [ 0 ] .key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY ,
2168
2202
v6 -> gtk .tkip_mic_key ,
2169
2203
sizeof (v6 -> gtk .tkip_mic_key ));
2170
2204
2171
2205
iwl_mvm_convert_key_counters (status , & v6 -> gtk .rsc .all_tsc_rsc );
2172
2206
2173
2207
/* hardcode the key length to 16 since v6 only supports 16 */
2174
- status -> gtk .len = 16 ;
2208
+ status -> gtk [ 0 ] .len = 16 ;
2175
2209
2176
2210
/*
2177
2211
* The key index only uses 2 bits (values 0 to 3) and
2178
2212
* we always set bit 7 which means this is the
2179
2213
* currently used key.
2180
2214
*/
2181
- status -> gtk .flags = v6 -> gtk .key_index | BIT (7 );
2215
+ status -> gtk [ 0 ] .flags = v6 -> gtk .key_index | BIT (7 );
2182
2216
} else if (notif_ver == 7 ) {
2183
2217
struct iwl_wowlan_status_v7 * v7 = (void * )cmd .resp_pkt -> data ;
2184
2218
@@ -2212,7 +2246,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
2212
2246
goto out_free_resp ;
2213
2247
2214
2248
iwl_mvm_convert_key_counters_v5 (status , & v12 -> gtk [0 ].sc );
2215
- iwl_mvm_convert_gtk_v3 (status , & v12 -> gtk [ 0 ] );
2249
+ iwl_mvm_convert_gtk_v3 (status , v12 -> gtk );
2216
2250
iwl_mvm_convert_igtk (status , & v12 -> igtk [0 ]);
2217
2251
2218
2252
status -> tid_tear_down = v12 -> tid_tear_down ;
0 commit comments