untrusted comment: signature from openbsd 6.0 base secret key
RWSho3oKSqgLQ23A0xOCp400PktTZDUBix4+WeFGbvgFpT0syqTQuVCngviXTDrfBjkHEtJf4NmhIhDL44A9T2UnLSaoMOVPyAc=

OpenBSD 6.0 errata 18, Mar 1, 2017:

WiFi clients using WPA1 or WPA2 are vulnerable to a man-in-the-middle attack
by rouge access points.

This is version 2 of the patch file.

Apply by doing:
    signify -Vep /etc/signify/openbsd-60-base.pub -x 018_net80211.patch.sig \
        -m - | (cd /usr/src && patch -p0)

And then rebuild and install a new kernel:
    cd /usr/src/sys/arch/`machine`/conf
    KK=`sysctl -n kern.osversion | cut -d# -f1`
    config $KK
    cd ../compile/$KK
    make
    make install

Index: sys/net80211/ieee80211_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.178
diff -u -p -r1.178 ieee80211_input.c
--- sys/net80211/ieee80211_input.c	18 May 2016 08:15:28 -0000	1.178
+++ sys/net80211/ieee80211_input.c	1 Mar 2017 18:24:55 -0000
@@ -2299,6 +2299,7 @@ ieee80211_recv_assoc_resp(struct ieee802
 	 */
 	if (ic->ic_flags & IEEE80211_F_RSNON) {
 		/* XXX ic->ic_mgt_timer = 5; */
+		ni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
 	} else if (ic->ic_flags & IEEE80211_F_WEPON)
 		ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
 
Index: sys/net80211/ieee80211_node.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_node.h,v
retrieving revision 1.60
diff -u -p -r1.60 ieee80211_node.h
--- sys/net80211/ieee80211_node.h	28 Apr 2016 08:18:10 -0000	1.60
+++ sys/net80211/ieee80211_node.h	1 Mar 2017 18:24:55 -0000
@@ -99,6 +99,14 @@ enum {
 	RSNA_KEYERROR
 };
 
+/* Supplicant state machine: 4-Way Handshake (not documented in standard) */
+enum {
+	RSNA_SUPP_INITIALIZE,		/* not expecting any messages */
+	RSNA_SUPP_PTKSTART,		/* awaiting handshake message 1 */
+	RSNA_SUPP_PTKNEGOTIATING,	/* got message 1 and derived PTK */
+	RNSA_SUPP_PTKDONE		/* got message 3 and authenticated AP */
+};
+
 struct ieee80211_rxinfo {
 	u_int32_t		rxi_flags;
 	u_int32_t		rxi_tstamp;
@@ -205,6 +213,7 @@ struct ieee80211_node {
 	/* RSN */
 	struct timeout		ni_eapol_to;
 	u_int			ni_rsn_state;
+	u_int			ni_rsn_supp_state;
 	u_int			ni_rsn_gstate;
 	u_int			ni_rsn_retries;
 	u_int			ni_rsnprotos;
Index: sys/net80211/ieee80211_pae_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_pae_input.c,v
retrieving revision 1.25
diff -u -p -r1.25 ieee80211_pae_input.c
--- sys/net80211/ieee80211_pae_input.c	15 Jul 2015 22:16:42 -0000	1.25
+++ sys/net80211/ieee80211_pae_input.c	2 Mar 2017 09:00:08 -0000
@@ -193,6 +193,15 @@ ieee80211_recv_4way_msg1(struct ieee8021
 	    ic->ic_opmode != IEEE80211_M_IBSS)
 		return;
 #endif
+	/* 
+	 * Message 1 is always expected while RSN is active since some
+	 * APs will rekey the PTK by sending Msg1/4 after some time.
+	 */
+	if (ni->ni_rsn_supp_state == RSNA_SUPP_INITIALIZE) {
+		DPRINTF(("unexpected in state: %d\n", ni->ni_rsn_supp_state));
+		return;
+	}
+	/* enforce monotonicity of key request replay counter */
 	if (ni->ni_replaycnt_ok &&
 	    BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {
 		ic->ic_stats.is_rx_eapol_replay++;
@@ -343,6 +352,13 @@ ieee80211_recv_4way_msg3(struct ieee8021
 	    ic->ic_opmode != IEEE80211_M_IBSS)
 		return;
 #endif
+	/* discard if we're not expecting this message */
+	if (ni->ni_rsn_supp_state != RSNA_SUPP_PTKNEGOTIATING &&
+	    ni->ni_rsn_supp_state != RNSA_SUPP_PTKDONE) {
+		DPRINTF(("unexpected in state: %d\n", ni->ni_rsn_supp_state));
+		return;
+	}
+	/* enforce monotonicity of key request replay counter */
 	if (ni->ni_replaycnt_ok &&
 	    BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {
 		ic->ic_stats.is_rx_eapol_replay++;
@@ -737,6 +753,12 @@ ieee80211_recv_rsn_group_msg1(struct iee
 	    ic->ic_opmode != IEEE80211_M_IBSS)
 		return;
 #endif
+	/* discard if we're not expecting this message */
+	if (ni->ni_rsn_supp_state != RNSA_SUPP_PTKDONE) {
+		DPRINTF(("unexpected in state: %d\n", ni->ni_rsn_supp_state));
+		return;
+	}
+	/* enforce monotonicity of key request replay counter */
 	if (BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {
 		ic->ic_stats.is_rx_eapol_replay++;
 		return;
@@ -883,6 +905,12 @@ ieee80211_recv_wpa_group_msg1(struct iee
 	    ic->ic_opmode != IEEE80211_M_IBSS)
 		return;
 #endif
+	/* discard if we're not expecting this message */
+	if (ni->ni_rsn_supp_state != RNSA_SUPP_PTKDONE) {
+		DPRINTF(("unexpected in state: %d\n", ni->ni_rsn_supp_state));
+		return;
+	}
+	/* enforce monotonicity of key request replay counter */
 	if (BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {
 		ic->ic_stats.is_rx_eapol_replay++;
 		return;
@@ -975,6 +1003,7 @@ ieee80211_recv_group_msg2(struct ieee802
 		     ni->ni_rsn_gstate));
 		return;
 	}
+	/* enforce monotonicity of key request replay counter */
 	if (BE_READ_8(key->replaycnt) != ni->ni_replaycnt) {
 		ic->ic_stats.is_rx_eapol_replay++;
 		return;
@@ -1019,6 +1048,11 @@ ieee80211_recv_eapol_key_req(struct ieee
 	    ic->ic_opmode != IEEE80211_M_IBSS)
 		return;
 
+	/* discard if we're not expecting this message */
+	if (ni->ni_rsn_state != RSNA_PTKINITDONE) {
+		DPRINTF(("unexpected in state: %d\n", ni->ni_rsn_state));
+		return;
+	}
 	/* enforce monotonicity of key request replay counter */
 	if (ni->ni_reqreplaycnt_ok &&
 	    BE_READ_8(key->replaycnt) <= ni->ni_reqreplaycnt) {
Index: sys/net80211/ieee80211_pae_output.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_pae_output.c,v
retrieving revision 1.27
diff -u -p -r1.27 ieee80211_pae_output.c
--- sys/net80211/ieee80211_pae_output.c	12 Apr 2016 14:33:27 -0000	1.27
+++ sys/net80211/ieee80211_pae_output.c	1 Mar 2017 18:24:55 -0000
@@ -310,6 +310,7 @@ ieee80211_send_4way_msg2(struct ieee8021
 	u_int16_t info;
 	u_int8_t *frm;
 
+	ni->ni_rsn_supp_state = RSNA_SUPP_PTKNEGOTIATING;
 	m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
 	    (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) ?
 		2 + IEEE80211_WPAIE_MAXLEN :
@@ -438,6 +439,7 @@ ieee80211_send_4way_msg4(struct ieee8021
 	struct mbuf *m;
 	u_int16_t info;
 
+	ni->ni_rsn_supp_state = RNSA_SUPP_PTKDONE;
 	m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
 	if (m == NULL)
 		return ENOMEM;
Index: sys/net80211/ieee80211_proto.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_proto.c,v
retrieving revision 1.68
diff -u -p -r1.68 ieee80211_proto.c
--- sys/net80211/ieee80211_proto.c	20 Jul 2016 15:40:27 -0000	1.68
+++ sys/net80211/ieee80211_proto.c	2 Mar 2017 08:57:50 -0000
@@ -358,8 +358,8 @@ ieee80211_set_shortslottime(struct ieee8
 int
 ieee80211_keyrun(struct ieee80211com *ic, u_int8_t *macaddr)
 {
+	struct ieee80211_node *ni = ic->ic_bss;
 #ifndef IEEE80211_STA_ONLY
-	struct ieee80211_node *ni;
 	struct ieee80211_pmk *pmk;
 #endif
 
@@ -368,6 +368,7 @@ ieee80211_keyrun(struct ieee80211com *ic
 	    !(ic->ic_flags & IEEE80211_F_RSNON))
 		return ENETDOWN;
 
+	ni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
 #ifndef IEEE80211_STA_ONLY
 	if (ic->ic_opmode == IEEE80211_M_STA)
 #endif
@@ -732,6 +733,10 @@ ieee80211_auth_open(struct ieee80211com 
 		}
 		ieee80211_new_state(ic, IEEE80211_S_AUTH,
 		    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
+
+		/* In IBSS mode no (re)association frames are sent. */
+		if (ic->ic_flags & IEEE80211_F_RSNON)
+			ni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
 		break;
 
 	case IEEE80211_M_AHDEMO:
@@ -898,6 +903,7 @@ justcleanup:
 			ieee80211_free_allnodes(ic);
 			break;
 		}
+		ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
 		break;
 	case IEEE80211_S_SCAN:
 		ic->ic_flags &= ~IEEE80211_F_SIBSS;
@@ -908,6 +914,7 @@ justcleanup:
 			ieee80211_chan2mode(ic, ni->ni_chan)];
 		ni->ni_associd = 0;
 		ni->ni_rstamp = 0;
+		ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
 		switch (ostate) {
 		case IEEE80211_S_INIT:
 #ifndef IEEE80211_STA_ONLY
@@ -950,6 +957,7 @@ justcleanup:
 		}
 		break;
 	case IEEE80211_S_AUTH:
+		ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
 		switch (ostate) {
 		case IEEE80211_S_INIT:
 			DPRINTF(("invalid transition\n"));