Blame view
net/mac80211/wpa.c
15.5 KB
f0706e828 [MAC80211]: Add m... |
1 2 |
/* * Copyright 2002-2004, Instant802 Networks, Inc. |
765cb46a3 mac80211: 802.11w... |
3 |
* Copyright 2008, Jouni Malinen <j@w1.fi> |
f0706e828 [MAC80211]: Add m... |
4 5 6 7 8 9 10 11 |
* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/netdevice.h> #include <linux/types.h> |
f0706e828 [MAC80211]: Add m... |
12 13 |
#include <linux/skbuff.h> #include <linux/compiler.h> |
f14df8049 mac80211: remove ... |
14 |
#include <linux/ieee80211.h> |
5a0e3ad6a include cleanup: ... |
15 |
#include <linux/gfp.h> |
f14df8049 mac80211: remove ... |
16 |
#include <asm/unaligned.h> |
f0706e828 [MAC80211]: Add m... |
17 |
#include <net/mac80211.h> |
aba83a0b3 mac80211: fix CCM... |
18 |
#include <crypto/aes.h> |
eb063c170 [MAC80211]: refac... |
19 |
|
f0706e828 [MAC80211]: Add m... |
20 21 22 23 |
#include "ieee80211_i.h" #include "michael.h" #include "tkip.h" #include "aes_ccm.h" |
765cb46a3 mac80211: 802.11w... |
24 |
#include "aes_cmac.h" |
f0706e828 [MAC80211]: Add m... |
25 |
#include "wpa.h" |
9ae54c846 mac80211: split i... |
26 |
ieee80211_tx_result |
5cf121c3c mac80211: split i... |
27 |
ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) |
f0706e828 [MAC80211]: Add m... |
28 |
{ |
747d753df mac80211: Remove ... |
29 |
u8 *data, *key, *mic; |
f0706e828 [MAC80211]: Add m... |
30 |
size_t data_len; |
8e8862b79 mac80211: remove ... |
31 32 |
unsigned int hdrlen; struct ieee80211_hdr *hdr; |
f0706e828 [MAC80211]: Add m... |
33 |
struct sk_buff *skb = tx->skb; |
813d76694 mac80211: move co... |
34 |
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
23c0752a2 mac80211: clean u... |
35 |
int tail; |
f0706e828 [MAC80211]: Add m... |
36 |
|
c34498b9e mac80211: wpa.c r... |
37 |
hdr = (struct ieee80211_hdr *)skb->data; |
97359d123 mac80211: use cip... |
38 39 |
if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control)) |
9ae54c846 mac80211: split i... |
40 |
return TX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
41 |
|
8e8862b79 mac80211: remove ... |
42 43 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); if (skb->len < hdrlen) |
9ae54c846 mac80211: split i... |
44 |
return TX_DROP; |
f0706e828 [MAC80211]: Add m... |
45 |
|
8e8862b79 mac80211: remove ... |
46 47 |
data = skb->data + hdrlen; data_len = skb->len - hdrlen; |
681d11904 mac80211: Add tes... |
48 49 50 51 |
if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) { /* Need to use software crypto for the test */ info->control.hw_key = NULL; } |
813d76694 mac80211: move co... |
52 |
if (info->control.hw_key && |
a26eb27ab mac80211: move fr... |
53 54 |
(info->flags & IEEE80211_TX_CTL_DONTFRAG || tx->local->ops->set_frag_threshold) && |
813d76694 mac80211: move co... |
55 56 |
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { /* hwaccel - with no need for SW-generated MMIC */ |
9ae54c846 mac80211: split i... |
57 |
return TX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
58 |
} |
23c0752a2 mac80211: clean u... |
59 |
tail = MICHAEL_MIC_LEN; |
813d76694 mac80211: move co... |
60 |
if (!info->control.hw_key) |
23c0752a2 mac80211: clean u... |
61 62 63 64 65 |
tail += TKIP_ICV_LEN; if (WARN_ON(skb_tailroom(skb) < tail || skb_headroom(skb) < TKIP_IV_LEN)) return TX_DROP; |
f0706e828 [MAC80211]: Add m... |
66 |
|
747d753df mac80211: Remove ... |
67 |
key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]; |
f0706e828 [MAC80211]: Add m... |
68 |
mic = skb_put(skb, MICHAEL_MIC_LEN); |
8e8862b79 mac80211: remove ... |
69 |
michael_mic(key, hdr, data, data_len, mic); |
681d11904 mac80211: Add tes... |
70 71 |
if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) mic[0]++; |
f0706e828 [MAC80211]: Add m... |
72 |
|
9ae54c846 mac80211: split i... |
73 |
return TX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
74 |
} |
9ae54c846 mac80211: split i... |
75 |
ieee80211_rx_result |
5cf121c3c mac80211: split i... |
76 |
ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) |
f0706e828 [MAC80211]: Add m... |
77 |
{ |
747d753df mac80211: Remove ... |
78 |
u8 *data, *key = NULL; |
f0706e828 [MAC80211]: Add m... |
79 |
size_t data_len; |
8e8862b79 mac80211: remove ... |
80 |
unsigned int hdrlen; |
f0706e828 [MAC80211]: Add m... |
81 82 |
u8 mic[MICHAEL_MIC_LEN]; struct sk_buff *skb = rx->skb; |
eb9fb5b88 mac80211: trim RX... |
83 84 |
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
f0706e828 [MAC80211]: Add m... |
85 |
|
816c04fe7 mac80211: consoli... |
86 87 88 89 90 |
/* * it makes no sense to check for MIC errors on anything other * than data frames. */ if (!ieee80211_is_data_present(hdr->frame_control)) |
9ae54c846 mac80211: split i... |
91 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
92 |
|
816c04fe7 mac80211: consoli... |
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
/* * No way to verify the MIC if the hardware stripped it or * the IV with the key index. In this case we have solely rely * on the driver to set RX_FLAG_MMIC_ERROR in the event of a * MIC failure report. */ if (status->flag & (RX_FLAG_MMIC_STRIPPED | RX_FLAG_IV_STRIPPED)) { if (status->flag & RX_FLAG_MMIC_ERROR) goto mic_fail; if (!(status->flag & RX_FLAG_IV_STRIPPED)) goto update_iv; return RX_CONTINUE; } /* * Some hardware seems to generate Michael MIC failure reports; even * though, the frame was not encrypted with TKIP and therefore has no * MIC. Ignore the flag them to avoid triggering countermeasures. */ |
97359d123 mac80211: use cip... |
114 |
if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || |
816c04fe7 mac80211: consoli... |
115 |
!(status->flag & RX_FLAG_DECRYPTED)) |
9ae54c846 mac80211: split i... |
116 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
117 |
|
816c04fe7 mac80211: consoli... |
118 119 120 121 122 123 124 125 126 127 128 129 |
if (rx->sdata->vif.type == NL80211_IFTYPE_AP && rx->key->conf.keyidx) { /* * APs with pairwise keys should never receive Michael MIC * errors for non-zero keyidx because these are reserved for * group keys and only the AP is sending real multicast * frames in the BSS. ( */ return RX_DROP_UNUSABLE; } if (status->flag & RX_FLAG_MMIC_ERROR) goto mic_fail; |
8e8862b79 mac80211: remove ... |
130 131 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); if (skb->len < hdrlen + MICHAEL_MIC_LEN) |
e4c26add8 mac80211: split R... |
132 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
133 |
|
8e8862b79 mac80211: remove ... |
134 135 |
data = skb->data + hdrlen; data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; |
747d753df mac80211: Remove ... |
136 |
key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; |
8e8862b79 mac80211: remove ... |
137 |
michael_mic(key, hdr, data, data_len, mic); |
816c04fe7 mac80211: consoli... |
138 139 |
if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) goto mic_fail; |
f0706e828 [MAC80211]: Add m... |
140 |
|
f0706e828 [MAC80211]: Add m... |
141 142 |
/* remove Michael MIC from payload */ skb_trim(skb, skb->len - MICHAEL_MIC_LEN); |
816c04fe7 mac80211: consoli... |
143 |
update_iv: |
50741ae05 [PATCH] mac80211:... |
144 |
/* update IV in key information to be able to detect replays */ |
9e26297a5 mac80211: simplif... |
145 146 |
rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32; rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16; |
50741ae05 [PATCH] mac80211:... |
147 |
|
9ae54c846 mac80211: split i... |
148 |
return RX_CONTINUE; |
816c04fe7 mac80211: consoli... |
149 150 |
mic_fail: |
a66b98db5 mac80211: fix rx-... |
151 152 153 154 155 156 157 |
/* * In some cases the key can be unset - e.g. a multicast packet, in * a driver that supports HW encryption. Send up the key idx only if * the key is set. */ mac80211_ev_michael_mic_failure(rx->sdata, rx->key ? rx->key->conf.keyidx : -1, |
816c04fe7 mac80211: consoli... |
158 159 |
(void *) skb->data, NULL, GFP_ATOMIC); return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
160 |
} |
e039fa4a4 mac80211: move TX... |
161 |
static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) |
f0706e828 [MAC80211]: Add m... |
162 163 164 |
{ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_key *key = tx->key; |
e039fa4a4 mac80211: move TX... |
165 |
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
523b02ea2 mac80211: fix TKI... |
166 |
unsigned long flags; |
d5184cacf mac80211: wpa.c u... |
167 168 |
unsigned int hdrlen; int len, tail; |
f0706e828 [MAC80211]: Add m... |
169 |
u8 *pos; |
813d76694 mac80211: move co... |
170 171 172 |
if (info->control.hw_key && !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { /* hwaccel - with no need for software-generated IV */ |
23c0752a2 mac80211: clean u... |
173 |
return 0; |
e039fa4a4 mac80211: move TX... |
174 |
} |
d5184cacf mac80211: wpa.c u... |
175 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); |
f0706e828 [MAC80211]: Add m... |
176 |
len = skb->len - hdrlen; |
813d76694 mac80211: move co... |
177 |
if (info->control.hw_key) |
23c0752a2 mac80211: clean u... |
178 |
tail = 0; |
11a843b7e [MAC80211]: rewor... |
179 |
else |
23c0752a2 mac80211: clean u... |
180 181 182 183 184 |
tail = TKIP_ICV_LEN; if (WARN_ON(skb_tailroom(skb) < tail || skb_headroom(skb) < TKIP_IV_LEN)) return -1; |
f0706e828 [MAC80211]: Add m... |
185 186 187 188 189 190 |
pos = skb_push(skb, TKIP_IV_LEN); memmove(pos, pos + TKIP_IV_LEN, hdrlen); pos += hdrlen; /* Increase IV for the frame */ |
523b02ea2 mac80211: fix TKI... |
191 |
spin_lock_irqsave(&key->u.tkip.txlock, flags); |
b0f76b335 mac80211: add a s... |
192 193 194 |
key->u.tkip.tx.iv16++; if (key->u.tkip.tx.iv16 == 0) key->u.tkip.tx.iv32++; |
523b02ea2 mac80211: fix TKI... |
195 196 |
pos = ieee80211_tkip_add_iv(pos, key); spin_unlock_irqrestore(&key->u.tkip.txlock, flags); |
f0706e828 [MAC80211]: Add m... |
197 |
|
813d76694 mac80211: move co... |
198 199 |
/* hwaccel - with software IV */ if (info->control.hw_key) |
f0706e828 [MAC80211]: Add m... |
200 |
return 0; |
f0706e828 [MAC80211]: Add m... |
201 202 203 |
/* Add room for ICV */ skb_put(skb, TKIP_ICV_LEN); |
3473187d2 mac80211: remove ... |
204 |
return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, |
523b02ea2 mac80211: fix TKI... |
205 |
key, skb, pos, len); |
f0706e828 [MAC80211]: Add m... |
206 |
} |
9ae54c846 mac80211: split i... |
207 |
ieee80211_tx_result |
5cf121c3c mac80211: split i... |
208 |
ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) |
f0706e828 [MAC80211]: Add m... |
209 |
{ |
f0706e828 [MAC80211]: Add m... |
210 |
struct sk_buff *skb = tx->skb; |
f0706e828 [MAC80211]: Add m... |
211 |
|
5cf121c3c mac80211: split i... |
212 |
ieee80211_tx_set_protected(tx); |
f0706e828 [MAC80211]: Add m... |
213 |
|
2de8e0d99 mac80211: rewrite... |
214 215 216 217 |
do { if (tkip_encrypt_skb(tx, skb) < 0) return TX_DROP; } while ((skb = skb->next)); |
f0706e828 [MAC80211]: Add m... |
218 |
|
9ae54c846 mac80211: split i... |
219 |
return TX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
220 |
} |
9ae54c846 mac80211: split i... |
221 |
ieee80211_rx_result |
5cf121c3c mac80211: split i... |
222 |
ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) |
f0706e828 [MAC80211]: Add m... |
223 224 |
{ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; |
747d753df mac80211: Remove ... |
225 |
int hdrlen, res, hwaccel = 0; |
f0706e828 [MAC80211]: Add m... |
226 227 |
struct ieee80211_key *key = rx->key; struct sk_buff *skb = rx->skb; |
eb9fb5b88 mac80211: trim RX... |
228 |
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
f0706e828 [MAC80211]: Add m... |
229 |
|
d5184cacf mac80211: wpa.c u... |
230 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); |
f0706e828 [MAC80211]: Add m... |
231 |
|
c34498b9e mac80211: wpa.c r... |
232 |
if (!ieee80211_is_data(hdr->frame_control)) |
9ae54c846 mac80211: split i... |
233 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
234 235 |
if (!rx->sta || skb->len - hdrlen < 12) |
e4c26add8 mac80211: split R... |
236 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
237 |
|
dc1580ddf mac80211: remove ... |
238 239 240 241 242 243 |
/* * Let TKIP code verify IV, but skip decryption. * In the case where hardware checks the IV as well, * we don't even get here, see ieee80211_rx_h_decrypt() */ if (status->flag & RX_FLAG_DECRYPTED) |
f0706e828 [MAC80211]: Add m... |
244 |
hwaccel = 1; |
f0706e828 [MAC80211]: Add m... |
245 246 247 |
res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, key, skb->data + hdrlen, |
17741cdc2 mac80211: share S... |
248 |
skb->len - hdrlen, rx->sta->sta.addr, |
9e26297a5 mac80211: simplif... |
249 |
hdr->addr1, hwaccel, rx->security_idx, |
5cf121c3c mac80211: split i... |
250 251 |
&rx->tkip_iv32, &rx->tkip_iv16); |
747d753df mac80211: Remove ... |
252 |
if (res != TKIP_DECRYPT_OK) |
e4c26add8 mac80211: split R... |
253 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
254 255 256 257 258 259 260 |
/* Trim ICV */ skb_trim(skb, skb->len - TKIP_ICV_LEN); /* Remove IV */ memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen); skb_pull(skb, TKIP_IV_LEN); |
9ae54c846 mac80211: split i... |
261 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
262 |
} |
feccb4669 mac80211: pass sc... |
263 |
static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, |
f0706e828 [MAC80211]: Add m... |
264 265 |
int encrypted) { |
f14df8049 mac80211: remove ... |
266 |
__le16 mask_fc; |
fb7333367 mac80211: 802.11w... |
267 |
int a4_included, mgmt; |
f14df8049 mac80211: remove ... |
268 |
u8 qos_tid; |
feccb4669 mac80211: pass sc... |
269 |
u8 *b_0, *aad; |
f14df8049 mac80211: remove ... |
270 271 272 |
u16 data_len, len_a; unsigned int hdrlen; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
f0706e828 [MAC80211]: Add m... |
273 |
|
0cd20a278 mac80211: use AES... |
274 |
memset(scratch, 0, 6 * AES_BLOCK_SIZE); |
aba83a0b3 mac80211: fix CCM... |
275 |
|
0cd20a278 mac80211: use AES... |
276 277 |
b_0 = scratch + 3 * AES_BLOCK_SIZE; aad = scratch + 4 * AES_BLOCK_SIZE; |
feccb4669 mac80211: pass sc... |
278 |
|
f14df8049 mac80211: remove ... |
279 |
/* |
fb7333367 mac80211: 802.11w... |
280 |
* Mask FC: zero subtype b4 b5 b6 (if not mgmt) |
f14df8049 mac80211: remove ... |
281 282 |
* Retry, PwrMgt, MoreData; set Protected */ |
fb7333367 mac80211: 802.11w... |
283 |
mgmt = ieee80211_is_mgmt(hdr->frame_control); |
f14df8049 mac80211: remove ... |
284 |
mask_fc = hdr->frame_control; |
fb7333367 mac80211: 802.11w... |
285 |
mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | |
f14df8049 mac80211: remove ... |
286 |
IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); |
fb7333367 mac80211: 802.11w... |
287 288 |
if (!mgmt) mask_fc &= ~cpu_to_le16(0x0070); |
f14df8049 mac80211: remove ... |
289 290 291 292 293 |
mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); hdrlen = ieee80211_hdrlen(hdr->frame_control); len_a = hdrlen - 2; a4_included = ieee80211_has_a4(hdr->frame_control); |
f0706e828 [MAC80211]: Add m... |
294 |
|
f14df8049 mac80211: remove ... |
295 296 297 298 299 300 301 302 303 304 |
if (ieee80211_is_data_qos(hdr->frame_control)) qos_tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; else qos_tid = 0; data_len = skb->len - hdrlen - CCMP_HDR_LEN; if (encrypted) data_len -= CCMP_MIC_LEN; /* First block, b_0 */ |
f0706e828 [MAC80211]: Add m... |
305 |
b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ |
fb7333367 mac80211: 802.11w... |
306 307 308 309 |
/* Nonce: Nonce Flags | A2 | PN * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) */ b_0[1] = qos_tid | (mgmt << 4); |
73e1f7c82 mac80211: use sym... |
310 |
memcpy(&b_0[2], hdr->addr2, ETH_ALEN); |
f0706e828 [MAC80211]: Add m... |
311 312 |
memcpy(&b_0[8], pn, CCMP_PN_LEN); /* l(m) */ |
f14df8049 mac80211: remove ... |
313 |
put_unaligned_be16(data_len, &b_0[14]); |
f0706e828 [MAC80211]: Add m... |
314 315 316 |
/* AAD (extra authenticate-only data) / masked 802.11 header * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ |
f14df8049 mac80211: remove ... |
317 318 |
put_unaligned_be16(len_a, &aad[0]); put_unaligned(mask_fc, (__le16 *)&aad[2]); |
73e1f7c82 mac80211: use sym... |
319 |
memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN); |
f0706e828 [MAC80211]: Add m... |
320 321 322 323 |
/* Mask Seq#, leave Frag# */ aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f; aad[23] = 0; |
f14df8049 mac80211: remove ... |
324 |
|
f0706e828 [MAC80211]: Add m... |
325 |
if (a4_included) { |
73e1f7c82 mac80211: use sym... |
326 |
memcpy(&aad[24], hdr->addr4, ETH_ALEN); |
f14df8049 mac80211: remove ... |
327 |
aad[30] = qos_tid; |
f0706e828 [MAC80211]: Add m... |
328 |
aad[31] = 0; |
f14df8049 mac80211: remove ... |
329 |
} else { |
73e1f7c82 mac80211: use sym... |
330 |
memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN); |
f14df8049 mac80211: remove ... |
331 |
aad[24] = qos_tid; |
f0706e828 [MAC80211]: Add m... |
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
} } static inline void ccmp_pn2hdr(u8 *hdr, u8 *pn, int key_id) { hdr[0] = pn[5]; hdr[1] = pn[4]; hdr[2] = 0; hdr[3] = 0x20 | (key_id << 6); hdr[4] = pn[3]; hdr[5] = pn[2]; hdr[6] = pn[1]; hdr[7] = pn[0]; } |
c6a1fa12d mac80211: minor c... |
347 |
static inline void ccmp_hdr2pn(u8 *pn, u8 *hdr) |
f0706e828 [MAC80211]: Add m... |
348 349 350 351 352 353 354 |
{ pn[0] = hdr[7]; pn[1] = hdr[6]; pn[2] = hdr[5]; pn[3] = hdr[4]; pn[4] = hdr[1]; pn[5] = hdr[0]; |
f0706e828 [MAC80211]: Add m... |
355 |
} |
e039fa4a4 mac80211: move TX... |
356 |
static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) |
f0706e828 [MAC80211]: Add m... |
357 358 359 |
{ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_key *key = tx->key; |
e039fa4a4 mac80211: move TX... |
360 |
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
23c0752a2 mac80211: clean u... |
361 |
int hdrlen, len, tail; |
aba83a0b3 mac80211: fix CCM... |
362 363 364 |
u8 *pos; u8 pn[6]; u64 pn64; |
0cd20a278 mac80211: use AES... |
365 |
u8 scratch[6 * AES_BLOCK_SIZE]; |
f0706e828 [MAC80211]: Add m... |
366 |
|
813d76694 mac80211: move co... |
367 368 369 370 371 372 |
if (info->control.hw_key && !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { /* * hwaccel has no need for preallocated room for CCMP * header or MIC fields */ |
23c0752a2 mac80211: clean u... |
373 |
return 0; |
e039fa4a4 mac80211: move TX... |
374 |
} |
d5184cacf mac80211: wpa.c u... |
375 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); |
f0706e828 [MAC80211]: Add m... |
376 |
len = skb->len - hdrlen; |
813d76694 mac80211: move co... |
377 |
if (info->control.hw_key) |
23c0752a2 mac80211: clean u... |
378 |
tail = 0; |
11a843b7e [MAC80211]: rewor... |
379 |
else |
23c0752a2 mac80211: clean u... |
380 381 382 383 384 |
tail = CCMP_MIC_LEN; if (WARN_ON(skb_tailroom(skb) < tail || skb_headroom(skb) < CCMP_HDR_LEN)) return -1; |
f0706e828 [MAC80211]: Add m... |
385 386 387 388 389 |
pos = skb_push(skb, CCMP_HDR_LEN); memmove(pos, pos + CCMP_HDR_LEN, hdrlen); hdr = (struct ieee80211_hdr *) pos; pos += hdrlen; |
aba83a0b3 mac80211: fix CCM... |
390 |
pn64 = atomic64_inc_return(&key->u.ccmp.tx_pn); |
f0706e828 [MAC80211]: Add m... |
391 |
|
aba83a0b3 mac80211: fix CCM... |
392 393 394 395 396 397 |
pn[5] = pn64; pn[4] = pn64 >> 8; pn[3] = pn64 >> 16; pn[2] = pn64 >> 24; pn[1] = pn64 >> 32; pn[0] = pn64 >> 40; |
f0706e828 [MAC80211]: Add m... |
398 |
|
8f20fc249 [MAC80211]: embed... |
399 |
ccmp_pn2hdr(pos, pn, key->conf.keyidx); |
f0706e828 [MAC80211]: Add m... |
400 |
|
813d76694 mac80211: move co... |
401 402 |
/* hwaccel - with software CCMP header */ if (info->control.hw_key) |
f0706e828 [MAC80211]: Add m... |
403 |
return 0; |
f0706e828 [MAC80211]: Add m... |
404 405 |
pos += CCMP_HDR_LEN; |
aba83a0b3 mac80211: fix CCM... |
406 407 |
ccmp_special_blocks(skb, pn, scratch, 0); ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, |
f0706e828 [MAC80211]: Add m... |
408 409 410 411 |
pos, skb_put(skb, CCMP_MIC_LEN)); return 0; } |
9ae54c846 mac80211: split i... |
412 |
ieee80211_tx_result |
5cf121c3c mac80211: split i... |
413 |
ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) |
f0706e828 [MAC80211]: Add m... |
414 |
{ |
f0706e828 [MAC80211]: Add m... |
415 |
struct sk_buff *skb = tx->skb; |
f0706e828 [MAC80211]: Add m... |
416 |
|
5cf121c3c mac80211: split i... |
417 |
ieee80211_tx_set_protected(tx); |
f0706e828 [MAC80211]: Add m... |
418 |
|
2de8e0d99 mac80211: rewrite... |
419 420 421 422 |
do { if (ccmp_encrypt_skb(tx, skb) < 0) return TX_DROP; } while ((skb = skb->next)); |
f0706e828 [MAC80211]: Add m... |
423 |
|
9ae54c846 mac80211: split i... |
424 |
return TX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
425 |
} |
9ae54c846 mac80211: split i... |
426 |
ieee80211_rx_result |
5cf121c3c mac80211: split i... |
427 |
ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) |
f0706e828 [MAC80211]: Add m... |
428 |
{ |
c34498b9e mac80211: wpa.c r... |
429 |
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
f0706e828 [MAC80211]: Add m... |
430 431 432 |
int hdrlen; struct ieee80211_key *key = rx->key; struct sk_buff *skb = rx->skb; |
eb9fb5b88 mac80211: trim RX... |
433 |
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
f0706e828 [MAC80211]: Add m... |
434 435 |
u8 pn[CCMP_PN_LEN]; int data_len; |
9190252c9 mac80211: Use a s... |
436 |
int queue; |
f0706e828 [MAC80211]: Add m... |
437 |
|
d5184cacf mac80211: wpa.c u... |
438 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); |
f0706e828 [MAC80211]: Add m... |
439 |
|
fb7333367 mac80211: 802.11w... |
440 441 |
if (!ieee80211_is_data(hdr->frame_control) && !ieee80211_is_robust_mgmt_frame(hdr)) |
9ae54c846 mac80211: split i... |
442 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
443 444 445 |
data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; if (!rx->sta || data_len < 0) |
e4c26add8 mac80211: split R... |
446 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
447 |
|
c6a1fa12d mac80211: minor c... |
448 |
ccmp_hdr2pn(pn, skb->data + hdrlen); |
f0706e828 [MAC80211]: Add m... |
449 |
|
9e26297a5 mac80211: simplif... |
450 |
queue = rx->security_idx; |
9190252c9 mac80211: Use a s... |
451 452 |
if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) { |
f0706e828 [MAC80211]: Add m... |
453 |
key->u.ccmp.replays++; |
e4c26add8 mac80211: split R... |
454 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
455 |
} |
eb9fb5b88 mac80211: trim RX... |
456 |
if (!(status->flag & RX_FLAG_DECRYPTED)) { |
0cd20a278 mac80211: use AES... |
457 |
u8 scratch[6 * AES_BLOCK_SIZE]; |
7848ba7d7 [MAC80211]: rewor... |
458 |
/* hardware didn't decrypt/verify MIC */ |
aba83a0b3 mac80211: fix CCM... |
459 |
ccmp_special_blocks(skb, pn, scratch, 1); |
f0706e828 [MAC80211]: Add m... |
460 461 |
if (ieee80211_aes_ccm_decrypt( |
aba83a0b3 mac80211: fix CCM... |
462 |
key->u.ccmp.tfm, scratch, |
f0706e828 [MAC80211]: Add m... |
463 464 |
skb->data + hdrlen + CCMP_HDR_LEN, data_len, skb->data + skb->len - CCMP_MIC_LEN, |
c6a1fa12d mac80211: minor c... |
465 |
skb->data + hdrlen + CCMP_HDR_LEN)) |
e4c26add8 mac80211: split R... |
466 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
467 |
} |
9190252c9 mac80211: Use a s... |
468 |
memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); |
f0706e828 [MAC80211]: Add m... |
469 470 471 472 473 |
/* Remove CCMP header and MIC */ skb_trim(skb, skb->len - CCMP_MIC_LEN); memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen); skb_pull(skb, CCMP_HDR_LEN); |
9ae54c846 mac80211: split i... |
474 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
475 |
} |
765cb46a3 mac80211: 802.11w... |
476 477 478 479 480 481 482 483 484 485 486 487 488 |
static void bip_aad(struct sk_buff *skb, u8 *aad) { /* BIP AAD: FC(masked) || A1 || A2 || A3 */ /* FC type/subtype */ aad[0] = skb->data[0]; /* Mask FC Retry, PwrMgt, MoreData flags to zero */ aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); /* A1 || A2 || A3 */ memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); } |
75396ae6d mac80211: fix CMA... |
489 490 491 492 493 494 495 496 497 |
static inline void bip_ipn_set64(u8 *d, u64 pn) { *d++ = pn; *d++ = pn >> 8; *d++ = pn >> 16; *d++ = pn >> 24; *d++ = pn >> 32; *d = pn >> 40; } |
765cb46a3 mac80211: 802.11w... |
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 |
static inline void bip_ipn_swap(u8 *d, const u8 *s) { *d++ = s[5]; *d++ = s[4]; *d++ = s[3]; *d++ = s[2]; *d++ = s[1]; *d = s[0]; } ieee80211_tx_result ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) { struct sk_buff *skb = tx->skb; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_key *key = tx->key; struct ieee80211_mmie *mmie; |
75396ae6d mac80211: fix CMA... |
516 517 |
u8 aad[20]; u64 pn64; |
765cb46a3 mac80211: 802.11w... |
518 |
|
813d76694 mac80211: move co... |
519 |
if (info->control.hw_key) |
765cb46a3 mac80211: 802.11w... |
520 |
return 0; |
765cb46a3 mac80211: 802.11w... |
521 522 523 524 525 526 527 528 529 530 |
if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) return TX_DROP; mmie = (struct ieee80211_mmie *) skb_put(skb, sizeof(*mmie)); mmie->element_id = WLAN_EID_MMIE; mmie->length = sizeof(*mmie) - 2; mmie->key_id = cpu_to_le16(key->conf.keyidx); /* PN = PN + 1 */ |
75396ae6d mac80211: fix CMA... |
531 |
pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn); |
765cb46a3 mac80211: 802.11w... |
532 |
|
75396ae6d mac80211: fix CMA... |
533 |
bip_ipn_set64(mmie->sequence_number, pn64); |
765cb46a3 mac80211: 802.11w... |
534 535 536 537 538 539 |
bip_aad(skb, aad); /* * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */ |
75396ae6d mac80211: fix CMA... |
540 541 |
ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, skb->data + 24, skb->len - 24, mmie->mic); |
765cb46a3 mac80211: 802.11w... |
542 543 544 545 546 547 548 549 550 |
return TX_CONTINUE; } ieee80211_rx_result ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) { struct sk_buff *skb = rx->skb; |
eb9fb5b88 mac80211: trim RX... |
551 |
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
765cb46a3 mac80211: 802.11w... |
552 553 554 555 556 557 558 |
struct ieee80211_key *key = rx->key; struct ieee80211_mmie *mmie; u8 aad[20], mic[8], ipn[6]; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; if (!ieee80211_is_mgmt(hdr->frame_control)) return RX_CONTINUE; |
765cb46a3 mac80211: 802.11w... |
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 |
if (skb->len < 24 + sizeof(*mmie)) return RX_DROP_UNUSABLE; mmie = (struct ieee80211_mmie *) (skb->data + skb->len - sizeof(*mmie)); if (mmie->element_id != WLAN_EID_MMIE || mmie->length != sizeof(*mmie) - 2) return RX_DROP_UNUSABLE; /* Invalid MMIE */ bip_ipn_swap(ipn, mmie->sequence_number); if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) { key->u.aes_cmac.replays++; return RX_DROP_UNUSABLE; } |
eb9fb5b88 mac80211: trim RX... |
574 |
if (!(status->flag & RX_FLAG_DECRYPTED)) { |
765cb46a3 mac80211: 802.11w... |
575 576 |
/* hardware didn't decrypt/verify MIC */ bip_aad(skb, aad); |
75396ae6d mac80211: fix CMA... |
577 |
ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, |
765cb46a3 mac80211: 802.11w... |
578 579 580 581 582 583 584 585 586 587 588 589 590 591 |
skb->data + 24, skb->len - 24, mic); if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { key->u.aes_cmac.icverrors++; return RX_DROP_UNUSABLE; } } memcpy(key->u.aes_cmac.rx_pn, ipn, 6); /* Remove MMIE */ skb_trim(skb, skb->len - sizeof(*mmie)); return RX_CONTINUE; } |