aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/wpa.c
diff options
context:
space:
mode:
authorHarvey Harrison <harvey.harrison@gmail.com>2008-07-02 14:05:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-07-08 14:16:00 -0400
commitf14df8049f9c9f34164dd598772fecea83a394a2 (patch)
tree3f13b28d569b69246e2a66bc6e9a9faf54c1f46b /net/mac80211/wpa.c
parent73e1f7c823252d671361cddde0b498bf2c0fe4e1 (diff)
mac80211: remove one user of ieee80211_get_hdr_info
ccmp_special_blocks was only using it to calculate data_len, calculate that directly. Use unaligned helpers rather than masking/shifting. Use symbolic constants for the masked frame_control, and do it directly on a le16 value. Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/wpa.c')
-rw-r--r--net/mac80211/wpa.c78
1 files changed, 37 insertions, 41 deletions
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 222001c47d89..919e30ce2980 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -11,6 +11,8 @@
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/skbuff.h> 12#include <linux/skbuff.h>
13#include <linux/compiler.h> 13#include <linux/compiler.h>
14#include <linux/ieee80211.h>
15#include <asm/unaligned.h>
14#include <net/mac80211.h> 16#include <net/mac80211.h>
15 17
16#include "ieee80211_i.h" 18#include "ieee80211_i.h"
@@ -296,67 +298,61 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
296static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, 298static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
297 int encrypted) 299 int encrypted)
298{ 300{
299 u16 fc; 301 __le16 mask_fc;
300 int a4_included, qos_included; 302 int a4_included;
301 u8 qos_tid, *fc_pos, *data, *sa, *da; 303 u8 qos_tid;
302 int len_a; 304 u16 data_len, len_a;
303 size_t data_len; 305 unsigned int hdrlen;
304 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 306 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
305 307
306 fc_pos = (u8 *) &hdr->frame_control; 308 /*
307 fc = fc_pos[0] ^ (fc_pos[1] << 8); 309 * Mask FC: zero subtype b4 b5 b6
308 a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == 310 * Retry, PwrMgt, MoreData; set Protected
309 (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); 311 */
310 312 mask_fc = hdr->frame_control;
311 ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len); 313 mask_fc &= ~cpu_to_le16(0x0070 | IEEE80211_FCTL_RETRY |
312 data_len -= CCMP_HDR_LEN + (encrypted ? CCMP_MIC_LEN : 0); 314 IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA);
313 if (qos_tid & 0x80) { 315 mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
314 qos_included = 1; 316
315 qos_tid &= IEEE80211_QOS_CTL_TID_MASK; 317 hdrlen = ieee80211_hdrlen(hdr->frame_control);
316 } else 318 len_a = hdrlen - 2;
317 qos_included = 0; 319 a4_included = ieee80211_has_a4(hdr->frame_control);
318 /* First block, b_0 */
319 320
321 if (ieee80211_is_data_qos(hdr->frame_control))
322 qos_tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
323 else
324 qos_tid = 0;
325
326 data_len = skb->len - hdrlen - CCMP_HDR_LEN;
327 if (encrypted)
328 data_len -= CCMP_MIC_LEN;
329
330 /* First block, b_0 */
320 b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ 331 b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
321 /* Nonce: QoS Priority | A2 | PN */ 332 /* Nonce: QoS Priority | A2 | PN */
322 b_0[1] = qos_tid; 333 b_0[1] = qos_tid;
323 memcpy(&b_0[2], hdr->addr2, ETH_ALEN); 334 memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
324 memcpy(&b_0[8], pn, CCMP_PN_LEN); 335 memcpy(&b_0[8], pn, CCMP_PN_LEN);
325 /* l(m) */ 336 /* l(m) */
326 b_0[14] = (data_len >> 8) & 0xff; 337 put_unaligned_be16(data_len, &b_0[14]);
327 b_0[15] = data_len & 0xff;
328
329 338
330 /* AAD (extra authenticate-only data) / masked 802.11 header 339 /* AAD (extra authenticate-only data) / masked 802.11 header
331 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ 340 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
332 341 put_unaligned_be16(len_a, &aad[0]);
333 len_a = a4_included ? 28 : 22; 342 put_unaligned(mask_fc, (__le16 *)&aad[2]);
334 if (qos_included)
335 len_a += IEEE80211_QOS_CTL_LEN;
336
337 aad[0] = 0; /* (len_a >> 8) & 0xff; */
338 aad[1] = len_a & 0xff;
339 /* Mask FC: zero subtype b4 b5 b6 */
340 aad[2] = fc_pos[0] & ~(BIT(4) | BIT(5) | BIT(6));
341 /* Retry, PwrMgt, MoreData; set Protected */
342 aad[3] = (fc_pos[1] & ~(BIT(3) | BIT(4) | BIT(5))) | BIT(6);
343 memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN); 343 memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);
344 344
345 /* Mask Seq#, leave Frag# */ 345 /* Mask Seq#, leave Frag# */
346 aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f; 346 aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f;
347 aad[23] = 0; 347 aad[23] = 0;
348
348 if (a4_included) { 349 if (a4_included) {
349 memcpy(&aad[24], hdr->addr4, ETH_ALEN); 350 memcpy(&aad[24], hdr->addr4, ETH_ALEN);
350 aad[30] = 0; 351 aad[30] = qos_tid;
351 aad[31] = 0; 352 aad[31] = 0;
352 } else 353 } else {
353 memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN); 354 memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
354 if (qos_included) { 355 aad[24] = qos_tid;
355 u8 *dpos = &aad[a4_included ? 30 : 24];
356
357 /* Mask QoS Control field */
358 dpos[0] = qos_tid;
359 dpos[1] = 0;
360 } 356 }
361} 357}
362 358