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

Generated by: LCOV version 1.10