From 504497cf4a1cf51669f5e51783a3637c64c1a4eb Mon Sep 17 00:00:00 2001 From: Haiqing Bai Date: Wed, 1 Nov 2017 19:31:16 +0800 Subject: [PATCH] wpa-supplicant: WPA packet number reuse with replayed messages and key reinstallation Issue: LIN5-23848 LIN5-23860 LIN5-23879 LIN5-23852 LIN5-23847 LIN5-23828 LIN5-23840 LIN5-23838 LIN5-23825 A vulnerability was found in how a number of implementations can be triggered to reconfigure WPA/WPA2/RSN keys (TK, GTK, or IGTK) by replaying a specific frame that is used to manage the keys. Such reinstallation of the encryption key can result in two different types of vulnerabilities: disabling replay protection and significantly reducing the security of encryption to the point of allowing frames to be decrypted or some parts of the keys to be determined by an attacker depending on which cipher is used. CVE list: CVE-2017-13077 CVE-2017-13078 CVE-2017-13079 CVE-2017-13080 CVE-2017-13081 CVE-2017-13082 CVE-2017-13086 CVE-2017-13087 CVE-2017-13088 Signed-off-by: Haiqing Bai --- ...-Avoid-key-reinstallation-in-FT-handshake.patch | 130 ++++++++++++ ...nstallation-of-an-already-in-use-group-ke.patch | 219 +++++++++++++++++++++ ...ection-of-GTK-IGTK-reinstallation-of-WNM-.patch | 171 ++++++++++++++++ ...04-Prevent-installation-of-an-all-zero-TK.patch | 61 ++++++ ...Fix-PTK-rekeying-to-generate-a-new-ANonce.patch | 67 +++++++ ...llow-multiple-Reassociation-Response-fram.patch | 87 ++++++++ .../wpa-supplicant/wpa-supplicant_0.7.3.bb | 11 +- 7 files changed, 745 insertions(+), 1 deletion(-) create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0001-hostapd-Avoid-key-reinstallation-in-FT-handshake.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0002-Prevent-reinstallation-of-an-already-in-use-group-ke.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0003-Extend-protection-of-GTK-IGTK-reinstallation-of-WNM-.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0004-Prevent-installation-of-an-all-zero-TK.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0005-Fix-PTK-rekeying-to-generate-a-new-ANonce.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0008-FT-Do-not-allow-multiple-Reassociation-Response-fram.patch diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0001-hostapd-Avoid-key-reinstallation-in-FT-handshake.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0001-hostapd-Avoid-key-reinstallation-in-FT-handshake.patch new file mode 100644 index 0000000..432a341 --- /dev/null +++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0001-hostapd-Avoid-key-reinstallation-in-FT-handshake.patch @@ -0,0 +1,130 @@ +From 2847dd67cd07dd9b50d2b90a2deeea9e54ac7c01 Mon Sep 17 00:00:00 2001 +From: Haiqing Bai +Date: Wed, 18 Oct 2017 16:31:14 +0800 +Subject: [PATCH 1/6] hostapd: Avoid key reinstallation in FT handshake + +https://w1.fi/security/2017-1/rebased-v2.6-0001-hostapd-Avoid-key-reinstallation-in-FT-handshake.patch + +Do not reinstall TK to the driver during Reassociation Response frame +processing if the first attempt of setting the TK succeeded. This avoids +issues related to clearing the TX/RX PN that could result in reusing +same PN values for transmitted frames (e.g., due to CCM nonce reuse and +also hitting replay protection on the receiver) and accepting replayed +frames on RX side. + +This issue was introduced by the commit +0e84c25434e6a1f283c7b4e62e483729085b78d2 ('FT: Fix PTK configuration in +authenticator') which allowed wpa_ft_install_ptk() to be called multiple +times with the same PTK. While the second configuration attempt is +needed with some drivers, it must be done only if the first attempt +failed. + +Upstream-Status: Backport + +Signed-off-by: Mathy Vanhoef +Signed-off-by: Haiqing Bai +--- + src/ap/wpa_auth.c | 9 +++++++++ + src/ap/wpa_auth.h | 3 ++- + src/ap/wpa_auth_ft.c | 10 ++++++++++ + src/ap/wpa_auth_i.h | 1 + + 4 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c +index 36cb0f4..2ba2619 100644 +--- a/src/ap/wpa_auth.c ++++ b/src/ap/wpa_auth.c +@@ -1315,6 +1315,9 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) + #else /* CONFIG_IEEE80211R */ + break; + #endif /* CONFIG_IEEE80211R */ ++ case WPA_DRV_STA_REMOVED: ++ sm->tk_already_set = FALSE; ++ return 0; + } + + #ifdef CONFIG_IEEE80211R +@@ -2533,6 +2536,12 @@ int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) + return sm->wpa; + } + ++int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm) ++{ ++ if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt)) ++ return 0; ++ return sm->tk_already_set; ++} + + int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, + struct rsn_pmksa_cache_entry *entry) +diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h +index d0136c7..ddefc27 100644 +--- a/src/ap/wpa_auth.h ++++ b/src/ap/wpa_auth.h +@@ -232,7 +232,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, + u8 *data, size_t data_len); + typedef enum { + WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH, +- WPA_REAUTH_EAPOL, WPA_ASSOC_FT ++ WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED + } wpa_event; + void wpa_remove_ptk(struct wpa_state_machine *sm); + int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event); +@@ -245,6 +245,7 @@ int wpa_auth_pairwise_set(struct wpa_state_machine *sm); + int wpa_auth_get_pairwise(struct wpa_state_machine *sm); + int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm); + int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm); ++int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm); + int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, + struct rsn_pmksa_cache_entry *entry); + struct rsn_pmksa_cache_entry * +diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c +index c9871d9..dbfc9a6 100644 +--- a/src/ap/wpa_auth_ft.c ++++ b/src/ap/wpa_auth_ft.c +@@ -892,6 +892,14 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) + return; + } + ++ if (sm->tk_already_set) { ++ /* Must avoid TK reconfiguration to prevent clearing of TX/RX ++ * PN in the driver */ ++ wpa_printf(MSG_DEBUG, ++ "FT: Do not re-install same PTK to the driver"); ++ return; ++ } ++ + /* FIX: add STA entry to kernel/driver here? The set_key will fail + * most likely without this.. At the moment, STA entry is added only + * after association has been completed. This function will be called +@@ -904,6 +912,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) + + /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ + sm->pairwise_set = TRUE; ++ sm->tk_already_set = TRUE; + } + + +@@ -1017,6 +1026,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm, + wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); + + sm->pairwise = pairwise; ++ sm->tk_already_set = FALSE; + wpa_ft_install_ptk(sm); + + buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + +diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h +index b69129f..e52e931 100644 +--- a/src/ap/wpa_auth_i.h ++++ b/src/ap/wpa_auth_i.h +@@ -67,6 +67,7 @@ struct wpa_state_machine { + struct wpa_ptk PTK; + Boolean PTK_valid; + Boolean pairwise_set; ++ Boolean tk_already_set; + int keycount; + Boolean Pair; + struct { +-- +1.9.1 + diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0002-Prevent-reinstallation-of-an-already-in-use-group-ke.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0002-Prevent-reinstallation-of-an-already-in-use-group-ke.patch new file mode 100644 index 0000000..6a72745 --- /dev/null +++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0002-Prevent-reinstallation-of-an-already-in-use-group-ke.patch @@ -0,0 +1,219 @@ +From bbf5b35691d7e3c0a6b8f2b7c90197f9e4a800c9 Mon Sep 17 00:00:00 2001 +From: Haiqing Bai +Date: Tue, 24 Oct 2017 17:22:37 +0800 +Subject: [PATCH 2/6] Prevent reinstallation of an already in-use group key + +https://w1.fi/security/2017-1/rebased-v2.6-0002-Prevent-reinstallation-of-an-already-in-use-group-ke.patch + +Track the current GTK and IGTK that is in use and when receiving a +(possibly retransmitted) Group Message 1 or WNM-Sleep Mode Response, do +not install the given key if it is already in use. This prevents an +attacker from trying to trick the client into resetting or lowering the +sequence counter associated to the group key. + +Upstream-Status: Backport + +Signed-off-by: Mathy Vanhoef +Signed-off-by: Haiqing Bai +--- + src/common/wpa_common.h | 11 ++++++ + src/rsn_supp/wpa.c | 90 ++++++++++++++++++++++++++++++++++++------------- + src/rsn_supp/wpa_i.h | 4 +++ + 3 files changed, 82 insertions(+), 23 deletions(-) + +diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h +index fd8a79f..0c2bf78 100644 +--- a/src/common/wpa_common.h ++++ b/src/common/wpa_common.h +@@ -177,6 +177,17 @@ struct wpa_ptk { + } u; + } STRUCT_PACKED; + ++struct wpa_gtk { ++ u8 gtk[WPA_GTK_MAX_LEN]; ++ size_t gtk_len; ++}; ++ ++#ifdef CONFIG_IEEE80211W ++struct wpa_igtk { ++ u8 igtk[WPA_IGTK_MAX_LEN]; ++ size_t igtk_len; ++}; ++#endif /* CONFIG_IEEE80211W */ + + /* WPA IE version 1 + * 00-50-f2:1 (OUI:OUI type) +diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c +index 9439f97..405dd07 100644 +--- a/src/rsn_supp/wpa.c ++++ b/src/rsn_supp/wpa.c +@@ -618,6 +618,15 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *sm, + const u8 *_gtk = gd->gtk; + u8 gtk_buf[32]; + ++ /* Detect possible key reinstallation */ ++ if (sm->gtk.gtk_len == (size_t) gd->gtk_len && ++ os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) { ++ wpa_printf(MSG_DEBUG, ++ "WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)", ++ gd->keyidx, gd->tx, gd->gtk_len); ++ return 0; ++ } ++ + wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len); + wpa_printf(MSG_DEBUG, "WPA: Installing GTK to the driver " + "(keyidx=%d tx=%d len=%d).", gd->keyidx, gd->tx, +@@ -649,6 +658,9 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *sm, + return -1; + } + ++ sm->gtk.gtk_len = gd->gtk_len; ++ os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len); ++ + return 0; + } + +@@ -718,6 +730,46 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, + #endif /* CONFIG_NO_WPA2 */ + } + ++#ifdef CONFIG_IEEE80211W ++static int wpa_supplicant_install_igtk(struct wpa_sm *sm, ++ const struct wpa_igtk_kde *igtk) ++{ ++ size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher); ++ u16 keyidx = WPA_GET_LE16(igtk->keyid); ++ ++ /* Detect possible key reinstallation */ ++ if (sm->igtk.igtk_len == len && ++ os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) { ++ wpa_printf(MSG_DEBUG, ++ "WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)", ++ keyidx); ++ return 0; ++ } ++ ++ wpa_printf(MSG_DEBUG, ++ "WPA: IGTK keyid %d pn %02x%02x%02x%02x%02x%02x", ++ keyidx, MAC2STR(igtk->pn)); ++ wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len); ++ if (keyidx > 4095) { ++ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, ++ "WPA: Invalid IGTK KeyID %d", keyidx); ++ return -1; ++ } ++ if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher), ++ broadcast_ether_addr, ++ keyidx, 0, igtk->pn, sizeof(igtk->pn), ++ igtk->igtk, len) < 0) { ++ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, ++ "WPA: Failed to configure IGTK to the driver"); ++ return -1; ++ } ++ ++ sm->igtk.igtk_len = len; ++ os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len); ++ ++ return 0; ++} ++#endif /* CONFIG_IEEE80211W */ + + static int ieee80211w_set_keys(struct wpa_sm *sm, + struct wpa_eapol_ie_parse *ie) +@@ -728,29 +780,13 @@ static int ieee80211w_set_keys(struct wpa_sm *sm, + + if (ie->igtk) { + const struct wpa_igtk_kde *igtk; +- u16 keyidx; ++ + if (ie->igtk_len != sizeof(*igtk)) + return -1; ++ + igtk = (const struct wpa_igtk_kde *) ie->igtk; +- keyidx = WPA_GET_LE16(igtk->keyid); +- wpa_printf(MSG_DEBUG, "WPA: IGTK keyid %d " +- "pn %02x%02x%02x%02x%02x%02x", +- keyidx, MAC2STR(igtk->pn)); +- wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", +- igtk->igtk, WPA_IGTK_LEN); +- if (keyidx > 4095) { +- wpa_printf(MSG_WARNING, "WPA: Invalid IGTK KeyID %d", +- keyidx); +- return -1; +- } +- if (wpa_sm_set_key(sm, WPA_ALG_IGTK, +- (u8 *) "\xff\xff\xff\xff\xff\xff", +- keyidx, 0, igtk->pn, sizeof(igtk->pn), +- igtk->igtk, WPA_IGTK_LEN) < 0) { +- wpa_printf(MSG_WARNING, "WPA: Failed to configure IGTK" +- " to the driver"); +- return -1; +- } ++ if (wpa_supplicant_install_igtk(sm, igtk) < 0) ++ return -1; + } + + return 0; +@@ -2025,7 +2061,7 @@ void wpa_sm_deinit(struct wpa_sm *sm) + */ + void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) + { +- int clear_ptk = 1; ++ int clear_keys = 1; + + if (sm == NULL) + return; +@@ -2050,11 +2086,11 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) + /* Prepare for the next transition */ + wpa_ft_prepare_auth_request(sm, NULL); + +- clear_ptk = 0; ++ clear_keys = 0; + } + #endif /* CONFIG_IEEE80211R */ + +- if (clear_ptk) { ++ if (clear_keys) { + /* + * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if + * this is not part of a Fast BSS Transition. +@@ -2062,6 +2098,10 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) + wpa_printf(MSG_DEBUG, "WPA: Clear old PTK"); + sm->ptk_set = 0; + sm->tptk_set = 0; ++ os_memset(&sm->gtk, 0, sizeof(sm->gtk)); ++#ifdef CONFIG_IEEE80211W ++ os_memset(&sm->igtk, 0, sizeof(sm->igtk)); ++#endif /* CONFIG_IEEE80211W */ + } + } + +@@ -2555,6 +2595,10 @@ void wpa_sm_drop_sa(struct wpa_sm *sm) + os_memset(sm->pmk, 0, sizeof(sm->pmk)); + os_memset(&sm->ptk, 0, sizeof(sm->ptk)); + os_memset(&sm->tptk, 0, sizeof(sm->tptk)); ++ os_memset(&sm->gtk, 0, sizeof(sm->gtk)); ++#ifdef CONFIG_IEEE80211W ++ os_memset(&sm->igtk, 0, sizeof(sm->igtk)); ++#endif /* CONFIG_IEEE80211W */ + } + + +diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h +index 618c090..2394adf 100644 +--- a/src/rsn_supp/wpa_i.h ++++ b/src/rsn_supp/wpa_i.h +@@ -34,6 +34,10 @@ struct wpa_sm { + u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN]; + int rx_replay_counter_set; + u8 request_counter[WPA_REPLAY_COUNTER_LEN]; ++ struct wpa_gtk gtk; ++#ifdef CONFIG_IEEE80211W ++ struct wpa_igtk igtk; ++#endif /* CONFIG_IEEE80211W */ + + struct eapol_sm *eapol; /* EAPOL state machine from upper level code */ + +-- +1.9.1 + diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0003-Extend-protection-of-GTK-IGTK-reinstallation-of-WNM-.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0003-Extend-protection-of-GTK-IGTK-reinstallation-of-WNM-.patch new file mode 100644 index 0000000..a14391a --- /dev/null +++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0003-Extend-protection-of-GTK-IGTK-reinstallation-of-WNM-.patch @@ -0,0 +1,171 @@ +From a133877da02dfa41fd1fa07c65d6645c6189c1c4 Mon Sep 17 00:00:00 2001 +From: Haiqing Bai +Date: Tue, 24 Oct 2017 17:41:36 +0800 +Subject: [PATCH 3/6] Extend protection of GTK/IGTK reinstallation of WNM-Sleep + Mode cases + +https://w1.fi/security/2017-1/rebased-v2.6-0003-Extend-protection-of-GTK-IGTK-reinstallation-of-WNM-.patch + +This extends the protection to track last configured GTK/IGTK value +separately from EAPOL-Key frames and WNM-Sleep Mode frames to cover a +corner case where these two different mechanisms may get used when the +GTK/IGTK has changed and tracking a single value is not sufficient to +detect a possible key reconfiguration. + +Upstream-Status: Backport + +Signed-off-by: Jouni Malinen +Signed-off-by: Haiqing Bai +--- + src/rsn_supp/wpa.c | 49 ++++++++++++++++++++++++++++++++++++------------- + src/rsn_supp/wpa_i.h | 2 ++ + 2 files changed, 38 insertions(+), 13 deletions(-) + +diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c +index 405dd07..53c7ad2 100644 +--- a/src/rsn_supp/wpa.c ++++ b/src/rsn_supp/wpa.c +@@ -613,14 +613,17 @@ struct wpa_gtk_data { + + static int wpa_supplicant_install_gtk(struct wpa_sm *sm, + const struct wpa_gtk_data *gd, +- const u8 *key_rsc) ++ const u8 *key_rsc, int wnm_sleep) + { + const u8 *_gtk = gd->gtk; + u8 gtk_buf[32]; + + /* Detect possible key reinstallation */ +- if (sm->gtk.gtk_len == (size_t) gd->gtk_len && +- os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) { ++ if ((sm->gtk.gtk_len == (size_t) gd->gtk_len && ++ os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) || ++ (sm->gtk_wnm_sleep.gtk_len == (size_t) gd->gtk_len && ++ os_memcmp(sm->gtk_wnm_sleep.gtk, gd->gtk, ++ sm->gtk_wnm_sleep.gtk_len) == 0)) { + wpa_printf(MSG_DEBUG, + "WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)", + gd->keyidx, gd->tx, gd->gtk_len); +@@ -658,8 +661,14 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *sm, + return -1; + } + +- sm->gtk.gtk_len = gd->gtk_len; +- os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len); ++ if (wnm_sleep) { ++ sm->gtk_wnm_sleep.gtk_len = gd->gtk_len; ++ os_memcpy(sm->gtk_wnm_sleep.gtk, gd->gtk, ++ sm->gtk_wnm_sleep.gtk_len); ++ } else { ++ sm->gtk.gtk_len = gd->gtk_len; ++ os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len); ++ } + + return 0; + } +@@ -717,7 +726,7 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, + if (wpa_supplicant_check_group_cipher(sm->group_cipher, + gtk_len, gtk_len, + &gd.key_rsc_len, &gd.alg) || +- wpa_supplicant_install_gtk(sm, &gd, key->key_rsc)) { ++ wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0)) { + wpa_printf(MSG_DEBUG, "RSN: Failed to install GTK"); + return -1; + } +@@ -732,14 +741,18 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, + + #ifdef CONFIG_IEEE80211W + static int wpa_supplicant_install_igtk(struct wpa_sm *sm, +- const struct wpa_igtk_kde *igtk) ++ const struct wpa_igtk_kde *igtk, ++ int wnm_sleep) + { + size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher); + u16 keyidx = WPA_GET_LE16(igtk->keyid); + + /* Detect possible key reinstallation */ +- if (sm->igtk.igtk_len == len && +- os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) { ++ if ((sm->igtk.igtk_len == len && ++ os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) || ++ (sm->igtk_wnm_sleep.igtk_len == len && ++ os_memcmp(sm->igtk_wnm_sleep.igtk, igtk->igtk, ++ sm->igtk_wnm_sleep.igtk_len) == 0)) { + wpa_printf(MSG_DEBUG, + "WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)", + keyidx); +@@ -764,8 +777,14 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm, + return -1; + } + +- sm->igtk.igtk_len = len; +- os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len); ++ if (wnm_sleep) { ++ sm->igtk_wnm_sleep.igtk_len = len; ++ os_memcpy(sm->igtk_wnm_sleep.igtk, igtk->igtk, ++ sm->igtk_wnm_sleep.igtk_len); ++ } else { ++ sm->igtk.igtk_len = len; ++ os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len); ++ } + + return 0; + } +@@ -785,7 +804,7 @@ static int ieee80211w_set_keys(struct wpa_sm *sm, + return -1; + + igtk = (const struct wpa_igtk_kde *) ie->igtk; +- if (wpa_supplicant_install_igtk(sm, igtk) < 0) ++ if (wpa_supplicant_install_igtk(sm, igtk, 0) < 0) + return -1; + } + +@@ -1378,7 +1397,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, + if (ret) + goto failed; + +- if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) || ++ if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0) || + wpa_supplicant_send_2_of_2(sm, key, ver, key_info)) + goto failed; + +@@ -2099,8 +2118,10 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) + sm->ptk_set = 0; + sm->tptk_set = 0; + os_memset(&sm->gtk, 0, sizeof(sm->gtk)); ++ os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep)); + #ifdef CONFIG_IEEE80211W + os_memset(&sm->igtk, 0, sizeof(sm->igtk)); ++ os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep)); + #endif /* CONFIG_IEEE80211W */ + } + } +@@ -2596,8 +2617,10 @@ void wpa_sm_drop_sa(struct wpa_sm *sm) + os_memset(&sm->ptk, 0, sizeof(sm->ptk)); + os_memset(&sm->tptk, 0, sizeof(sm->tptk)); + os_memset(&sm->gtk, 0, sizeof(sm->gtk)); ++ os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep)); + #ifdef CONFIG_IEEE80211W + os_memset(&sm->igtk, 0, sizeof(sm->igtk)); ++ os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep)); + #endif /* CONFIG_IEEE80211W */ + } + +diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h +index 2394adf..c17a103 100644 +--- a/src/rsn_supp/wpa_i.h ++++ b/src/rsn_supp/wpa_i.h +@@ -35,8 +35,10 @@ struct wpa_sm { + int rx_replay_counter_set; + u8 request_counter[WPA_REPLAY_COUNTER_LEN]; + struct wpa_gtk gtk; ++ struct wpa_gtk gtk_wnm_sleep; + #ifdef CONFIG_IEEE80211W + struct wpa_igtk igtk; ++ struct wpa_igtk igtk_wnm_sleep; + #endif /* CONFIG_IEEE80211W */ + + struct eapol_sm *eapol; /* EAPOL state machine from upper level code */ +-- +1.9.1 + diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0004-Prevent-installation-of-an-all-zero-TK.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0004-Prevent-installation-of-an-all-zero-TK.patch new file mode 100644 index 0000000..d7e1e3b --- /dev/null +++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0004-Prevent-installation-of-an-all-zero-TK.patch @@ -0,0 +1,61 @@ +From 27e83efe125a3040e1659af891d9c2613e7fd864 Mon Sep 17 00:00:00 2001 +From: Haiqing Bai +Date: Fri, 27 Oct 2017 15:21:48 +0800 +Subject: [PATCH 4/6] Prevent installation of an all-zero TK + +https://w1.fi/security/2017-1/rebased-v2.6-0004-Prevent-installation-of-an-all-zero-TK.patch + +Properly track whether a PTK has already been installed to the driver +and the TK part cleared from memory. This prevents an attacker from +trying to trick the client into installing an all-zero TK. + +Upstream-Status: Backport + +Signed-off-by: Mathy Vanhoef +Signed-off-by: Haiqing Bai +--- + src/common/wpa_common.h | 1 + + src/rsn_supp/wpa.c | 8 ++++++++ + 2 files changed, 9 insertions(+) + +diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h +index 0c2bf78..2701092 100644 +--- a/src/common/wpa_common.h ++++ b/src/common/wpa_common.h +@@ -175,6 +175,7 @@ struct wpa_ptk { + u8 rx_mic_key[8]; + } auth; + } u; ++ int installed; /* 1 if key has already been installed to driver */ + } STRUCT_PACKED; + + struct wpa_gtk { +diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c +index 53c7ad2..b39a1fd 100644 +--- a/src/rsn_supp/wpa.c ++++ b/src/rsn_supp/wpa.c +@@ -499,6 +499,12 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, + const u8 *key_rsc; + u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + ++ if (sm->ptk.installed) { ++ wpa_printf(MSG_DEBUG, ++ "WPA: Do not re-install same PTK to the driver"); ++ return 0; ++ } ++ + wpa_printf(MSG_DEBUG, "WPA: Installing PTK to the driver."); + + switch (sm->pairwise_cipher) { +@@ -537,6 +543,8 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, + return -1; + } + ++ sm->ptk.installed = 1; ++ + if (sm->wpa_ptk_rekey) { + eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); + eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, +-- +1.9.1 + diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0005-Fix-PTK-rekeying-to-generate-a-new-ANonce.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0005-Fix-PTK-rekeying-to-generate-a-new-ANonce.patch new file mode 100644 index 0000000..628c57f --- /dev/null +++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0005-Fix-PTK-rekeying-to-generate-a-new-ANonce.patch @@ -0,0 +1,67 @@ +From 7a392c9f5478007e52222228cdf0ccfaff27a43c Mon Sep 17 00:00:00 2001 +From: Haiqing Bai +Date: Wed, 18 Oct 2017 15:59:36 +0800 +Subject: [PATCH 5/6] Fix PTK rekeying to generate a new ANonce + +https://w1.fi/security/2017-1/rebased-v2.6-0005-Fix-PTK-rekeying-to-generate-a-new-ANonce.patch + +The Authenticator state machine path for PTK rekeying ended up bypassing +the AUTHENTICATION2 state where a new ANonce is generated when going +directly to the PTKSTART state since there is no need to try to +determine the PMK again in such a case. This is far from ideal since the +new PTK would depend on a new nonce only from the supplicant. + +Fix this by generating a new ANonce when moving to the PTKSTART state +for the purpose of starting new 4-way handshake to rekey PTK. + +Upstream-Status: Backport + +Signed-off-by: Jouni Malinen +Signed-off-by: Haiqing Bai +--- + src/ap/wpa_auth.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c +index 2ba2619..547754d 100644 +--- a/src/ap/wpa_auth.c ++++ b/src/ap/wpa_auth.c +@@ -1427,6 +1427,19 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) + sm->TimeoutCtr = 0; + } + ++static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm) ++{ ++ if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { ++ wpa_printf(MSG_ERROR, ++ "WPA: Failed to get random data for ANonce"); ++ sm->Disconnect = TRUE; ++ return -1; ++ } ++ wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce, ++ WPA_NONCE_LEN); ++ sm->TimeoutCtr = 0; ++ return 0; ++} + + SM_STATE(WPA_PTK, INITPMK) + { +@@ -1887,9 +1900,12 @@ SM_STEP(WPA_PTK) + SM_ENTER(WPA_PTK, AUTHENTICATION); + else if (sm->ReAuthenticationRequest) + SM_ENTER(WPA_PTK, AUTHENTICATION2); +- else if (sm->PTKRequest) +- SM_ENTER(WPA_PTK, PTKSTART); +- else switch (sm->wpa_ptk_state) { ++ else if (sm->PTKRequest) { ++ if (wpa_auth_sm_ptk_update(sm) < 0) ++ SM_ENTER(WPA_PTK, DISCONNECTED); ++ else ++ SM_ENTER(WPA_PTK, PTKSTART); ++ } else switch (sm->wpa_ptk_state) { + case WPA_PTK_INITIALIZE: + break; + case WPA_PTK_DISCONNECT: +-- +1.9.1 + diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0008-FT-Do-not-allow-multiple-Reassociation-Response-fram.patch b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0008-FT-Do-not-allow-multiple-Reassociation-Response-fram.patch new file mode 100644 index 0000000..01f1e60 --- /dev/null +++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant-0.7.3/0008-FT-Do-not-allow-multiple-Reassociation-Response-fram.patch @@ -0,0 +1,87 @@ +From 08ee9827ec6cfdc10b9a2cf5a3c096c81bff2055 Mon Sep 17 00:00:00 2001 +From: Haiqing Bai +Date: Tue, 24 Oct 2017 18:42:29 +0800 +Subject: [PATCH 6/6] FT: Do not allow multiple Reassociation Response frames + +https://w1.fi/security/2017-1/rebased-v2.6-0008-FT-Do-not-allow-multiple-Reassociation-Response-fram.patch + +The driver is expected to not report a second association event without +the station having explicitly request a new association. As such, this +case should not be reachable. However, since reconfiguring the same +pairwise or group keys to the driver could result in nonce reuse issues, +be extra careful here and do an additional state check to avoid this +even if the local driver ends up somehow accepting an unexpected +Reassociation Response frame. + +Upstream-Status: Backport + +Signed-off-by: Jouni Malinen +Signed-off-by: Haiqing Bai +--- + src/rsn_supp/wpa.c | 3 +++ + src/rsn_supp/wpa_ft.c | 8 ++++++++ + src/rsn_supp/wpa_i.h | 1 + + 3 files changed, 12 insertions(+) + +diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c +index b39a1fd..c041e33 100644 +--- a/src/rsn_supp/wpa.c ++++ b/src/rsn_supp/wpa.c +@@ -2147,6 +2147,9 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) + rsn_preauth_deinit(sm); + if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE) + sm->dot11RSNA4WayHandshakeFailures++; ++#ifdef CONFIG_IEEE80211R ++ sm->ft_reassoc_completed = 0; ++#endif /* CONFIG_IEEE80211R */ + } + + +diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c +index 23063bc..4bf7355 100644 +--- a/src/rsn_supp/wpa_ft.c ++++ b/src/rsn_supp/wpa_ft.c +@@ -187,6 +187,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, + u16 capab; + + sm->ft_completed = 0; ++ sm->ft_reassoc_completed = 0; + + buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + + 2 + sm->r0kh_id_len + ric_ies_len + 100; +@@ -879,6 +880,11 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, + return -1; + } + ++ if (sm->ft_reassoc_completed) { ++ wpa_printf(MSG_DEBUG, "FT: Reassociation has already been completed for this FT protocol instance - ignore unexpected retransmission"); ++ return 0; ++ } ++ + if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { + wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); + return -1; +@@ -977,6 +983,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, + return -1; + } + ++ sm->ft_reassoc_completed = 1; ++ + if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) + return -1; + +diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h +index c17a103..df9b2a6 100644 +--- a/src/rsn_supp/wpa_i.h ++++ b/src/rsn_supp/wpa_i.h +@@ -111,6 +111,7 @@ struct wpa_sm { + size_t r0kh_id_len; + u8 r1kh_id[FT_R1KH_ID_LEN]; + int ft_completed; ++ int ft_reassoc_completed; + int over_the_ds_in_progress; + u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */ + int set_ptk_after_assoc; +-- +1.9.1 + diff --git a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant_0.7.3.bb b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant_0.7.3.bb index 7bbb8c0..af70cf5 100644 --- a/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant_0.7.3.bb +++ b/meta/recipes-connectivity/wpa-supplicant/wpa-supplicant_0.7.3.bb @@ -1,6 +1,15 @@ require wpa-supplicant-0.7.inc -PR = "r11" +PR = "r12" + +SRC_URI += "\ + file://0001-hostapd-Avoid-key-reinstallation-in-FT-handshake.patch;patchdir=.. \ + file://0002-Prevent-reinstallation-of-an-already-in-use-group-ke.patch;patchdir=.. \ + file://0003-Extend-protection-of-GTK-IGTK-reinstallation-of-WNM-.patch;patchdir=.. \ + file://0004-Prevent-installation-of-an-all-zero-TK.patch;patchdir=.. \ + file://0005-Fix-PTK-rekeying-to-generate-a-new-ANonce.patch;patchdir=.. \ + file://0008-FT-Do-not-allow-multiple-Reassociation-Response-fram.patch;patchdir=.. \ + " SRC_URI[md5sum] = "f516f191384a9a546e3f5145c08addda" SRC_URI[sha256sum] = "d0cd50caa85346ccc376dcda5ed3c258eef19a93b3cade39d25760118ad59443" -- 1.9.1