LCOV - code coverage report
Current view: top level - src/ap - wpa_auth_ie.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 407 496 82.1 %
Date: 2015-02-03 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :  * hostapd - WPA/RSN IE and KDE definitions
       3             :  * Copyright (c) 2004-2015, 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 "common/ieee802_11_defs.h"
      13             : #include "eapol_auth/eapol_auth_sm.h"
      14             : #include "ap_config.h"
      15             : #include "ieee802_11.h"
      16             : #include "wpa_auth.h"
      17             : #include "pmksa_cache_auth.h"
      18             : #include "wpa_auth_ie.h"
      19             : #include "wpa_auth_i.h"
      20             : 
      21             : 
      22             : #ifdef CONFIG_RSN_TESTING
      23             : int rsn_testing = 0;
      24             : #endif /* CONFIG_RSN_TESTING */
      25             : 
      26             : 
      27          31 : static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
      28             : {
      29             :         struct wpa_ie_hdr *hdr;
      30             :         int num_suites;
      31             :         u8 *pos, *count;
      32             :         u32 suite;
      33             : 
      34          31 :         hdr = (struct wpa_ie_hdr *) buf;
      35          31 :         hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
      36          31 :         RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE);
      37          31 :         WPA_PUT_LE16(hdr->version, WPA_VERSION);
      38          31 :         pos = (u8 *) (hdr + 1);
      39             : 
      40          31 :         suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group);
      41          31 :         if (suite == 0) {
      42           0 :                 wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
      43             :                            conf->wpa_group);
      44           0 :                 return -1;
      45             :         }
      46          31 :         RSN_SELECTOR_PUT(pos, suite);
      47          31 :         pos += WPA_SELECTOR_LEN;
      48             : 
      49          31 :         count = pos;
      50          31 :         pos += 2;
      51             : 
      52          31 :         num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise);
      53          31 :         if (num_suites == 0) {
      54           0 :                 wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
      55             :                            conf->wpa_pairwise);
      56           0 :                 return -1;
      57             :         }
      58          31 :         pos += num_suites * WPA_SELECTOR_LEN;
      59          31 :         WPA_PUT_LE16(count, num_suites);
      60             : 
      61          31 :         num_suites = 0;
      62          31 :         count = pos;
      63          31 :         pos += 2;
      64             : 
      65          31 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
      66           5 :                 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
      67           5 :                 pos += WPA_SELECTOR_LEN;
      68           5 :                 num_suites++;
      69             :         }
      70          31 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
      71          29 :                 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
      72          29 :                 pos += WPA_SELECTOR_LEN;
      73          29 :                 num_suites++;
      74             :         }
      75             : 
      76          31 :         if (num_suites == 0) {
      77           0 :                 wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
      78             :                            conf->wpa_key_mgmt);
      79           0 :                 return -1;
      80             :         }
      81          31 :         WPA_PUT_LE16(count, num_suites);
      82             : 
      83             :         /* WPA Capabilities; use defaults, so no need to include it */
      84             : 
      85          31 :         hdr->len = (pos - buf) - 2;
      86             : 
      87          31 :         return pos - buf;
      88             : }
      89             : 
      90             : 
      91        1309 : int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
      92             :                      const u8 *pmkid)
      93             : {
      94             :         struct rsn_ie_hdr *hdr;
      95             :         int num_suites, res;
      96             :         u8 *pos, *count;
      97             :         u16 capab;
      98             :         u32 suite;
      99             : 
     100        1309 :         hdr = (struct rsn_ie_hdr *) buf;
     101        1309 :         hdr->elem_id = WLAN_EID_RSN;
     102        1309 :         WPA_PUT_LE16(hdr->version, RSN_VERSION);
     103        1309 :         pos = (u8 *) (hdr + 1);
     104             : 
     105        1309 :         suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
     106        1309 :         if (suite == 0) {
     107           0 :                 wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
     108             :                            conf->wpa_group);
     109           0 :                 return -1;
     110             :         }
     111        1309 :         RSN_SELECTOR_PUT(pos, suite);
     112        1309 :         pos += RSN_SELECTOR_LEN;
     113             : 
     114        1309 :         num_suites = 0;
     115        1309 :         count = pos;
     116        1309 :         pos += 2;
     117             : 
     118             : #ifdef CONFIG_RSN_TESTING
     119             :         if (rsn_testing) {
     120             :                 RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
     121             :                 pos += RSN_SELECTOR_LEN;
     122             :                 num_suites++;
     123             :         }
     124             : #endif /* CONFIG_RSN_TESTING */
     125             : 
     126        1309 :         res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
     127        1309 :         num_suites += res;
     128        1309 :         pos += res * RSN_SELECTOR_LEN;
     129             : 
     130             : #ifdef CONFIG_RSN_TESTING
     131             :         if (rsn_testing) {
     132             :                 RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
     133             :                 pos += RSN_SELECTOR_LEN;
     134             :                 num_suites++;
     135             :         }
     136             : #endif /* CONFIG_RSN_TESTING */
     137             : 
     138        1309 :         if (num_suites == 0) {
     139           0 :                 wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
     140             :                            conf->rsn_pairwise);
     141           0 :                 return -1;
     142             :         }
     143        1309 :         WPA_PUT_LE16(count, num_suites);
     144             : 
     145        1309 :         num_suites = 0;
     146        1309 :         count = pos;
     147        1309 :         pos += 2;
     148             : 
     149             : #ifdef CONFIG_RSN_TESTING
     150             :         if (rsn_testing) {
     151             :                 RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
     152             :                 pos += RSN_SELECTOR_LEN;
     153             :                 num_suites++;
     154             :         }
     155             : #endif /* CONFIG_RSN_TESTING */
     156             : 
     157        1309 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
     158         375 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
     159         375 :                 pos += RSN_SELECTOR_LEN;
     160         375 :                 num_suites++;
     161             :         }
     162        1309 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
     163         427 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
     164         427 :                 pos += RSN_SELECTOR_LEN;
     165         427 :                 num_suites++;
     166             :         }
     167             : #ifdef CONFIG_IEEE80211R
     168        1309 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
     169          14 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
     170          14 :                 pos += RSN_SELECTOR_LEN;
     171          14 :                 num_suites++;
     172             :         }
     173        1309 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
     174         458 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
     175         458 :                 pos += RSN_SELECTOR_LEN;
     176         458 :                 num_suites++;
     177             :         }
     178             : #endif /* CONFIG_IEEE80211R */
     179             : #ifdef CONFIG_IEEE80211W
     180        1309 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
     181           3 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
     182           3 :                 pos += RSN_SELECTOR_LEN;
     183           3 :                 num_suites++;
     184             :         }
     185        1309 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
     186          17 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
     187          17 :                 pos += RSN_SELECTOR_LEN;
     188          17 :                 num_suites++;
     189             :         }
     190             : #endif /* CONFIG_IEEE80211W */
     191             : #ifdef CONFIG_SAE
     192        1309 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
     193          18 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
     194          18 :                 pos += RSN_SELECTOR_LEN;
     195          18 :                 num_suites++;
     196             :         }
     197        1309 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
     198          13 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
     199          13 :                 pos += RSN_SELECTOR_LEN;
     200          13 :                 num_suites++;
     201             :         }
     202             : #endif /* CONFIG_SAE */
     203        1309 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
     204           1 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
     205           1 :                 pos += RSN_SELECTOR_LEN;
     206           1 :                 num_suites++;
     207             :         }
     208        1309 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
     209           1 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
     210           1 :                 pos += RSN_SELECTOR_LEN;
     211           1 :                 num_suites++;
     212             :         }
     213             : 
     214             : #ifdef CONFIG_RSN_TESTING
     215             :         if (rsn_testing) {
     216             :                 RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
     217             :                 pos += RSN_SELECTOR_LEN;
     218             :                 num_suites++;
     219             :         }
     220             : #endif /* CONFIG_RSN_TESTING */
     221             : 
     222        1309 :         if (num_suites == 0) {
     223           0 :                 wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
     224             :                            conf->wpa_key_mgmt);
     225           0 :                 return -1;
     226             :         }
     227        1309 :         WPA_PUT_LE16(count, num_suites);
     228             : 
     229             :         /* RSN Capabilities */
     230        1309 :         capab = 0;
     231        1309 :         if (conf->rsn_preauth)
     232           2 :                 capab |= WPA_CAPABILITY_PREAUTH;
     233        1309 :         if (conf->peerkey)
     234           3 :                 capab |= WPA_CAPABILITY_PEERKEY_ENABLED;
     235        1309 :         if (conf->wmm_enabled) {
     236             :                 /* 4 PTKSA replay counters when using WMM */
     237        1296 :                 capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
     238             :         }
     239             : #ifdef CONFIG_IEEE80211W
     240        1309 :         if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
     241         158 :                 capab |= WPA_CAPABILITY_MFPC;
     242         158 :                 if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
     243          34 :                         capab |= WPA_CAPABILITY_MFPR;
     244             :         }
     245             : #endif /* CONFIG_IEEE80211W */
     246             : #ifdef CONFIG_RSN_TESTING
     247             :         if (rsn_testing)
     248             :                 capab |= BIT(8) | BIT(14) | BIT(15);
     249             : #endif /* CONFIG_RSN_TESTING */
     250        1309 :         WPA_PUT_LE16(pos, capab);
     251        1309 :         pos += 2;
     252             : 
     253        1309 :         if (pmkid) {
     254         442 :                 if (pos + 2 + PMKID_LEN > buf + len)
     255           0 :                         return -1;
     256             :                 /* PMKID Count */
     257         442 :                 WPA_PUT_LE16(pos, 1);
     258         442 :                 pos += 2;
     259         442 :                 os_memcpy(pos, pmkid, PMKID_LEN);
     260         442 :                 pos += PMKID_LEN;
     261             :         }
     262             : 
     263             : #ifdef CONFIG_IEEE80211W
     264        1309 :         if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
     265         158 :                 if (pos + 2 + 4 > buf + len)
     266           0 :                         return -1;
     267         158 :                 if (pmkid == NULL) {
     268             :                         /* PMKID Count */
     269         150 :                         WPA_PUT_LE16(pos, 0);
     270         150 :                         pos += 2;
     271             :                 }
     272             : 
     273             :                 /* Management Group Cipher Suite */
     274         158 :                 switch (conf->group_mgmt_cipher) {
     275             :                 case WPA_CIPHER_AES_128_CMAC:
     276         153 :                         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
     277         153 :                         break;
     278             :                 case WPA_CIPHER_BIP_GMAC_128:
     279           2 :                         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128);
     280           2 :                         break;
     281             :                 case WPA_CIPHER_BIP_GMAC_256:
     282           2 :                         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256);
     283           2 :                         break;
     284             :                 case WPA_CIPHER_BIP_CMAC_256:
     285           1 :                         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_CMAC_256);
     286           1 :                         break;
     287             :                 default:
     288           0 :                         wpa_printf(MSG_DEBUG,
     289             :                                    "Invalid group management cipher (0x%x)",
     290             :                                    conf->group_mgmt_cipher);
     291           0 :                         return -1;
     292             :                 }
     293         158 :                 pos += RSN_SELECTOR_LEN;
     294             :         }
     295             : #endif /* CONFIG_IEEE80211W */
     296             : 
     297             : #ifdef CONFIG_RSN_TESTING
     298             :         if (rsn_testing) {
     299             :                 /*
     300             :                  * Fill in any defined fields and add extra data to the end of
     301             :                  * the element.
     302             :                  */
     303             :                 int pmkid_count_set = pmkid != NULL;
     304             :                 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
     305             :                         pmkid_count_set = 1;
     306             :                 /* PMKID Count */
     307             :                 WPA_PUT_LE16(pos, 0);
     308             :                 pos += 2;
     309             :                 if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
     310             :                         /* Management Group Cipher Suite */
     311             :                         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
     312             :                         pos += RSN_SELECTOR_LEN;
     313             :                 }
     314             : 
     315             :                 os_memset(pos, 0x12, 17);
     316             :                 pos += 17;
     317             :         }
     318             : #endif /* CONFIG_RSN_TESTING */
     319             : 
     320        1309 :         hdr->len = (pos - buf) - 2;
     321             : 
     322        1309 :         return pos - buf;
     323             : }
     324             : 
     325             : 
     326           1 : static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
     327             : {
     328             :         u8 *len;
     329             :         u16 capab;
     330             : 
     331           1 :         *eid++ = WLAN_EID_VENDOR_SPECIFIC;
     332           1 :         len = eid++; /* to be filled */
     333           1 :         WPA_PUT_BE24(eid, OUI_WFA);
     334           1 :         eid += 3;
     335           1 :         *eid++ = HS20_OSEN_OUI_TYPE;
     336             : 
     337             :         /* Group Data Cipher Suite */
     338           1 :         RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
     339           1 :         eid += RSN_SELECTOR_LEN;
     340             : 
     341             :         /* Pairwise Cipher Suite Count and List */
     342           1 :         WPA_PUT_LE16(eid, 1);
     343           1 :         eid += 2;
     344           1 :         RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP);
     345           1 :         eid += RSN_SELECTOR_LEN;
     346             : 
     347             :         /* AKM Suite Count and List */
     348           1 :         WPA_PUT_LE16(eid, 1);
     349           1 :         eid += 2;
     350           1 :         RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN);
     351           1 :         eid += RSN_SELECTOR_LEN;
     352             : 
     353             :         /* RSN Capabilities */
     354           1 :         capab = 0;
     355           1 :         if (conf->wmm_enabled) {
     356             :                 /* 4 PTKSA replay counters when using WMM */
     357           1 :                 capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
     358             :         }
     359             : #ifdef CONFIG_IEEE80211W
     360           1 :         if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
     361           1 :                 capab |= WPA_CAPABILITY_MFPC;
     362           1 :                 if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
     363           0 :                         capab |= WPA_CAPABILITY_MFPR;
     364             :         }
     365             : #endif /* CONFIG_IEEE80211W */
     366           1 :         WPA_PUT_LE16(eid, capab);
     367           1 :         eid += 2;
     368             : 
     369           1 :         *len = eid - len - 1;
     370             : 
     371           1 :         return eid;
     372             : }
     373             : 
     374             : 
     375         879 : int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
     376             : {
     377             :         u8 *pos, buf[128];
     378             :         int res;
     379             : 
     380         879 :         pos = buf;
     381             : 
     382         879 :         if (wpa_auth->conf.wpa == WPA_PROTO_OSEN) {
     383           1 :                 pos = wpa_write_osen(&wpa_auth->conf, pos);
     384             :         }
     385         879 :         if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
     386         867 :                 res = wpa_write_rsn_ie(&wpa_auth->conf,
     387         867 :                                        pos, buf + sizeof(buf) - pos, NULL);
     388         867 :                 if (res < 0)
     389           0 :                         return res;
     390         867 :                 pos += res;
     391             :         }
     392             : #ifdef CONFIG_IEEE80211R
     393         879 :         if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
     394          41 :                 res = wpa_write_mdie(&wpa_auth->conf, pos,
     395          41 :                                      buf + sizeof(buf) - pos);
     396          41 :                 if (res < 0)
     397           0 :                         return res;
     398          41 :                 pos += res;
     399             :         }
     400             : #endif /* CONFIG_IEEE80211R */
     401         879 :         if (wpa_auth->conf.wpa & WPA_PROTO_WPA) {
     402          31 :                 res = wpa_write_wpa_ie(&wpa_auth->conf,
     403          31 :                                        pos, buf + sizeof(buf) - pos);
     404          31 :                 if (res < 0)
     405           0 :                         return res;
     406          31 :                 pos += res;
     407             :         }
     408             : 
     409         879 :         os_free(wpa_auth->wpa_ie);
     410         879 :         wpa_auth->wpa_ie = os_malloc(pos - buf);
     411         879 :         if (wpa_auth->wpa_ie == NULL)
     412           0 :                 return -1;
     413         879 :         os_memcpy(wpa_auth->wpa_ie, buf, pos - buf);
     414         879 :         wpa_auth->wpa_ie_len = pos - buf;
     415             : 
     416         879 :         return 0;
     417             : }
     418             : 
     419             : 
     420        1436 : u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
     421             :                  const u8 *data2, size_t data2_len)
     422             : {
     423        1436 :         *pos++ = WLAN_EID_VENDOR_SPECIFIC;
     424        1436 :         *pos++ = RSN_SELECTOR_LEN + data_len + data2_len;
     425        1436 :         RSN_SELECTOR_PUT(pos, kde);
     426        1436 :         pos += RSN_SELECTOR_LEN;
     427        1436 :         os_memcpy(pos, data, data_len);
     428        1436 :         pos += data_len;
     429        1436 :         if (data2) {
     430        1292 :                 os_memcpy(pos, data2, data2_len);
     431        1292 :                 pos += data2_len;
     432             :         }
     433        1436 :         return pos;
     434             : }
     435             : 
     436             : 
     437             : struct wpa_auth_okc_iter_data {
     438             :         struct rsn_pmksa_cache_entry *pmksa;
     439             :         const u8 *aa;
     440             :         const u8 *spa;
     441             :         const u8 *pmkid;
     442             : };
     443             : 
     444             : 
     445           6 : static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx)
     446             : {
     447           6 :         struct wpa_auth_okc_iter_data *data = ctx;
     448           6 :         data->pmksa = pmksa_cache_get_okc(a->pmksa, data->aa, data->spa,
     449             :                                           data->pmkid);
     450           6 :         if (data->pmksa)
     451           6 :                 return 1;
     452           0 :         return 0;
     453             : }
     454             : 
     455             : 
     456        1869 : int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
     457             :                         struct wpa_state_machine *sm,
     458             :                         const u8 *wpa_ie, size_t wpa_ie_len,
     459             :                         const u8 *mdie, size_t mdie_len)
     460             : {
     461             :         struct wpa_ie_data data;
     462             :         int ciphers, key_mgmt, res, version;
     463             :         u32 selector;
     464             :         size_t i;
     465        1869 :         const u8 *pmkid = NULL;
     466             : 
     467        1869 :         if (wpa_auth == NULL || sm == NULL)
     468           0 :                 return WPA_NOT_ENABLED;
     469             : 
     470        1869 :         if (wpa_ie == NULL || wpa_ie_len < 1)
     471           0 :                 return WPA_INVALID_IE;
     472             : 
     473        1869 :         if (wpa_ie[0] == WLAN_EID_RSN)
     474        1852 :                 version = WPA_PROTO_RSN;
     475             :         else
     476          17 :                 version = WPA_PROTO_WPA;
     477             : 
     478        1869 :         if (!(wpa_auth->conf.wpa & version)) {
     479           0 :                 wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR,
     480           0 :                            version, MAC2STR(sm->addr));
     481           0 :                 return WPA_INVALID_PROTO;
     482             :         }
     483             : 
     484        1869 :         if (version == WPA_PROTO_RSN) {
     485        1852 :                 res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data);
     486             : 
     487        1852 :                 selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
     488             :                 if (0) {
     489             :                 }
     490        1852 :                 else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
     491           2 :                         selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
     492        1850 :                 else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
     493           2 :                         selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
     494             : #ifdef CONFIG_IEEE80211R
     495        1848 :                 else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
     496           8 :                         selector = RSN_AUTH_KEY_MGMT_FT_802_1X;
     497        1840 :                 else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK)
     498         230 :                         selector = RSN_AUTH_KEY_MGMT_FT_PSK;
     499             : #endif /* CONFIG_IEEE80211R */
     500             : #ifdef CONFIG_IEEE80211W
     501        1610 :                 else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
     502           4 :                         selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
     503        1606 :                 else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
     504          26 :                         selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
     505             : #endif /* CONFIG_IEEE80211W */
     506             : #ifdef CONFIG_SAE
     507        1580 :                 else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
     508          26 :                         selector = RSN_AUTH_KEY_MGMT_SAE;
     509        1554 :                 else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE)
     510           7 :                         selector = RSN_AUTH_KEY_MGMT_FT_SAE;
     511             : #endif /* CONFIG_SAE */
     512        1547 :                 else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
     513         956 :                         selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
     514         591 :                 else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
     515         591 :                         selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
     516        1852 :                 wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
     517             : 
     518        1852 :                 selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
     519             :                                                data.pairwise_cipher);
     520        1852 :                 if (!selector)
     521           0 :                         selector = RSN_CIPHER_SUITE_CCMP;
     522        1852 :                 wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
     523             : 
     524        1852 :                 selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
     525             :                                                data.group_cipher);
     526        1852 :                 if (!selector)
     527           0 :                         selector = RSN_CIPHER_SUITE_CCMP;
     528        1852 :                 wpa_auth->dot11RSNAGroupCipherSelected = selector;
     529             :         } else {
     530          17 :                 res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data);
     531             : 
     532          17 :                 selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
     533          17 :                 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
     534           2 :                         selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
     535          15 :                 else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
     536          15 :                         selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
     537          17 :                 wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
     538             : 
     539          17 :                 selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
     540             :                                                data.pairwise_cipher);
     541          17 :                 if (!selector)
     542           0 :                         selector = RSN_CIPHER_SUITE_TKIP;
     543          17 :                 wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
     544             : 
     545          17 :                 selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
     546             :                                                data.group_cipher);
     547          17 :                 if (!selector)
     548           0 :                         selector = WPA_CIPHER_SUITE_TKIP;
     549          17 :                 wpa_auth->dot11RSNAGroupCipherSelected = selector;
     550             :         }
     551        1869 :         if (res) {
     552           0 :                 wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from "
     553           0 :                            MACSTR " (res=%d)", MAC2STR(sm->addr), res);
     554           0 :                 wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len);
     555           0 :                 return WPA_INVALID_IE;
     556             :         }
     557             : 
     558        1869 :         if (data.group_cipher != wpa_auth->conf.wpa_group) {
     559           0 :                 wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from "
     560           0 :                            MACSTR, data.group_cipher, MAC2STR(sm->addr));
     561           0 :                 return WPA_INVALID_GROUP;
     562             :         }
     563             : 
     564        1869 :         key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
     565        1869 :         if (!key_mgmt) {
     566           0 :                 wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
     567           0 :                            MACSTR, data.key_mgmt, MAC2STR(sm->addr));
     568           0 :                 return WPA_INVALID_AKMP;
     569             :         }
     570             :         if (0) {
     571             :         }
     572        1869 :         else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
     573           2 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
     574        1867 :         else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
     575           2 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
     576             : #ifdef CONFIG_IEEE80211R
     577        1865 :         else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
     578           8 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
     579        1857 :         else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
     580         230 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
     581             : #endif /* CONFIG_IEEE80211R */
     582             : #ifdef CONFIG_IEEE80211W
     583        1627 :         else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
     584           4 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
     585        1623 :         else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
     586          26 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
     587             : #endif /* CONFIG_IEEE80211W */
     588             : #ifdef CONFIG_SAE
     589        1597 :         else if (key_mgmt & WPA_KEY_MGMT_SAE)
     590          26 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE;
     591        1571 :         else if (key_mgmt & WPA_KEY_MGMT_FT_SAE)
     592           7 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE;
     593             : #endif /* CONFIG_SAE */
     594        1564 :         else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
     595         958 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
     596             :         else
     597         606 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
     598             : 
     599        1869 :         if (version == WPA_PROTO_RSN)
     600        1852 :                 ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
     601             :         else
     602          17 :                 ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
     603        1869 :         if (!ciphers) {
     604           0 :                 wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) "
     605             :                            "from " MACSTR,
     606             :                            version == WPA_PROTO_RSN ? "RSN" : "WPA",
     607           0 :                            data.pairwise_cipher, MAC2STR(sm->addr));
     608           0 :                 return WPA_INVALID_PAIRWISE;
     609             :         }
     610             : 
     611             : #ifdef CONFIG_IEEE80211W
     612        1869 :         if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
     613          37 :                 if (!(data.capabilities & WPA_CAPABILITY_MFPC)) {
     614           0 :                         wpa_printf(MSG_DEBUG, "Management frame protection "
     615             :                                    "required, but client did not enable it");
     616           0 :                         return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
     617             :                 }
     618             : 
     619          37 :                 if (ciphers & WPA_CIPHER_TKIP) {
     620           0 :                         wpa_printf(MSG_DEBUG, "Management frame protection "
     621             :                                    "cannot use TKIP");
     622           0 :                         return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
     623             :                 }
     624             : 
     625          37 :                 if (data.mgmt_group_cipher != wpa_auth->conf.group_mgmt_cipher)
     626             :                 {
     627           1 :                         wpa_printf(MSG_DEBUG, "Unsupported management group "
     628             :                                    "cipher %d", data.mgmt_group_cipher);
     629           1 :                         return WPA_INVALID_MGMT_GROUP_CIPHER;
     630             :                 }
     631             :         }
     632             : 
     633        2007 :         if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
     634         139 :             !(data.capabilities & WPA_CAPABILITY_MFPC))
     635        1817 :                 sm->mgmt_frame_prot = 0;
     636             :         else
     637          51 :                 sm->mgmt_frame_prot = 1;
     638             : #endif /* CONFIG_IEEE80211W */
     639             : 
     640             : #ifdef CONFIG_IEEE80211R
     641        1868 :         if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
     642         245 :                 if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) {
     643           0 :                         wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but "
     644             :                                    "MDIE not included");
     645           0 :                         return WPA_INVALID_MDIE;
     646             :                 }
     647         245 :                 if (os_memcmp(mdie, wpa_auth->conf.mobility_domain,
     648             :                               MOBILITY_DOMAIN_ID_LEN) != 0) {
     649           0 :                         wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown "
     650             :                                     "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN);
     651           0 :                         return WPA_INVALID_MDIE;
     652             :                 }
     653             :         }
     654             : #endif /* CONFIG_IEEE80211R */
     655             : 
     656        1868 :         sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0);
     657        1868 :         if (sm->pairwise < 0)
     658           0 :                 return WPA_INVALID_PAIRWISE;
     659             : 
     660             :         /* TODO: clear WPA/WPA2 state if STA changes from one to another */
     661        1868 :         if (wpa_ie[0] == WLAN_EID_RSN)
     662        1851 :                 sm->wpa = WPA_VERSION_WPA2;
     663             :         else
     664          17 :                 sm->wpa = WPA_VERSION_WPA;
     665             : 
     666        1868 :         sm->pmksa = NULL;
     667        2131 :         for (i = 0; i < data.num_pmkid; i++) {
     668         287 :                 wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID",
     669         287 :                             &data.pmkid[i * PMKID_LEN], PMKID_LEN);
     670         287 :                 sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr,
     671         287 :                                                  &data.pmkid[i * PMKID_LEN]);
     672         287 :                 if (sm->pmksa) {
     673          24 :                         pmkid = sm->pmksa->pmkid;
     674          24 :                         break;
     675             :                 }
     676             :         }
     677        3748 :         for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc &&
     678          12 :                      i < data.num_pmkid; i++) {
     679             :                 struct wpa_auth_okc_iter_data idata;
     680           6 :                 idata.pmksa = NULL;
     681           6 :                 idata.aa = wpa_auth->addr;
     682           6 :                 idata.spa = sm->addr;
     683           6 :                 idata.pmkid = &data.pmkid[i * PMKID_LEN];
     684           6 :                 wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata);
     685           6 :                 if (idata.pmksa) {
     686           6 :                         wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
     687             :                                          "OKC match for PMKID");
     688          12 :                         sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa,
     689           6 :                                                         idata.pmksa,
     690           6 :                                                         wpa_auth->addr,
     691             :                                                         idata.pmkid);
     692           6 :                         pmkid = idata.pmkid;
     693           6 :                         break;
     694             :                 }
     695             :         }
     696        1868 :         if (sm->pmksa && pmkid) {
     697          60 :                 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
     698             :                                  "PMKID found from PMKSA cache "
     699             :                                  "eap_type=%d vlan_id=%d",
     700          30 :                                  sm->pmksa->eap_type_authsrv,
     701          30 :                                  sm->pmksa->vlan_id);
     702          30 :                 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN);
     703             :         }
     704             : 
     705        1868 :         if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
     706        1607 :                 os_free(sm->wpa_ie);
     707        1607 :                 sm->wpa_ie = os_malloc(wpa_ie_len);
     708        1607 :                 if (sm->wpa_ie == NULL)
     709           0 :                         return WPA_ALLOC_FAIL;
     710             :         }
     711        1868 :         os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len);
     712        1868 :         sm->wpa_ie_len = wpa_ie_len;
     713             : 
     714        1868 :         return WPA_IE_OK;
     715             : }
     716             : 
     717             : 
     718             : #ifdef CONFIG_HS20
     719           2 : int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
     720             :                       struct wpa_state_machine *sm,
     721             :                       const u8 *osen_ie, size_t osen_ie_len)
     722             : {
     723           2 :         if (wpa_auth == NULL || sm == NULL)
     724           0 :                 return -1;
     725             : 
     726             :         /* TODO: parse OSEN element */
     727           2 :         sm->wpa_key_mgmt = WPA_KEY_MGMT_OSEN;
     728           2 :         sm->mgmt_frame_prot = 1;
     729           2 :         sm->pairwise = WPA_CIPHER_CCMP;
     730           2 :         sm->wpa = WPA_VERSION_WPA2;
     731             : 
     732           2 :         if (sm->wpa_ie == NULL || sm->wpa_ie_len < osen_ie_len) {
     733           2 :                 os_free(sm->wpa_ie);
     734           2 :                 sm->wpa_ie = os_malloc(osen_ie_len);
     735           2 :                 if (sm->wpa_ie == NULL)
     736           0 :                         return -1;
     737             :         }
     738             : 
     739           2 :         os_memcpy(sm->wpa_ie, osen_ie, osen_ie_len);
     740           2 :         sm->wpa_ie_len = osen_ie_len;
     741             : 
     742           2 :         return 0;
     743             : }
     744             : 
     745             : #endif /* CONFIG_HS20 */
     746             : 
     747             : 
     748             : /**
     749             :  * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
     750             :  * @pos: Pointer to the IE header
     751             :  * @end: Pointer to the end of the Key Data buffer
     752             :  * @ie: Pointer to parsed IE data
     753             :  * Returns: 0 on success, 1 if end mark is found, -1 on failure
     754             :  */
     755         233 : static int wpa_parse_generic(const u8 *pos, const u8 *end,
     756             :                              struct wpa_eapol_ie_parse *ie)
     757             : {
     758         233 :         if (pos[1] == 0)
     759           0 :                 return 1;
     760             : 
     761         267 :         if (pos[1] >= 6 &&
     762          56 :             RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
     763          44 :             pos[2 + WPA_SELECTOR_LEN] == 1 &&
     764          22 :             pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
     765          22 :                 ie->wpa_ie = pos;
     766          22 :                 ie->wpa_ie_len = pos[1] + 2;
     767          22 :                 return 0;
     768             :         }
     769             : 
     770         211 :         if (pos[1] >= 4 && WPA_GET_BE32(pos + 2) == OSEN_IE_VENDOR_TYPE) {
     771           2 :                 ie->osen = pos;
     772           2 :                 ie->osen_len = pos[1] + 2;
     773           2 :                 return 0;
     774             :         }
     775             : 
     776         418 :         if (pos + 1 + RSN_SELECTOR_LEN < end &&
     777         210 :             pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
     778           1 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
     779           0 :                 ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
     780           0 :                 return 0;
     781             :         }
     782             : 
     783         219 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     784          10 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
     785           0 :                 ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
     786           0 :                 ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
     787           0 :                 return 0;
     788             :         }
     789             : 
     790         219 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     791          10 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
     792           7 :                 ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
     793           7 :                 ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
     794           7 :                 return 0;
     795             :         }
     796             : 
     797             : #ifdef CONFIG_PEERKEY
     798         205 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     799           3 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) {
     800           0 :                 ie->smk = pos + 2 + RSN_SELECTOR_LEN;
     801           0 :                 ie->smk_len = pos[1] - RSN_SELECTOR_LEN;
     802           0 :                 return 0;
     803             :         }
     804             : 
     805         205 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     806           3 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) {
     807           1 :                 ie->nonce = pos + 2 + RSN_SELECTOR_LEN;
     808           1 :                 ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;
     809           1 :                 return 0;
     810             :         }
     811             : 
     812         203 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     813           2 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) {
     814           0 :                 ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;
     815           0 :                 ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;
     816           0 :                 return 0;
     817             :         }
     818             : 
     819         203 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     820           2 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) {
     821           2 :                 ie->error = pos + 2 + RSN_SELECTOR_LEN;
     822           2 :                 ie->error_len = pos[1] - RSN_SELECTOR_LEN;
     823           2 :                 return 0;
     824             :         }
     825             : #endif /* CONFIG_PEERKEY */
     826             : 
     827             : #ifdef CONFIG_IEEE80211W
     828         199 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     829           0 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
     830           0 :                 ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
     831           0 :                 ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
     832           0 :                 return 0;
     833             :         }
     834             : #endif /* CONFIG_IEEE80211W */
     835             : 
     836             : #ifdef CONFIG_P2P
     837         398 :         if (pos[1] >= RSN_SELECTOR_LEN + 1 &&
     838         199 :             RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) {
     839         199 :                 ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN;
     840         398 :                 wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key",
     841         398 :                             ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN);
     842         199 :                 return 0;
     843             :         }
     844             : 
     845           0 :         if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 &&
     846           0 :             RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) {
     847           0 :                 ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN;
     848           0 :                 wpa_hexdump(MSG_DEBUG,
     849             :                             "WPA: IP Address Allocation in EAPOL-Key",
     850           0 :                             ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN);
     851           0 :                 return 0;
     852             :         }
     853             : #endif /* CONFIG_P2P */
     854             : 
     855           0 :         return 0;
     856             : }
     857             : 
     858             : 
     859             : /**
     860             :  * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs
     861             :  * @buf: Pointer to the Key Data buffer
     862             :  * @len: Key Data Length
     863             :  * @ie: Pointer to parsed IE data
     864             :  * Returns: 0 on success, -1 on failure
     865             :  */
     866        1331 : int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
     867             : {
     868             :         const u8 *pos, *end;
     869        1331 :         int ret = 0;
     870             : 
     871        1331 :         os_memset(ie, 0, sizeof(*ie));
     872        2917 :         for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
     873        1819 :                 if (pos[0] == 0xdd &&
     874         466 :                     ((pos == buf + len - 1) || pos[1] == 0)) {
     875             :                         /* Ignore padding */
     876             :                         break;
     877             :                 }
     878        1586 :                 if (pos + 2 + pos[1] > end) {
     879           0 :                         wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
     880             :                                    "underflow (ie=%d len=%d pos=%d)",
     881           0 :                                    pos[0], pos[1], (int) (pos - buf));
     882           0 :                         wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
     883             :                                         buf, len);
     884           0 :                         ret = -1;
     885           0 :                         break;
     886             :                 }
     887        1586 :                 if (*pos == WLAN_EID_RSN) {
     888        1305 :                         ie->rsn_ie = pos;
     889        1305 :                         ie->rsn_ie_len = pos[1] + 2;
     890             : #ifdef CONFIG_IEEE80211R
     891         281 :                 } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
     892          24 :                         ie->mdie = pos;
     893          24 :                         ie->mdie_len = pos[1] + 2;
     894         257 :                 } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
     895          24 :                         ie->ftie = pos;
     896          24 :                         ie->ftie_len = pos[1] + 2;
     897             : #endif /* CONFIG_IEEE80211R */
     898         233 :                 } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
     899         233 :                         ret = wpa_parse_generic(pos, end, ie);
     900         233 :                         if (ret < 0)
     901           0 :                                 break;
     902         233 :                         if (ret > 0) {
     903           0 :                                 ret = 0;
     904           0 :                                 break;
     905             :                         }
     906             :                 } else {
     907           0 :                         wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
     908           0 :                                     "Key Data IE", pos, 2 + pos[1]);
     909             :                 }
     910             :         }
     911             : 
     912        1331 :         return ret;
     913             : }
     914             : 
     915             : 
     916        1868 : int wpa_auth_uses_mfp(struct wpa_state_machine *sm)
     917             : {
     918        1868 :         return sm ? sm->mgmt_frame_prot : 0;
     919             : }

Generated by: LCOV version 1.10