Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[mech_eap.git] / libeap / src / rsn_supp / wpa_ft.c
index 23063bc..205793e 100644 (file)
@@ -1,57 +1,25 @@
 /*
  * WPA Supplicant - IEEE 802.11r - Fast BSS Transition
- * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 
 #include "includes.h"
 
 #include "common.h"
 #include "crypto/aes_wrap.h"
+#include "crypto/random.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "wpa.h"
 #include "wpa_i.h"
-#include "wpa_ie.h"
 
 #ifdef CONFIG_IEEE80211R
 
-struct wpa_ft_ies {
-       const u8 *mdie;
-       size_t mdie_len;
-       const u8 *ftie;
-       size_t ftie_len;
-       const u8 *r1kh_id;
-       const u8 *gtk;
-       size_t gtk_len;
-       const u8 *r0kh_id;
-       size_t r0kh_id_len;
-       const u8 *rsn;
-       size_t rsn_len;
-       const u8 *rsn_pmkid;
-       const u8 *tie;
-       size_t tie_len;
-       const u8 *igtk;
-       size_t igtk_len;
-       const u8 *ric;
-       size_t ric_len;
-};
-
-static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
-                           struct wpa_ft_ies *parse);
-
-
 int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
-                     const struct wpa_eapol_key *key,
-                     struct wpa_ptk *ptk, size_t ptk_len)
+                     const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
 {
        u8 ptk_name[WPA_PMK_NAME_LEN];
        const u8 *anonce = key->key_nonce;
@@ -74,13 +42,9 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
        wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
        wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
                    WPA_PMK_NAME_LEN);
-       wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
-                         sm->bssid, sm->pmk_r1_name,
-                         (u8 *) ptk, ptk_len, ptk_name);
-       wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len);
-       wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
-
-       return 0;
+       return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
+                                sm->bssid, sm->pmk_r1_name, ptk, ptk_name,
+                                sm->key_mgmt, sm->pairwise_cipher);
 }
 
 
@@ -165,6 +129,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
  * @anonce: ANonce or %NULL if not yet available
  * @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List
  * @kck: 128-bit KCK for MIC or %NULL if no MIC is used
+ * @kck_len: KCK length in octets
  * @target_ap: Target AP address
  * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL
  * @ric_ies_len: Length of ric_ies buffer in octets
@@ -175,7 +140,8 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
  */
 static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
                               const u8 *anonce, const u8 *pmk_name,
-                              const u8 *kck, const u8 *target_ap,
+                              const u8 *kck, size_t kck_len,
+                              const u8 *target_ap,
                               const u8 *ric_ies, size_t ric_ies_len,
                               const u8 *ap_mdie)
 {
@@ -202,16 +168,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
        pos = (u8 *) (rsnie + 1);
 
        /* Group Suite Selector */
-       if (sm->group_cipher == WPA_CIPHER_CCMP)
-               RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
-       else if (sm->group_cipher == WPA_CIPHER_TKIP)
-               RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
-       else {
+       if (!wpa_cipher_valid_group(sm->group_cipher)) {
                wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)",
                           sm->group_cipher);
                os_free(buf);
                return NULL;
        }
+       RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
+                                                 sm->group_cipher));
        pos += RSN_SELECTOR_LEN;
 
        /* Pairwise Suite Count */
@@ -219,16 +183,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
        pos += 2;
 
        /* Pairwise Suite List */
-       if (sm->pairwise_cipher == WPA_CIPHER_CCMP)
-               RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
-       else if (sm->pairwise_cipher == WPA_CIPHER_TKIP)
-               RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
-       else {
+       if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
                wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)",
                           sm->pairwise_cipher);
                os_free(buf);
                return NULL;
        }
+       RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
+                                                 sm->pairwise_cipher));
        pos += RSN_SELECTOR_LEN;
 
        /* Authenticated Key Management Suite Count */
@@ -240,6 +202,8 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
                RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
        else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK)
                RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
+       else if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE)
+               RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
        else {
                wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)",
                           sm->key_mgmt);
@@ -329,7 +293,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
                /* Information element count */
                ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies,
                                                               ric_ies_len);
-               if (wpa_ft_mic(kck, sm->own_addr, target_ap, 5,
+               if (wpa_ft_mic(kck, kck_len, sm->own_addr, target_ap, 5,
                               ((u8 *) mdie) - 2, 2 + sizeof(*mdie),
                               ftie_pos, 2 + *ftie_len,
                               (u8 *) rsnie, 2 + rsnie->len, ric_ies,
@@ -346,155 +310,6 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
 }
 
 
-static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
-                            struct wpa_ft_ies *parse)
-{
-       const u8 *end, *pos;
-
-       parse->ftie = ie;
-       parse->ftie_len = ie_len;
-
-       pos = ie + sizeof(struct rsn_ftie);
-       end = ie + ie_len;
-
-       while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
-               switch (pos[0]) {
-               case FTIE_SUBELEM_R1KH_ID:
-                       if (pos[1] != FT_R1KH_ID_LEN) {
-                               wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
-                                          "length in FTIE: %d", pos[1]);
-                               return -1;
-                       }
-                       parse->r1kh_id = pos + 2;
-                       break;
-               case FTIE_SUBELEM_GTK:
-                       parse->gtk = pos + 2;
-                       parse->gtk_len = pos[1];
-                       break;
-               case FTIE_SUBELEM_R0KH_ID:
-                       if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
-                               wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
-                                          "length in FTIE: %d", pos[1]);
-                               return -1;
-                       }
-                       parse->r0kh_id = pos + 2;
-                       parse->r0kh_id_len = pos[1];
-                       break;
-#ifdef CONFIG_IEEE80211W
-               case FTIE_SUBELEM_IGTK:
-                       parse->igtk = pos + 2;
-                       parse->igtk_len = pos[1];
-                       break;
-#endif /* CONFIG_IEEE80211W */
-               }
-
-               pos += 2 + pos[1];
-       }
-
-       return 0;
-}
-
-
-static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
-                           struct wpa_ft_ies *parse)
-{
-       const u8 *end, *pos;
-       struct wpa_ie_data data;
-       int ret;
-       const struct rsn_ftie *ftie;
-       int prot_ie_count = 0;
-
-       os_memset(parse, 0, sizeof(*parse));
-       if (ies == NULL)
-               return 0;
-
-       pos = ies;
-       end = ies + ies_len;
-       while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
-               switch (pos[0]) {
-               case WLAN_EID_RSN:
-                       parse->rsn = pos + 2;
-                       parse->rsn_len = pos[1];
-                       ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
-                                                  parse->rsn_len + 2,
-                                                  &data);
-                       if (ret < 0) {
-                               wpa_printf(MSG_DEBUG, "FT: Failed to parse "
-                                          "RSN IE: %d", ret);
-                               return -1;
-                       }
-                       if (data.num_pmkid == 1 && data.pmkid)
-                               parse->rsn_pmkid = data.pmkid;
-                       break;
-               case WLAN_EID_MOBILITY_DOMAIN:
-                       parse->mdie = pos + 2;
-                       parse->mdie_len = pos[1];
-                       break;
-               case WLAN_EID_FAST_BSS_TRANSITION:
-                       if (pos[1] < sizeof(*ftie))
-                               return -1;
-                       ftie = (const struct rsn_ftie *) (pos + 2);
-                       prot_ie_count = ftie->mic_control[1];
-                       if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
-                               return -1;
-                       break;
-               case WLAN_EID_TIMEOUT_INTERVAL:
-                       parse->tie = pos + 2;
-                       parse->tie_len = pos[1];
-                       break;
-               case WLAN_EID_RIC_DATA:
-                       if (parse->ric == NULL)
-                               parse->ric = pos;
-               }
-
-               pos += 2 + pos[1];
-       }
-
-       if (prot_ie_count == 0)
-               return 0; /* no MIC */
-
-       /*
-        * Check that the protected IE count matches with IEs included in the
-        * frame.
-        */
-       if (parse->rsn)
-               prot_ie_count--;
-       if (parse->mdie)
-               prot_ie_count--;
-       if (parse->ftie)
-               prot_ie_count--;
-       if (parse->tie)
-               prot_ie_count--;
-       if (prot_ie_count < 0) {
-               wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
-                          "the protected IE count");
-               return -1;
-       }
-
-       if (prot_ie_count == 0 && parse->ric) {
-               wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
-                          "included in protected IE count");
-               return -1;
-       }
-
-       /* Determine the end of the RIC IE(s) */
-       pos = parse->ric;
-       while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
-              prot_ie_count) {
-               prot_ie_count--;
-               pos += 2 + pos[1];
-       }
-       parse->ric_len = pos - parse->ric;
-       if (prot_ie_count) {
-               wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
-                          "frame", (int) prot_ie_count);
-               return -1;
-       }
-
-       return 0;
-}
-
-
 static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
 {
        int keylen;
@@ -503,23 +318,17 @@ static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
 
        wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver.");
 
-       switch (sm->pairwise_cipher) {
-       case WPA_CIPHER_CCMP:
-               alg = WPA_ALG_CCMP;
-               keylen = 16;
-               break;
-       case WPA_CIPHER_TKIP:
-               alg = WPA_ALG_TKIP;
-               keylen = 32;
-               break;
-       default:
+       if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
                wpa_printf(MSG_WARNING, "FT: Unsupported pairwise cipher %d",
                           sm->pairwise_cipher);
                return -1;
        }
 
+       alg = wpa_cipher_to_alg(sm->pairwise_cipher);
+       keylen = wpa_cipher_key_len(sm->pairwise_cipher);
+
        if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc,
-                          sizeof(null_rsc), (u8 *) sm->ptk.tk1, keylen) < 0) {
+                          sizeof(null_rsc), (u8 *) sm->ptk.tk, keylen) < 0) {
                wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver");
                return -1;
        }
@@ -540,13 +349,13 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie)
        size_t ft_ies_len;
 
        /* Generate a new SNonce */
-       if (os_get_random(sm->snonce, WPA_NONCE_LEN)) {
+       if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
                wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
                return -1;
        }
 
        ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
-                                   NULL, sm->bssid, NULL, 0, mdie);
+                                   NULL, 0, sm->bssid, NULL, 0, mdie);
        if (ft_ies) {
                wpa_sm_update_ft_ies(sm, sm->mobility_domain,
                                     ft_ies, ft_ies_len);
@@ -562,7 +371,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
                            const u8 *ric_ies, size_t ric_ies_len)
 {
        u8 *ft_ies;
-       size_t ft_ies_len, ptk_len;
+       size_t ft_ies_len;
        struct wpa_ft_ies parse;
        struct rsn_mdie *mdie;
        struct rsn_ftie *ftie;
@@ -588,8 +397,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
                }
        }
 
-       if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
-           sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) {
+       if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
                wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
                           "enabled for this connection");
                return -1;
@@ -629,7 +437,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
        }
 
        if (parse.r0kh_id_len != sm->r0kh_id_len ||
-           os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
+           os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
+       {
                wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
                           "the current R0KH-ID");
                wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
@@ -645,7 +454,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
        }
 
        if (parse.rsn_pmkid == NULL ||
-           os_memcmp(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN)) {
+           os_memcmp_const(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN))
+       {
                wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name (PMKID) in "
                           "RSNIE");
                return -1;
@@ -663,16 +473,14 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
                    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
 
        bssid = target_ap;
-       ptk_len = sm->pairwise_cipher == WPA_CIPHER_CCMP ? 48 : 64;
-       wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, sm->own_addr,
-                         bssid, sm->pmk_r1_name,
-                         (u8 *) &sm->ptk, ptk_len, ptk_name);
-       wpa_hexdump_key(MSG_DEBUG, "FT: PTK",
-                       (u8 *) &sm->ptk, ptk_len);
-       wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
+       if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce,
+                             sm->own_addr, bssid, sm->pmk_r1_name, &sm->ptk,
+                             ptk_name, sm->key_mgmt, sm->pairwise_cipher) < 0)
+               return -1;
 
        ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
-                                   sm->pmk_r1_name, sm->ptk.kck, bssid,
+                                   sm->pmk_r1_name,
+                                   sm->ptk.kck, sm->ptk.kck_len, bssid,
                                    ric_ies, ric_ies_len,
                                    parse.mdie ? parse.mdie - 2 : NULL);
        if (ft_ies) {
@@ -714,14 +522,20 @@ int wpa_ft_is_completed(struct wpa_sm *sm)
        if (sm == NULL)
                return 0;
 
-       if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
-           sm->key_mgmt != WPA_KEY_MGMT_FT_PSK)
+       if (!wpa_key_mgmt_ft(sm->key_mgmt))
                return 0;
 
        return sm->ft_completed;
 }
 
 
+void wpa_reset_ft_completed(struct wpa_sm *sm)
+{
+       if (sm != NULL)
+               sm->ft_completed = 0;
+}
+
+
 static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
                                      size_t gtk_elem_len)
 {
@@ -745,34 +559,17 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
                return -1;
        }
        gtk_len = gtk_elem_len - 19;
-       if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 11, gtk)) {
+       if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, gtk_len / 8, gtk_elem + 11,
+                      gtk)) {
                wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
                           "decrypt GTK");
                return -1;
        }
 
-       switch (sm->group_cipher) {
-       case WPA_CIPHER_CCMP:
-               keylen = 16;
-               rsc_len = 6;
-               alg = WPA_ALG_CCMP;
-               break;
-       case WPA_CIPHER_TKIP:
-               keylen = 32;
-               rsc_len = 6;
-               alg = WPA_ALG_TKIP;
-               break;
-       case WPA_CIPHER_WEP104:
-               keylen = 13;
-               rsc_len = 0;
-               alg = WPA_ALG_WEP;
-               break;
-       case WPA_CIPHER_WEP40:
-               keylen = 5;
-               rsc_len = 0;
-               alg = WPA_ALG_WEP;
-               break;
-       default:
+       keylen = wpa_cipher_key_len(sm->group_cipher);
+       rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
+       alg = wpa_cipher_to_alg(sm->group_cipher);
+       if (alg == WPA_ALG_NONE) {
                wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d",
                           sm->group_cipher);
                return -1;
@@ -795,9 +592,15 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
        }
 
        wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
-       if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff",
-                          keyidx, 0, gtk_elem + 3, rsc_len, gtk, keylen) <
-           0) {
+       if (sm->group_cipher == WPA_CIPHER_TKIP) {
+               /* Swap Tx/Rx keys for Michael MIC */
+               u8 tmp[8];
+               os_memcpy(tmp, gtk + 16, 8);
+               os_memcpy(gtk + 16, gtk + 24, 8);
+               os_memcpy(gtk + 24, tmp, 8);
+       }
+       if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0,
+                          gtk_elem + 3, rsc_len, gtk, keylen) < 0) {
                wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
                           "driver.");
                return -1;
@@ -836,7 +639,8 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
                return -1;
        }
 
-       if (aes_unwrap(sm->ptk.kek, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) {
+       if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, WPA_IGTK_LEN / 8,
+                      igtk_elem + 9, igtk)) {
                wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
                           "decrypt IGTK");
                return -1;
@@ -848,9 +652,8 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
 
        wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk,
                        WPA_IGTK_LEN);
-       if (wpa_sm_set_key(sm, WPA_ALG_IGTK, (u8 *) "\xff\xff\xff\xff\xff\xff",
-                          keyidx, 0, igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) <
-           0) {
+       if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, keyidx, 0,
+                          igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < 0) {
                wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
                           "driver.");
                return -1;
@@ -868,12 +671,11 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
        struct rsn_mdie *mdie;
        struct rsn_ftie *ftie;
        unsigned int count;
-       u8 mic[16];
+       u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
 
        wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
 
-       if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
-           sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) {
+       if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
                wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
                           "enabled for this connection");
                return -1;
@@ -922,7 +724,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
        }
 
        if (parse.r0kh_id_len != sm->r0kh_id_len ||
-           os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
+           os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
+       {
                wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
                           "the current R0KH-ID");
                wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
@@ -937,22 +740,23 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
                return -1;
        }
 
-       if (os_memcmp(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
+       if (os_memcmp_const(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
                wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
                           "ReassocResp");
                return -1;
        }
 
        if (parse.rsn_pmkid == NULL ||
-           os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) {
+           os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN))
+       {
                wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
                           "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
                return -1;
        }
 
        count = 3;
-       if (parse.tie)
-               count++;
+       if (parse.ric)
+               count += ieee802_11_ie_count(parse.ric, parse.ric_len);
        if (ftie->mic_control[1] != count) {
                wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
                           "Control: received %u expected %u",
@@ -960,7 +764,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
                return -1;
        }
 
-       if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, src_addr, 6,
+       if (wpa_ft_mic(sm->ptk.kck, sm->ptk.kck_len, sm->own_addr, src_addr, 6,
                       parse.mdie - 2, parse.mdie_len + 2,
                       parse.ftie - 2, parse.ftie_len + 2,
                       parse.rsn - 2, parse.rsn_len + 2,
@@ -970,7 +774,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
                return -1;
        }
 
-       if (os_memcmp(mic, ftie->mic, 16) != 0) {
+       if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
                wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
                wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
                wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
@@ -996,9 +800,12 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
        if (parse.ric) {
                wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
                            parse.ric, parse.ric_len);
-               /* TODO: parse response and inform driver about results */
+               /* TODO: parse response and inform driver about results when
+                * using wpa_supplicant SME */
        }
 
+       wpa_printf(MSG_DEBUG, "FT: Completed successfully");
+
        return 0;
 }
 
@@ -1020,13 +827,13 @@ int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
                   MAC2STR(target_ap));
 
        /* Generate a new SNonce */
-       if (os_get_random(sm->snonce, WPA_NONCE_LEN)) {
+       if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
                wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
                return -1;
        }
 
        ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
-                                   NULL, target_ap, NULL, 0, mdie);
+                                   NULL, 0, target_ap, NULL, 0, mdie);
        if (ft_ies) {
                sm->over_the_ds_in_progress = 1;
                os_memcpy(sm->target_ap, target_ap, ETH_ALEN);