Commit ca99861d authored by gregor kowski's avatar gregor kowski Committed by John W. Linville

mac80211 : fix a race with update_tkip_key

The mac80211 tkip code won't call update_tkip_key, if rx packets
are received without KEY_FLAG_UPLOADED_TO_HARDWARE. This can happen on
first packet because the hardware key stuff is called asynchronously with
todo workqueue.

This patch workaround that by tracking if we sent the key to the driver.
Signed-off-by: default avatarGregor Kowski <gregor.kowski@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e54be4e7
...@@ -59,11 +59,17 @@ enum ieee80211_internal_key_flags { ...@@ -59,11 +59,17 @@ enum ieee80211_internal_key_flags {
KEY_FLAG_TODO_DEFMGMTKEY = BIT(6), KEY_FLAG_TODO_DEFMGMTKEY = BIT(6),
}; };
enum ieee80211_internal_tkip_state {
TKIP_STATE_NOT_INIT,
TKIP_STATE_PHASE1_DONE,
TKIP_STATE_PHASE1_HW_UPLOADED,
};
struct tkip_ctx { struct tkip_ctx {
u32 iv32; u32 iv32;
u16 iv16; u16 iv16;
u16 p1k[5]; u16 p1k[5];
int initialized; enum ieee80211_internal_tkip_state state;
}; };
struct ieee80211_key { struct ieee80211_key {
......
...@@ -100,7 +100,7 @@ static void tkip_mixing_phase1(const u8 *tk, struct tkip_ctx *ctx, ...@@ -100,7 +100,7 @@ static void tkip_mixing_phase1(const u8 *tk, struct tkip_ctx *ctx,
p1k[3] += tkipS(p1k[2] ^ get_unaligned_le16(tk + 12 + j)); p1k[3] += tkipS(p1k[2] ^ get_unaligned_le16(tk + 12 + j));
p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i;
} }
ctx->initialized = 1; ctx->state = TKIP_STATE_PHASE1_DONE;
} }
static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx,
...@@ -183,7 +183,7 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, ...@@ -183,7 +183,7 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
/* Update the p1k only when the iv16 in the packet wraps around, this /* Update the p1k only when the iv16 in the packet wraps around, this
* might occur after the wrap around of iv16 in the key in case of * might occur after the wrap around of iv16 in the key in case of
* fragmented packets. */ * fragmented packets. */
if (iv16 == 0 || !ctx->initialized) if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32); tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32);
if (type == IEEE80211_TKIP_P1_KEY) { if (type == IEEE80211_TKIP_P1_KEY) {
...@@ -209,7 +209,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, ...@@ -209,7 +209,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
/* Calculate per-packet key */ /* Calculate per-packet key */
if (ctx->iv16 == 0 || !ctx->initialized) if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
tkip_mixing_phase1(tk, ctx, ta, ctx->iv32); tkip_mixing_phase1(tk, ctx, ta, ctx->iv32);
tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key);
...@@ -259,7 +259,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, ...@@ -259,7 +259,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
if ((keyid >> 6) != key->conf.keyidx) if ((keyid >> 6) != key->conf.keyidx)
return TKIP_DECRYPT_INVALID_KEYIDX; return TKIP_DECRYPT_INVALID_KEYIDX;
if (key->u.tkip.rx[queue].initialized && if (key->u.tkip.rx[queue].state != TKIP_STATE_NOT_INIT &&
(iv32 < key->u.tkip.rx[queue].iv32 || (iv32 < key->u.tkip.rx[queue].iv32 ||
(iv32 == key->u.tkip.rx[queue].iv32 && (iv32 == key->u.tkip.rx[queue].iv32 &&
iv16 <= key->u.tkip.rx[queue].iv16))) { iv16 <= key->u.tkip.rx[queue].iv16))) {
...@@ -275,11 +275,11 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, ...@@ -275,11 +275,11 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
if (only_iv) { if (only_iv) {
res = TKIP_DECRYPT_OK; res = TKIP_DECRYPT_OK;
key->u.tkip.rx[queue].initialized = 1; key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED;
goto done; goto done;
} }
if (!key->u.tkip.rx[queue].initialized || if (key->u.tkip.rx[queue].state == TKIP_STATE_NOT_INIT ||
key->u.tkip.rx[queue].iv32 != iv32) { key->u.tkip.rx[queue].iv32 != iv32) {
/* IV16 wrapped around - perform TKIP phase 1 */ /* IV16 wrapped around - perform TKIP phase 1 */
tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32);
...@@ -299,18 +299,20 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, ...@@ -299,18 +299,20 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
printk("\n"); printk("\n");
} }
#endif #endif
if (key->local->ops->update_tkip_key && }
key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { if (key->local->ops->update_tkip_key &&
static const u8 bcast[ETH_ALEN] = key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) {
const u8 *sta_addr = key->sta->sta.addr; static const u8 bcast[ETH_ALEN] =
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
if (is_multicast_ether_addr(ra)) const u8 *sta_addr = key->sta->sta.addr;
sta_addr = bcast;
if (is_multicast_ether_addr(ra))
drv_update_tkip_key(key->local, &key->conf, sta_addr, sta_addr = bcast;
iv32, key->u.tkip.rx[queue].p1k);
} drv_update_tkip_key(key->local, &key->conf, sta_addr,
iv32, key->u.tkip.rx[queue].p1k);
key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED;
} }
tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key);
......
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