aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/wpa.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/wpa.c')
-rw-r--r--net/mac80211/wpa.c72
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;