Skip to content

Commit fa4e48f

Browse files
yedidyaBenshjmberg-intel
authored andcommitted
wifi: iwlwifi: mvm: update two most recent GTKs on D3 resume flow
When resuming from D3 the two most recent GTKs are passed from the FW with wowlan_info_notif. Both keys should be updated as they both might be needed upon FW restart and they both should be removed upon station removal. Signed-off-by: Yedidya Benshimol <[email protected]> Signed-off-by: Gregory Greenman <[email protected]> Link: https://lore.kernel.org/r/20230621144844.3ea3a9f52ec2.I7cedfa2bb0eafb83e7c77363673560acf05bff74@changeid Signed-off-by: Johannes Berg <[email protected]>
1 parent 60555ea commit fa4e48f

File tree

1 file changed

+115
-81
lines changed
  • drivers/net/wireless/intel/iwlwifi/mvm

1 file changed

+115
-81
lines changed

drivers/net/wireless/intel/iwlwifi/mvm/d3.c

Lines changed: 115 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,7 +1398,8 @@ struct iwl_wowlan_status_data {
13981398
u8 key[WOWLAN_KEY_MAX_SIZE];
13991399
u8 len;
14001400
u8 flags;
1401-
} gtk;
1401+
u8 id;
1402+
} gtk[WOWLAN_GTK_KEYS_NUM];
14021403

14031404
struct {
14041405
/*
@@ -1758,7 +1759,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
17581759
s8 new_key_id = -1;
17591760

17601761
if (status->num_of_gtk_rekeys)
1761-
new_key_id = status->gtk.flags &
1762+
new_key_id = status->gtk[0].flags &
17621763
IWL_WOWLAN_GTK_IDX_MASK;
17631764

17641765
/* 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,
17771778
struct iwl_mvm_d3_gtk_iter_data {
17781779
struct iwl_mvm *mvm;
17791780
struct iwl_wowlan_status_data *status;
1780-
void *last_gtk;
1781-
u32 cipher;
1781+
u32 gtk_cipher;
17821782
bool unhandled_cipher;
17831783
int num_keys;
17841784
};
@@ -1804,8 +1804,7 @@ static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw,
18041804
case WLAN_CIPHER_SUITE_GCMP_256:
18051805
case WLAN_CIPHER_SUITE_TKIP:
18061806
/* we support these */
1807-
data->last_gtk = key;
1808-
data->cipher = key->cipher;
1807+
data->gtk_cipher = key->cipher;
18091808
break;
18101809
default:
18111810
/* everything else - disconnect from AP */
@@ -1824,6 +1823,7 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
18241823
{
18251824
struct iwl_mvm_d3_gtk_iter_data *data = _data;
18261825
struct iwl_wowlan_status_data *status = data->status;
1826+
s8 keyidx;
18271827

18281828
if (data->unhandled_cipher)
18291829
return;
@@ -1848,14 +1848,76 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
18481848
iwl_mvm_set_key_rx_seq_tids(key, status->ptk.tkip.seq);
18491849
return;
18501850
}
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))) {
18521860
ieee80211_remove_key(key);
1853-
1854-
if (data->last_gtk == key)
1861+
} else {
18551862
iwl_mvm_set_key_rx_seq(key, data->status, false);
1863+
}
18561864
}
18571865
}
18581866

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+
18591921
static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
18601922
struct ieee80211_vif *vif,
18611923
struct iwl_wowlan_status_data *status)
@@ -1883,8 +1945,6 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
18831945
return false;
18841946
if (!gtkdata.num_keys)
18851947
goto out;
1886-
if (!gtkdata.last_gtk)
1887-
return false;
18881948

18891949
/*
18901950
* 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,
18931953
ieee80211_iter_keys(mvm->hw, vif,
18941954
iwl_mvm_d3_update_keys, &gtkdata);
18951955

1896-
IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n",
1897-
status->num_of_gtk_rekeys);
18981956
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);
19131958

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);
19191961

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))
19371963
return false;
1938-
iwl_mvm_set_key_rx_seq(key, status, true);
1939-
1940-
replay_ctr = cpu_to_be64(status->replay_ctr);
1941-
19421964
ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
19431965
(void *)&replay_ctr, GFP_KERNEL);
19441966
}
@@ -1957,40 +1979,52 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
19571979
static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status,
19581980
struct iwl_wowlan_gtk_status_v2 *data)
19591981
{
1960-
BUILD_BUG_ON(sizeof(status->gtk.key) < sizeof(data->key));
1982+
BUILD_BUG_ON(sizeof(status->gtk[0].key) < sizeof(data->key));
19611983
BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
19621984
sizeof(data->tkip_mic_key) >
1963-
sizeof(status->gtk.key));
1985+
sizeof(status->gtk[0].key));
19641986

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;
19671989

1968-
memcpy(status->gtk.key, data->key, sizeof(data->key));
1990+
memcpy(status->gtk[0].key, data->key, sizeof(data->key));
19691991

19701992
/* 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,
19731995
data->tkip_mic_key, sizeof(data->tkip_mic_key));
19741996
}
19751997

19761998
static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status,
19771999
struct iwl_wowlan_gtk_status_v3 *data)
19782000
{
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;
19862002

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));
19922018

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+
}
19942028
}
19952029

19962030
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,
20332067
}
20342068

20352069
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);
20372071
iwl_mvm_convert_igtk(status, &data->igtk[0]);
20382072

20392073
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)
21562190
goto out_free_resp;
21572191

21582192
BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) >
2159-
sizeof(status->gtk.key));
2193+
sizeof(status->gtk[0].key));
21602194
BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
21612195
sizeof(v6->gtk.tkip_mic_key) >
2162-
sizeof(status->gtk.key));
2196+
sizeof(status->gtk[0].key));
21632197

21642198
/* 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,
21662200
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,
21682202
v6->gtk.tkip_mic_key,
21692203
sizeof(v6->gtk.tkip_mic_key));
21702204

21712205
iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc);
21722206

21732207
/* hardcode the key length to 16 since v6 only supports 16 */
2174-
status->gtk.len = 16;
2208+
status->gtk[0].len = 16;
21752209

21762210
/*
21772211
* The key index only uses 2 bits (values 0 to 3) and
21782212
* we always set bit 7 which means this is the
21792213
* currently used key.
21802214
*/
2181-
status->gtk.flags = v6->gtk.key_index | BIT(7);
2215+
status->gtk[0].flags = v6->gtk.key_index | BIT(7);
21822216
} else if (notif_ver == 7) {
21832217
struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;
21842218

@@ -2212,7 +2246,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
22122246
goto out_free_resp;
22132247

22142248
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);
22162250
iwl_mvm_convert_igtk(status, &v12->igtk[0]);
22172251

22182252
status->tid_tear_down = v12->tid_tear_down;

0 commit comments

Comments
 (0)