Commit 631ee512 authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho

iwlwifi: mvm: d3: refactor TSC/RSC configuration

Refactor the TSC/RSC configuration out from the normal wowlan
key iteration so we can replace it later with a different one
adapted to a different firmware API.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210805130823.78e431c9aaeb.I5b83b8b30e3e7c04706a1f99b3970e4e5f36af9e@changeidSigned-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 398760aa
...@@ -102,9 +102,8 @@ static const u8 *iwl_mvm_find_max_pn(struct ieee80211_key_conf *key, ...@@ -102,9 +102,8 @@ static const u8 *iwl_mvm_find_max_pn(struct ieee80211_key_conf *key,
} }
struct wowlan_key_data { struct wowlan_key_data {
struct iwl_wowlan_rsc_tsc_params_cmd *rsc_tsc;
struct iwl_wowlan_kek_kck_material_cmd_v4 *kek_kck_cmd; struct iwl_wowlan_kek_kck_material_cmd_v4 *kek_kck_cmd;
bool error, use_rsc_tsc, configure_keys; bool error, configure_keys;
int wep_key_idx; int wep_key_idx;
}; };
...@@ -117,10 +116,7 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, ...@@ -117,10 +116,7 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct wowlan_key_data *data = _data; struct wowlan_key_data *data = _data;
struct aes_sc *aes_sc, *aes_tx_sc = NULL; int ret;
struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL;
struct ieee80211_key_seq seq;
int ret, i;
switch (key->cipher) { switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP40:
...@@ -190,6 +186,71 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, ...@@ -190,6 +186,71 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
* be deauthenticated, but that was considered acceptable. * be deauthenticated, but that was considered acceptable.
*/ */
return; return;
case WLAN_CIPHER_SUITE_TKIP:
if (!sta)
data->kek_kck_cmd->gtk_cipher =
cpu_to_le32(STA_KEY_FLG_TKIP);
break;
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
if (!sta)
data->kek_kck_cmd->gtk_cipher =
key->cipher == WLAN_CIPHER_SUITE_CCMP ?
cpu_to_le32(STA_KEY_FLG_CCM) :
cpu_to_le32(STA_KEY_FLG_GCMP);
break;
}
IWL_DEBUG_WOWLAN(mvm, "GTK cipher %d\n", data->kek_kck_cmd->gtk_cipher);
if (data->configure_keys) {
mutex_lock(&mvm->mutex);
/*
* The D3 firmware hardcodes the key offset 0 as the key it
* uses to transmit packets to the AP, i.e. the PTK.
*/
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
mvm->ptk_ivlen = key->iv_len;
mvm->ptk_icvlen = key->icv_len;
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, 0);
} else {
/*
* firmware only supports TSC/RSC for a single key,
* so if there are multiple keep overwriting them
* with new ones -- this relies on mac80211 doing
* list_add_tail().
*/
mvm->gtk_ivlen = key->iv_len;
mvm->gtk_icvlen = key->icv_len;
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, 1);
}
mutex_unlock(&mvm->mutex);
data->error = ret != 0;
}
}
struct wowlan_key_rsc_tsc_data {
struct iwl_wowlan_rsc_tsc_params_cmd *rsc_tsc;
bool have_rsc_tsc;
};
static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key,
void *_data)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct wowlan_key_rsc_tsc_data *data = _data;
struct aes_sc *aes_sc;
struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL;
struct ieee80211_key_seq seq;
int i;
switch (key->cipher) {
default:
break;
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
if (sta) { if (sta) {
u64 pn64; u64 pn64;
...@@ -205,8 +266,6 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, ...@@ -205,8 +266,6 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
} else { } else {
tkip_sc = tkip_sc =
data->rsc_tsc->params.all_tsc_rsc.tkip.multicast_rsc; data->rsc_tsc->params.all_tsc_rsc.tkip.multicast_rsc;
data->kek_kck_cmd->gtk_cipher =
cpu_to_le32(STA_KEY_FLG_TKIP);
} }
/* /*
...@@ -220,12 +279,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, ...@@ -220,12 +279,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32); tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32);
} }
data->use_rsc_tsc = true; data->have_rsc_tsc = true;
break; break;
case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_GCMP_256:
if (sta) { if (sta) {
struct aes_sc *aes_tx_sc;
u64 pn64; u64 pn64;
aes_sc = aes_sc =
...@@ -238,10 +298,6 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, ...@@ -238,10 +298,6 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
} else { } else {
aes_sc = aes_sc =
data->rsc_tsc->params.all_tsc_rsc.aes.multicast_rsc; data->rsc_tsc->params.all_tsc_rsc.aes.multicast_rsc;
data->kek_kck_cmd->gtk_cipher =
key->cipher == WLAN_CIPHER_SUITE_CCMP ?
cpu_to_le32(STA_KEY_FLG_CCM) :
cpu_to_le32(STA_KEY_FLG_GCMP);
} }
/* /*
...@@ -286,36 +342,48 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, ...@@ -286,36 +342,48 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
((u64)pn[0] << 40)); ((u64)pn[0] << 40));
} }
} }
data->use_rsc_tsc = true; data->have_rsc_tsc = true;
break; break;
} }
}
IWL_DEBUG_WOWLAN(mvm, "GTK cipher %d\n", data->kek_kck_cmd->gtk_cipher); static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ver = iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
WOWLAN_TSC_RSC_PARAM,
IWL_FW_CMD_VER_UNKNOWN);
struct wowlan_key_rsc_tsc_data data = {};
int size;
int ret;
if (data->configure_keys) { data.rsc_tsc = kzalloc(sizeof(*data.rsc_tsc), GFP_KERNEL);
mutex_lock(&mvm->mutex); if (!data.rsc_tsc)
/* return -ENOMEM;
* The D3 firmware hardcodes the key offset 0 as the key it
* uses to transmit packets to the AP, i.e. the PTK. if (ver == 4) {
*/ size = sizeof(*data.rsc_tsc);
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { data.rsc_tsc->sta_id = cpu_to_le32(mvmvif->ap_sta_id);
mvm->ptk_ivlen = key->iv_len; } else if (ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) {
mvm->ptk_icvlen = key->icv_len; size = sizeof(data.rsc_tsc->params);
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, 0);
} else { } else {
/* ret = 0;
* firmware only supports TSC/RSC for a single key, WARN_ON_ONCE(1);
* so if there are multiple keep overwriting them goto out;
* with new ones -- this relies on mac80211 doing
* list_add_tail().
*/
mvm->gtk_ivlen = key->iv_len;
mvm->gtk_icvlen = key->icv_len;
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, 1);
}
mutex_unlock(&mvm->mutex);
data->error = ret != 0;
} }
ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_get_rsc_tsc_data,
&data);
if (data.have_rsc_tsc)
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_TSC_RSC_PARAM,
CMD_ASYNC, size, data.rsc_tsc);
else
ret = 0;
out:
kfree(data.rsc_tsc);
return ret;
} }
struct wowlan_key_tkip_data { struct wowlan_key_tkip_data {
...@@ -753,7 +821,6 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm, ...@@ -753,7 +821,6 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
struct wowlan_key_data key_data = { struct wowlan_key_data key_data = {
.configure_keys = !unified, .configure_keys = !unified,
.use_rsc_tsc = false,
.kek_kck_cmd = _kek_kck_cmd, .kek_kck_cmd = _kek_kck_cmd,
}; };
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
...@@ -761,10 +828,6 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm, ...@@ -761,10 +828,6 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
u8 cmd_ver; u8 cmd_ver;
size_t cmd_size; size_t cmd_size;
key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
if (!key_data.rsc_tsc)
return -ENOMEM;
/* /*
* if we have to configure keys, call ieee80211_iter_keys(), * if we have to configure keys, call ieee80211_iter_keys(),
* as we need non-atomic context in order to take the * as we need non-atomic context in order to take the
...@@ -779,37 +842,12 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm, ...@@ -779,37 +842,12 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_program_keys, ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_program_keys,
&key_data); &key_data);
if (key_data.error) { if (key_data.error)
ret = -EIO; return -EIO;
goto out;
}
if (key_data.use_rsc_tsc) {
int ver = iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
WOWLAN_TSC_RSC_PARAM,
IWL_FW_CMD_VER_UNKNOWN);
int size;
if (ver == 4) {
size = sizeof(*key_data.rsc_tsc);
key_data.rsc_tsc->sta_id =
cpu_to_le32(mvmvif->ap_sta_id);
} else if (ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) {
size = sizeof(key_data.rsc_tsc->params);
} else {
ret = 0;
WARN_ON_ONCE(1);
goto out;
}
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_TSC_RSC_PARAM,
CMD_ASYNC, size,
key_data.rsc_tsc);
ret = iwl_mvm_wowlan_config_rsc_tsc(mvm, vif);
if (ret) if (ret)
goto out; return ret;
}
if (!fw_has_api(&mvm->fw->ucode_capa, if (!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_TKIP_MIC_KEYS)) { IWL_UCODE_TLV_API_TKIP_MIC_KEYS)) {
...@@ -826,9 +864,8 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm, ...@@ -826,9 +864,8 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
} else if (ver == 1 || ver == IWL_FW_CMD_VER_UNKNOWN) { } else if (ver == 1 || ver == IWL_FW_CMD_VER_UNKNOWN) {
size = sizeof(struct iwl_wowlan_tkip_params_cmd_ver_1); size = sizeof(struct iwl_wowlan_tkip_params_cmd_ver_1);
} else { } else {
ret = -EINVAL;
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
goto out; return -EINVAL;
} }
ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_get_tkip_data, ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_get_tkip_data,
...@@ -841,7 +878,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm, ...@@ -841,7 +878,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
CMD_ASYNC, size, CMD_ASYNC, size,
&tkip_data.tkip); &tkip_data.tkip);
if (ret) if (ret)
goto out; return ret;
} }
} }
...@@ -885,12 +922,10 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm, ...@@ -885,12 +922,10 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_KEK_KCK_MATERIAL, ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_KEK_KCK_MATERIAL,
CMD_ASYNC, cmd_size, _kek_kck_cmd); CMD_ASYNC, cmd_size, _kek_kck_cmd);
if (ret) if (ret)
goto out;
}
ret = 0;
out:
kfree(key_data.rsc_tsc);
return ret; return ret;
}
return 0;
} }
static int static int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment