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 1443382998 Lines: 422 508 83.1 %
Date: 2015-09-27 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          36 : 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          36 :         hdr = (struct wpa_ie_hdr *) buf;
      35          36 :         hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
      36          36 :         RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE);
      37          36 :         WPA_PUT_LE16(hdr->version, WPA_VERSION);
      38          36 :         pos = (u8 *) (hdr + 1);
      39             : 
      40          36 :         suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group);
      41          36 :         if (suite == 0) {
      42           0 :                 wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
      43             :                            conf->wpa_group);
      44           0 :                 return -1;
      45             :         }
      46          36 :         RSN_SELECTOR_PUT(pos, suite);
      47          36 :         pos += WPA_SELECTOR_LEN;
      48             : 
      49          36 :         count = pos;
      50          36 :         pos += 2;
      51             : 
      52          36 :         num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise);
      53          36 :         if (num_suites == 0) {
      54           0 :                 wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
      55             :                            conf->wpa_pairwise);
      56           0 :                 return -1;
      57             :         }
      58          36 :         pos += num_suites * WPA_SELECTOR_LEN;
      59          36 :         WPA_PUT_LE16(count, num_suites);
      60             : 
      61          36 :         num_suites = 0;
      62          36 :         count = pos;
      63          36 :         pos += 2;
      64             : 
      65          36 :         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          36 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
      71          33 :                 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
      72          33 :                 pos += WPA_SELECTOR_LEN;
      73          33 :                 num_suites++;
      74             :         }
      75             : 
      76          36 :         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          36 :         WPA_PUT_LE16(count, num_suites);
      82             : 
      83             :         /* WPA Capabilities; use defaults, so no need to include it */
      84             : 
      85          36 :         hdr->len = (pos - buf) - 2;
      86             : 
      87          36 :         return pos - buf;
      88             : }
      89             : 
      90             : 
      91        1709 : 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        1709 :         hdr = (struct rsn_ie_hdr *) buf;
     101        1709 :         hdr->elem_id = WLAN_EID_RSN;
     102        1709 :         WPA_PUT_LE16(hdr->version, RSN_VERSION);
     103        1709 :         pos = (u8 *) (hdr + 1);
     104             : 
     105        1709 :         suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
     106        1709 :         if (suite == 0) {
     107           0 :                 wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
     108             :                            conf->wpa_group);
     109           0 :                 return -1;
     110             :         }
     111        1709 :         RSN_SELECTOR_PUT(pos, suite);
     112        1709 :         pos += RSN_SELECTOR_LEN;
     113             : 
     114        1709 :         num_suites = 0;
     115        1709 :         count = pos;
     116        1709 :         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        1709 :         res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
     127        1709 :         num_suites += res;
     128        1709 :         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        1709 :         if (num_suites == 0) {
     139           0 :                 wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
     140             :                            conf->rsn_pairwise);
     141           0 :                 return -1;
     142             :         }
     143        1709 :         WPA_PUT_LE16(count, num_suites);
     144             : 
     145        1709 :         num_suites = 0;
     146        1709 :         count = pos;
     147        1709 :         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        1709 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
     158         436 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
     159         436 :                 pos += RSN_SELECTOR_LEN;
     160         436 :                 num_suites++;
     161             :         }
     162        1709 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
     163         730 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
     164         730 :                 pos += RSN_SELECTOR_LEN;
     165         730 :                 num_suites++;
     166             :         }
     167             : #ifdef CONFIG_IEEE80211R
     168        1709 :         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        1709 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
     174         477 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
     175         477 :                 pos += RSN_SELECTOR_LEN;
     176         477 :                 num_suites++;
     177             :         }
     178             : #endif /* CONFIG_IEEE80211R */
     179             : #ifdef CONFIG_IEEE80211W
     180        1709 :         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        1709 :         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        1709 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
     193          33 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
     194          33 :                 pos += RSN_SELECTOR_LEN;
     195          33 :                 num_suites++;
     196             :         }
     197        1709 :         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        1709 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
     204           2 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
     205           2 :                 pos += RSN_SELECTOR_LEN;
     206           2 :                 num_suites++;
     207             :         }
     208        1709 :         if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
     209           2 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
     210           2 :                 pos += RSN_SELECTOR_LEN;
     211           2 :                 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        1709 :         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        1709 :         WPA_PUT_LE16(count, num_suites);
     228             : 
     229             :         /* RSN Capabilities */
     230        1709 :         capab = 0;
     231        1709 :         if (conf->rsn_preauth)
     232           4 :                 capab |= WPA_CAPABILITY_PREAUTH;
     233        1709 :         if (conf->peerkey)
     234           3 :                 capab |= WPA_CAPABILITY_PEERKEY_ENABLED;
     235        1709 :         if (conf->wmm_enabled) {
     236             :                 /* 4 PTKSA replay counters when using WMM */
     237        1689 :                 capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
     238             :         }
     239             : #ifdef CONFIG_IEEE80211W
     240        1709 :         if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
     241         168 :                 capab |= WPA_CAPABILITY_MFPC;
     242         168 :                 if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
     243          36 :                         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        1709 :         WPA_PUT_LE16(pos, capab);
     251        1709 :         pos += 2;
     252             : 
     253        1709 :         if (pmkid) {
     254         450 :                 if (pos + 2 + PMKID_LEN > buf + len)
     255           0 :                         return -1;
     256             :                 /* PMKID Count */
     257         450 :                 WPA_PUT_LE16(pos, 1);
     258         450 :                 pos += 2;
     259         450 :                 os_memcpy(pos, pmkid, PMKID_LEN);
     260         450 :                 pos += PMKID_LEN;
     261             :         }
     262             : 
     263             : #ifdef CONFIG_IEEE80211W
     264        1877 :         if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
     265         168 :             conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
     266           7 :                 if (pos + 2 + 4 > buf + len)
     267           0 :                         return -1;
     268           7 :                 if (pmkid == NULL) {
     269             :                         /* PMKID Count */
     270           7 :                         WPA_PUT_LE16(pos, 0);
     271           7 :                         pos += 2;
     272             :                 }
     273             : 
     274             :                 /* Management Group Cipher Suite */
     275           7 :                 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           3 :                         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128);
     281           3 :                         break;
     282             :                 case WPA_CIPHER_BIP_GMAC_256:
     283           3 :                         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256);
     284           3 :                         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           7 :                 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        1709 :         hdr->len = (pos - buf) - 2;
     322             : 
     323        1709 :         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        1295 : 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        1295 :         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        1274 :         pos = buf;
     399             : 
     400        1274 :         if (wpa_auth->conf.wpa == WPA_PROTO_OSEN) {
     401           1 :                 pos = wpa_write_osen(&wpa_auth->conf, pos);
     402             :         }
     403        1274 :         if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
     404        1259 :                 res = wpa_write_rsn_ie(&wpa_auth->conf,
     405        1259 :                                        pos, buf + sizeof(buf) - pos, NULL);
     406        1259 :                 if (res < 0)
     407           0 :                         return res;
     408        1259 :                 pos += res;
     409             :         }
     410             : #ifdef CONFIG_IEEE80211R
     411        1274 :         if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
     412          52 :                 res = wpa_write_mdie(&wpa_auth->conf, pos,
     413          52 :                                      buf + sizeof(buf) - pos);
     414          52 :                 if (res < 0)
     415           0 :                         return res;
     416          52 :                 pos += res;
     417             :         }
     418             : #endif /* CONFIG_IEEE80211R */
     419        1274 :         if (wpa_auth->conf.wpa & WPA_PROTO_WPA) {
     420          36 :                 res = wpa_write_wpa_ie(&wpa_auth->conf,
     421          36 :                                        pos, buf + sizeof(buf) - pos);
     422          36 :                 if (res < 0)
     423           0 :                         return res;
     424          36 :                 pos += res;
     425             :         }
     426             : 
     427        1274 :         os_free(wpa_auth->wpa_ie);
     428        1274 :         wpa_auth->wpa_ie = os_malloc(pos - buf);
     429        1274 :         if (wpa_auth->wpa_ie == NULL)
     430           0 :                 return -1;
     431        1274 :         os_memcpy(wpa_auth->wpa_ie, buf, pos - buf);
     432        1274 :         wpa_auth->wpa_ie_len = pos - buf;
     433             : 
     434        1274 :         return 0;
     435             : }
     436             : 
     437             : 
     438        1718 : 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        1718 :         *pos++ = WLAN_EID_VENDOR_SPECIFIC;
     442        1718 :         *pos++ = RSN_SELECTOR_LEN + data_len + data2_len;
     443        1718 :         RSN_SELECTOR_PUT(pos, kde);
     444        1718 :         pos += RSN_SELECTOR_LEN;
     445        1718 :         os_memcpy(pos, data, data_len);
     446        1718 :         pos += data_len;
     447        1718 :         if (data2) {
     448        1551 :                 os_memcpy(pos, data2, data2_len);
     449        1551 :                 pos += data2_len;
     450             :         }
     451        1718 :         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        2242 : 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        2242 :         const u8 *pmkid = NULL;
     484             : 
     485        2242 :         if (wpa_auth == NULL || sm == NULL)
     486           0 :                 return WPA_NOT_ENABLED;
     487             : 
     488        2242 :         if (wpa_ie == NULL || wpa_ie_len < 1)
     489           0 :                 return WPA_INVALID_IE;
     490             : 
     491        2242 :         if (wpa_ie[0] == WLAN_EID_RSN)
     492        2198 :                 version = WPA_PROTO_RSN;
     493             :         else
     494          44 :                 version = WPA_PROTO_WPA;
     495             : 
     496        2242 :         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        2242 :         if (version == WPA_PROTO_RSN) {
     503        2198 :                 res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data);
     504             : 
     505        2198 :                 selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
     506             :                 if (0) {
     507             :                 }
     508        2198 :                 else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
     509           3 :                         selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
     510        2195 :                 else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
     511           3 :                         selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
     512             : #ifdef CONFIG_IEEE80211R
     513        2192 :                 else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
     514           8 :                         selector = RSN_AUTH_KEY_MGMT_FT_802_1X;
     515        2184 :                 else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK)
     516         257 :                         selector = RSN_AUTH_KEY_MGMT_FT_PSK;
     517             : #endif /* CONFIG_IEEE80211R */
     518             : #ifdef CONFIG_IEEE80211W
     519        1927 :                 else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
     520           5 :                         selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
     521        1922 :                 else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
     522          23 :                         selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
     523             : #endif /* CONFIG_IEEE80211W */
     524             : #ifdef CONFIG_SAE
     525        1899 :                 else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
     526          59 :                         selector = RSN_AUTH_KEY_MGMT_SAE;
     527        1840 :                 else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE)
     528           7 :                         selector = RSN_AUTH_KEY_MGMT_FT_SAE;
     529             : #endif /* CONFIG_SAE */
     530        1833 :                 else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
     531        1137 :                         selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
     532         696 :                 else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
     533         696 :                         selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
     534        2198 :                 wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
     535             : 
     536        2198 :                 selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
     537             :                                                data.pairwise_cipher);
     538        2198 :                 if (!selector)
     539           0 :                         selector = RSN_CIPHER_SUITE_CCMP;
     540        2198 :                 wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
     541             : 
     542        2198 :                 selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
     543             :                                                data.group_cipher);
     544        2198 :                 if (!selector)
     545           0 :                         selector = RSN_CIPHER_SUITE_CCMP;
     546        2198 :                 wpa_auth->dot11RSNAGroupCipherSelected = selector;
     547             :         } else {
     548          44 :                 res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data);
     549             : 
     550          44 :                 selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
     551          44 :                 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
     552          19 :                         selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
     553          25 :                 else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
     554          19 :                         selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
     555          44 :                 wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
     556             : 
     557          44 :                 selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
     558             :                                                data.pairwise_cipher);
     559          44 :                 if (!selector)
     560           6 :                         selector = RSN_CIPHER_SUITE_TKIP;
     561          44 :                 wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
     562             : 
     563          44 :                 selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
     564             :                                                data.group_cipher);
     565          44 :                 if (!selector)
     566           0 :                         selector = WPA_CIPHER_SUITE_TKIP;
     567          44 :                 wpa_auth->dot11RSNAGroupCipherSelected = selector;
     568             :         }
     569        2242 :         if (res) {
     570         120 :                 wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from "
     571         120 :                            MACSTR " (res=%d)", MAC2STR(sm->addr), res);
     572          20 :                 wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len);
     573          20 :                 return WPA_INVALID_IE;
     574             :         }
     575             : 
     576        2222 :         if (data.group_cipher != wpa_auth->conf.wpa_group) {
     577           0 :                 wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from "
     578           0 :                            MACSTR, data.group_cipher, MAC2STR(sm->addr));
     579           0 :                 return WPA_INVALID_GROUP;
     580             :         }
     581             : 
     582        2222 :         key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
     583        2222 :         if (!key_mgmt) {
     584          18 :                 wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
     585          18 :                            MACSTR, data.key_mgmt, MAC2STR(sm->addr));
     586           3 :                 return WPA_INVALID_AKMP;
     587             :         }
     588             :         if (0) {
     589             :         }
     590        2219 :         else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
     591           3 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
     592        2216 :         else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
     593           3 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
     594             : #ifdef CONFIG_IEEE80211R
     595        2213 :         else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
     596           8 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
     597        2205 :         else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
     598         257 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
     599             : #endif /* CONFIG_IEEE80211R */
     600             : #ifdef CONFIG_IEEE80211W
     601        1948 :         else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
     602           5 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
     603        1943 :         else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
     604          23 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
     605             : #endif /* CONFIG_IEEE80211W */
     606             : #ifdef CONFIG_SAE
     607        1920 :         else if (key_mgmt & WPA_KEY_MGMT_SAE)
     608          59 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE;
     609        1861 :         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        1854 :         else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
     613        1139 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
     614             :         else
     615         715 :                 sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
     616             : 
     617        2219 :         if (version == WPA_PROTO_RSN)
     618        2198 :                 ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
     619             :         else
     620          21 :                 ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
     621        2219 :         if (!ciphers) {
     622           0 :                 wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) "
     623             :                            "from " MACSTR,
     624             :                            version == WPA_PROTO_RSN ? "RSN" : "WPA",
     625           0 :                            data.pairwise_cipher, MAC2STR(sm->addr));
     626           0 :                 return WPA_INVALID_PAIRWISE;
     627             :         }
     628             : 
     629             : #ifdef CONFIG_IEEE80211W
     630        2219 :         if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
     631          37 :                 if (!(data.capabilities & WPA_CAPABILITY_MFPC)) {
     632           0 :                         wpa_printf(MSG_DEBUG, "Management frame protection "
     633             :                                    "required, but client did not enable it");
     634           0 :                         return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
     635             :                 }
     636             : 
     637          37 :                 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          37 :                 if (data.mgmt_group_cipher != wpa_auth->conf.group_mgmt_cipher)
     644             :                 {
     645           0 :                         wpa_printf(MSG_DEBUG, "Unsupported management group "
     646             :                                    "cipher %d", data.mgmt_group_cipher);
     647           0 :                         return WPA_INVALID_MGMT_GROUP_CIPHER;
     648             :                 }
     649             :         }
     650             : 
     651        2375 :         if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
     652         156 :             !(data.capabilities & WPA_CAPABILITY_MFPC))
     653        2155 :                 sm->mgmt_frame_prot = 0;
     654             :         else
     655          64 :                 sm->mgmt_frame_prot = 1;
     656             : #endif /* CONFIG_IEEE80211W */
     657             : 
     658             : #ifdef CONFIG_IEEE80211R
     659        2219 :         if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
     660         272 :                 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         272 :                 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        2219 :         sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0);
     675        2219 :         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        2219 :         if (wpa_ie[0] == WLAN_EID_RSN)
     680        2198 :                 sm->wpa = WPA_VERSION_WPA2;
     681             :         else
     682          21 :                 sm->wpa = WPA_VERSION_WPA;
     683             : 
     684        2219 :         sm->pmksa = NULL;
     685        2494 :         for (i = 0; i < data.num_pmkid; i++) {
     686         303 :                 wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID",
     687         303 :                             &data.pmkid[i * PMKID_LEN], PMKID_LEN);
     688         303 :                 sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr,
     689         303 :                                                  &data.pmkid[i * PMKID_LEN]);
     690         303 :                 if (sm->pmksa) {
     691          28 :                         pmkid = sm->pmksa->pmkid;
     692          28 :                         break;
     693             :                 }
     694             :         }
     695        4450 :         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        2219 :         if (sm->pmksa && pmkid) {
     715          68 :                 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
     716             :                                  "PMKID found from PMKSA cache "
     717             :                                  "eap_type=%d vlan_id=%d",
     718          34 :                                  sm->pmksa->eap_type_authsrv,
     719          34 :                                  sm->pmksa->vlan_id);
     720          34 :                 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN);
     721             :         }
     722             : 
     723        2219 :         if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
     724        1891 :                 os_free(sm->wpa_ie);
     725        1891 :                 sm->wpa_ie = os_malloc(wpa_ie_len);
     726        1891 :                 if (sm->wpa_ie == NULL)
     727           0 :                         return WPA_ALLOC_FAIL;
     728             :         }
     729        2219 :         os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len);
     730        2219 :         sm->wpa_ie_len = wpa_ie_len;
     731             : 
     732        2219 :         return WPA_IE_OK;
     733             : }
     734             : 
     735             : 
     736             : #ifdef CONFIG_HS20
     737           2 : int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
     738             :                       struct wpa_state_machine *sm,
     739             :                       const u8 *osen_ie, size_t osen_ie_len)
     740             : {
     741           2 :         if (wpa_auth == NULL || sm == NULL)
     742           0 :                 return -1;
     743             : 
     744             :         /* TODO: parse OSEN element */
     745           2 :         sm->wpa_key_mgmt = WPA_KEY_MGMT_OSEN;
     746           2 :         sm->mgmt_frame_prot = 1;
     747           2 :         sm->pairwise = WPA_CIPHER_CCMP;
     748           2 :         sm->wpa = WPA_VERSION_WPA2;
     749             : 
     750           2 :         if (sm->wpa_ie == NULL || sm->wpa_ie_len < osen_ie_len) {
     751           2 :                 os_free(sm->wpa_ie);
     752           2 :                 sm->wpa_ie = os_malloc(osen_ie_len);
     753           2 :                 if (sm->wpa_ie == NULL)
     754           0 :                         return -1;
     755             :         }
     756             : 
     757           2 :         os_memcpy(sm->wpa_ie, osen_ie, osen_ie_len);
     758           2 :         sm->wpa_ie_len = osen_ie_len;
     759             : 
     760           2 :         return 0;
     761             : }
     762             : 
     763             : #endif /* CONFIG_HS20 */
     764             : 
     765             : 
     766             : /**
     767             :  * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
     768             :  * @pos: Pointer to the IE header
     769             :  * @end: Pointer to the end of the Key Data buffer
     770             :  * @ie: Pointer to parsed IE data
     771             :  * Returns: 0 on success, 1 if end mark is found, -1 on failure
     772             :  */
     773         257 : static int wpa_parse_generic(const u8 *pos, const u8 *end,
     774             :                              struct wpa_eapol_ie_parse *ie)
     775             : {
     776         257 :         if (pos[1] == 0)
     777           0 :                 return 1;
     778             : 
     779         295 :         if (pos[1] >= 6 &&
     780          64 :             RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
     781          52 :             pos[2 + WPA_SELECTOR_LEN] == 1 &&
     782          26 :             pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
     783          26 :                 ie->wpa_ie = pos;
     784          26 :                 ie->wpa_ie_len = pos[1] + 2;
     785          26 :                 return 0;
     786             :         }
     787             : 
     788         231 :         if (pos[1] >= 4 && WPA_GET_BE32(pos + 2) == OSEN_IE_VENDOR_TYPE) {
     789           2 :                 ie->osen = pos;
     790           2 :                 ie->osen_len = pos[1] + 2;
     791           2 :                 return 0;
     792             :         }
     793             : 
     794         458 :         if (pos + 1 + RSN_SELECTOR_LEN < end &&
     795         230 :             pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
     796           1 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
     797           0 :                 ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
     798           0 :                 return 0;
     799             :         }
     800             : 
     801         239 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     802          10 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
     803           0 :                 ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
     804           0 :                 ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
     805           0 :                 return 0;
     806             :         }
     807             : 
     808         239 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     809          10 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
     810           7 :                 ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
     811           7 :                 ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
     812           7 :                 return 0;
     813             :         }
     814             : 
     815             : #ifdef CONFIG_PEERKEY
     816         225 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     817           3 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) {
     818           0 :                 ie->smk = pos + 2 + RSN_SELECTOR_LEN;
     819           0 :                 ie->smk_len = pos[1] - RSN_SELECTOR_LEN;
     820           0 :                 return 0;
     821             :         }
     822             : 
     823         225 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     824           3 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) {
     825           1 :                 ie->nonce = pos + 2 + RSN_SELECTOR_LEN;
     826           1 :                 ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;
     827           1 :                 return 0;
     828             :         }
     829             : 
     830         223 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     831           2 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) {
     832           0 :                 ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;
     833           0 :                 ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;
     834           0 :                 return 0;
     835             :         }
     836             : 
     837         223 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     838           2 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) {
     839           2 :                 ie->error = pos + 2 + RSN_SELECTOR_LEN;
     840           2 :                 ie->error_len = pos[1] - RSN_SELECTOR_LEN;
     841           2 :                 return 0;
     842             :         }
     843             : #endif /* CONFIG_PEERKEY */
     844             : 
     845             : #ifdef CONFIG_IEEE80211W
     846         219 :         if (pos[1] > RSN_SELECTOR_LEN + 2 &&
     847           0 :             RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
     848           0 :                 ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
     849           0 :                 ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
     850           0 :                 return 0;
     851             :         }
     852             : #endif /* CONFIG_IEEE80211W */
     853             : 
     854             : #ifdef CONFIG_P2P
     855         438 :         if (pos[1] >= RSN_SELECTOR_LEN + 1 &&
     856         219 :             RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) {
     857         219 :                 ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN;
     858         438 :                 wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key",
     859         438 :                             ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN);
     860         219 :                 return 0;
     861             :         }
     862             : 
     863           0 :         if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 &&
     864           0 :             RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) {
     865           0 :                 ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN;
     866           0 :                 wpa_hexdump(MSG_DEBUG,
     867             :                             "WPA: IP Address Allocation in EAPOL-Key",
     868           0 :                             ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN);
     869           0 :                 return 0;
     870             :         }
     871             : #endif /* CONFIG_P2P */
     872             : 
     873           0 :         return 0;
     874             : }
     875             : 
     876             : 
     877             : /**
     878             :  * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs
     879             :  * @buf: Pointer to the Key Data buffer
     880             :  * @len: Key Data Length
     881             :  * @ie: Pointer to parsed IE data
     882             :  * Returns: 0 on success, -1 on failure
     883             :  */
     884        1595 : int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
     885             : {
     886             :         const u8 *pos, *end;
     887        1595 :         int ret = 0;
     888             : 
     889        1595 :         os_memset(ie, 0, sizeof(*ie));
     890        3509 :         for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
     891        2171 :                 if (pos[0] == 0xdd &&
     892         514 :                     ((pos == buf + len - 1) || pos[1] == 0)) {
     893             :                         /* Ignore padding */
     894             :                         break;
     895             :                 }
     896        1914 :                 if (pos + 2 + pos[1] > end) {
     897           0 :                         wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
     898             :                                    "underflow (ie=%d len=%d pos=%d)",
     899           0 :                                    pos[0], pos[1], (int) (pos - buf));
     900           0 :                         wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
     901             :                                         buf, len);
     902           0 :                         ret = -1;
     903           0 :                         break;
     904             :                 }
     905        1914 :                 if (*pos == WLAN_EID_RSN) {
     906        1565 :                         ie->rsn_ie = pos;
     907        1565 :                         ie->rsn_ie_len = pos[1] + 2;
     908             : #ifdef CONFIG_IEEE80211R
     909         349 :                 } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
     910          46 :                         ie->mdie = pos;
     911          46 :                         ie->mdie_len = pos[1] + 2;
     912         303 :                 } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
     913          46 :                         ie->ftie = pos;
     914          46 :                         ie->ftie_len = pos[1] + 2;
     915             : #endif /* CONFIG_IEEE80211R */
     916         257 :                 } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
     917         257 :                         ret = wpa_parse_generic(pos, end, ie);
     918         257 :                         if (ret < 0)
     919           0 :                                 break;
     920         257 :                         if (ret > 0) {
     921           0 :                                 ret = 0;
     922           0 :                                 break;
     923             :                         }
     924             :                 } else {
     925           0 :                         wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
     926           0 :                                     "Key Data IE", pos, 2 + pos[1]);
     927             :                 }
     928             :         }
     929             : 
     930        1595 :         return ret;
     931             : }
     932             : 
     933             : 
     934        2216 : int wpa_auth_uses_mfp(struct wpa_state_machine *sm)
     935             : {
     936        2216 :         return sm ? sm->mgmt_frame_prot : 0;
     937             : }

Generated by: LCOV version 1.10