diff options
Diffstat (limited to 'net/mac80211/wpa.c')
-rw-r--r-- | net/mac80211/wpa.c | 44 |
1 files changed, 20 insertions, 24 deletions
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index c9edfcb7a13b..d65728220763 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -301,22 +301,16 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
301 | } | 301 | } |
302 | 302 | ||
303 | 303 | ||
304 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | 304 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, |
305 | int encrypted) | 305 | int encrypted) |
306 | { | 306 | { |
307 | __le16 mask_fc; | 307 | __le16 mask_fc; |
308 | int a4_included, mgmt; | 308 | int a4_included, mgmt; |
309 | u8 qos_tid; | 309 | u8 qos_tid; |
310 | u8 *b_0, *aad; | 310 | u16 len_a; |
311 | u16 data_len, len_a; | ||
312 | unsigned int hdrlen; | 311 | unsigned int hdrlen; |
313 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 312 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
314 | 313 | ||
315 | memset(scratch, 0, 6 * AES_BLOCK_SIZE); | ||
316 | |||
317 | b_0 = scratch + 3 * AES_BLOCK_SIZE; | ||
318 | aad = scratch + 4 * AES_BLOCK_SIZE; | ||
319 | |||
320 | /* | 314 | /* |
321 | * Mask FC: zero subtype b4 b5 b6 (if not mgmt) | 315 | * Mask FC: zero subtype b4 b5 b6 (if not mgmt) |
322 | * Retry, PwrMgt, MoreData; set Protected | 316 | * Retry, PwrMgt, MoreData; set Protected |
@@ -338,20 +332,21 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | |||
338 | else | 332 | else |
339 | qos_tid = 0; | 333 | qos_tid = 0; |
340 | 334 | ||
341 | data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN; | 335 | /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC |
342 | if (encrypted) | 336 | * mode authentication are not allowed to collide, yet both are derived |
343 | data_len -= IEEE80211_CCMP_MIC_LEN; | 337 | * from this vector b_0. We only set L := 1 here to indicate that the |
338 | * data size can be represented in (L+1) bytes. The CCM layer will take | ||
339 | * care of storing the data length in the top (L+1) bytes and setting | ||
340 | * and clearing the other bits as is required to derive the two IVs. | ||
341 | */ | ||
342 | b_0[0] = 0x1; | ||
344 | 343 | ||
345 | /* First block, b_0 */ | ||
346 | b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ | ||
347 | /* Nonce: Nonce Flags | A2 | PN | 344 | /* Nonce: Nonce Flags | A2 | PN |
348 | * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) | 345 | * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) |
349 | */ | 346 | */ |
350 | b_0[1] = qos_tid | (mgmt << 4); | 347 | b_0[1] = qos_tid | (mgmt << 4); |
351 | memcpy(&b_0[2], hdr->addr2, ETH_ALEN); | 348 | memcpy(&b_0[2], hdr->addr2, ETH_ALEN); |
352 | memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); | 349 | memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); |
353 | /* l(m) */ | ||
354 | put_unaligned_be16(data_len, &b_0[14]); | ||
355 | 350 | ||
356 | /* AAD (extra authenticate-only data) / masked 802.11 header | 351 | /* AAD (extra authenticate-only data) / masked 802.11 header |
357 | * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ | 352 | * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ |
@@ -407,7 +402,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
407 | u8 *pos; | 402 | u8 *pos; |
408 | u8 pn[6]; | 403 | u8 pn[6]; |
409 | u64 pn64; | 404 | u64 pn64; |
410 | u8 scratch[6 * AES_BLOCK_SIZE]; | 405 | u8 aad[2 * AES_BLOCK_SIZE]; |
406 | u8 b_0[AES_BLOCK_SIZE]; | ||
411 | 407 | ||
412 | if (info->control.hw_key && | 408 | if (info->control.hw_key && |
413 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && | 409 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && |
@@ -460,9 +456,9 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
460 | return 0; | 456 | return 0; |
461 | 457 | ||
462 | pos += IEEE80211_CCMP_HDR_LEN; | 458 | pos += IEEE80211_CCMP_HDR_LEN; |
463 | ccmp_special_blocks(skb, pn, scratch, 0); | 459 | ccmp_special_blocks(skb, pn, b_0, aad, 0); |
464 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, | 460 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, |
465 | pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN)); | 461 | skb_put(skb, IEEE80211_CCMP_MIC_LEN)); |
466 | 462 | ||
467 | return 0; | 463 | return 0; |
468 | } | 464 | } |
@@ -525,16 +521,16 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
525 | } | 521 | } |
526 | 522 | ||
527 | if (!(status->flag & RX_FLAG_DECRYPTED)) { | 523 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
528 | u8 scratch[6 * AES_BLOCK_SIZE]; | 524 | u8 aad[2 * AES_BLOCK_SIZE]; |
525 | u8 b_0[AES_BLOCK_SIZE]; | ||
529 | /* hardware didn't decrypt/verify MIC */ | 526 | /* hardware didn't decrypt/verify MIC */ |
530 | ccmp_special_blocks(skb, pn, scratch, 1); | 527 | ccmp_special_blocks(skb, pn, b_0, aad, 1); |
531 | 528 | ||
532 | if (ieee80211_aes_ccm_decrypt( | 529 | if (ieee80211_aes_ccm_decrypt( |
533 | key->u.ccmp.tfm, scratch, | 530 | key->u.ccmp.tfm, b_0, aad, |
534 | skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, | 531 | skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, |
535 | data_len, | 532 | data_len, |
536 | skb->data + skb->len - IEEE80211_CCMP_MIC_LEN, | 533 | skb->data + skb->len - IEEE80211_CCMP_MIC_LEN)) |
537 | skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN)) | ||
538 | return RX_DROP_UNUSABLE; | 534 | return RX_DROP_UNUSABLE; |
539 | } | 535 | } |
540 | 536 | ||