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 <jouni@qca.qualcomm.com>
This commit is contained in:
Vidyullatha Kanchanapally 2017-03-22 16:10:05 +05:30 committed by Jouni Malinen
parent 199eb3a4e6
commit ad295f3b85
4 changed files with 171 additions and 4 deletions

View 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 {

View 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;

View 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;
}

View 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,