LCOV - code coverage report
Current view: top level - src/rsn_supp - wpa_ft.c (source / functions) Hit Total Coverage
Test: wpa_supplicant hwsim test run 1388167526 Lines: 277 426 65.0 %
Date: 2013-12-27 Functions: 11 12 91.7 %
Branches: 115 204 56.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * WPA Supplicant - IEEE 802.11r - Fast BSS Transition
       3                 :            :  * Copyright (c) 2006-2007, 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/random.h"
      14                 :            : #include "common/ieee802_11_defs.h"
      15                 :            : #include "common/ieee802_11_common.h"
      16                 :            : #include "wpa.h"
      17                 :            : #include "wpa_i.h"
      18                 :            : 
      19                 :            : #ifdef CONFIG_IEEE80211R
      20                 :            : 
      21                 :          3 : int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
      22                 :            :                       const struct wpa_eapol_key *key,
      23                 :            :                       struct wpa_ptk *ptk, size_t ptk_len)
      24                 :            : {
      25                 :            :         u8 ptk_name[WPA_PMK_NAME_LEN];
      26                 :          3 :         const u8 *anonce = key->key_nonce;
      27                 :            : 
      28         [ -  + ]:          3 :         if (sm->xxkey_len == 0) {
      29                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
      30                 :            :                            "derivation");
      31                 :          0 :                 return -1;
      32                 :            :         }
      33                 :            : 
      34                 :          3 :         wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid,
      35                 :          3 :                           sm->ssid_len, sm->mobility_domain,
      36                 :          6 :                           sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
      37                 :          3 :                           sm->pmk_r0, sm->pmk_r0_name);
      38                 :          3 :         wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, PMK_LEN);
      39                 :          3 :         wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name",
      40                 :          3 :                     sm->pmk_r0_name, WPA_PMK_NAME_LEN);
      41                 :          3 :         wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
      42                 :          3 :                           sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
      43                 :          3 :         wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
      44                 :          3 :         wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
      45                 :            :                     WPA_PMK_NAME_LEN);
      46                 :          3 :         wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
      47                 :          3 :                           sm->bssid, sm->pmk_r1_name,
      48                 :            :                           (u8 *) ptk, ptk_len, ptk_name);
      49                 :          3 :         wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len);
      50                 :          3 :         wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
      51                 :            : 
      52                 :          3 :         return 0;
      53                 :            : }
      54                 :            : 
      55                 :            : 
      56                 :            : /**
      57                 :            :  * wpa_sm_set_ft_params - Set FT (IEEE 802.11r) parameters
      58                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
      59                 :            :  * @ies: Association Response IEs or %NULL to clear FT parameters
      60                 :            :  * @ies_len: Length of ies buffer in octets
      61                 :            :  * Returns: 0 on success, -1 on failure
      62                 :            :  */
      63                 :        682 : int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
      64                 :            : {
      65                 :            :         struct wpa_ft_ies ft;
      66                 :            : 
      67         [ -  + ]:        682 :         if (sm == NULL)
      68                 :          0 :                 return 0;
      69                 :            : 
      70         [ -  + ]:        682 :         if (wpa_ft_parse_ies(ies, ies_len, &ft) < 0)
      71                 :          0 :                 return -1;
      72                 :            : 
      73 [ +  + ][ -  + ]:        682 :         if (ft.mdie && ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1)
      74                 :          0 :                 return -1;
      75                 :            : 
      76         [ +  + ]:        682 :         if (ft.mdie) {
      77                 :         18 :                 wpa_hexdump(MSG_DEBUG, "FT: Mobility domain",
      78                 :         18 :                             ft.mdie, MOBILITY_DOMAIN_ID_LEN);
      79                 :         18 :                 os_memcpy(sm->mobility_domain, ft.mdie,
      80                 :            :                           MOBILITY_DOMAIN_ID_LEN);
      81                 :         18 :                 sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN];
      82                 :         18 :                 wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x",
      83                 :         18 :                            sm->mdie_ft_capab);
      84                 :            :         } else
      85                 :        664 :                 os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN);
      86                 :            : 
      87         [ +  + ]:        682 :         if (ft.r0kh_id) {
      88                 :          9 :                 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID",
      89                 :          9 :                             ft.r0kh_id, ft.r0kh_id_len);
      90                 :          9 :                 os_memcpy(sm->r0kh_id, ft.r0kh_id, ft.r0kh_id_len);
      91                 :          9 :                 sm->r0kh_id_len = ft.r0kh_id_len;
      92                 :            :         } else {
      93                 :            :                 /* FIX: When should R0KH-ID be cleared? We need to keep the
      94                 :            :                  * old R0KH-ID in order to be able to use this during FT. */
      95                 :            :                 /*
      96                 :            :                  * os_memset(sm->r0kh_id, 0, FT_R0KH_ID_LEN);
      97                 :            :                  * sm->r0kh_id_len = 0;
      98                 :            :                  */
      99                 :            :         }
     100                 :            : 
     101         [ +  + ]:        682 :         if (ft.r1kh_id) {
     102                 :          9 :                 wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID",
     103                 :          9 :                             ft.r1kh_id, FT_R1KH_ID_LEN);
     104                 :          9 :                 os_memcpy(sm->r1kh_id, ft.r1kh_id, FT_R1KH_ID_LEN);
     105                 :            :         } else
     106                 :        673 :                 os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN);
     107                 :            : 
     108                 :        682 :         os_free(sm->assoc_resp_ies);
     109                 :        682 :         sm->assoc_resp_ies = os_malloc(ft.mdie_len + 2 + ft.ftie_len + 2);
     110         [ +  - ]:        682 :         if (sm->assoc_resp_ies) {
     111                 :        682 :                 u8 *pos = sm->assoc_resp_ies;
     112         [ +  + ]:        682 :                 if (ft.mdie) {
     113                 :         18 :                         os_memcpy(pos, ft.mdie - 2, ft.mdie_len + 2);
     114                 :         18 :                         pos += ft.mdie_len + 2;
     115                 :            :                 }
     116         [ +  + ]:        682 :                 if (ft.ftie) {
     117                 :          9 :                         os_memcpy(pos, ft.ftie - 2, ft.ftie_len + 2);
     118                 :          9 :                         pos += ft.ftie_len + 2;
     119                 :            :                 }
     120                 :        682 :                 sm->assoc_resp_ies_len = pos - sm->assoc_resp_ies;
     121                 :        682 :                 wpa_hexdump(MSG_DEBUG, "FT: Stored MDIE and FTIE from "
     122                 :            :                             "(Re)Association Response",
     123                 :        682 :                             sm->assoc_resp_ies, sm->assoc_resp_ies_len);
     124                 :            :         }
     125                 :            : 
     126                 :        682 :         return 0;
     127                 :            : }
     128                 :            : 
     129                 :            : 
     130                 :            : /**
     131                 :            :  * wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth/ReAssoc Request
     132                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     133                 :            :  * @len: Buffer for returning the length of the IEs
     134                 :            :  * @anonce: ANonce or %NULL if not yet available
     135                 :            :  * @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List
     136                 :            :  * @kck: 128-bit KCK for MIC or %NULL if no MIC is used
     137                 :            :  * @target_ap: Target AP address
     138                 :            :  * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL
     139                 :            :  * @ric_ies_len: Length of ric_ies buffer in octets
     140                 :            :  * @ap_mdie: Mobility Domain IE from the target AP
     141                 :            :  * Returns: Pointer to buffer with IEs or %NULL on failure
     142                 :            :  *
     143                 :            :  * Caller is responsible for freeing the returned buffer with os_free();
     144                 :            :  */
     145                 :         30 : static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
     146                 :            :                                const u8 *anonce, const u8 *pmk_name,
     147                 :            :                                const u8 *kck, const u8 *target_ap,
     148                 :            :                                const u8 *ric_ies, size_t ric_ies_len,
     149                 :            :                                const u8 *ap_mdie)
     150                 :            : {
     151                 :            :         size_t buf_len;
     152                 :            :         u8 *buf, *pos, *ftie_len, *ftie_pos;
     153                 :            :         struct rsn_mdie *mdie;
     154                 :            :         struct rsn_ftie *ftie;
     155                 :            :         struct rsn_ie_hdr *rsnie;
     156                 :            :         u16 capab;
     157                 :            : 
     158                 :         30 :         sm->ft_completed = 0;
     159                 :            : 
     160                 :         30 :         buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
     161                 :         30 :                 2 + sm->r0kh_id_len + ric_ies_len + 100;
     162                 :         30 :         buf = os_zalloc(buf_len);
     163         [ -  + ]:         30 :         if (buf == NULL)
     164                 :          0 :                 return NULL;
     165                 :         30 :         pos = buf;
     166                 :            : 
     167                 :            :         /* RSNIE[PMKR0Name/PMKR1Name] */
     168                 :         30 :         rsnie = (struct rsn_ie_hdr *) pos;
     169                 :         30 :         rsnie->elem_id = WLAN_EID_RSN;
     170                 :         30 :         WPA_PUT_LE16(rsnie->version, RSN_VERSION);
     171                 :         30 :         pos = (u8 *) (rsnie + 1);
     172                 :            : 
     173                 :            :         /* Group Suite Selector */
     174 [ +  + ][ +  - ]:         30 :         if (sm->group_cipher != WPA_CIPHER_CCMP &&
     175         [ -  + ]:         10 :             sm->group_cipher != WPA_CIPHER_GCMP &&
     176                 :         10 :             sm->group_cipher != WPA_CIPHER_TKIP) {
     177                 :          0 :                 wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)",
     178                 :            :                            sm->group_cipher);
     179                 :          0 :                 os_free(buf);
     180                 :          0 :                 return NULL;
     181                 :            :         }
     182                 :         30 :         RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
     183                 :            :                                                   sm->group_cipher));
     184                 :         30 :         pos += RSN_SELECTOR_LEN;
     185                 :            : 
     186                 :            :         /* Pairwise Suite Count */
     187                 :         30 :         WPA_PUT_LE16(pos, 1);
     188                 :         30 :         pos += 2;
     189                 :            : 
     190                 :            :         /* Pairwise Suite List */
     191         [ -  + ]:         30 :         if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
     192                 :          0 :                 wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)",
     193                 :            :                            sm->pairwise_cipher);
     194                 :          0 :                 os_free(buf);
     195                 :          0 :                 return NULL;
     196                 :            :         }
     197                 :         30 :         RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
     198                 :            :                                                   sm->pairwise_cipher));
     199                 :         30 :         pos += RSN_SELECTOR_LEN;
     200                 :            : 
     201                 :            :         /* Authenticated Key Management Suite Count */
     202                 :         30 :         WPA_PUT_LE16(pos, 1);
     203                 :         30 :         pos += 2;
     204                 :            : 
     205                 :            :         /* Authenticated Key Management Suite List */
     206         [ -  + ]:         30 :         if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X)
     207                 :          0 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
     208         [ +  - ]:         30 :         else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK)
     209                 :         30 :                 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
     210                 :            :         else {
     211                 :          0 :                 wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)",
     212                 :            :                            sm->key_mgmt);
     213                 :          0 :                 os_free(buf);
     214                 :          0 :                 return NULL;
     215                 :            :         }
     216                 :         30 :         pos += RSN_SELECTOR_LEN;
     217                 :            : 
     218                 :            :         /* RSN Capabilities */
     219                 :         30 :         capab = 0;
     220                 :            : #ifdef CONFIG_IEEE80211W
     221         [ +  + ]:         30 :         if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)
     222                 :         10 :                 capab |= WPA_CAPABILITY_MFPC;
     223                 :            : #endif /* CONFIG_IEEE80211W */
     224                 :         30 :         WPA_PUT_LE16(pos, capab);
     225                 :         30 :         pos += 2;
     226                 :            : 
     227                 :            :         /* PMKID Count */
     228                 :         30 :         WPA_PUT_LE16(pos, 1);
     229                 :         30 :         pos += 2;
     230                 :            : 
     231                 :            :         /* PMKID List [PMKR0Name/PMKR1Name] */
     232                 :         30 :         os_memcpy(pos, pmk_name, WPA_PMK_NAME_LEN);
     233                 :         30 :         pos += WPA_PMK_NAME_LEN;
     234                 :            : 
     235                 :            : #ifdef CONFIG_IEEE80211W
     236         [ +  + ]:         30 :         if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
     237                 :            :                 /* Management Group Cipher Suite */
     238                 :         10 :                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
     239                 :         10 :                 pos += RSN_SELECTOR_LEN;
     240                 :            :         }
     241                 :            : #endif /* CONFIG_IEEE80211W */
     242                 :            : 
     243                 :         30 :         rsnie->len = (pos - (u8 *) rsnie) - 2;
     244                 :            : 
     245                 :            :         /* MDIE */
     246                 :         30 :         *pos++ = WLAN_EID_MOBILITY_DOMAIN;
     247                 :         30 :         *pos++ = sizeof(*mdie);
     248                 :         30 :         mdie = (struct rsn_mdie *) pos;
     249                 :         30 :         pos += sizeof(*mdie);
     250                 :         30 :         os_memcpy(mdie->mobility_domain, sm->mobility_domain,
     251                 :            :                   MOBILITY_DOMAIN_ID_LEN);
     252 [ +  + ][ +  - ]:         30 :         mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] :
     253                 :            :                 sm->mdie_ft_capab;
     254                 :            : 
     255                 :            :         /* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */
     256                 :         30 :         ftie_pos = pos;
     257                 :         30 :         *pos++ = WLAN_EID_FAST_BSS_TRANSITION;
     258                 :         30 :         ftie_len = pos++;
     259                 :         30 :         ftie = (struct rsn_ftie *) pos;
     260                 :         30 :         pos += sizeof(*ftie);
     261                 :         30 :         os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN);
     262         [ +  + ]:         30 :         if (anonce)
     263                 :          6 :                 os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN);
     264         [ +  + ]:         30 :         if (kck) {
     265                 :            :                 /* R1KH-ID sub-element in third FT message */
     266                 :          6 :                 *pos++ = FTIE_SUBELEM_R1KH_ID;
     267                 :          6 :                 *pos++ = FT_R1KH_ID_LEN;
     268                 :          6 :                 os_memcpy(pos, sm->r1kh_id, FT_R1KH_ID_LEN);
     269                 :          6 :                 pos += FT_R1KH_ID_LEN;
     270                 :            :         }
     271                 :            :         /* R0KH-ID sub-element */
     272                 :         30 :         *pos++ = FTIE_SUBELEM_R0KH_ID;
     273                 :         30 :         *pos++ = sm->r0kh_id_len;
     274                 :         30 :         os_memcpy(pos, sm->r0kh_id, sm->r0kh_id_len);
     275                 :         30 :         pos += sm->r0kh_id_len;
     276                 :         30 :         *ftie_len = pos - ftie_len - 1;
     277                 :            : 
     278         [ -  + ]:         30 :         if (ric_ies) {
     279                 :            :                 /* RIC Request */
     280                 :          0 :                 os_memcpy(pos, ric_ies, ric_ies_len);
     281                 :          0 :                 pos += ric_ies_len;
     282                 :            :         }
     283                 :            : 
     284         [ +  + ]:         30 :         if (kck) {
     285                 :            :                 /*
     286                 :            :                  * IEEE Std 802.11r-2008, 11A.8.4
     287                 :            :                  * MIC shall be calculated over:
     288                 :            :                  * non-AP STA MAC address
     289                 :            :                  * Target AP MAC address
     290                 :            :                  * Transaction seq number (5 for ReassocReq, 3 otherwise)
     291                 :            :                  * RSN IE
     292                 :            :                  * MDIE
     293                 :            :                  * FTIE (with MIC field set to 0)
     294                 :            :                  * RIC-Request (if present)
     295                 :            :                  */
     296                 :            :                 /* Information element count */
     297                 :          6 :                 ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies,
     298                 :            :                                                                ric_ies_len);
     299         [ -  + ]:          6 :                 if (wpa_ft_mic(kck, sm->own_addr, target_ap, 5,
     300                 :            :                                ((u8 *) mdie) - 2, 2 + sizeof(*mdie),
     301                 :          6 :                                ftie_pos, 2 + *ftie_len,
     302                 :          6 :                                (u8 *) rsnie, 2 + rsnie->len, ric_ies,
     303                 :          6 :                                ric_ies_len, ftie->mic) < 0) {
     304                 :          0 :                         wpa_printf(MSG_INFO, "FT: Failed to calculate MIC");
     305                 :          0 :                         os_free(buf);
     306                 :          0 :                         return NULL;
     307                 :            :                 }
     308                 :            :         }
     309                 :            : 
     310                 :         30 :         *len = pos - buf;
     311                 :            : 
     312                 :         30 :         return buf;
     313                 :            : }
     314                 :            : 
     315                 :            : 
     316                 :         12 : static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
     317                 :            : {
     318                 :            :         int keylen;
     319                 :            :         enum wpa_alg alg;
     320                 :         12 :         u8 null_rsc[6] = { 0, 0, 0, 0, 0, 0 };
     321                 :            : 
     322                 :         12 :         wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver.");
     323                 :            : 
     324         [ -  + ]:         12 :         if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
     325                 :          0 :                 wpa_printf(MSG_WARNING, "FT: Unsupported pairwise cipher %d",
     326                 :            :                            sm->pairwise_cipher);
     327                 :          0 :                 return -1;
     328                 :            :         }
     329                 :            : 
     330                 :         12 :         alg = wpa_cipher_to_alg(sm->pairwise_cipher);
     331                 :         12 :         keylen = wpa_cipher_key_len(sm->pairwise_cipher);
     332                 :            : 
     333         [ +  + ]:         12 :         if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc,
     334                 :         12 :                            sizeof(null_rsc), (u8 *) sm->ptk.tk1, keylen) < 0) {
     335                 :          6 :                 wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver");
     336                 :          6 :                 return -1;
     337                 :            :         }
     338                 :            : 
     339                 :         12 :         return 0;
     340                 :            : }
     341                 :            : 
     342                 :            : 
     343                 :            : /**
     344                 :            :  * wpa_ft_prepare_auth_request - Generate over-the-air auth request
     345                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     346                 :            :  * @mdie: Target AP MDIE
     347                 :            :  * Returns: 0 on success, -1 on failure
     348                 :            :  */
     349                 :         24 : int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie)
     350                 :            : {
     351                 :            :         u8 *ft_ies;
     352                 :            :         size_t ft_ies_len;
     353                 :            : 
     354                 :            :         /* Generate a new SNonce */
     355         [ -  + ]:         24 :         if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
     356                 :          0 :                 wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
     357                 :          0 :                 return -1;
     358                 :            :         }
     359                 :            : 
     360                 :         24 :         ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
     361                 :         24 :                                     NULL, sm->bssid, NULL, 0, mdie);
     362         [ +  - ]:         24 :         if (ft_ies) {
     363                 :         24 :                 wpa_sm_update_ft_ies(sm, sm->mobility_domain,
     364                 :            :                                      ft_ies, ft_ies_len);
     365                 :         24 :                 os_free(ft_ies);
     366                 :            :         }
     367                 :            : 
     368                 :         24 :         return 0;
     369                 :            : }
     370                 :            : 
     371                 :            : 
     372                 :          6 : int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
     373                 :            :                             int ft_action, const u8 *target_ap,
     374                 :            :                             const u8 *ric_ies, size_t ric_ies_len)
     375                 :            : {
     376                 :            :         u8 *ft_ies;
     377                 :            :         size_t ft_ies_len, ptk_len;
     378                 :            :         struct wpa_ft_ies parse;
     379                 :            :         struct rsn_mdie *mdie;
     380                 :            :         struct rsn_ftie *ftie;
     381                 :            :         u8 ptk_name[WPA_PMK_NAME_LEN];
     382                 :            :         int ret;
     383                 :            :         const u8 *bssid;
     384                 :            : 
     385                 :          6 :         wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
     386                 :          6 :         wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len);
     387                 :            : 
     388         [ -  + ]:          6 :         if (ft_action) {
     389         [ #  # ]:          0 :                 if (!sm->over_the_ds_in_progress) {
     390                 :          0 :                         wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress "
     391                 :            :                                    "- drop FT Action Response");
     392                 :          0 :                         return -1;
     393                 :            :                 }
     394                 :            : 
     395         [ #  # ]:          0 :                 if (os_memcmp(target_ap, sm->target_ap, ETH_ALEN) != 0) {
     396                 :          0 :                         wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress "
     397                 :            :                                    "with this Target AP - drop FT Action "
     398                 :            :                                    "Response");
     399                 :          0 :                         return -1;
     400                 :            :                 }
     401                 :            :         }
     402                 :            : 
     403 [ +  - ][ -  + ]:          6 :         if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
     404                 :          6 :             sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) {
     405                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
     406                 :            :                            "enabled for this connection");
     407                 :          0 :                 return -1;
     408                 :            :         }
     409                 :            : 
     410         [ -  + ]:          6 :         if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
     411                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
     412                 :          0 :                 return -1;
     413                 :            :         }
     414                 :            : 
     415                 :          6 :         mdie = (struct rsn_mdie *) parse.mdie;
     416 [ +  - ][ +  - ]:          6 :         if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
                 [ -  + ]
     417                 :          6 :             os_memcmp(mdie->mobility_domain, sm->mobility_domain,
     418                 :            :                       MOBILITY_DOMAIN_ID_LEN) != 0) {
     419                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
     420                 :          0 :                 return -1;
     421                 :            :         }
     422                 :            : 
     423                 :          6 :         ftie = (struct rsn_ftie *) parse.ftie;
     424 [ +  - ][ -  + ]:          6 :         if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
     425                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
     426                 :          0 :                 return -1;
     427                 :            :         }
     428                 :            : 
     429         [ -  + ]:          6 :         if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
     430                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
     431                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
     432                 :          0 :                             ftie->snonce, WPA_NONCE_LEN);
     433                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
     434                 :          0 :                             sm->snonce, WPA_NONCE_LEN);
     435                 :          0 :                 return -1;
     436                 :            :         }
     437                 :            : 
     438         [ -  + ]:          6 :         if (parse.r0kh_id == NULL) {
     439                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
     440                 :          0 :                 return -1;
     441                 :            :         }
     442                 :            : 
     443 [ +  - ][ -  + ]:          6 :         if (parse.r0kh_id_len != sm->r0kh_id_len ||
     444                 :          6 :             os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
     445                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
     446                 :            :                            "the current R0KH-ID");
     447                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
     448                 :          0 :                             parse.r0kh_id, parse.r0kh_id_len);
     449                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
     450                 :          0 :                             sm->r0kh_id, sm->r0kh_id_len);
     451                 :          0 :                 return -1;
     452                 :            :         }
     453                 :            : 
     454         [ -  + ]:          6 :         if (parse.r1kh_id == NULL) {
     455                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
     456                 :          0 :                 return -1;
     457                 :            :         }
     458                 :            : 
     459 [ +  - ][ -  + ]:          6 :         if (parse.rsn_pmkid == NULL ||
     460                 :          6 :             os_memcmp(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN)) {
     461                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name (PMKID) in "
     462                 :            :                            "RSNIE");
     463                 :          0 :                 return -1;
     464                 :            :         }
     465                 :            : 
     466                 :          6 :         os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
     467                 :          6 :         wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", sm->r1kh_id, FT_R1KH_ID_LEN);
     468                 :          6 :         wpa_hexdump(MSG_DEBUG, "FT: SNonce", sm->snonce, WPA_NONCE_LEN);
     469                 :          6 :         wpa_hexdump(MSG_DEBUG, "FT: ANonce", ftie->anonce, WPA_NONCE_LEN);
     470                 :          6 :         os_memcpy(sm->anonce, ftie->anonce, WPA_NONCE_LEN);
     471                 :          6 :         wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
     472                 :          6 :                           sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
     473                 :          6 :         wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
     474                 :          6 :         wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name",
     475                 :          6 :                     sm->pmk_r1_name, WPA_PMK_NAME_LEN);
     476                 :            : 
     477                 :          6 :         bssid = target_ap;
     478         [ +  - ]:          6 :         ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64;
     479                 :          6 :         wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, sm->own_addr,
     480                 :          6 :                           bssid, sm->pmk_r1_name,
     481                 :          6 :                           (u8 *) &sm->ptk, ptk_len, ptk_name);
     482                 :          6 :         wpa_hexdump_key(MSG_DEBUG, "FT: PTK",
     483                 :          6 :                         (u8 *) &sm->ptk, ptk_len);
     484                 :          6 :         wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
     485                 :            : 
     486         [ +  - ]:          6 :         ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
     487                 :          6 :                                     sm->pmk_r1_name, sm->ptk.kck, bssid,
     488                 :            :                                     ric_ies, ric_ies_len,
     489                 :         12 :                                     parse.mdie ? parse.mdie - 2 : NULL);
     490         [ +  - ]:          6 :         if (ft_ies) {
     491                 :          6 :                 wpa_sm_update_ft_ies(sm, sm->mobility_domain,
     492                 :            :                                      ft_ies, ft_ies_len);
     493                 :          6 :                 os_free(ft_ies);
     494                 :            :         }
     495                 :            : 
     496                 :          6 :         wpa_sm_mark_authenticated(sm, bssid);
     497                 :          6 :         ret = wpa_ft_install_ptk(sm, bssid);
     498         [ +  - ]:          6 :         if (ret) {
     499                 :            :                 /*
     500                 :            :                  * Some drivers do not support key configuration when we are
     501                 :            :                  * not associated with the target AP. Work around this by
     502                 :            :                  * trying again after the following reassociation gets
     503                 :            :                  * completed.
     504                 :            :                  */
     505                 :          6 :                 wpa_printf(MSG_DEBUG, "FT: Failed to set PTK prior to "
     506                 :            :                            "association - try again after reassociation");
     507                 :          6 :                 sm->set_ptk_after_assoc = 1;
     508                 :            :         } else
     509                 :          0 :                 sm->set_ptk_after_assoc = 0;
     510                 :            : 
     511                 :          6 :         sm->ft_completed = 1;
     512         [ -  + ]:          6 :         if (ft_action) {
     513                 :            :                 /*
     514                 :            :                  * The caller is expected trigger re-association with the
     515                 :            :                  * Target AP.
     516                 :            :                  */
     517                 :          0 :                 os_memcpy(sm->bssid, target_ap, ETH_ALEN);
     518                 :            :         }
     519                 :            : 
     520                 :          6 :         return 0;
     521                 :            : }
     522                 :            : 
     523                 :            : 
     524                 :        676 : int wpa_ft_is_completed(struct wpa_sm *sm)
     525                 :            : {
     526         [ -  + ]:        676 :         if (sm == NULL)
     527                 :          0 :                 return 0;
     528                 :            : 
     529 [ +  - ][ +  + ]:        676 :         if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
     530                 :        676 :             sm->key_mgmt != WPA_KEY_MGMT_FT_PSK)
     531                 :        658 :                 return 0;
     532                 :            : 
     533                 :        676 :         return sm->ft_completed;
     534                 :            : }
     535                 :            : 
     536                 :            : 
     537                 :        646 : void wpa_reset_ft_completed(struct wpa_sm *sm)
     538                 :            : {
     539         [ +  - ]:        646 :         if (sm != NULL)
     540                 :        646 :                 sm->ft_completed = 0;
     541                 :        646 : }
     542                 :            : 
     543                 :            : 
     544                 :          6 : static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
     545                 :            :                                       size_t gtk_elem_len)
     546                 :            : {
     547                 :            :         u8 gtk[32];
     548                 :            :         int keyidx;
     549                 :            :         enum wpa_alg alg;
     550                 :            :         size_t gtk_len, keylen, rsc_len;
     551                 :            : 
     552         [ -  + ]:          6 :         if (gtk_elem == NULL) {
     553                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE");
     554                 :          0 :                 return 0;
     555                 :            :         }
     556                 :            : 
     557                 :          6 :         wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp",
     558                 :            :                         gtk_elem, gtk_elem_len);
     559                 :            : 
     560 [ +  - ][ +  - ]:          6 :         if (gtk_elem_len < 11 + 24 || (gtk_elem_len - 11) % 8 ||
                 [ -  + ]
     561                 :          6 :             gtk_elem_len - 19 > sizeof(gtk)) {
     562                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem "
     563                 :            :                            "length %lu", (unsigned long) gtk_elem_len);
     564                 :          0 :                 return -1;
     565                 :            :         }
     566                 :          6 :         gtk_len = gtk_elem_len - 19;
     567         [ -  + ]:          6 :         if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 11, gtk)) {
     568                 :          0 :                 wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
     569                 :            :                            "decrypt GTK");
     570                 :          0 :                 return -1;
     571                 :            :         }
     572                 :            : 
     573                 :          6 :         keylen = wpa_cipher_key_len(sm->group_cipher);
     574                 :          6 :         rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
     575                 :          6 :         alg = wpa_cipher_to_alg(sm->group_cipher);
     576         [ -  + ]:          6 :         if (alg == WPA_ALG_NONE) {
     577                 :          0 :                 wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d",
     578                 :            :                            sm->group_cipher);
     579                 :          0 :                 return -1;
     580                 :            :         }
     581                 :            : 
     582         [ -  + ]:          6 :         if (gtk_len < keylen) {
     583                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE");
     584                 :          0 :                 return -1;
     585                 :            :         }
     586                 :            : 
     587                 :            :         /* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */
     588                 :            : 
     589                 :          6 :         keyidx = WPA_GET_LE16(gtk_elem) & 0x03;
     590                 :            : 
     591         [ -  + ]:          6 :         if (gtk_elem[2] != keylen) {
     592                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d "
     593                 :            :                            "negotiated %lu",
     594                 :          0 :                            gtk_elem[2], (unsigned long) keylen);
     595                 :          0 :                 return -1;
     596                 :            :         }
     597                 :            : 
     598                 :          6 :         wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
     599         [ +  + ]:          6 :         if (sm->group_cipher == WPA_CIPHER_TKIP) {
     600                 :            :                 /* Swap Tx/Rx keys for Michael MIC */
     601                 :            :                 u8 tmp[8];
     602                 :          2 :                 os_memcpy(tmp, gtk + 16, 8);
     603                 :          2 :                 os_memcpy(gtk + 16, gtk + 24, 8);
     604                 :          2 :                 os_memcpy(gtk + 24, tmp, 8);
     605                 :            :         }
     606         [ -  + ]:          6 :         if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0,
     607                 :            :                            gtk_elem + 3, rsc_len, gtk, keylen) < 0) {
     608                 :          0 :                 wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
     609                 :            :                            "driver.");
     610                 :          0 :                 return -1;
     611                 :            :         }
     612                 :            : 
     613                 :          6 :         return 0;
     614                 :            : }
     615                 :            : 
     616                 :            : 
     617                 :            : #ifdef CONFIG_IEEE80211W
     618                 :          6 : static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
     619                 :            :                                        size_t igtk_elem_len)
     620                 :            : {
     621                 :            :         u8 igtk[WPA_IGTK_LEN];
     622                 :            :         u16 keyidx;
     623                 :            : 
     624         [ +  + ]:          6 :         if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC)
     625                 :          4 :                 return 0;
     626                 :            : 
     627         [ -  + ]:          2 :         if (igtk_elem == NULL) {
     628                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: No IGTK included in FTIE");
     629                 :          0 :                 return 0;
     630                 :            :         }
     631                 :            : 
     632                 :          2 :         wpa_hexdump_key(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp",
     633                 :            :                         igtk_elem, igtk_elem_len);
     634                 :            : 
     635         [ -  + ]:          2 :         if (igtk_elem_len != 2 + 6 + 1 + WPA_IGTK_LEN + 8) {
     636                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem "
     637                 :            :                            "length %lu", (unsigned long) igtk_elem_len);
     638                 :          0 :                 return -1;
     639                 :            :         }
     640         [ -  + ]:          2 :         if (igtk_elem[8] != WPA_IGTK_LEN) {
     641                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length "
     642                 :          0 :                            "%d", igtk_elem[8]);
     643                 :          0 :                 return -1;
     644                 :            :         }
     645                 :            : 
     646         [ -  + ]:          2 :         if (aes_unwrap(sm->ptk.kek, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) {
     647                 :          0 :                 wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
     648                 :            :                            "decrypt IGTK");
     649                 :          0 :                 return -1;
     650                 :            :         }
     651                 :            : 
     652                 :            :         /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */
     653                 :            : 
     654                 :          2 :         keyidx = WPA_GET_LE16(igtk_elem);
     655                 :            : 
     656                 :          2 :         wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk,
     657                 :            :                         WPA_IGTK_LEN);
     658         [ -  + ]:          2 :         if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, keyidx, 0,
     659                 :            :                            igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < 0) {
     660                 :          0 :                 wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
     661                 :            :                            "driver.");
     662                 :          0 :                 return -1;
     663                 :            :         }
     664                 :            : 
     665                 :          6 :         return 0;
     666                 :            : }
     667                 :            : #endif /* CONFIG_IEEE80211W */
     668                 :            : 
     669                 :            : 
     670                 :          6 : int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
     671                 :            :                                  size_t ies_len, const u8 *src_addr)
     672                 :            : {
     673                 :            :         struct wpa_ft_ies parse;
     674                 :            :         struct rsn_mdie *mdie;
     675                 :            :         struct rsn_ftie *ftie;
     676                 :            :         unsigned int count;
     677                 :            :         u8 mic[16];
     678                 :            : 
     679                 :          6 :         wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
     680                 :            : 
     681 [ +  - ][ -  + ]:          6 :         if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
     682                 :          6 :             sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) {
     683                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
     684                 :            :                            "enabled for this connection");
     685                 :          0 :                 return -1;
     686                 :            :         }
     687                 :            : 
     688         [ -  + ]:          6 :         if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
     689                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
     690                 :          0 :                 return -1;
     691                 :            :         }
     692                 :            : 
     693                 :          6 :         mdie = (struct rsn_mdie *) parse.mdie;
     694 [ +  - ][ +  - ]:          6 :         if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
                 [ -  + ]
     695                 :          6 :             os_memcmp(mdie->mobility_domain, sm->mobility_domain,
     696                 :            :                       MOBILITY_DOMAIN_ID_LEN) != 0) {
     697                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
     698                 :          0 :                 return -1;
     699                 :            :         }
     700                 :            : 
     701                 :          6 :         ftie = (struct rsn_ftie *) parse.ftie;
     702 [ +  - ][ -  + ]:          6 :         if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
     703                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
     704                 :          0 :                 return -1;
     705                 :            :         }
     706                 :            : 
     707         [ -  + ]:          6 :         if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
     708                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
     709                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
     710                 :          0 :                             ftie->snonce, WPA_NONCE_LEN);
     711                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
     712                 :          0 :                             sm->snonce, WPA_NONCE_LEN);
     713                 :          0 :                 return -1;
     714                 :            :         }
     715                 :            : 
     716         [ -  + ]:          6 :         if (os_memcmp(ftie->anonce, sm->anonce, WPA_NONCE_LEN) != 0) {
     717                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
     718                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
     719                 :          0 :                             ftie->anonce, WPA_NONCE_LEN);
     720                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
     721                 :          0 :                             sm->anonce, WPA_NONCE_LEN);
     722                 :          0 :                 return -1;
     723                 :            :         }
     724                 :            : 
     725         [ -  + ]:          6 :         if (parse.r0kh_id == NULL) {
     726                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
     727                 :          0 :                 return -1;
     728                 :            :         }
     729                 :            : 
     730 [ +  - ][ -  + ]:          6 :         if (parse.r0kh_id_len != sm->r0kh_id_len ||
     731                 :          6 :             os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
     732                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
     733                 :            :                            "the current R0KH-ID");
     734                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
     735                 :          0 :                             parse.r0kh_id, parse.r0kh_id_len);
     736                 :          0 :                 wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
     737                 :          0 :                             sm->r0kh_id, sm->r0kh_id_len);
     738                 :          0 :                 return -1;
     739                 :            :         }
     740                 :            : 
     741         [ -  + ]:          6 :         if (parse.r1kh_id == NULL) {
     742                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
     743                 :          0 :                 return -1;
     744                 :            :         }
     745                 :            : 
     746         [ -  + ]:          6 :         if (os_memcmp(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
     747                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
     748                 :            :                            "ReassocResp");
     749                 :          0 :                 return -1;
     750                 :            :         }
     751                 :            : 
     752 [ +  - ][ -  + ]:          6 :         if (parse.rsn_pmkid == NULL ||
     753                 :          6 :             os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) {
     754                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
     755                 :          0 :                            "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
     756                 :          0 :                 return -1;
     757                 :            :         }
     758                 :            : 
     759                 :          6 :         count = 3;
     760         [ -  + ]:          6 :         if (parse.ric)
     761                 :          0 :                 count += ieee802_11_ie_count(parse.ric, parse.ric_len);
     762         [ -  + ]:          6 :         if (ftie->mic_control[1] != count) {
     763                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
     764                 :            :                            "Control: received %u expected %u",
     765                 :          0 :                            ftie->mic_control[1], count);
     766                 :          0 :                 return -1;
     767                 :            :         }
     768                 :            : 
     769         [ -  + ]:          6 :         if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, src_addr, 6,
     770                 :         12 :                        parse.mdie - 2, parse.mdie_len + 2,
     771                 :         12 :                        parse.ftie - 2, parse.ftie_len + 2,
     772                 :         12 :                        parse.rsn - 2, parse.rsn_len + 2,
     773                 :            :                        parse.ric, parse.ric_len,
     774                 :            :                        mic) < 0) {
     775                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
     776                 :          0 :                 return -1;
     777                 :            :         }
     778                 :            : 
     779         [ -  + ]:          6 :         if (os_memcmp(mic, ftie->mic, 16) != 0) {
     780                 :          0 :                 wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
     781                 :          0 :                 wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
     782                 :          0 :                 wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
     783                 :          0 :                 return -1;
     784                 :            :         }
     785                 :            : 
     786         [ -  + ]:          6 :         if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0)
     787                 :          0 :                 return -1;
     788                 :            : 
     789                 :            : #ifdef CONFIG_IEEE80211W
     790         [ -  + ]:          6 :         if (wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0)
     791                 :          0 :                 return -1;
     792                 :            : #endif /* CONFIG_IEEE80211W */
     793                 :            : 
     794         [ +  - ]:          6 :         if (sm->set_ptk_after_assoc) {
     795                 :          6 :                 wpa_printf(MSG_DEBUG, "FT: Try to set PTK again now that we "
     796                 :            :                            "are associated");
     797         [ -  + ]:          6 :                 if (wpa_ft_install_ptk(sm, src_addr) < 0)
     798                 :          0 :                         return -1;
     799                 :          6 :                 sm->set_ptk_after_assoc = 0;
     800                 :            :         }
     801                 :            : 
     802         [ -  + ]:          6 :         if (parse.ric) {
     803                 :          0 :                 wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
     804                 :          0 :                             parse.ric, parse.ric_len);
     805                 :            :                 /* TODO: parse response and inform driver about results when
     806                 :            :                  * using wpa_supplicant SME */
     807                 :            :         }
     808                 :            : 
     809                 :          6 :         wpa_printf(MSG_DEBUG, "FT: Completed successfully");
     810                 :            : 
     811                 :          6 :         return 0;
     812                 :            : }
     813                 :            : 
     814                 :            : 
     815                 :            : /**
     816                 :            :  * wpa_ft_start_over_ds - Generate over-the-DS auth request
     817                 :            :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     818                 :            :  * @target_ap: Target AP Address
     819                 :            :  * @mdie: Mobility Domain IE from the target AP
     820                 :            :  * Returns: 0 on success, -1 on failure
     821                 :            :  */
     822                 :          0 : int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
     823                 :            :                          const u8 *mdie)
     824                 :            : {
     825                 :            :         u8 *ft_ies;
     826                 :            :         size_t ft_ies_len;
     827                 :            : 
     828                 :          0 :         wpa_printf(MSG_DEBUG, "FT: Request over-the-DS with " MACSTR,
     829                 :          0 :                    MAC2STR(target_ap));
     830                 :            : 
     831                 :            :         /* Generate a new SNonce */
     832         [ #  # ]:          0 :         if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
     833                 :          0 :                 wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
     834                 :          0 :                 return -1;
     835                 :            :         }
     836                 :            : 
     837                 :          0 :         ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
     838                 :            :                                     NULL, target_ap, NULL, 0, mdie);
     839         [ #  # ]:          0 :         if (ft_ies) {
     840                 :          0 :                 sm->over_the_ds_in_progress = 1;
     841                 :          0 :                 os_memcpy(sm->target_ap, target_ap, ETH_ALEN);
     842                 :          0 :                 wpa_sm_send_ft_action(sm, 1, target_ap, ft_ies, ft_ies_len);
     843                 :          0 :                 os_free(ft_ies);
     844                 :            :         }
     845                 :            : 
     846                 :          0 :         return 0;
     847                 :            : }
     848                 :            : 
     849                 :            : #endif /* CONFIG_IEEE80211R */

Generated by: LCOV version 1.9