]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Add support for FILS shared key offload
authorVidyullatha Kanchanapally <vkanchan@qti.qualcomm.com>
Wed, 22 Mar 2017 10:40:05 +0000 (16:10 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 7 Apr 2017 13:21:55 +0000 (16:21 +0300)
Add support for FILS shared key offload for drivers which advertize
FILS shared key support using NL80211_CMD_CONNECT.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/drivers/driver.h
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211_capa.c
src/drivers/driver_nl80211_event.c

index fc2593e3e686a11967d41041770e97b99c5d23f0..999b6a63e20d030db74b09defb473aa4d0aca62f 100644 (file)
@@ -1011,6 +1011,43 @@ struct wpa_driver_associate_params {
         * fils_nonces_len: Length of fils_nonce in bytes
         */
        size_t fils_nonces_len;
+
+       /**
+        * fils_erp_username - Username part of keyName-NAI
+        */
+       const u8 *fils_erp_username;
+
+       /**
+        * fils_erp_username_len - Length of fils_erp_username in bytes
+        */
+       size_t fils_erp_username_len;
+
+       /**
+        * fils_erp_realm - Realm/domain name to use in FILS ERP
+        */
+       const u8 *fils_erp_realm;
+
+       /**
+        * fils_erp_realm_len - Length of fils_erp_realm in bytes
+        */
+       size_t fils_erp_realm_len;
+
+       /**
+        * fils_erp_next_seq_num - The next sequence number to use in FILS ERP
+        * messages
+        */
+       u16 fils_erp_next_seq_num;
+
+       /**
+        * fils_erp_rrk - Re-authentication root key (rRK) for the keyName-NAI
+        * specified by fils_erp_username@fils_erp_realm.
+        */
+       const u8 *fils_erp_rrk;
+
+       /**
+        * fils_erp_rrk_len - Length of fils_erp_rrk in bytes
+        */
+       size_t fils_erp_rrk_len;
 };
 
 enum hide_ssid {
@@ -1469,6 +1506,8 @@ struct wpa_driver_capa {
 #define WPA_DRIVER_FLAGS_SCHED_SCAN_RELATIVE_RSSI      0x0001000000000000ULL
 /** Driver supports HE capabilities */
 #define WPA_DRIVER_FLAGS_HE_CAPABILITIES       0x0002000000000000ULL
+/** Driver supports FILS shared key offload */
+#define WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD       0x0004000000000000ULL
        u64 flags;
 
 #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
@@ -4528,6 +4567,8 @@ union wpa_event_data {
 
                /**
                 * ptk_kek - The derived PTK KEK
+                * This is used in key management offload and also in FILS SK
+                * offload.
                 */
                const u8 *ptk_kek;
 
@@ -4541,6 +4582,36 @@ union wpa_event_data {
                 * 0 = unknown, 1 = unchanged, 2 = changed
                 */
                u8 subnet_status;
+
+               /**
+                * The following information is used in FILS SK offload
+                * @fils_erp_next_seq_num
+                * @fils_pmk
+                * @fils_pmk_len
+                * @fils_pmkid
+                */
+
+               /**
+                * fils_erp_next_seq_num - The next sequence number to use in
+                * FILS ERP messages
+                */
+               u16 fils_erp_next_seq_num;
+
+               /**
+                * fils_pmk - A new PMK if generated in case of FILS
+                * authentication
+                */
+               const u8 *fils_pmk;
+
+               /**
+                * fils_pmk_len - Length of fils_pmk
+                */
+               size_t fils_pmk_len;
+
+               /**
+                * fils_pmkid - PMKID used or generated in FILS authentication
+                */
+               const u8 *fils_pmkid;
        } assoc_info;
 
        /**
@@ -4756,6 +4827,12 @@ union wpa_event_data {
                 * timeout_reason - Reason for the timeout
                 */
                const char *timeout_reason;
+
+               /**
+                * fils_erp_next_seq_num - The next sequence number to use in
+                * FILS ERP messages
+                */
+               u16 fils_erp_next_seq_num;
        } assoc_reject;
 
        struct timeout_event {
index bceeba2b23ea462eb3a63bcdd3c45313b7f199df..8671e737492f12b9fde6cbb86eae226fd60959e0 100644 (file)
@@ -5067,6 +5067,47 @@ fail:
 }
 
 
+static int nl80211_put_fils_connect_params(struct wpa_driver_nl80211_data *drv,
+                                          struct wpa_driver_associate_params *params,
+                                          struct nl_msg *msg)
+{
+       if (params->fils_erp_username_len) {
+               wpa_hexdump_ascii(MSG_DEBUG, "  * FILS ERP EMSKname/username",
+                                 params->fils_erp_username,
+                                 params->fils_erp_username_len);
+               if (nla_put(msg, NL80211_ATTR_FILS_ERP_USERNAME,
+                           params->fils_erp_username_len,
+                           params->fils_erp_username))
+                       return -1;
+       }
+
+       if (params->fils_erp_realm_len) {
+               wpa_hexdump_ascii(MSG_DEBUG, "  * FILS ERP Realm",
+                                 params->fils_erp_realm,
+                                 params->fils_erp_realm_len);
+               if (nla_put(msg, NL80211_ATTR_FILS_ERP_REALM,
+                           params->fils_erp_realm_len, params->fils_erp_realm))
+                       return -1;
+       }
+
+       wpa_printf(MSG_DEBUG, "  * FILS ERP next seq %u",
+                  params->fils_erp_next_seq_num);
+       if (nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
+                       params->fils_erp_next_seq_num))
+               return -1;
+
+       if (params->fils_erp_rrk_len) {
+               wpa_printf(MSG_DEBUG, "  * FILS ERP rRK (len=%lu)",
+                          (unsigned long) params->fils_erp_rrk_len);
+               if (nla_put(msg, NL80211_ATTR_FILS_ERP_RRK,
+                           params->fils_erp_rrk_len, params->fils_erp_rrk))
+                       return -1;
+       }
+
+       return 0;
+}
+
+
 static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
                                  struct wpa_driver_associate_params *params,
                                  struct nl_msg *msg)
@@ -5174,7 +5215,11 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
            params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
            params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
            params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
-           params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
+           params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
+           params->key_mgmt_suite == WPA_KEY_MGMT_FILS_SHA256 ||
+           params->key_mgmt_suite == WPA_KEY_MGMT_FILS_SHA384 ||
+           params->key_mgmt_suite == WPA_KEY_MGMT_FT_FILS_SHA256 ||
+           params->key_mgmt_suite == WPA_KEY_MGMT_FT_FILS_SHA384) {
                int mgmt = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
 
                switch (params->key_mgmt_suite) {
@@ -5205,6 +5250,18 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
                case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
                        mgmt = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
                        break;
+               case WPA_KEY_MGMT_FILS_SHA256:
+                       mgmt = RSN_AUTH_KEY_MGMT_FILS_SHA256;
+                       break;
+               case WPA_KEY_MGMT_FILS_SHA384:
+                       mgmt = RSN_AUTH_KEY_MGMT_FILS_SHA384;
+                       break;
+               case WPA_KEY_MGMT_FT_FILS_SHA256:
+                       mgmt = RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
+                       break;
+               case WPA_KEY_MGMT_FT_FILS_SHA384:
+                       mgmt = RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
+                       break;
                case WPA_KEY_MGMT_PSK:
                default:
                        mgmt = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
@@ -5262,6 +5319,10 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
                drv->connect_reassoc = 1;
        }
 
+       if ((params->auth_alg & WPA_AUTH_ALG_FILS) &&
+           nl80211_put_fils_connect_params(drv, params, msg) != 0)
+               return -1;
+
        return 0;
 }
 
@@ -5317,6 +5378,8 @@ static int wpa_driver_nl80211_try_connect(
                type = NL80211_AUTHTYPE_NETWORK_EAP;
        else if (params->auth_alg & WPA_AUTH_ALG_FT)
                type = NL80211_AUTHTYPE_FT;
+       else if (params->auth_alg & WPA_AUTH_ALG_FILS)
+               type = NL80211_AUTHTYPE_FILS_SK;
        else
                goto fail;
 
index f67ad21cc55b8ee1b01f2277200eeeaee08dc540..ea7bac1d60a4d248f9cf9f60706b6d67f54674d2 100644 (file)
@@ -398,6 +398,9 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
        if (ext_feature_isset(ext_features, len,
                              NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI))
                capa->flags |= WPA_DRIVER_FLAGS_SCHED_SCAN_RELATIVE_RSSI;
+       if (ext_feature_isset(ext_features, len,
+                             NL80211_EXT_FEATURE_FILS_SK_OFFLOAD))
+               capa->flags |= WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD;
 }
 
 
index f05c5466cbe2eec807f071568127a8ae3d2bed90..f3ed82bf50eba128e9bc6e213dc79f601d59127b 100644 (file)
@@ -284,7 +284,10 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
                               struct nlattr *key_replay_ctr,
                               struct nlattr *ptk_kck,
                               struct nlattr *ptk_kek,
-                              struct nlattr *subnet_status)
+                              struct nlattr *subnet_status,
+                              struct nlattr *fils_erp_next_seq_num,
+                              struct nlattr *fils_pmk,
+                              struct nlattr *fils_pmkid)
 {
        union wpa_event_data event;
        const u8 *ssid = NULL;
@@ -357,6 +360,9 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
                                break;
                        }
                }
+               if (fils_erp_next_seq_num)
+                       event.assoc_reject.fils_erp_next_seq_num =
+                               nla_get_u16(fils_erp_next_seq_num);
                wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
                return;
        }
@@ -430,6 +436,18 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
                event.assoc_info.subnet_status = nla_get_u8(subnet_status);
        }
 
+       if (fils_erp_next_seq_num)
+               event.assoc_info.fils_erp_next_seq_num =
+                       nla_get_u16(fils_erp_next_seq_num);
+
+       if (fils_pmk) {
+               event.assoc_info.fils_pmk = nla_data(fils_pmk);
+               event.assoc_info.fils_pmk_len = nla_len(fils_pmk);
+       }
+
+       if (fils_pmkid)
+               event.assoc_info.fils_pmkid = nla_data(fils_pmkid);
+
        wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
 }
 
@@ -1754,7 +1772,8 @@ static void qca_nl80211_key_mgmt_auth(struct wpa_driver_nl80211_data *drv,
                           tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR],
                           tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK],
                           tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK],
-                          tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS]);
+                          tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS],
+                          NULL, NULL, NULL);
 }
 
 
@@ -2270,7 +2289,12 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
                                   tb[NL80211_ATTR_RESP_IE],
                                   tb[NL80211_ATTR_TIMED_OUT],
                                   tb[NL80211_ATTR_TIMEOUT_REASON],
-                                  NULL, NULL, NULL, NULL, NULL);
+                                  NULL, NULL, NULL,
+                                  tb[NL80211_ATTR_FILS_KEK],
+                                  NULL,
+                                  tb[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM],
+                                  tb[NL80211_ATTR_PMK],
+                                  tb[NL80211_ATTR_PMKID]);
                break;
        case NL80211_CMD_CH_SWITCH_NOTIFY:
                mlme_event_ch_switch(drv,