Blame view
net/mac80211/wpa.c
14.4 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> |
eb063c170 [MAC80211]: refac... |
18 |
|
f0706e828 [MAC80211]: Add m... |
19 20 21 22 |
#include "ieee80211_i.h" #include "michael.h" #include "tkip.h" #include "aes_ccm.h" |
765cb46a3 mac80211: 802.11w... |
23 |
#include "aes_cmac.h" |
f0706e828 [MAC80211]: Add m... |
24 |
#include "wpa.h" |
9ae54c846 mac80211: split i... |
25 |
ieee80211_tx_result |
5cf121c3c mac80211: split i... |
26 |
ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) |
f0706e828 [MAC80211]: Add m... |
27 |
{ |
8e8862b79 mac80211: remove ... |
28 |
u8 *data, *key, *mic, key_offset; |
f0706e828 [MAC80211]: Add m... |
29 |
size_t data_len; |
8e8862b79 mac80211: remove ... |
30 31 |
unsigned int hdrlen; struct ieee80211_hdr *hdr; |
f0706e828 [MAC80211]: Add m... |
32 |
struct sk_buff *skb = tx->skb; |
813d76694 mac80211: move co... |
33 |
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
f0706e828 [MAC80211]: Add m... |
34 |
int authenticator; |
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; |
813d76694 mac80211: move co... |
48 |
if (info->control.hw_key && |
5cf121c3c mac80211: split i... |
49 |
!(tx->flags & IEEE80211_TX_FRAGMENTED) && |
813d76694 mac80211: move co... |
50 51 |
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { /* hwaccel - with no need for SW-generated MMIC */ |
9ae54c846 mac80211: split i... |
52 |
return TX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
53 |
} |
23c0752a2 mac80211: clean u... |
54 |
tail = MICHAEL_MIC_LEN; |
813d76694 mac80211: move co... |
55 |
if (!info->control.hw_key) |
23c0752a2 mac80211: clean u... |
56 57 58 59 60 |
tail += TKIP_ICV_LEN; if (WARN_ON(skb_tailroom(skb) < tail || skb_headroom(skb) < TKIP_IV_LEN)) return TX_DROP; |
f0706e828 [MAC80211]: Add m... |
61 62 63 64 65 66 |
#if 0 authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */ #else authenticator = 1; #endif |
ffd7891dc mac80211: Let dri... |
67 68 69 70 |
key_offset = authenticator ? NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY : NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; key = &tx->key->conf.key[key_offset]; |
f0706e828 [MAC80211]: Add m... |
71 |
mic = skb_put(skb, MICHAEL_MIC_LEN); |
8e8862b79 mac80211: remove ... |
72 |
michael_mic(key, hdr, data, data_len, mic); |
f0706e828 [MAC80211]: Add m... |
73 |
|
9ae54c846 mac80211: split i... |
74 |
return TX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
75 |
} |
9ae54c846 mac80211: split i... |
76 |
ieee80211_rx_result |
5cf121c3c mac80211: split i... |
77 |
ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) |
f0706e828 [MAC80211]: Add m... |
78 |
{ |
8e8862b79 mac80211: remove ... |
79 |
u8 *data, *key = NULL, key_offset; |
f0706e828 [MAC80211]: Add m... |
80 |
size_t data_len; |
8e8862b79 mac80211: remove ... |
81 |
unsigned int hdrlen; |
f0706e828 [MAC80211]: Add m... |
82 83 |
u8 mic[MICHAEL_MIC_LEN]; struct sk_buff *skb = rx->skb; |
eb9fb5b88 mac80211: trim RX... |
84 85 |
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
f0706e828 [MAC80211]: Add m... |
86 |
int authenticator = 1, wpa_test = 0; |
c6a1fa12d mac80211: minor c... |
87 |
/* No way to verify the MIC if the hardware stripped it */ |
eb9fb5b88 mac80211: trim RX... |
88 |
if (status->flag & RX_FLAG_MMIC_STRIPPED) |
9ae54c846 mac80211: split i... |
89 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
90 |
|
97359d123 mac80211: use cip... |
91 |
if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || |
c34498b9e mac80211: wpa.c r... |
92 93 |
!ieee80211_has_protected(hdr->frame_control) || !ieee80211_is_data_present(hdr->frame_control)) |
9ae54c846 mac80211: split i... |
94 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
95 |
|
8e8862b79 mac80211: remove ... |
96 97 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); if (skb->len < hdrlen + MICHAEL_MIC_LEN) |
e4c26add8 mac80211: split R... |
98 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
99 |
|
8e8862b79 mac80211: remove ... |
100 101 |
data = skb->data + hdrlen; data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; |
f0706e828 [MAC80211]: Add m... |
102 103 104 105 106 107 |
#if 0 authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */ #else authenticator = 1; #endif |
ffd7891dc mac80211: Let dri... |
108 109 110 111 |
key_offset = authenticator ? NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY : NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; key = &rx->key->conf.key[key_offset]; |
8e8862b79 mac80211: remove ... |
112 |
michael_mic(key, hdr, data, data_len, mic); |
f0706e828 [MAC80211]: Add m... |
113 |
if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { |
554891e63 mac80211: move pa... |
114 |
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) |
e4c26add8 mac80211: split R... |
115 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
116 |
|
f698d856f replace net_devic... |
117 |
mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, |
e6d6e3420 cfg80211: use pro... |
118 119 |
(void *) skb->data, NULL, GFP_ATOMIC); |
e4c26add8 mac80211: split R... |
120 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
121 |
} |
f0706e828 [MAC80211]: Add m... |
122 123 |
/* remove Michael MIC from payload */ skb_trim(skb, skb->len - MICHAEL_MIC_LEN); |
50741ae05 [PATCH] mac80211:... |
124 |
/* update IV in key information to be able to detect replays */ |
b0f76b335 mac80211: add a s... |
125 126 |
rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32; rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16; |
50741ae05 [PATCH] mac80211:... |
127 |
|
9ae54c846 mac80211: split i... |
128 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
129 |
} |
e039fa4a4 mac80211: move TX... |
130 |
static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) |
f0706e828 [MAC80211]: Add m... |
131 132 133 |
{ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_key *key = tx->key; |
e039fa4a4 mac80211: move TX... |
134 |
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
d5184cacf mac80211: wpa.c u... |
135 136 |
unsigned int hdrlen; int len, tail; |
f0706e828 [MAC80211]: Add m... |
137 |
u8 *pos; |
813d76694 mac80211: move co... |
138 139 140 |
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... |
141 |
return 0; |
e039fa4a4 mac80211: move TX... |
142 |
} |
d5184cacf mac80211: wpa.c u... |
143 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); |
f0706e828 [MAC80211]: Add m... |
144 |
len = skb->len - hdrlen; |
813d76694 mac80211: move co... |
145 |
if (info->control.hw_key) |
23c0752a2 mac80211: clean u... |
146 |
tail = 0; |
11a843b7e [MAC80211]: rewor... |
147 |
else |
23c0752a2 mac80211: clean u... |
148 149 150 151 152 |
tail = TKIP_ICV_LEN; if (WARN_ON(skb_tailroom(skb) < tail || skb_headroom(skb) < TKIP_IV_LEN)) return -1; |
f0706e828 [MAC80211]: Add m... |
153 154 155 156 157 158 |
pos = skb_push(skb, TKIP_IV_LEN); memmove(pos, pos + TKIP_IV_LEN, hdrlen); pos += hdrlen; /* Increase IV for the frame */ |
b0f76b335 mac80211: add a s... |
159 160 161 |
key->u.tkip.tx.iv16++; if (key->u.tkip.tx.iv16 == 0) key->u.tkip.tx.iv32++; |
f0706e828 [MAC80211]: Add m... |
162 |
|
813d76694 mac80211: move co... |
163 |
pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); |
f0706e828 [MAC80211]: Add m... |
164 |
|
813d76694 mac80211: move co... |
165 166 |
/* hwaccel - with software IV */ if (info->control.hw_key) |
f0706e828 [MAC80211]: Add m... |
167 |
return 0; |
f0706e828 [MAC80211]: Add m... |
168 169 170 171 172 |
/* Add room for ICV */ skb_put(skb, TKIP_ICV_LEN); hdr = (struct ieee80211_hdr *) skb->data; |
3473187d2 mac80211: remove ... |
173 174 |
return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, key, pos, len, hdr->addr2); |
f0706e828 [MAC80211]: Add m... |
175 |
} |
9ae54c846 mac80211: split i... |
176 |
ieee80211_tx_result |
5cf121c3c mac80211: split i... |
177 |
ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) |
f0706e828 [MAC80211]: Add m... |
178 |
{ |
f0706e828 [MAC80211]: Add m... |
179 |
struct sk_buff *skb = tx->skb; |
f0706e828 [MAC80211]: Add m... |
180 |
|
5cf121c3c mac80211: split i... |
181 |
ieee80211_tx_set_protected(tx); |
f0706e828 [MAC80211]: Add m... |
182 |
|
2de8e0d99 mac80211: rewrite... |
183 184 185 186 |
do { if (tkip_encrypt_skb(tx, skb) < 0) return TX_DROP; } while ((skb = skb->next)); |
f0706e828 [MAC80211]: Add m... |
187 |
|
9ae54c846 mac80211: split i... |
188 |
return TX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
189 |
} |
9ae54c846 mac80211: split i... |
190 |
ieee80211_rx_result |
5cf121c3c mac80211: split i... |
191 |
ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) |
f0706e828 [MAC80211]: Add m... |
192 193 |
{ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; |
f0706e828 [MAC80211]: Add m... |
194 195 196 |
int hdrlen, res, hwaccel = 0, wpa_test = 0; struct ieee80211_key *key = rx->key; struct sk_buff *skb = rx->skb; |
eb9fb5b88 mac80211: trim RX... |
197 |
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
f0706e828 [MAC80211]: Add m... |
198 |
|
d5184cacf mac80211: wpa.c u... |
199 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); |
f0706e828 [MAC80211]: Add m... |
200 |
|
c34498b9e mac80211: wpa.c r... |
201 |
if (!ieee80211_is_data(hdr->frame_control)) |
9ae54c846 mac80211: split i... |
202 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
203 204 |
if (!rx->sta || skb->len - hdrlen < 12) |
e4c26add8 mac80211: split R... |
205 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
206 |
|
dc1580ddf mac80211: remove ... |
207 208 209 210 211 212 |
/* * 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... |
213 |
hwaccel = 1; |
f0706e828 [MAC80211]: Add m... |
214 215 216 |
res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, key, skb->data + hdrlen, |
17741cdc2 mac80211: share S... |
217 |
skb->len - hdrlen, rx->sta->sta.addr, |
9ae4fda33 mac80211: allows ... |
218 |
hdr->addr1, hwaccel, rx->queue, |
5cf121c3c mac80211: split i... |
219 220 |
&rx->tkip_iv32, &rx->tkip_iv16); |
f4ea83dd7 mac80211: rework ... |
221 |
if (res != TKIP_DECRYPT_OK || wpa_test) |
e4c26add8 mac80211: split R... |
222 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
223 224 225 226 227 228 229 |
/* 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... |
230 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
231 |
} |
feccb4669 mac80211: pass sc... |
232 |
static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, |
f0706e828 [MAC80211]: Add m... |
233 234 |
int encrypted) { |
f14df8049 mac80211: remove ... |
235 |
__le16 mask_fc; |
fb7333367 mac80211: 802.11w... |
236 |
int a4_included, mgmt; |
f14df8049 mac80211: remove ... |
237 |
u8 qos_tid; |
feccb4669 mac80211: pass sc... |
238 |
u8 *b_0, *aad; |
f14df8049 mac80211: remove ... |
239 240 241 |
u16 data_len, len_a; unsigned int hdrlen; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
f0706e828 [MAC80211]: Add m... |
242 |
|
feccb4669 mac80211: pass sc... |
243 244 |
b_0 = scratch + 3 * AES_BLOCK_LEN; aad = scratch + 4 * AES_BLOCK_LEN; |
f14df8049 mac80211: remove ... |
245 |
/* |
fb7333367 mac80211: 802.11w... |
246 |
* Mask FC: zero subtype b4 b5 b6 (if not mgmt) |
f14df8049 mac80211: remove ... |
247 248 |
* Retry, PwrMgt, MoreData; set Protected */ |
fb7333367 mac80211: 802.11w... |
249 |
mgmt = ieee80211_is_mgmt(hdr->frame_control); |
f14df8049 mac80211: remove ... |
250 |
mask_fc = hdr->frame_control; |
fb7333367 mac80211: 802.11w... |
251 |
mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | |
f14df8049 mac80211: remove ... |
252 |
IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); |
fb7333367 mac80211: 802.11w... |
253 254 |
if (!mgmt) mask_fc &= ~cpu_to_le16(0x0070); |
f14df8049 mac80211: remove ... |
255 256 257 258 259 |
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... |
260 |
|
f14df8049 mac80211: remove ... |
261 262 263 264 265 266 267 268 269 270 |
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... |
271 |
b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ |
fb7333367 mac80211: 802.11w... |
272 273 274 275 |
/* 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... |
276 |
memcpy(&b_0[2], hdr->addr2, ETH_ALEN); |
f0706e828 [MAC80211]: Add m... |
277 278 |
memcpy(&b_0[8], pn, CCMP_PN_LEN); /* l(m) */ |
f14df8049 mac80211: remove ... |
279 |
put_unaligned_be16(data_len, &b_0[14]); |
f0706e828 [MAC80211]: Add m... |
280 281 282 |
/* AAD (extra authenticate-only data) / masked 802.11 header * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ |
f14df8049 mac80211: remove ... |
283 284 |
put_unaligned_be16(len_a, &aad[0]); put_unaligned(mask_fc, (__le16 *)&aad[2]); |
73e1f7c82 mac80211: use sym... |
285 |
memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN); |
f0706e828 [MAC80211]: Add m... |
286 287 288 289 |
/* Mask Seq#, leave Frag# */ aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f; aad[23] = 0; |
f14df8049 mac80211: remove ... |
290 |
|
f0706e828 [MAC80211]: Add m... |
291 |
if (a4_included) { |
73e1f7c82 mac80211: use sym... |
292 |
memcpy(&aad[24], hdr->addr4, ETH_ALEN); |
f14df8049 mac80211: remove ... |
293 |
aad[30] = qos_tid; |
f0706e828 [MAC80211]: Add m... |
294 |
aad[31] = 0; |
f14df8049 mac80211: remove ... |
295 |
} else { |
73e1f7c82 mac80211: use sym... |
296 |
memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN); |
f14df8049 mac80211: remove ... |
297 |
aad[24] = qos_tid; |
f0706e828 [MAC80211]: Add m... |
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
} } 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... |
313 |
static inline void ccmp_hdr2pn(u8 *pn, u8 *hdr) |
f0706e828 [MAC80211]: Add m... |
314 315 316 317 318 319 320 |
{ 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... |
321 |
} |
e039fa4a4 mac80211: move TX... |
322 |
static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) |
f0706e828 [MAC80211]: Add m... |
323 324 325 |
{ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_key *key = tx->key; |
e039fa4a4 mac80211: move TX... |
326 |
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
23c0752a2 mac80211: clean u... |
327 |
int hdrlen, len, tail; |
feccb4669 mac80211: pass sc... |
328 |
u8 *pos, *pn; |
f0706e828 [MAC80211]: Add m... |
329 |
int i; |
813d76694 mac80211: move co... |
330 331 332 333 334 335 |
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... |
336 |
return 0; |
e039fa4a4 mac80211: move TX... |
337 |
} |
d5184cacf mac80211: wpa.c u... |
338 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); |
f0706e828 [MAC80211]: Add m... |
339 |
len = skb->len - hdrlen; |
813d76694 mac80211: move co... |
340 |
if (info->control.hw_key) |
23c0752a2 mac80211: clean u... |
341 |
tail = 0; |
11a843b7e [MAC80211]: rewor... |
342 |
else |
23c0752a2 mac80211: clean u... |
343 344 345 346 347 |
tail = CCMP_MIC_LEN; if (WARN_ON(skb_tailroom(skb) < tail || skb_headroom(skb) < CCMP_HDR_LEN)) return -1; |
f0706e828 [MAC80211]: Add m... |
348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
pos = skb_push(skb, CCMP_HDR_LEN); memmove(pos, pos + CCMP_HDR_LEN, hdrlen); hdr = (struct ieee80211_hdr *) pos; pos += hdrlen; /* PN = PN + 1 */ pn = key->u.ccmp.tx_pn; for (i = CCMP_PN_LEN - 1; i >= 0; i--) { pn[i]++; if (pn[i]) break; } |
8f20fc249 [MAC80211]: embed... |
362 |
ccmp_pn2hdr(pos, pn, key->conf.keyidx); |
f0706e828 [MAC80211]: Add m... |
363 |
|
813d76694 mac80211: move co... |
364 365 |
/* hwaccel - with software CCMP header */ if (info->control.hw_key) |
f0706e828 [MAC80211]: Add m... |
366 |
return 0; |
f0706e828 [MAC80211]: Add m... |
367 368 |
pos += CCMP_HDR_LEN; |
feccb4669 mac80211: pass sc... |
369 370 |
ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len, |
f0706e828 [MAC80211]: Add m... |
371 372 373 374 |
pos, skb_put(skb, CCMP_MIC_LEN)); return 0; } |
9ae54c846 mac80211: split i... |
375 |
ieee80211_tx_result |
5cf121c3c mac80211: split i... |
376 |
ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) |
f0706e828 [MAC80211]: Add m... |
377 |
{ |
f0706e828 [MAC80211]: Add m... |
378 |
struct sk_buff *skb = tx->skb; |
f0706e828 [MAC80211]: Add m... |
379 |
|
5cf121c3c mac80211: split i... |
380 |
ieee80211_tx_set_protected(tx); |
f0706e828 [MAC80211]: Add m... |
381 |
|
2de8e0d99 mac80211: rewrite... |
382 383 384 385 |
do { if (ccmp_encrypt_skb(tx, skb) < 0) return TX_DROP; } while ((skb = skb->next)); |
f0706e828 [MAC80211]: Add m... |
386 |
|
9ae54c846 mac80211: split i... |
387 |
return TX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
388 |
} |
9ae54c846 mac80211: split i... |
389 |
ieee80211_rx_result |
5cf121c3c mac80211: split i... |
390 |
ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) |
f0706e828 [MAC80211]: Add m... |
391 |
{ |
c34498b9e mac80211: wpa.c r... |
392 |
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
f0706e828 [MAC80211]: Add m... |
393 394 395 |
int hdrlen; struct ieee80211_key *key = rx->key; struct sk_buff *skb = rx->skb; |
eb9fb5b88 mac80211: trim RX... |
396 |
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
f0706e828 [MAC80211]: Add m... |
397 398 |
u8 pn[CCMP_PN_LEN]; int data_len; |
9190252c9 mac80211: Use a s... |
399 |
int queue; |
f0706e828 [MAC80211]: Add m... |
400 |
|
d5184cacf mac80211: wpa.c u... |
401 |
hdrlen = ieee80211_hdrlen(hdr->frame_control); |
f0706e828 [MAC80211]: Add m... |
402 |
|
fb7333367 mac80211: 802.11w... |
403 404 |
if (!ieee80211_is_data(hdr->frame_control) && !ieee80211_is_robust_mgmt_frame(hdr)) |
9ae54c846 mac80211: split i... |
405 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
406 407 408 |
data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; if (!rx->sta || data_len < 0) |
e4c26add8 mac80211: split R... |
409 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
410 |
|
c6a1fa12d mac80211: minor c... |
411 |
ccmp_hdr2pn(pn, skb->data + hdrlen); |
f0706e828 [MAC80211]: Add m... |
412 |
|
9190252c9 mac80211: Use a s... |
413 414 415 416 |
queue = ieee80211_is_mgmt(hdr->frame_control) ? NUM_RX_DATA_QUEUES : rx->queue; if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) { |
f0706e828 [MAC80211]: Add m... |
417 |
key->u.ccmp.replays++; |
e4c26add8 mac80211: split R... |
418 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
419 |
} |
eb9fb5b88 mac80211: trim RX... |
420 |
if (!(status->flag & RX_FLAG_DECRYPTED)) { |
7848ba7d7 [MAC80211]: rewor... |
421 |
/* hardware didn't decrypt/verify MIC */ |
feccb4669 mac80211: pass sc... |
422 |
ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1); |
f0706e828 [MAC80211]: Add m... |
423 424 |
if (ieee80211_aes_ccm_decrypt( |
feccb4669 mac80211: pass sc... |
425 |
key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf, |
f0706e828 [MAC80211]: Add m... |
426 427 |
skb->data + hdrlen + CCMP_HDR_LEN, data_len, skb->data + skb->len - CCMP_MIC_LEN, |
c6a1fa12d mac80211: minor c... |
428 |
skb->data + hdrlen + CCMP_HDR_LEN)) |
e4c26add8 mac80211: split R... |
429 |
return RX_DROP_UNUSABLE; |
f0706e828 [MAC80211]: Add m... |
430 |
} |
9190252c9 mac80211: Use a s... |
431 |
memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); |
f0706e828 [MAC80211]: Add m... |
432 433 434 435 436 |
/* 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... |
437 |
return RX_CONTINUE; |
f0706e828 [MAC80211]: Add m... |
438 |
} |
765cb46a3 mac80211: 802.11w... |
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
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); } 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; u8 *pn, aad[20]; int i; |
813d76694 mac80211: move co... |
474 |
if (info->control.hw_key) |
765cb46a3 mac80211: 802.11w... |
475 |
return 0; |
765cb46a3 mac80211: 802.11w... |
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
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 */ pn = key->u.aes_cmac.tx_pn; for (i = sizeof(key->u.aes_cmac.tx_pn) - 1; i >= 0; i--) { pn[i]++; if (pn[i]) break; } bip_ipn_swap(mmie->sequence_number, pn); bip_aad(skb, aad); /* * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */ ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.tx_crypto_buf, aad, skb->data + 24, skb->len - 24, mmie->mic); 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... |
511 |
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
765cb46a3 mac80211: 802.11w... |
512 513 514 515 516 517 518 |
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... |
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 |
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... |
534 |
if (!(status->flag & RX_FLAG_DECRYPTED)) { |
765cb46a3 mac80211: 802.11w... |
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 |
/* hardware didn't decrypt/verify MIC */ bip_aad(skb, aad); ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.rx_crypto_buf, aad, 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; } |