iwlwifi: mvm: scrub key material in firmware dumps
Use the previously added infrastructure to scrub key material in firmware dumps: * in the TX FIFO data, just search for each key that we know about and override such data * scrub various commands that we sent to the firmware if they're present * in firmware memory, where advertised by firmware TLVs Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Link: https://lore.kernel.org/r/iwlwifi.20211017123741.d1514964e6a7.I18f8c2ce8082952af7cfe5f8fe75fe51851b8853@changeid Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
fad92a1d11
commit
12d60c1efc
@ -725,6 +725,183 @@ static int iwl_mvm_start_post_nvm(struct iwl_mvm *mvm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iwl_mvm_frob_txf_data {
|
||||
u8 *buf;
|
||||
size_t buflen;
|
||||
};
|
||||
|
||||
static void iwl_mvm_frob_txf_key_iter(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key,
|
||||
void *data)
|
||||
{
|
||||
struct iwl_mvm_frob_txf_data *txf = data;
|
||||
u8 keylen, match, matchend;
|
||||
u8 *keydata;
|
||||
size_t i;
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
keydata = key->key;
|
||||
keylen = key->keylen;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
/*
|
||||
* WEP has short keys which might show up in the payload,
|
||||
* and then you can deduce the key, so in this case just
|
||||
* remove all FIFO data.
|
||||
* For TKIP, we don't know the phase 2 keys here, so same.
|
||||
*/
|
||||
memset(txf->buf, 0xBB, txf->buflen);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* scan for key material and clear it out */
|
||||
match = 0;
|
||||
for (i = 0; i < txf->buflen; i++) {
|
||||
if (txf->buf[i] != keydata[match]) {
|
||||
match = 0;
|
||||
continue;
|
||||
}
|
||||
match++;
|
||||
if (match == keylen) {
|
||||
memset(txf->buf + i - keylen, 0xAA, keylen);
|
||||
match = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* we're dealing with a FIFO, so check wrapped around data */
|
||||
matchend = match;
|
||||
for (i = 0; match && i < keylen - match; i++) {
|
||||
if (txf->buf[i] != keydata[match])
|
||||
break;
|
||||
match++;
|
||||
if (match == keylen) {
|
||||
memset(txf->buf, 0xAA, i + 1);
|
||||
memset(txf->buf + txf->buflen - matchend, 0xAA,
|
||||
matchend);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_frob_txf(void *ctx, void *buf, size_t buflen)
|
||||
{
|
||||
struct iwl_mvm_frob_txf_data txf = {
|
||||
.buf = buf,
|
||||
.buflen = buflen,
|
||||
};
|
||||
struct iwl_mvm *mvm = ctx;
|
||||
|
||||
/* embedded key material exists only on old API */
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
ieee80211_iter_keys_rcu(mvm->hw, NULL, iwl_mvm_frob_txf_key_iter, &txf);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void iwl_mvm_frob_hcmd(void *ctx, void *hcmd, size_t len)
|
||||
{
|
||||
/* we only use wide headers for commands */
|
||||
struct iwl_cmd_header_wide *hdr = hcmd;
|
||||
unsigned int frob_start = sizeof(*hdr), frob_end = 0;
|
||||
|
||||
if (len < sizeof(hdr))
|
||||
return;
|
||||
|
||||
/* all the commands we care about are in LONG_GROUP */
|
||||
if (hdr->group_id != LONG_GROUP)
|
||||
return;
|
||||
|
||||
switch (hdr->cmd) {
|
||||
case WEP_KEY:
|
||||
case WOWLAN_TKIP_PARAM:
|
||||
case WOWLAN_KEK_KCK_MATERIAL:
|
||||
case ADD_STA_KEY:
|
||||
/*
|
||||
* blank out everything here, easier than dealing
|
||||
* with the various versions of the command
|
||||
*/
|
||||
frob_end = INT_MAX;
|
||||
break;
|
||||
case MGMT_MCAST_KEY:
|
||||
frob_start = offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk);
|
||||
BUILD_BUG_ON(offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk) !=
|
||||
offsetof(struct iwl_mvm_mgmt_mcast_key_cmd_v1, igtk));
|
||||
|
||||
frob_end = offsetofend(struct iwl_mvm_mgmt_mcast_key_cmd, igtk);
|
||||
BUILD_BUG_ON(offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk) <
|
||||
offsetof(struct iwl_mvm_mgmt_mcast_key_cmd_v1, igtk));
|
||||
break;
|
||||
}
|
||||
|
||||
if (frob_start >= frob_end)
|
||||
return;
|
||||
|
||||
if (frob_end > len)
|
||||
frob_end = len;
|
||||
|
||||
memset((u8 *)hcmd + frob_start, 0xAA, frob_end - frob_start);
|
||||
}
|
||||
|
||||
static void iwl_mvm_frob_mem(void *ctx, u32 mem_addr, void *mem, size_t buflen)
|
||||
{
|
||||
const struct iwl_dump_exclude *excl;
|
||||
struct iwl_mvm *mvm = ctx;
|
||||
int i;
|
||||
|
||||
switch (mvm->fwrt.cur_fw_img) {
|
||||
case IWL_UCODE_INIT:
|
||||
default:
|
||||
/* not relevant */
|
||||
return;
|
||||
case IWL_UCODE_REGULAR:
|
||||
case IWL_UCODE_REGULAR_USNIFFER:
|
||||
excl = mvm->fw->dump_excl;
|
||||
break;
|
||||
case IWL_UCODE_WOWLAN:
|
||||
excl = mvm->fw->dump_excl_wowlan;
|
||||
break;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(sizeof(mvm->fw->dump_excl) !=
|
||||
sizeof(mvm->fw->dump_excl_wowlan));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mvm->fw->dump_excl); i++) {
|
||||
u32 start, end;
|
||||
|
||||
if (!excl[i].addr || !excl[i].size)
|
||||
continue;
|
||||
|
||||
start = excl[i].addr;
|
||||
end = start + excl[i].size;
|
||||
|
||||
if (end <= mem_addr || start >= mem_addr + buflen)
|
||||
continue;
|
||||
|
||||
if (start < mem_addr)
|
||||
start = mem_addr;
|
||||
|
||||
if (end > mem_addr + buflen)
|
||||
end = mem_addr + buflen;
|
||||
|
||||
memset((u8 *)mem + start - mem_addr, 0xAA, end - start);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct iwl_dump_sanitize_ops iwl_mvm_sanitize_ops = {
|
||||
.frob_txf = iwl_mvm_frob_txf,
|
||||
.frob_hcmd = iwl_mvm_frob_hcmd,
|
||||
.frob_mem = iwl_mvm_frob_mem,
|
||||
};
|
||||
|
||||
static struct iwl_op_mode *
|
||||
iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
const struct iwl_fw *fw, struct dentry *dbgfs_dir)
|
||||
@ -774,7 +951,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
mvm->hw = hw;
|
||||
|
||||
iwl_fw_runtime_init(&mvm->fwrt, trans, fw, &iwl_mvm_fwrt_ops, mvm,
|
||||
NULL, NULL, dbgfs_dir);
|
||||
&iwl_mvm_sanitize_ops, mvm, dbgfs_dir);
|
||||
|
||||
iwl_mvm_get_acpi_tables(mvm);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user