diff options
Diffstat (limited to 'net/mac80211/wpa.c')
-rw-r--r-- | net/mac80211/wpa.c | 198 |
1 files changed, 74 insertions, 124 deletions
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 45709ada8fee..345e10e9b313 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -24,46 +24,22 @@ static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da, | |||
24 | { | 24 | { |
25 | struct ieee80211_hdr *hdr; | 25 | struct ieee80211_hdr *hdr; |
26 | size_t hdrlen; | 26 | size_t hdrlen; |
27 | u16 fc; | 27 | __le16 fc; |
28 | int a4_included; | ||
29 | u8 *pos; | ||
30 | 28 | ||
31 | hdr = (struct ieee80211_hdr *) skb->data; | 29 | hdr = (struct ieee80211_hdr *)skb->data; |
32 | fc = le16_to_cpu(hdr->frame_control); | 30 | fc = hdr->frame_control; |
33 | |||
34 | hdrlen = 24; | ||
35 | if ((fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) == | ||
36 | (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { | ||
37 | hdrlen += ETH_ALEN; | ||
38 | *sa = hdr->addr4; | ||
39 | *da = hdr->addr3; | ||
40 | } else if (fc & IEEE80211_FCTL_FROMDS) { | ||
41 | *sa = hdr->addr3; | ||
42 | *da = hdr->addr1; | ||
43 | } else if (fc & IEEE80211_FCTL_TODS) { | ||
44 | *sa = hdr->addr2; | ||
45 | *da = hdr->addr3; | ||
46 | } else { | ||
47 | *sa = hdr->addr2; | ||
48 | *da = hdr->addr1; | ||
49 | } | ||
50 | 31 | ||
51 | if (fc & 0x80) | 32 | hdrlen = ieee80211_hdrlen(fc); |
52 | hdrlen += 2; | 33 | |
34 | *sa = ieee80211_get_SA(hdr); | ||
35 | *da = ieee80211_get_DA(hdr); | ||
53 | 36 | ||
54 | *data = skb->data + hdrlen; | 37 | *data = skb->data + hdrlen; |
55 | *data_len = skb->len - hdrlen; | 38 | *data_len = skb->len - hdrlen; |
56 | 39 | ||
57 | a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == | 40 | if (ieee80211_is_data_qos(fc)) |
58 | (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); | 41 | *qos_tid = (*ieee80211_get_qos_ctl(hdr) & 0x0f) | 0x80; |
59 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && | 42 | else |
60 | fc & IEEE80211_STYPE_QOS_DATA) { | ||
61 | pos = (u8 *) &hdr->addr4; | ||
62 | if (a4_included) | ||
63 | pos += 6; | ||
64 | *qos_tid = pos[0] & 0x0f; | ||
65 | *qos_tid |= 0x80; /* qos_included flag */ | ||
66 | } else | ||
67 | *qos_tid = 0; | 43 | *qos_tid = 0; |
68 | 44 | ||
69 | return skb->len < hdrlen ? -1 : 0; | 45 | return skb->len < hdrlen ? -1 : 0; |
@@ -79,6 +55,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
79 | struct sk_buff *skb = tx->skb; | 55 | struct sk_buff *skb = tx->skb; |
80 | int authenticator; | 56 | int authenticator; |
81 | int wpa_test = 0; | 57 | int wpa_test = 0; |
58 | int tail; | ||
82 | 59 | ||
83 | fc = tx->fc; | 60 | fc = tx->fc; |
84 | 61 | ||
@@ -98,16 +75,13 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
98 | return TX_CONTINUE; | 75 | return TX_CONTINUE; |
99 | } | 76 | } |
100 | 77 | ||
101 | if (skb_tailroom(skb) < MICHAEL_MIC_LEN) { | 78 | tail = MICHAEL_MIC_LEN; |
102 | I802_DEBUG_INC(tx->local->tx_expand_skb_head); | 79 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
103 | if (unlikely(pskb_expand_head(skb, TKIP_IV_LEN, | 80 | tail += TKIP_ICV_LEN; |
104 | MICHAEL_MIC_LEN + TKIP_ICV_LEN, | 81 | |
105 | GFP_ATOMIC))) { | 82 | if (WARN_ON(skb_tailroom(skb) < tail || |
106 | printk(KERN_DEBUG "%s: failed to allocate more memory " | 83 | skb_headroom(skb) < TKIP_IV_LEN)) |
107 | "for Michael MIC\n", tx->dev->name); | 84 | return TX_DROP; |
108 | return TX_DROP; | ||
109 | } | ||
110 | } | ||
111 | 85 | ||
112 | #if 0 | 86 | #if 0 |
113 | authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */ | 87 | authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */ |
@@ -176,59 +150,58 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
176 | skb_trim(skb, skb->len - MICHAEL_MIC_LEN); | 150 | skb_trim(skb, skb->len - MICHAEL_MIC_LEN); |
177 | 151 | ||
178 | /* update IV in key information to be able to detect replays */ | 152 | /* update IV in key information to be able to detect replays */ |
179 | rx->key->u.tkip.iv32_rx[rx->queue] = rx->tkip_iv32; | 153 | rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32; |
180 | rx->key->u.tkip.iv16_rx[rx->queue] = rx->tkip_iv16; | 154 | rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16; |
181 | 155 | ||
182 | return RX_CONTINUE; | 156 | return RX_CONTINUE; |
183 | } | 157 | } |
184 | 158 | ||
185 | 159 | ||
186 | static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, | 160 | static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) |
187 | struct sk_buff *skb, int test) | ||
188 | { | 161 | { |
189 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 162 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
190 | struct ieee80211_key *key = tx->key; | 163 | struct ieee80211_key *key = tx->key; |
191 | int hdrlen, len, tailneed; | 164 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
192 | u16 fc; | 165 | unsigned int hdrlen; |
166 | int len, tail; | ||
193 | u8 *pos; | 167 | u8 *pos; |
194 | 168 | ||
195 | fc = le16_to_cpu(hdr->frame_control); | 169 | info->control.icv_len = TKIP_ICV_LEN; |
196 | hdrlen = ieee80211_get_hdrlen(fc); | 170 | info->control.iv_len = TKIP_IV_LEN; |
171 | |||
172 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | ||
173 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | ||
174 | /* hwaccel - with no need for preallocated room for IV/ICV */ | ||
175 | info->control.hw_key = &tx->key->conf; | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
197 | len = skb->len - hdrlen; | 180 | len = skb->len - hdrlen; |
198 | 181 | ||
199 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 182 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) |
200 | tailneed = 0; | 183 | tail = 0; |
201 | else | 184 | else |
202 | tailneed = TKIP_ICV_LEN; | 185 | tail = TKIP_ICV_LEN; |
203 | 186 | ||
204 | if ((skb_headroom(skb) < TKIP_IV_LEN || | 187 | if (WARN_ON(skb_tailroom(skb) < tail || |
205 | skb_tailroom(skb) < tailneed)) { | 188 | skb_headroom(skb) < TKIP_IV_LEN)) |
206 | I802_DEBUG_INC(tx->local->tx_expand_skb_head); | 189 | return -1; |
207 | if (unlikely(pskb_expand_head(skb, TKIP_IV_LEN, tailneed, | ||
208 | GFP_ATOMIC))) | ||
209 | return -1; | ||
210 | } | ||
211 | 190 | ||
212 | pos = skb_push(skb, TKIP_IV_LEN); | 191 | pos = skb_push(skb, TKIP_IV_LEN); |
213 | memmove(pos, pos + TKIP_IV_LEN, hdrlen); | 192 | memmove(pos, pos + TKIP_IV_LEN, hdrlen); |
214 | pos += hdrlen; | 193 | pos += hdrlen; |
215 | 194 | ||
216 | /* Increase IV for the frame */ | 195 | /* Increase IV for the frame */ |
217 | key->u.tkip.iv16++; | 196 | key->u.tkip.tx.iv16++; |
218 | if (key->u.tkip.iv16 == 0) | 197 | if (key->u.tkip.tx.iv16 == 0) |
219 | key->u.tkip.iv32++; | 198 | key->u.tkip.tx.iv32++; |
220 | 199 | ||
221 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 200 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
222 | hdr = (struct ieee80211_hdr *)skb->data; | ||
223 | |||
224 | /* hwaccel - with preallocated room for IV */ | 201 | /* hwaccel - with preallocated room for IV */ |
225 | ieee80211_tkip_add_iv(pos, key, | 202 | ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); |
226 | (u8) (key->u.tkip.iv16 >> 8), | ||
227 | (u8) (((key->u.tkip.iv16 >> 8) | 0x20) & | ||
228 | 0x7f), | ||
229 | (u8) key->u.tkip.iv16); | ||
230 | 203 | ||
231 | tx->control->key_idx = tx->key->conf.hw_key_idx; | 204 | info->control.hw_key = &tx->key->conf; |
232 | return 0; | 205 | return 0; |
233 | } | 206 | } |
234 | 207 | ||
@@ -246,28 +219,16 @@ ieee80211_tx_result | |||
246 | ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) | 219 | ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) |
247 | { | 220 | { |
248 | struct sk_buff *skb = tx->skb; | 221 | struct sk_buff *skb = tx->skb; |
249 | int wpa_test = 0, test = 0; | ||
250 | 222 | ||
251 | tx->control->icv_len = TKIP_ICV_LEN; | ||
252 | tx->control->iv_len = TKIP_IV_LEN; | ||
253 | ieee80211_tx_set_protected(tx); | 223 | ieee80211_tx_set_protected(tx); |
254 | 224 | ||
255 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 225 | if (tkip_encrypt_skb(tx, skb) < 0) |
256 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) && | ||
257 | !wpa_test) { | ||
258 | /* hwaccel - with no need for preallocated room for IV/ICV */ | ||
259 | tx->control->key_idx = tx->key->conf.hw_key_idx; | ||
260 | return TX_CONTINUE; | ||
261 | } | ||
262 | |||
263 | if (tkip_encrypt_skb(tx, skb, test) < 0) | ||
264 | return TX_DROP; | 226 | return TX_DROP; |
265 | 227 | ||
266 | if (tx->extra_frag) { | 228 | if (tx->extra_frag) { |
267 | int i; | 229 | int i; |
268 | for (i = 0; i < tx->num_extra_frag; i++) { | 230 | for (i = 0; i < tx->num_extra_frag; i++) { |
269 | if (tkip_encrypt_skb(tx, tx->extra_frag[i], test) | 231 | if (tkip_encrypt_skb(tx, tx->extra_frag[i]) < 0) |
270 | < 0) | ||
271 | return TX_DROP; | 232 | return TX_DROP; |
272 | } | 233 | } |
273 | } | 234 | } |
@@ -280,14 +241,12 @@ ieee80211_rx_result | |||
280 | ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | 241 | ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) |
281 | { | 242 | { |
282 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 243 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; |
283 | u16 fc; | ||
284 | int hdrlen, res, hwaccel = 0, wpa_test = 0; | 244 | int hdrlen, res, hwaccel = 0, wpa_test = 0; |
285 | struct ieee80211_key *key = rx->key; | 245 | struct ieee80211_key *key = rx->key; |
286 | struct sk_buff *skb = rx->skb; | 246 | struct sk_buff *skb = rx->skb; |
287 | DECLARE_MAC_BUF(mac); | 247 | DECLARE_MAC_BUF(mac); |
288 | 248 | ||
289 | fc = le16_to_cpu(hdr->frame_control); | 249 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
290 | hdrlen = ieee80211_get_hdrlen(fc); | ||
291 | 250 | ||
292 | if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) | 251 | if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) |
293 | return RX_CONTINUE; | 252 | return RX_CONTINUE; |
@@ -429,36 +388,41 @@ static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr) | |||
429 | } | 388 | } |
430 | 389 | ||
431 | 390 | ||
432 | static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, | 391 | static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) |
433 | struct sk_buff *skb, int test) | ||
434 | { | 392 | { |
435 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 393 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
436 | struct ieee80211_key *key = tx->key; | 394 | struct ieee80211_key *key = tx->key; |
437 | int hdrlen, len, tailneed; | 395 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
438 | u16 fc; | 396 | int hdrlen, len, tail; |
439 | u8 *pos, *pn, *b_0, *aad, *scratch; | 397 | u8 *pos, *pn, *b_0, *aad, *scratch; |
440 | int i; | 398 | int i; |
441 | 399 | ||
400 | info->control.icv_len = CCMP_MIC_LEN; | ||
401 | info->control.iv_len = CCMP_HDR_LEN; | ||
402 | |||
403 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | ||
404 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | ||
405 | /* hwaccel - with no need for preallocated room for CCMP " | ||
406 | * header or MIC fields */ | ||
407 | info->control.hw_key = &tx->key->conf; | ||
408 | return 0; | ||
409 | } | ||
410 | |||
442 | scratch = key->u.ccmp.tx_crypto_buf; | 411 | scratch = key->u.ccmp.tx_crypto_buf; |
443 | b_0 = scratch + 3 * AES_BLOCK_LEN; | 412 | b_0 = scratch + 3 * AES_BLOCK_LEN; |
444 | aad = scratch + 4 * AES_BLOCK_LEN; | 413 | aad = scratch + 4 * AES_BLOCK_LEN; |
445 | 414 | ||
446 | fc = le16_to_cpu(hdr->frame_control); | 415 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
447 | hdrlen = ieee80211_get_hdrlen(fc); | ||
448 | len = skb->len - hdrlen; | 416 | len = skb->len - hdrlen; |
449 | 417 | ||
450 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 418 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) |
451 | tailneed = 0; | 419 | tail = 0; |
452 | else | 420 | else |
453 | tailneed = CCMP_MIC_LEN; | 421 | tail = CCMP_MIC_LEN; |
454 | 422 | ||
455 | if ((skb_headroom(skb) < CCMP_HDR_LEN || | 423 | if (WARN_ON(skb_tailroom(skb) < tail || |
456 | skb_tailroom(skb) < tailneed)) { | 424 | skb_headroom(skb) < CCMP_HDR_LEN)) |
457 | I802_DEBUG_INC(tx->local->tx_expand_skb_head); | 425 | return -1; |
458 | if (unlikely(pskb_expand_head(skb, CCMP_HDR_LEN, tailneed, | ||
459 | GFP_ATOMIC))) | ||
460 | return -1; | ||
461 | } | ||
462 | 426 | ||
463 | pos = skb_push(skb, CCMP_HDR_LEN); | 427 | pos = skb_push(skb, CCMP_HDR_LEN); |
464 | memmove(pos, pos + CCMP_HDR_LEN, hdrlen); | 428 | memmove(pos, pos + CCMP_HDR_LEN, hdrlen); |
@@ -478,7 +442,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, | |||
478 | 442 | ||
479 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 443 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
480 | /* hwaccel - with preallocated room for CCMP header */ | 444 | /* hwaccel - with preallocated room for CCMP header */ |
481 | tx->control->key_idx = key->conf.hw_key_idx; | 445 | info->control.hw_key = &tx->key->conf; |
482 | return 0; | 446 | return 0; |
483 | } | 447 | } |
484 | 448 | ||
@@ -495,28 +459,16 @@ ieee80211_tx_result | |||
495 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) | 459 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) |
496 | { | 460 | { |
497 | struct sk_buff *skb = tx->skb; | 461 | struct sk_buff *skb = tx->skb; |
498 | int test = 0; | ||
499 | 462 | ||
500 | tx->control->icv_len = CCMP_MIC_LEN; | ||
501 | tx->control->iv_len = CCMP_HDR_LEN; | ||
502 | ieee80211_tx_set_protected(tx); | 463 | ieee80211_tx_set_protected(tx); |
503 | 464 | ||
504 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 465 | if (ccmp_encrypt_skb(tx, skb) < 0) |
505 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | ||
506 | /* hwaccel - with no need for preallocated room for CCMP " | ||
507 | * header or MIC fields */ | ||
508 | tx->control->key_idx = tx->key->conf.hw_key_idx; | ||
509 | return TX_CONTINUE; | ||
510 | } | ||
511 | |||
512 | if (ccmp_encrypt_skb(tx, skb, test) < 0) | ||
513 | return TX_DROP; | 466 | return TX_DROP; |
514 | 467 | ||
515 | if (tx->extra_frag) { | 468 | if (tx->extra_frag) { |
516 | int i; | 469 | int i; |
517 | for (i = 0; i < tx->num_extra_frag; i++) { | 470 | for (i = 0; i < tx->num_extra_frag; i++) { |
518 | if (ccmp_encrypt_skb(tx, tx->extra_frag[i], test) | 471 | if (ccmp_encrypt_skb(tx, tx->extra_frag[i]) < 0) |
519 | < 0) | ||
520 | return TX_DROP; | 472 | return TX_DROP; |
521 | } | 473 | } |
522 | } | 474 | } |
@@ -529,7 +481,6 @@ ieee80211_rx_result | |||
529 | ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | 481 | ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) |
530 | { | 482 | { |
531 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 483 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; |
532 | u16 fc; | ||
533 | int hdrlen; | 484 | int hdrlen; |
534 | struct ieee80211_key *key = rx->key; | 485 | struct ieee80211_key *key = rx->key; |
535 | struct sk_buff *skb = rx->skb; | 486 | struct sk_buff *skb = rx->skb; |
@@ -537,8 +488,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
537 | int data_len; | 488 | int data_len; |
538 | DECLARE_MAC_BUF(mac); | 489 | DECLARE_MAC_BUF(mac); |
539 | 490 | ||
540 | fc = le16_to_cpu(hdr->frame_control); | 491 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
541 | hdrlen = ieee80211_get_hdrlen(fc); | ||
542 | 492 | ||
543 | if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) | 493 | if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) |
544 | return RX_CONTINUE; | 494 | return RX_CONTINUE; |