From 515985afed746eae567b6e2ca92854abf69c6287 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 16 Jul 2018 15:29:18 -0700 Subject: [PATCH] netdev: choose correct address on NEW_KEY/SET_STATION With the introduction of Ad-Hoc, its not as simple as choosing aa/spa addresses when setting the keys. Since Ad-Hoc acts as both the authenticator and supplicant we must check how the netdev address relates to the particular handshake object as well as choose the correct key depending on the value of the AA/SPA address. 802.11 states that the higher of the two addresses is to be used to set the key for the Ad-Hoc connection. A simple helper was added to choose the correct addressed based on netdev type and handshake state. netdev_set_tk also checks that aa > spa in the handshake object when in Ad-Hoc mode. If this is true then the keys from that handshake are used, otherwise return and the other handshake key will be used (aa will be > spa). The station/ap mode behaves exactly the same as before. --- src/netdev.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/netdev.c b/src/netdev.c index e71b9628..1c5e4ba5 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -1022,7 +1022,7 @@ static void netdev_set_station_cb(struct l_genl_msg *msg, void *user_data) nhs->set_station_cmd_id = 0; - if (!netdev->connected) + if (netdev->type == NL80211_IFTYPE_STATION && !netdev->connected) return; err = l_genl_msg_get_error(msg); @@ -1250,12 +1250,29 @@ static void netdev_set_igtk(struct handshake_state *hs, uint8_t key_index, netdev_setting_keys_failed(nhs, MMPDU_REASON_CODE_UNSPECIFIED); } +static const uint8_t *netdev_choose_key_address( + struct netdev_handshake_state *nhs) +{ + switch (nhs->netdev->type) { + case NL80211_IFTYPE_STATION: + return nhs->super.aa; + case NL80211_IFTYPE_AP: + return nhs->super.spa; + case NL80211_IFTYPE_ADHOC: + if (!memcmp(nhs->netdev->addr, nhs->super.aa, 6)) + return nhs->super.spa; + else + return nhs->super.aa; + default: + return NULL; + } +} + static void netdev_new_pairwise_key_cb(struct l_genl_msg *msg, void *data) { struct netdev_handshake_state *nhs = data; struct netdev *netdev = nhs->netdev; - const uint8_t *addr = (netdev->type == NL80211_IFTYPE_STATION) ? - nhs->super.aa : nhs->super.spa; + const uint8_t *addr = netdev_choose_key_address(nhs); nhs->pairwise_new_key_cmd_id = 0; @@ -1313,8 +1330,18 @@ static void netdev_set_tk(struct handshake_state *hs, struct netdev *netdev = nhs->netdev; struct l_genl_msg *msg; enum mmpdu_reason_code rc; - const uint8_t *addr = (netdev->type == NL80211_IFTYPE_STATION) ? - nhs->super.aa : nhs->super.spa; + const uint8_t *addr = netdev_choose_key_address(nhs); + + /* + * 802.11 Section 4.10.4.3: + * Because in an IBSS there are two 4-way handshakes between + * any two Supplicants and Authenticators, the pairwise key used + * between any two STAs is from the 4-way handshake initiated + * by the STA Authenticator with the higher MAC address... + */ + if (netdev->type == NL80211_IFTYPE_ADHOC && + memcmp(nhs->super.aa, nhs->super.spa, 6) < 0) + return; l_debug("%d", netdev->index);