Fixes CVE-2017-{13078,13079,13080,13081,13082,13087,13088}.
See these announcements for more information:
https://w1.fi/security/2017-1/wpa-packet-number-reuse-with-replayed-messages.txt
https://www.krackattacks.com/
* gnu/packages/patches/wpa-supplicant-CVE-2017-13082.patch,
gnu/packages/patches/wpa-supplicant-fix-key-reuse.patch,
gnu/packages/patches/wpa-supplicant-fix-nonce-reuse.patch
gnu/packages/patches/wpa-supplicant-fix-zeroed-keys.patch,
gnu/packages/patches/wpa-supplicant-krack-followups.patch: New files.
* gnu/packages/admin.scm (wpa-supplicant-minimal)[source]: Use them.
* gnu/local.mk (dist_patch_DATA): Add them.
		
	
			
		
			
				
	
	
		
			275 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			275 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| These three patches are follow-ups to the bug fixes for the 'KRACK' key
 | |
| re-installation attacks on Wi-Fi's WPA2 security protocol. See upstream
 | |
| security announcement for more information:
 | |
| 
 | |
| https://w1.fi/security/2017-1/wpa-packet-number-reuse-with-replayed-messages.txt
 | |
| 
 | |
| These three patches copied from upstream:
 | |
| 
 | |
| https://w1.fi/security/2017-1/rebased-v2.6-0006-TDLS-Reject-TPK-TK-reconfiguration.patch
 | |
| https://w1.fi/security/2017-1/rebased-v2.6-0007-WNM-Ignore-WNM-Sleep-Mode-Response-without-pending-r.patch
 | |
| https://w1.fi/security/2017-1/rebased-v2.6-0008-FT-Do-not-allow-multiple-Reassociation-Response-fram.patch
 | |
| 
 | |
| From 6c4bed4f47d1960ec04981a9d50e5076aea5223d Mon Sep 17 00:00:00 2001
 | |
| From: Jouni Malinen <j@w1.fi>
 | |
| Date: Fri, 22 Sep 2017 11:03:15 +0300
 | |
| Subject: [PATCH 6/8] TDLS: Reject TPK-TK reconfiguration
 | |
| 
 | |
| Do not try to reconfigure the same TPK-TK to the driver after it has
 | |
| been successfully configured. This is an explicit check to avoid issues
 | |
| related to resetting the TX/RX packet number. There was already a check
 | |
| for this for TPK M2 (retries of that message are ignored completely), so
 | |
| that behavior does not get modified.
 | |
| 
 | |
| For TPK M3, the TPK-TK could have been reconfigured, but that was
 | |
| followed by immediate teardown of the link due to an issue in updating
 | |
| the STA entry. Furthermore, for TDLS with any real security (i.e.,
 | |
| ignoring open/WEP), the TPK message exchange is protected on the AP path
 | |
| and simple replay attacks are not feasible.
 | |
| 
 | |
| As an additional corner case, make sure the local nonce gets updated if
 | |
| the peer uses a very unlikely "random nonce" of all zeros.
 | |
| 
 | |
| Signed-off-by: Jouni Malinen <j@w1.fi>
 | |
| ---
 | |
|  src/rsn_supp/tdls.c | 38 ++++++++++++++++++++++++++++++++++++--
 | |
|  1 file changed, 36 insertions(+), 2 deletions(-)
 | |
| 
 | |
| diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
 | |
| index e424168..9eb9738 100644
 | |
| --- a/src/rsn_supp/tdls.c
 | |
| +++ b/src/rsn_supp/tdls.c
 | |
| @@ -112,6 +112,7 @@ struct wpa_tdls_peer {
 | |
|  		u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */
 | |
|  	} tpk;
 | |
|  	int tpk_set;
 | |
| +	int tk_set; /* TPK-TK configured to the driver */
 | |
|  	int tpk_success;
 | |
|  	int tpk_in_progress;
 | |
|  
 | |
| @@ -192,6 +193,20 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 | |
|  	u8 rsc[6];
 | |
|  	enum wpa_alg alg;
 | |
|  
 | |
| +	if (peer->tk_set) {
 | |
| +		/*
 | |
| +		 * This same TPK-TK has already been configured to the driver
 | |
| +		 * and this new configuration attempt (likely due to an
 | |
| +		 * unexpected retransmitted frame) would result in clearing
 | |
| +		 * the TX/RX sequence number which can break security, so must
 | |
| +		 * not allow that to happen.
 | |
| +		 */
 | |
| +		wpa_printf(MSG_INFO, "TDLS: TPK-TK for the peer " MACSTR
 | |
| +			   " has already been configured to the driver - do not reconfigure",
 | |
| +			   MAC2STR(peer->addr));
 | |
| +		return -1;
 | |
| +	}
 | |
| +
 | |
|  	os_memset(rsc, 0, 6);
 | |
|  
 | |
|  	switch (peer->cipher) {
 | |
| @@ -209,12 +224,15 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 | |
|  		return -1;
 | |
|  	}
 | |
|  
 | |
| +	wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR,
 | |
| +		   MAC2STR(peer->addr));
 | |
|  	if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
 | |
|  			   rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
 | |
|  		wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
 | |
|  			   "driver");
 | |
|  		return -1;
 | |
|  	}
 | |
| +	peer->tk_set = 1;
 | |
|  	return 0;
 | |
|  }
 | |
|  
 | |
| @@ -696,7 +714,7 @@ static void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 | |
|  	peer->cipher = 0;
 | |
|  	peer->qos_info = 0;
 | |
|  	peer->wmm_capable = 0;
 | |
| -	peer->tpk_set = peer->tpk_success = 0;
 | |
| +	peer->tk_set = peer->tpk_set = peer->tpk_success = 0;
 | |
|  	peer->chan_switch_enabled = 0;
 | |
|  	os_memset(&peer->tpk, 0, sizeof(peer->tpk));
 | |
|  	os_memset(peer->inonce, 0, WPA_NONCE_LEN);
 | |
| @@ -1159,6 +1177,7 @@ skip_rsnie:
 | |
|  		wpa_tdls_peer_free(sm, peer);
 | |
|  		return -1;
 | |
|  	}
 | |
| +	peer->tk_set = 0; /* A new nonce results in a new TK */
 | |
|  	wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
 | |
|  		    peer->inonce, WPA_NONCE_LEN);
 | |
|  	os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
 | |
| @@ -1751,6 +1770,19 @@ static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
 | |
|  }
 | |
|  
 | |
|  
 | |
| +static int tdls_nonce_set(const u8 *nonce)
 | |
| +{
 | |
| +	int i;
 | |
| +
 | |
| +	for (i = 0; i < WPA_NONCE_LEN; i++) {
 | |
| +		if (nonce[i])
 | |
| +			return 1;
 | |
| +	}
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +
 | |
|  static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
 | |
|  				   const u8 *buf, size_t len)
 | |
|  {
 | |
| @@ -2004,7 +2036,8 @@ skip_rsn:
 | |
|  	peer->rsnie_i_len = kde.rsn_ie_len;
 | |
|  	peer->cipher = cipher;
 | |
|  
 | |
| -	if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
 | |
| +	if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0 ||
 | |
| +	    !tdls_nonce_set(peer->inonce)) {
 | |
|  		/*
 | |
|  		 * There is no point in updating the RNonce for every obtained
 | |
|  		 * TPK M1 frame (e.g., retransmission due to timeout) with the
 | |
| @@ -2020,6 +2053,7 @@ skip_rsn:
 | |
|  				"TDLS: Failed to get random data for responder nonce");
 | |
|  			goto error;
 | |
|  		}
 | |
| +		peer->tk_set = 0; /* A new nonce results in a new TK */
 | |
|  	}
 | |
|  
 | |
|  #if 0
 | |
| -- 
 | |
| 2.7.4
 | |
| 
 | |
| From 53c5eb58e95004f86e65ee9fbfccbc291b139057 Mon Sep 17 00:00:00 2001
 | |
| From: Jouni Malinen <j@w1.fi>
 | |
| Date: Fri, 22 Sep 2017 11:25:02 +0300
 | |
| Subject: [PATCH 7/8] WNM: Ignore WNM-Sleep Mode Response without pending
 | |
|  request
 | |
| 
 | |
| Commit 03ed0a52393710be6bdae657d1b36efa146520e5 ('WNM: Ignore WNM-Sleep
 | |
| Mode Response if WNM-Sleep Mode has not been used') started ignoring the
 | |
| response when no WNM-Sleep Mode Request had been used during the
 | |
| association. This can be made tighter by clearing the used flag when
 | |
| successfully processing a response. This adds an additional layer of
 | |
| protection against unexpected retransmissions of the response frame.
 | |
| 
 | |
| Signed-off-by: Jouni Malinen <j@w1.fi>
 | |
| ---
 | |
|  wpa_supplicant/wnm_sta.c | 4 +++-
 | |
|  1 file changed, 3 insertions(+), 1 deletion(-)
 | |
| 
 | |
| diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
 | |
| index 1b3409c..67a07ff 100644
 | |
| --- a/wpa_supplicant/wnm_sta.c
 | |
| +++ b/wpa_supplicant/wnm_sta.c
 | |
| @@ -260,7 +260,7 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s,
 | |
|  
 | |
|  	if (!wpa_s->wnmsleep_used) {
 | |
|  		wpa_printf(MSG_DEBUG,
 | |
| -			   "WNM: Ignore WNM-Sleep Mode Response frame since WNM-Sleep Mode has not been used in this association");
 | |
| +			   "WNM: Ignore WNM-Sleep Mode Response frame since WNM-Sleep Mode operation has not been requested");
 | |
|  		return;
 | |
|  	}
 | |
|  
 | |
| @@ -299,6 +299,8 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s,
 | |
|  		return;
 | |
|  	}
 | |
|  
 | |
| +	wpa_s->wnmsleep_used = 0;
 | |
| +
 | |
|  	if (wnmsleep_ie->status == WNM_STATUS_SLEEP_ACCEPT ||
 | |
|  	    wnmsleep_ie->status == WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) {
 | |
|  		wpa_printf(MSG_DEBUG, "Successfully recv WNM-Sleep Response "
 | |
| -- 
 | |
| 2.7.4
 | |
| 
 | |
| https://w1.fi/security/2017-1/wpa-packet-number-reuse-with-replayed-messages.txt
 | |
| 
 | |
| Patch copied from upstream:
 | |
| 
 | |
| https://w1.fi/security/2017-1/rebased-v2.6-0008-FT-Do-not-allow-multiple-Reassociation-Response-fram.patch
 | |
| 
 | |
| From b372ab0b7daea719749194dc554b26e6367603f2 Mon Sep 17 00:00:00 2001
 | |
| From: Jouni Malinen <j@w1.fi>
 | |
| Date: Fri, 22 Sep 2017 12:06:37 +0300
 | |
| Subject: [PATCH 8/8] FT: Do not allow multiple Reassociation Response frames
 | |
| 
 | |
| 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.
 | |
| 
 | |
| Signed-off-by: Jouni Malinen <j@w1.fi>
 | |
| ---
 | |
|  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 0550a41..2a53c6f 100644
 | |
| --- a/src/rsn_supp/wpa.c
 | |
| +++ b/src/rsn_supp/wpa.c
 | |
| @@ -2440,6 +2440,9 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm)
 | |
|  #ifdef CONFIG_TDLS
 | |
|  	wpa_tdls_disassoc(sm);
 | |
|  #endif /* CONFIG_TDLS */
 | |
| +#ifdef CONFIG_IEEE80211R
 | |
| +	sm->ft_reassoc_completed = 0;
 | |
| +#endif /* CONFIG_IEEE80211R */
 | |
|  
 | |
|  	/* Keys are not needed in the WPA state machine anymore */
 | |
|  	wpa_sm_drop_sa(sm);
 | |
| diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
 | |
| index 205793e..d45bb45 100644
 | |
| --- a/src/rsn_supp/wpa_ft.c
 | |
| +++ b/src/rsn_supp/wpa_ft.c
 | |
| @@ -153,6 +153,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;
 | |
| @@ -681,6 +682,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;
 | |
| @@ -781,6 +787,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 41f371f..56f88dc 100644
 | |
| --- a/src/rsn_supp/wpa_i.h
 | |
| +++ b/src/rsn_supp/wpa_i.h
 | |
| @@ -128,6 +128,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;
 | |
| -- 
 | |
| 2.7.4
 | |
| 
 |