aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2015-01-02 23:01:42 (GMT)
committerJouni Malinen <j@w1.fi>2015-01-02 23:15:34 (GMT)
commitbbd89bfca0b446d605c4cc38cedf55eb81d0eed7 (patch)
tree00bd3d84a016d9f4ef02f2c00c510aa088fc5516
parentf2535da8790df8a44a441a6ca3a9a77b6beb1d78 (diff)
downloadhostap-bbd89bfca0b446d605c4cc38cedf55eb81d0eed7.zip
hostap-bbd89bfca0b446d605c4cc38cedf55eb81d0eed7.tar.gz
hostap-bbd89bfca0b446d605c4cc38cedf55eb81d0eed7.tar.bz2
nl80211: Clear nlmsg payload with keys before freeing
This reduces the time possible keys could remain in heap memory. Couple of the nl80211 messages include keys (TK for normal ciphers and KCK/KEK/PMK for various offloading cases). Signed-off-by: Jouni Malinen <j@w1.fi>
-rw-r--r--src/drivers/driver_nl80211.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 05521fb..74f5762 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -281,6 +281,22 @@ static int no_seq_check(struct nl_msg *msg, void *arg)
}
+static void nl80211_nlmsg_clear(struct nl_msg *msg)
+{
+ /*
+ * Clear nlmsg data, e.g., to make sure key material is not left in
+ * heap memory for unnecessarily long time.
+ */
+ if (msg) {
+ struct nlmsghdr *hdr = nlmsg_hdr(msg);
+ void *data = nlmsg_data(hdr);
+ int len = nlmsg_datalen(hdr);
+
+ os_memset(data, 0, len);
+ }
+}
+
+
static int send_and_recv(struct nl80211_global *global,
struct nl_handle *nl_handle, struct nl_msg *msg,
int (*valid_handler)(struct nl_msg *, void *),
@@ -320,6 +336,8 @@ static int send_and_recv(struct nl80211_global *global,
}
out:
nl_cb_put(cb);
+ if (!valid_handler && valid_data == (void *) -1)
+ nl80211_nlmsg_clear(msg);
nlmsg_free(msg);
return err;
}
@@ -2331,10 +2349,11 @@ static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY) ||
nla_put(msg, NL80211_ATTR_VENDOR_DATA, key_len, key)) {
+ nl80211_nlmsg_clear(msg);
nlmsg_free(msg);
return -1;
}
- ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1);
if (ret) {
wpa_printf(MSG_DEBUG,
"nl80211: Key management set key failed: ret=%d (%s)",
@@ -2426,7 +2445,7 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
goto fail;
- ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL);
if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
ret = 0;
if (ret)
@@ -2477,6 +2496,7 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
return ret;
fail:
+ nl80211_nlmsg_clear(msg);
nlmsg_free(msg);
return -ENOBUFS;
}
@@ -6717,13 +6737,14 @@ static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,
nla_put(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck) ||
nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
replay_ctr)) {
+ nl80211_nlmsg_clear(msg);
nlmsg_free(msg);
return;
}
nla_nest_end(msg, replay_nested);
- send_and_recv_msgs(drv, msg, NULL, NULL);
+ send_and_recv_msgs(drv, msg, NULL, (void *) -1);
}