diff options
author | Jouni Malinen <j@w1.fi> | 2009-01-08 06:32:02 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 16:00:03 -0500 |
commit | 3cfcf6ac6d69dc290e96416731eea5c88ac7d426 (patch) | |
tree | 35bc626e2e3f7c37a7eb50c1f057adb4830eccc6 /net/mac80211/rx.c | |
parent | 765cb46a3fc856245ea68a7c961ac87c77e4ae2d (diff) |
mac80211: 802.11w - Use BIP (AES-128-CMAC)
Add mechanism for managing BIP keys (IGTK) and integrate BIP into the
TX/RX paths.
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/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 90 |
1 files changed, 83 insertions, 7 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b68e082e99ce..abc3aa583ca6 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -446,6 +446,52 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
446 | return RX_CONTINUE; | 446 | return RX_CONTINUE; |
447 | } | 447 | } |
448 | 448 | ||
449 | |||
450 | static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) | ||
451 | { | ||
452 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
453 | |||
454 | if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) | ||
455 | return 0; | ||
456 | |||
457 | return ieee80211_is_robust_mgmt_frame(hdr); | ||
458 | } | ||
459 | |||
460 | |||
461 | static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb) | ||
462 | { | ||
463 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
464 | |||
465 | if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) | ||
466 | return 0; | ||
467 | |||
468 | return ieee80211_is_robust_mgmt_frame(hdr); | ||
469 | } | ||
470 | |||
471 | |||
472 | /* Get the BIP key index from MMIE; return -1 if this is not a BIP frame */ | ||
473 | static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | ||
474 | { | ||
475 | struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; | ||
476 | struct ieee80211_mmie *mmie; | ||
477 | |||
478 | if (skb->len < 24 + sizeof(*mmie) || | ||
479 | !is_multicast_ether_addr(hdr->da)) | ||
480 | return -1; | ||
481 | |||
482 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) | ||
483 | return -1; /* not a robust management frame */ | ||
484 | |||
485 | mmie = (struct ieee80211_mmie *) | ||
486 | (skb->data + skb->len - sizeof(*mmie)); | ||
487 | if (mmie->element_id != WLAN_EID_MMIE || | ||
488 | mmie->length != sizeof(*mmie) - 2) | ||
489 | return -1; | ||
490 | |||
491 | return le16_to_cpu(mmie->key_id); | ||
492 | } | ||
493 | |||
494 | |||
449 | static ieee80211_rx_result | 495 | static ieee80211_rx_result |
450 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | 496 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) |
451 | { | 497 | { |
@@ -561,21 +607,23 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
561 | int hdrlen; | 607 | int hdrlen; |
562 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | 608 | ieee80211_rx_result result = RX_DROP_UNUSABLE; |
563 | struct ieee80211_key *stakey = NULL; | 609 | struct ieee80211_key *stakey = NULL; |
610 | int mmie_keyidx = -1; | ||
564 | 611 | ||
565 | /* | 612 | /* |
566 | * Key selection 101 | 613 | * Key selection 101 |
567 | * | 614 | * |
568 | * There are three types of keys: | 615 | * There are four types of keys: |
569 | * - GTK (group keys) | 616 | * - GTK (group keys) |
617 | * - IGTK (group keys for management frames) | ||
570 | * - PTK (pairwise keys) | 618 | * - PTK (pairwise keys) |
571 | * - STK (station-to-station pairwise keys) | 619 | * - STK (station-to-station pairwise keys) |
572 | * | 620 | * |
573 | * When selecting a key, we have to distinguish between multicast | 621 | * When selecting a key, we have to distinguish between multicast |
574 | * (including broadcast) and unicast frames, the latter can only | 622 | * (including broadcast) and unicast frames, the latter can only |
575 | * use PTKs and STKs while the former always use GTKs. Unless, of | 623 | * use PTKs and STKs while the former always use GTKs and IGTKs. |
576 | * course, actual WEP keys ("pre-RSNA") are used, then unicast | 624 | * Unless, of course, actual WEP keys ("pre-RSNA") are used, then |
577 | * frames can also use key indizes like GTKs. Hence, if we don't | 625 | * unicast frames can also use key indices like GTKs. Hence, if we |
578 | * have a PTK/STK we check the key index for a WEP key. | 626 | * don't have a PTK/STK we check the key index for a WEP key. |
579 | * | 627 | * |
580 | * Note that in a regular BSS, multicast frames are sent by the | 628 | * Note that in a regular BSS, multicast frames are sent by the |
581 | * AP only, associated stations unicast the frame to the AP first | 629 | * AP only, associated stations unicast the frame to the AP first |
@@ -588,8 +636,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
588 | * possible. | 636 | * possible. |
589 | */ | 637 | */ |
590 | 638 | ||
591 | if (!ieee80211_has_protected(hdr->frame_control)) | 639 | if (!ieee80211_has_protected(hdr->frame_control)) { |
592 | return RX_CONTINUE; | 640 | if (!ieee80211_is_mgmt(hdr->frame_control) || |
641 | rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP)) | ||
642 | return RX_CONTINUE; | ||
643 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | ||
644 | if (mmie_keyidx < 0) | ||
645 | return RX_CONTINUE; | ||
646 | } | ||
593 | 647 | ||
594 | /* | 648 | /* |
595 | * No point in finding a key and decrypting if the frame is neither | 649 | * No point in finding a key and decrypting if the frame is neither |
@@ -603,6 +657,16 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
603 | 657 | ||
604 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 658 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { |
605 | rx->key = stakey; | 659 | rx->key = stakey; |
660 | } else if (mmie_keyidx >= 0) { | ||
661 | /* Broadcast/multicast robust management frame / BIP */ | ||
662 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | ||
663 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | ||
664 | return RX_CONTINUE; | ||
665 | |||
666 | if (mmie_keyidx < NUM_DEFAULT_KEYS || | ||
667 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | ||
668 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | ||
669 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | ||
606 | } else { | 670 | } else { |
607 | /* | 671 | /* |
608 | * The device doesn't give us the IV so we won't be | 672 | * The device doesn't give us the IV so we won't be |
@@ -665,6 +729,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
665 | case ALG_CCMP: | 729 | case ALG_CCMP: |
666 | result = ieee80211_crypto_ccmp_decrypt(rx); | 730 | result = ieee80211_crypto_ccmp_decrypt(rx); |
667 | break; | 731 | break; |
732 | case ALG_AES_CMAC: | ||
733 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | ||
734 | break; | ||
668 | } | 735 | } |
669 | 736 | ||
670 | /* either the frame has been decrypted or will be dropped */ | 737 | /* either the frame has been decrypted or will be dropped */ |
@@ -1112,6 +1179,15 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | |||
1112 | /* Drop unencrypted frames if key is set. */ | 1179 | /* Drop unencrypted frames if key is set. */ |
1113 | if (unlikely(!ieee80211_has_protected(fc) && | 1180 | if (unlikely(!ieee80211_has_protected(fc) && |
1114 | !ieee80211_is_nullfunc(fc) && | 1181 | !ieee80211_is_nullfunc(fc) && |
1182 | (!ieee80211_is_mgmt(fc) || | ||
1183 | (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1184 | rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) && | ||
1185 | (rx->key || rx->sdata->drop_unencrypted))) | ||
1186 | return -EACCES; | ||
1187 | /* BIP does not use Protected field, so need to check MMIE */ | ||
1188 | if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) && | ||
1189 | ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | ||
1190 | ieee80211_get_mmie_keyidx(rx->skb) < 0 && | ||
1115 | (rx->key || rx->sdata->drop_unencrypted))) | 1191 | (rx->key || rx->sdata->drop_unencrypted))) |
1116 | return -EACCES; | 1192 | return -EACCES; |
1117 | 1193 | ||