wlantest: Parse Key Data KDEs and store GTK and IGTK
[mech_eap.git] / wlantest / rx_data.c
1 /*
2  * Received Data frame processing
3  * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "utils/includes.h"
16
17 #include "utils/common.h"
18 #include "crypto/aes_wrap.h"
19 #include "crypto/crypto.h"
20 #include "common/ieee802_11_defs.h"
21 #include "common/eapol_common.h"
22 #include "common/wpa_common.h"
23 #include "rsn_supp/wpa_ie.h"
24 #include "wlantest.h"
25
26
27 static const char * data_stype(u16 stype)
28 {
29         switch (stype) {
30         case WLAN_FC_STYPE_DATA:
31                 return "DATA";
32         case WLAN_FC_STYPE_DATA_CFACK:
33                 return "DATA-CFACK";
34         case WLAN_FC_STYPE_DATA_CFPOLL:
35                 return "DATA-CFPOLL";
36         case WLAN_FC_STYPE_DATA_CFACKPOLL:
37                 return "DATA-CFACKPOLL";
38         case WLAN_FC_STYPE_NULLFUNC:
39                 return "NULLFUNC";
40         case WLAN_FC_STYPE_CFACK:
41                 return "CFACK";
42         case WLAN_FC_STYPE_CFPOLL:
43                 return "CFPOLL";
44         case WLAN_FC_STYPE_CFACKPOLL:
45                 return "CFACKPOLL";
46         case WLAN_FC_STYPE_QOS_DATA:
47                 return "QOSDATA";
48         case WLAN_FC_STYPE_QOS_DATA_CFACK:
49                 return "QOSDATA-CFACK";
50         case WLAN_FC_STYPE_QOS_DATA_CFPOLL:
51                 return "QOSDATA-CFPOLL";
52         case WLAN_FC_STYPE_QOS_DATA_CFACKPOLL:
53                 return "QOSDATA-CFACKPOLL";
54         case WLAN_FC_STYPE_QOS_NULL:
55                 return "QOS-NULL";
56         case WLAN_FC_STYPE_QOS_CFPOLL:
57                 return "QOS-CFPOLL";
58         case WLAN_FC_STYPE_QOS_CFACKPOLL:
59                 return "QOS-CFACKPOLL";
60         }
61         return "??";
62 }
63
64
65 static int check_mic(const u8 *kck, int ver, const u8 *data, size_t len)
66 {
67         u8 *buf;
68         int ret = -1;
69         struct ieee802_1x_hdr *hdr;
70         struct wpa_eapol_key *key;
71         u8 rx_mic[16];
72
73         buf = os_malloc(len);
74         if (buf == NULL)
75                 return -1;
76         os_memcpy(buf, data, len);
77         hdr = (struct ieee802_1x_hdr *) buf;
78         key = (struct wpa_eapol_key *) (hdr + 1);
79
80         os_memcpy(rx_mic, key->key_mic, 16);
81         os_memset(key->key_mic, 0, 16);
82
83         if (wpa_eapol_key_mic(kck, ver, buf, len, key->key_mic) == 0 &&
84             os_memcmp(rx_mic, key->key_mic, 16) == 0)
85                 ret = 0;
86
87         os_free(buf);
88
89         return ret;
90 }
91
92
93 static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst,
94                                      const u8 *src, const u8 *data, size_t len)
95 {
96         struct wlantest_bss *bss;
97         struct wlantest_sta *sta;
98         const struct ieee802_1x_hdr *eapol;
99         const struct wpa_eapol_key *hdr;
100
101         wpa_printf(MSG_DEBUG, "EAPOL-Key 1/4 " MACSTR " -> " MACSTR,
102                    MAC2STR(src), MAC2STR(dst));
103         bss = bss_get(wt, src);
104         if (bss == NULL)
105                 return;
106         sta = sta_get(bss, dst);
107         if (sta == NULL)
108                 return;
109
110         eapol = (const struct ieee802_1x_hdr *) data;
111         hdr = (const struct wpa_eapol_key *) (eapol + 1);
112         os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
113 }
114
115
116 static int try_pmk(struct wlantest_bss *bss, struct wlantest_sta *sta,
117                    u16 ver, const u8 *data, size_t len,
118                    struct wlantest_pmk *pmk)
119 {
120         struct wpa_ptk ptk;
121         size_t ptk_len = 48; /* FIX: 64 for TKIP */
122         wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk),
123                        "Pairwise key expansion",
124                        bss->bssid, sta->addr, sta->anonce, sta->snonce,
125                        (u8 *) &ptk, ptk_len,
126                        0 /* FIX: SHA256 based on AKM */);
127         if (check_mic(ptk.kck, ver,
128                       data, len) < 0)
129                 return -1;
130
131         wpa_printf(MSG_INFO, "Derived PTK for STA " MACSTR " BSSID " MACSTR
132                    ")", MAC2STR(sta->addr), MAC2STR(bss->bssid));
133         os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
134         sta->ptk_set = 1;
135         return 0;
136 }
137
138
139 static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss,
140                        struct wlantest_sta *sta, u16 ver,
141                        const u8 *data, size_t len)
142 {
143         struct wlantest_pmk *pmk;
144
145         dl_list_for_each(pmk, &bss->pmk, struct wlantest_pmk, list) {
146                 if (try_pmk(bss, sta, ver, data, len, pmk) == 0)
147                         return;
148         }
149
150         dl_list_for_each(pmk, &wt->pmk, struct wlantest_pmk, list) {
151                 if (try_pmk(bss, sta, ver, data, len, pmk) == 0)
152                         return;
153         }
154 }
155
156
157 static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
158                                      const u8 *src, const u8 *data, size_t len)
159 {
160         struct wlantest_bss *bss;
161         struct wlantest_sta *sta;
162         const struct ieee802_1x_hdr *eapol;
163         const struct wpa_eapol_key *hdr;
164         u16 key_info;
165
166         wpa_printf(MSG_DEBUG, "EAPOL-Key 2/4 " MACSTR " -> " MACSTR,
167                    MAC2STR(src), MAC2STR(dst));
168         bss = bss_get(wt, dst);
169         if (bss == NULL)
170                 return;
171         sta = sta_get(bss, src);
172         if (sta == NULL)
173                 return;
174
175         eapol = (const struct ieee802_1x_hdr *) data;
176         hdr = (const struct wpa_eapol_key *) (eapol + 1);
177         os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN);
178         key_info = WPA_GET_BE16(hdr->key_info);
179         derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len);
180 }
181
182
183 static u8 * decrypt_eapol_key_data_rc4(const u8 *kek,
184                                        const struct wpa_eapol_key *hdr,
185                                        size_t *len)
186 {
187         u8 ek[32], *buf;
188         u16 keydatalen = WPA_GET_BE16(hdr->key_data_length);
189
190         buf = os_malloc(keydatalen);
191         if (buf == NULL)
192                 return NULL;
193
194         os_memcpy(ek, hdr->key_iv, 16);
195         os_memcpy(ek + 16, kek, 16);
196         os_memcpy(buf, hdr + 1, keydatalen);
197         if (rc4_skip(ek, 32, 256, buf, keydatalen)) {
198                 wpa_printf(MSG_INFO, "RC4 failed");
199                 os_free(buf);
200                 return NULL;
201         }
202
203         *len = keydatalen;
204         return buf;
205 }
206
207
208 static u8 * decrypt_eapol_key_data_aes(const u8 *kek,
209                                        const struct wpa_eapol_key *hdr,
210                                        size_t *len)
211 {
212         u8 *buf;
213         u16 keydatalen = WPA_GET_BE16(hdr->key_data_length);
214
215         if (keydatalen % 8) {
216                 wpa_printf(MSG_INFO, "Unsupported AES-WRAP len %d",
217                            keydatalen);
218                 return NULL;
219         }
220         keydatalen -= 8; /* AES-WRAP adds 8 bytes */
221         buf = os_malloc(keydatalen);
222         if (buf == NULL)
223                 return NULL;
224         if (aes_unwrap(kek, keydatalen / 8, (u8 *) (hdr + 1), buf)) {
225                 os_free(buf);
226                 wpa_printf(MSG_INFO, "AES unwrap failed - "
227                            "could not decrypt EAPOL-Key key data");
228                 return NULL;
229         }
230
231         *len = keydatalen;
232         return buf;
233 }
234
235
236 static u8 * decrypt_eapol_key_data(const u8 *kek, u16 ver,
237                                    const struct wpa_eapol_key *hdr,
238                                    size_t *len)
239 {
240         switch (ver) {
241         case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
242                 return decrypt_eapol_key_data_rc4(kek, hdr, len);
243         case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
244         case WPA_KEY_INFO_TYPE_AES_128_CMAC:
245                 return decrypt_eapol_key_data_aes(kek, hdr, len);
246         default:
247                 wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Key Descriptor "
248                            "Version %u", ver);
249                 return NULL;
250         }
251 }
252
253
254 static void learn_kde_keys(struct wlantest_bss *bss, u8 *buf, size_t len)
255 {
256         struct wpa_eapol_ie_parse ie;
257
258         if (wpa_supplicant_parse_ies(buf, len, &ie) < 0) {
259                 wpa_printf(MSG_INFO, "Failed to parse EAPOL-Key Key Data");
260                 return;
261         }
262
263         if (ie.wpa_ie) {
264                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - WPA IE",
265                             ie.wpa_ie, ie.wpa_ie_len);
266         }
267
268         if (ie.rsn_ie) {
269                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - RSN IE",
270                             ie.rsn_ie, ie.rsn_ie_len);
271         }
272
273         if (ie.gtk) {
274                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - GTK KDE",
275                             ie.gtk, ie.gtk_len);
276                 if (ie.gtk_len >= 2 && ie.gtk_len <= 2 + 32) {
277                         int id;
278                         id = ie.gtk[0] & 0x03;
279                         wpa_printf(MSG_INFO, "GTK KeyID=%u tx=%u",
280                                    id, !!(ie.gtk[0] & 0x04));
281                         if ((ie.gtk[0] & 0xf8) || ie.gtk[1])
282                                 wpa_printf(MSG_INFO, "GTK KDE: Reserved field "
283                                            "set: %02x %02x",
284                                            ie.gtk[0], ie.gtk[1]);
285                         wpa_hexdump(MSG_DEBUG, "GTK", ie.gtk + 2,
286                                     ie.gtk_len - 2);
287                         bss->gtk_len[id] = ie.gtk_len - 2;
288                         os_memcpy(bss->gtk[id], ie.gtk + 2, ie.gtk_len - 2);
289                 } else {
290                         wpa_printf(MSG_INFO, "Invalid GTK KDE length %u",
291                                    (unsigned) ie.gtk_len);
292                 }
293         }
294
295         if (ie.igtk) {
296                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - IGTK KDE",
297                             ie.igtk, ie.igtk_len);
298                 if (ie.igtk_len == 24) {
299                         u16 id;
300                         id = WPA_GET_LE16(ie.igtk);
301                         if (id > 5) {
302                                 wpa_printf(MSG_INFO, "Unexpected IGTK KeyID "
303                                            "%u", id);
304                         } else {
305                                 wpa_printf(MSG_INFO, "IGTK KeyID %u", id);
306                                 wpa_hexdump(MSG_INFO, "IPN", ie.igtk + 2, 6);
307                                 wpa_hexdump(MSG_INFO, "IGTK", ie.igtk + 8, 16);
308                                 os_memcpy(bss->igtk[id], ie.igtk + 8, 16);
309                                 bss->igtk_set[id] = 1;
310                         }
311                 } else {
312                         wpa_printf(MSG_INFO, "Invalid IGTK KDE length %u",
313                                    (unsigned) ie.igtk_len);
314                 }
315         }
316 }
317
318
319 static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
320                                      const u8 *src, const u8 *data, size_t len)
321 {
322         struct wlantest_bss *bss;
323         struct wlantest_sta *sta;
324         const struct ieee802_1x_hdr *eapol;
325         const struct wpa_eapol_key *hdr;
326         const u8 *key_data;
327         int recalc = 0;
328         u16 key_info, ver, key_data_len;
329         u8 *decrypted;
330         size_t decrypted_len = 0;
331
332         wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR,
333                    MAC2STR(src), MAC2STR(dst));
334         bss = bss_get(wt, src);
335         if (bss == NULL)
336                 return;
337         sta = sta_get(bss, dst);
338         if (sta == NULL)
339                 return;
340
341         eapol = (const struct ieee802_1x_hdr *) data;
342         hdr = (const struct wpa_eapol_key *) (eapol + 1);
343         key_info = WPA_GET_BE16(hdr->key_info);
344         key_data_len = WPA_GET_BE16(hdr->key_data_length);
345
346         if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) {
347                 wpa_printf(MSG_INFO, "EAPOL-Key ANonce mismatch between 1/4 "
348                            "and 3/4");
349                 recalc = 1;
350         }
351         os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
352         if (recalc) {
353                 derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK,
354                            data, len);
355         }
356
357         if (!sta->ptk_set) {
358                 wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 3/4");
359                 return;
360         }
361
362         if (check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
363                       data, len) < 0) {
364                 wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
365                 return;
366         }
367         wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 3/4");
368
369         key_data = (const u8 *) (hdr + 1);
370         /* TODO: handle WPA without EncrKeyData bit */
371         if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
372                 wpa_printf(MSG_INFO, "EAPOL-Key 3/4 without EncrKeyData bit");
373                 return;
374         }
375         ver = key_info & WPA_KEY_INFO_TYPE_MASK;
376         decrypted = decrypt_eapol_key_data(sta->ptk.kek, ver, hdr,
377                                            &decrypted_len);
378         if (decrypted == NULL) {
379                 wpa_printf(MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
380                 return;
381         }
382         wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data",
383                     decrypted, decrypted_len);
384         learn_kde_keys(bss, decrypted, decrypted_len);
385         os_free(decrypted);
386 }
387
388
389 static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
390                                      const u8 *src, const u8 *data, size_t len)
391 {
392         struct wlantest_bss *bss;
393         struct wlantest_sta *sta;
394         const struct ieee802_1x_hdr *eapol;
395         const struct wpa_eapol_key *hdr;
396         u16 key_info;
397
398         wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR,
399                    MAC2STR(src), MAC2STR(dst));
400         bss = bss_get(wt, dst);
401         if (bss == NULL)
402                 return;
403         sta = sta_get(bss, src);
404         if (sta == NULL)
405                 return;
406
407         eapol = (const struct ieee802_1x_hdr *) data;
408         hdr = (const struct wpa_eapol_key *) (eapol + 1);
409         key_info = WPA_GET_BE16(hdr->key_info);
410
411         if (!sta->ptk_set) {
412                 wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 4/4");
413                 return;
414         }
415
416         if (sta->ptk_set &&
417             check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
418                       data, len) < 0) {
419                 wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
420                 return;
421         }
422         wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 4/4");
423 }
424
425
426 static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
427                                      const u8 *src, const u8 *data, size_t len)
428 {
429         wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR,
430                    MAC2STR(src), MAC2STR(dst));
431 }
432
433
434 static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
435                                      const u8 *src, const u8 *data, size_t len)
436 {
437         wpa_printf(MSG_DEBUG, "EAPOL-Key 2/2 " MACSTR " -> " MACSTR,
438                    MAC2STR(src), MAC2STR(dst));
439 }
440
441
442 static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
443                               const u8 *src, const u8 *data, size_t len,
444                               int prot)
445 {
446         const struct ieee802_1x_hdr *eapol;
447         const struct wpa_eapol_key *hdr;
448         const u8 *key_data;
449         u16 key_info, key_length, ver, key_data_length;
450
451         eapol = (const struct ieee802_1x_hdr *) data;
452         hdr = (const struct wpa_eapol_key *) (eapol + 1);
453
454         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key",
455                     (const u8 *) hdr, len - sizeof(*eapol));
456         if (len < sizeof(*hdr)) {
457                 wpa_printf(MSG_INFO, "Too short EAPOL-Key frame from " MACSTR,
458                            MAC2STR(src));
459                 return;
460         }
461
462         if (hdr->type == EAPOL_KEY_TYPE_RC4) {
463                 /* TODO: EAPOL-Key RC4 for WEP */
464                 return;
465         }
466
467         if (hdr->type != EAPOL_KEY_TYPE_RSN &&
468             hdr->type != EAPOL_KEY_TYPE_WPA) {
469                 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key type %u",
470                            hdr->type);
471                 return;
472         }
473
474         key_info = WPA_GET_BE16(hdr->key_info);
475         key_length = WPA_GET_BE16(hdr->key_length);
476         key_data_length = WPA_GET_BE16(hdr->key_data_length);
477         key_data = (const u8 *) (hdr + 1);
478         if (key_data + key_data_length > data + len) {
479                 wpa_printf(MSG_INFO, "Truncated EAPOL-Key from " MACSTR,
480                            MAC2STR(src));
481                 return;
482         }
483         if (key_data + key_data_length < data + len) {
484                 wpa_hexdump(MSG_DEBUG, "Extra data after EAPOL-Key Key Data "
485                             "field", key_data + key_data_length,
486                         data + len - key_data - key_data_length);
487         }
488
489
490         ver = key_info & WPA_KEY_INFO_TYPE_MASK;
491         wpa_printf(MSG_DEBUG, "EAPOL-Key ver=%u %c idx=%u%s%s%s%s%s%s%s%s "
492                    "datalen=%u",
493                    ver, key_info & WPA_KEY_INFO_KEY_TYPE ? 'P' : 'G',
494                    (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
495                    WPA_KEY_INFO_KEY_INDEX_SHIFT,
496                    (key_info & WPA_KEY_INFO_INSTALL) ? " Install" : "",
497                    (key_info & WPA_KEY_INFO_ACK) ? " ACK" : "",
498                    (key_info & WPA_KEY_INFO_MIC) ? " MIC" : "",
499                    (key_info & WPA_KEY_INFO_SECURE) ? " Secure" : "",
500                    (key_info & WPA_KEY_INFO_ERROR) ? " Error" : "",
501                    (key_info & WPA_KEY_INFO_REQUEST) ? " Request" : "",
502                    (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ? " Encr" : "",
503                    (key_info & WPA_KEY_INFO_SMK_MESSAGE) ? " SMK" : "",
504                    key_data_length);
505
506         if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
507             ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
508             ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
509                 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key Key Descriptor "
510                            "Version %u", ver);
511                 return;
512         }
513
514         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Replay Counter",
515                     hdr->replay_counter, WPA_REPLAY_COUNTER_LEN);
516         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Nonce",
517                     hdr->key_nonce, WPA_NONCE_LEN);
518         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key IV",
519                     hdr->key_iv, 16);
520         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key RSC",
521                     hdr->key_nonce, WPA_KEY_RSC_LEN);
522         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key MIC",
523                     hdr->key_mic, 16);
524         wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data",
525                     key_data, key_data_length);
526
527         if (key_info & (WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST))
528                 return;
529
530         if (key_info & WPA_KEY_INFO_SMK_MESSAGE)
531                 return;
532
533         if (key_info & WPA_KEY_INFO_KEY_TYPE) {
534                 /* 4-Way Handshake */
535                 switch (key_info & (WPA_KEY_INFO_SECURE |
536                                     WPA_KEY_INFO_MIC |
537                                     WPA_KEY_INFO_ACK |
538                                     WPA_KEY_INFO_INSTALL)) {
539                 case WPA_KEY_INFO_ACK:
540                         rx_data_eapol_key_1_of_4(wt, dst, src, data, len);
541                         break;
542                 case WPA_KEY_INFO_MIC:
543                         rx_data_eapol_key_2_of_4(wt, dst, src, data, len);
544                         break;
545                 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
546                         WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL:
547                         rx_data_eapol_key_3_of_4(wt, dst, src, data, len);
548                         break;
549                 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
550                         rx_data_eapol_key_4_of_4(wt, dst, src, data, len);
551                         break;
552                 default:
553                         wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
554                         break;
555                 }
556         } else {
557                 /* Group Key Handshake */
558                 switch (key_info & (WPA_KEY_INFO_SECURE |
559                                     WPA_KEY_INFO_MIC |
560                                     WPA_KEY_INFO_ACK)) {
561                 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
562                         WPA_KEY_INFO_ACK:
563                         rx_data_eapol_key_1_of_2(wt, dst, src, data, len);
564                         break;
565                 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
566                         rx_data_eapol_key_2_of_2(wt, dst, src, data, len);
567                         break;
568                 default:
569                         wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
570                         break;
571                 }
572         }
573 }
574
575
576 static void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src,
577                           const u8 *data, size_t len, int prot)
578 {
579         const struct ieee802_1x_hdr *hdr;
580         u16 length;
581         const u8 *p;
582
583         wpa_hexdump(MSG_EXCESSIVE, "EAPOL", data, len);
584         if (len < sizeof(*hdr)) {
585                 wpa_printf(MSG_INFO, "Too short EAPOL frame from " MACSTR,
586                            MAC2STR(src));
587                 return;
588         }
589
590         hdr = (const struct ieee802_1x_hdr *) data;
591         length = be_to_host16(hdr->length);
592         wpa_printf(MSG_DEBUG, "RX EAPOL: " MACSTR " -> " MACSTR "%s ver=%u "
593                    "type=%u len=%u",
594                    MAC2STR(src), MAC2STR(dst), prot ? " Prot" : "",
595                    hdr->version, hdr->type, length);
596         if (sizeof(*hdr) + length > len) {
597                 wpa_printf(MSG_INFO, "Truncated EAPOL frame from " MACSTR,
598                            MAC2STR(src));
599                 return;
600         }
601
602         if (sizeof(*hdr) + length < len) {
603                 wpa_printf(MSG_INFO, "EAPOL frame with %d extra bytes",
604                            (int) (len - sizeof(*hdr) - length));
605         }
606         p = (const u8 *) (hdr + 1);
607
608         switch (hdr->type) {
609         case IEEE802_1X_TYPE_EAP_PACKET:
610                 wpa_hexdump(MSG_MSGDUMP, "EAPOL - EAP packet", p, length);
611                 break;
612         case IEEE802_1X_TYPE_EAPOL_START:
613                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Start", p, length);
614                 break;
615         case IEEE802_1X_TYPE_EAPOL_LOGOFF:
616                 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Logoff", p, length);
617                 break;
618         case IEEE802_1X_TYPE_EAPOL_KEY:
619                 rx_data_eapol_key(wt, dst, src, data, sizeof(*hdr) + length,
620                                   prot);
621                 break;
622         case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
623                 wpa_hexdump(MSG_MSGDUMP, "EAPOL - Encapsulated ASF alert",
624                             p, length);
625                 break;
626         default:
627                 wpa_hexdump(MSG_MSGDUMP, "Unknown EAPOL payload", p, length);
628                 break;
629         }
630 }
631
632
633 static void rx_data_eth(struct wlantest *wt, const u8 *dst, const u8 *src,
634                         u16 ethertype, const u8 *data, size_t len, int prot)
635 {
636         if (ethertype == ETH_P_PAE)
637                 rx_data_eapol(wt, dst, src, data, len, prot);
638 }
639
640
641 static void rx_data_process(struct wlantest *wt, const u8 *dst, const u8 *src,
642                             const u8 *data, size_t len, int prot)
643 {
644         if (len == 0)
645                 return;
646
647         if (len >= 8 && os_memcmp(data, "\xaa\xaa\x03\x00\x00\x00", 6) == 0) {
648                 rx_data_eth(wt, dst, src, WPA_GET_BE16(data + 6),
649                             data + 8, len - 8, prot);
650                 return;
651         }
652
653         wpa_hexdump(MSG_DEBUG, "Unrecognized LLC", data, len > 8 ? 8 : len);
654 }
655
656
657 static void rx_data_bss_prot(struct wlantest *wt,
658                              const struct ieee80211_hdr *hdr, const u8 *qos,
659                              const u8 *dst, const u8 *src, const u8 *data,
660                              size_t len)
661 {
662         /* TODO: Try to decrypt and if success, call rx_data_process() with
663          * prot = 1 */
664 }
665
666
667 static void rx_data_bss(struct wlantest *wt, const struct ieee80211_hdr *hdr,
668                         const u8 *qos, const u8 *dst, const u8 *src,
669                         const u8 *data, size_t len)
670 {
671         u16 fc = le_to_host16(hdr->frame_control);
672         int prot = !!(fc & WLAN_FC_ISWEP);
673
674         if (qos) {
675                 u8 ack = (qos[0] & 0x60) >> 5;
676                 wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR
677                            " len=%u%s tid=%u%s%s",
678                            MAC2STR(src), MAC2STR(dst), (unsigned int) len,
679                            prot ? " Prot" : "", qos[0] & 0x0f,
680                            (qos[0] & 0x10) ? " EOSP" : "",
681                            ack == 0 ? "" :
682                            (ack == 1 ? " NoAck" :
683                             (ack == 2 ? " NoExpAck" : " BA")));
684         } else {
685                 wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR
686                            " len=%u%s",
687                            MAC2STR(src), MAC2STR(dst), (unsigned int) len,
688                            prot ? " Prot" : "");
689         }
690
691         if (prot)
692                 rx_data_bss_prot(wt, hdr, qos, dst, src, data, len);
693         else
694                 rx_data_process(wt, dst, src, data, len, 0);
695 }
696
697
698 void rx_data(struct wlantest *wt, const u8 *data, size_t len)
699 {
700         const struct ieee80211_hdr *hdr;
701         u16 fc, stype;
702         size_t hdrlen;
703         const u8 *qos = NULL;
704
705         if (len < 24)
706                 return;
707
708         hdr = (const struct ieee80211_hdr *) data;
709         fc = le_to_host16(hdr->frame_control);
710         stype = WLAN_FC_GET_STYPE(fc);
711         hdrlen = 24;
712         if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
713             (WLAN_FC_TODS | WLAN_FC_FROMDS))
714                 hdrlen += ETH_ALEN;
715         if (stype & 0x08) {
716                 qos = data + hdrlen;
717                 hdrlen += 2;
718         }
719         if (len < hdrlen)
720                 return;
721         wt->rx_data++;
722
723         switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) {
724         case 0:
725                 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s IBSS DA=" MACSTR " SA="
726                            MACSTR " BSSID=" MACSTR,
727                            data_stype(WLAN_FC_GET_STYPE(fc)),
728                            fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
729                            fc & WLAN_FC_ISWEP ? " Prot" : "",
730                            MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
731                            MAC2STR(hdr->addr3));
732                 break;
733         case WLAN_FC_FROMDS:
734                 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s FromDS DA=" MACSTR
735                            " BSSID=" MACSTR " SA=" MACSTR,
736                            data_stype(WLAN_FC_GET_STYPE(fc)),
737                            fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
738                            fc & WLAN_FC_ISWEP ? " Prot" : "",
739                            MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
740                            MAC2STR(hdr->addr3));
741                 rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr2,
742                             data + hdrlen, len - hdrlen);
743                 break;
744         case WLAN_FC_TODS:
745                 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s ToDS BSSID=" MACSTR
746                            " SA=" MACSTR " DA=" MACSTR,
747                            data_stype(WLAN_FC_GET_STYPE(fc)),
748                            fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
749                            fc & WLAN_FC_ISWEP ? " Prot" : "",
750                            MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
751                            MAC2STR(hdr->addr3));
752                 rx_data_bss(wt, hdr, qos, hdr->addr3, hdr->addr2,
753                             data + hdrlen, len - hdrlen);
754                 break;
755         case WLAN_FC_TODS | WLAN_FC_FROMDS:
756                 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s WDS RA=" MACSTR " TA="
757                            MACSTR " DA=" MACSTR " SA=" MACSTR,
758                            data_stype(WLAN_FC_GET_STYPE(fc)),
759                            fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
760                            fc & WLAN_FC_ISWEP ? " Prot" : "",
761                            MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
762                            MAC2STR(hdr->addr3),
763                            MAC2STR((const u8 *) (hdr + 1)));
764                 break;
765         }
766 }