cozybit / wpa_s_mesh_android

Other
2 stars 1 forks source link

Invalid authentication frames #7

Closed jcard0na closed 10 years ago

jcard0na commented 10 years ago

The attached screenshot shows an invalid mesh authentication frame. That particular capture has two invalid frames, followed by 2 valid authentication commits (auth_seq == 1) and finally 2 valid authentication confirms (auth_seq == 2).

  1. Mesh management frames have TA == BSSID (Per section 8.3.3.1 (a)(4)(iv) of the standard: "If the STA is a mesh STA, the Address 3 field is the TA"
  2. The function mesh_rsn_send_auth() generates this type of invalid frames because the code that constructs the header reads as:

       os_memcpy(auth->da, dst, ETH_ALEN);
       os_memcpy(auth->sa, src, ETH_ALEN);
       os_memcpy(auth->bssid, dst, ETH_ALEN);   # should be src instead of dst
  3. Also, the other place where we could be sending SAE authentication frames is in send_auth_reply(). In fact, that would result in the same swapped address pattern that we see. But this function would only be called in response to an authentication frame, and the invalid frames we observed are the first authentication frames in the capture... Still, that theory can be quickly discarded by checking if that function is ever called with auth_transaction == 1

screenshot from 2014-03-19 10 57 49

jcard0na commented 10 years ago

Yep, confirmed that the invalid frame is sent by send_auth_reply():

wpas_mesh_secure.log0: authentication reply: STA=02:00:00:00:01:00 auth_alg=3 \
    auth_transaction=1 resp=0 (IE len=98)

The IE length also matches the length of the variable section of the observed invalid framed.

Now the theory:

  1. The order of the frames in wireshark is wrong: what we see is two instances of:

      A ---- commit                                            ---> B
      B  ----- commit response (invalid format) ----> A   (not ignored?)
      A  ----- confirm                                          ----> B

    It could be that the fact that the BSSID is incorrect goes unnoticed by wpa_supplicant and the transaction can proceed. And we see two transactions because of each station detects each other independently.

In fact, we do see two Pairwise Master Keys being generated by each station. Only the second key matches both stations:

 grep 'SAE: PMK -' *
wpas_mesh_secure.log0:1395248558.102041: SAE: PMK - hexdump(len=32): cc 8e 94 4f c7 a5 e7 8b d6 55 44 17 19 82 9c 5f 74 d9 e2 e2 fe 9e 33 de c7 95 1c bb 50 88 0d 0c
wpas_mesh_secure.log0:1395248558.103553: SAE: PMK - hexdump(len=32): d1 62 4e 24 74 a2 13 22 f9 59 13 c0 c1 e3 af 65 a0 69 fc 24 70 c4 5f b5 17 70 40 05 ff 41 9a d4
wpas_mesh_secure.log1:1395248558.102004: SAE: PMK - hexdump(len=32): 19 cc 70 08 da 93 cb 4e 1d d0 19 9f 71 0a 33 a1 fe f2 e3 7e 9d 44 70 fe 9d 64 57 f1 e3 e2 6c 4a
wpas_mesh_secure.log1:1395248558.103645: SAE: PMK - hexdump(len=32): d1 62 4e 24 74 a2 13 22 f9 59 13 c0 c1 e3 af 65 a0 69 fc 24 70 c4 5f b5 17 70 40 05 ff 41 9a d4

So, action items:

  1. Fix the frame format of the SAE response and confirm we still see 6 frames.
  2. Disable auto_peer on one of the stations and observe that the authentication completes in just 3 frames.
jcard0na commented 10 years ago

A fix for the frame format issue could be something like:

diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index eb699ce..fef9dd7 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -251,7 +251,12 @@ static void send_auth_reply(struct hostapd_data *hapd,
                                            WLAN_FC_STYPE_AUTH);
        os_memcpy(reply->da, dst, ETH_ALEN);
        os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
-       os_memcpy(reply->bssid, bssid, ETH_ALEN);
+
+       /* Per IEEE Std802.11 Sec 8.3.3.1, mesh frames have TA in address 3 */
+       if (hapd->conf->mesh & MESH_ENABLED)
+               os_memcpy(reply->bssid, reply->sa, ETH_ALEN);
+       else
+               os_memcpy(reply->bssid, bssid, ETH_ALEN);

        reply->u.auth.auth_alg = host_to_le16(auth_alg);
        reply->u.auth.auth_transaction = host_to_le16(auth_transaction);

And somewhere else we should be checking that all mesh mgmt frames have Address 2 == Address 3.

jcard0na commented 10 years ago

Fixed by d007d9514ac554ae4448cabe54bdcfd5fbb9be13