nl80211: Define vendor interface functions to offload PASN authentication
This defines the QCA vendor interface functions to offload PASN authentication from the driver. The driver sends the QCA_NL80211_VENDOR_SUBCMD_PASN event requesting to perform PASN authentication with a list of peers with which the driver needs to do ranging. wpa_supplicant performs PASN handshake with all the peer devices and sets the required keys using the command QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT to the driver. After PASN handshake is completed with all requested peers, wpa_supplicant sends consolidated status for all peers to the driver. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
edd89d6dbb
commit
de3b91a172
4 changed files with 254 additions and 0 deletions
|
@ -31,6 +31,8 @@
|
|||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "common/wpa_common.h"
|
||||
#include "crypto/sha256.h"
|
||||
#include "crypto/sha384.h"
|
||||
#include "netlink.h"
|
||||
#include "linux_defines.h"
|
||||
#include "linux_ioctl.h"
|
||||
|
@ -11957,6 +11959,169 @@ fail:
|
|||
|
||||
#endif /* CONFIG_MBO */
|
||||
|
||||
|
||||
#ifdef CONFIG_PASN
|
||||
|
||||
static int nl80211_send_pasn_resp(void *priv, struct pasn_auth *params)
|
||||
{
|
||||
unsigned int i;
|
||||
struct i802_bss *bss = priv;
|
||||
struct nl_msg *msg = NULL;
|
||||
struct nlattr *nlpeers, *attr, *attr1;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG,
|
||||
"nl80211: PASN authentication response for %d entries",
|
||||
params->num_peers);
|
||||
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
|
||||
if (!msg ||
|
||||
nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
|
||||
QCA_NL80211_VENDOR_SUBCMD_PASN))
|
||||
goto fail;
|
||||
|
||||
attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
|
||||
if (!attr)
|
||||
goto fail;
|
||||
|
||||
nlpeers = nla_nest_start(msg, QCA_WLAN_VENDOR_ATTR_PASN_PEERS);
|
||||
if (!nlpeers)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < params->num_peers; i++) {
|
||||
attr1 = nla_nest_start(msg, i);
|
||||
if (!attr1 ||
|
||||
nla_put(msg, QCA_WLAN_VENDOR_ATTR_PASN_PEER_SRC_ADDR,
|
||||
ETH_ALEN, params->peer[i].own_addr) ||
|
||||
nla_put(msg, QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAC_ADDR,
|
||||
ETH_ALEN, params->peer[i].peer_addr))
|
||||
goto fail;
|
||||
|
||||
if (params->peer[i].status == 0)
|
||||
nla_put_flag(msg,
|
||||
QCA_WLAN_VENDOR_ATTR_PASN_PEER_STATUS_SUCCESS);
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Own address[%u]: " MACSTR
|
||||
" Peer address[%u]: " MACSTR " Status: %s",
|
||||
i, MAC2STR(params->peer[i].own_addr), i,
|
||||
MAC2STR(params->peer[i].peer_addr),
|
||||
params->peer[i].status ? "Fail" : "Success");
|
||||
nla_nest_end(msg, attr1);
|
||||
}
|
||||
|
||||
nla_nest_end(msg, nlpeers);
|
||||
nla_nest_end(msg, attr);
|
||||
|
||||
return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
|
||||
|
||||
fail:
|
||||
nlmsg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static u32 wpa_ltf_keyseed_len_to_sha_type(size_t len)
|
||||
{
|
||||
if (len == SHA384_MAC_LEN)
|
||||
return QCA_WLAN_VENDOR_SHA_384;
|
||||
if (len == SHA256_MAC_LEN)
|
||||
return QCA_WLAN_VENDOR_SHA_256;
|
||||
|
||||
wpa_printf(MSG_ERROR, "nl80211: Unexpected LTF keyseed len %zu", len);
|
||||
return (u32) -1;
|
||||
}
|
||||
|
||||
|
||||
static int nl80211_set_secure_ranging_ctx(void *priv,
|
||||
struct secure_ranging_params *params)
|
||||
{
|
||||
int ret;
|
||||
u32 suite;
|
||||
struct nlattr *attr;
|
||||
struct nl_msg *msg = NULL;
|
||||
struct i802_bss *bss = priv;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
|
||||
/* Configure secure ranging context only to the drivers that support it.
|
||||
*/
|
||||
if (!drv->secure_ranging_ctx_vendor_cmd_avail)
|
||||
return 0;
|
||||
|
||||
if (!params->peer_addr || !params->own_addr)
|
||||
return -1;
|
||||
|
||||
wpa_dbg(drv->ctx, MSG_DEBUG,
|
||||
"nl80211: Secure ranging context for " MACSTR,
|
||||
MAC2STR(params->peer_addr));
|
||||
|
||||
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
|
||||
if (!msg ||
|
||||
nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
|
||||
QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT))
|
||||
goto fail;
|
||||
|
||||
attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
|
||||
if (!attr)
|
||||
goto fail;
|
||||
|
||||
if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_PEER_MAC_ADDR,
|
||||
ETH_ALEN, params->peer_addr) ||
|
||||
nla_put(msg, QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SRC_ADDR,
|
||||
ETH_ALEN, params->own_addr) ||
|
||||
nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_ACTION,
|
||||
params->action))
|
||||
goto fail;
|
||||
|
||||
if (params->cipher) {
|
||||
suite = wpa_cipher_to_cipher_suite(params->cipher);
|
||||
if (!suite ||
|
||||
nla_put_u32(msg,
|
||||
QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_CIPHER,
|
||||
suite))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (params->tk_len && params->tk) {
|
||||
if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_TK,
|
||||
params->tk_len, params->tk))
|
||||
goto fail;
|
||||
wpa_hexdump_key(MSG_DEBUG, "nl80211: TK",
|
||||
params->tk, params->tk_len);
|
||||
}
|
||||
|
||||
if (params->ltf_keyseed_len && params->ltf_keyseed) {
|
||||
u32 sha_type = wpa_ltf_keyseed_len_to_sha_type(
|
||||
params->ltf_keyseed_len);
|
||||
|
||||
if (sha_type == (u32) -1 ||
|
||||
nla_put_u32(
|
||||
msg,
|
||||
QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SHA_TYPE,
|
||||
sha_type) ||
|
||||
nla_put(msg,
|
||||
QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_LTF_KEYSEED,
|
||||
params->ltf_keyseed_len, params->ltf_keyseed))
|
||||
goto fail;
|
||||
wpa_hexdump_key(MSG_DEBUG, "nl80211: LTF keyseed",
|
||||
params->ltf_keyseed, params->ltf_keyseed_len);
|
||||
}
|
||||
nla_nest_end(msg, attr);
|
||||
|
||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
|
||||
if (ret)
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Set secure ranging context failed: ret=%d (%s)",
|
||||
ret, strerror(-ret));
|
||||
return ret;
|
||||
fail:
|
||||
nlmsg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PASN */
|
||||
|
||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||
|
||||
|
||||
|
@ -12525,6 +12690,10 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|||
#endif /* CONFIG_MBO */
|
||||
.set_bssid_tmp_disallow = nl80211_set_bssid_tmp_disallow,
|
||||
.add_sta_node = nl80211_add_sta_node,
|
||||
#ifdef CONFIG_PASN
|
||||
.send_pasn_resp = nl80211_send_pasn_resp,
|
||||
.set_secure_ranging_ctx = nl80211_set_secure_ranging_ctx,
|
||||
#endif /* CONFIG_PASN */
|
||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||
.do_acs = nl80211_do_acs,
|
||||
.configure_data_frame_filters = nl80211_configure_data_frame_filters,
|
||||
|
|
|
@ -181,6 +181,7 @@ struct wpa_driver_nl80211_data {
|
|||
unsigned int qca_do_acs:1;
|
||||
unsigned int brcm_do_acs:1;
|
||||
unsigned int uses_6ghz:1;
|
||||
unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
|
||||
|
||||
u64 vendor_scan_cookie;
|
||||
u64 remain_on_chan_cookie;
|
||||
|
|
|
@ -1055,6 +1055,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
|
|||
case QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO:
|
||||
drv->get_sta_info_vendor_cmd_avail = 1;
|
||||
break;
|
||||
case QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT:
|
||||
drv->secure_ranging_ctx_vendor_cmd_avail = 1;
|
||||
break;
|
||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||
}
|
||||
#ifdef CONFIG_DRIVER_NL80211_BRCM
|
||||
|
|
|
@ -2401,6 +2401,82 @@ static void qca_nl80211_p2p_lo_stop_event(struct wpa_driver_nl80211_data *drv,
|
|||
wpa_supplicant_event(drv->ctx, EVENT_P2P_LO_STOP, &event);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PASN
|
||||
|
||||
static void qca_nl80211_pasn_auth(struct wpa_driver_nl80211_data *drv,
|
||||
u8 *data, size_t len)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct nlattr *attr;
|
||||
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
|
||||
struct nlattr *cfg[QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAX + 1];
|
||||
unsigned int n_peers = 0, idx = 0;
|
||||
int rem_conf;
|
||||
enum qca_wlan_vendor_pasn_action action;
|
||||
union wpa_event_data event;
|
||||
|
||||
if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PASN_MAX,
|
||||
(struct nlattr *) data, len, NULL) ||
|
||||
!tb[QCA_WLAN_VENDOR_ATTR_PASN_PEERS] ||
|
||||
!tb[QCA_WLAN_VENDOR_ATTR_PASN_ACTION]) {
|
||||
return;
|
||||
}
|
||||
|
||||
os_memset(&event, 0, sizeof(event));
|
||||
action = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_PASN_ACTION]);
|
||||
switch (action) {
|
||||
case QCA_WLAN_VENDOR_PASN_ACTION_AUTH:
|
||||
event.pasn_auth.action = PASN_ACTION_AUTH;
|
||||
break;
|
||||
case QCA_WLAN_VENDOR_PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT:
|
||||
event.pasn_auth.action =
|
||||
PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
nla_for_each_nested(attr, tb[QCA_WLAN_VENDOR_ATTR_PASN_PEERS], rem_conf)
|
||||
n_peers++;
|
||||
|
||||
if (n_peers > WPAS_MAX_PASN_PEERS) {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: PASN auth: too many peers (%d)",
|
||||
n_peers);
|
||||
return;
|
||||
}
|
||||
|
||||
nla_for_each_nested(attr, tb[QCA_WLAN_VENDOR_ATTR_PASN_PEERS],
|
||||
rem_conf) {
|
||||
struct nlattr *nl_src, *nl_peer;
|
||||
|
||||
ret = nla_parse_nested(cfg, QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAX,
|
||||
attr, NULL);
|
||||
if (ret)
|
||||
return;
|
||||
nl_src = cfg[QCA_WLAN_VENDOR_ATTR_PASN_PEER_SRC_ADDR];
|
||||
nl_peer = cfg[QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAC_ADDR];
|
||||
if (nl_src)
|
||||
os_memcpy(event.pasn_auth.peer[idx].own_addr, nl_src,
|
||||
ETH_ALEN);
|
||||
if (nl_peer)
|
||||
os_memcpy(event.pasn_auth.peer[idx].peer_addr, nl_peer,
|
||||
ETH_ALEN);
|
||||
if (cfg[QCA_WLAN_VENDOR_ATTR_PASN_PEER_LTF_KEYSEED_REQUIRED])
|
||||
event.pasn_auth.peer[idx].ltf_keyseed_required = true;
|
||||
idx++;
|
||||
}
|
||||
event.pasn_auth.num_peers = n_peers;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: PASN auth action: %u, num_bssids: %d",
|
||||
event.pasn_auth.action,
|
||||
event.pasn_auth.num_peers);
|
||||
wpa_supplicant_event(drv->ctx, EVENT_PASN_AUTH, &event);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PASN */
|
||||
|
||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||
|
||||
|
||||
|
@ -2437,6 +2513,11 @@ static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
|
|||
case QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP:
|
||||
qca_nl80211_p2p_lo_stop_event(drv, data, len);
|
||||
break;
|
||||
#ifdef CONFIG_PASN
|
||||
case QCA_NL80211_VENDOR_SUBCMD_PASN:
|
||||
qca_nl80211_pasn_auth(drv, data, len);
|
||||
break;
|
||||
#endif /* CONFIG_PASN */
|
||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG,
|
||||
|
|
Loading…
Reference in a new issue