diff options
Diffstat (limited to 'net/mac80211/wpa.c')
| -rw-r--r-- | net/mac80211/wpa.c | 72 |
1 files changed, 31 insertions, 41 deletions
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 5332014cb229..8d59d27d887e 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
| @@ -9,10 +9,10 @@ | |||
| 9 | 9 | ||
| 10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
| 11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
| 12 | #include <linux/slab.h> | ||
| 13 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
| 14 | #include <linux/compiler.h> | 13 | #include <linux/compiler.h> |
| 15 | #include <linux/ieee80211.h> | 14 | #include <linux/ieee80211.h> |
| 15 | #include <linux/gfp.h> | ||
| 16 | #include <asm/unaligned.h> | 16 | #include <asm/unaligned.h> |
| 17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
| 18 | 18 | ||
| @@ -31,8 +31,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
| 31 | unsigned int hdrlen; | 31 | unsigned int hdrlen; |
| 32 | struct ieee80211_hdr *hdr; | 32 | struct ieee80211_hdr *hdr; |
| 33 | struct sk_buff *skb = tx->skb; | 33 | struct sk_buff *skb = tx->skb; |
| 34 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 34 | int authenticator; | 35 | int authenticator; |
| 35 | int wpa_test = 0; | ||
| 36 | int tail; | 36 | int tail; |
| 37 | 37 | ||
| 38 | hdr = (struct ieee80211_hdr *)skb->data; | 38 | hdr = (struct ieee80211_hdr *)skb->data; |
| @@ -47,16 +47,15 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
| 47 | data = skb->data + hdrlen; | 47 | data = skb->data + hdrlen; |
| 48 | data_len = skb->len - hdrlen; | 48 | data_len = skb->len - hdrlen; |
| 49 | 49 | ||
| 50 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 50 | if (info->control.hw_key && |
| 51 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && | 51 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && |
| 52 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) && | 52 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
| 53 | !wpa_test) { | 53 | /* hwaccel - with no need for SW-generated MMIC */ |
| 54 | /* hwaccel - with no need for preallocated room for MMIC */ | ||
| 55 | return TX_CONTINUE; | 54 | return TX_CONTINUE; |
| 56 | } | 55 | } |
| 57 | 56 | ||
| 58 | tail = MICHAEL_MIC_LEN; | 57 | tail = MICHAEL_MIC_LEN; |
| 59 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 58 | if (!info->control.hw_key) |
| 60 | tail += TKIP_ICV_LEN; | 59 | tail += TKIP_ICV_LEN; |
| 61 | 60 | ||
| 62 | if (WARN_ON(skb_tailroom(skb) < tail || | 61 | if (WARN_ON(skb_tailroom(skb) < tail || |
| @@ -147,17 +146,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
| 147 | int len, tail; | 146 | int len, tail; |
| 148 | u8 *pos; | 147 | u8 *pos; |
| 149 | 148 | ||
| 150 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 149 | if (info->control.hw_key && |
| 151 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 150 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
| 152 | /* hwaccel - with no need for preallocated room for IV/ICV */ | 151 | /* hwaccel - with no need for software-generated IV */ |
| 153 | info->control.hw_key = &tx->key->conf; | ||
| 154 | return 0; | 152 | return 0; |
| 155 | } | 153 | } |
| 156 | 154 | ||
| 157 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 155 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
| 158 | len = skb->len - hdrlen; | 156 | len = skb->len - hdrlen; |
| 159 | 157 | ||
| 160 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 158 | if (info->control.hw_key) |
| 161 | tail = 0; | 159 | tail = 0; |
| 162 | else | 160 | else |
| 163 | tail = TKIP_ICV_LEN; | 161 | tail = TKIP_ICV_LEN; |
| @@ -175,21 +173,18 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
| 175 | if (key->u.tkip.tx.iv16 == 0) | 173 | if (key->u.tkip.tx.iv16 == 0) |
| 176 | key->u.tkip.tx.iv32++; | 174 | key->u.tkip.tx.iv32++; |
| 177 | 175 | ||
| 178 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 176 | pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); |
| 179 | /* hwaccel - with preallocated room for IV */ | ||
| 180 | ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); | ||
| 181 | 177 | ||
| 182 | info->control.hw_key = &tx->key->conf; | 178 | /* hwaccel - with software IV */ |
| 179 | if (info->control.hw_key) | ||
| 183 | return 0; | 180 | return 0; |
| 184 | } | ||
| 185 | 181 | ||
| 186 | /* Add room for ICV */ | 182 | /* Add room for ICV */ |
| 187 | skb_put(skb, TKIP_ICV_LEN); | 183 | skb_put(skb, TKIP_ICV_LEN); |
| 188 | 184 | ||
| 189 | hdr = (struct ieee80211_hdr *) skb->data; | 185 | hdr = (struct ieee80211_hdr *) skb->data; |
| 190 | ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, | 186 | return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, |
| 191 | key, pos, len, hdr->addr2); | 187 | key, pos, len, hdr->addr2); |
| 192 | return 0; | ||
| 193 | } | 188 | } |
| 194 | 189 | ||
| 195 | 190 | ||
| @@ -363,24 +358,20 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
| 363 | int hdrlen, len, tail; | 358 | int hdrlen, len, tail; |
| 364 | u8 *pos, *pn; | 359 | u8 *pos, *pn; |
| 365 | int i; | 360 | int i; |
| 366 | bool skip_hw; | ||
| 367 | |||
| 368 | skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) && | ||
| 369 | ieee80211_is_mgmt(hdr->frame_control); | ||
| 370 | 361 | ||
| 371 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 362 | if (info->control.hw_key && |
| 372 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) && | 363 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
| 373 | !skip_hw) { | 364 | /* |
| 374 | /* hwaccel - with no need for preallocated room for CCMP | 365 | * hwaccel has no need for preallocated room for CCMP |
| 375 | * header or MIC fields */ | 366 | * header or MIC fields |
| 376 | info->control.hw_key = &tx->key->conf; | 367 | */ |
| 377 | return 0; | 368 | return 0; |
| 378 | } | 369 | } |
| 379 | 370 | ||
| 380 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 371 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
| 381 | len = skb->len - hdrlen; | 372 | len = skb->len - hdrlen; |
| 382 | 373 | ||
| 383 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 374 | if (info->control.hw_key) |
| 384 | tail = 0; | 375 | tail = 0; |
| 385 | else | 376 | else |
| 386 | tail = CCMP_MIC_LEN; | 377 | tail = CCMP_MIC_LEN; |
| @@ -405,11 +396,9 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
| 405 | 396 | ||
| 406 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); | 397 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); |
| 407 | 398 | ||
| 408 | if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) { | 399 | /* hwaccel - with software CCMP header */ |
| 409 | /* hwaccel - with preallocated room for CCMP header */ | 400 | if (info->control.hw_key) |
| 410 | info->control.hw_key = &tx->key->conf; | ||
| 411 | return 0; | 401 | return 0; |
| 412 | } | ||
| 413 | 402 | ||
| 414 | pos += CCMP_HDR_LEN; | 403 | pos += CCMP_HDR_LEN; |
| 415 | ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); | 404 | ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); |
| @@ -446,6 +435,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
| 446 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 435 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
| 447 | u8 pn[CCMP_PN_LEN]; | 436 | u8 pn[CCMP_PN_LEN]; |
| 448 | int data_len; | 437 | int data_len; |
| 438 | int queue; | ||
| 449 | 439 | ||
| 450 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 440 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
| 451 | 441 | ||
| @@ -463,7 +453,10 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
| 463 | 453 | ||
| 464 | ccmp_hdr2pn(pn, skb->data + hdrlen); | 454 | ccmp_hdr2pn(pn, skb->data + hdrlen); |
| 465 | 455 | ||
| 466 | if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) { | 456 | queue = ieee80211_is_mgmt(hdr->frame_control) ? |
| 457 | NUM_RX_DATA_QUEUES : rx->queue; | ||
| 458 | |||
| 459 | if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) { | ||
| 467 | key->u.ccmp.replays++; | 460 | key->u.ccmp.replays++; |
| 468 | return RX_DROP_UNUSABLE; | 461 | return RX_DROP_UNUSABLE; |
| 469 | } | 462 | } |
| @@ -480,7 +473,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
| 480 | return RX_DROP_UNUSABLE; | 473 | return RX_DROP_UNUSABLE; |
| 481 | } | 474 | } |
| 482 | 475 | ||
| 483 | memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN); | 476 | memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); |
| 484 | 477 | ||
| 485 | /* Remove CCMP header and MIC */ | 478 | /* Remove CCMP header and MIC */ |
| 486 | skb_trim(skb, skb->len - CCMP_MIC_LEN); | 479 | skb_trim(skb, skb->len - CCMP_MIC_LEN); |
| @@ -525,11 +518,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) | |||
| 525 | u8 *pn, aad[20]; | 518 | u8 *pn, aad[20]; |
| 526 | int i; | 519 | int i; |
| 527 | 520 | ||
| 528 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 521 | if (info->control.hw_key) |
| 529 | /* hwaccel */ | ||
| 530 | info->control.hw_key = &tx->key->conf; | ||
| 531 | return 0; | 522 | return 0; |
| 532 | } | ||
| 533 | 523 | ||
| 534 | if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) | 524 | if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) |
| 535 | return TX_DROP; | 525 | return TX_DROP; |
