wpa.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2002-2004, Instant802 Networks, Inc.
00003  * Copyright 2008, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
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                 /* Need to use software crypto for the test */
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                 /* hwaccel - with no need for SW-generated MMIC */
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          * it makes no sense to check for MIC errors on anything other
00094          * than data frames.
00095          */
00096         if (!ieee80211_is_data_present(hdr->frame_control))
00097                 return RX_CONTINUE;
00098 
00099         /*
00100          * No way to verify the MIC if the hardware stripped it or
00101          * the IV with the key index. In this case we have solely rely
00102          * on the driver to set RX_FLAG_MMIC_ERROR in the event of a
00103          * MIC failure report.
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          * Some hardware seems to generate Michael MIC failure reports; even
00117          * though, the frame was not encrypted with TKIP and therefore has no
00118          * MIC. Ignore the flag them to avoid triggering countermeasures.
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                  * APs with pairwise keys should never receive Michael MIC
00127                  * errors for non-zero keyidx because these are reserved for
00128                  * group keys and only the AP is sending real multicast
00129                  * frames in the BSS. (
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         /* remove Michael MIC from payload */
00153         skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
00154 
00155 update_iv:
00156         /* update IV in key information to be able to detect replays */
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          * In some cases the key can be unset - e.g. a multicast packet, in
00165          * a driver that supports HW encryption. Send up the key idx only if
00166          * the key is set.
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                 /* hwaccel - with no need for software-generated IV */
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         /* the HW only needs room for the IV, but not the actual IV */
00210         if (info->control.hw_key &&
00211             (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
00212                 return 0;
00213 
00214         /* Increase IV for the frame */
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         /* hwaccel - with software IV */
00223         if (info->control.hw_key)
00224                 return 0;
00225 
00226         /* Add room for ICV */
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         /* it may be possible to optimize this a bit more */
00268         if (skb_linearize(rx->skb))
00269                 return RX_DROP_UNUSABLE;
00270         hdr = (void *)skb->data;
00271 
00272         /*
00273          * Let TKIP code verify IV, but skip decryption.
00274          * In the case where hardware checks the IV as well,
00275          * we don't even get here, see ieee80211_rx_h_decrypt()
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         /* Trim ICV */
00290         skb_trim(skb, skb->len - TKIP_ICV_LEN);
00291 
00292         /* Remove IV */
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          * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
00318          * Retry, PwrMgt, MoreData; set Protected
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         /* First block, b_0 */
00342         b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
00343         /* Nonce: Nonce Flags | A2 | PN
00344          * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
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         /* l(m) */
00350         put_unaligned_be16(data_len, &b_0[14]);
00351 
00352         /* AAD (extra authenticate-only data) / masked 802.11 header
00353          * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
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         /* Mask Seq#, leave Frag# */
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                  * hwaccel has no need for preallocated room for CCMP
00413                  * header or MIC fields
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         /* the HW only needs room for the IV, but not the actual IV */
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         /* hwaccel - with software CCMP header */
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                 /* hardware didn't decrypt/verify MIC */
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         /* Remove CCMP header and MIC */
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         /* BIP AAD: FC(masked) || A1 || A2 || A3 */
00549 
00550         /* FC type/subtype */
00551         aad[0] = skb->data[0];
00552         /* Mask FC Retry, PwrMgt, MoreData flags to zero */
00553         aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6));
00554         /* A1 || A2 || A3 */
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         /* PN = PN + 1 */
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          * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
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         /* management frames are already linear */
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; /* Invalid MMIE */
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                 /* hardware didn't decrypt/verify MIC */
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         /* Remove MMIE */
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                 /* handle hw-only algorithm */
00685                 if (!info->control.hw_key)
00686                         return TX_DROP;
00687         }
00688 
00689         ieee80211_tx_set_protected(tx);
00690 
00691         return TX_CONTINUE;
00692 }


ros_rt_wmp
Author(s): Danilo Tardioli, dantard@unizar.es
autogenerated on Fri Jan 3 2014 12:07:56