diff options
author | Jouni Malinen <j@w1.fi> | 2009-01-08 06:32:00 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 16:00:01 -0500 |
commit | fb7333367632c67d8b6b06fb8d906cdabb11b02a (patch) | |
tree | 337d89f2c8c033b00dfcefbbcbded3f914d51661 /net/mac80211 | |
parent | 5394af4d86ae51b369ff243c3f75b6f9a74e164b (diff) |
mac80211: 802.11w - CCMP for management frames
Extend CCMP to support encryption and decryption of unicast management
frames.
Signed-off-by: Jouni Malinen <j@w1.fi>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/tx.c | 23 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 18 |
2 files changed, 34 insertions, 7 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index cd6bc87eec73..50c6c4fabea5 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -330,6 +330,22 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
330 | return TX_CONTINUE; | 330 | return TX_CONTINUE; |
331 | } | 331 | } |
332 | 332 | ||
333 | static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, | ||
334 | struct sk_buff *skb) | ||
335 | { | ||
336 | if (!ieee80211_is_mgmt(fc)) | ||
337 | return 0; | ||
338 | |||
339 | if (sta == NULL || !test_sta_flags(sta, WLAN_STA_MFP)) | ||
340 | return 0; | ||
341 | |||
342 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) | ||
343 | skb->data)) | ||
344 | return 0; | ||
345 | |||
346 | return 1; | ||
347 | } | ||
348 | |||
333 | static ieee80211_tx_result | 349 | static ieee80211_tx_result |
334 | ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | 350 | ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) |
335 | { | 351 | { |
@@ -428,10 +444,15 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
428 | if (ieee80211_is_auth(hdr->frame_control)) | 444 | if (ieee80211_is_auth(hdr->frame_control)) |
429 | break; | 445 | break; |
430 | case ALG_TKIP: | 446 | case ALG_TKIP: |
431 | case ALG_CCMP: | ||
432 | if (!ieee80211_is_data_present(hdr->frame_control)) | 447 | if (!ieee80211_is_data_present(hdr->frame_control)) |
433 | tx->key = NULL; | 448 | tx->key = NULL; |
434 | break; | 449 | break; |
450 | case ALG_CCMP: | ||
451 | if (!ieee80211_is_data_present(hdr->frame_control) && | ||
452 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, | ||
453 | tx->skb)) | ||
454 | tx->key = NULL; | ||
455 | break; | ||
435 | } | 456 | } |
436 | } | 457 | } |
437 | 458 | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 7aa63caf8d50..aff46adde3f0 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -266,7 +266,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | |||
266 | int encrypted) | 266 | int encrypted) |
267 | { | 267 | { |
268 | __le16 mask_fc; | 268 | __le16 mask_fc; |
269 | int a4_included; | 269 | int a4_included, mgmt; |
270 | u8 qos_tid; | 270 | u8 qos_tid; |
271 | u8 *b_0, *aad; | 271 | u8 *b_0, *aad; |
272 | u16 data_len, len_a; | 272 | u16 data_len, len_a; |
@@ -277,12 +277,15 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | |||
277 | aad = scratch + 4 * AES_BLOCK_LEN; | 277 | aad = scratch + 4 * AES_BLOCK_LEN; |
278 | 278 | ||
279 | /* | 279 | /* |
280 | * Mask FC: zero subtype b4 b5 b6 | 280 | * Mask FC: zero subtype b4 b5 b6 (if not mgmt) |
281 | * Retry, PwrMgt, MoreData; set Protected | 281 | * Retry, PwrMgt, MoreData; set Protected |
282 | */ | 282 | */ |
283 | mgmt = ieee80211_is_mgmt(hdr->frame_control); | ||
283 | mask_fc = hdr->frame_control; | 284 | mask_fc = hdr->frame_control; |
284 | mask_fc &= ~cpu_to_le16(0x0070 | IEEE80211_FCTL_RETRY | | 285 | mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | |
285 | IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); | 286 | IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); |
287 | if (!mgmt) | ||
288 | mask_fc &= ~cpu_to_le16(0x0070); | ||
286 | mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 289 | mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
287 | 290 | ||
288 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 291 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
@@ -300,8 +303,10 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | |||
300 | 303 | ||
301 | /* First block, b_0 */ | 304 | /* First block, b_0 */ |
302 | b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ | 305 | b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ |
303 | /* Nonce: QoS Priority | A2 | PN */ | 306 | /* Nonce: Nonce Flags | A2 | PN |
304 | b_0[1] = qos_tid; | 307 | * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) |
308 | */ | ||
309 | b_0[1] = qos_tid | (mgmt << 4); | ||
305 | memcpy(&b_0[2], hdr->addr2, ETH_ALEN); | 310 | memcpy(&b_0[2], hdr->addr2, ETH_ALEN); |
306 | memcpy(&b_0[8], pn, CCMP_PN_LEN); | 311 | memcpy(&b_0[8], pn, CCMP_PN_LEN); |
307 | /* l(m) */ | 312 | /* l(m) */ |
@@ -446,7 +451,8 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
446 | 451 | ||
447 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 452 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
448 | 453 | ||
449 | if (!ieee80211_is_data(hdr->frame_control)) | 454 | if (!ieee80211_is_data(hdr->frame_control) && |
455 | !ieee80211_is_robust_mgmt_frame(hdr)) | ||
450 | return RX_CONTINUE; | 456 | return RX_CONTINUE; |
451 | 457 | ||
452 | data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; | 458 | data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; |