GTK msg 1/2 fields possibly incorrect

Jouni Malinen j at
Sun Feb 5 04:03:13 PST 2017

On Tue, Jan 31, 2017 at 02:20:34AM +0100, Andrew Zaborowski wrote:
> i'm receiving a GTK-handshake msg 1/2 after an FT roam which our code
> can't validate.  This is confirmed by hostapd code in
> SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) in src/ap/wpa_auth.c.  The
> comment says hostap sends the following msg 1/2:
> EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN])
> I couldn't firgure out what sm->Pair is exactly but with FT it's going
> to be false, unlike after an EAPOL 4-Way handshake and the install bit
> will be true in effect.  Is there any reason the install bit isn't
> just hardcoded to 0, as defined by 11.6.2 and illustrated by the
> message sequences in 11.6.7?

sm->Pair is actually supposed to be hardcoded to TRUE and it is just
because of the FT protocol (and FILS authentication) case having a
mechanism to skip proper state machine initialization which resulted in
this not getting set.. The !Pair case is somewhat of a theoretical one
here currently, but based on the standard, this should be used for RSN
IBSS in one direction.

I'll do following to fix the Install bit in group key handshake during
an association started with FT protocol or FILS authentication:

diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 66b2d50..0bd901f 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -615,6 +615,7 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
 				"start 4-way handshake");
 		/* Go to PTKINITDONE state to allow GTK rekeying */
 		sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
+		sm->Pair = TRUE;
 		return 0;
 #endif /* CONFIG_IEEE80211R_AP */
@@ -625,6 +626,7 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
 				"FILS authentication already completed - do not start 4-way handshake");
 		/* Go to PTKINITDONE state to allow GTK rekeying */
 		sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
+		sm->Pair = TRUE;
 		return 0;
 #endif /* CONFIG_FILS */

> Similarly it seems the nonce should just be 0 since it's neither
> ANonce or SNonce, and Key Length should be hardcoded to 0 in
> __wpa_send_eapol.  Patch for illustration.

The standard looks a bit ambiguous on the Key Nonce field.. The example
group handshake figure and the Authenticator state machine figures
describe the Send EAPOL operation as using GNonce as the nonce value
while the subclauses listing the field values for EAPOL-Key messages
show 0. The hostapd implementation followed the Authenticator state
machine description. That said, there is no use for GNonce on the
Supplicant side, so I'll clear it to zero with this:

 		       (wpa_mic_len(sm->wpa_key_mgmt) ? WPA_KEY_INFO_MIC : 0) |
 		       WPA_KEY_INFO_ACK |
 		       (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
-		       rsc, gsm->GNonce, kde, kde_len, gsm->GN, 1);
+		       rsc, NULL, kde, kde_len, gsm->GN, 1);

The Key Length field has a bit more complex story.. P802.11i/D3.0
defines that field as having value 16 for EAPOL-Key group message 1/2.
That behavior needs to be maintained for WPA interoperability. That
said, it looks like it would be fine to clear this to 0 for WPA2 (RSN)
cases and hopefully that does not cause any new interop issues.. I'm
planning on doing this to address that:

@@ -1482,9 +1484,11 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
 	WPA_PUT_BE16(key->key_info, key_info);
 	alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group;
-	WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
-	if (key_info & WPA_KEY_INFO_SMK_MESSAGE)
+	if ((key_info & WPA_KEY_INFO_SMK_MESSAGE) ||
+	    (sm->wpa == WPA_VERSION_WPA2 && !pairwise))
 		WPA_PUT_BE16(key->key_length, 0);
+	else
+		WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
 	/* FIX: STSL: what to use as key_replay_counter? */
 	for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {

Jouni Malinen                                            PGP id EFC895FA

More information about the Hostap mailing list