00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <linux/netdevice.h>
00011 #include <linux/types.h>
00012 #include <linux/skbuff.h>
00013 #include <linux/compiler.h>
00014 #include <linux/ieee80211.h>
00015 #include <linux/gfp.h>
00016 #include <asm/unaligned.h>
00017 #include <net/mac80211.h>
00018 #include <crypto/aes.h>
00019
00020 #include "ieee80211_i.h"
00021 #include "michael.h"
00022 #include "tkip.h"
00023 #include "aes_ccm.h"
00024 #include "aes_cmac.h"
00025 #include "wpa.h"
00026
00027 ieee80211_tx_result
00028 ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
00029 {
00030 u8 *data, *key, *mic;
00031 size_t data_len;
00032 unsigned int hdrlen;
00033 struct ieee80211_hdr *hdr;
00034 struct sk_buff *skb = tx->skb;
00035 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00036 int tail;
00037
00038 hdr = (struct ieee80211_hdr *)skb->data;
00039 if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
00040 skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control))
00041 return TX_CONTINUE;
00042
00043 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00044 if (skb->len < hdrlen)
00045 return TX_DROP;
00046
00047 data = skb->data + hdrlen;
00048 data_len = skb->len - hdrlen;
00049
00050 if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) {
00051
00052 info->control.hw_key = NULL;
00053 }
00054
00055 if (info->control.hw_key &&
00056 (info->flags & IEEE80211_TX_CTL_DONTFRAG ||
00057 tx->local->ops->set_frag_threshold) &&
00058 !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
00059
00060 return TX_CONTINUE;
00061 }
00062
00063 tail = MICHAEL_MIC_LEN;
00064 if (!info->control.hw_key)
00065 tail += TKIP_ICV_LEN;
00066
00067 if (WARN_ON(skb_tailroom(skb) < tail ||
00068 skb_headroom(skb) < TKIP_IV_LEN))
00069 return TX_DROP;
00070
00071 key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY];
00072 mic = skb_put(skb, MICHAEL_MIC_LEN);
00073 michael_mic(key, hdr, data, data_len, mic);
00074 if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE))
00075 mic[0]++;
00076
00077 return TX_CONTINUE;
00078 }
00079
00080
00081 ieee80211_rx_result
00082 ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
00083 {
00084 u8 *data, *key = NULL;
00085 size_t data_len;
00086 unsigned int hdrlen;
00087 u8 mic[MICHAEL_MIC_LEN];
00088 struct sk_buff *skb = rx->skb;
00089 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
00090 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
00091
00092
00093
00094
00095
00096 if (!ieee80211_is_data_present(hdr->frame_control))
00097 return RX_CONTINUE;
00098
00099
00100
00101
00102
00103
00104
00105 if (status->flag & (RX_FLAG_MMIC_STRIPPED | RX_FLAG_IV_STRIPPED)) {
00106 if (status->flag & RX_FLAG_MMIC_ERROR)
00107 goto mic_fail;
00108
00109 if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key)
00110 goto update_iv;
00111
00112 return RX_CONTINUE;
00113 }
00114
00115
00116
00117
00118
00119
00120 if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
00121 !(status->flag & RX_FLAG_DECRYPTED))
00122 return RX_CONTINUE;
00123
00124 if (rx->sdata->vif.type == NL80211_IFTYPE_AP && rx->key->conf.keyidx) {
00125
00126
00127
00128
00129
00130
00131 return RX_DROP_UNUSABLE;
00132 }
00133
00134 if (status->flag & RX_FLAG_MMIC_ERROR)
00135 goto mic_fail;
00136
00137 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00138 if (skb->len < hdrlen + MICHAEL_MIC_LEN)
00139 return RX_DROP_UNUSABLE;
00140
00141 if (skb_linearize(rx->skb))
00142 return RX_DROP_UNUSABLE;
00143 hdr = (void *)skb->data;
00144
00145 data = skb->data + hdrlen;
00146 data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
00147 key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
00148 michael_mic(key, hdr, data, data_len, mic);
00149 if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0)
00150 goto mic_fail;
00151
00152
00153 skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
00154
00155 update_iv:
00156
00157 rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32;
00158 rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16;
00159
00160 return RX_CONTINUE;
00161
00162 mic_fail:
00163
00164
00165
00166
00167
00168 mac80211_ev_michael_mic_failure(rx->sdata,
00169 rx->key ? rx->key->conf.keyidx : -1,
00170 (void *) skb->data, NULL, GFP_ATOMIC);
00171 return RX_DROP_UNUSABLE;
00172 }
00173
00174
00175 static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
00176 {
00177 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
00178 struct ieee80211_key *key = tx->key;
00179 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00180 unsigned long flags;
00181 unsigned int hdrlen;
00182 int len, tail;
00183 u8 *pos;
00184
00185 if (info->control.hw_key &&
00186 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
00187 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
00188
00189 return 0;
00190 }
00191
00192 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00193 len = skb->len - hdrlen;
00194
00195 if (info->control.hw_key)
00196 tail = 0;
00197 else
00198 tail = TKIP_ICV_LEN;
00199
00200 if (WARN_ON(skb_tailroom(skb) < tail ||
00201 skb_headroom(skb) < TKIP_IV_LEN))
00202 return -1;
00203
00204 pos = skb_push(skb, TKIP_IV_LEN);
00205 memmove(pos, pos + TKIP_IV_LEN, hdrlen);
00206 skb_set_network_header(skb, skb_network_offset(skb) + TKIP_IV_LEN);
00207 pos += hdrlen;
00208
00209
00210 if (info->control.hw_key &&
00211 (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
00212 return 0;
00213
00214
00215 spin_lock_irqsave(&key->u.tkip.txlock, flags);
00216 key->u.tkip.tx.iv16++;
00217 if (key->u.tkip.tx.iv16 == 0)
00218 key->u.tkip.tx.iv32++;
00219 pos = ieee80211_tkip_add_iv(pos, key);
00220 spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
00221
00222
00223 if (info->control.hw_key)
00224 return 0;
00225
00226
00227 skb_put(skb, TKIP_ICV_LEN);
00228
00229 return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
00230 key, skb, pos, len);
00231 }
00232
00233
00234 ieee80211_tx_result
00235 ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
00236 {
00237 struct sk_buff *skb;
00238
00239 ieee80211_tx_set_protected(tx);
00240
00241 skb_queue_walk(&tx->skbs, skb) {
00242 if (tkip_encrypt_skb(tx, skb) < 0)
00243 return TX_DROP;
00244 }
00245
00246 return TX_CONTINUE;
00247 }
00248
00249
00250 ieee80211_rx_result
00251 ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
00252 {
00253 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
00254 int hdrlen, res, hwaccel = 0;
00255 struct ieee80211_key *key = rx->key;
00256 struct sk_buff *skb = rx->skb;
00257 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
00258
00259 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00260
00261 if (!ieee80211_is_data(hdr->frame_control))
00262 return RX_CONTINUE;
00263
00264 if (!rx->sta || skb->len - hdrlen < 12)
00265 return RX_DROP_UNUSABLE;
00266
00267
00268 if (skb_linearize(rx->skb))
00269 return RX_DROP_UNUSABLE;
00270 hdr = (void *)skb->data;
00271
00272
00273
00274
00275
00276
00277 if (status->flag & RX_FLAG_DECRYPTED)
00278 hwaccel = 1;
00279
00280 res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
00281 key, skb->data + hdrlen,
00282 skb->len - hdrlen, rx->sta->sta.addr,
00283 hdr->addr1, hwaccel, rx->security_idx,
00284 &rx->tkip_iv32,
00285 &rx->tkip_iv16);
00286 if (res != TKIP_DECRYPT_OK)
00287 return RX_DROP_UNUSABLE;
00288
00289
00290 skb_trim(skb, skb->len - TKIP_ICV_LEN);
00291
00292
00293 memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
00294 skb_pull(skb, TKIP_IV_LEN);
00295
00296 return RX_CONTINUE;
00297 }
00298
00299
00300 static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
00301 int encrypted)
00302 {
00303 __le16 mask_fc;
00304 int a4_included, mgmt;
00305 u8 qos_tid;
00306 u8 *b_0, *aad;
00307 u16 data_len, len_a;
00308 unsigned int hdrlen;
00309 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
00310
00311 memset(scratch, 0, 6 * AES_BLOCK_SIZE);
00312
00313 b_0 = scratch + 3 * AES_BLOCK_SIZE;
00314 aad = scratch + 4 * AES_BLOCK_SIZE;
00315
00316
00317
00318
00319
00320 mgmt = ieee80211_is_mgmt(hdr->frame_control);
00321 mask_fc = hdr->frame_control;
00322 mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY |
00323 IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA);
00324 if (!mgmt)
00325 mask_fc &= ~cpu_to_le16(0x0070);
00326 mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
00327
00328 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00329 len_a = hdrlen - 2;
00330 a4_included = ieee80211_has_a4(hdr->frame_control);
00331
00332 if (ieee80211_is_data_qos(hdr->frame_control))
00333 qos_tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
00334 else
00335 qos_tid = 0;
00336
00337 data_len = skb->len - hdrlen - CCMP_HDR_LEN;
00338 if (encrypted)
00339 data_len -= CCMP_MIC_LEN;
00340
00341
00342 b_0[0] = 0x59;
00343
00344
00345
00346 b_0[1] = qos_tid | (mgmt << 4);
00347 memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
00348 memcpy(&b_0[8], pn, CCMP_PN_LEN);
00349
00350 put_unaligned_be16(data_len, &b_0[14]);
00351
00352
00353
00354 put_unaligned_be16(len_a, &aad[0]);
00355 put_unaligned(mask_fc, (__le16 *)&aad[2]);
00356 memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);
00357
00358
00359 aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f;
00360 aad[23] = 0;
00361
00362 if (a4_included) {
00363 memcpy(&aad[24], hdr->addr4, ETH_ALEN);
00364 aad[30] = qos_tid;
00365 aad[31] = 0;
00366 } else {
00367 memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
00368 aad[24] = qos_tid;
00369 }
00370 }
00371
00372
00373 static inline void ccmp_pn2hdr(u8 *hdr, u8 *pn, int key_id)
00374 {
00375 hdr[0] = pn[5];
00376 hdr[1] = pn[4];
00377 hdr[2] = 0;
00378 hdr[3] = 0x20 | (key_id << 6);
00379 hdr[4] = pn[3];
00380 hdr[5] = pn[2];
00381 hdr[6] = pn[1];
00382 hdr[7] = pn[0];
00383 }
00384
00385
00386 static inline void ccmp_hdr2pn(u8 *pn, u8 *hdr)
00387 {
00388 pn[0] = hdr[7];
00389 pn[1] = hdr[6];
00390 pn[2] = hdr[5];
00391 pn[3] = hdr[4];
00392 pn[4] = hdr[1];
00393 pn[5] = hdr[0];
00394 }
00395
00396
00397 static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
00398 {
00399 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
00400 struct ieee80211_key *key = tx->key;
00401 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00402 int hdrlen, len, tail;
00403 u8 *pos;
00404 u8 pn[6];
00405 u64 pn64;
00406 u8 scratch[6 * AES_BLOCK_SIZE];
00407
00408 if (info->control.hw_key &&
00409 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
00410 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
00411
00412
00413
00414
00415 return 0;
00416 }
00417
00418 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00419 len = skb->len - hdrlen;
00420
00421 if (info->control.hw_key)
00422 tail = 0;
00423 else
00424 tail = CCMP_MIC_LEN;
00425
00426 if (WARN_ON(skb_tailroom(skb) < tail ||
00427 skb_headroom(skb) < CCMP_HDR_LEN))
00428 return -1;
00429
00430 pos = skb_push(skb, CCMP_HDR_LEN);
00431 memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
00432 skb_set_network_header(skb, skb_network_offset(skb) + CCMP_HDR_LEN);
00433
00434
00435 if (info->control.hw_key &&
00436 (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
00437 return 0;
00438
00439 hdr = (struct ieee80211_hdr *) pos;
00440 pos += hdrlen;
00441
00442 pn64 = atomic64_inc_return(&key->u.ccmp.tx_pn);
00443
00444 pn[5] = pn64;
00445 pn[4] = pn64 >> 8;
00446 pn[3] = pn64 >> 16;
00447 pn[2] = pn64 >> 24;
00448 pn[1] = pn64 >> 32;
00449 pn[0] = pn64 >> 40;
00450
00451 ccmp_pn2hdr(pos, pn, key->conf.keyidx);
00452
00453
00454 if (info->control.hw_key)
00455 return 0;
00456
00457 pos += CCMP_HDR_LEN;
00458 ccmp_special_blocks(skb, pn, scratch, 0);
00459 ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
00460 pos, skb_put(skb, CCMP_MIC_LEN));
00461
00462 return 0;
00463 }
00464
00465
00466 ieee80211_tx_result
00467 ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
00468 {
00469 struct sk_buff *skb;
00470
00471 ieee80211_tx_set_protected(tx);
00472
00473 skb_queue_walk(&tx->skbs, skb) {
00474 if (ccmp_encrypt_skb(tx, skb) < 0)
00475 return TX_DROP;
00476 }
00477
00478 return TX_CONTINUE;
00479 }
00480
00481
00482 ieee80211_rx_result
00483 ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
00484 {
00485 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
00486 int hdrlen;
00487 struct ieee80211_key *key = rx->key;
00488 struct sk_buff *skb = rx->skb;
00489 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
00490 u8 pn[CCMP_PN_LEN];
00491 int data_len;
00492 int queue;
00493
00494 hdrlen = ieee80211_hdrlen(hdr->frame_control);
00495
00496 if (!ieee80211_is_data(hdr->frame_control) &&
00497 !ieee80211_is_robust_mgmt_frame(hdr))
00498 return RX_CONTINUE;
00499
00500 data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
00501 if (!rx->sta || data_len < 0)
00502 return RX_DROP_UNUSABLE;
00503
00504 if (status->flag & RX_FLAG_DECRYPTED) {
00505 if (!pskb_may_pull(rx->skb, hdrlen + CCMP_HDR_LEN))
00506 return RX_DROP_UNUSABLE;
00507 } else {
00508 if (skb_linearize(rx->skb))
00509 return RX_DROP_UNUSABLE;
00510 }
00511
00512 ccmp_hdr2pn(pn, skb->data + hdrlen);
00513
00514 queue = rx->security_idx;
00515
00516 if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) {
00517 key->u.ccmp.replays++;
00518 return RX_DROP_UNUSABLE;
00519 }
00520
00521 if (!(status->flag & RX_FLAG_DECRYPTED)) {
00522 u8 scratch[6 * AES_BLOCK_SIZE];
00523
00524 ccmp_special_blocks(skb, pn, scratch, 1);
00525
00526 if (ieee80211_aes_ccm_decrypt(
00527 key->u.ccmp.tfm, scratch,
00528 skb->data + hdrlen + CCMP_HDR_LEN, data_len,
00529 skb->data + skb->len - CCMP_MIC_LEN,
00530 skb->data + hdrlen + CCMP_HDR_LEN))
00531 return RX_DROP_UNUSABLE;
00532 }
00533
00534 memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN);
00535
00536
00537 if (pskb_trim(skb, skb->len - CCMP_MIC_LEN))
00538 return RX_DROP_UNUSABLE;
00539 memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
00540 skb_pull(skb, CCMP_HDR_LEN);
00541
00542 return RX_CONTINUE;
00543 }
00544
00545
00546 static void bip_aad(struct sk_buff *skb, u8 *aad)
00547 {
00548
00549
00550
00551 aad[0] = skb->data[0];
00552
00553 aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6));
00554
00555 memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN);
00556 }
00557
00558
00559 static inline void bip_ipn_set64(u8 *d, u64 pn)
00560 {
00561 *d++ = pn;
00562 *d++ = pn >> 8;
00563 *d++ = pn >> 16;
00564 *d++ = pn >> 24;
00565 *d++ = pn >> 32;
00566 *d = pn >> 40;
00567 }
00568
00569 static inline void bip_ipn_swap(u8 *d, const u8 *s)
00570 {
00571 *d++ = s[5];
00572 *d++ = s[4];
00573 *d++ = s[3];
00574 *d++ = s[2];
00575 *d++ = s[1];
00576 *d = s[0];
00577 }
00578
00579
00580 ieee80211_tx_result
00581 ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
00582 {
00583 struct sk_buff *skb;
00584 struct ieee80211_tx_info *info;
00585 struct ieee80211_key *key = tx->key;
00586 struct ieee80211_mmie *mmie;
00587 u8 aad[20];
00588 u64 pn64;
00589
00590 if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
00591 return TX_DROP;
00592
00593 skb = skb_peek(&tx->skbs);
00594
00595 info = IEEE80211_SKB_CB(skb);
00596
00597 if (info->control.hw_key)
00598 return TX_CONTINUE;
00599
00600 if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
00601 return TX_DROP;
00602
00603 mmie = (struct ieee80211_mmie *) skb_put(skb, sizeof(*mmie));
00604 mmie->element_id = WLAN_EID_MMIE;
00605 mmie->length = sizeof(*mmie) - 2;
00606 mmie->key_id = cpu_to_le16(key->conf.keyidx);
00607
00608
00609 pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn);
00610
00611 bip_ipn_set64(mmie->sequence_number, pn64);
00612
00613 bip_aad(skb, aad);
00614
00615
00616
00617
00618 ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
00619 skb->data + 24, skb->len - 24, mmie->mic);
00620
00621 return TX_CONTINUE;
00622 }
00623
00624
00625 ieee80211_rx_result
00626 ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
00627 {
00628 struct sk_buff *skb = rx->skb;
00629 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
00630 struct ieee80211_key *key = rx->key;
00631 struct ieee80211_mmie *mmie;
00632 u8 aad[20], mic[8], ipn[6];
00633 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
00634
00635 if (!ieee80211_is_mgmt(hdr->frame_control))
00636 return RX_CONTINUE;
00637
00638
00639
00640 if (skb->len < 24 + sizeof(*mmie))
00641 return RX_DROP_UNUSABLE;
00642
00643 mmie = (struct ieee80211_mmie *)
00644 (skb->data + skb->len - sizeof(*mmie));
00645 if (mmie->element_id != WLAN_EID_MMIE ||
00646 mmie->length != sizeof(*mmie) - 2)
00647 return RX_DROP_UNUSABLE;
00648
00649 bip_ipn_swap(ipn, mmie->sequence_number);
00650
00651 if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) {
00652 key->u.aes_cmac.replays++;
00653 return RX_DROP_UNUSABLE;
00654 }
00655
00656 if (!(status->flag & RX_FLAG_DECRYPTED)) {
00657
00658 bip_aad(skb, aad);
00659 ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
00660 skb->data + 24, skb->len - 24, mic);
00661 if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
00662 key->u.aes_cmac.icverrors++;
00663 return RX_DROP_UNUSABLE;
00664 }
00665 }
00666
00667 memcpy(key->u.aes_cmac.rx_pn, ipn, 6);
00668
00669
00670 skb_trim(skb, skb->len - sizeof(*mmie));
00671
00672 return RX_CONTINUE;
00673 }
00674
00675 ieee80211_tx_result
00676 ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
00677 {
00678 struct sk_buff *skb;
00679 struct ieee80211_tx_info *info = NULL;
00680
00681 skb_queue_walk(&tx->skbs, skb) {
00682 info = IEEE80211_SKB_CB(skb);
00683
00684
00685 if (!info->control.hw_key)
00686 return TX_DROP;
00687 }
00688
00689 ieee80211_tx_set_protected(tx);
00690
00691 return TX_CONTINUE;
00692 }