From bbd89bfca0b446d605c4cc38cedf55eb81d0eed7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 3 Jan 2015 01:01:42 +0200 Subject: [PATCH] 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 --- src/drivers/driver_nl80211.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 05521fb53..74f576290 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); }