aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-01-08 06:32:00 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:01 -0500
commitfb7333367632c67d8b6b06fb8d906cdabb11b02a (patch)
tree337d89f2c8c033b00dfcefbbcbded3f914d51661 /net/mac80211
parent5394af4d86ae51b369ff243c3f75b6f9a74e164b (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.c23
-rw-r--r--net/mac80211/wpa.c18
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
333static 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
333static ieee80211_tx_result 349static ieee80211_tx_result
334ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) 350ieee80211_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;