cfg80211: Allow user space to specify non-IEs to SAE Authentication
SAE extends Authentication frames with fields that are not information elements. NL80211_ATTR_IE is not suitable for these, so introduce a new attribute that can be used to specify the fields needed for SAE in station mode. Signed-off-by: Jouni Malinen <j@w1.fi> [change to verify that SAE is only used with authenticate command] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
0f4126e891
commit
e39e5b5e72
|
@ -1152,6 +1152,9 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
|
|||
* @key_len: length of WEP key for shared key authentication
|
||||
* @key_idx: index of WEP key for shared key authentication
|
||||
* @key: WEP key for shared key authentication
|
||||
* @sae_data: Non-IE data to use with SAE or %NULL. This starts with
|
||||
* Authentication transaction sequence number field.
|
||||
* @sae_data_len: Length of sae_data buffer in octets
|
||||
*/
|
||||
struct cfg80211_auth_request {
|
||||
struct cfg80211_bss *bss;
|
||||
|
@ -1160,6 +1163,8 @@ struct cfg80211_auth_request {
|
|||
enum nl80211_auth_type auth_type;
|
||||
const u8 *key;
|
||||
u8 key_len, key_idx;
|
||||
const u8 *sae_data;
|
||||
size_t sae_data_len;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1273,6 +1273,9 @@ enum nl80211_commands {
|
|||
* the connection request from a station. nl80211_connect_failed_reason
|
||||
* enum has different reasons of connection failure.
|
||||
*
|
||||
* @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts
|
||||
* with the Authentication transaction sequence number field.
|
||||
*
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
*/
|
||||
|
@ -1530,6 +1533,8 @@ enum nl80211_attrs {
|
|||
|
||||
NL80211_ATTR_CONN_FAILED_REASON,
|
||||
|
||||
NL80211_ATTR_SAE_DATA,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
@ -2489,6 +2494,7 @@ enum nl80211_bss_status {
|
|||
* @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
|
||||
* @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
|
||||
* @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
|
||||
* @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals
|
||||
* @__NL80211_AUTHTYPE_NUM: internal
|
||||
* @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
|
||||
* @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
|
||||
|
@ -2500,6 +2506,7 @@ enum nl80211_auth_type {
|
|||
NL80211_AUTHTYPE_SHARED_KEY,
|
||||
NL80211_AUTHTYPE_FT,
|
||||
NL80211_AUTHTYPE_NETWORK_EAP,
|
||||
NL80211_AUTHTYPE_SAE,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_AUTHTYPE_NUM,
|
||||
|
@ -3028,6 +3035,9 @@ enum nl80211_ap_sme_features {
|
|||
* in the interface combinations, even when it's only used for scan
|
||||
* and remain-on-channel. This could be due to, for example, the
|
||||
* remain-on-channel implementation requiring a channel context.
|
||||
* @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of
|
||||
* equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station
|
||||
* mode
|
||||
*/
|
||||
enum nl80211_feature_flags {
|
||||
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
|
||||
|
@ -3035,6 +3045,7 @@ enum nl80211_feature_flags {
|
|||
NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
|
||||
NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,
|
||||
NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4,
|
||||
NL80211_FEATURE_SAE = 1 << 5,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -320,13 +320,15 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
|||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
const u8 *ie, int ie_len,
|
||||
const u8 *key, int key_len, int key_idx);
|
||||
const u8 *key, int key_len, int key_idx,
|
||||
const u8 *sae_data, int sae_data_len);
|
||||
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, struct ieee80211_channel *chan,
|
||||
enum nl80211_auth_type auth_type, const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
const u8 *ie, int ie_len,
|
||||
const u8 *key, int key_len, int key_idx);
|
||||
const u8 *key, int key_len, int key_idx,
|
||||
const u8 *sae_data, int sae_data_len);
|
||||
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
|
|
|
@ -273,7 +273,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
|||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
const u8 *ie, int ie_len,
|
||||
const u8 *key, int key_len, int key_idx)
|
||||
const u8 *key, int key_len, int key_idx,
|
||||
const u8 *sae_data, int sae_data_len)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_auth_request req;
|
||||
|
@ -293,6 +294,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
|||
|
||||
req.ie = ie;
|
||||
req.ie_len = ie_len;
|
||||
req.sae_data = sae_data;
|
||||
req.sae_data_len = sae_data_len;
|
||||
req.auth_type = auth_type;
|
||||
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
|
||||
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
|
||||
|
@ -319,7 +322,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
|||
enum nl80211_auth_type auth_type, const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
const u8 *ie, int ie_len,
|
||||
const u8 *key, int key_len, int key_idx)
|
||||
const u8 *key, int key_len, int key_idx,
|
||||
const u8 *sae_data, int sae_data_len)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -327,7 +331,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
|||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
|
||||
ssid, ssid_len, ie, ie_len,
|
||||
key, key_len, key_idx);
|
||||
key, key_len, key_idx,
|
||||
sae_data, sae_data_len);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "nl80211.h"
|
||||
#include "reg.h"
|
||||
|
||||
static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type);
|
||||
static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
|
||||
struct genl_info *info,
|
||||
struct cfg80211_crypto_settings *settings,
|
||||
|
@ -355,6 +354,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
|
|||
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_WDEV] = { .type = NLA_U64 },
|
||||
[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
@ -2490,6 +2490,30 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
|
||||
enum nl80211_auth_type auth_type,
|
||||
enum nl80211_commands cmd)
|
||||
{
|
||||
if (auth_type > NL80211_AUTHTYPE_MAX)
|
||||
return false;
|
||||
|
||||
switch (cmd) {
|
||||
case NL80211_CMD_AUTHENTICATE:
|
||||
if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
|
||||
auth_type == NL80211_AUTHTYPE_SAE)
|
||||
return false;
|
||||
return true;
|
||||
case NL80211_CMD_CONNECT:
|
||||
case NL80211_CMD_START_AP:
|
||||
/* SAE not supported yet */
|
||||
if (auth_type == NL80211_AUTHTYPE_SAE)
|
||||
return false;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
|
@ -2559,7 +2583,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
|
||||
params.auth_type = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_AUTH_TYPE]);
|
||||
if (!nl80211_valid_auth_type(params.auth_type))
|
||||
if (!nl80211_valid_auth_type(rdev, params.auth_type,
|
||||
NL80211_CMD_START_AP))
|
||||
return -EINVAL;
|
||||
} else
|
||||
params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||
|
@ -4852,11 +4877,6 @@ static int nl80211_dump_survey(struct sk_buff *skb,
|
|||
return res;
|
||||
}
|
||||
|
||||
static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type)
|
||||
{
|
||||
return auth_type <= NL80211_AUTHTYPE_MAX;
|
||||
}
|
||||
|
||||
static bool nl80211_valid_wpa_versions(u32 wpa_versions)
|
||||
{
|
||||
return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
|
||||
|
@ -4868,8 +4888,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct ieee80211_channel *chan;
|
||||
const u8 *bssid, *ssid, *ie = NULL;
|
||||
int err, ssid_len, ie_len = 0;
|
||||
const u8 *bssid, *ssid, *ie = NULL, *sae_data = NULL;
|
||||
int err, ssid_len, ie_len = 0, sae_data_len = 0;
|
||||
enum nl80211_auth_type auth_type;
|
||||
struct key_parse key;
|
||||
bool local_state_change;
|
||||
|
@ -4945,9 +4965,23 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
|
||||
auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
|
||||
if (!nl80211_valid_auth_type(auth_type))
|
||||
if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
|
||||
return -EINVAL;
|
||||
|
||||
if (auth_type == NL80211_AUTHTYPE_SAE &&
|
||||
!info->attrs[NL80211_ATTR_SAE_DATA])
|
||||
return -EINVAL;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SAE_DATA]) {
|
||||
if (auth_type != NL80211_AUTHTYPE_SAE)
|
||||
return -EINVAL;
|
||||
sae_data = nla_data(info->attrs[NL80211_ATTR_SAE_DATA]);
|
||||
sae_data_len = nla_len(info->attrs[NL80211_ATTR_SAE_DATA]);
|
||||
/* need to include at least Auth Transaction and Status Code */
|
||||
if (sae_data_len < 4)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
|
||||
|
||||
/*
|
||||
|
@ -4959,7 +4993,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
|
||||
ssid, ssid_len, ie, ie_len,
|
||||
key.p.key, key.p.key_len, key.idx);
|
||||
key.p.key, key.p.key_len, key.idx,
|
||||
sae_data, sae_data_len);
|
||||
}
|
||||
|
||||
static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
|
||||
|
@ -5596,7 +5631,8 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
|
|||
if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
|
||||
connect.auth_type =
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
|
||||
if (!nl80211_valid_auth_type(connect.auth_type))
|
||||
if (!nl80211_valid_auth_type(rdev, connect.auth_type,
|
||||
NL80211_CMD_CONNECT))
|
||||
return -EINVAL;
|
||||
} else
|
||||
connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||
|
|
|
@ -179,7 +179,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
|
|||
params->ssid, params->ssid_len,
|
||||
NULL, 0,
|
||||
params->key, params->key_len,
|
||||
params->key_idx);
|
||||
params->key_idx, NULL, 0);
|
||||
case CFG80211_CONN_ASSOCIATE_NEXT:
|
||||
BUG_ON(!rdev->ops->assoc);
|
||||
wdev->conn->state = CFG80211_CONN_ASSOCIATING;
|
||||
|
|
Loading…
Reference in New Issue