#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"
#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 */
#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,
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 */
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,