diff options
author | Zhu Yi <yi.zhu@intel.com> | 2006-08-20 23:33:09 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-08-29 17:06:30 -0400 |
commit | b4328d87ec5711543b818fea2e1cf64f09d326f1 (patch) | |
tree | c458073bed1b554b0f1a64fc5cd27b16181e6c90 | |
parent | 051562f7e980b53f7bc6529f2e55b68e20f5d0e6 (diff) |
[PATCH] ieee80211: TKIP and CCMP replay check rework
Signed-off-by: Hong Liu <hong.liu@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | net/ieee80211/ieee80211_crypt_ccmp.c | 23 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_crypt_tkip.c | 16 |
2 files changed, 36 insertions, 3 deletions
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c index ed90a8af1444..098c66846339 100644 --- a/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/net/ieee80211/ieee80211_crypt_ccmp.c | |||
@@ -271,6 +271,27 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
271 | return 0; | 271 | return 0; |
272 | } | 272 | } |
273 | 273 | ||
274 | /* | ||
275 | * deal with seq counter wrapping correctly. | ||
276 | * refer to timer_after() for jiffies wrapping handling | ||
277 | */ | ||
278 | static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o) | ||
279 | { | ||
280 | u32 iv32_n, iv16_n; | ||
281 | u32 iv32_o, iv16_o; | ||
282 | |||
283 | iv32_n = (pn_n[0] << 24) | (pn_n[1] << 16) | (pn_n[2] << 8) | pn_n[3]; | ||
284 | iv16_n = (pn_n[4] << 8) | pn_n[5]; | ||
285 | |||
286 | iv32_o = (pn_o[0] << 24) | (pn_o[1] << 16) | (pn_o[2] << 8) | pn_o[3]; | ||
287 | iv16_o = (pn_o[4] << 8) | pn_o[5]; | ||
288 | |||
289 | if ((s32)iv32_n - (s32)iv32_o < 0 || | ||
290 | (iv32_n == iv32_o && iv16_n <= iv16_o)) | ||
291 | return 1; | ||
292 | return 0; | ||
293 | } | ||
294 | |||
274 | static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | 295 | static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
275 | { | 296 | { |
276 | struct ieee80211_ccmp_data *key = priv; | 297 | struct ieee80211_ccmp_data *key = priv; |
@@ -323,7 +344,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
323 | pn[5] = pos[0]; | 344 | pn[5] = pos[0]; |
324 | pos += 8; | 345 | pos += 8; |
325 | 346 | ||
326 | if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { | 347 | if (ccmp_replay_check(pn, key->rx_pn)) { |
327 | if (net_ratelimit()) { | 348 | if (net_ratelimit()) { |
328 | printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT | 349 | printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT |
329 | " previous PN %02x%02x%02x%02x%02x%02x " | 350 | " previous PN %02x%02x%02x%02x%02x%02x " |
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index a61b09ef70f2..02abf2985b84 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c | |||
@@ -360,6 +360,19 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
360 | return 0; | 360 | return 0; |
361 | } | 361 | } |
362 | 362 | ||
363 | /* | ||
364 | * deal with seq counter wrapping correctly. | ||
365 | * refer to timer_after() for jiffies wrapping handling | ||
366 | */ | ||
367 | static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n, | ||
368 | u32 iv32_o, u16 iv16_o) | ||
369 | { | ||
370 | if ((s32)iv32_n - (s32)iv32_o < 0 || | ||
371 | (iv32_n == iv32_o && iv16_n <= iv16_o)) | ||
372 | return 1; | ||
373 | return 0; | ||
374 | } | ||
375 | |||
363 | static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | 376 | static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
364 | { | 377 | { |
365 | struct ieee80211_tkip_data *tkey = priv; | 378 | struct ieee80211_tkip_data *tkey = priv; |
@@ -414,8 +427,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
414 | iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); | 427 | iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); |
415 | pos += 8; | 428 | pos += 8; |
416 | 429 | ||
417 | if (iv32 < tkey->rx_iv32 || | 430 | if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { |
418 | (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) { | ||
419 | if (net_ratelimit()) { | 431 | if (net_ratelimit()) { |
420 | printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT | 432 | printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT |
421 | " previous TSC %08x%04x received TSC " | 433 | " previous TSC %08x%04x received TSC " |