From ad295f3b85756a188d4c18f98f59bfce1a28efeb Mon Sep 17 00:00:00 2001 From: Vidyullatha Kanchanapally Date: Wed, 22 Mar 2017 16:10:05 +0530 Subject: [PATCH] nl80211: Add support for FILS shared key offload Add support for FILS shared key offload for drivers which advertize FILS shared key support using NL80211_CMD_CONNECT. Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 77 ++++++++++++++++++++++++++++++ src/drivers/driver_nl80211.c | 65 ++++++++++++++++++++++++- src/drivers/driver_nl80211_capa.c | 3 ++ src/drivers/driver_nl80211_event.c | 30 ++++++++++-- 4 files changed, 171 insertions(+), 4 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index fc2593e3e..999b6a63e 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -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 { diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index bceeba2b2..8671e7374 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -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; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index f67ad21cc..ea7bac1d6 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -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; } diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index f05c5466c..f3ed82bf5 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -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,