Commit a3b8b0569fbef725597f05278ec58083321f6e9d

Authored by Jouni Malinen
Committed by John W. Linville
1 parent 53b46b8444

nl80211: Add Michael MIC failure event

Define a new nl80211 event, NL80211_CMD_MICHAEL_MIC_FAILURE, to be
used to notify user space about locally detected Michael MIC failures.
This matches with the MLME-MICHAELMICFAILURE.indication() primitive.

Since we do not actually have TSC in the skb anymore when
mac80211_ev_michael_mic_failure() is called, that function is changed
to take in the TSC as an optional parameter instead of as a
requirement to include the TSC after the hdr field (which we did not
really follow). For now, TSC is not included in the events from
mac80211, but it could be added at some point.

Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 9 changed files with 111 additions and 11 deletions Side-by-side Diff

include/linux/nl80211.h
... ... @@ -199,6 +199,14 @@
199 199 * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to
200 200 * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives).
201 201 *
  202 + * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael
  203 + * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the
  204 + * event includes %NL80211_ATTR_MAC to describe the source MAC address of
  205 + * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key
  206 + * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and
  207 + * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this
  208 + * event matches with MLME-MICHAELMICFAILURE.indication() primitive
  209 + *
202 210 * @NL80211_CMD_MAX: highest used command number
203 211 * @__NL80211_CMD_AFTER_LAST: internal use
204 212 */
... ... @@ -260,6 +268,8 @@
260 268 NL80211_CMD_DEAUTHENTICATE,
261 269 NL80211_CMD_DISASSOCIATE,
262 270  
  271 + NL80211_CMD_MICHAEL_MIC_FAILURE,
  272 +
263 273 /* add new commands above here */
264 274  
265 275 /* used to define NL80211_CMD_MAX below */
... ... @@ -408,6 +418,9 @@
408 418 * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and
409 419 * %NL80211_CMD_DISASSOCIATE, u16
410 420 *
  421 + * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as
  422 + * a u32
  423 + *
411 424 * @NL80211_ATTR_MAX: highest attribute number currently defined
412 425 * @__NL80211_ATTR_AFTER_LAST: internal use
413 426 */
... ... @@ -492,6 +505,8 @@
492 505 NL80211_ATTR_AUTH_TYPE,
493 506 NL80211_ATTR_REASON_CODE,
494 507  
  508 + NL80211_ATTR_KEY_TYPE,
  509 +
495 510 /* add attributes here, update the policy in nl80211.c */
496 511  
497 512 __NL80211_ATTR_AFTER_LAST,
... ... @@ -1062,5 +1077,18 @@
1062 1077 NL80211_AUTHTYPE_FT,
1063 1078 NL80211_AUTHTYPE_NETWORK_EAP,
1064 1079 };
  1080 +
  1081 +/**
  1082 + * enum nl80211_key_type - Key Type
  1083 + * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key
  1084 + * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key
  1085 + * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS)
  1086 + */
  1087 +enum nl80211_key_type {
  1088 + NL80211_KEYTYPE_GROUP,
  1089 + NL80211_KEYTYPE_PAIRWISE,
  1090 + NL80211_KEYTYPE_PEERKEY,
  1091 +};
  1092 +
1065 1093 #endif /* __LINUX_NL80211_H */
include/net/cfg80211.h
... ... @@ -957,5 +957,21 @@
957 957 */
958 958 void cfg80211_unhold_bss(struct cfg80211_bss *bss);
959 959  
  960 +/**
  961 + * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP)
  962 + * @dev: network device
  963 + * @addr: The source MAC address of the frame
  964 + * @key_type: The key type that the received frame used
  965 + * @key_id: Key identifier (0..3)
  966 + * @tsc: The TSC value of the frame that generated the MIC failure (6 octets)
  967 + *
  968 + * This function is called whenever the local MAC detects a MIC failure in a
  969 + * received frame. This matches with MLME-MICHAELMICFAILURE.indication()
  970 + * primitive.
  971 + */
  972 +void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
  973 + enum nl80211_key_type key_type, int key_id,
  974 + const u8 *tsc);
  975 +
960 976 #endif /* __NET_CFG80211_H */
net/mac80211/event.c
... ... @@ -12,12 +12,12 @@
12 12 #include "ieee80211_i.h"
13 13  
14 14 /*
15   - * indicate a failed Michael MIC to userspace; the passed packet
16   - * (in the variable hdr) must be long enough to extract the TKIP
17   - * fields like TSC
  15 + * Indicate a failed Michael MIC to userspace. If the caller knows the TSC of
  16 + * the frame that generated the MIC failure (i.e., if it was provided by the
  17 + * driver or is still in the frame), it should provide that information.
18 18 */
19 19 void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
20   - struct ieee80211_hdr *hdr)
  20 + struct ieee80211_hdr *hdr, const u8 *tsc)
21 21 {
22 22 union iwreq_data wrqu;
23 23 char *buf = kmalloc(128, GFP_ATOMIC);
... ... @@ -34,9 +34,10 @@
34 34 kfree(buf);
35 35 }
36 36  
37   - /*
38   - * TODO: re-add support for sending MIC failure indication
39   - * with all info via nl80211
40   - */
  37 + cfg80211_michael_mic_failure(sdata->dev, hdr->addr2,
  38 + (hdr->addr1[0] & 0x01) ?
  39 + NL80211_KEYTYPE_GROUP :
  40 + NL80211_KEYTYPE_PAIRWISE,
  41 + keyidx, tsc);
41 42 }
net/mac80211/ieee80211_i.h
... ... @@ -1060,7 +1060,7 @@
1060 1060 int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
1061 1061 int rate, int erp, int short_preamble);
1062 1062 void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
1063   - struct ieee80211_hdr *hdr);
  1063 + struct ieee80211_hdr *hdr, const u8 *tsc);
1064 1064 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata);
1065 1065 void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
1066 1066 int encrypt);
... ... @@ -1932,7 +1932,7 @@
1932 1932 !ieee80211_is_auth(hdr->frame_control))
1933 1933 goto ignore;
1934 1934  
1935   - mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr);
  1935 + mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL);
1936 1936 ignore:
1937 1937 dev_kfree_skb(rx->skb);
1938 1938 rx->skb = NULL;
... ... @@ -122,7 +122,7 @@
122 122 return RX_DROP_UNUSABLE;
123 123  
124 124 mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx,
125   - (void *) skb->data);
  125 + (void *) skb->data, NULL);
126 126 return RX_DROP_UNUSABLE;
127 127 }
128 128  
... ... @@ -43,4 +43,14 @@
43 43 nl80211_send_disassoc(rdev, dev, buf, len);
44 44 }
45 45 EXPORT_SYMBOL(cfg80211_send_disassoc);
  46 +
  47 +void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
  48 + enum nl80211_key_type key_type, int key_id,
  49 + const u8 *tsc)
  50 +{
  51 + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
  52 + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  53 + nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc);
  54 +}
  55 +EXPORT_SYMBOL(cfg80211_michael_mic_failure);
net/wireless/nl80211.c
... ... @@ -3430,6 +3430,46 @@
3430 3430 NL80211_CMD_DISASSOCIATE);
3431 3431 }
3432 3432  
  3433 +void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
  3434 + struct net_device *netdev, const u8 *addr,
  3435 + enum nl80211_key_type key_type, int key_id,
  3436 + const u8 *tsc)
  3437 +{
  3438 + struct sk_buff *msg;
  3439 + void *hdr;
  3440 +
  3441 + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  3442 + if (!msg)
  3443 + return;
  3444 +
  3445 + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
  3446 + if (!hdr) {
  3447 + nlmsg_free(msg);
  3448 + return;
  3449 + }
  3450 +
  3451 + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
  3452 + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
  3453 + if (addr)
  3454 + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
  3455 + NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type);
  3456 + NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id);
  3457 + if (tsc)
  3458 + NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc);
  3459 +
  3460 + if (genlmsg_end(msg, hdr) < 0) {
  3461 + nlmsg_free(msg);
  3462 + return;
  3463 + }
  3464 +
  3465 + genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL);
  3466 + return;
  3467 +
  3468 + nla_put_failure:
  3469 + genlmsg_cancel(msg, hdr);
  3470 + nlmsg_free(msg);
  3471 +}
  3472 +
3433 3473 /* initialisation/exit functions */
3434 3474  
3435 3475 int nl80211_init(void)
net/wireless/nl80211.h
... ... @@ -23,6 +23,11 @@
23 23 extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
24 24 struct net_device *netdev,
25 25 const u8 *buf, size_t len);
  26 +extern void
  27 +nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
  28 + struct net_device *netdev, const u8 *addr,
  29 + enum nl80211_key_type key_type,
  30 + int key_id, const u8 *tsc);
26 31  
27 32 #endif /* __NET_WIRELESS_NL80211_H */