LCOV - code coverage report
Current view: top level - src/rsn_supp - wpa.c (source / functions) Hit Total Coverage
Test: wpa_supplicant hwsim test run 1388240082 Lines: 790 1199 65.9 %
Date: 2013-12-28 Functions: 54 63 85.7 %
Branches: 408 733 55.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * WPA Supplicant - WPA state machine and EAPOL-Key processing
       3                 :            :  * Copyright (c) 2003-2012, 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/aes_wrap.h"
      13                 :            : #include "crypto/crypto.h"
      14                 :            : #include "crypto/random.h"
      15                 :            : #include "common/ieee802_11_defs.h"
      16                 :            : #include "eapol_supp/eapol_supp_sm.h"
      17                 :            : #include "wpa.h"
      18                 :            : #include "eloop.h"
      19                 :            : #include "preauth.h"
      20                 :            : #include "pmksa_cache.h"
      21                 :            : #include "wpa_i.h"
      22                 :            : #include "wpa_ie.h"
      23                 :            : #include "peerkey.h"
      24                 :            : 
      25                 :            : 
      26                 :            : /**
      27                 :            :  * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
      28                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
      29                 :            :  * @kck: Key Confirmation Key (KCK, part of PTK)
      30                 :            :  * @ver: Version field from Key Info
      31                 :            :  * @dest: Destination address for the frame
      32                 :            :  * @proto: Ethertype (usually ETH_P_EAPOL)
      33                 :            :  * @msg: EAPOL-Key message
      34                 :            :  * @msg_len: Length of message
      35                 :            :  * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written
      36                 :            :  */
      37                 :        477 : void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck,
      38                 :            :                         int ver, const u8 *dest, u16 proto,
      39                 :            :                         u8 *msg, size_t msg_len, u8 *key_mic)
      40                 :            : {
      41 [ -  + ][ #  # ]:        477 :         if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
      42                 :            :                 /*
      43                 :            :                  * Association event was not yet received; try to fetch
      44                 :            :                  * BSSID from the driver.
      45                 :            :                  */
      46         [ #  # ]:          0 :                 if (wpa_sm_get_bssid(sm, sm->bssid) < 0) {
      47                 :          0 :                         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
      48                 :            :                                 "WPA: Failed to read BSSID for "
      49                 :            :                                 "EAPOL-Key destination address");
      50                 :            :                 } else {
      51                 :          0 :                         dest = sm->bssid;
      52                 :          0 :                         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
      53                 :            :                                 "WPA: Use BSSID (" MACSTR
      54                 :            :                                 ") as the destination for EAPOL-Key",
      55                 :            :                                 MAC2STR(dest));
      56                 :            :                 }
      57                 :            :         }
      58   [ +  +  -  + ]:        953 :         if (key_mic &&
      59                 :        476 :             wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic)) {
      60                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
      61                 :            :                         "WPA: Failed to generate EAPOL-Key "
      62                 :            :                         "version %d MIC", ver);
      63                 :          0 :                 goto out;
      64                 :            :         }
      65                 :        477 :         wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, 16);
      66                 :        477 :         wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, 16);
      67                 :        477 :         wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
      68                 :        477 :         wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
      69                 :        477 :         eapol_sm_notify_tx_eapol_key(sm->eapol);
      70                 :            : out:
      71                 :        477 :         os_free(msg);
      72                 :        477 : }
      73                 :            : 
      74                 :            : 
      75                 :            : /**
      76                 :            :  * wpa_sm_key_request - Send EAPOL-Key Request
      77                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
      78                 :            :  * @error: Indicate whether this is an Michael MIC error report
      79                 :            :  * @pairwise: 1 = error report for pairwise packet, 0 = for group packet
      80                 :            :  *
      81                 :            :  * Send an EAPOL-Key Request to the current authenticator. This function is
      82                 :            :  * used to request rekeying and it is usually called when a local Michael MIC
      83                 :            :  * failure is detected.
      84                 :            :  */
      85                 :          0 : void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
      86                 :            : {
      87                 :            :         size_t rlen;
      88                 :            :         struct wpa_eapol_key *reply;
      89                 :            :         int key_info, ver;
      90                 :            :         u8 bssid[ETH_ALEN], *rbuf;
      91                 :            : 
      92 [ #  # ][ #  # ]:          0 :         if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt))
      93                 :          0 :                 ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;
      94         [ #  # ]:          0 :         else if (sm->pairwise_cipher != WPA_CIPHER_TKIP)
      95                 :          0 :                 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
      96                 :            :         else
      97                 :          0 :                 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
      98                 :            : 
      99         [ #  # ]:          0 :         if (wpa_sm_get_bssid(sm, bssid) < 0) {
     100                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     101                 :            :                         "Failed to read BSSID for EAPOL-Key request");
     102                 :          0 :                 return;
     103                 :            :         }
     104                 :            : 
     105                 :          0 :         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
     106                 :            :                                   sizeof(*reply), &rlen, (void *) &reply);
     107         [ #  # ]:          0 :         if (rbuf == NULL)
     108                 :          0 :                 return;
     109                 :            : 
     110         [ #  # ]:          0 :         reply->type = sm->proto == WPA_PROTO_RSN ?
     111                 :            :                 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
     112                 :          0 :         key_info = WPA_KEY_INFO_REQUEST | ver;
     113         [ #  # ]:          0 :         if (sm->ptk_set)
     114                 :          0 :                 key_info |= WPA_KEY_INFO_MIC;
     115         [ #  # ]:          0 :         if (error)
     116                 :          0 :                 key_info |= WPA_KEY_INFO_ERROR;
     117         [ #  # ]:          0 :         if (pairwise)
     118                 :          0 :                 key_info |= WPA_KEY_INFO_KEY_TYPE;
     119                 :          0 :         WPA_PUT_BE16(reply->key_info, key_info);
     120                 :          0 :         WPA_PUT_BE16(reply->key_length, 0);
     121                 :          0 :         os_memcpy(reply->replay_counter, sm->request_counter,
     122                 :            :                   WPA_REPLAY_COUNTER_LEN);
     123                 :          0 :         inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
     124                 :            : 
     125                 :          0 :         WPA_PUT_BE16(reply->key_data_length, 0);
     126                 :            : 
     127                 :          0 :         wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
     128                 :            :                 "WPA: Sending EAPOL-Key Request (error=%d "
     129                 :            :                 "pairwise=%d ptk_set=%d len=%lu)",
     130                 :            :                 error, pairwise, sm->ptk_set, (unsigned long) rlen);
     131         [ #  # ]:          0 :         wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
     132                 :          0 :                            rbuf, rlen, key_info & WPA_KEY_INFO_MIC ?
     133                 :          0 :                            reply->key_mic : NULL);
     134                 :            : }
     135                 :            : 
     136                 :            : 
     137                 :        242 : static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
     138                 :            :                                   const unsigned char *src_addr,
     139                 :            :                                   const u8 *pmkid)
     140                 :            : {
     141                 :        242 :         int abort_cached = 0;
     142                 :            : 
     143 [ +  + ][ +  + ]:        242 :         if (pmkid && !sm->cur_pmksa) {
     144                 :            :                 /* When using drivers that generate RSN IE, wpa_supplicant may
     145                 :            :                  * not have enough time to get the association information
     146                 :            :                  * event before receiving this 1/4 message, so try to find a
     147                 :            :                  * matching PMKSA cache entry here. */
     148                 :         69 :                 sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid,
     149                 :            :                                                 NULL);
     150         [ -  + ]:         69 :                 if (sm->cur_pmksa) {
     151                 :          0 :                         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     152                 :            :                                 "RSN: found matching PMKID from PMKSA cache");
     153                 :            :                 } else {
     154                 :         69 :                         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     155                 :            :                                 "RSN: no matching PMKID found");
     156                 :         69 :                         abort_cached = 1;
     157                 :            :                 }
     158                 :            :         }
     159                 :            : 
     160 [ +  + ][ +  + ]:        242 :         if (pmkid && sm->cur_pmksa &&
                 [ +  - ]
     161                 :          1 :             os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
     162                 :          1 :                 wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);
     163                 :          1 :                 wpa_sm_set_pmk_from_pmksa(sm);
     164                 :          1 :                 wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",
     165                 :          1 :                                 sm->pmk, sm->pmk_len);
     166                 :          1 :                 eapol_sm_notify_cached(sm->eapol);
     167                 :            : #ifdef CONFIG_IEEE80211R
     168                 :          1 :                 sm->xxkey_len = 0;
     169                 :            : #endif /* CONFIG_IEEE80211R */
     170 [ +  + ][ +  - ]:        241 :         } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {
     171                 :            :                 int res, pmk_len;
     172                 :         71 :                 pmk_len = PMK_LEN;
     173                 :         71 :                 res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);
     174         [ -  + ]:         71 :                 if (res) {
     175                 :            :                         /*
     176                 :            :                          * EAP-LEAP is an exception from other EAP methods: it
     177                 :            :                          * uses only 16-byte PMK.
     178                 :            :                          */
     179                 :          0 :                         res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
     180                 :          0 :                         pmk_len = 16;
     181                 :            :                 } else {
     182                 :            : #ifdef CONFIG_IEEE80211R
     183                 :            :                         u8 buf[2 * PMK_LEN];
     184         [ +  - ]:         71 :                         if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0)
     185                 :            :                         {
     186                 :         71 :                                 os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN);
     187                 :         71 :                                 sm->xxkey_len = PMK_LEN;
     188                 :         71 :                                 os_memset(buf, 0, sizeof(buf));
     189                 :            :                         }
     190                 :            : #endif /* CONFIG_IEEE80211R */
     191                 :            :                 }
     192         [ +  - ]:         71 :                 if (res == 0) {
     193                 :         71 :                         struct rsn_pmksa_cache_entry *sa = NULL;
     194                 :         71 :                         wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
     195                 :         71 :                                         "machines", sm->pmk, pmk_len);
     196                 :         71 :                         sm->pmk_len = pmk_len;
     197   [ +  +  +  + ]:        140 :                         if (sm->proto == WPA_PROTO_RSN &&
     198                 :         69 :                             !wpa_key_mgmt_ft(sm->key_mgmt)) {
     199                 :         68 :                                 sa = pmksa_cache_add(sm->pmksa,
     200                 :         68 :                                                      sm->pmk, pmk_len,
     201                 :         68 :                                                      src_addr, sm->own_addr,
     202                 :            :                                                      sm->network_ctx,
     203                 :         68 :                                                      sm->key_mgmt);
     204                 :            :                         }
     205         [ +  - ]:        140 :                         if (!sm->cur_pmksa && pmkid &&
           [ +  +  +  + ]
     206                 :         69 :                             pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL))
     207                 :            :                         {
     208                 :         68 :                                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     209                 :            :                                         "RSN: the new PMK matches with the "
     210                 :            :                                         "PMKID");
     211                 :         68 :                                 abort_cached = 0;
     212                 :            :                         }
     213                 :            : 
     214         [ +  - ]:         71 :                         if (!sm->cur_pmksa)
     215                 :         71 :                                 sm->cur_pmksa = sa;
     216                 :            :                 } else {
     217                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     218                 :            :                                 "WPA: Failed to get master session key from "
     219                 :            :                                 "EAPOL state machines - key handshake "
     220                 :            :                                 "aborted");
     221         [ #  # ]:          0 :                         if (sm->cur_pmksa) {
     222                 :          0 :                                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     223                 :            :                                         "RSN: Cancelled PMKSA caching "
     224                 :            :                                         "attempt");
     225                 :          0 :                                 sm->cur_pmksa = NULL;
     226                 :          0 :                                 abort_cached = 1;
     227         [ #  # ]:          0 :                         } else if (!abort_cached) {
     228                 :          0 :                                 return -1;
     229                 :            :                         }
     230                 :            :                 }
     231                 :            :         }
     232                 :            : 
     233         [ +  + ]:        243 :         if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) &&
           [ +  -  -  + ]
     234                 :          1 :             !wpa_key_mgmt_ft(sm->key_mgmt)) {
     235                 :            :                 /* Send EAPOL-Start to trigger full EAP authentication. */
     236                 :            :                 u8 *buf;
     237                 :            :                 size_t buflen;
     238                 :            : 
     239                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     240                 :            :                         "RSN: no PMKSA entry found - trigger "
     241                 :            :                         "full EAP authentication");
     242                 :          0 :                 buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
     243                 :            :                                          NULL, 0, &buflen, NULL);
     244         [ #  # ]:          0 :                 if (buf) {
     245                 :          0 :                         wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
     246                 :            :                                           buf, buflen);
     247                 :          0 :                         os_free(buf);
     248                 :          0 :                         return -2;
     249                 :            :                 }
     250                 :            : 
     251                 :          0 :                 return -1;
     252                 :            :         }
     253                 :            : 
     254                 :        242 :         return 0;
     255                 :            : }
     256                 :            : 
     257                 :            : 
     258                 :            : /**
     259                 :            :  * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake
     260                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     261                 :            :  * @dst: Destination address for the frame
     262                 :            :  * @key: Pointer to the EAPOL-Key frame header
     263                 :            :  * @ver: Version bits from EAPOL-Key Key Info
     264                 :            :  * @nonce: Nonce value for the EAPOL-Key frame
     265                 :            :  * @wpa_ie: WPA/RSN IE
     266                 :            :  * @wpa_ie_len: Length of the WPA/RSN IE
     267                 :            :  * @ptk: PTK to use for keyed hash and encryption
     268                 :            :  * Returns: 0 on success, -1 on failure
     269                 :            :  */
     270                 :        243 : int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
     271                 :            :                                const struct wpa_eapol_key *key,
     272                 :            :                                int ver, const u8 *nonce,
     273                 :            :                                const u8 *wpa_ie, size_t wpa_ie_len,
     274                 :            :                                struct wpa_ptk *ptk)
     275                 :            : {
     276                 :            :         size_t rlen;
     277                 :            :         struct wpa_eapol_key *reply;
     278                 :            :         u8 *rbuf;
     279                 :        243 :         u8 *rsn_ie_buf = NULL;
     280                 :            : 
     281         [ -  + ]:        243 :         if (wpa_ie == NULL) {
     282                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - "
     283                 :            :                         "cannot generate msg 2/4");
     284                 :          0 :                 return -1;
     285                 :            :         }
     286                 :            : 
     287                 :            : #ifdef CONFIG_IEEE80211R
     288         [ +  + ]:        243 :         if (wpa_key_mgmt_ft(sm->key_mgmt)) {
     289                 :            :                 int res;
     290                 :            : 
     291                 :            :                 /*
     292                 :            :                  * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and
     293                 :            :                  * FTIE from (Re)Association Response.
     294                 :            :                  */
     295                 :          8 :                 rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN +
     296                 :          8 :                                        sm->assoc_resp_ies_len);
     297         [ -  + ]:          8 :                 if (rsn_ie_buf == NULL)
     298                 :          0 :                         return -1;
     299                 :          8 :                 os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
     300                 :          8 :                 res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len,
     301                 :          8 :                                        sm->pmk_r1_name);
     302         [ -  + ]:          8 :                 if (res < 0) {
     303                 :          0 :                         os_free(rsn_ie_buf);
     304                 :          0 :                         return -1;
     305                 :            :                 }
     306                 :          8 :                 wpa_ie_len += res;
     307                 :            : 
     308         [ +  - ]:          8 :                 if (sm->assoc_resp_ies) {
     309                 :          8 :                         os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
     310                 :            :                                   sm->assoc_resp_ies_len);
     311                 :          8 :                         wpa_ie_len += sm->assoc_resp_ies_len;
     312                 :            :                 }
     313                 :            : 
     314                 :          8 :                 wpa_ie = rsn_ie_buf;
     315                 :            :         }
     316                 :            : #endif /* CONFIG_IEEE80211R */
     317                 :            : 
     318                 :        243 :         wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
     319                 :            : 
     320                 :        243 :         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
     321                 :            :                                   NULL, sizeof(*reply) + wpa_ie_len,
     322                 :            :                                   &rlen, (void *) &reply);
     323         [ -  + ]:        243 :         if (rbuf == NULL) {
     324                 :          0 :                 os_free(rsn_ie_buf);
     325                 :          0 :                 return -1;
     326                 :            :         }
     327                 :            : 
     328         [ +  + ]:        243 :         reply->type = sm->proto == WPA_PROTO_RSN ?
     329                 :            :                 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
     330                 :        243 :         WPA_PUT_BE16(reply->key_info,
     331                 :            :                      ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC);
     332         [ +  + ]:        243 :         if (sm->proto == WPA_PROTO_RSN)
     333                 :        237 :                 WPA_PUT_BE16(reply->key_length, 0);
     334                 :            :         else
     335                 :          6 :                 os_memcpy(reply->key_length, key->key_length, 2);
     336                 :        243 :         os_memcpy(reply->replay_counter, key->replay_counter,
     337                 :            :                   WPA_REPLAY_COUNTER_LEN);
     338                 :        243 :         wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter,
     339                 :            :                     WPA_REPLAY_COUNTER_LEN);
     340                 :            : 
     341                 :        243 :         WPA_PUT_BE16(reply->key_data_length, wpa_ie_len);
     342                 :        243 :         os_memcpy(reply + 1, wpa_ie, wpa_ie_len);
     343                 :        243 :         os_free(rsn_ie_buf);
     344                 :            : 
     345                 :        243 :         os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
     346                 :            : 
     347                 :        243 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
     348                 :        243 :         wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,
     349                 :        243 :                            rbuf, rlen, reply->key_mic);
     350                 :            : 
     351                 :        243 :         return 0;
     352                 :            : }
     353                 :            : 
     354                 :            : 
     355                 :        242 : static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
     356                 :            :                           const struct wpa_eapol_key *key,
     357                 :            :                           struct wpa_ptk *ptk)
     358                 :            : {
     359         [ +  + ]:        242 :         size_t ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64;
     360                 :            : #ifdef CONFIG_IEEE80211R
     361         [ +  + ]:        242 :         if (wpa_key_mgmt_ft(sm->key_mgmt))
     362                 :          8 :                 return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len);
     363                 :            : #endif /* CONFIG_IEEE80211R */
     364                 :            : 
     365                 :        234 :         wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
     366                 :        234 :                        sm->own_addr, sm->bssid, sm->snonce, key->key_nonce,
     367                 :            :                        (u8 *) ptk, ptk_len,
     368                 :        234 :                        wpa_key_mgmt_sha256(sm->key_mgmt));
     369                 :        242 :         return 0;
     370                 :            : }
     371                 :            : 
     372                 :            : 
     373                 :        242 : static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
     374                 :            :                                           const unsigned char *src_addr,
     375                 :            :                                           const struct wpa_eapol_key *key,
     376                 :            :                                           u16 ver)
     377                 :            : {
     378                 :            :         struct wpa_eapol_ie_parse ie;
     379                 :            :         struct wpa_ptk *ptk;
     380                 :            :         u8 buf[8];
     381                 :            :         int res;
     382                 :            : 
     383         [ -  + ]:        242 :         if (wpa_sm_get_network_ctx(sm) == NULL) {
     384                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info "
     385                 :            :                         "found (msg 1 of 4)");
     386                 :          0 :                 return;
     387                 :            :         }
     388                 :            : 
     389                 :        242 :         wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
     390                 :        242 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way "
     391                 :            :                 "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
     392                 :            : 
     393                 :        242 :         os_memset(&ie, 0, sizeof(ie));
     394                 :            : 
     395         [ +  + ]:        242 :         if (sm->proto == WPA_PROTO_RSN) {
     396                 :            :                 /* RSN: msg 1/4 should contain PMKID for the selected PMK */
     397                 :        236 :                 const u8 *_buf = (const u8 *) (key + 1);
     398                 :        236 :                 size_t len = WPA_GET_BE16(key->key_data_length);
     399                 :        236 :                 wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len);
     400         [ -  + ]:        236 :                 if (wpa_supplicant_parse_ies(_buf, len, &ie) < 0)
     401                 :          0 :                         goto failed;
     402         [ +  + ]:        236 :                 if (ie.pmkid) {
     403                 :         70 :                         wpa_hexdump(MSG_DEBUG, "RSN: PMKID from "
     404                 :         70 :                                     "Authenticator", ie.pmkid, PMKID_LEN);
     405                 :            :                 }
     406                 :            :         }
     407                 :            : 
     408                 :        242 :         res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
     409         [ -  + ]:        242 :         if (res == -2) {
     410                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to "
     411                 :            :                         "msg 1/4 - requesting full EAP authentication");
     412                 :          0 :                 return;
     413                 :            :         }
     414         [ -  + ]:        242 :         if (res)
     415                 :          0 :                 goto failed;
     416                 :            : 
     417         [ +  + ]:        242 :         if (sm->renew_snonce) {
     418         [ -  + ]:        227 :                 if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
     419                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     420                 :            :                                 "WPA: Failed to get random data for SNonce");
     421                 :          0 :                         goto failed;
     422                 :            :                 }
     423                 :        227 :                 sm->renew_snonce = 0;
     424                 :        227 :                 wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
     425                 :        227 :                             sm->snonce, WPA_NONCE_LEN);
     426                 :            :         }
     427                 :            : 
     428                 :            :         /* Calculate PTK which will be stored as a temporary PTK until it has
     429                 :            :          * been verified when processing message 3/4. */
     430                 :        242 :         ptk = &sm->tptk;
     431                 :        242 :         wpa_derive_ptk(sm, src_addr, key, ptk);
     432                 :            :         /* Supplicant: swap tx/rx Mic keys */
     433                 :        242 :         os_memcpy(buf, ptk->u.auth.tx_mic_key, 8);
     434                 :        242 :         os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);
     435                 :        242 :         os_memcpy(ptk->u.auth.rx_mic_key, buf, 8);
     436                 :        242 :         sm->tptk_set = 1;
     437                 :            : 
     438         [ -  + ]:        242 :         if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
     439                 :        242 :                                        sm->assoc_wpa_ie, sm->assoc_wpa_ie_len,
     440                 :            :                                        ptk))
     441                 :          0 :                 goto failed;
     442                 :            : 
     443                 :        242 :         os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
     444                 :        242 :         return;
     445                 :            : 
     446                 :            : failed:
     447                 :        242 :         wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
     448                 :            : }
     449                 :            : 
     450                 :            : 
     451                 :        227 : static void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx)
     452                 :            : {
     453                 :        227 :         struct wpa_sm *sm = eloop_ctx;
     454                 :        227 :         rsn_preauth_candidate_process(sm);
     455                 :        227 : }
     456                 :            : 
     457                 :            : 
     458                 :        236 : static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
     459                 :            :                                             const u8 *addr, int secure)
     460                 :            : {
     461                 :        236 :         wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
     462                 :            :                 "WPA: Key negotiation completed with "
     463                 :       1416 :                 MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),
     464                 :        236 :                 wpa_cipher_txt(sm->pairwise_cipher),
     465                 :        236 :                 wpa_cipher_txt(sm->group_cipher));
     466                 :        236 :         wpa_sm_cancel_auth_timeout(sm);
     467                 :        236 :         wpa_sm_set_state(sm, WPA_COMPLETED);
     468                 :            : 
     469         [ +  - ]:        236 :         if (secure) {
     470                 :        236 :                 wpa_sm_mlme_setprotection(
     471                 :            :                         sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX,
     472                 :            :                         MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
     473                 :        236 :                 eapol_sm_notify_portValid(sm->eapol, TRUE);
     474         [ +  + ]:        236 :                 if (wpa_key_mgmt_wpa_psk(sm->key_mgmt))
     475                 :        162 :                         eapol_sm_notify_eap_success(sm->eapol, TRUE);
     476                 :            :                 /*
     477                 :            :                  * Start preauthentication after a short wait to avoid a
     478                 :            :                  * possible race condition between the data receive and key
     479                 :            :                  * configuration after the 4-Way Handshake. This increases the
     480                 :            :                  * likelihood of the first preauth EAPOL-Start frame getting to
     481                 :            :                  * the target AP.
     482                 :            :                  */
     483                 :        236 :                 eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL);
     484                 :            :         }
     485                 :            : 
     486 [ +  + ][ -  + ]:        236 :         if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) {
     487                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     488                 :            :                         "RSN: Authenticator accepted "
     489                 :            :                         "opportunistic PMKSA entry - marking it valid");
     490                 :          0 :                 sm->cur_pmksa->opportunistic = 0;
     491                 :            :         }
     492                 :            : 
     493                 :            : #ifdef CONFIG_IEEE80211R
     494         [ +  + ]:        236 :         if (wpa_key_mgmt_ft(sm->key_mgmt)) {
     495                 :            :                 /* Prepare for the next transition */
     496                 :         22 :                 wpa_ft_prepare_auth_request(sm, NULL);
     497                 :            :         }
     498                 :            : #endif /* CONFIG_IEEE80211R */
     499                 :        236 : }
     500                 :            : 
     501                 :            : 
     502                 :          0 : static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
     503                 :            : {
     504                 :          0 :         struct wpa_sm *sm = eloop_ctx;
     505                 :          0 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Request PTK rekeying");
     506                 :          0 :         wpa_sm_key_request(sm, 0, 1);
     507                 :          0 : }
     508                 :            : 
     509                 :            : 
     510                 :        222 : static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
     511                 :            :                                       const struct wpa_eapol_key *key)
     512                 :            : {
     513                 :            :         int keylen, rsclen;
     514                 :            :         enum wpa_alg alg;
     515                 :            :         const u8 *key_rsc;
     516                 :        222 :         u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
     517                 :            : 
     518                 :        222 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     519                 :            :                 "WPA: Installing PTK to the driver");
     520                 :            : 
     521         [ -  + ]:        222 :         if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
     522                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher "
     523                 :            :                         "Suite: NONE - do not use pairwise keys");
     524                 :          0 :                 return 0;
     525                 :            :         }
     526                 :            : 
     527         [ -  + ]:        222 :         if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
     528                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     529                 :            :                         "WPA: Unsupported pairwise cipher %d",
     530                 :            :                         sm->pairwise_cipher);
     531                 :          0 :                 return -1;
     532                 :            :         }
     533                 :            : 
     534                 :        222 :         alg = wpa_cipher_to_alg(sm->pairwise_cipher);
     535                 :        222 :         keylen = wpa_cipher_key_len(sm->pairwise_cipher);
     536                 :        222 :         rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
     537                 :            : 
     538         [ +  + ]:        222 :         if (sm->proto == WPA_PROTO_RSN) {
     539                 :        216 :                 key_rsc = null_rsc;
     540                 :            :         } else {
     541                 :          6 :                 key_rsc = key->key_rsc;
     542                 :          6 :                 wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen);
     543                 :            :         }
     544                 :            : 
     545         [ -  + ]:        222 :         if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen,
     546                 :        222 :                            (u8 *) sm->ptk.tk1, keylen) < 0) {
     547                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     548                 :            :                         "WPA: Failed to set PTK to the "
     549                 :            :                         "driver (alg=%d keylen=%d bssid=" MACSTR ")",
     550                 :          0 :                         alg, keylen, MAC2STR(sm->bssid));
     551                 :          0 :                 return -1;
     552                 :            :         }
     553                 :            : 
     554         [ -  + ]:        222 :         if (sm->wpa_ptk_rekey) {
     555                 :          0 :                 eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
     556                 :          0 :                 eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk,
     557                 :            :                                        sm, NULL);
     558                 :            :         }
     559                 :            : 
     560                 :        222 :         return 0;
     561                 :            : }
     562                 :            : 
     563                 :            : 
     564                 :        223 : static int wpa_supplicant_check_group_cipher(struct wpa_sm *sm,
     565                 :            :                                              int group_cipher,
     566                 :            :                                              int keylen, int maxkeylen,
     567                 :            :                                              int *key_rsc_len,
     568                 :            :                                              enum wpa_alg *alg)
     569                 :            : {
     570                 :            :         int klen;
     571                 :            : 
     572                 :        223 :         *alg = wpa_cipher_to_alg(group_cipher);
     573         [ -  + ]:        223 :         if (*alg == WPA_ALG_NONE) {
     574                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     575                 :            :                         "WPA: Unsupported Group Cipher %d",
     576                 :            :                         group_cipher);
     577                 :          0 :                 return -1;
     578                 :            :         }
     579                 :        223 :         *key_rsc_len = wpa_cipher_rsc_len(group_cipher);
     580                 :            : 
     581                 :        223 :         klen = wpa_cipher_key_len(group_cipher);
     582 [ +  - ][ -  + ]:        223 :         if (keylen != klen || maxkeylen < klen) {
     583                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     584                 :            :                         "WPA: Unsupported %s Group Cipher key length %d (%d)",
     585                 :            :                         wpa_cipher_txt(group_cipher), keylen, maxkeylen);
     586                 :          0 :                 return -1;
     587                 :            :         }
     588                 :        223 :         return 0;
     589                 :            : }
     590                 :            : 
     591                 :            : 
     592                 :            : struct wpa_gtk_data {
     593                 :            :         enum wpa_alg alg;
     594                 :            :         int tx, key_rsc_len, keyidx;
     595                 :            :         u8 gtk[32];
     596                 :            :         int gtk_len;
     597                 :            : };
     598                 :            : 
     599                 :            : 
     600                 :        224 : static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
     601                 :            :                                       const struct wpa_gtk_data *gd,
     602                 :            :                                       const u8 *key_rsc)
     603                 :            : {
     604                 :        224 :         const u8 *_gtk = gd->gtk;
     605                 :            :         u8 gtk_buf[32];
     606                 :            : 
     607                 :        224 :         wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len);
     608                 :        224 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     609                 :            :                 "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)",
     610                 :            :                 gd->keyidx, gd->tx, gd->gtk_len);
     611                 :        224 :         wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len);
     612         [ +  + ]:        224 :         if (sm->group_cipher == WPA_CIPHER_TKIP) {
     613                 :            :                 /* Swap Tx/Rx keys for Michael MIC */
     614                 :         13 :                 os_memcpy(gtk_buf, gd->gtk, 16);
     615                 :         13 :                 os_memcpy(gtk_buf + 16, gd->gtk + 24, 8);
     616                 :         13 :                 os_memcpy(gtk_buf + 24, gd->gtk + 16, 8);
     617                 :         13 :                 _gtk = gtk_buf;
     618                 :            :         }
     619         [ -  + ]:        224 :         if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
     620         [ #  # ]:          0 :                 if (wpa_sm_set_key(sm, gd->alg, NULL,
     621                 :          0 :                                    gd->keyidx, 1, key_rsc, gd->key_rsc_len,
     622                 :          0 :                                    _gtk, gd->gtk_len) < 0) {
     623                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     624                 :            :                                 "WPA: Failed to set GTK to the driver "
     625                 :            :                                 "(Group only)");
     626                 :          0 :                         return -1;
     627                 :            :                 }
     628         [ -  + ]:        224 :         } else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr,
     629                 :        224 :                                   gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len,
     630                 :        224 :                                   _gtk, gd->gtk_len) < 0) {
     631                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     632                 :            :                         "WPA: Failed to set GTK to "
     633                 :            :                         "the driver (alg=%d keylen=%d keyidx=%d)",
     634                 :          0 :                         gd->alg, gd->gtk_len, gd->keyidx);
     635                 :          0 :                 return -1;
     636                 :            :         }
     637                 :            : 
     638                 :        224 :         return 0;
     639                 :            : }
     640                 :            : 
     641                 :            : 
     642                 :        224 : static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
     643                 :            :                                                 int tx)
     644                 :            : {
     645 [ -  + ][ #  # ]:        224 :         if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) {
     646                 :            :                 /* Ignore Tx bit for GTK if a pairwise key is used. One AP
     647                 :            :                  * seemed to set this bit (incorrectly, since Tx is only when
     648                 :            :                  * doing Group Key only APs) and without this workaround, the
     649                 :            :                  * data connection does not work because wpa_supplicant
     650                 :            :                  * configured non-zero keyidx to be used for unicast. */
     651                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
     652                 :            :                         "WPA: Tx bit set for GTK, but pairwise "
     653                 :            :                         "keys are used - ignore Tx bit");
     654                 :          0 :                 return 0;
     655                 :            :         }
     656                 :        224 :         return tx;
     657                 :            : }
     658                 :            : 
     659                 :            : 
     660                 :        216 : static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
     661                 :            :                                        const struct wpa_eapol_key *key,
     662                 :            :                                        const u8 *gtk, size_t gtk_len,
     663                 :            :                                        int key_info)
     664                 :            : {
     665                 :            :         struct wpa_gtk_data gd;
     666                 :            : 
     667                 :            :         /*
     668                 :            :          * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x
     669                 :            :          * GTK KDE format:
     670                 :            :          * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7]
     671                 :            :          * Reserved [bits 0-7]
     672                 :            :          * GTK
     673                 :            :          */
     674                 :            : 
     675                 :        216 :         os_memset(&gd, 0, sizeof(gd));
     676                 :        216 :         wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake",
     677                 :            :                         gtk, gtk_len);
     678                 :            : 
     679 [ +  - ][ -  + ]:        216 :         if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk))
     680                 :          0 :                 return -1;
     681                 :            : 
     682                 :        216 :         gd.keyidx = gtk[0] & 0x3;
     683                 :        216 :         gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
     684                 :        216 :                                                      !!(gtk[0] & BIT(2)));
     685                 :        216 :         gtk += 2;
     686                 :        216 :         gtk_len -= 2;
     687                 :            : 
     688                 :        216 :         os_memcpy(gd.gtk, gtk, gtk_len);
     689                 :        216 :         gd.gtk_len = gtk_len;
     690                 :            : 
     691   [ +  -  +  - ]:        432 :         if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED &&
     692                 :        216 :             (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
     693                 :            :                                                gtk_len, gtk_len,
     694         [ -  + ]:        216 :                                                &gd.key_rsc_len, &gd.alg) ||
     695                 :        216 :              wpa_supplicant_install_gtk(sm, &gd, key->key_rsc))) {
     696                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     697                 :            :                         "RSN: Failed to install GTK");
     698                 :          0 :                 return -1;
     699                 :            :         }
     700                 :            : 
     701                 :        216 :         wpa_supplicant_key_neg_complete(sm, sm->bssid,
     702                 :            :                                         key_info & WPA_KEY_INFO_SECURE);
     703                 :        216 :         return 0;
     704                 :            : }
     705                 :            : 
     706                 :            : 
     707                 :        223 : static int ieee80211w_set_keys(struct wpa_sm *sm,
     708                 :            :                                struct wpa_eapol_ie_parse *ie)
     709                 :            : {
     710                 :            : #ifdef CONFIG_IEEE80211W
     711         [ +  + ]:        223 :         if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC)
     712                 :        211 :                 return 0;
     713                 :            : 
     714         [ +  - ]:         12 :         if (ie->igtk) {
     715                 :            :                 const struct wpa_igtk_kde *igtk;
     716                 :            :                 u16 keyidx;
     717         [ -  + ]:         12 :                 if (ie->igtk_len != sizeof(*igtk))
     718                 :          0 :                         return -1;
     719                 :         12 :                 igtk = (const struct wpa_igtk_kde *) ie->igtk;
     720                 :         12 :                 keyidx = WPA_GET_LE16(igtk->keyid);
     721                 :         12 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d "
     722                 :            :                         "pn %02x%02x%02x%02x%02x%02x",
     723                 :            :                         keyidx, MAC2STR(igtk->pn));
     724                 :         12 :                 wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK",
     725                 :         12 :                                 igtk->igtk, WPA_IGTK_LEN);
     726         [ -  + ]:         12 :                 if (keyidx > 4095) {
     727                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     728                 :            :                                 "WPA: Invalid IGTK KeyID %d", keyidx);
     729                 :          0 :                         return -1;
     730                 :            :                 }
     731         [ -  + ]:         12 :                 if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr,
     732                 :         12 :                                    keyidx, 0, igtk->pn, sizeof(igtk->pn),
     733                 :         12 :                                    igtk->igtk, WPA_IGTK_LEN) < 0) {
     734                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     735                 :            :                                 "WPA: Failed to configure IGTK to the driver");
     736                 :          0 :                         return -1;
     737                 :            :                 }
     738                 :            :         }
     739                 :            : 
     740                 :        223 :         return 0;
     741                 :            : #else /* CONFIG_IEEE80211W */
     742                 :            :         return 0;
     743                 :            : #endif /* CONFIG_IEEE80211W */
     744                 :            : }
     745                 :            : 
     746                 :            : 
     747                 :          0 : static void wpa_report_ie_mismatch(struct wpa_sm *sm,
     748                 :            :                                    const char *reason, const u8 *src_addr,
     749                 :            :                                    const u8 *wpa_ie, size_t wpa_ie_len,
     750                 :            :                                    const u8 *rsn_ie, size_t rsn_ie_len)
     751                 :            : {
     752                 :          0 :         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")",
     753                 :          0 :                 reason, MAC2STR(src_addr));
     754                 :            : 
     755         [ #  # ]:          0 :         if (sm->ap_wpa_ie) {
     756                 :          0 :                 wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp",
     757                 :          0 :                             sm->ap_wpa_ie, sm->ap_wpa_ie_len);
     758                 :            :         }
     759         [ #  # ]:          0 :         if (wpa_ie) {
     760         [ #  # ]:          0 :                 if (!sm->ap_wpa_ie) {
     761                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
     762                 :            :                                 "WPA: No WPA IE in Beacon/ProbeResp");
     763                 :            :                 }
     764                 :          0 :                 wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg",
     765                 :            :                             wpa_ie, wpa_ie_len);
     766                 :            :         }
     767                 :            : 
     768         [ #  # ]:          0 :         if (sm->ap_rsn_ie) {
     769                 :          0 :                 wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp",
     770                 :          0 :                             sm->ap_rsn_ie, sm->ap_rsn_ie_len);
     771                 :            :         }
     772         [ #  # ]:          0 :         if (rsn_ie) {
     773         [ #  # ]:          0 :                 if (!sm->ap_rsn_ie) {
     774                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
     775                 :            :                                 "WPA: No RSN IE in Beacon/ProbeResp");
     776                 :            :                 }
     777                 :          0 :                 wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg",
     778                 :            :                             rsn_ie, rsn_ie_len);
     779                 :            :         }
     780                 :            : 
     781                 :          0 :         wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
     782                 :          0 : }
     783                 :            : 
     784                 :            : 
     785                 :            : #ifdef CONFIG_IEEE80211R
     786                 :            : 
     787                 :          8 : static int ft_validate_mdie(struct wpa_sm *sm,
     788                 :            :                             const unsigned char *src_addr,
     789                 :            :                             struct wpa_eapol_ie_parse *ie,
     790                 :            :                             const u8 *assoc_resp_mdie)
     791                 :            : {
     792                 :            :         struct rsn_mdie *mdie;
     793                 :            : 
     794                 :          8 :         mdie = (struct rsn_mdie *) (ie->mdie + 2);
     795 [ +  - ][ +  - ]:          8 :         if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) ||
                 [ -  + ]
     796                 :          8 :             os_memcmp(mdie->mobility_domain, sm->mobility_domain,
     797                 :            :                       MOBILITY_DOMAIN_ID_LEN) != 0) {
     798                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did "
     799                 :            :                         "not match with the current mobility domain");
     800                 :          0 :                 return -1;
     801                 :            :         }
     802                 :            : 
     803 [ +  - ][ +  - ]:          8 :         if (assoc_resp_mdie &&
     804         [ -  + ]:          8 :             (assoc_resp_mdie[1] != ie->mdie[1] ||
     805                 :          8 :              os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) {
     806                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch");
     807                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4",
     808                 :          0 :                             ie->mdie, 2 + ie->mdie[1]);
     809                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response",
     810                 :          0 :                             assoc_resp_mdie, 2 + assoc_resp_mdie[1]);
     811                 :          0 :                 return -1;
     812                 :            :         }
     813                 :            : 
     814                 :          8 :         return 0;
     815                 :            : }
     816                 :            : 
     817                 :            : 
     818                 :          8 : static int ft_validate_ftie(struct wpa_sm *sm,
     819                 :            :                             const unsigned char *src_addr,
     820                 :            :                             struct wpa_eapol_ie_parse *ie,
     821                 :            :                             const u8 *assoc_resp_ftie)
     822                 :            : {
     823         [ -  + ]:          8 :         if (ie->ftie == NULL) {
     824                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     825                 :            :                         "FT: No FTIE in EAPOL-Key msg 3/4");
     826                 :          0 :                 return -1;
     827                 :            :         }
     828                 :            : 
     829         [ -  + ]:          8 :         if (assoc_resp_ftie == NULL)
     830                 :          0 :                 return 0;
     831                 :            : 
     832 [ +  - ][ -  + ]:          8 :         if (assoc_resp_ftie[1] != ie->ftie[1] ||
     833                 :          8 :             os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) {
     834                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch");
     835                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4",
     836                 :          0 :                             ie->ftie, 2 + ie->ftie[1]);
     837                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response",
     838                 :          0 :                             assoc_resp_ftie, 2 + assoc_resp_ftie[1]);
     839                 :          0 :                 return -1;
     840                 :            :         }
     841                 :            : 
     842                 :          8 :         return 0;
     843                 :            : }
     844                 :            : 
     845                 :            : 
     846                 :          8 : static int ft_validate_rsnie(struct wpa_sm *sm,
     847                 :            :                              const unsigned char *src_addr,
     848                 :            :                              struct wpa_eapol_ie_parse *ie)
     849                 :            : {
     850                 :            :         struct wpa_ie_data rsn;
     851                 :            : 
     852         [ -  + ]:          8 :         if (!ie->rsn_ie)
     853                 :          0 :                 return 0;
     854                 :            : 
     855                 :            :         /*
     856                 :            :          * Verify that PMKR1Name from EAPOL-Key message 3/4
     857                 :            :          * matches with the value we derived.
     858                 :            :          */
     859 [ +  - ][ +  - ]:          8 :         if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 ||
     860         [ -  + ]:          8 :             rsn.num_pmkid != 1 || rsn.pmkid == NULL) {
     861                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in "
     862                 :            :                         "FT 4-way handshake message 3/4");
     863                 :          0 :                 return -1;
     864                 :            :         }
     865                 :            : 
     866         [ -  + ]:          8 :         if (os_memcmp(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) {
     867                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     868                 :            :                         "FT: PMKR1Name mismatch in "
     869                 :            :                         "FT 4-way handshake message 3/4");
     870                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator",
     871                 :          0 :                             rsn.pmkid, WPA_PMK_NAME_LEN);
     872                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
     873                 :          0 :                             sm->pmk_r1_name, WPA_PMK_NAME_LEN);
     874                 :          0 :                 return -1;
     875                 :            :         }
     876                 :            : 
     877                 :          8 :         return 0;
     878                 :            : }
     879                 :            : 
     880                 :            : 
     881                 :          8 : static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
     882                 :            :                                          const unsigned char *src_addr,
     883                 :            :                                          struct wpa_eapol_ie_parse *ie)
     884                 :            : {
     885                 :          8 :         const u8 *pos, *end, *mdie = NULL, *ftie = NULL;
     886                 :            : 
     887         [ +  - ]:          8 :         if (sm->assoc_resp_ies) {
     888                 :          8 :                 pos = sm->assoc_resp_ies;
     889                 :          8 :                 end = pos + sm->assoc_resp_ies_len;
     890         [ +  + ]:         24 :                 while (pos + 2 < end) {
     891         [ -  + ]:         16 :                         if (pos + 2 + pos[1] > end)
     892                 :          0 :                                 break;
     893      [ +  +  - ]:         16 :                         switch (*pos) {
     894                 :            :                         case WLAN_EID_MOBILITY_DOMAIN:
     895                 :          8 :                                 mdie = pos;
     896                 :          8 :                                 break;
     897                 :            :                         case WLAN_EID_FAST_BSS_TRANSITION:
     898                 :          8 :                                 ftie = pos;
     899                 :          8 :                                 break;
     900                 :            :                         }
     901                 :         16 :                         pos += 2 + pos[1];
     902                 :            :                 }
     903                 :            :         }
     904                 :            : 
     905   [ +  -  +  - ]:         16 :         if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 ||
     906         [ -  + ]:         16 :             ft_validate_ftie(sm, src_addr, ie, ftie) < 0 ||
     907                 :          8 :             ft_validate_rsnie(sm, src_addr, ie) < 0)
     908                 :          0 :                 return -1;
     909                 :            : 
     910                 :          8 :         return 0;
     911                 :            : }
     912                 :            : 
     913                 :            : #endif /* CONFIG_IEEE80211R */
     914                 :            : 
     915                 :            : 
     916                 :        222 : static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
     917                 :            :                                       const unsigned char *src_addr,
     918                 :            :                                       struct wpa_eapol_ie_parse *ie)
     919                 :            : {
     920 [ +  + ][ +  + ]:        222 :         if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) {
     921                 :          6 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
     922                 :            :                         "WPA: No WPA/RSN IE for this AP known. "
     923                 :            :                         "Trying to get from scan results");
     924         [ -  + ]:          6 :                 if (wpa_sm_get_beacon_ie(sm) < 0) {
     925                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
     926                 :            :                                 "WPA: Could not find AP from "
     927                 :            :                                 "the scan results");
     928                 :            :                 } else {
     929                 :          6 :                         wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
     930                 :            :                                 "WPA: Found the current AP from "
     931                 :            :                                 "updated scan results");
     932                 :            :                 }
     933                 :            :         }
     934                 :            : 
     935 [ +  + ][ -  + ]:        222 :         if (ie->wpa_ie == NULL && ie->rsn_ie == NULL &&
                 [ #  # ]
     936         [ #  # ]:          0 :             (sm->ap_wpa_ie || sm->ap_rsn_ie)) {
     937                 :          0 :                 wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
     938                 :            :                                        "with IE in Beacon/ProbeResp (no IE?)",
     939                 :            :                                        src_addr, ie->wpa_ie, ie->wpa_ie_len,
     940                 :            :                                        ie->rsn_ie, ie->rsn_ie_len);
     941                 :          0 :                 return -1;
     942                 :            :         }
     943                 :            : 
     944 [ +  + ][ +  - ]:        222 :         if ((ie->wpa_ie && sm->ap_wpa_ie &&
                 [ +  - ]
     945         [ +  - ]:         12 :              (ie->wpa_ie_len != sm->ap_wpa_ie_len ||
     946         [ +  + ]:        222 :               os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||
     947   [ +  -  -  + ]:        432 :             (ie->rsn_ie && sm->ap_rsn_ie &&
     948                 :        216 :              wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
     949                 :        216 :                                 sm->ap_rsn_ie, sm->ap_rsn_ie_len,
     950                 :            :                                 ie->rsn_ie, ie->rsn_ie_len))) {
     951                 :          0 :                 wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
     952                 :            :                                        "with IE in Beacon/ProbeResp",
     953                 :            :                                        src_addr, ie->wpa_ie, ie->wpa_ie_len,
     954                 :            :                                        ie->rsn_ie, ie->rsn_ie_len);
     955                 :          0 :                 return -1;
     956                 :            :         }
     957                 :            : 
     958 [ +  + ][ -  + ]:        222 :         if (sm->proto == WPA_PROTO_WPA &&
     959 [ #  # ][ #  # ]:          0 :             ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) {
     960                 :          0 :                 wpa_report_ie_mismatch(sm, "Possible downgrade attack "
     961                 :            :                                        "detected - RSN was enabled and RSN IE "
     962                 :            :                                        "was in msg 3/4, but not in "
     963                 :            :                                        "Beacon/ProbeResp",
     964                 :            :                                        src_addr, ie->wpa_ie, ie->wpa_ie_len,
     965                 :            :                                        ie->rsn_ie, ie->rsn_ie_len);
     966                 :          0 :                 return -1;
     967                 :            :         }
     968                 :            : 
     969                 :            : #ifdef CONFIG_IEEE80211R
     970   [ +  +  -  + ]:        230 :         if (wpa_key_mgmt_ft(sm->key_mgmt) &&
     971                 :          8 :             wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
     972                 :          0 :                 return -1;
     973                 :            : #endif /* CONFIG_IEEE80211R */
     974                 :            : 
     975                 :        222 :         return 0;
     976                 :            : }
     977                 :            : 
     978                 :            : 
     979                 :            : /**
     980                 :            :  * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake
     981                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     982                 :            :  * @dst: Destination address for the frame
     983                 :            :  * @key: Pointer to the EAPOL-Key frame header
     984                 :            :  * @ver: Version bits from EAPOL-Key Key Info
     985                 :            :  * @key_info: Key Info
     986                 :            :  * @kde: KDEs to include the EAPOL-Key frame
     987                 :            :  * @kde_len: Length of KDEs
     988                 :            :  * @ptk: PTK to use for keyed hash and encryption
     989                 :            :  * Returns: 0 on success, -1 on failure
     990                 :            :  */
     991                 :        223 : int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
     992                 :            :                                const struct wpa_eapol_key *key,
     993                 :            :                                u16 ver, u16 key_info,
     994                 :            :                                const u8 *kde, size_t kde_len,
     995                 :            :                                struct wpa_ptk *ptk)
     996                 :            : {
     997                 :            :         size_t rlen;
     998                 :            :         struct wpa_eapol_key *reply;
     999                 :            :         u8 *rbuf;
    1000                 :            : 
    1001         [ -  + ]:        223 :         if (kde)
    1002                 :          0 :                 wpa_hexdump(MSG_DEBUG, "WPA: KDE for msg 4/4", kde, kde_len);
    1003                 :            : 
    1004                 :        223 :         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
    1005                 :            :                                   sizeof(*reply) + kde_len,
    1006                 :            :                                   &rlen, (void *) &reply);
    1007         [ -  + ]:        223 :         if (rbuf == NULL)
    1008                 :          0 :                 return -1;
    1009                 :            : 
    1010         [ +  + ]:        223 :         reply->type = sm->proto == WPA_PROTO_RSN ?
    1011                 :            :                 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
    1012                 :        223 :         key_info &= WPA_KEY_INFO_SECURE;
    1013                 :        223 :         key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC;
    1014                 :        223 :         WPA_PUT_BE16(reply->key_info, key_info);
    1015         [ +  + ]:        223 :         if (sm->proto == WPA_PROTO_RSN)
    1016                 :        217 :                 WPA_PUT_BE16(reply->key_length, 0);
    1017                 :            :         else
    1018                 :          6 :                 os_memcpy(reply->key_length, key->key_length, 2);
    1019                 :        223 :         os_memcpy(reply->replay_counter, key->replay_counter,
    1020                 :            :                   WPA_REPLAY_COUNTER_LEN);
    1021                 :            : 
    1022                 :        223 :         WPA_PUT_BE16(reply->key_data_length, kde_len);
    1023         [ -  + ]:        223 :         if (kde)
    1024                 :          0 :                 os_memcpy(reply + 1, kde, kde_len);
    1025                 :            : 
    1026                 :        223 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
    1027                 :        223 :         wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,
    1028                 :        223 :                            rbuf, rlen, reply->key_mic);
    1029                 :            : 
    1030                 :        223 :         return 0;
    1031                 :            : }
    1032                 :            : 
    1033                 :            : 
    1034                 :        222 : static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
    1035                 :            :                                           const struct wpa_eapol_key *key,
    1036                 :            :                                           u16 ver)
    1037                 :            : {
    1038                 :            :         u16 key_info, keylen, len;
    1039                 :            :         const u8 *pos;
    1040                 :            :         struct wpa_eapol_ie_parse ie;
    1041                 :            : 
    1042                 :        222 :         wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
    1043                 :        222 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 3 of 4-Way "
    1044                 :            :                 "Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver);
    1045                 :            : 
    1046                 :        222 :         key_info = WPA_GET_BE16(key->key_info);
    1047                 :            : 
    1048                 :        222 :         pos = (const u8 *) (key + 1);
    1049                 :        222 :         len = WPA_GET_BE16(key->key_data_length);
    1050                 :        222 :         wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len);
    1051         [ -  + ]:        222 :         if (wpa_supplicant_parse_ies(pos, len, &ie) < 0)
    1052                 :          0 :                 goto failed;
    1053 [ +  + ][ -  + ]:        222 :         if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
    1054                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1055                 :            :                         "WPA: GTK IE in unencrypted key data");
    1056                 :          0 :                 goto failed;
    1057                 :            :         }
    1058                 :            : #ifdef CONFIG_IEEE80211W
    1059 [ +  + ][ -  + ]:        222 :         if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
    1060                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1061                 :            :                         "WPA: IGTK KDE in unencrypted key data");
    1062                 :          0 :                 goto failed;
    1063                 :            :         }
    1064                 :            : 
    1065 [ +  + ][ -  + ]:        222 :         if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) {
    1066                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1067                 :            :                         "WPA: Invalid IGTK KDE length %lu",
    1068                 :            :                         (unsigned long) ie.igtk_len);
    1069                 :          0 :                 goto failed;
    1070                 :            :         }
    1071                 :            : #endif /* CONFIG_IEEE80211W */
    1072                 :            : 
    1073         [ -  + ]:        222 :         if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
    1074                 :          0 :                 goto failed;
    1075                 :            : 
    1076         [ -  + ]:        222 :         if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
    1077                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1078                 :            :                         "WPA: ANonce from message 1 of 4-Way Handshake "
    1079                 :            :                         "differs from 3 of 4-Way Handshake - drop packet (src="
    1080                 :          0 :                         MACSTR ")", MAC2STR(sm->bssid));
    1081                 :          0 :                 goto failed;
    1082                 :            :         }
    1083                 :            : 
    1084                 :        222 :         keylen = WPA_GET_BE16(key->key_length);
    1085         [ -  + ]:        222 :         if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) {
    1086                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1087                 :            :                         "WPA: Invalid %s key length %d (src=" MACSTR
    1088                 :          0 :                         ")", wpa_cipher_txt(sm->pairwise_cipher), keylen,
    1089                 :          0 :                         MAC2STR(sm->bssid));
    1090                 :          0 :                 goto failed;
    1091                 :            :         }
    1092                 :            : 
    1093         [ -  + ]:        222 :         if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
    1094                 :            :                                        NULL, 0, &sm->ptk)) {
    1095                 :          0 :                 goto failed;
    1096                 :            :         }
    1097                 :            : 
    1098                 :            :         /* SNonce was successfully used in msg 3/4, so mark it to be renewed
    1099                 :            :          * for the next 4-Way Handshake. If msg 3 is received again, the old
    1100                 :            :          * SNonce will still be used to avoid changing PTK. */
    1101                 :        222 :         sm->renew_snonce = 1;
    1102                 :            : 
    1103         [ +  - ]:        222 :         if (key_info & WPA_KEY_INFO_INSTALL) {
    1104         [ -  + ]:        222 :                 if (wpa_supplicant_install_ptk(sm, key))
    1105                 :          0 :                         goto failed;
    1106                 :            :         }
    1107                 :            : 
    1108         [ +  + ]:        222 :         if (key_info & WPA_KEY_INFO_SECURE) {
    1109                 :        216 :                 wpa_sm_mlme_setprotection(
    1110                 :        216 :                         sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,
    1111                 :            :                         MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
    1112                 :        216 :                 eapol_sm_notify_portValid(sm->eapol, TRUE);
    1113                 :            :         }
    1114                 :        222 :         wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
    1115                 :            : 
    1116         [ -  + ]:        222 :         if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) {
    1117                 :          0 :                 wpa_supplicant_key_neg_complete(sm, sm->bssid,
    1118                 :            :                                                 key_info & WPA_KEY_INFO_SECURE);
    1119   [ +  +  -  + ]:        438 :         } else if (ie.gtk &&
    1120                 :        216 :             wpa_supplicant_pairwise_gtk(sm, key,
    1121                 :            :                                         ie.gtk, ie.gtk_len, key_info) < 0) {
    1122                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1123                 :            :                         "RSN: Failed to configure GTK");
    1124                 :          0 :                 goto failed;
    1125                 :            :         }
    1126                 :            : 
    1127         [ -  + ]:        222 :         if (ieee80211w_set_keys(sm, &ie) < 0) {
    1128                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1129                 :            :                         "RSN: Failed to configure IGTK");
    1130                 :          0 :                 goto failed;
    1131                 :            :         }
    1132                 :            : 
    1133         [ +  + ]:        222 :         if (ie.gtk)
    1134                 :        216 :                 wpa_sm_set_rekey_offload(sm);
    1135                 :            : 
    1136                 :        222 :         return;
    1137                 :            : 
    1138                 :            : failed:
    1139                 :          0 :         wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
    1140                 :            : }
    1141                 :            : 
    1142                 :            : 
    1143                 :          1 : static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
    1144                 :            :                                              const u8 *keydata,
    1145                 :            :                                              size_t keydatalen,
    1146                 :            :                                              u16 key_info,
    1147                 :            :                                              struct wpa_gtk_data *gd)
    1148                 :            : {
    1149                 :            :         int maxkeylen;
    1150                 :            :         struct wpa_eapol_ie_parse ie;
    1151                 :            : 
    1152                 :          1 :         wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen);
    1153         [ -  + ]:          1 :         if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0)
    1154                 :          0 :                 return -1;
    1155 [ +  - ][ -  + ]:          1 :         if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
    1156                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1157                 :            :                         "WPA: GTK IE in unencrypted key data");
    1158                 :          0 :                 return -1;
    1159                 :            :         }
    1160         [ -  + ]:          1 :         if (ie.gtk == NULL) {
    1161                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1162                 :            :                         "WPA: No GTK IE in Group Key msg 1/2");
    1163                 :          0 :                 return -1;
    1164                 :            :         }
    1165                 :          1 :         maxkeylen = gd->gtk_len = ie.gtk_len - 2;
    1166                 :            : 
    1167         [ -  + ]:          1 :         if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
    1168                 :            :                                               gd->gtk_len, maxkeylen,
    1169                 :            :                                               &gd->key_rsc_len, &gd->alg))
    1170                 :          0 :                 return -1;
    1171                 :            : 
    1172                 :          1 :         wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake",
    1173                 :          1 :                     ie.gtk, ie.gtk_len);
    1174                 :          1 :         gd->keyidx = ie.gtk[0] & 0x3;
    1175                 :          1 :         gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
    1176                 :          1 :                                                       !!(ie.gtk[0] & BIT(2)));
    1177         [ -  + ]:          1 :         if (ie.gtk_len - 2 > sizeof(gd->gtk)) {
    1178                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1179                 :            :                         "RSN: Too long GTK in GTK IE (len=%lu)",
    1180                 :          0 :                         (unsigned long) ie.gtk_len - 2);
    1181                 :          0 :                 return -1;
    1182                 :            :         }
    1183                 :          1 :         os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2);
    1184                 :            : 
    1185         [ -  + ]:          1 :         if (ieee80211w_set_keys(sm, &ie) < 0)
    1186                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1187                 :            :                         "RSN: Failed to configure IGTK");
    1188                 :            : 
    1189                 :          1 :         return 0;
    1190                 :            : }
    1191                 :            : 
    1192                 :            : 
    1193                 :          6 : static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
    1194                 :            :                                              const struct wpa_eapol_key *key,
    1195                 :            :                                              size_t keydatalen, int key_info,
    1196                 :            :                                              size_t extra_len, u16 ver,
    1197                 :            :                                              struct wpa_gtk_data *gd)
    1198                 :            : {
    1199                 :            :         size_t maxkeylen;
    1200                 :            :         u8 ek[32];
    1201                 :            : 
    1202                 :          6 :         gd->gtk_len = WPA_GET_BE16(key->key_length);
    1203                 :          6 :         maxkeylen = keydatalen;
    1204         [ -  + ]:          6 :         if (keydatalen > extra_len) {
    1205                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1206                 :            :                         "WPA: Truncated EAPOL-Key packet: "
    1207                 :            :                         "key_data_length=%lu > extra_len=%lu",
    1208                 :            :                         (unsigned long) keydatalen, (unsigned long) extra_len);
    1209                 :          0 :                 return -1;
    1210                 :            :         }
    1211         [ -  + ]:          6 :         if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
    1212         [ #  # ]:          0 :                 if (maxkeylen < 8) {
    1213                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1214                 :            :                                 "WPA: Too short maxkeylen (%lu)",
    1215                 :            :                                 (unsigned long) maxkeylen);
    1216                 :          0 :                         return -1;
    1217                 :            :                 }
    1218                 :          0 :                 maxkeylen -= 8;
    1219                 :            :         }
    1220                 :            : 
    1221         [ -  + ]:          6 :         if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
    1222                 :            :                                               gd->gtk_len, maxkeylen,
    1223                 :            :                                               &gd->key_rsc_len, &gd->alg))
    1224                 :          0 :                 return -1;
    1225                 :            : 
    1226                 :          6 :         gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
    1227                 :            :                 WPA_KEY_INFO_KEY_INDEX_SHIFT;
    1228         [ +  - ]:          6 :         if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
    1229                 :          6 :                 os_memcpy(ek, key->key_iv, 16);
    1230                 :          6 :                 os_memcpy(ek + 16, sm->ptk.kek, 16);
    1231         [ -  + ]:          6 :                 if (keydatalen > sizeof(gd->gtk)) {
    1232                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1233                 :            :                                 "WPA: RC4 key data too long (%lu)",
    1234                 :            :                                 (unsigned long) keydatalen);
    1235                 :          0 :                         return -1;
    1236                 :            :                 }
    1237                 :          6 :                 os_memcpy(gd->gtk, key + 1, keydatalen);
    1238         [ -  + ]:          6 :                 if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) {
    1239                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
    1240                 :            :                                 "WPA: RC4 failed");
    1241                 :          0 :                         return -1;
    1242                 :            :                 }
    1243         [ #  # ]:          0 :         } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
    1244         [ #  # ]:          0 :                 if (keydatalen % 8) {
    1245                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1246                 :            :                                 "WPA: Unsupported AES-WRAP len %lu",
    1247                 :            :                                 (unsigned long) keydatalen);
    1248                 :          0 :                         return -1;
    1249                 :            :                 }
    1250         [ #  # ]:          0 :                 if (maxkeylen > sizeof(gd->gtk)) {
    1251                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1252                 :            :                                 "WPA: AES-WRAP key data "
    1253                 :            :                                 "too long (keydatalen=%lu maxkeylen=%lu)",
    1254                 :            :                                 (unsigned long) keydatalen,
    1255                 :            :                                 (unsigned long) maxkeylen);
    1256                 :          0 :                         return -1;
    1257                 :            :                 }
    1258         [ #  # ]:          0 :                 if (aes_unwrap(sm->ptk.kek, maxkeylen / 8,
    1259                 :          0 :                                (const u8 *) (key + 1), gd->gtk)) {
    1260                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1261                 :            :                                 "WPA: AES unwrap failed - could not decrypt "
    1262                 :            :                                 "GTK");
    1263                 :          0 :                         return -1;
    1264                 :            :                 }
    1265                 :            :         } else {
    1266                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1267                 :            :                         "WPA: Unsupported key_info type %d", ver);
    1268                 :          0 :                 return -1;
    1269                 :            :         }
    1270                 :          6 :         gd->tx = wpa_supplicant_gtk_tx_bit_workaround(
    1271                 :          6 :                 sm, !!(key_info & WPA_KEY_INFO_TXRX));
    1272                 :          6 :         return 0;
    1273                 :            : }
    1274                 :            : 
    1275                 :            : 
    1276                 :          7 : static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
    1277                 :            :                                       const struct wpa_eapol_key *key,
    1278                 :            :                                       int ver, u16 key_info)
    1279                 :            : {
    1280                 :            :         size_t rlen;
    1281                 :            :         struct wpa_eapol_key *reply;
    1282                 :            :         u8 *rbuf;
    1283                 :            : 
    1284                 :          7 :         rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
    1285                 :            :                                   sizeof(*reply), &rlen, (void *) &reply);
    1286         [ -  + ]:          7 :         if (rbuf == NULL)
    1287                 :          0 :                 return -1;
    1288                 :            : 
    1289         [ +  + ]:          7 :         reply->type = sm->proto == WPA_PROTO_RSN ?
    1290                 :            :                 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
    1291                 :          7 :         key_info &= WPA_KEY_INFO_KEY_INDEX_MASK;
    1292                 :          7 :         key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
    1293                 :          7 :         WPA_PUT_BE16(reply->key_info, key_info);
    1294         [ +  + ]:          7 :         if (sm->proto == WPA_PROTO_RSN)
    1295                 :          1 :                 WPA_PUT_BE16(reply->key_length, 0);
    1296                 :            :         else
    1297                 :          6 :                 os_memcpy(reply->key_length, key->key_length, 2);
    1298                 :          7 :         os_memcpy(reply->replay_counter, key->replay_counter,
    1299                 :            :                   WPA_REPLAY_COUNTER_LEN);
    1300                 :            : 
    1301                 :          7 :         WPA_PUT_BE16(reply->key_data_length, 0);
    1302                 :            : 
    1303                 :          7 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
    1304                 :          7 :         wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL,
    1305                 :          7 :                            rbuf, rlen, reply->key_mic);
    1306                 :            : 
    1307                 :          7 :         return 0;
    1308                 :            : }
    1309                 :            : 
    1310                 :            : 
    1311                 :          7 : static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
    1312                 :            :                                           const unsigned char *src_addr,
    1313                 :            :                                           const struct wpa_eapol_key *key,
    1314                 :            :                                           int extra_len, u16 ver)
    1315                 :            : {
    1316                 :            :         u16 key_info, keydatalen;
    1317                 :            :         int rekey, ret;
    1318                 :            :         struct wpa_gtk_data gd;
    1319                 :            : 
    1320                 :          7 :         os_memset(&gd, 0, sizeof(gd));
    1321                 :            : 
    1322                 :          7 :         rekey = wpa_sm_get_state(sm) == WPA_COMPLETED;
    1323                 :          7 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key "
    1324                 :            :                 "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
    1325                 :            : 
    1326                 :          7 :         key_info = WPA_GET_BE16(key->key_info);
    1327                 :          7 :         keydatalen = WPA_GET_BE16(key->key_data_length);
    1328                 :            : 
    1329         [ +  + ]:          7 :         if (sm->proto == WPA_PROTO_RSN) {
    1330                 :          1 :                 ret = wpa_supplicant_process_1_of_2_rsn(sm,
    1331                 :            :                                                         (const u8 *) (key + 1),
    1332                 :            :                                                         keydatalen, key_info,
    1333                 :            :                                                         &gd);
    1334                 :            :         } else {
    1335                 :          6 :                 ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen,
    1336                 :            :                                                         key_info, extra_len,
    1337                 :            :                                                         ver, &gd);
    1338                 :            :         }
    1339                 :            : 
    1340                 :          7 :         wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
    1341                 :            : 
    1342         [ -  + ]:          7 :         if (ret)
    1343                 :          0 :                 goto failed;
    1344                 :            : 
    1345   [ +  -  +  - ]:         14 :         if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) ||
    1346                 :          7 :             wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
    1347                 :            :                 goto failed;
    1348                 :            : 
    1349         [ +  + ]:          7 :         if (rekey) {
    1350                 :          1 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying "
    1351                 :            :                         "completed with " MACSTR " [GTK=%s]",
    1352                 :          7 :                         MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
    1353                 :          1 :                 wpa_sm_cancel_auth_timeout(sm);
    1354                 :          1 :                 wpa_sm_set_state(sm, WPA_COMPLETED);
    1355                 :            :         } else {
    1356                 :          6 :                 wpa_supplicant_key_neg_complete(sm, sm->bssid,
    1357                 :            :                                                 key_info &
    1358                 :            :                                                 WPA_KEY_INFO_SECURE);
    1359                 :            :         }
    1360                 :            : 
    1361                 :          7 :         wpa_sm_set_rekey_offload(sm);
    1362                 :            : 
    1363                 :          7 :         return;
    1364                 :            : 
    1365                 :            : failed:
    1366                 :          0 :         wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
    1367                 :            : }
    1368                 :            : 
    1369                 :            : 
    1370                 :        232 : static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
    1371                 :            :                                                struct wpa_eapol_key *key,
    1372                 :            :                                                u16 ver,
    1373                 :            :                                                const u8 *buf, size_t len)
    1374                 :            : {
    1375                 :            :         u8 mic[16];
    1376                 :        232 :         int ok = 0;
    1377                 :            : 
    1378                 :        232 :         os_memcpy(mic, key->key_mic, 16);
    1379         [ +  + ]:        232 :         if (sm->tptk_set) {
    1380                 :        222 :                 os_memset(key->key_mic, 0, 16);
    1381                 :        222 :                 wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len,
    1382                 :        222 :                                   key->key_mic);
    1383         [ -  + ]:        222 :                 if (os_memcmp(mic, key->key_mic, 16) != 0) {
    1384                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1385                 :            :                                 "WPA: Invalid EAPOL-Key MIC "
    1386                 :            :                                 "when using TPTK - ignoring TPTK");
    1387                 :            :                 } else {
    1388                 :        222 :                         ok = 1;
    1389                 :        222 :                         sm->tptk_set = 0;
    1390                 :        222 :                         sm->ptk_set = 1;
    1391                 :        222 :                         os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
    1392                 :            :                 }
    1393                 :            :         }
    1394                 :            : 
    1395 [ +  + ][ +  - ]:        232 :         if (!ok && sm->ptk_set) {
    1396                 :         10 :                 os_memset(key->key_mic, 0, 16);
    1397                 :         10 :                 wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len,
    1398                 :         10 :                                   key->key_mic);
    1399         [ -  + ]:         10 :                 if (os_memcmp(mic, key->key_mic, 16) != 0) {
    1400                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1401                 :            :                                 "WPA: Invalid EAPOL-Key MIC - "
    1402                 :            :                                 "dropping packet");
    1403                 :          0 :                         return -1;
    1404                 :            :                 }
    1405                 :         10 :                 ok = 1;
    1406                 :            :         }
    1407                 :            : 
    1408         [ -  + ]:        232 :         if (!ok) {
    1409                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1410                 :            :                         "WPA: Could not verify EAPOL-Key MIC - "
    1411                 :            :                         "dropping packet");
    1412                 :          0 :                 return -1;
    1413                 :            :         }
    1414                 :            : 
    1415                 :        232 :         os_memcpy(sm->rx_replay_counter, key->replay_counter,
    1416                 :            :                   WPA_REPLAY_COUNTER_LEN);
    1417                 :        232 :         sm->rx_replay_counter_set = 1;
    1418                 :        232 :         return 0;
    1419                 :            : }
    1420                 :            : 
    1421                 :            : 
    1422                 :            : /* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
    1423                 :        219 : static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
    1424                 :            :                                            struct wpa_eapol_key *key, u16 ver)
    1425                 :            : {
    1426                 :        219 :         u16 keydatalen = WPA_GET_BE16(key->key_data_length);
    1427                 :            : 
    1428                 :        219 :         wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
    1429                 :            :                     (u8 *) (key + 1), keydatalen);
    1430         [ -  + ]:        219 :         if (!sm->ptk_set) {
    1431                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1432                 :            :                         "WPA: PTK not available, cannot decrypt EAPOL-Key Key "
    1433                 :            :                         "Data");
    1434                 :          0 :                 return -1;
    1435                 :            :         }
    1436                 :            : 
    1437                 :            :         /* Decrypt key data here so that this operation does not need
    1438                 :            :          * to be implemented separately for each message type. */
    1439         [ +  + ]:        219 :         if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
    1440                 :            :                 u8 ek[32];
    1441                 :          1 :                 os_memcpy(ek, key->key_iv, 16);
    1442                 :          1 :                 os_memcpy(ek + 16, sm->ptk.kek, 16);
    1443         [ -  + ]:          1 :                 if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) {
    1444                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
    1445                 :            :                                 "WPA: RC4 failed");
    1446                 :          0 :                         return -1;
    1447                 :            :                 }
    1448 [ +  + ][ +  - ]:        218 :         } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
    1449                 :        218 :                    ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
    1450                 :            :                 u8 *buf;
    1451         [ -  + ]:        218 :                 if (keydatalen % 8) {
    1452                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1453                 :            :                                 "WPA: Unsupported AES-WRAP len %d",
    1454                 :            :                                 keydatalen);
    1455                 :          0 :                         return -1;
    1456                 :            :                 }
    1457                 :        218 :                 keydatalen -= 8; /* AES-WRAP adds 8 bytes */
    1458                 :        218 :                 buf = os_malloc(keydatalen);
    1459         [ -  + ]:        218 :                 if (buf == NULL) {
    1460                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1461                 :            :                                 "WPA: No memory for AES-UNWRAP buffer");
    1462                 :          0 :                         return -1;
    1463                 :            :                 }
    1464         [ -  + ]:        218 :                 if (aes_unwrap(sm->ptk.kek, keydatalen / 8,
    1465                 :            :                                (u8 *) (key + 1), buf)) {
    1466                 :          0 :                         os_free(buf);
    1467                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1468                 :            :                                 "WPA: AES unwrap failed - "
    1469                 :            :                                 "could not decrypt EAPOL-Key key data");
    1470                 :          0 :                         return -1;
    1471                 :            :                 }
    1472                 :        218 :                 os_memcpy(key + 1, buf, keydatalen);
    1473                 :        218 :                 os_free(buf);
    1474                 :        218 :                 WPA_PUT_BE16(key->key_data_length, keydatalen);
    1475                 :            :         } else {
    1476                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1477                 :            :                         "WPA: Unsupported key_info type %d", ver);
    1478                 :          0 :                 return -1;
    1479                 :            :         }
    1480                 :        219 :         wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
    1481                 :            :                         (u8 *) (key + 1), keydatalen);
    1482                 :        219 :         return 0;
    1483                 :            : }
    1484                 :            : 
    1485                 :            : 
    1486                 :            : /**
    1487                 :            :  * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted
    1488                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    1489                 :            :  */
    1490                 :          1 : void wpa_sm_aborted_cached(struct wpa_sm *sm)
    1491                 :            : {
    1492 [ +  - ][ -  + ]:          1 :         if (sm && sm->cur_pmksa) {
    1493                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1494                 :            :                         "RSN: Cancelling PMKSA caching attempt");
    1495                 :          0 :                 sm->cur_pmksa = NULL;
    1496                 :            :         }
    1497                 :          1 : }
    1498                 :            : 
    1499                 :            : 
    1500                 :        478 : static void wpa_eapol_key_dump(struct wpa_sm *sm,
    1501                 :            :                                const struct wpa_eapol_key *key)
    1502                 :            : {
    1503                 :            : #ifndef CONFIG_NO_STDOUT_DEBUG
    1504                 :        478 :         u16 key_info = WPA_GET_BE16(key->key_info);
    1505                 :            : 
    1506                 :        478 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "  EAPOL-Key type=%d", key->type);
    1507 [ +  + ][ -  + ]:        478 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
         [ -  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
    1508                 :            :                 "  key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)",
    1509                 :            :                 key_info, key_info & WPA_KEY_INFO_TYPE_MASK,
    1510                 :            :                 (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
    1511                 :            :                 WPA_KEY_INFO_KEY_INDEX_SHIFT,
    1512                 :            :                 (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13,
    1513                 :            :                 key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group",
    1514                 :            :                 key_info & WPA_KEY_INFO_INSTALL ? " Install" : "",
    1515                 :            :                 key_info & WPA_KEY_INFO_ACK ? " Ack" : "",
    1516                 :            :                 key_info & WPA_KEY_INFO_MIC ? " MIC" : "",
    1517                 :            :                 key_info & WPA_KEY_INFO_SECURE ? " Secure" : "",
    1518                 :            :                 key_info & WPA_KEY_INFO_ERROR ? " Error" : "",
    1519                 :            :                 key_info & WPA_KEY_INFO_REQUEST ? " Request" : "",
    1520                 :            :                 key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : "");
    1521                 :        478 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1522                 :            :                 "  key_length=%u key_data_length=%u",
    1523                 :            :                 WPA_GET_BE16(key->key_length),
    1524                 :            :                 WPA_GET_BE16(key->key_data_length));
    1525                 :        478 :         wpa_hexdump(MSG_DEBUG, "  replay_counter",
    1526                 :        478 :                     key->replay_counter, WPA_REPLAY_COUNTER_LEN);
    1527                 :        478 :         wpa_hexdump(MSG_DEBUG, "  key_nonce", key->key_nonce, WPA_NONCE_LEN);
    1528                 :        478 :         wpa_hexdump(MSG_DEBUG, "  key_iv", key->key_iv, 16);
    1529                 :        478 :         wpa_hexdump(MSG_DEBUG, "  key_rsc", key->key_rsc, 8);
    1530                 :        478 :         wpa_hexdump(MSG_DEBUG, "  key_id (reserved)", key->key_id, 8);
    1531                 :        478 :         wpa_hexdump(MSG_DEBUG, "  key_mic", key->key_mic, 16);
    1532                 :            : #endif /* CONFIG_NO_STDOUT_DEBUG */
    1533                 :        478 : }
    1534                 :            : 
    1535                 :            : 
    1536                 :            : /**
    1537                 :            :  * wpa_sm_rx_eapol - Process received WPA EAPOL frames
    1538                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    1539                 :            :  * @src_addr: Source MAC address of the EAPOL packet
    1540                 :            :  * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
    1541                 :            :  * @len: Length of the EAPOL frame
    1542                 :            :  * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure
    1543                 :            :  *
    1544                 :            :  * This function is called for each received EAPOL frame. Other than EAPOL-Key
    1545                 :            :  * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is
    1546                 :            :  * only processing WPA and WPA2 EAPOL-Key frames.
    1547                 :            :  *
    1548                 :            :  * The received EAPOL-Key packets are validated and valid packets are replied
    1549                 :            :  * to. In addition, key material (PTK, GTK) is configured at the end of a
    1550                 :            :  * successful key handshake.
    1551                 :            :  */
    1552                 :        478 : int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
    1553                 :            :                     const u8 *buf, size_t len)
    1554                 :            : {
    1555                 :            :         size_t plen, data_len, extra_len;
    1556                 :            :         struct ieee802_1x_hdr *hdr;
    1557                 :            :         struct wpa_eapol_key *key;
    1558                 :            :         u16 key_info, ver;
    1559                 :            :         u8 *tmp;
    1560                 :        478 :         int ret = -1;
    1561                 :        478 :         struct wpa_peerkey *peerkey = NULL;
    1562                 :            : 
    1563                 :            : #ifdef CONFIG_IEEE80211R
    1564                 :        478 :         sm->ft_completed = 0;
    1565                 :            : #endif /* CONFIG_IEEE80211R */
    1566                 :            : 
    1567         [ -  + ]:        478 :         if (len < sizeof(*hdr) + sizeof(*key)) {
    1568                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1569                 :            :                         "WPA: EAPOL frame too short to be a WPA "
    1570                 :            :                         "EAPOL-Key (len %lu, expecting at least %lu)",
    1571                 :            :                         (unsigned long) len,
    1572                 :            :                         (unsigned long) sizeof(*hdr) + sizeof(*key));
    1573                 :          0 :                 return 0;
    1574                 :            :         }
    1575                 :            : 
    1576                 :        478 :         tmp = os_malloc(len);
    1577         [ -  + ]:        478 :         if (tmp == NULL)
    1578                 :          0 :                 return -1;
    1579                 :        478 :         os_memcpy(tmp, buf, len);
    1580                 :            : 
    1581                 :        478 :         hdr = (struct ieee802_1x_hdr *) tmp;
    1582                 :        478 :         key = (struct wpa_eapol_key *) (hdr + 1);
    1583                 :        478 :         plen = be_to_host16(hdr->length);
    1584                 :        478 :         data_len = plen + sizeof(*hdr);
    1585                 :        478 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1586                 :            :                 "IEEE 802.1X RX: version=%d type=%d length=%lu",
    1587                 :            :                 hdr->version, hdr->type, (unsigned long) plen);
    1588                 :            : 
    1589                 :        478 :         if (hdr->version < EAPOL_VERSION) {
    1590                 :            :                 /* TODO: backwards compatibility */
    1591                 :            :         }
    1592         [ -  + ]:        478 :         if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) {
    1593                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1594                 :            :                         "WPA: EAPOL frame (type %u) discarded, "
    1595                 :            :                         "not a Key frame", hdr->type);
    1596                 :          0 :                 ret = 0;
    1597                 :          0 :                 goto out;
    1598                 :            :         }
    1599 [ +  - ][ -  + ]:        478 :         if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) {
    1600                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1601                 :            :                         "WPA: EAPOL frame payload size %lu "
    1602                 :            :                         "invalid (frame size %lu)",
    1603                 :            :                         (unsigned long) plen, (unsigned long) len);
    1604                 :          0 :                 ret = 0;
    1605                 :          0 :                 goto out;
    1606                 :            :         }
    1607                 :            : 
    1608 [ +  + ][ -  + ]:        478 :         if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
    1609                 :            :         {
    1610                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1611                 :            :                         "WPA: EAPOL-Key type (%d) unknown, discarded",
    1612                 :            :                         key->type);
    1613                 :          0 :                 ret = 0;
    1614                 :          0 :                 goto out;
    1615                 :            :         }
    1616                 :        478 :         wpa_eapol_key_dump(sm, key);
    1617                 :            : 
    1618                 :        478 :         eapol_sm_notify_lower_layer_success(sm->eapol, 0);
    1619                 :        478 :         wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len);
    1620         [ -  + ]:        478 :         if (data_len < len) {
    1621                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1622                 :            :                         "WPA: ignoring %lu bytes after the IEEE 802.1X data",
    1623                 :            :                         (unsigned long) len - data_len);
    1624                 :            :         }
    1625                 :        478 :         key_info = WPA_GET_BE16(key->key_info);
    1626                 :        478 :         ver = key_info & WPA_KEY_INFO_TYPE_MASK;
    1627 [ +  + ][ +  + ]:        478 :         if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
    1628                 :            : #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
    1629         [ -  + ]:        426 :             ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
    1630                 :            : #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
    1631                 :            :             ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
    1632                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1633                 :            :                         "WPA: Unsupported EAPOL-Key descriptor version %d",
    1634                 :            :                         ver);
    1635                 :          0 :                 goto out;
    1636                 :            :         }
    1637                 :            : 
    1638                 :            : #ifdef CONFIG_IEEE80211R
    1639         [ +  + ]:        478 :         if (wpa_key_mgmt_ft(sm->key_mgmt)) {
    1640                 :            :                 /* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */
    1641         [ -  + ]:         16 :                 if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
    1642                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1643                 :            :                                 "FT: AP did not use AES-128-CMAC");
    1644                 :          0 :                         goto out;
    1645                 :            :                 }
    1646                 :            :         } else
    1647                 :            : #endif /* CONFIG_IEEE80211R */
    1648                 :            : #ifdef CONFIG_IEEE80211W
    1649         [ +  + ]:        462 :         if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
    1650         [ -  + ]:         16 :                 if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
    1651                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1652                 :            :                                 "WPA: AP did not use the "
    1653                 :            :                                 "negotiated AES-128-CMAC");
    1654                 :          0 :                         goto out;
    1655                 :            :                 }
    1656                 :            :         } else
    1657                 :            : #endif /* CONFIG_IEEE80211W */
    1658 [ +  + ][ -  + ]:        446 :         if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
    1659                 :            :             ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
    1660                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1661                 :            :                         "WPA: CCMP is used, but EAPOL-Key "
    1662                 :            :                         "descriptor version (%d) is not 2", ver);
    1663 [ #  # ][ #  # ]:          0 :                 if (sm->group_cipher != WPA_CIPHER_CCMP &&
    1664                 :          0 :                     !(key_info & WPA_KEY_INFO_KEY_TYPE)) {
    1665                 :            :                         /* Earlier versions of IEEE 802.11i did not explicitly
    1666                 :            :                          * require version 2 descriptor for all EAPOL-Key
    1667                 :            :                          * packets, so allow group keys to use version 1 if
    1668                 :            :                          * CCMP is not used for them. */
    1669                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1670                 :            :                                 "WPA: Backwards compatibility: allow invalid "
    1671                 :            :                                 "version for non-CCMP group keys");
    1672                 :            :                 } else
    1673                 :            :                         goto out;
    1674                 :            :         }
    1675 [ +  + ][ -  + ]:        478 :         if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
    1676                 :            :             ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
    1677                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1678                 :            :                         "WPA: GCMP is used, but EAPOL-Key "
    1679                 :            :                         "descriptor version (%d) is not 2", ver);
    1680                 :          0 :                 goto out;
    1681                 :            :         }
    1682                 :            : 
    1683                 :            : #ifdef CONFIG_PEERKEY
    1684         [ +  + ]:        480 :         for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
    1685         [ +  + ]:          6 :                 if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
    1686                 :          4 :                         break;
    1687                 :            :         }
    1688                 :            : 
    1689 [ +  + ][ +  + ]:        478 :         if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) {
    1690 [ +  + ][ -  + ]:          4 :                 if (!peerkey->initiator && peerkey->replay_counter_set &&
                 [ #  # ]
    1691                 :          0 :                     os_memcmp(key->replay_counter, peerkey->replay_counter,
    1692                 :            :                               WPA_REPLAY_COUNTER_LEN) <= 0) {
    1693                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1694                 :            :                                 "RSN: EAPOL-Key Replay Counter did not "
    1695                 :            :                                 "increase (STK) - dropping packet");
    1696                 :          0 :                         goto out;
    1697         [ +  + ]:          4 :                 } else if (peerkey->initiator) {
    1698                 :            :                         u8 _tmp[WPA_REPLAY_COUNTER_LEN];
    1699                 :          2 :                         os_memcpy(_tmp, key->replay_counter,
    1700                 :            :                                   WPA_REPLAY_COUNTER_LEN);
    1701                 :          2 :                         inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN);
    1702         [ -  + ]:          2 :                         if (os_memcmp(_tmp, peerkey->replay_counter,
    1703                 :            :                                       WPA_REPLAY_COUNTER_LEN) != 0) {
    1704                 :          0 :                                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1705                 :            :                                         "RSN: EAPOL-Key Replay "
    1706                 :            :                                         "Counter did not match (STK) - "
    1707                 :            :                                         "dropping packet");
    1708                 :          0 :                                 goto out;
    1709                 :            :                         }
    1710                 :            :                 }
    1711                 :            :         }
    1712                 :            : 
    1713 [ +  + ][ +  + ]:        478 :         if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) {
                 [ -  + ]
    1714                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1715                 :            :                         "RSN: Ack bit in key_info from STK peer");
    1716                 :          0 :                 goto out;
    1717                 :            :         }
    1718                 :            : #endif /* CONFIG_PEERKEY */
    1719                 :            : 
    1720 [ +  + ][ +  + ]:        478 :         if (!peerkey && sm->rx_replay_counter_set &&
                 [ -  + ]
    1721                 :         52 :             os_memcmp(key->replay_counter, sm->rx_replay_counter,
    1722                 :            :                       WPA_REPLAY_COUNTER_LEN) <= 0) {
    1723                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1724                 :            :                         "WPA: EAPOL-Key Replay Counter did not increase - "
    1725                 :            :                         "dropping packet");
    1726                 :          0 :                 goto out;
    1727                 :            :         }
    1728                 :            : 
    1729         [ +  + ]:        478 :         if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE))
    1730                 :            : #ifdef CONFIG_PEERKEY
    1731 [ +  - ][ -  + ]:          2 :             && (peerkey == NULL || !peerkey->initiator)
    1732                 :            : #endif /* CONFIG_PEERKEY */
    1733                 :            :                 ) {
    1734                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1735                 :            :                         "WPA: No Ack bit in key_info");
    1736                 :          0 :                 goto out;
    1737                 :            :         }
    1738                 :            : 
    1739         [ -  + ]:        478 :         if (key_info & WPA_KEY_INFO_REQUEST) {
    1740                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
    1741                 :            :                         "WPA: EAPOL-Key with Request bit - dropped");
    1742                 :          0 :                 goto out;
    1743                 :            :         }
    1744                 :            : 
    1745         [ +  + ]:        710 :         if ((key_info & WPA_KEY_INFO_MIC) && !peerkey &&
           [ +  +  -  + ]
    1746                 :        232 :             wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))
    1747                 :          0 :                 goto out;
    1748                 :            : 
    1749                 :            : #ifdef CONFIG_PEERKEY
    1750         [ +  + ]:        481 :         if ((key_info & WPA_KEY_INFO_MIC) && peerkey &&
           [ +  +  -  + ]
    1751                 :          3 :             peerkey_verify_eapol_key_mic(sm, peerkey, key, ver, tmp, data_len))
    1752                 :          0 :                 goto out;
    1753                 :            : #endif /* CONFIG_PEERKEY */
    1754                 :            : 
    1755                 :        478 :         extra_len = data_len - sizeof(*hdr) - sizeof(*key);
    1756                 :            : 
    1757         [ -  + ]:        478 :         if (WPA_GET_BE16(key->key_data_length) > extra_len) {
    1758                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
    1759                 :            :                         "frame - key_data overflow (%d > %lu)",
    1760                 :          0 :                         WPA_GET_BE16(key->key_data_length),
    1761                 :            :                         (unsigned long) extra_len);
    1762                 :          0 :                 goto out;
    1763                 :            :         }
    1764                 :        478 :         extra_len = WPA_GET_BE16(key->key_data_length);
    1765                 :            : 
    1766 [ +  + ][ +  + ]:        478 :         if (sm->proto == WPA_PROTO_RSN &&
    1767                 :        460 :             (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
    1768         [ -  + ]:        219 :                 if (wpa_supplicant_decrypt_key_data(sm, key, ver))
    1769                 :          0 :                         goto out;
    1770                 :        219 :                 extra_len = WPA_GET_BE16(key->key_data_length);
    1771                 :            :         }
    1772                 :            : 
    1773         [ +  + ]:        478 :         if (key_info & WPA_KEY_INFO_KEY_TYPE) {
    1774         [ -  + ]:        468 :                 if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
    1775                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1776                 :            :                                 "WPA: Ignored EAPOL-Key (Pairwise) with "
    1777                 :            :                                 "non-zero key index");
    1778                 :          0 :                         goto out;
    1779                 :            :                 }
    1780         [ +  + ]:        468 :                 if (peerkey) {
    1781                 :            :                         /* PeerKey 4-Way Handshake */
    1782                 :          4 :                         peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver);
    1783         [ +  + ]:        464 :                 } else if (key_info & WPA_KEY_INFO_MIC) {
    1784                 :            :                         /* 3/4 4-Way Handshake */
    1785                 :        222 :                         wpa_supplicant_process_3_of_4(sm, key, ver);
    1786                 :            :                 } else {
    1787                 :            :                         /* 1/4 4-Way Handshake */
    1788                 :        242 :                         wpa_supplicant_process_1_of_4(sm, src_addr, key,
    1789                 :            :                                                       ver);
    1790                 :            :                 }
    1791         [ +  + ]:         10 :         } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
    1792                 :            :                 /* PeerKey SMK Handshake */
    1793                 :          3 :                 peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info,
    1794                 :            :                                      ver);
    1795                 :            :         } else {
    1796         [ +  - ]:          7 :                 if (key_info & WPA_KEY_INFO_MIC) {
    1797                 :            :                         /* 1/2 Group Key Handshake */
    1798                 :          7 :                         wpa_supplicant_process_1_of_2(sm, src_addr, key,
    1799                 :            :                                                       extra_len, ver);
    1800                 :            :                 } else {
    1801                 :          0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1802                 :            :                                 "WPA: EAPOL-Key (Group) without Mic bit - "
    1803                 :            :                                 "dropped");
    1804                 :            :                 }
    1805                 :            :         }
    1806                 :            : 
    1807                 :        478 :         ret = 1;
    1808                 :            : 
    1809                 :            : out:
    1810                 :        478 :         os_free(tmp);
    1811                 :        478 :         return ret;
    1812                 :            : }
    1813                 :            : 
    1814                 :            : 
    1815                 :            : #ifdef CONFIG_CTRL_IFACE
    1816                 :          0 : static u32 wpa_key_mgmt_suite(struct wpa_sm *sm)
    1817                 :            : {
    1818   [ #  #  #  #  :          0 :         switch (sm->key_mgmt) {
             #  #  #  #  
                      # ]
    1819                 :            :         case WPA_KEY_MGMT_IEEE8021X:
    1820                 :          0 :                 return (sm->proto == WPA_PROTO_RSN ?
    1821         [ #  # ]:          0 :                         RSN_AUTH_KEY_MGMT_UNSPEC_802_1X :
    1822                 :            :                         WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
    1823                 :            :         case WPA_KEY_MGMT_PSK:
    1824                 :          0 :                 return (sm->proto == WPA_PROTO_RSN ?
    1825         [ #  # ]:          0 :                         RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X :
    1826                 :            :                         WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
    1827                 :            : #ifdef CONFIG_IEEE80211R
    1828                 :            :         case WPA_KEY_MGMT_FT_IEEE8021X:
    1829                 :          0 :                 return RSN_AUTH_KEY_MGMT_FT_802_1X;
    1830                 :            :         case WPA_KEY_MGMT_FT_PSK:
    1831                 :          0 :                 return RSN_AUTH_KEY_MGMT_FT_PSK;
    1832                 :            : #endif /* CONFIG_IEEE80211R */
    1833                 :            : #ifdef CONFIG_IEEE80211W
    1834                 :            :         case WPA_KEY_MGMT_IEEE8021X_SHA256:
    1835                 :          0 :                 return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
    1836                 :            :         case WPA_KEY_MGMT_PSK_SHA256:
    1837                 :          0 :                 return RSN_AUTH_KEY_MGMT_PSK_SHA256;
    1838                 :            : #endif /* CONFIG_IEEE80211W */
    1839                 :            :         case WPA_KEY_MGMT_CCKM:
    1840                 :          0 :                 return (sm->proto == WPA_PROTO_RSN ?
    1841                 :            :                         RSN_AUTH_KEY_MGMT_CCKM:
    1842                 :            :                         WPA_AUTH_KEY_MGMT_CCKM);
    1843                 :            :         case WPA_KEY_MGMT_WPA_NONE:
    1844                 :          0 :                 return WPA_AUTH_KEY_MGMT_NONE;
    1845                 :            :         default:
    1846                 :          0 :                 return 0;
    1847                 :            :         }
    1848                 :            : }
    1849                 :            : 
    1850                 :            : 
    1851                 :            : #define RSN_SUITE "%02x-%02x-%02x-%d"
    1852                 :            : #define RSN_SUITE_ARG(s) \
    1853                 :            : ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
    1854                 :            : 
    1855                 :            : /**
    1856                 :            :  * wpa_sm_get_mib - Dump text list of MIB entries
    1857                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    1858                 :            :  * @buf: Buffer for the list
    1859                 :            :  * @buflen: Length of the buffer
    1860                 :            :  * Returns: Number of bytes written to buffer
    1861                 :            :  *
    1862                 :            :  * This function is used fetch dot11 MIB variables.
    1863                 :            :  */
    1864                 :          0 : int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
    1865                 :            : {
    1866                 :            :         char pmkid_txt[PMKID_LEN * 2 + 1];
    1867                 :            :         int rsna, ret;
    1868                 :            :         size_t len;
    1869                 :            : 
    1870         [ #  # ]:          0 :         if (sm->cur_pmksa) {
    1871                 :          0 :                 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
    1872                 :          0 :                                  sm->cur_pmksa->pmkid, PMKID_LEN);
    1873                 :            :         } else
    1874                 :          0 :                 pmkid_txt[0] = '\0';
    1875                 :            : 
    1876   [ #  #  #  # ]:          0 :         if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) ||
    1877         [ #  # ]:          0 :              wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) &&
    1878                 :          0 :             sm->proto == WPA_PROTO_RSN)
    1879                 :          0 :                 rsna = 1;
    1880                 :            :         else
    1881                 :          0 :                 rsna = 0;
    1882                 :            : 
    1883 [ #  # ][ #  # ]:          0 :         ret = os_snprintf(buf, buflen,
    1884                 :            :                           "dot11RSNAOptionImplemented=TRUE\n"
    1885                 :            :                           "dot11RSNAPreauthenticationImplemented=TRUE\n"
    1886                 :            :                           "dot11RSNAEnabled=%s\n"
    1887                 :            :                           "dot11RSNAPreauthenticationEnabled=%s\n"
    1888                 :            :                           "dot11RSNAConfigVersion=%d\n"
    1889                 :            :                           "dot11RSNAConfigPairwiseKeysSupported=5\n"
    1890                 :            :                           "dot11RSNAConfigGroupCipherSize=%d\n"
    1891                 :            :                           "dot11RSNAConfigPMKLifetime=%d\n"
    1892                 :            :                           "dot11RSNAConfigPMKReauthThreshold=%d\n"
    1893                 :            :                           "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n"
    1894                 :            :                           "dot11RSNAConfigSATimeout=%d\n",
    1895                 :            :                           rsna ? "TRUE" : "FALSE",
    1896                 :            :                           rsna ? "TRUE" : "FALSE",
    1897                 :            :                           RSN_VERSION,
    1898                 :          0 :                           wpa_cipher_key_len(sm->group_cipher) * 8,
    1899                 :            :                           sm->dot11RSNAConfigPMKLifetime,
    1900                 :            :                           sm->dot11RSNAConfigPMKReauthThreshold,
    1901                 :            :                           sm->dot11RSNAConfigSATimeout);
    1902 [ #  # ][ #  # ]:          0 :         if (ret < 0 || (size_t) ret >= buflen)
    1903                 :          0 :                 return 0;
    1904                 :          0 :         len = ret;
    1905                 :            : 
    1906                 :          0 :         ret = os_snprintf(
    1907                 :            :                 buf + len, buflen - len,
    1908                 :            :                 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
    1909                 :            :                 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
    1910                 :            :                 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
    1911                 :            :                 "dot11RSNAPMKIDUsed=%s\n"
    1912                 :            :                 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
    1913                 :            :                 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
    1914                 :            :                 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
    1915                 :            :                 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n"
    1916                 :            :                 "dot11RSNA4WayHandshakeFailures=%u\n",
    1917                 :          0 :                 RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
    1918                 :          0 :                 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
    1919                 :            :                                                   sm->pairwise_cipher)),
    1920                 :          0 :                 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
    1921                 :            :                                                   sm->group_cipher)),
    1922                 :            :                 pmkid_txt,
    1923                 :          0 :                 RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
    1924                 :          0 :                 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
    1925                 :            :                                                   sm->pairwise_cipher)),
    1926                 :          0 :                 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
    1927                 :            :                                                   sm->group_cipher)),
    1928                 :            :                 sm->dot11RSNA4WayHandshakeFailures);
    1929 [ #  # ][ #  # ]:          0 :         if (ret >= 0 && (size_t) ret < buflen)
    1930                 :          0 :                 len += ret;
    1931                 :            : 
    1932                 :          0 :         return (int) len;
    1933                 :            : }
    1934                 :            : #endif /* CONFIG_CTRL_IFACE */
    1935                 :            : 
    1936                 :            : 
    1937                 :         68 : static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
    1938                 :            :                                  void *ctx, enum pmksa_free_reason reason)
    1939                 :            : {
    1940                 :         68 :         struct wpa_sm *sm = ctx;
    1941                 :         68 :         int deauth = 0;
    1942                 :            : 
    1943                 :         68 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA cache entry free_cb: "
    1944                 :            :                 MACSTR " reason=%d", MAC2STR(entry->aa), reason);
    1945                 :            : 
    1946         [ +  + ]:         68 :         if (sm->cur_pmksa == entry) {
    1947         [ -  + ]:          4 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1948                 :            :                         "RSN: %s current PMKSA entry",
    1949                 :            :                         reason == PMKSA_REPLACE ? "replaced" : "removed");
    1950                 :          4 :                 pmksa_cache_clear_current(sm);
    1951                 :            : 
    1952                 :            :                 /*
    1953                 :            :                  * If an entry is simply being replaced, there's no need to
    1954                 :            :                  * deauthenticate because it will be immediately re-added.
    1955                 :            :                  * This happens when EAP authentication is completed again
    1956                 :            :                  * (reauth or failed PMKSA caching attempt).
    1957                 :            :                  */
    1958         [ +  - ]:          4 :                 if (reason != PMKSA_REPLACE)
    1959                 :          4 :                         deauth = 1;
    1960                 :            :         }
    1961                 :            : 
    1962 [ -  + ][ #  # ]:         68 :         if (reason == PMKSA_EXPIRE &&
    1963         [ #  # ]:          0 :             (sm->pmk_len == entry->pmk_len &&
    1964                 :          0 :              os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) {
    1965                 :          0 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    1966                 :            :                         "RSN: deauthenticating due to expired PMK");
    1967                 :          0 :                 pmksa_cache_clear_current(sm);
    1968                 :          0 :                 deauth = 1;
    1969                 :            :         }
    1970                 :            : 
    1971         [ +  + ]:         68 :         if (deauth) {
    1972                 :          4 :                 os_memset(sm->pmk, 0, sizeof(sm->pmk));
    1973                 :          4 :                 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
    1974                 :            :         }
    1975                 :         68 : }
    1976                 :            : 
    1977                 :            : 
    1978                 :            : /**
    1979                 :            :  * wpa_sm_init - Initialize WPA state machine
    1980                 :            :  * @ctx: Context pointer for callbacks; this needs to be an allocated buffer
    1981                 :            :  * Returns: Pointer to the allocated WPA state machine data
    1982                 :            :  *
    1983                 :            :  * This function is used to allocate a new WPA state machine and the returned
    1984                 :            :  * value is passed to all WPA state machine calls.
    1985                 :            :  */
    1986                 :         28 : struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
    1987                 :            : {
    1988                 :            :         struct wpa_sm *sm;
    1989                 :            : 
    1990                 :         28 :         sm = os_zalloc(sizeof(*sm));
    1991         [ -  + ]:         28 :         if (sm == NULL)
    1992                 :          0 :                 return NULL;
    1993                 :         28 :         dl_list_init(&sm->pmksa_candidates);
    1994                 :         28 :         sm->renew_snonce = 1;
    1995                 :         28 :         sm->ctx = ctx;
    1996                 :            : 
    1997                 :         28 :         sm->dot11RSNAConfigPMKLifetime = 43200;
    1998                 :         28 :         sm->dot11RSNAConfigPMKReauthThreshold = 70;
    1999                 :         28 :         sm->dot11RSNAConfigSATimeout = 60;
    2000                 :            : 
    2001                 :         28 :         sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm);
    2002         [ -  + ]:         28 :         if (sm->pmksa == NULL) {
    2003                 :          0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
    2004                 :            :                         "RSN: PMKSA cache initialization failed");
    2005                 :          0 :                 os_free(sm);
    2006                 :          0 :                 return NULL;
    2007                 :            :         }
    2008                 :            : 
    2009                 :         28 :         return sm;
    2010                 :            : }
    2011                 :            : 
    2012                 :            : 
    2013                 :            : /**
    2014                 :            :  * wpa_sm_deinit - Deinitialize WPA state machine
    2015                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2016                 :            :  */
    2017                 :         28 : void wpa_sm_deinit(struct wpa_sm *sm)
    2018                 :            : {
    2019         [ -  + ]:         28 :         if (sm == NULL)
    2020                 :         28 :                 return;
    2021                 :         28 :         pmksa_cache_deinit(sm->pmksa);
    2022                 :         28 :         eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
    2023                 :         28 :         eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
    2024                 :         28 :         os_free(sm->assoc_wpa_ie);
    2025                 :         28 :         os_free(sm->ap_wpa_ie);
    2026                 :         28 :         os_free(sm->ap_rsn_ie);
    2027                 :         28 :         os_free(sm->ctx);
    2028                 :         28 :         peerkey_deinit(sm);
    2029                 :            : #ifdef CONFIG_IEEE80211R
    2030                 :         28 :         os_free(sm->assoc_resp_ies);
    2031                 :            : #endif /* CONFIG_IEEE80211R */
    2032                 :         28 :         os_free(sm);
    2033                 :            : }
    2034                 :            : 
    2035                 :            : 
    2036                 :            : /**
    2037                 :            :  * wpa_sm_notify_assoc - Notify WPA state machine about association
    2038                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2039                 :            :  * @bssid: The BSSID of the new association
    2040                 :            :  *
    2041                 :            :  * This function is called to let WPA state machine know that the connection
    2042                 :            :  * was established.
    2043                 :            :  */
    2044                 :        368 : void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
    2045                 :            : {
    2046                 :        368 :         int clear_ptk = 1;
    2047                 :            : 
    2048         [ -  + ]:        368 :         if (sm == NULL)
    2049                 :        368 :                 return;
    2050                 :            : 
    2051                 :        368 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    2052                 :            :                 "WPA: Association event - clear replay counter");
    2053                 :        368 :         os_memcpy(sm->bssid, bssid, ETH_ALEN);
    2054                 :        368 :         os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
    2055                 :        368 :         sm->rx_replay_counter_set = 0;
    2056                 :        368 :         sm->renew_snonce = 1;
    2057         [ -  + ]:        368 :         if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0)
    2058                 :          0 :                 rsn_preauth_deinit(sm);
    2059                 :            : 
    2060                 :            : #ifdef CONFIG_IEEE80211R
    2061         [ +  + ]:        368 :         if (wpa_ft_is_completed(sm)) {
    2062                 :            :                 /*
    2063                 :            :                  * Clear portValid to kick EAPOL state machine to re-enter
    2064                 :            :                  * AUTHENTICATED state to get the EAPOL port Authorized.
    2065                 :            :                  */
    2066                 :         14 :                 eapol_sm_notify_portValid(sm->eapol, FALSE);
    2067                 :         14 :                 wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
    2068                 :            : 
    2069                 :            :                 /* Prepare for the next transition */
    2070                 :         14 :                 wpa_ft_prepare_auth_request(sm, NULL);
    2071                 :            : 
    2072                 :         14 :                 clear_ptk = 0;
    2073                 :            :         }
    2074                 :            : #endif /* CONFIG_IEEE80211R */
    2075                 :            : 
    2076         [ +  + ]:        368 :         if (clear_ptk) {
    2077                 :            :                 /*
    2078                 :            :                  * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
    2079                 :            :                  * this is not part of a Fast BSS Transition.
    2080                 :            :                  */
    2081                 :        354 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK");
    2082                 :        354 :                 sm->ptk_set = 0;
    2083                 :        354 :                 sm->tptk_set = 0;
    2084                 :            :         }
    2085                 :            : 
    2086                 :            : #ifdef CONFIG_TDLS
    2087                 :        368 :         wpa_tdls_assoc(sm);
    2088                 :            : #endif /* CONFIG_TDLS */
    2089                 :            : }
    2090                 :            : 
    2091                 :            : 
    2092                 :            : /**
    2093                 :            :  * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation
    2094                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2095                 :            :  *
    2096                 :            :  * This function is called to let WPA state machine know that the connection
    2097                 :            :  * was lost. This will abort any existing pre-authentication session.
    2098                 :            :  */
    2099                 :        663 : void wpa_sm_notify_disassoc(struct wpa_sm *sm)
    2100                 :            : {
    2101                 :        663 :         peerkey_deinit(sm);
    2102                 :        663 :         rsn_preauth_deinit(sm);
    2103                 :        663 :         pmksa_cache_clear_current(sm);
    2104         [ +  + ]:        663 :         if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE)
    2105                 :          5 :                 sm->dot11RSNA4WayHandshakeFailures++;
    2106                 :            : #ifdef CONFIG_TDLS
    2107                 :        663 :         wpa_tdls_disassoc(sm);
    2108                 :            : #endif /* CONFIG_TDLS */
    2109                 :        663 : }
    2110                 :            : 
    2111                 :            : 
    2112                 :            : /**
    2113                 :            :  * wpa_sm_set_pmk - Set PMK
    2114                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2115                 :            :  * @pmk: The new PMK
    2116                 :            :  * @pmk_len: The length of the new PMK in bytes
    2117                 :            :  *
    2118                 :            :  * Configure the PMK for WPA state machine.
    2119                 :            :  */
    2120                 :        200 : void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len)
    2121                 :            : {
    2122         [ -  + ]:        200 :         if (sm == NULL)
    2123                 :        200 :                 return;
    2124                 :            : 
    2125                 :        200 :         sm->pmk_len = pmk_len;
    2126                 :        200 :         os_memcpy(sm->pmk, pmk, pmk_len);
    2127                 :            : 
    2128                 :            : #ifdef CONFIG_IEEE80211R
    2129                 :            :         /* Set XXKey to be PSK for FT key derivation */
    2130                 :        200 :         sm->xxkey_len = pmk_len;
    2131                 :        200 :         os_memcpy(sm->xxkey, pmk, pmk_len);
    2132                 :            : #endif /* CONFIG_IEEE80211R */
    2133                 :            : }
    2134                 :            : 
    2135                 :            : 
    2136                 :            : /**
    2137                 :            :  * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA
    2138                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2139                 :            :  *
    2140                 :            :  * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK
    2141                 :            :  * will be cleared.
    2142                 :            :  */
    2143                 :         59 : void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm)
    2144                 :            : {
    2145         [ -  + ]:         59 :         if (sm == NULL)
    2146                 :         59 :                 return;
    2147                 :            : 
    2148         [ +  + ]:         59 :         if (sm->cur_pmksa) {
    2149                 :          2 :                 sm->pmk_len = sm->cur_pmksa->pmk_len;
    2150                 :          2 :                 os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len);
    2151                 :            :         } else {
    2152                 :         57 :                 sm->pmk_len = PMK_LEN;
    2153                 :         57 :                 os_memset(sm->pmk, 0, PMK_LEN);
    2154                 :            :         }
    2155                 :            : }
    2156                 :            : 
    2157                 :            : 
    2158                 :            : /**
    2159                 :            :  * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled
    2160                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2161                 :            :  * @fast_reauth: Whether fast reauthentication (EAP) is allowed
    2162                 :            :  */
    2163                 :         22 : void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth)
    2164                 :            : {
    2165         [ +  - ]:         22 :         if (sm)
    2166                 :         22 :                 sm->fast_reauth = fast_reauth;
    2167                 :         22 : }
    2168                 :            : 
    2169                 :            : 
    2170                 :            : /**
    2171                 :            :  * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks
    2172                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2173                 :            :  * @scard_ctx: Context pointer for smartcard related callback functions
    2174                 :            :  */
    2175                 :         22 : void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx)
    2176                 :            : {
    2177         [ -  + ]:         22 :         if (sm == NULL)
    2178                 :         22 :                 return;
    2179                 :         22 :         sm->scard_ctx = scard_ctx;
    2180         [ -  + ]:         22 :         if (sm->preauth_eapol)
    2181                 :          0 :                 eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx);
    2182                 :            : }
    2183                 :            : 
    2184                 :            : 
    2185                 :            : /**
    2186                 :            :  * wpa_sm_set_config - Notification of current configration change
    2187                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2188                 :            :  * @config: Pointer to current network configuration
    2189                 :            :  *
    2190                 :            :  * Notify WPA state machine that configuration has changed. config will be
    2191                 :            :  * stored as a backpointer to network configuration. This can be %NULL to clear
    2192                 :            :  * the stored pointed.
    2193                 :            :  */
    2194                 :        915 : void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
    2195                 :            : {
    2196         [ -  + ]:        915 :         if (!sm)
    2197                 :        915 :                 return;
    2198                 :            : 
    2199         [ +  + ]:        915 :         if (config) {
    2200                 :        379 :                 sm->network_ctx = config->network_ctx;
    2201                 :        379 :                 sm->peerkey_enabled = config->peerkey_enabled;
    2202                 :        379 :                 sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher;
    2203                 :        379 :                 sm->proactive_key_caching = config->proactive_key_caching;
    2204                 :        379 :                 sm->eap_workaround = config->eap_workaround;
    2205                 :        379 :                 sm->eap_conf_ctx = config->eap_conf_ctx;
    2206         [ +  + ]:        379 :                 if (config->ssid) {
    2207                 :        359 :                         os_memcpy(sm->ssid, config->ssid, config->ssid_len);
    2208                 :        359 :                         sm->ssid_len = config->ssid_len;
    2209                 :            :                 } else
    2210                 :         20 :                         sm->ssid_len = 0;
    2211                 :        379 :                 sm->wpa_ptk_rekey = config->wpa_ptk_rekey;
    2212                 :            :         } else {
    2213                 :        536 :                 sm->network_ctx = NULL;
    2214                 :        536 :                 sm->peerkey_enabled = 0;
    2215                 :        536 :                 sm->allowed_pairwise_cipher = 0;
    2216                 :        536 :                 sm->proactive_key_caching = 0;
    2217                 :        536 :                 sm->eap_workaround = 0;
    2218                 :        536 :                 sm->eap_conf_ctx = NULL;
    2219                 :        536 :                 sm->ssid_len = 0;
    2220                 :        536 :                 sm->wpa_ptk_rekey = 0;
    2221                 :            :         }
    2222                 :            : }
    2223                 :            : 
    2224                 :            : 
    2225                 :            : /**
    2226                 :            :  * wpa_sm_set_own_addr - Set own MAC address
    2227                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2228                 :            :  * @addr: Own MAC address
    2229                 :            :  */
    2230                 :         28 : void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr)
    2231                 :            : {
    2232         [ +  - ]:         28 :         if (sm)
    2233                 :         28 :                 os_memcpy(sm->own_addr, addr, ETH_ALEN);
    2234                 :         28 : }
    2235                 :            : 
    2236                 :            : 
    2237                 :            : /**
    2238                 :            :  * wpa_sm_set_ifname - Set network interface name
    2239                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2240                 :            :  * @ifname: Interface name
    2241                 :            :  * @bridge_ifname: Optional bridge interface name (for pre-auth)
    2242                 :            :  */
    2243                 :         22 : void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname,
    2244                 :            :                        const char *bridge_ifname)
    2245                 :            : {
    2246         [ +  - ]:         22 :         if (sm) {
    2247                 :         22 :                 sm->ifname = ifname;
    2248                 :         22 :                 sm->bridge_ifname = bridge_ifname;
    2249                 :            :         }
    2250                 :         22 : }
    2251                 :            : 
    2252                 :            : 
    2253                 :            : /**
    2254                 :            :  * wpa_sm_set_eapol - Set EAPOL state machine pointer
    2255                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2256                 :            :  * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init()
    2257                 :            :  */
    2258                 :         44 : void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol)
    2259                 :            : {
    2260         [ +  - ]:         44 :         if (sm)
    2261                 :         44 :                 sm->eapol = eapol;
    2262                 :         44 : }
    2263                 :            : 
    2264                 :            : 
    2265                 :            : /**
    2266                 :            :  * wpa_sm_set_param - Set WPA state machine parameters
    2267                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2268                 :            :  * @param: Parameter field
    2269                 :            :  * @value: Parameter value
    2270                 :            :  * Returns: 0 on success, -1 on failure
    2271                 :            :  */
    2272                 :       2401 : int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
    2273                 :            :                      unsigned int value)
    2274                 :            : {
    2275                 :       2401 :         int ret = 0;
    2276                 :            : 
    2277         [ -  + ]:       2401 :         if (sm == NULL)
    2278                 :          0 :                 return -1;
    2279                 :            : 
    2280   [ -  -  -  +  :       2401 :         switch (param) {
          +  +  +  +  +  
                   +  - ]
    2281                 :            :         case RSNA_PMK_LIFETIME:
    2282         [ #  # ]:          0 :                 if (value > 0)
    2283                 :          0 :                         sm->dot11RSNAConfigPMKLifetime = value;
    2284                 :            :                 else
    2285                 :          0 :                         ret = -1;
    2286                 :          0 :                 break;
    2287                 :            :         case RSNA_PMK_REAUTH_THRESHOLD:
    2288 [ #  # ][ #  # ]:          0 :                 if (value > 0 && value <= 100)
    2289                 :          0 :                         sm->dot11RSNAConfigPMKReauthThreshold = value;
    2290                 :            :                 else
    2291                 :          0 :                         ret = -1;
    2292                 :          0 :                 break;
    2293                 :            :         case RSNA_SA_TIMEOUT:
    2294         [ #  # ]:          0 :                 if (value > 0)
    2295                 :          0 :                         sm->dot11RSNAConfigSATimeout = value;
    2296                 :            :                 else
    2297                 :          0 :                         ret = -1;
    2298                 :          0 :                 break;
    2299                 :            :         case WPA_PARAM_PROTO:
    2300                 :        244 :                 sm->proto = value;
    2301                 :        244 :                 break;
    2302                 :            :         case WPA_PARAM_PAIRWISE:
    2303                 :        385 :                 sm->pairwise_cipher = value;
    2304                 :        385 :                 break;
    2305                 :            :         case WPA_PARAM_GROUP:
    2306                 :        385 :                 sm->group_cipher = value;
    2307                 :        385 :                 break;
    2308                 :            :         case WPA_PARAM_KEY_MGMT:
    2309                 :        385 :                 sm->key_mgmt = value;
    2310                 :        385 :                 break;
    2311                 :            : #ifdef CONFIG_IEEE80211W
    2312                 :            :         case WPA_PARAM_MGMT_GROUP:
    2313                 :        379 :                 sm->mgmt_group_cipher = value;
    2314                 :        379 :                 break;
    2315                 :            : #endif /* CONFIG_IEEE80211W */
    2316                 :            :         case WPA_PARAM_RSN_ENABLED:
    2317                 :        385 :                 sm->rsn_enabled = value;
    2318                 :        385 :                 break;
    2319                 :            :         case WPA_PARAM_MFP:
    2320                 :        238 :                 sm->mfp = value;
    2321                 :        238 :                 break;
    2322                 :            :         default:
    2323                 :          0 :                 break;
    2324                 :            :         }
    2325                 :            : 
    2326                 :       2401 :         return ret;
    2327                 :            : }
    2328                 :            : 
    2329                 :            : 
    2330                 :            : /**
    2331                 :            :  * wpa_sm_get_param - Get WPA state machine parameters
    2332                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2333                 :            :  * @param: Parameter field
    2334                 :            :  * Returns: Parameter value
    2335                 :            :  */
    2336                 :          0 : unsigned int wpa_sm_get_param(struct wpa_sm *sm, enum wpa_sm_conf_params param)
    2337                 :            : {
    2338         [ #  # ]:          0 :         if (sm == NULL)
    2339                 :          0 :                 return 0;
    2340                 :            : 
    2341   [ #  #  #  #  :          0 :         switch (param) {
          #  #  #  #  #  
                      # ]
    2342                 :            :         case RSNA_PMK_LIFETIME:
    2343                 :          0 :                 return sm->dot11RSNAConfigPMKLifetime;
    2344                 :            :         case RSNA_PMK_REAUTH_THRESHOLD:
    2345                 :          0 :                 return sm->dot11RSNAConfigPMKReauthThreshold;
    2346                 :            :         case RSNA_SA_TIMEOUT:
    2347                 :          0 :                 return sm->dot11RSNAConfigSATimeout;
    2348                 :            :         case WPA_PARAM_PROTO:
    2349                 :          0 :                 return sm->proto;
    2350                 :            :         case WPA_PARAM_PAIRWISE:
    2351                 :          0 :                 return sm->pairwise_cipher;
    2352                 :            :         case WPA_PARAM_GROUP:
    2353                 :          0 :                 return sm->group_cipher;
    2354                 :            :         case WPA_PARAM_KEY_MGMT:
    2355                 :          0 :                 return sm->key_mgmt;
    2356                 :            : #ifdef CONFIG_IEEE80211W
    2357                 :            :         case WPA_PARAM_MGMT_GROUP:
    2358                 :          0 :                 return sm->mgmt_group_cipher;
    2359                 :            : #endif /* CONFIG_IEEE80211W */
    2360                 :            :         case WPA_PARAM_RSN_ENABLED:
    2361                 :          0 :                 return sm->rsn_enabled;
    2362                 :            :         default:
    2363                 :          0 :                 return 0;
    2364                 :            :         }
    2365                 :            : }
    2366                 :            : 
    2367                 :            : 
    2368                 :            : /**
    2369                 :            :  * wpa_sm_get_status - Get WPA state machine
    2370                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2371                 :            :  * @buf: Buffer for status information
    2372                 :            :  * @buflen: Maximum buffer length
    2373                 :            :  * @verbose: Whether to include verbose status information
    2374                 :            :  * Returns: Number of bytes written to buf.
    2375                 :            :  *
    2376                 :            :  * Query WPA state machine for status information. This function fills in
    2377                 :            :  * a text area with current status information. If the buffer (buf) is not
    2378                 :            :  * large enough, status information will be truncated to fit the buffer.
    2379                 :            :  */
    2380                 :        240 : int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
    2381                 :            :                       int verbose)
    2382                 :            : {
    2383                 :        240 :         char *pos = buf, *end = buf + buflen;
    2384                 :            :         int ret;
    2385                 :            : 
    2386                 :        240 :         ret = os_snprintf(pos, end - pos,
    2387                 :            :                           "pairwise_cipher=%s\n"
    2388                 :            :                           "group_cipher=%s\n"
    2389                 :            :                           "key_mgmt=%s\n",
    2390                 :        240 :                           wpa_cipher_txt(sm->pairwise_cipher),
    2391                 :        240 :                           wpa_cipher_txt(sm->group_cipher),
    2392                 :        480 :                           wpa_key_mgmt_txt(sm->key_mgmt, sm->proto));
    2393 [ +  - ][ -  + ]:        240 :         if (ret < 0 || ret >= end - pos)
    2394                 :          0 :                 return pos - buf;
    2395                 :        240 :         pos += ret;
    2396                 :            : 
    2397 [ +  + ][ +  + ]:        240 :         if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) {
    2398                 :            :                 struct wpa_ie_data rsn;
    2399         [ +  - ]:         76 :                 if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn)
    2400         [ +  + ]:         76 :                     >= 0 &&
    2401                 :         76 :                     rsn.capabilities & (WPA_CAPABILITY_MFPR |
    2402                 :            :                                         WPA_CAPABILITY_MFPC)) {
    2403         [ +  + ]:         20 :                         ret = os_snprintf(pos, end - pos, "pmf=%d\n",
    2404                 :         20 :                                           (rsn.capabilities &
    2405                 :            :                                            WPA_CAPABILITY_MFPR) ? 2 : 1);
    2406 [ +  - ][ -  + ]:         20 :                         if (ret < 0 || ret >= end - pos)
    2407                 :          0 :                                 return pos - buf;
    2408                 :         20 :                         pos += ret;
    2409                 :            :                 }
    2410                 :            :         }
    2411                 :            : 
    2412                 :        240 :         return pos - buf;
    2413                 :            : }
    2414                 :            : 
    2415                 :            : 
    2416                 :          2 : int wpa_sm_pmf_enabled(struct wpa_sm *sm)
    2417                 :            : {
    2418                 :            :         struct wpa_ie_data rsn;
    2419                 :            : 
    2420 [ +  + ][ -  + ]:          2 :         if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie)
    2421                 :          1 :                 return 0;
    2422                 :            : 
    2423 [ +  - ][ +  - ]:          1 :         if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 &&
    2424                 :          1 :             rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
    2425                 :          1 :                 return 1;
    2426                 :            : 
    2427                 :          2 :         return 0;
    2428                 :            : }
    2429                 :            : 
    2430                 :            : 
    2431                 :            : /**
    2432                 :            :  * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration
    2433                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2434                 :            :  * @wpa_ie: Pointer to buffer for WPA/RSN IE
    2435                 :            :  * @wpa_ie_len: Pointer to the length of the wpa_ie buffer
    2436                 :            :  * Returns: 0 on success, -1 on failure
    2437                 :            :  */
    2438                 :        244 : int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
    2439                 :            :                                     size_t *wpa_ie_len)
    2440                 :            : {
    2441                 :            :         int res;
    2442                 :            : 
    2443         [ -  + ]:        244 :         if (sm == NULL)
    2444                 :          0 :                 return -1;
    2445                 :            : 
    2446                 :        244 :         res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len);
    2447         [ -  + ]:        244 :         if (res < 0)
    2448                 :          0 :                 return -1;
    2449                 :        244 :         *wpa_ie_len = res;
    2450                 :            : 
    2451                 :        244 :         wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default",
    2452                 :            :                     wpa_ie, *wpa_ie_len);
    2453                 :            : 
    2454         [ +  + ]:        244 :         if (sm->assoc_wpa_ie == NULL) {
    2455                 :            :                 /*
    2456                 :            :                  * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets
    2457                 :            :                  * the correct version of the IE even if PMKSA caching is
    2458                 :            :                  * aborted (which would remove PMKID from IE generation).
    2459                 :            :                  */
    2460                 :         88 :                 sm->assoc_wpa_ie = os_malloc(*wpa_ie_len);
    2461         [ -  + ]:         88 :                 if (sm->assoc_wpa_ie == NULL)
    2462                 :          0 :                         return -1;
    2463                 :            : 
    2464                 :         88 :                 os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len);
    2465                 :         88 :                 sm->assoc_wpa_ie_len = *wpa_ie_len;
    2466                 :            :         }
    2467                 :            : 
    2468                 :        244 :         return 0;
    2469                 :            : }
    2470                 :            : 
    2471                 :            : 
    2472                 :            : /**
    2473                 :            :  * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq
    2474                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2475                 :            :  * @ie: Pointer to IE data (starting from id)
    2476                 :            :  * @len: IE length
    2477                 :            :  * Returns: 0 on success, -1 on failure
    2478                 :            :  *
    2479                 :            :  * Inform WPA state machine about the WPA/RSN IE used in (Re)Association
    2480                 :            :  * Request frame. The IE will be used to override the default value generated
    2481                 :            :  * with wpa_sm_set_assoc_wpa_ie_default().
    2482                 :            :  */
    2483                 :        504 : int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
    2484                 :            : {
    2485         [ -  + ]:        504 :         if (sm == NULL)
    2486                 :          0 :                 return -1;
    2487                 :            : 
    2488                 :        504 :         os_free(sm->assoc_wpa_ie);
    2489 [ +  + ][ -  + ]:        504 :         if (ie == NULL || len == 0) {
    2490                 :        288 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    2491                 :            :                         "WPA: clearing own WPA/RSN IE");
    2492                 :        288 :                 sm->assoc_wpa_ie = NULL;
    2493                 :        288 :                 sm->assoc_wpa_ie_len = 0;
    2494                 :            :         } else {
    2495                 :        216 :                 wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len);
    2496                 :        216 :                 sm->assoc_wpa_ie = os_malloc(len);
    2497         [ -  + ]:        216 :                 if (sm->assoc_wpa_ie == NULL)
    2498                 :          0 :                         return -1;
    2499                 :            : 
    2500                 :        216 :                 os_memcpy(sm->assoc_wpa_ie, ie, len);
    2501                 :        216 :                 sm->assoc_wpa_ie_len = len;
    2502                 :            :         }
    2503                 :            : 
    2504                 :        504 :         return 0;
    2505                 :            : }
    2506                 :            : 
    2507                 :            : 
    2508                 :            : /**
    2509                 :            :  * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp
    2510                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2511                 :            :  * @ie: Pointer to IE data (starting from id)
    2512                 :            :  * @len: IE length
    2513                 :            :  * Returns: 0 on success, -1 on failure
    2514                 :            :  *
    2515                 :            :  * Inform WPA state machine about the WPA IE used in Beacon / Probe Response
    2516                 :            :  * frame.
    2517                 :            :  */
    2518                 :        379 : int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
    2519                 :            : {
    2520         [ -  + ]:        379 :         if (sm == NULL)
    2521                 :          0 :                 return -1;
    2522                 :            : 
    2523                 :        379 :         os_free(sm->ap_wpa_ie);
    2524 [ +  + ][ -  + ]:        379 :         if (ie == NULL || len == 0) {
    2525                 :        366 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    2526                 :            :                         "WPA: clearing AP WPA IE");
    2527                 :        366 :                 sm->ap_wpa_ie = NULL;
    2528                 :        366 :                 sm->ap_wpa_ie_len = 0;
    2529                 :            :         } else {
    2530                 :         13 :                 wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len);
    2531                 :         13 :                 sm->ap_wpa_ie = os_malloc(len);
    2532         [ -  + ]:         13 :                 if (sm->ap_wpa_ie == NULL)
    2533                 :          0 :                         return -1;
    2534                 :            : 
    2535                 :         13 :                 os_memcpy(sm->ap_wpa_ie, ie, len);
    2536                 :         13 :                 sm->ap_wpa_ie_len = len;
    2537                 :            :         }
    2538                 :            : 
    2539                 :        379 :         return 0;
    2540                 :            : }
    2541                 :            : 
    2542                 :            : 
    2543                 :            : /**
    2544                 :            :  * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp
    2545                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2546                 :            :  * @ie: Pointer to IE data (starting from id)
    2547                 :            :  * @len: IE length
    2548                 :            :  * Returns: 0 on success, -1 on failure
    2549                 :            :  *
    2550                 :            :  * Inform WPA state machine about the RSN IE used in Beacon / Probe Response
    2551                 :            :  * frame.
    2552                 :            :  */
    2553                 :        385 : int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
    2554                 :            : {
    2555         [ -  + ]:        385 :         if (sm == NULL)
    2556                 :          0 :                 return -1;
    2557                 :            : 
    2558                 :        385 :         os_free(sm->ap_rsn_ie);
    2559 [ +  + ][ -  + ]:        385 :         if (ie == NULL || len == 0) {
    2560                 :        151 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    2561                 :            :                         "WPA: clearing AP RSN IE");
    2562                 :        151 :                 sm->ap_rsn_ie = NULL;
    2563                 :        151 :                 sm->ap_rsn_ie_len = 0;
    2564                 :            :         } else {
    2565                 :        234 :                 wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
    2566                 :        234 :                 sm->ap_rsn_ie = os_malloc(len);
    2567         [ -  + ]:        234 :                 if (sm->ap_rsn_ie == NULL)
    2568                 :          0 :                         return -1;
    2569                 :            : 
    2570                 :        234 :                 os_memcpy(sm->ap_rsn_ie, ie, len);
    2571                 :        234 :                 sm->ap_rsn_ie_len = len;
    2572                 :            :         }
    2573                 :            : 
    2574                 :        385 :         return 0;
    2575                 :            : }
    2576                 :            : 
    2577                 :            : 
    2578                 :            : /**
    2579                 :            :  * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
    2580                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2581                 :            :  * @data: Pointer to data area for parsing results
    2582                 :            :  * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure
    2583                 :            :  *
    2584                 :            :  * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the
    2585                 :            :  * parsed data into data.
    2586                 :            :  */
    2587                 :          6 : int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data)
    2588                 :            : {
    2589         [ -  + ]:          6 :         if (sm == NULL)
    2590                 :          0 :                 return -1;
    2591                 :            : 
    2592         [ +  - ]:          6 :         if (sm->assoc_wpa_ie == NULL) {
    2593                 :          6 :                 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
    2594                 :            :                         "WPA: No WPA/RSN IE available from association info");
    2595                 :          6 :                 return -1;
    2596                 :            :         }
    2597         [ #  # ]:          0 :         if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data))
    2598                 :          0 :                 return -2;
    2599                 :          6 :         return 0;
    2600                 :            : }
    2601                 :            : 
    2602                 :            : 
    2603                 :          0 : int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
    2604                 :            : {
    2605                 :          0 :         return pmksa_cache_list(sm->pmksa, buf, len);
    2606                 :            : }
    2607                 :            : 
    2608                 :            : 
    2609                 :          0 : void wpa_sm_drop_sa(struct wpa_sm *sm)
    2610                 :            : {
    2611                 :          0 :         wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK");
    2612                 :          0 :         sm->ptk_set = 0;
    2613                 :          0 :         sm->tptk_set = 0;
    2614                 :          0 :         os_memset(sm->pmk, 0, sizeof(sm->pmk));
    2615                 :          0 :         os_memset(&sm->ptk, 0, sizeof(sm->ptk));
    2616                 :          0 :         os_memset(&sm->tptk, 0, sizeof(sm->tptk));
    2617                 :          0 : }
    2618                 :            : 
    2619                 :            : 
    2620                 :         10 : int wpa_sm_has_ptk(struct wpa_sm *sm)
    2621                 :            : {
    2622         [ -  + ]:         10 :         if (sm == NULL)
    2623                 :          0 :                 return 0;
    2624                 :         10 :         return sm->ptk_set;
    2625                 :            : }
    2626                 :            : 
    2627                 :            : 
    2628                 :          0 : void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr)
    2629                 :            : {
    2630                 :          0 :         os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN);
    2631                 :          0 : }
    2632                 :            : 
    2633                 :            : 
    2634                 :       1117 : void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
    2635                 :            : {
    2636                 :       1117 :         pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0);
    2637                 :       1117 : }
    2638                 :            : 
    2639                 :            : 
    2640                 :            : #ifdef CONFIG_WNM
    2641                 :          2 : int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
    2642                 :            : {
    2643                 :            :         struct wpa_gtk_data gd;
    2644                 :            : #ifdef CONFIG_IEEE80211W
    2645                 :            :         struct wpa_igtk_kde igd;
    2646                 :            :         u16 keyidx;
    2647                 :            : #endif /* CONFIG_IEEE80211W */
    2648                 :            :         u16 keyinfo;
    2649                 :            :         u8 keylen;  /* plaintext key len */
    2650                 :            :         u8 *key_rsc;
    2651                 :            : 
    2652                 :          2 :         os_memset(&gd, 0, sizeof(gd));
    2653                 :            : #ifdef CONFIG_IEEE80211W
    2654                 :          2 :         os_memset(&igd, 0, sizeof(igd));
    2655                 :            : #endif /* CONFIG_IEEE80211W */
    2656                 :            : 
    2657                 :          2 :         keylen = wpa_cipher_key_len(sm->group_cipher);
    2658                 :          2 :         gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
    2659                 :          2 :         gd.alg = wpa_cipher_to_alg(sm->group_cipher);
    2660         [ -  + ]:          2 :         if (gd.alg == WPA_ALG_NONE) {
    2661                 :          0 :                 wpa_printf(MSG_DEBUG, "Unsupported group cipher suite");
    2662                 :          0 :                 return -1;
    2663                 :            :         }
    2664                 :            : 
    2665         [ +  + ]:          2 :         if (subelem_id == WNM_SLEEP_SUBELEM_GTK) {
    2666                 :          1 :                 key_rsc = buf + 5;
    2667                 :          1 :                 keyinfo = WPA_GET_LE16(buf + 2);
    2668                 :          1 :                 gd.gtk_len = keylen;
    2669         [ -  + ]:          1 :                 if (gd.gtk_len != buf[4]) {
    2670                 :          0 :                         wpa_printf(MSG_DEBUG, "GTK len mismatch len %d vs %d",
    2671                 :          0 :                                    gd.gtk_len, buf[4]);
    2672                 :          0 :                         return -1;
    2673                 :            :                 }
    2674                 :          1 :                 gd.keyidx = keyinfo & 0x03; /* B0 - B1 */
    2675                 :          1 :                 gd.tx = wpa_supplicant_gtk_tx_bit_workaround(
    2676                 :          1 :                          sm, !!(keyinfo & WPA_KEY_INFO_TXRX));
    2677                 :            : 
    2678                 :          1 :                 os_memcpy(gd.gtk, buf + 13, gd.gtk_len);
    2679                 :            : 
    2680                 :          1 :                 wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
    2681                 :          1 :                                 gd.gtk, gd.gtk_len);
    2682         [ -  + ]:          1 :                 if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) {
    2683                 :          0 :                         wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
    2684                 :            :                                    "WNM mode");
    2685                 :          0 :                         return -1;
    2686                 :            :                 }
    2687                 :            : #ifdef CONFIG_IEEE80211W
    2688         [ +  - ]:          1 :         } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
    2689                 :          1 :                 os_memcpy(igd.keyid, buf + 2, 2);
    2690                 :          1 :                 os_memcpy(igd.pn, buf + 4, 6);
    2691                 :            : 
    2692                 :          1 :                 keyidx = WPA_GET_LE16(igd.keyid);
    2693                 :          1 :                 os_memcpy(igd.igtk, buf + 10, WPA_IGTK_LEN);
    2694                 :            : 
    2695                 :          1 :                 wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)",
    2696                 :            :                                 igd.igtk, WPA_IGTK_LEN);
    2697         [ -  + ]:          1 :                 if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr,
    2698                 :            :                                    keyidx, 0, igd.pn, sizeof(igd.pn),
    2699                 :            :                                    igd.igtk, WPA_IGTK_LEN) < 0) {
    2700                 :          0 :                         wpa_printf(MSG_DEBUG, "Failed to install the IGTK in "
    2701                 :            :                                    "WNM mode");
    2702                 :          0 :                         return -1;
    2703                 :            :                 }
    2704                 :            : #endif /* CONFIG_IEEE80211W */
    2705                 :            :         } else {
    2706                 :          0 :                 wpa_printf(MSG_DEBUG, "Unknown element id");
    2707                 :          0 :                 return -1;
    2708                 :            :         }
    2709                 :            : 
    2710                 :          2 :         return 0;
    2711                 :            : }
    2712                 :            : #endif /* CONFIG_WNM */
    2713                 :            : 
    2714                 :            : 
    2715                 :            : #ifdef CONFIG_PEERKEY
    2716                 :          9 : int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr,
    2717                 :            :                             const u8 *buf, size_t len)
    2718                 :            : {
    2719                 :            :         struct wpa_peerkey *peerkey;
    2720                 :            : 
    2721         [ +  + ]:         11 :         for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
    2722         [ +  + ]:          6 :                 if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
    2723                 :          4 :                         break;
    2724                 :            :         }
    2725                 :            : 
    2726         [ +  + ]:          9 :         if (!peerkey)
    2727                 :          5 :                 return 0;
    2728                 :            : 
    2729                 :          4 :         wpa_sm_rx_eapol(sm, src_addr, buf, len);
    2730                 :            : 
    2731                 :          9 :         return 1;
    2732                 :            : }
    2733                 :            : #endif /* CONFIG_PEERKEY */

Generated by: LCOV version 1.9