LCOV - code coverage report
Current view: top level - src/common - wpa_common.c (source / functions) Hit Total Coverage
Test: wpa_supplicant hwsim test run 1401872338 Lines: 628 786 79.9 %
Date: 2014-06-04 Functions: 34 34 100.0 %

          Line data    Source code
       1             : /*
       2             :  * WPA/RSN - Shared functions for supplicant and authenticator
       3             :  * Copyright (c) 2002-2013, 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 "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "crypto/md5.h"
      13             : #include "crypto/sha1.h"
      14             : #include "crypto/sha256.h"
      15             : #include "crypto/aes_wrap.h"
      16             : #include "crypto/crypto.h"
      17             : #include "ieee802_11_defs.h"
      18             : #include "defs.h"
      19             : #include "wpa_common.h"
      20             : 
      21             : 
      22             : /**
      23             :  * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
      24             :  * @key: EAPOL-Key Key Confirmation Key (KCK)
      25             :  * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
      26             :  * @buf: Pointer to the beginning of the EAPOL header (version field)
      27             :  * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
      28             :  * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written
      29             :  * Returns: 0 on success, -1 on failure
      30             :  *
      31             :  * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has
      32             :  * to be cleared (all zeroes) when calling this function.
      33             :  *
      34             :  * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the
      35             :  * description of the Key MIC calculation. It includes packet data from the
      36             :  * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change
      37             :  * happened during final editing of the standard and the correct behavior is
      38             :  * defined in the last draft (IEEE 802.11i/D10).
      39             :  */
      40        2544 : int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
      41             :                       u8 *mic)
      42             : {
      43             :         u8 hash[SHA1_MAC_LEN];
      44             : 
      45        2544 :         switch (ver) {
      46             : #ifndef CONFIG_FIPS
      47             :         case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
      48          95 :                 return hmac_md5(key, 16, buf, len, mic);
      49             : #endif /* CONFIG_FIPS */
      50             :         case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
      51        2329 :                 if (hmac_sha1(key, 16, buf, len, hash))
      52           0 :                         return -1;
      53        2329 :                 os_memcpy(mic, hash, MD5_MAC_LEN);
      54        2329 :                 break;
      55             : #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
      56             :         case WPA_KEY_INFO_TYPE_AES_128_CMAC:
      57         114 :                 return omac1_aes_128(key, buf, len, mic);
      58             : #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
      59             : #ifdef CONFIG_HS20
      60             :         case WPA_KEY_INFO_TYPE_AKM_DEFINED:
      61             :                 /* FIX: This should be based on negotiated AKM */
      62           6 :                 return omac1_aes_128(key, buf, len, mic);
      63             : #endif /* CONFIG_HS20 */
      64             :         default:
      65           0 :                 return -1;
      66             :         }
      67             : 
      68        2329 :         return 0;
      69             : }
      70             : 
      71             : 
      72             : /**
      73             :  * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces
      74             :  * @pmk: Pairwise master key
      75             :  * @pmk_len: Length of PMK
      76             :  * @label: Label to use in derivation
      77             :  * @addr1: AA or SA
      78             :  * @addr2: SA or AA
      79             :  * @nonce1: ANonce or SNonce
      80             :  * @nonce2: SNonce or ANonce
      81             :  * @ptk: Buffer for pairwise transient key
      82             :  * @ptk_len: Length of PTK
      83             :  * @use_sha256: Whether to use SHA256-based KDF
      84             :  *
      85             :  * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
      86             :  * PTK = PRF-X(PMK, "Pairwise key expansion",
      87             :  *             Min(AA, SA) || Max(AA, SA) ||
      88             :  *             Min(ANonce, SNonce) || Max(ANonce, SNonce))
      89             :  *
      90             :  * STK = PRF-X(SMK, "Peer key expansion",
      91             :  *             Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) ||
      92             :  *             Min(INonce, PNonce) || Max(INonce, PNonce))
      93             :  */
      94         834 : void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
      95             :                     const u8 *addr1, const u8 *addr2,
      96             :                     const u8 *nonce1, const u8 *nonce2,
      97             :                     u8 *ptk, size_t ptk_len, int use_sha256)
      98             : {
      99             :         u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
     100             : 
     101         834 :         if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
     102         657 :                 os_memcpy(data, addr1, ETH_ALEN);
     103         657 :                 os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
     104             :         } else {
     105         177 :                 os_memcpy(data, addr2, ETH_ALEN);
     106         177 :                 os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
     107             :         }
     108             : 
     109         834 :         if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
     110         421 :                 os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
     111         421 :                 os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
     112             :                           WPA_NONCE_LEN);
     113             :         } else {
     114         413 :                 os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
     115         413 :                 os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
     116             :                           WPA_NONCE_LEN);
     117             :         }
     118             : 
     119             : #ifdef CONFIG_IEEE80211W
     120         834 :         if (use_sha256)
     121          19 :                 sha256_prf(pmk, pmk_len, label, data, sizeof(data),
     122             :                            ptk, ptk_len);
     123             :         else
     124             : #endif /* CONFIG_IEEE80211W */
     125         815 :                 sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk,
     126             :                          ptk_len);
     127             : 
     128       10008 :         wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
     129       10008 :                    MAC2STR(addr1), MAC2STR(addr2));
     130         834 :         wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
     131         834 :         wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN);
     132         834 :         wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
     133         834 :         wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);
     134         834 : }
     135             : 
     136             : 
     137             : #ifdef CONFIG_IEEE80211R
     138         442 : int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
     139             :                u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
     140             :                const u8 *ftie, size_t ftie_len,
     141             :                const u8 *rsnie, size_t rsnie_len,
     142             :                const u8 *ric, size_t ric_len, u8 *mic)
     143             : {
     144             :         u8 *buf, *pos;
     145             :         size_t buf_len;
     146             : 
     147         442 :         buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
     148         442 :         buf = os_malloc(buf_len);
     149         442 :         if (buf == NULL)
     150           0 :                 return -1;
     151             : 
     152         442 :         pos = buf;
     153         442 :         os_memcpy(pos, sta_addr, ETH_ALEN);
     154         442 :         pos += ETH_ALEN;
     155         442 :         os_memcpy(pos, ap_addr, ETH_ALEN);
     156         442 :         pos += ETH_ALEN;
     157         442 :         *pos++ = transaction_seqnum;
     158         442 :         if (rsnie) {
     159         442 :                 os_memcpy(pos, rsnie, rsnie_len);
     160         442 :                 pos += rsnie_len;
     161             :         }
     162         442 :         if (mdie) {
     163         442 :                 os_memcpy(pos, mdie, mdie_len);
     164         442 :                 pos += mdie_len;
     165             :         }
     166         442 :         if (ftie) {
     167             :                 struct rsn_ftie *_ftie;
     168         442 :                 os_memcpy(pos, ftie, ftie_len);
     169         442 :                 if (ftie_len < 2 + sizeof(*_ftie)) {
     170           0 :                         os_free(buf);
     171           0 :                         return -1;
     172             :                 }
     173         442 :                 _ftie = (struct rsn_ftie *) (pos + 2);
     174         442 :                 os_memset(_ftie->mic, 0, sizeof(_ftie->mic));
     175         442 :                 pos += ftie_len;
     176             :         }
     177         442 :         if (ric) {
     178           0 :                 os_memcpy(pos, ric, ric_len);
     179           0 :                 pos += ric_len;
     180             :         }
     181             : 
     182         442 :         wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
     183         442 :         if (omac1_aes_128(kck, buf, pos - buf, mic)) {
     184           0 :                 os_free(buf);
     185           0 :                 return -1;
     186             :         }
     187             : 
     188         442 :         os_free(buf);
     189             : 
     190         442 :         return 0;
     191             : }
     192             : 
     193             : 
     194         682 : static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
     195             :                              struct wpa_ft_ies *parse)
     196             : {
     197             :         const u8 *end, *pos;
     198             : 
     199         682 :         parse->ftie = ie;
     200         682 :         parse->ftie_len = ie_len;
     201             : 
     202         682 :         pos = ie + sizeof(struct rsn_ftie);
     203         682 :         end = ie + ie_len;
     204             : 
     205        3178 :         while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
     206        1814 :                 switch (pos[0]) {
     207             :                 case FTIE_SUBELEM_R1KH_ID:
     208         682 :                         if (pos[1] != FT_R1KH_ID_LEN) {
     209           0 :                                 wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
     210           0 :                                            "length in FTIE: %d", pos[1]);
     211           0 :                                 return -1;
     212             :                         }
     213         682 :                         parse->r1kh_id = pos + 2;
     214         682 :                         break;
     215             :                 case FTIE_SUBELEM_GTK:
     216         442 :                         parse->gtk = pos + 2;
     217         442 :                         parse->gtk_len = pos[1];
     218         442 :                         break;
     219             :                 case FTIE_SUBELEM_R0KH_ID:
     220         682 :                         if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
     221           0 :                                 wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
     222           0 :                                            "length in FTIE: %d", pos[1]);
     223           0 :                                 return -1;
     224             :                         }
     225         682 :                         parse->r0kh_id = pos + 2;
     226         682 :                         parse->r0kh_id_len = pos[1];
     227         682 :                         break;
     228             : #ifdef CONFIG_IEEE80211W
     229             :                 case FTIE_SUBELEM_IGTK:
     230           8 :                         parse->igtk = pos + 2;
     231           8 :                         parse->igtk_len = pos[1];
     232           8 :                         break;
     233             : #endif /* CONFIG_IEEE80211W */
     234             :                 }
     235             : 
     236        1814 :                 pos += 2 + pos[1];
     237             :         }
     238             : 
     239         682 :         return 0;
     240             : }
     241             : 
     242             : 
     243        2948 : int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
     244             :                      struct wpa_ft_ies *parse)
     245             : {
     246             :         const u8 *end, *pos;
     247             :         struct wpa_ie_data data;
     248             :         int ret;
     249             :         const struct rsn_ftie *ftie;
     250        2948 :         int prot_ie_count = 0;
     251             : 
     252        2948 :         os_memset(parse, 0, sizeof(*parse));
     253        2948 :         if (ies == NULL)
     254        1089 :                 return 0;
     255             : 
     256        1859 :         pos = ies;
     257        1859 :         end = ies + ies_len;
     258       16586 :         while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
     259       12868 :                 switch (pos[0]) {
     260             :                 case WLAN_EID_RSN:
     261         663 :                         parse->rsn = pos + 2;
     262         663 :                         parse->rsn_len = pos[1];
     263         663 :                         ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
     264         663 :                                                    parse->rsn_len + 2,
     265             :                                                    &data);
     266         663 :                         if (ret < 0) {
     267           0 :                                 wpa_printf(MSG_DEBUG, "FT: Failed to parse "
     268             :                                            "RSN IE: %d", ret);
     269           0 :                                 return -1;
     270             :                         }
     271         663 :                         if (data.num_pmkid == 1 && data.pmkid)
     272         663 :                                 parse->rsn_pmkid = data.pmkid;
     273         663 :                         break;
     274             :                 case WLAN_EID_MOBILITY_DOMAIN:
     275         816 :                         parse->mdie = pos + 2;
     276         816 :                         parse->mdie_len = pos[1];
     277         816 :                         break;
     278             :                 case WLAN_EID_FAST_BSS_TRANSITION:
     279         682 :                         if (pos[1] < sizeof(*ftie))
     280           0 :                                 return -1;
     281         682 :                         ftie = (const struct rsn_ftie *) (pos + 2);
     282         682 :                         prot_ie_count = ftie->mic_control[1];
     283         682 :                         if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
     284           0 :                                 return -1;
     285         682 :                         break;
     286             :                 case WLAN_EID_TIMEOUT_INTERVAL:
     287           0 :                         parse->tie = pos + 2;
     288           0 :                         parse->tie_len = pos[1];
     289           0 :                         break;
     290             :                 case WLAN_EID_RIC_DATA:
     291           0 :                         if (parse->ric == NULL)
     292           0 :                                 parse->ric = pos;
     293           0 :                         break;
     294             :                 }
     295             : 
     296       12868 :                 pos += 2 + pos[1];
     297             :         }
     298             : 
     299        1859 :         if (prot_ie_count == 0)
     300        1417 :                 return 0; /* no MIC */
     301             : 
     302             :         /*
     303             :          * Check that the protected IE count matches with IEs included in the
     304             :          * frame.
     305             :          */
     306         442 :         if (parse->rsn)
     307         442 :                 prot_ie_count--;
     308         442 :         if (parse->mdie)
     309         442 :                 prot_ie_count--;
     310         442 :         if (parse->ftie)
     311         442 :                 prot_ie_count--;
     312         442 :         if (prot_ie_count < 0) {
     313           0 :                 wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
     314             :                            "the protected IE count");
     315           0 :                 return -1;
     316             :         }
     317             : 
     318         442 :         if (prot_ie_count == 0 && parse->ric) {
     319           0 :                 wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
     320             :                            "included in protected IE count");
     321           0 :                 return -1;
     322             :         }
     323             : 
     324             :         /* Determine the end of the RIC IE(s) */
     325         442 :         pos = parse->ric;
     326         884 :         while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
     327             :                prot_ie_count) {
     328           0 :                 prot_ie_count--;
     329           0 :                 pos += 2 + pos[1];
     330             :         }
     331         442 :         parse->ric_len = pos - parse->ric;
     332         442 :         if (prot_ie_count) {
     333           0 :                 wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
     334             :                            "frame", (int) prot_ie_count);
     335           0 :                 return -1;
     336             :         }
     337             : 
     338         442 :         return 0;
     339             : }
     340             : #endif /* CONFIG_IEEE80211R */
     341             : 
     342             : 
     343        7389 : static int rsn_selector_to_bitfield(const u8 *s)
     344             : {
     345        7389 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
     346           0 :                 return WPA_CIPHER_NONE;
     347        7389 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40)
     348           0 :                 return WPA_CIPHER_WEP40;
     349        7389 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
     350         131 :                 return WPA_CIPHER_TKIP;
     351        7258 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
     352        6805 :                 return WPA_CIPHER_CCMP;
     353         453 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104)
     354           0 :                 return WPA_CIPHER_WEP104;
     355             : #ifdef CONFIG_IEEE80211W
     356         453 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
     357         408 :                 return WPA_CIPHER_AES_128_CMAC;
     358             : #endif /* CONFIG_IEEE80211W */
     359          45 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
     360           1 :                 return WPA_CIPHER_GCMP;
     361          44 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256)
     362           0 :                 return WPA_CIPHER_CCMP_256;
     363          44 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256)
     364           0 :                 return WPA_CIPHER_GCMP_256;
     365          44 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128)
     366           0 :                 return WPA_CIPHER_BIP_GMAC_128;
     367          44 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256)
     368           0 :                 return WPA_CIPHER_BIP_GMAC_256;
     369          44 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256)
     370           0 :                 return WPA_CIPHER_BIP_CMAC_256;
     371          44 :         if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED)
     372          42 :                 return WPA_CIPHER_GTK_NOT_USED;
     373           2 :         return 0;
     374             : }
     375             : 
     376             : 
     377        3531 : static int rsn_key_mgmt_to_bitfield(const u8 *s)
     378             : {
     379        3531 :         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
     380         995 :                 return WPA_KEY_MGMT_IEEE8021X;
     381        2536 :         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
     382        1050 :                 return WPA_KEY_MGMT_PSK;
     383             : #ifdef CONFIG_IEEE80211R
     384        1486 :         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
     385          48 :                 return WPA_KEY_MGMT_FT_IEEE8021X;
     386        1438 :         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
     387        1181 :                 return WPA_KEY_MGMT_FT_PSK;
     388             : #endif /* CONFIG_IEEE80211R */
     389             : #ifdef CONFIG_IEEE80211W
     390         257 :         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
     391          11 :                 return WPA_KEY_MGMT_IEEE8021X_SHA256;
     392         246 :         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
     393          48 :                 return WPA_KEY_MGMT_PSK_SHA256;
     394             : #endif /* CONFIG_IEEE80211W */
     395             : #ifdef CONFIG_SAE
     396         198 :         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
     397         110 :                 return WPA_KEY_MGMT_SAE;
     398          88 :         if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
     399          46 :                 return WPA_KEY_MGMT_FT_SAE;
     400             : #endif /* CONFIG_SAE */
     401          42 :         return 0;
     402             : }
     403             : 
     404             : 
     405        3471 : static int wpa_cipher_valid_group(int cipher)
     406             : {
     407        6985 :         return wpa_cipher_valid_pairwise(cipher) ||
     408          43 :                 cipher == WPA_CIPHER_WEP104 ||
     409        3514 :                 cipher == WPA_CIPHER_WEP40 ||
     410             :                 cipher == WPA_CIPHER_GTK_NOT_USED;
     411             : }
     412             : 
     413             : 
     414             : #ifdef CONFIG_IEEE80211W
     415        1914 : int wpa_cipher_valid_mgmt_group(int cipher)
     416             : {
     417        3335 :         return cipher == WPA_CIPHER_AES_128_CMAC ||
     418        1421 :                 cipher == WPA_CIPHER_BIP_GMAC_128 ||
     419        3335 :                 cipher == WPA_CIPHER_BIP_GMAC_256 ||
     420             :                 cipher == WPA_CIPHER_BIP_CMAC_256;
     421             : }
     422             : #endif /* CONFIG_IEEE80211W */
     423             : 
     424             : 
     425             : /**
     426             :  * wpa_parse_wpa_ie_rsn - Parse RSN IE
     427             :  * @rsn_ie: Buffer containing RSN IE
     428             :  * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
     429             :  * @data: Pointer to structure that will be filled in with parsed data
     430             :  * Returns: 0 on success, <0 on failure
     431             :  */
     432        3479 : int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
     433             :                          struct wpa_ie_data *data)
     434             : {
     435             :         const struct rsn_ie_hdr *hdr;
     436             :         const u8 *pos;
     437             :         int left;
     438             :         int i, count;
     439             : 
     440        3479 :         os_memset(data, 0, sizeof(*data));
     441        3479 :         data->proto = WPA_PROTO_RSN;
     442        3479 :         data->pairwise_cipher = WPA_CIPHER_CCMP;
     443        3479 :         data->group_cipher = WPA_CIPHER_CCMP;
     444        3479 :         data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
     445        3479 :         data->capabilities = 0;
     446        3479 :         data->pmkid = NULL;
     447        3479 :         data->num_pmkid = 0;
     448             : #ifdef CONFIG_IEEE80211W
     449        3479 :         data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
     450             : #else /* CONFIG_IEEE80211W */
     451             :         data->mgmt_group_cipher = 0;
     452             : #endif /* CONFIG_IEEE80211W */
     453             : 
     454        3479 :         if (rsn_ie_len == 0) {
     455             :                 /* No RSN IE - fail silently */
     456           1 :                 return -1;
     457             :         }
     458             : 
     459        3478 :         if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
     460           1 :                 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
     461             :                            __func__, (unsigned long) rsn_ie_len);
     462           1 :                 return -1;
     463             :         }
     464             : 
     465        3477 :         hdr = (const struct rsn_ie_hdr *) rsn_ie;
     466             : 
     467        6954 :         if (hdr->elem_id != WLAN_EID_RSN ||
     468        6953 :             hdr->len != rsn_ie_len - 2 ||
     469        3476 :             WPA_GET_LE16(hdr->version) != RSN_VERSION) {
     470           4 :                 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
     471             :                            __func__);
     472           4 :                 return -2;
     473             :         }
     474             : 
     475        3473 :         pos = (const u8 *) (hdr + 1);
     476        3473 :         left = rsn_ie_len - sizeof(*hdr);
     477             : 
     478        3473 :         if (left >= RSN_SELECTOR_LEN) {
     479        3471 :                 data->group_cipher = rsn_selector_to_bitfield(pos);
     480        3471 :                 if (!wpa_cipher_valid_group(data->group_cipher)) {
     481           1 :                         wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x",
     482             :                                    __func__, data->group_cipher);
     483           1 :                         return -1;
     484             :                 }
     485        3470 :                 pos += RSN_SELECTOR_LEN;
     486        3470 :                 left -= RSN_SELECTOR_LEN;
     487           2 :         } else if (left > 0) {
     488           1 :                 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
     489             :                            __func__, left);
     490           1 :                 return -3;
     491             :         }
     492             : 
     493        3471 :         if (left >= 2) {
     494        3468 :                 data->pairwise_cipher = 0;
     495        3468 :                 count = WPA_GET_LE16(pos);
     496        3468 :                 pos += 2;
     497        3468 :                 left -= 2;
     498        3468 :                 if (count == 0 || left < count * RSN_SELECTOR_LEN) {
     499           3 :                         wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
     500             :                                    "count %u left %u", __func__, count, left);
     501           3 :                         return -4;
     502             :                 }
     503        6975 :                 for (i = 0; i < count; i++) {
     504        3510 :                         data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
     505        3510 :                         pos += RSN_SELECTOR_LEN;
     506        3510 :                         left -= RSN_SELECTOR_LEN;
     507             :                 }
     508             : #ifdef CONFIG_IEEE80211W
     509        3465 :                 if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
     510           1 :                         wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
     511             :                                    "pairwise cipher", __func__);
     512           1 :                         return -1;
     513             :                 }
     514             : #endif /* CONFIG_IEEE80211W */
     515           3 :         } else if (left == 1) {
     516           1 :                 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
     517             :                            __func__);
     518           1 :                 return -5;
     519             :         }
     520             : 
     521        3466 :         if (left >= 2) {
     522        3457 :                 data->key_mgmt = 0;
     523        3457 :                 count = WPA_GET_LE16(pos);
     524        3457 :                 pos += 2;
     525        3457 :                 left -= 2;
     526        3457 :                 if (count == 0 || left < count * RSN_SELECTOR_LEN) {
     527           2 :                         wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
     528             :                                    "count %u left %u", __func__, count, left);
     529           2 :                         return -6;
     530             :                 }
     531        6986 :                 for (i = 0; i < count; i++) {
     532        3531 :                         data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
     533        3531 :                         pos += RSN_SELECTOR_LEN;
     534        3531 :                         left -= RSN_SELECTOR_LEN;
     535             :                 }
     536           9 :         } else if (left == 1) {
     537           1 :                 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
     538             :                            __func__);
     539           1 :                 return -7;
     540             :         }
     541             : 
     542        3463 :         if (left >= 2) {
     543        3452 :                 data->capabilities = WPA_GET_LE16(pos);
     544        3452 :                 pos += 2;
     545        3452 :                 left -= 2;
     546             :         }
     547             : 
     548        3463 :         if (left >= 2) {
     549        1093 :                 data->num_pmkid = WPA_GET_LE16(pos);
     550        1093 :                 pos += 2;
     551        1093 :                 left -= 2;
     552        1093 :                 if (left < (int) data->num_pmkid * PMKID_LEN) {
     553           1 :                         wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
     554             :                                    "(num_pmkid=%lu left=%d)",
     555             :                                    __func__, (unsigned long) data->num_pmkid,
     556             :                                    left);
     557           1 :                         data->num_pmkid = 0;
     558           1 :                         return -9;
     559             :                 } else {
     560        1092 :                         data->pmkid = pos;
     561        1092 :                         pos += data->num_pmkid * PMKID_LEN;
     562        1092 :                         left -= data->num_pmkid * PMKID_LEN;
     563             :                 }
     564             :         }
     565             : 
     566             : #ifdef CONFIG_IEEE80211W
     567        3462 :         if (left >= 4) {
     568         408 :                 data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
     569         408 :                 if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
     570           1 :                         wpa_printf(MSG_DEBUG, "%s: Unsupported management "
     571             :                                    "group cipher 0x%x", __func__,
     572             :                                    data->mgmt_group_cipher);
     573           1 :                         return -10;
     574             :                 }
     575         407 :                 pos += RSN_SELECTOR_LEN;
     576         407 :                 left -= RSN_SELECTOR_LEN;
     577             :         }
     578             : #endif /* CONFIG_IEEE80211W */
     579             : 
     580        3461 :         if (left > 0) {
     581           2 :                 wpa_hexdump(MSG_DEBUG,
     582             :                             "wpa_parse_wpa_ie_rsn: ignore trailing bytes",
     583             :                             pos, left);
     584             :         }
     585             : 
     586        3461 :         return 0;
     587             : }
     588             : 
     589             : 
     590          92 : static int wpa_selector_to_bitfield(const u8 *s)
     591             : {
     592          92 :         if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
     593           0 :                 return WPA_CIPHER_NONE;
     594          92 :         if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
     595           0 :                 return WPA_CIPHER_WEP40;
     596          92 :         if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
     597          78 :                 return WPA_CIPHER_TKIP;
     598          14 :         if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
     599          14 :                 return WPA_CIPHER_CCMP;
     600           0 :         if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
     601           0 :                 return WPA_CIPHER_WEP104;
     602           0 :         return 0;
     603             : }
     604             : 
     605             : 
     606          41 : static int wpa_key_mgmt_to_bitfield(const u8 *s)
     607             : {
     608          41 :         if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
     609           2 :                 return WPA_KEY_MGMT_IEEE8021X;
     610          39 :         if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
     611          39 :                 return WPA_KEY_MGMT_PSK;
     612           0 :         if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
     613           0 :                 return WPA_KEY_MGMT_WPA_NONE;
     614           0 :         return 0;
     615             : }
     616             : 
     617             : 
     618          41 : int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
     619             :                          struct wpa_ie_data *data)
     620             : {
     621             :         const struct wpa_ie_hdr *hdr;
     622             :         const u8 *pos;
     623             :         int left;
     624             :         int i, count;
     625             : 
     626          41 :         os_memset(data, 0, sizeof(*data));
     627          41 :         data->proto = WPA_PROTO_WPA;
     628          41 :         data->pairwise_cipher = WPA_CIPHER_TKIP;
     629          41 :         data->group_cipher = WPA_CIPHER_TKIP;
     630          41 :         data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
     631          41 :         data->capabilities = 0;
     632          41 :         data->pmkid = NULL;
     633          41 :         data->num_pmkid = 0;
     634          41 :         data->mgmt_group_cipher = 0;
     635             : 
     636          41 :         if (wpa_ie_len == 0) {
     637             :                 /* No WPA IE - fail silently */
     638           0 :                 return -1;
     639             :         }
     640             : 
     641          41 :         if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
     642           0 :                 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
     643             :                            __func__, (unsigned long) wpa_ie_len);
     644           0 :                 return -1;
     645             :         }
     646             : 
     647          41 :         hdr = (const struct wpa_ie_hdr *) wpa_ie;
     648             : 
     649          82 :         if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
     650          82 :             hdr->len != wpa_ie_len - 2 ||
     651          82 :             RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
     652          41 :             WPA_GET_LE16(hdr->version) != WPA_VERSION) {
     653           0 :                 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
     654             :                            __func__);
     655           0 :                 return -2;
     656             :         }
     657             : 
     658          41 :         pos = (const u8 *) (hdr + 1);
     659          41 :         left = wpa_ie_len - sizeof(*hdr);
     660             : 
     661          41 :         if (left >= WPA_SELECTOR_LEN) {
     662          41 :                 data->group_cipher = wpa_selector_to_bitfield(pos);
     663          41 :                 pos += WPA_SELECTOR_LEN;
     664          41 :                 left -= WPA_SELECTOR_LEN;
     665           0 :         } else if (left > 0) {
     666           0 :                 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
     667             :                            __func__, left);
     668           0 :                 return -3;
     669             :         }
     670             : 
     671          41 :         if (left >= 2) {
     672          41 :                 data->pairwise_cipher = 0;
     673          41 :                 count = WPA_GET_LE16(pos);
     674          41 :                 pos += 2;
     675          41 :                 left -= 2;
     676          41 :                 if (count == 0 || left < count * WPA_SELECTOR_LEN) {
     677           0 :                         wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
     678             :                                    "count %u left %u", __func__, count, left);
     679           0 :                         return -4;
     680             :                 }
     681          92 :                 for (i = 0; i < count; i++) {
     682          51 :                         data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
     683          51 :                         pos += WPA_SELECTOR_LEN;
     684          51 :                         left -= WPA_SELECTOR_LEN;
     685             :                 }
     686           0 :         } else if (left == 1) {
     687           0 :                 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
     688             :                            __func__);
     689           0 :                 return -5;
     690             :         }
     691             : 
     692          41 :         if (left >= 2) {
     693          41 :                 data->key_mgmt = 0;
     694          41 :                 count = WPA_GET_LE16(pos);
     695          41 :                 pos += 2;
     696          41 :                 left -= 2;
     697          41 :                 if (count == 0 || left < count * WPA_SELECTOR_LEN) {
     698           0 :                         wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
     699             :                                    "count %u left %u", __func__, count, left);
     700           0 :                         return -6;
     701             :                 }
     702          82 :                 for (i = 0; i < count; i++) {
     703          41 :                         data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
     704          41 :                         pos += WPA_SELECTOR_LEN;
     705          41 :                         left -= WPA_SELECTOR_LEN;
     706             :                 }
     707           0 :         } else if (left == 1) {
     708           0 :                 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
     709             :                            __func__);
     710           0 :                 return -7;
     711             :         }
     712             : 
     713          41 :         if (left >= 2) {
     714           0 :                 data->capabilities = WPA_GET_LE16(pos);
     715           0 :                 pos += 2;
     716           0 :                 left -= 2;
     717             :         }
     718             : 
     719          41 :         if (left > 0) {
     720           0 :                 wpa_hexdump(MSG_DEBUG,
     721             :                             "wpa_parse_wpa_ie_wpa: ignore trailing bytes",
     722             :                             pos, left);
     723             :         }
     724             : 
     725          41 :         return 0;
     726             : }
     727             : 
     728             : 
     729             : #ifdef CONFIG_IEEE80211R
     730             : 
     731             : /**
     732             :  * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
     733             :  *
     734             :  * IEEE Std 802.11r-2008 - 8.5.1.5.3
     735             :  */
     736          19 : void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
     737             :                        const u8 *ssid, size_t ssid_len,
     738             :                        const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
     739             :                        const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
     740             : {
     741             :         u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
     742             :                FT_R0KH_ID_MAX_LEN + ETH_ALEN];
     743             :         u8 *pos, r0_key_data[48], hash[32];
     744             :         const u8 *addr[2];
     745             :         size_t len[2];
     746             : 
     747             :         /*
     748             :          * R0-Key-Data = KDF-384(XXKey, "FT-R0",
     749             :          *                       SSIDlength || SSID || MDID || R0KHlength ||
     750             :          *                       R0KH-ID || S0KH-ID)
     751             :          * XXKey is either the second 256 bits of MSK or PSK.
     752             :          * PMK-R0 = L(R0-Key-Data, 0, 256)
     753             :          * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
     754             :          */
     755          19 :         if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
     756          19 :                 return;
     757          19 :         pos = buf;
     758          19 :         *pos++ = ssid_len;
     759          19 :         os_memcpy(pos, ssid, ssid_len);
     760          19 :         pos += ssid_len;
     761          19 :         os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
     762          19 :         pos += MOBILITY_DOMAIN_ID_LEN;
     763          19 :         *pos++ = r0kh_id_len;
     764          19 :         os_memcpy(pos, r0kh_id, r0kh_id_len);
     765          19 :         pos += r0kh_id_len;
     766          19 :         os_memcpy(pos, s0kh_id, ETH_ALEN);
     767          19 :         pos += ETH_ALEN;
     768             : 
     769          19 :         sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
     770             :                    r0_key_data, sizeof(r0_key_data));
     771          19 :         os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
     772             : 
     773             :         /*
     774             :          * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
     775             :          */
     776          19 :         addr[0] = (const u8 *) "FT-R0N";
     777          19 :         len[0] = 6;
     778          19 :         addr[1] = r0_key_data + PMK_LEN;
     779          19 :         len[1] = 16;
     780             : 
     781          19 :         sha256_vector(2, addr, len, hash);
     782          19 :         os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
     783             : }
     784             : 
     785             : 
     786             : /**
     787             :  * wpa_derive_pmk_r1_name - Derive PMKR1Name
     788             :  *
     789             :  * IEEE Std 802.11r-2008 - 8.5.1.5.4
     790             :  */
     791         240 : void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
     792             :                             const u8 *s1kh_id, u8 *pmk_r1_name)
     793             : {
     794             :         u8 hash[32];
     795             :         const u8 *addr[4];
     796             :         size_t len[4];
     797             : 
     798             :         /*
     799             :          * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
     800             :          *                                  R1KH-ID || S1KH-ID))
     801             :          */
     802         240 :         addr[0] = (const u8 *) "FT-R1N";
     803         240 :         len[0] = 6;
     804         240 :         addr[1] = pmk_r0_name;
     805         240 :         len[1] = WPA_PMK_NAME_LEN;
     806         240 :         addr[2] = r1kh_id;
     807         240 :         len[2] = FT_R1KH_ID_LEN;
     808         240 :         addr[3] = s1kh_id;
     809         240 :         len[3] = ETH_ALEN;
     810             : 
     811         240 :         sha256_vector(4, addr, len, hash);
     812         240 :         os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
     813         240 : }
     814             : 
     815             : 
     816             : /**
     817             :  * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
     818             :  *
     819             :  * IEEE Std 802.11r-2008 - 8.5.1.5.4
     820             :  */
     821         240 : void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
     822             :                        const u8 *r1kh_id, const u8 *s1kh_id,
     823             :                        u8 *pmk_r1, u8 *pmk_r1_name)
     824             : {
     825             :         u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
     826             :         u8 *pos;
     827             : 
     828             :         /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
     829         240 :         pos = buf;
     830         240 :         os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
     831         240 :         pos += FT_R1KH_ID_LEN;
     832         240 :         os_memcpy(pos, s1kh_id, ETH_ALEN);
     833         240 :         pos += ETH_ALEN;
     834             : 
     835         240 :         sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
     836             : 
     837         240 :         wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
     838         240 : }
     839             : 
     840             : 
     841             : /**
     842             :  * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
     843             :  *
     844             :  * IEEE Std 802.11r-2008 - 8.5.1.5.5
     845             :  */
     846         240 : void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
     847             :                        const u8 *sta_addr, const u8 *bssid,
     848             :                        const u8 *pmk_r1_name,
     849             :                        u8 *ptk, size_t ptk_len, u8 *ptk_name)
     850             : {
     851             :         u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
     852             :         u8 *pos, hash[32];
     853             :         const u8 *addr[6];
     854             :         size_t len[6];
     855             : 
     856             :         /*
     857             :          * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
     858             :          *                  BSSID || STA-ADDR)
     859             :          */
     860         240 :         pos = buf;
     861         240 :         os_memcpy(pos, snonce, WPA_NONCE_LEN);
     862         240 :         pos += WPA_NONCE_LEN;
     863         240 :         os_memcpy(pos, anonce, WPA_NONCE_LEN);
     864         240 :         pos += WPA_NONCE_LEN;
     865         240 :         os_memcpy(pos, bssid, ETH_ALEN);
     866         240 :         pos += ETH_ALEN;
     867         240 :         os_memcpy(pos, sta_addr, ETH_ALEN);
     868         240 :         pos += ETH_ALEN;
     869             : 
     870         240 :         sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len);
     871             : 
     872             :         /*
     873             :          * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
     874             :          *                                ANonce || BSSID || STA-ADDR))
     875             :          */
     876         240 :         addr[0] = pmk_r1_name;
     877         240 :         len[0] = WPA_PMK_NAME_LEN;
     878         240 :         addr[1] = (const u8 *) "FT-PTKN";
     879         240 :         len[1] = 7;
     880         240 :         addr[2] = snonce;
     881         240 :         len[2] = WPA_NONCE_LEN;
     882         240 :         addr[3] = anonce;
     883         240 :         len[3] = WPA_NONCE_LEN;
     884         240 :         addr[4] = bssid;
     885         240 :         len[4] = ETH_ALEN;
     886         240 :         addr[5] = sta_addr;
     887         240 :         len[5] = ETH_ALEN;
     888             : 
     889         240 :         sha256_vector(6, addr, len, hash);
     890         240 :         os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
     891         240 : }
     892             : 
     893             : #endif /* CONFIG_IEEE80211R */
     894             : 
     895             : 
     896             : /**
     897             :  * rsn_pmkid - Calculate PMK identifier
     898             :  * @pmk: Pairwise master key
     899             :  * @pmk_len: Length of pmk in bytes
     900             :  * @aa: Authenticator address
     901             :  * @spa: Supplicant address
     902             :  * @pmkid: Buffer for PMKID
     903             :  * @use_sha256: Whether to use SHA256-based KDF
     904             :  *
     905             :  * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
     906             :  * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
     907             :  */
     908         277 : void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
     909             :                u8 *pmkid, int use_sha256)
     910             : {
     911         277 :         char *title = "PMK Name";
     912             :         const u8 *addr[3];
     913         277 :         const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
     914             :         unsigned char hash[SHA256_MAC_LEN];
     915             : 
     916         277 :         addr[0] = (u8 *) title;
     917         277 :         addr[1] = aa;
     918         277 :         addr[2] = spa;
     919             : 
     920             : #ifdef CONFIG_IEEE80211W
     921         277 :         if (use_sha256)
     922           3 :                 hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
     923             :         else
     924             : #endif /* CONFIG_IEEE80211W */
     925         274 :                 hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
     926         277 :         os_memcpy(pmkid, hash, PMKID_LEN);
     927         277 : }
     928             : 
     929             : 
     930             : /**
     931             :  * wpa_cipher_txt - Convert cipher suite to a text string
     932             :  * @cipher: Cipher suite (WPA_CIPHER_* enum)
     933             :  * Returns: Pointer to a text string of the cipher suite name
     934             :  */
     935        4835 : const char * wpa_cipher_txt(int cipher)
     936             : {
     937        4835 :         switch (cipher) {
     938             :         case WPA_CIPHER_NONE:
     939         200 :                 return "NONE";
     940             :         case WPA_CIPHER_WEP40:
     941          12 :                 return "WEP-40";
     942             :         case WPA_CIPHER_WEP104:
     943           0 :                 return "WEP-104";
     944             :         case WPA_CIPHER_TKIP:
     945         167 :                 return "TKIP";
     946             :         case WPA_CIPHER_CCMP:
     947        4451 :                 return "CCMP";
     948             :         case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
     949           1 :                 return "CCMP+TKIP";
     950             :         case WPA_CIPHER_GCMP:
     951           0 :                 return "GCMP";
     952             :         case WPA_CIPHER_GCMP_256:
     953           0 :                 return "GCMP-256";
     954             :         case WPA_CIPHER_CCMP_256:
     955           0 :                 return "CCMP-256";
     956             :         case WPA_CIPHER_GTK_NOT_USED:
     957           4 :                 return "GTK_NOT_USED";
     958             :         default:
     959           0 :                 return "UNKNOWN";
     960             :         }
     961             : }
     962             : 
     963             : 
     964             : /**
     965             :  * wpa_key_mgmt_txt - Convert key management suite to a text string
     966             :  * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
     967             :  * @proto: WPA/WPA2 version (WPA_PROTO_*)
     968             :  * Returns: Pointer to a text string of the key management suite name
     969             :  */
     970         713 : const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
     971             : {
     972         713 :         switch (key_mgmt) {
     973             :         case WPA_KEY_MGMT_IEEE8021X:
     974         185 :                 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
     975           0 :                         return "WPA2+WPA/IEEE 802.1X/EAP";
     976         185 :                 return proto == WPA_PROTO_RSN ?
     977         185 :                         "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
     978             :         case WPA_KEY_MGMT_PSK:
     979         156 :                 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
     980           0 :                         return "WPA2-PSK+WPA-PSK";
     981         156 :                 return proto == WPA_PROTO_RSN ?
     982         156 :                         "WPA2-PSK" : "WPA-PSK";
     983             :         case WPA_KEY_MGMT_NONE:
     984         105 :                 return "NONE";
     985             :         case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
     986           0 :                 return "IEEE 802.1X (no WPA)";
     987             : #ifdef CONFIG_IEEE80211R
     988             :         case WPA_KEY_MGMT_FT_IEEE8021X:
     989           6 :                 return "FT-EAP";
     990             :         case WPA_KEY_MGMT_FT_PSK:
     991         225 :                 return "FT-PSK";
     992             : #endif /* CONFIG_IEEE80211R */
     993             : #ifdef CONFIG_IEEE80211W
     994             :         case WPA_KEY_MGMT_IEEE8021X_SHA256:
     995           2 :                 return "WPA2-EAP-SHA256";
     996             :         case WPA_KEY_MGMT_PSK_SHA256:
     997          14 :                 return "WPA2-PSK-SHA256";
     998             : #endif /* CONFIG_IEEE80211W */
     999             :         default:
    1000          20 :                 return "UNKNOWN";
    1001             :         }
    1002             : }
    1003             : 
    1004             : 
    1005         806 : int wpa_compare_rsn_ie(int ft_initial_assoc,
    1006             :                        const u8 *ie1, size_t ie1len,
    1007             :                        const u8 *ie2, size_t ie2len)
    1008             : {
    1009         806 :         if (ie1 == NULL || ie2 == NULL)
    1010           0 :                 return -1;
    1011             : 
    1012         806 :         if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
    1013         787 :                 return 0; /* identical IEs */
    1014             : 
    1015             : #ifdef CONFIG_IEEE80211R
    1016          19 :         if (ft_initial_assoc) {
    1017             :                 struct wpa_ie_data ie1d, ie2d;
    1018             :                 /*
    1019             :                  * The PMKID-List in RSN IE is different between Beacon/Probe
    1020             :                  * Response/(Re)Association Request frames and EAPOL-Key
    1021             :                  * messages in FT initial mobility domain association. Allow
    1022             :                  * for this, but verify that other parts of the RSN IEs are
    1023             :                  * identical.
    1024             :                  */
    1025          38 :                 if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
    1026          19 :                     wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
    1027          19 :                         return -1;
    1028          38 :                 if (ie1d.proto == ie2d.proto &&
    1029          38 :                     ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
    1030          38 :                     ie1d.group_cipher == ie2d.group_cipher &&
    1031          38 :                     ie1d.key_mgmt == ie2d.key_mgmt &&
    1032          38 :                     ie1d.capabilities == ie2d.capabilities &&
    1033          19 :                     ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
    1034          19 :                         return 0;
    1035             :         }
    1036             : #endif /* CONFIG_IEEE80211R */
    1037             : 
    1038           0 :         return -1;
    1039             : }
    1040             : 
    1041             : 
    1042             : #ifdef CONFIG_IEEE80211R
    1043          19 : int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
    1044             : {
    1045             :         u8 *start, *end, *rpos, *rend;
    1046          19 :         int added = 0;
    1047             : 
    1048          19 :         start = ies;
    1049          19 :         end = ies + ies_len;
    1050             : 
    1051          38 :         while (start < end) {
    1052          19 :                 if (*start == WLAN_EID_RSN)
    1053          19 :                         break;
    1054           0 :                 start += 2 + start[1];
    1055             :         }
    1056          19 :         if (start >= end) {
    1057           0 :                 wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
    1058             :                            "IEs data");
    1059           0 :                 return -1;
    1060             :         }
    1061          19 :         wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
    1062          19 :                     start, 2 + start[1]);
    1063             : 
    1064             :         /* Find start of PMKID-Count */
    1065          19 :         rpos = start + 2;
    1066          19 :         rend = rpos + start[1];
    1067             : 
    1068             :         /* Skip Version and Group Data Cipher Suite */
    1069          19 :         rpos += 2 + 4;
    1070             :         /* Skip Pairwise Cipher Suite Count and List */
    1071          19 :         rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
    1072             :         /* Skip AKM Suite Count and List */
    1073          19 :         rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
    1074             : 
    1075          19 :         if (rpos == rend) {
    1076             :                 /* Add RSN Capabilities */
    1077           0 :                 os_memmove(rpos + 2, rpos, end - rpos);
    1078           0 :                 *rpos++ = 0;
    1079           0 :                 *rpos++ = 0;
    1080             :         } else {
    1081             :                 /* Skip RSN Capabilities */
    1082          19 :                 rpos += 2;
    1083          19 :                 if (rpos > rend) {
    1084           0 :                         wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
    1085             :                                    "IEs data");
    1086           0 :                         return -1;
    1087             :                 }
    1088             :         }
    1089             : 
    1090          19 :         if (rpos == rend) {
    1091             :                 /* No PMKID-Count field included; add it */
    1092          15 :                 os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
    1093          15 :                 WPA_PUT_LE16(rpos, 1);
    1094          15 :                 rpos += 2;
    1095          15 :                 os_memcpy(rpos, pmkid, PMKID_LEN);
    1096          15 :                 added += 2 + PMKID_LEN;
    1097          15 :                 start[1] += 2 + PMKID_LEN;
    1098             :         } else {
    1099             :                 /* PMKID-Count was included; use it */
    1100           4 :                 if (WPA_GET_LE16(rpos) != 0) {
    1101           0 :                         wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
    1102             :                                    "in RSN IE in EAPOL-Key data");
    1103           0 :                         return -1;
    1104             :                 }
    1105           4 :                 WPA_PUT_LE16(rpos, 1);
    1106           4 :                 rpos += 2;
    1107           4 :                 os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
    1108           4 :                 os_memcpy(rpos, pmkid, PMKID_LEN);
    1109           4 :                 added += PMKID_LEN;
    1110           4 :                 start[1] += PMKID_LEN;
    1111             :         }
    1112             : 
    1113          19 :         wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
    1114          19 :                     "(PMKID inserted)", start, 2 + start[1]);
    1115             : 
    1116          19 :         return added;
    1117             : }
    1118             : #endif /* CONFIG_IEEE80211R */
    1119             : 
    1120             : 
    1121        4328 : int wpa_cipher_key_len(int cipher)
    1122             : {
    1123        4328 :         switch (cipher) {
    1124             :         case WPA_CIPHER_CCMP_256:
    1125             :         case WPA_CIPHER_GCMP_256:
    1126             :         case WPA_CIPHER_BIP_GMAC_256:
    1127             :         case WPA_CIPHER_BIP_CMAC_256:
    1128           0 :                 return 32;
    1129             :         case WPA_CIPHER_CCMP:
    1130             :         case WPA_CIPHER_GCMP:
    1131             :         case WPA_CIPHER_AES_128_CMAC:
    1132             :         case WPA_CIPHER_BIP_GMAC_128:
    1133        4221 :                 return 16;
    1134             :         case WPA_CIPHER_TKIP:
    1135          96 :                 return 32;
    1136             :         case WPA_CIPHER_WEP104:
    1137           0 :                 return 13;
    1138             :         case WPA_CIPHER_WEP40:
    1139           0 :                 return 5;
    1140             :         }
    1141             : 
    1142          11 :         return 0;
    1143             : }
    1144             : 
    1145             : 
    1146        1545 : int wpa_cipher_rsc_len(int cipher)
    1147             : {
    1148        1545 :         switch (cipher) {
    1149             :         case WPA_CIPHER_CCMP_256:
    1150             :         case WPA_CIPHER_GCMP_256:
    1151             :         case WPA_CIPHER_CCMP:
    1152             :         case WPA_CIPHER_GCMP:
    1153             :         case WPA_CIPHER_TKIP:
    1154        1545 :                 return 6;
    1155             :         case WPA_CIPHER_WEP104:
    1156             :         case WPA_CIPHER_WEP40:
    1157           0 :                 return 0;
    1158             :         }
    1159             : 
    1160           0 :         return 0;
    1161             : }
    1162             : 
    1163             : 
    1164        2427 : int wpa_cipher_to_alg(int cipher)
    1165             : {
    1166        2427 :         switch (cipher) {
    1167             :         case WPA_CIPHER_CCMP_256:
    1168           0 :                 return WPA_ALG_CCMP_256;
    1169             :         case WPA_CIPHER_GCMP_256:
    1170           0 :                 return WPA_ALG_GCMP_256;
    1171             :         case WPA_CIPHER_CCMP:
    1172        2336 :                 return WPA_ALG_CCMP;
    1173             :         case WPA_CIPHER_GCMP:
    1174           0 :                 return WPA_ALG_GCMP;
    1175             :         case WPA_CIPHER_TKIP:
    1176          60 :                 return WPA_ALG_TKIP;
    1177             :         case WPA_CIPHER_WEP104:
    1178             :         case WPA_CIPHER_WEP40:
    1179           0 :                 return WPA_ALG_WEP;
    1180             :         case WPA_CIPHER_AES_128_CMAC:
    1181          31 :                 return WPA_ALG_IGTK;
    1182             :         case WPA_CIPHER_BIP_GMAC_128:
    1183           0 :                 return WPA_ALG_BIP_GMAC_128;
    1184             :         case WPA_CIPHER_BIP_GMAC_256:
    1185           0 :                 return WPA_ALG_BIP_GMAC_256;
    1186             :         case WPA_CIPHER_BIP_CMAC_256:
    1187           0 :                 return WPA_ALG_BIP_CMAC_256;
    1188             :         }
    1189           0 :         return WPA_ALG_NONE;
    1190             : }
    1191             : 
    1192             : 
    1193        6332 : int wpa_cipher_valid_pairwise(int cipher)
    1194             : {
    1195       12664 :         return cipher == WPA_CIPHER_CCMP_256 ||
    1196        6332 :                 cipher == WPA_CIPHER_GCMP_256 ||
    1197         166 :                 cipher == WPA_CIPHER_CCMP ||
    1198        6498 :                 cipher == WPA_CIPHER_GCMP ||
    1199             :                 cipher == WPA_CIPHER_TKIP;
    1200             : }
    1201             : 
    1202             : 
    1203        4149 : u32 wpa_cipher_to_suite(int proto, int cipher)
    1204             : {
    1205        4149 :         if (cipher & WPA_CIPHER_CCMP_256)
    1206           0 :                 return RSN_CIPHER_SUITE_CCMP_256;
    1207        4149 :         if (cipher & WPA_CIPHER_GCMP_256)
    1208           0 :                 return RSN_CIPHER_SUITE_GCMP_256;
    1209        4149 :         if (cipher & WPA_CIPHER_CCMP)
    1210        4006 :                 return (proto == WPA_PROTO_RSN ?
    1211        4006 :                         RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
    1212         143 :         if (cipher & WPA_CIPHER_GCMP)
    1213           0 :                 return RSN_CIPHER_SUITE_GCMP;
    1214         143 :         if (cipher & WPA_CIPHER_TKIP)
    1215          95 :                 return (proto == WPA_PROTO_RSN ?
    1216          95 :                         RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
    1217          48 :         if (cipher & WPA_CIPHER_WEP104)
    1218           0 :                 return (proto == WPA_PROTO_RSN ?
    1219           0 :                         RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104);
    1220          48 :         if (cipher & WPA_CIPHER_WEP40)
    1221           0 :                 return (proto == WPA_PROTO_RSN ?
    1222           0 :                         RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40);
    1223          48 :         if (cipher & WPA_CIPHER_NONE)
    1224          16 :                 return (proto == WPA_PROTO_RSN ?
    1225          16 :                         RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
    1226          32 :         if (cipher & WPA_CIPHER_GTK_NOT_USED)
    1227           2 :                 return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
    1228          30 :         if (cipher & WPA_CIPHER_AES_128_CMAC)
    1229          30 :                 return RSN_CIPHER_SUITE_AES_128_CMAC;
    1230           0 :         if (cipher & WPA_CIPHER_BIP_GMAC_128)
    1231           0 :                 return RSN_CIPHER_SUITE_BIP_GMAC_128;
    1232           0 :         if (cipher & WPA_CIPHER_BIP_GMAC_256)
    1233           0 :                 return RSN_CIPHER_SUITE_BIP_GMAC_256;
    1234           0 :         if (cipher & WPA_CIPHER_BIP_CMAC_256)
    1235           0 :                 return RSN_CIPHER_SUITE_BIP_CMAC_256;
    1236           0 :         return 0;
    1237             : }
    1238             : 
    1239             : 
    1240         143 : int rsn_cipher_put_suites(u8 *start, int ciphers)
    1241             : {
    1242         143 :         u8 *pos = start;
    1243             : 
    1244         143 :         if (ciphers & WPA_CIPHER_CCMP_256) {
    1245           0 :                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
    1246           0 :                 pos += RSN_SELECTOR_LEN;
    1247             :         }
    1248         143 :         if (ciphers & WPA_CIPHER_GCMP_256) {
    1249           0 :                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
    1250           0 :                 pos += RSN_SELECTOR_LEN;
    1251             :         }
    1252         143 :         if (ciphers & WPA_CIPHER_CCMP) {
    1253         142 :                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
    1254         142 :                 pos += RSN_SELECTOR_LEN;
    1255             :         }
    1256         143 :         if (ciphers & WPA_CIPHER_GCMP) {
    1257           0 :                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
    1258           0 :                 pos += RSN_SELECTOR_LEN;
    1259             :         }
    1260         143 :         if (ciphers & WPA_CIPHER_TKIP) {
    1261           4 :                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
    1262           4 :                 pos += RSN_SELECTOR_LEN;
    1263             :         }
    1264         143 :         if (ciphers & WPA_CIPHER_NONE) {
    1265           0 :                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
    1266           0 :                 pos += RSN_SELECTOR_LEN;
    1267             :         }
    1268             : 
    1269         143 :         return (pos - start) / RSN_SELECTOR_LEN;
    1270             : }
    1271             : 
    1272             : 
    1273           1 : int wpa_cipher_put_suites(u8 *start, int ciphers)
    1274             : {
    1275           1 :         u8 *pos = start;
    1276             : 
    1277           1 :         if (ciphers & WPA_CIPHER_CCMP) {
    1278           1 :                 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
    1279           1 :                 pos += WPA_SELECTOR_LEN;
    1280             :         }
    1281           1 :         if (ciphers & WPA_CIPHER_TKIP) {
    1282           1 :                 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
    1283           1 :                 pos += WPA_SELECTOR_LEN;
    1284             :         }
    1285           1 :         if (ciphers & WPA_CIPHER_NONE) {
    1286           0 :                 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
    1287           0 :                 pos += WPA_SELECTOR_LEN;
    1288             :         }
    1289             : 
    1290           1 :         return (pos - start) / RSN_SELECTOR_LEN;
    1291             : }
    1292             : 
    1293             : 
    1294        1121 : int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
    1295             : {
    1296        1121 :         if (ciphers & WPA_CIPHER_CCMP_256)
    1297           0 :                 return WPA_CIPHER_CCMP_256;
    1298        1121 :         if (ciphers & WPA_CIPHER_GCMP_256)
    1299           0 :                 return WPA_CIPHER_GCMP_256;
    1300        1121 :         if (ciphers & WPA_CIPHER_CCMP)
    1301        1098 :                 return WPA_CIPHER_CCMP;
    1302          23 :         if (ciphers & WPA_CIPHER_GCMP)
    1303           0 :                 return WPA_CIPHER_GCMP;
    1304          23 :         if (ciphers & WPA_CIPHER_TKIP)
    1305          21 :                 return WPA_CIPHER_TKIP;
    1306           2 :         if (none_allowed && (ciphers & WPA_CIPHER_NONE))
    1307           0 :                 return WPA_CIPHER_NONE;
    1308           2 :         return -1;
    1309             : }
    1310             : 
    1311             : 
    1312         820 : int wpa_pick_group_cipher(int ciphers)
    1313             : {
    1314         820 :         if (ciphers & WPA_CIPHER_CCMP_256)
    1315           0 :                 return WPA_CIPHER_CCMP_256;
    1316         820 :         if (ciphers & WPA_CIPHER_GCMP_256)
    1317           0 :                 return WPA_CIPHER_GCMP_256;
    1318         820 :         if (ciphers & WPA_CIPHER_CCMP)
    1319         776 :                 return WPA_CIPHER_CCMP;
    1320          44 :         if (ciphers & WPA_CIPHER_GCMP)
    1321           0 :                 return WPA_CIPHER_GCMP;
    1322          44 :         if (ciphers & WPA_CIPHER_GTK_NOT_USED)
    1323           2 :                 return WPA_CIPHER_GTK_NOT_USED;
    1324          42 :         if (ciphers & WPA_CIPHER_TKIP)
    1325          42 :                 return WPA_CIPHER_TKIP;
    1326           0 :         if (ciphers & WPA_CIPHER_WEP104)
    1327           0 :                 return WPA_CIPHER_WEP104;
    1328           0 :         if (ciphers & WPA_CIPHER_WEP40)
    1329           0 :                 return WPA_CIPHER_WEP40;
    1330           0 :         return -1;
    1331             : }
    1332             : 
    1333             : 
    1334         134 : int wpa_parse_cipher(const char *value)
    1335             : {
    1336         134 :         int val = 0, last;
    1337             :         char *start, *end, *buf;
    1338             : 
    1339         134 :         buf = os_strdup(value);
    1340         134 :         if (buf == NULL)
    1341           0 :                 return -1;
    1342         134 :         start = buf;
    1343             : 
    1344         278 :         while (*start != '\0') {
    1345         286 :                 while (*start == ' ' || *start == '\t')
    1346           0 :                         start++;
    1347         143 :                 if (*start == '\0')
    1348           0 :                         break;
    1349         143 :                 end = start;
    1350         893 :                 while (*end != ' ' && *end != '\t' && *end != '\0')
    1351         607 :                         end++;
    1352         143 :                 last = *end == '\0';
    1353         143 :                 *end = '\0';
    1354         143 :                 if (os_strcmp(start, "CCMP-256") == 0)
    1355           2 :                         val |= WPA_CIPHER_CCMP_256;
    1356         141 :                 else if (os_strcmp(start, "GCMP-256") == 0)
    1357           2 :                         val |= WPA_CIPHER_GCMP_256;
    1358         139 :                 else if (os_strcmp(start, "CCMP") == 0)
    1359         109 :                         val |= WPA_CIPHER_CCMP;
    1360          30 :                 else if (os_strcmp(start, "GCMP") == 0)
    1361           2 :                         val |= WPA_CIPHER_GCMP;
    1362          28 :                 else if (os_strcmp(start, "TKIP") == 0)
    1363          22 :                         val |= WPA_CIPHER_TKIP;
    1364           6 :                 else if (os_strcmp(start, "WEP104") == 0)
    1365           1 :                         val |= WPA_CIPHER_WEP104;
    1366           5 :                 else if (os_strcmp(start, "WEP40") == 0)
    1367           2 :                         val |= WPA_CIPHER_WEP40;
    1368           3 :                 else if (os_strcmp(start, "NONE") == 0)
    1369           0 :                         val |= WPA_CIPHER_NONE;
    1370           3 :                 else if (os_strcmp(start, "GTK_NOT_USED") == 0)
    1371           2 :                         val |= WPA_CIPHER_GTK_NOT_USED;
    1372             :                 else {
    1373           1 :                         os_free(buf);
    1374           1 :                         return -1;
    1375             :                 }
    1376             : 
    1377         142 :                 if (last)
    1378         132 :                         break;
    1379          10 :                 start = end + 1;
    1380             :         }
    1381         133 :         os_free(buf);
    1382             : 
    1383         133 :         return val;
    1384             : }
    1385             : 
    1386             : 
    1387         164 : int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
    1388             : {
    1389         164 :         char *pos = start;
    1390             :         int ret;
    1391             : 
    1392         164 :         if (ciphers & WPA_CIPHER_CCMP_256) {
    1393           2 :                 ret = os_snprintf(pos, end - pos, "%sCCMP-256",
    1394             :                                   pos == start ? "" : delim);
    1395           2 :                 if (ret < 0 || ret >= end - pos)
    1396           0 :                         return -1;
    1397           2 :                 pos += ret;
    1398             :         }
    1399         164 :         if (ciphers & WPA_CIPHER_GCMP_256) {
    1400           2 :                 ret = os_snprintf(pos, end - pos, "%sGCMP-256",
    1401             :                                   pos == start ? "" : delim);
    1402           2 :                 if (ret < 0 || ret >= end - pos)
    1403           0 :                         return -1;
    1404           2 :                 pos += ret;
    1405             :         }
    1406         164 :         if (ciphers & WPA_CIPHER_CCMP) {
    1407         161 :                 ret = os_snprintf(pos, end - pos, "%sCCMP",
    1408             :                                   pos == start ? "" : delim);
    1409         161 :                 if (ret < 0 || ret >= end - pos)
    1410           0 :                         return -1;
    1411         161 :                 pos += ret;
    1412             :         }
    1413         164 :         if (ciphers & WPA_CIPHER_GCMP) {
    1414           2 :                 ret = os_snprintf(pos, end - pos, "%sGCMP",
    1415             :                                   pos == start ? "" : delim);
    1416           2 :                 if (ret < 0 || ret >= end - pos)
    1417           0 :                         return -1;
    1418           2 :                 pos += ret;
    1419             :         }
    1420         164 :         if (ciphers & WPA_CIPHER_TKIP) {
    1421          21 :                 ret = os_snprintf(pos, end - pos, "%sTKIP",
    1422             :                                   pos == start ? "" : delim);
    1423          21 :                 if (ret < 0 || ret >= end - pos)
    1424           0 :                         return -1;
    1425          21 :                 pos += ret;
    1426             :         }
    1427         164 :         if (ciphers & WPA_CIPHER_WEP104) {
    1428           1 :                 ret = os_snprintf(pos, end - pos, "%sWEP104",
    1429             :                                   pos == start ? "" : delim);
    1430           1 :                 if (ret < 0 || ret >= end - pos)
    1431           0 :                         return -1;
    1432           1 :                 pos += ret;
    1433             :         }
    1434         164 :         if (ciphers & WPA_CIPHER_WEP40) {
    1435           1 :                 ret = os_snprintf(pos, end - pos, "%sWEP40",
    1436             :                                   pos == start ? "" : delim);
    1437           1 :                 if (ret < 0 || ret >= end - pos)
    1438           0 :                         return -1;
    1439           1 :                 pos += ret;
    1440             :         }
    1441         164 :         if (ciphers & WPA_CIPHER_NONE) {
    1442           0 :                 ret = os_snprintf(pos, end - pos, "%sNONE",
    1443             :                                   pos == start ? "" : delim);
    1444           0 :                 if (ret < 0 || ret >= end - pos)
    1445           0 :                         return -1;
    1446           0 :                 pos += ret;
    1447             :         }
    1448             : 
    1449         164 :         return pos - start;
    1450             : }
    1451             : 
    1452             : 
    1453         140 : int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
    1454             : {
    1455         140 :         int pairwise = 0;
    1456             : 
    1457             :         /* Select group cipher based on the enabled pairwise cipher suites */
    1458         140 :         if (wpa & 1)
    1459           1 :                 pairwise |= wpa_pairwise;
    1460         140 :         if (wpa & 2)
    1461         135 :                 pairwise |= rsn_pairwise;
    1462             : 
    1463         140 :         if (pairwise & WPA_CIPHER_TKIP)
    1464           1 :                 return WPA_CIPHER_TKIP;
    1465         139 :         if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
    1466           0 :                 return WPA_CIPHER_GCMP;
    1467         139 :         if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
    1468             :                          WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
    1469           0 :                 return WPA_CIPHER_GCMP_256;
    1470         139 :         if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
    1471             :                          WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
    1472           0 :                 return WPA_CIPHER_CCMP_256;
    1473         139 :         return WPA_CIPHER_CCMP;
    1474             : }

Generated by: LCOV version 1.10