P2P: Clone dtim_period to a new interface
[mech_eap.git] / wlantest / rx_eapol.c
1 /*
2  * Received Data frame processing for EAPOL messages
3  * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "utils/includes.h"
10
11 #include "utils/common.h"
12 #include "crypto/aes_wrap.h"
13 #include "crypto/crypto.h"
14 #include "common/defs.h"
15 #include "common/ieee802_11_defs.h"
16 #include "common/ieee802_11_common.h"
17 #include "common/eapol_common.h"
18 #include "common/wpa_common.h"
19 #include "rsn_supp/wpa_ie.h"
20 #include "wlantest.h"
21
22
23 static int is_zero(const u8 *buf, size_t len)
24 {
25         size_t i;
26         for (i = 0; i < len; i++) {
27                 if (buf[i])
28                         return 0;
29         }
30         return 1;
31 }
32
33
34 static int check_mic(const u8 *kck, int ver, const u8 *data, size_t len)
35 {
36         u8 *buf;
37         int ret = -1;
38         struct ieee802_1x_hdr *hdr;
39         struct wpa_eapol_key *key;
40         u8 rx_mic[16];
41
42         buf = os_malloc(len);
43         if (buf == NULL)
44                 return -1;
45         os_memcpy(buf, data, len);
46         hdr = (struct ieee802_1x_hdr *) buf;
47         key = (struct wpa_eapol_key *) (hdr + 1);
48
49         os_memcpy(rx_mic, key->key_mic, 16);
50         os_memset(key->key_mic, 0, 16);
51
52         if (wpa_eapol_key_mic(kck, ver, buf, len, key->key_mic) == 0 &&
53             os_memcmp(rx_mic, key->key_mic, 16) == 0)
54                 ret = 0;
55
56         os_free(buf);
57
58         return ret;
59 }
60
61
62 static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst,
63                                      const u8 *src, const u8 *data, size_t len)
64 {
65         struct wlantest_bss *bss;
66         struct wlantest_sta *sta;
67         const struct ieee802_1x_hdr *eapol;
68         const struct wpa_eapol_key *hdr;
69
70         wpa_printf(MSG_DEBUG, "EAPOL-Key 1/4 " MACSTR " -> " MACSTR,
71                    MAC2STR(src), MAC2STR(dst));
72         bss = bss_get(wt, src);
73         if (bss == NULL)
74                 return;
75         sta = sta_get(bss, dst);
76         if (sta == NULL)
77                 return;
78
79         eapol = (const struct ieee802_1x_hdr *) data;
80         hdr = (const struct wpa_eapol_key *) (eapol + 1);
81         if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) {
82                 add_note(wt, MSG_INFO, "EAPOL-Key 1/4 from " MACSTR
83                          " used zero nonce", MAC2STR(src));
84         }
85         if (!is_zero(hdr->key_rsc, 8)) {
86                 add_note(wt, MSG_INFO, "EAPOL-Key 1/4 from " MACSTR
87                          " used non-zero Key RSC", MAC2STR(src));
88         }
89         os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
90 }
91
92
93 static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
94                    struct wlantest_sta *sta, u16 ver,
95                    const u8 *data, size_t len,
96                    struct wlantest_pmk *pmk)
97 {
98         struct wpa_ptk ptk;
99         size_t ptk_len = sta->pairwise_cipher == WPA_CIPHER_TKIP ? 64 : 48;
100         wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk),
101                        "Pairwise key expansion",
102                        bss->bssid, sta->addr, sta->anonce, sta->snonce,
103                        (u8 *) &ptk, ptk_len,
104                        wpa_key_mgmt_sha256(sta->key_mgmt));
105         if (check_mic(ptk.kck, ver, data, len) < 0)
106                 return -1;
107
108         wpa_printf(MSG_INFO, "Derived PTK for STA " MACSTR " BSSID " MACSTR,
109                    MAC2STR(sta->addr), MAC2STR(bss->bssid));
110         sta->counters[WLANTEST_STA_COUNTER_PTK_LEARNED]++;
111         if (sta->ptk_set) {
112                 /*
113                  * Rekeying - use new PTK for EAPOL-Key frames, but continue
114                  * using the old PTK for frame decryption.
115                  */
116                 add_note(wt, MSG_DEBUG, "Derived PTK during rekeying");
117                 os_memcpy(&sta->tptk, &ptk, sizeof(ptk));
118                 wpa_hexdump(MSG_DEBUG, "TPTK:KCK", sta->tptk.kck, 16);
119                 wpa_hexdump(MSG_DEBUG, "TPTK:KEK", sta->tptk.kek, 16);
120                 wpa_hexdump(MSG_DEBUG, "TPTK:TK1", sta->tptk.tk1, 16);
121                 if (ptk_len > 48)
122                         wpa_hexdump(MSG_DEBUG, "TPTK:TK2", sta->tptk.u.tk2,
123                                     16);
124                 sta->tptk_set = 1;
125                 return 0;
126         }
127         add_note(wt, MSG_DEBUG, "Derived new PTK");
128         os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
129         wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16);
130         wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16);
131         wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16);
132         if (ptk_len > 48)
133                 wpa_hexdump(MSG_DEBUG, "PTK:TK2", sta->ptk.u.tk2, 16);
134         sta->ptk_set = 1;
135         os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
136         os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
137         return 0;
138 }
139
140
141 static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss,
142                        struct wlantest_sta *sta, u16 ver,
143                        const u8 *data, size_t len)
144 {
145         struct wlantest_pmk *pmk;
146
147         wpa_printf(MSG_DEBUG, "Trying to derive PTK for " MACSTR,
148                    MAC2STR(sta->addr));
149         dl_list_for_each(pmk, &bss->pmk, struct wlantest_pmk, list) {
150                 wpa_printf(MSG_DEBUG, "Try per-BSS PMK");
151                 if (try_pmk(wt, bss, sta, ver, data, len, pmk) == 0)
152                         return;
153         }
154
155         dl_list_for_each(pmk, &wt->pmk, struct wlantest_pmk, list) {
156                 wpa_printf(MSG_DEBUG, "Try global PMK");
157                 if (try_pmk(wt, bss, sta, ver, data, len, pmk) == 0)
158                         return;
159         }
160
161         if (!sta->ptk_set) {
162                 struct wlantest_ptk *ptk;
163                 int prev_level = wpa_debug_level;
164
165                 wpa_debug_level = MSG_WARNING;
166                 dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
167                         if (check_mic(ptk->ptk.kck, ver, data, len) < 0)
168                                 continue;
169                         wpa_printf(MSG_INFO, "Pre-set PTK matches for STA "
170                                    MACSTR " BSSID " MACSTR,
171                                    MAC2STR(sta->addr), MAC2STR(bss->bssid));
172                         add_note(wt, MSG_DEBUG, "Using pre-set PTK");
173                         os_memcpy(&sta->ptk, &ptk->ptk, sizeof(ptk->ptk));
174                         wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16);
175                         wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16);
176                         wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16);
177                         if (ptk->ptk_len > 48)
178                                 wpa_hexdump(MSG_DEBUG, "PTK:TK2",
179                                             sta->ptk.u.tk2, 16);
180                         sta->ptk_set = 1;
181                         os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
182                         os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
183                 }
184                 wpa_debug_level = prev_level;
185         }
186
187         add_note(wt, MSG_DEBUG, "No matching PMK found to derive PTK");
188 }
189
190
191 static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
192                                      const u8 *src, const u8 *data, size_t len)
193 {
194         struct wlantest_bss *bss;
195         struct wlantest_sta *sta;
196         const struct ieee802_1x_hdr *eapol;
197         const struct wpa_eapol_key *hdr;
198         const u8 *key_data, *kck;
199         u16 key_info, key_data_len;
200         struct wpa_eapol_ie_parse ie;
201
202         wpa_printf(MSG_DEBUG, "EAPOL-Key 2/4 " MACSTR " -> " MACSTR,
203                    MAC2STR(src), MAC2STR(dst));
204         bss = bss_get(wt, dst);
205         if (bss == NULL)
206                 return;
207         sta = sta_get(bss, src);
208         if (sta == NULL)
209                 return;
210
211         eapol = (const struct ieee802_1x_hdr *) data;
212         hdr = (const struct wpa_eapol_key *) (eapol + 1);
213         if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) {
214                 add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR
215                          " used zero nonce", MAC2STR(src));
216         }
217         if (!is_zero(hdr->key_rsc, 8)) {
218                 add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR
219                          " used non-zero Key RSC", MAC2STR(src));
220         }
221         os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN);
222         key_info = WPA_GET_BE16(hdr->key_info);
223         key_data_len = WPA_GET_BE16(hdr->key_data_length);
224         derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len);
225
226         if (!sta->ptk_set && !sta->tptk_set) {
227                 add_note(wt, MSG_DEBUG,
228                          "No PTK known to process EAPOL-Key 2/4");
229                 return;
230         }
231
232         kck = sta->ptk.kck;
233         if (sta->tptk_set) {
234                 add_note(wt, MSG_DEBUG,
235                          "Use TPTK for validation EAPOL-Key MIC");
236                 kck = sta->tptk.kck;
237         }
238         if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
239                 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC");
240                 return;
241         }
242         add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/4");
243
244         key_data = (const u8 *) (hdr + 1);
245
246         if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) {
247                 add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
248                 return;
249         }
250
251         if (ie.wpa_ie) {
252                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - WPA IE",
253                             ie.wpa_ie, ie.wpa_ie_len);
254                 if (os_memcmp(ie.wpa_ie, sta->rsnie, ie.wpa_ie_len) != 0) {
255                         struct ieee802_11_elems elems;
256                         add_note(wt, MSG_INFO,
257                                  "Mismatch in WPA IE between EAPOL-Key 2/4 "
258                                  "and (Re)Association Request from " MACSTR,
259                                  MAC2STR(sta->addr));
260                         wpa_hexdump(MSG_INFO, "WPA IE in EAPOL-Key",
261                                     ie.wpa_ie, ie.wpa_ie_len);
262                         wpa_hexdump(MSG_INFO, "WPA IE in (Re)Association "
263                                     "Request",
264                                     sta->rsnie,
265                                     sta->rsnie[0] ? 2 + sta->rsnie[1] : 0);
266                         /*
267                          * The sniffer may have missed (Re)Association
268                          * Request, so try to survive with the information from
269                          * EAPOL-Key.
270                          */
271                         os_memset(&elems, 0, sizeof(elems));
272                         elems.wpa_ie = ie.wpa_ie + 2;
273                         elems.wpa_ie_len = ie.wpa_ie_len - 2;
274                         wpa_printf(MSG_DEBUG, "Update STA data based on WPA "
275                                    "IE in EAPOL-Key 2/4");
276                         sta_update_assoc(sta, &elems);
277                 }
278         }
279
280         if (ie.rsn_ie) {
281                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - RSN IE",
282                             ie.rsn_ie, ie.rsn_ie_len);
283                 if (os_memcmp(ie.rsn_ie, sta->rsnie, ie.rsn_ie_len) != 0) {
284                         struct ieee802_11_elems elems;
285                         add_note(wt, MSG_INFO,
286                                  "Mismatch in RSN IE between EAPOL-Key 2/4 "
287                                  "and (Re)Association Request from " MACSTR,
288                                  MAC2STR(sta->addr));
289                         wpa_hexdump(MSG_INFO, "RSN IE in EAPOL-Key",
290                                     ie.rsn_ie, ie.rsn_ie_len);
291                         wpa_hexdump(MSG_INFO, "RSN IE in (Re)Association "
292                                     "Request",
293                                     sta->rsnie,
294                                     sta->rsnie[0] ? 2 + sta->rsnie[1] : 0);
295                         /*
296                          * The sniffer may have missed (Re)Association
297                          * Request, so try to survive with the information from
298                          * EAPOL-Key.
299                          */
300                         os_memset(&elems, 0, sizeof(elems));
301                         elems.rsn_ie = ie.rsn_ie + 2;
302                         elems.rsn_ie_len = ie.rsn_ie_len - 2;
303                         wpa_printf(MSG_DEBUG, "Update STA data based on RSN "
304                                    "IE in EAPOL-Key 2/4");
305                         sta_update_assoc(sta, &elems);
306                 }
307         }
308 }
309
310
311 static u8 * decrypt_eapol_key_data_rc4(struct wlantest *wt, const u8 *kek,
312                                        const struct wpa_eapol_key *hdr,
313                                        size_t *len)
314 {
315         u8 ek[32], *buf;
316         u16 keydatalen = WPA_GET_BE16(hdr->key_data_length);
317
318         buf = os_malloc(keydatalen);
319         if (buf == NULL)
320                 return NULL;
321
322         os_memcpy(ek, hdr->key_iv, 16);
323         os_memcpy(ek + 16, kek, 16);
324         os_memcpy(buf, hdr + 1, keydatalen);
325         if (rc4_skip(ek, 32, 256, buf, keydatalen)) {
326                 add_note(wt, MSG_INFO, "RC4 failed");
327                 os_free(buf);
328                 return NULL;
329         }
330
331         *len = keydatalen;
332         return buf;
333 }
334
335
336 static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek,
337                                        const struct wpa_eapol_key *hdr,
338                                        size_t *len)
339 {
340         u8 *buf;
341         u16 keydatalen = WPA_GET_BE16(hdr->key_data_length);
342
343         if (keydatalen % 8) {
344                 add_note(wt, MSG_INFO, "Unsupported AES-WRAP len %d",
345                          keydatalen);
346                 return NULL;
347         }
348         keydatalen -= 8; /* AES-WRAP adds 8 bytes */
349         buf = os_malloc(keydatalen);
350         if (buf == NULL)
351                 return NULL;
352         if (aes_unwrap(kek, keydatalen / 8, (u8 *) (hdr + 1), buf)) {
353                 os_free(buf);
354                 add_note(wt, MSG_INFO,
355                          "AES unwrap failed - could not decrypt EAPOL-Key "
356                          "key data");
357                 return NULL;
358         }
359
360         *len = keydatalen;
361         return buf;
362 }
363
364
365 static u8 * decrypt_eapol_key_data(struct wlantest *wt, const u8 *kek, u16 ver,
366                                    const struct wpa_eapol_key *hdr,
367                                    size_t *len)
368 {
369         switch (ver) {
370         case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
371                 return decrypt_eapol_key_data_rc4(wt, kek, hdr, len);
372         case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
373         case WPA_KEY_INFO_TYPE_AES_128_CMAC:
374                 return decrypt_eapol_key_data_aes(wt, kek, hdr, len);
375         default:
376                 add_note(wt, MSG_INFO,
377                          "Unsupported EAPOL-Key Key Descriptor Version %u",
378                          ver);
379                 return NULL;
380         }
381 }
382
383
384 static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss,
385                            struct wlantest_sta *sta,
386                            const u8 *buf, size_t len, const u8 *rsc)
387 {
388         struct wpa_eapol_ie_parse ie;
389
390         if (wpa_supplicant_parse_ies(buf, len, &ie) < 0) {
391                 add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
392                 return;
393         }
394
395         if (ie.wpa_ie) {
396                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - WPA IE",
397                             ie.wpa_ie, ie.wpa_ie_len);
398         }
399
400         if (ie.rsn_ie) {
401                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - RSN IE",
402                             ie.rsn_ie, ie.rsn_ie_len);
403         }
404
405         if (ie.gtk) {
406                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - GTK KDE",
407                             ie.gtk, ie.gtk_len);
408                 if (ie.gtk_len >= 2 && ie.gtk_len <= 2 + 32) {
409                         int id;
410                         id = ie.gtk[0] & 0x03;
411                         add_note(wt, MSG_DEBUG, "GTK KeyID=%u tx=%u",
412                                  id, !!(ie.gtk[0] & 0x04));
413                         if ((ie.gtk[0] & 0xf8) || ie.gtk[1]) {
414                                 add_note(wt, MSG_INFO,
415                                          "GTK KDE: Reserved field set: "
416                                          "%02x %02x", ie.gtk[0], ie.gtk[1]);
417                         }
418                         wpa_hexdump(MSG_DEBUG, "GTK", ie.gtk + 2,
419                                     ie.gtk_len - 2);
420                         bss->gtk_len[id] = ie.gtk_len - 2;
421                         sta->gtk_len = ie.gtk_len - 2;
422                         os_memcpy(bss->gtk[id], ie.gtk + 2, ie.gtk_len - 2);
423                         os_memcpy(sta->gtk, ie.gtk + 2, ie.gtk_len - 2);
424                         bss->rsc[id][0] = rsc[5];
425                         bss->rsc[id][1] = rsc[4];
426                         bss->rsc[id][2] = rsc[3];
427                         bss->rsc[id][3] = rsc[2];
428                         bss->rsc[id][4] = rsc[1];
429                         bss->rsc[id][5] = rsc[0];
430                         bss->gtk_idx = id;
431                         sta->gtk_idx = id;
432                         wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[id], 6);
433                 } else {
434                         add_note(wt, MSG_INFO, "Invalid GTK KDE length %u",
435                                  (unsigned) ie.gtk_len);
436                 }
437         }
438
439         if (ie.igtk) {
440                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - IGTK KDE",
441                             ie.igtk, ie.igtk_len);
442                 if (ie.igtk_len == 24) {
443                         u16 id;
444                         id = WPA_GET_LE16(ie.igtk);
445                         if (id > 5) {
446                                 add_note(wt, MSG_INFO,
447                                          "Unexpected IGTK KeyID %u", id);
448                         } else {
449                                 const u8 *ipn;
450                                 add_note(wt, MSG_DEBUG, "IGTK KeyID %u", id);
451                                 wpa_hexdump(MSG_DEBUG, "IPN", ie.igtk + 2, 6);
452                                 wpa_hexdump(MSG_DEBUG, "IGTK", ie.igtk + 8,
453                                             16);
454                                 os_memcpy(bss->igtk[id], ie.igtk + 8, 16);
455                                 bss->igtk_set[id] = 1;
456                                 ipn = ie.igtk + 2;
457                                 bss->ipn[id][0] = ipn[5];
458                                 bss->ipn[id][1] = ipn[4];
459                                 bss->ipn[id][2] = ipn[3];
460                                 bss->ipn[id][3] = ipn[2];
461                                 bss->ipn[id][4] = ipn[1];
462                                 bss->ipn[id][5] = ipn[0];
463                                 bss->igtk_idx = id;
464                         }
465                 } else {
466                         add_note(wt, MSG_INFO, "Invalid IGTK KDE length %u",
467                                  (unsigned) ie.igtk_len);
468                 }
469         }
470 }
471
472
473 static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
474                                      const u8 *src, const u8 *data, size_t len)
475 {
476         struct wlantest_bss *bss;
477         struct wlantest_sta *sta;
478         const struct ieee802_1x_hdr *eapol;
479         const struct wpa_eapol_key *hdr;
480         const u8 *key_data, *kck, *kek;
481         int recalc = 0;
482         u16 key_info, ver;
483         u8 *decrypted_buf = NULL;
484         const u8 *decrypted;
485         size_t decrypted_len = 0;
486         struct wpa_eapol_ie_parse ie;
487
488         wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR,
489                    MAC2STR(src), MAC2STR(dst));
490         bss = bss_get(wt, src);
491         if (bss == NULL)
492                 return;
493         sta = sta_get(bss, dst);
494         if (sta == NULL)
495                 return;
496
497         eapol = (const struct ieee802_1x_hdr *) data;
498         hdr = (const struct wpa_eapol_key *) (eapol + 1);
499         key_info = WPA_GET_BE16(hdr->key_info);
500
501         if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) {
502                 add_note(wt, MSG_INFO,
503                          "EAPOL-Key ANonce mismatch between 1/4 and 3/4");
504                 recalc = 1;
505         }
506         os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
507         if (recalc) {
508                 derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK,
509                            data, len);
510         }
511
512         if (!sta->ptk_set && !sta->tptk_set) {
513                 add_note(wt, MSG_DEBUG,
514                          "No PTK known to process EAPOL-Key 3/4");
515                 return;
516         }
517
518         kek = sta->ptk.kek;
519         kck = sta->ptk.kck;
520         if (sta->tptk_set) {
521                 add_note(wt, MSG_DEBUG,
522                          "Use TPTK for validation EAPOL-Key MIC");
523                 kck = sta->tptk.kck;
524                 kek = sta->tptk.kek;
525         }
526         if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
527                 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
528                 return;
529         }
530         add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 3/4");
531
532         key_data = (const u8 *) (hdr + 1);
533         if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
534                 if (sta->proto & WPA_PROTO_RSN)
535                         add_note(wt, MSG_INFO,
536                                  "EAPOL-Key 3/4 without EncrKeyData bit");
537                 decrypted = key_data;
538                 decrypted_len = WPA_GET_BE16(hdr->key_data_length);
539         } else {
540                 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
541                 decrypted_buf = decrypt_eapol_key_data(wt, kek, ver, hdr,
542                                                        &decrypted_len);
543                 if (decrypted_buf == NULL) {
544                         add_note(wt, MSG_INFO,
545                                  "Failed to decrypt EAPOL-Key Key Data");
546                         return;
547                 }
548                 decrypted = decrypted_buf;
549                 wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data",
550                             decrypted, decrypted_len);
551         }
552         if (wt->write_pcap_dumper && decrypted != key_data) {
553                 /* Fill in a dummy Data frame header */
554                 u8 buf[24 + 8 + sizeof(*eapol) + sizeof(*hdr)];
555                 struct ieee80211_hdr *h;
556                 struct wpa_eapol_key *k;
557                 const u8 *p;
558                 u8 *pos;
559                 size_t plain_len;
560
561                 plain_len = decrypted_len;
562                 p = decrypted;
563                 while (p + 1 < decrypted + decrypted_len) {
564                         if (p[0] == 0xdd && p[1] == 0x00) {
565                                 /* Remove padding */
566                                 plain_len = p - decrypted;
567                                 break;
568                         }
569                         p += 2 + p[1];
570                 }
571
572                 os_memset(buf, 0, sizeof(buf));
573                 h = (struct ieee80211_hdr *) buf;
574                 h->frame_control = host_to_le16(0x0208);
575                 os_memcpy(h->addr1, dst, ETH_ALEN);
576                 os_memcpy(h->addr2, src, ETH_ALEN);
577                 os_memcpy(h->addr3, src, ETH_ALEN);
578                 pos = (u8 *) (h + 1);
579                 os_memcpy(pos, "\xaa\xaa\x03\x00\x00\x00\x88\x8e", 8);
580                 pos += 8;
581                 os_memcpy(pos, eapol, sizeof(*eapol));
582                 pos += sizeof(*eapol);
583                 os_memcpy(pos, hdr, sizeof(*hdr));
584                 k = (struct wpa_eapol_key *) pos;
585                 WPA_PUT_BE16(k->key_info,
586                              key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA);
587                 WPA_PUT_BE16(k->key_data_length, plain_len);
588                 write_pcap_decrypted(wt, buf, sizeof(buf),
589                                      decrypted, plain_len);
590         }
591
592         if (wpa_supplicant_parse_ies(decrypted, decrypted_len, &ie) < 0) {
593                 add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
594                 os_free(decrypted_buf);
595                 return;
596         }
597
598         if ((ie.wpa_ie &&
599              os_memcmp(ie.wpa_ie, bss->wpaie, ie.wpa_ie_len) != 0) ||
600             (ie.wpa_ie == NULL && bss->wpaie[0])) {
601                 add_note(wt, MSG_INFO,
602                          "Mismatch in WPA IE between EAPOL-Key 3/4 and "
603                          "Beacon/Probe Response from " MACSTR,
604                          MAC2STR(bss->bssid));
605                 wpa_hexdump(MSG_INFO, "WPA IE in EAPOL-Key",
606                             ie.wpa_ie, ie.wpa_ie_len);
607                 wpa_hexdump(MSG_INFO, "WPA IE in Beacon/Probe "
608                             "Response",
609                             bss->wpaie,
610                             bss->wpaie[0] ? 2 + bss->wpaie[1] : 0);
611         }
612
613         if ((ie.rsn_ie &&
614              os_memcmp(ie.rsn_ie, bss->rsnie, ie.rsn_ie_len) != 0) ||
615             (ie.rsn_ie == NULL && bss->rsnie[0])) {
616                 add_note(wt, MSG_INFO, "Mismatch in RSN IE between EAPOL-Key "
617                          "3/4 and Beacon/Probe Response from " MACSTR,
618                          MAC2STR(bss->bssid));
619                 wpa_hexdump(MSG_INFO, "RSN IE in EAPOL-Key",
620                             ie.rsn_ie, ie.rsn_ie_len);
621                 wpa_hexdump(MSG_INFO, "RSN IE in (Re)Association "
622                             "Request",
623                             bss->rsnie,
624                             bss->rsnie[0] ? 2 + bss->rsnie[1] : 0);
625         }
626
627         learn_kde_keys(wt, bss, sta, decrypted, decrypted_len, hdr->key_rsc);
628         os_free(decrypted_buf);
629 }
630
631
632 static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
633                                      const u8 *src, const u8 *data, size_t len)
634 {
635         struct wlantest_bss *bss;
636         struct wlantest_sta *sta;
637         const struct ieee802_1x_hdr *eapol;
638         const struct wpa_eapol_key *hdr;
639         u16 key_info;
640         const u8 *kck;
641
642         wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR,
643                    MAC2STR(src), MAC2STR(dst));
644         bss = bss_get(wt, dst);
645         if (bss == NULL)
646                 return;
647         sta = sta_get(bss, src);
648         if (sta == NULL)
649                 return;
650
651         eapol = (const struct ieee802_1x_hdr *) data;
652         hdr = (const struct wpa_eapol_key *) (eapol + 1);
653         if (!is_zero(hdr->key_rsc, 8)) {
654                 add_note(wt, MSG_INFO, "EAPOL-Key 4/4 from " MACSTR " used "
655                          "non-zero Key RSC", MAC2STR(src));
656         }
657         key_info = WPA_GET_BE16(hdr->key_info);
658
659         if (!sta->ptk_set && !sta->tptk_set) {
660                 add_note(wt, MSG_DEBUG,
661                          "No PTK known to process EAPOL-Key 4/4");
662                 return;
663         }
664
665         kck = sta->ptk.kck;
666         if (sta->tptk_set) {
667                 add_note(wt, MSG_DEBUG,
668                          "Use TPTK for validation EAPOL-Key MIC");
669                 kck = sta->tptk.kck;
670         }
671         if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
672                 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
673                 return;
674         }
675         add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 4/4");
676         if (sta->tptk_set) {
677                 add_note(wt, MSG_DEBUG, "Update PTK (rekeying)");
678                 os_memcpy(&sta->ptk, &sta->tptk, sizeof(sta->ptk));
679                 sta->ptk_set = 1;
680                 sta->tptk_set = 0;
681                 os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
682                 os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
683         }
684 }
685
686
687 static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
688                                      const u8 *src, const u8 *data, size_t len)
689 {
690         struct wlantest_bss *bss;
691         struct wlantest_sta *sta;
692         const struct ieee802_1x_hdr *eapol;
693         const struct wpa_eapol_key *hdr;
694         u16 key_info, ver;
695         u8 *decrypted;
696         size_t decrypted_len = 0;
697
698         wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR,
699                    MAC2STR(src), MAC2STR(dst));
700         bss = bss_get(wt, src);
701         if (bss == NULL)
702                 return;
703         sta = sta_get(bss, dst);
704         if (sta == NULL)
705                 return;
706
707         eapol = (const struct ieee802_1x_hdr *) data;
708         hdr = (const struct wpa_eapol_key *) (eapol + 1);
709         key_info = WPA_GET_BE16(hdr->key_info);
710
711         if (!sta->ptk_set) {
712                 add_note(wt, MSG_DEBUG,
713                          "No PTK known to process EAPOL-Key 1/2");
714                 return;
715         }
716
717         if (sta->ptk_set &&
718             check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
719                       data, len) < 0) {
720                 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 1/2 MIC");
721                 return;
722         }
723         add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 1/2");
724
725         if (sta->proto & WPA_PROTO_RSN &&
726             !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
727                 add_note(wt, MSG_INFO, "EAPOL-Key 1/2 without EncrKeyData bit");
728                 return;
729         }
730         ver = key_info & WPA_KEY_INFO_TYPE_MASK;
731         decrypted = decrypt_eapol_key_data(wt, sta->ptk.kek, ver, hdr,
732                                            &decrypted_len);
733         if (decrypted == NULL) {
734                 add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
735                 return;
736         }
737         wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data",
738                     decrypted, decrypted_len);
739         if (wt->write_pcap_dumper) {
740                 /* Fill in a dummy Data frame header */
741                 u8 buf[24 + 8 + sizeof(*eapol) + sizeof(*hdr)];
742                 struct ieee80211_hdr *h;
743                 struct wpa_eapol_key *k;
744                 u8 *pos;
745                 size_t plain_len;
746
747                 plain_len = decrypted_len;
748                 pos = decrypted;
749                 while (pos + 1 < decrypted + decrypted_len) {
750                         if (pos[0] == 0xdd && pos[1] == 0x00) {
751                                 /* Remove padding */
752                                 plain_len = pos - decrypted;
753                                 break;
754                         }
755                         pos += 2 + pos[1];
756                 }
757
758                 os_memset(buf, 0, sizeof(buf));
759                 h = (struct ieee80211_hdr *) buf;
760                 h->frame_control = host_to_le16(0x0208);
761                 os_memcpy(h->addr1, dst, ETH_ALEN);
762                 os_memcpy(h->addr2, src, ETH_ALEN);
763                 os_memcpy(h->addr3, src, ETH_ALEN);
764                 pos = (u8 *) (h + 1);
765                 os_memcpy(pos, "\xaa\xaa\x03\x00\x00\x00\x88\x8e", 8);
766                 pos += 8;
767                 os_memcpy(pos, eapol, sizeof(*eapol));
768                 pos += sizeof(*eapol);
769                 os_memcpy(pos, hdr, sizeof(*hdr));
770                 k = (struct wpa_eapol_key *) pos;
771                 WPA_PUT_BE16(k->key_info,
772                              key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA);
773                 WPA_PUT_BE16(k->key_data_length, plain_len);
774                 write_pcap_decrypted(wt, buf, sizeof(buf),
775                                      decrypted, plain_len);
776         }
777         if (sta->proto & WPA_PROTO_RSN)
778                 learn_kde_keys(wt, bss, sta, decrypted, decrypted_len,
779                                hdr->key_rsc);
780         else {
781                 int klen = bss->group_cipher == WPA_CIPHER_TKIP ? 32 : 16;
782                 if (decrypted_len == klen) {
783                         const u8 *rsc = hdr->key_rsc;
784                         int id;
785                         id = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
786                                 WPA_KEY_INFO_KEY_INDEX_SHIFT;
787                         add_note(wt, MSG_DEBUG, "GTK key index %d", id);
788                         wpa_hexdump(MSG_DEBUG, "GTK", decrypted,
789                                     decrypted_len);
790                         bss->gtk_len[id] = decrypted_len;
791                         os_memcpy(bss->gtk[id], decrypted, decrypted_len);
792                         bss->rsc[id][0] = rsc[5];
793                         bss->rsc[id][1] = rsc[4];
794                         bss->rsc[id][2] = rsc[3];
795                         bss->rsc[id][3] = rsc[2];
796                         bss->rsc[id][4] = rsc[1];
797                         bss->rsc[id][5] = rsc[0];
798                         wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[id], 6);
799                 } else {
800                         add_note(wt, MSG_INFO, "Unexpected WPA Key Data length "
801                                  "in Group Key msg 1/2 from " MACSTR,
802                                  MAC2STR(src));
803                 }
804         }
805         os_free(decrypted);
806 }
807
808
809 static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
810                                      const u8 *src, const u8 *data, size_t len)
811 {
812         struct wlantest_bss *bss;
813         struct wlantest_sta *sta;
814         const struct ieee802_1x_hdr *eapol;
815         const struct wpa_eapol_key *hdr;
816         u16 key_info;
817
818         wpa_printf(MSG_DEBUG, "EAPOL-Key 2/2 " MACSTR " -> " MACSTR,
819                    MAC2STR(src), MAC2STR(dst));
820         bss = bss_get(wt, dst);
821         if (bss == NULL)
822                 return;
823         sta = sta_get(bss, src);
824         if (sta == NULL)
825                 return;
826
827         eapol = (const struct ieee802_1x_hdr *) data;
828         hdr = (const struct wpa_eapol_key *) (eapol + 1);
829         if (!is_zero(hdr->key_rsc, 8)) {
830                 add_note(wt, MSG_INFO, "EAPOL-Key 2/2 from " MACSTR " used "
831                          "non-zero Key RSC", MAC2STR(src));
832         }
833         key_info = WPA_GET_BE16(hdr->key_info);
834
835         if (!sta->ptk_set) {
836                 add_note(wt, MSG_DEBUG,
837                          "No PTK known to process EAPOL-Key 2/2");
838                 return;
839         }
840
841         if (sta->ptk_set &&
842             check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
843                       data, len) < 0) {
844                 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC");
845                 return;
846         }
847         add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/2");
848 }
849
850
851 static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
852                               const u8 *src, const u8 *data, size_t len,
853                               int prot)
854 {
855         const struct ieee802_1x_hdr *eapol;
856         const struct wpa_eapol_key *hdr;
857         const u8 *key_data;
858         u16 key_info, key_length, ver, key_data_length;
859
860         eapol = (const struct ieee802_1x_hdr *) data;
861         hdr = (const struct wpa_eapol_key *) (eapol + 1);
862
863         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key",
864                     (const u8 *) hdr, len - sizeof(*eapol));
865         if (len < sizeof(*hdr)) {
866                 add_note(wt, MSG_INFO, "Too short EAPOL-Key frame from " MACSTR,
867                          MAC2STR(src));
868                 return;
869         }
870
871         if (hdr->type == EAPOL_KEY_TYPE_RC4) {
872                 /* TODO: EAPOL-Key RC4 for WEP */
873                 wpa_printf(MSG_INFO, "EAPOL-Key Descriptor Type RC4 from "
874                            MACSTR, MAC2STR(src));
875                 return;
876         }
877
878         if (hdr->type != EAPOL_KEY_TYPE_RSN &&
879             hdr->type != EAPOL_KEY_TYPE_WPA) {
880                 wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Descriptor Type "
881                            "%u from " MACSTR, hdr->type, MAC2STR(src));
882                 return;
883         }
884
885         key_info = WPA_GET_BE16(hdr->key_info);
886         key_length = WPA_GET_BE16(hdr->key_length);
887         key_data_length = WPA_GET_BE16(hdr->key_data_length);
888         key_data = (const u8 *) (hdr + 1);
889         if (key_data + key_data_length > data + len) {
890                 add_note(wt, MSG_INFO, "Truncated EAPOL-Key from " MACSTR,
891                          MAC2STR(src));
892                 return;
893         }
894         if (key_data + key_data_length < data + len) {
895                 wpa_hexdump(MSG_DEBUG, "Extra data after EAPOL-Key Key Data "
896                             "field", key_data + key_data_length,
897                         data + len - key_data - key_data_length);
898         }
899
900
901         ver = key_info & WPA_KEY_INFO_TYPE_MASK;
902         wpa_printf(MSG_DEBUG, "EAPOL-Key ver=%u %c idx=%u%s%s%s%s%s%s%s%s "
903                    "datalen=%u",
904                    ver, key_info & WPA_KEY_INFO_KEY_TYPE ? 'P' : 'G',
905                    (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
906                    WPA_KEY_INFO_KEY_INDEX_SHIFT,
907                    (key_info & WPA_KEY_INFO_INSTALL) ? " Install" : "",
908                    (key_info & WPA_KEY_INFO_ACK) ? " ACK" : "",
909                    (key_info & WPA_KEY_INFO_MIC) ? " MIC" : "",
910                    (key_info & WPA_KEY_INFO_SECURE) ? " Secure" : "",
911                    (key_info & WPA_KEY_INFO_ERROR) ? " Error" : "",
912                    (key_info & WPA_KEY_INFO_REQUEST) ? " Request" : "",
913                    (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ? " Encr" : "",
914                    (key_info & WPA_KEY_INFO_SMK_MESSAGE) ? " SMK" : "",
915                    key_data_length);
916
917         if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
918             ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
919             ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
920                 wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Key Descriptor "
921                            "Version %u from " MACSTR, ver, MAC2STR(src));
922                 return;
923         }
924
925         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Replay Counter",
926                     hdr->replay_counter, WPA_REPLAY_COUNTER_LEN);
927         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Nonce",
928                     hdr->key_nonce, WPA_NONCE_LEN);
929         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key IV",
930                     hdr->key_iv, 16);
931         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key RSC",
932                     hdr->key_rsc, WPA_KEY_RSC_LEN);
933         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key MIC",
934                     hdr->key_mic, 16);
935         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data",
936                     key_data, key_data_length);
937
938         if (hdr->type == EAPOL_KEY_TYPE_RSN &&
939             (key_info & (WPA_KEY_INFO_KEY_INDEX_MASK | BIT(14) | BIT(15))) !=
940             0) {
941                 wpa_printf(MSG_INFO, "RSN EAPOL-Key with non-zero reserved "
942                            "Key Info bits 0x%x from " MACSTR,
943                            key_info, MAC2STR(src));
944         }
945
946         if (hdr->type == EAPOL_KEY_TYPE_WPA &&
947             (key_info & (WPA_KEY_INFO_ENCR_KEY_DATA |
948                          WPA_KEY_INFO_SMK_MESSAGE |BIT(14) | BIT(15))) != 0) {
949                 wpa_printf(MSG_INFO, "WPA EAPOL-Key with non-zero reserved "
950                            "Key Info bits 0x%x from " MACSTR,
951                            key_info, MAC2STR(src));
952         }
953
954         if (key_length > 32) {
955                 wpa_printf(MSG_INFO, "EAPOL-Key with invalid Key Length %d "
956                            "from " MACSTR, key_length, MAC2STR(src));
957         }
958
959         if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
960             !is_zero(hdr->key_iv, 16)) {
961                 wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key IV "
962                            "(reserved with ver=%d) field from " MACSTR,
963                            ver, MAC2STR(src));
964                 wpa_hexdump(MSG_INFO, "EAPOL-Key Key IV (reserved)",
965                             hdr->key_iv, 16);
966         }
967
968         if (!is_zero(hdr->key_id, 8)) {
969                 wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key ID "
970                            "(reserved) field from " MACSTR, MAC2STR(src));
971                 wpa_hexdump(MSG_INFO, "EAPOL-Key Key ID (reserved)",
972                             hdr->key_id, 8);
973         }
974
975         if (hdr->key_rsc[6] || hdr->key_rsc[7]) {
976                 wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key RSC octets "
977                            "(last two are unused)" MACSTR, MAC2STR(src));
978         }
979
980         if (key_info & (WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST))
981                 return;
982
983         if (key_info & WPA_KEY_INFO_SMK_MESSAGE)
984                 return;
985
986         if (key_info & WPA_KEY_INFO_KEY_TYPE) {
987                 /* 4-Way Handshake */
988                 switch (key_info & (WPA_KEY_INFO_SECURE |
989                                     WPA_KEY_INFO_MIC |
990                                     WPA_KEY_INFO_ACK |
991                                     WPA_KEY_INFO_INSTALL)) {
992                 case WPA_KEY_INFO_ACK:
993                         rx_data_eapol_key_1_of_4(wt, dst, src, data, len);
994                         break;
995                 case WPA_KEY_INFO_MIC:
996                         if (key_data_length == 0)
997                                 rx_data_eapol_key_4_of_4(wt, dst, src, data,
998                                                          len);
999                         else
1000                                 rx_data_eapol_key_2_of_4(wt, dst, src, data,
1001                                                          len);
1002                         break;
1003                 case WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK |
1004                         WPA_KEY_INFO_INSTALL:
1005                         /* WPA does not include Secure bit in 3/4 */
1006                         rx_data_eapol_key_3_of_4(wt, dst, src, data, len);
1007                         break;
1008                 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
1009                         WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL:
1010                         rx_data_eapol_key_3_of_4(wt, dst, src, data, len);
1011                         break;
1012                 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
1013                         if (key_data_length == 0)
1014                                 rx_data_eapol_key_4_of_4(wt, dst, src, data,
1015                                                          len);
1016                         else
1017                                 rx_data_eapol_key_2_of_4(wt, dst, src, data,
1018                                                          len);
1019                         break;
1020                 default:
1021                         wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
1022                         break;
1023                 }
1024         } else {
1025                 /* Group Key Handshake */
1026                 switch (key_info & (WPA_KEY_INFO_SECURE |
1027                                     WPA_KEY_INFO_MIC |
1028                                     WPA_KEY_INFO_ACK)) {
1029                 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
1030                         WPA_KEY_INFO_ACK:
1031                         rx_data_eapol_key_1_of_2(wt, dst, src, data, len);
1032                         break;
1033                 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
1034                         rx_data_eapol_key_2_of_2(wt, dst, src, data, len);
1035                         break;
1036                 default:
1037                         wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
1038                         break;
1039                 }
1040         }
1041 }
1042
1043
1044 void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src,
1045                    const u8 *data, size_t len, int prot)
1046 {
1047         const struct ieee802_1x_hdr *hdr;
1048         u16 length;
1049         const u8 *p;
1050
1051         wpa_hexdump(MSG_EXCESSIVE, "EAPOL", data, len);
1052         if (len < sizeof(*hdr)) {
1053                 wpa_printf(MSG_INFO, "Too short EAPOL frame from " MACSTR,
1054                            MAC2STR(src));
1055                 return;
1056         }
1057
1058         hdr = (const struct ieee802_1x_hdr *) data;
1059         length = be_to_host16(hdr->length);
1060         wpa_printf(MSG_DEBUG, "RX EAPOL: " MACSTR " -> " MACSTR "%s ver=%u "
1061                    "type=%u len=%u",
1062                    MAC2STR(src), MAC2STR(dst), prot ? " Prot" : "",
1063                    hdr->version, hdr->type, length);
1064         if (hdr->version < 1 || hdr->version > 3) {
1065                 wpa_printf(MSG_INFO, "Unexpected EAPOL version %u from "
1066                            MACSTR, hdr->version, MAC2STR(src));
1067         }
1068         if (sizeof(*hdr) + length > len) {
1069                 wpa_printf(MSG_INFO, "Truncated EAPOL frame from " MACSTR,
1070                            MAC2STR(src));
1071                 return;
1072         }
1073
1074         if (sizeof(*hdr) + length < len) {
1075                 wpa_printf(MSG_INFO, "EAPOL frame with %d extra bytes",
1076                            (int) (len - sizeof(*hdr) - length));
1077         }
1078         p = (const u8 *) (hdr + 1);
1079
1080         switch (hdr->type) {
1081         case IEEE802_1X_TYPE_EAP_PACKET:
1082                 wpa_hexdump(MSG_MSGDUMP, "EAPOL - EAP packet", p, length);
1083                 break;
1084         case IEEE802_1X_TYPE_EAPOL_START:
1085                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Start", p, length);
1086                 break;
1087         case IEEE802_1X_TYPE_EAPOL_LOGOFF:
1088                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Logoff", p, length);
1089                 break;
1090         case IEEE802_1X_TYPE_EAPOL_KEY:
1091                 rx_data_eapol_key(wt, dst, src, data, sizeof(*hdr) + length,
1092                                   prot);
1093                 break;
1094         case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
1095                 wpa_hexdump(MSG_MSGDUMP, "EAPOL - Encapsulated ASF alert",
1096                             p, length);
1097                 break;
1098         default:
1099                 wpa_hexdump(MSG_MSGDUMP, "Unknown EAPOL payload", p, length);
1100                 break;
1101         }
1102 }