DPP: Network Introduction protocol for wpa_supplicant
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
4ff89c2ebd
commit
a0d5c56f8b
6 changed files with 211 additions and 3 deletions
|
@ -155,6 +155,7 @@ extern "C" {
|
||||||
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
|
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
|
||||||
#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY "
|
#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY "
|
||||||
#define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY "
|
#define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY "
|
||||||
|
#define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR "
|
||||||
|
|
||||||
/* MESH events */
|
/* MESH events */
|
||||||
#define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
|
#define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
|
||||||
|
|
|
@ -13,10 +13,15 @@
|
||||||
#include "common/dpp.h"
|
#include "common/dpp.h"
|
||||||
#include "common/gas.h"
|
#include "common/gas.h"
|
||||||
#include "common/gas_server.h"
|
#include "common/gas_server.h"
|
||||||
|
#include "rsn_supp/wpa.h"
|
||||||
|
#include "rsn_supp/pmksa_cache.h"
|
||||||
#include "wpa_supplicant_i.h"
|
#include "wpa_supplicant_i.h"
|
||||||
|
#include "config.h"
|
||||||
#include "driver_i.h"
|
#include "driver_i.h"
|
||||||
#include "offchannel.h"
|
#include "offchannel.h"
|
||||||
#include "gas_query.h"
|
#include "gas_query.h"
|
||||||
|
#include "bss.h"
|
||||||
|
#include "scan.h"
|
||||||
#include "dpp_supplicant.h"
|
#include "dpp_supplicant.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -1079,6 +1084,108 @@ static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *src,
|
||||||
|
const u8 *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct wpa_ssid *ssid;
|
||||||
|
const u8 *connector, *pk_hash, *nk_hash;
|
||||||
|
u16 connector_len, pk_hash_len, nk_hash_len;
|
||||||
|
struct dpp_introduction intro;
|
||||||
|
struct rsn_pmksa_cache_entry *entry;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
|
||||||
|
MAC2STR(src));
|
||||||
|
if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
|
||||||
|
os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
|
||||||
|
MACSTR " - drop", MAC2STR(src));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
offchannel_send_action_done(wpa_s);
|
||||||
|
|
||||||
|
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
|
||||||
|
if (ssid == wpa_s->dpp_intro_network)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
|
||||||
|
!ssid->dpp_csign) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Profile not found for network introduction");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
|
||||||
|
if (!connector) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Peer did not include its Connector");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dpp_peer_intro(&intro, ssid->dpp_connector,
|
||||||
|
ssid->dpp_netaccesskey,
|
||||||
|
ssid->dpp_netaccesskey_len,
|
||||||
|
ssid->dpp_csign,
|
||||||
|
ssid->dpp_csign_len,
|
||||||
|
connector, connector_len) < 0) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"DPP: Network Introduction protocol resulted in failure");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
pk_hash = dpp_get_attr(buf, len, DPP_ATTR_PEER_NET_PK_HASH,
|
||||||
|
&pk_hash_len);
|
||||||
|
if (!pk_hash || pk_hash_len != SHA256_MAC_LEN) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Peer did not include SHA256(PK)");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (os_memcmp(pk_hash, intro.nk_hash, SHA256_MAC_LEN) != 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: SHA256(PK) mismatch");
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: Received SHA256(PK)",
|
||||||
|
pk_hash, pk_hash_len);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: Calculated SHA256(PK)",
|
||||||
|
intro.nk_hash, SHA256_MAC_LEN);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
nk_hash = dpp_get_attr(buf, len, DPP_ATTR_OWN_NET_NK_HASH,
|
||||||
|
&nk_hash_len);
|
||||||
|
if (!nk_hash || nk_hash_len != SHA256_MAC_LEN) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Peer did not include SHA256(NK)");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (os_memcmp(nk_hash, intro.pk_hash, SHA256_MAC_LEN) != 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: SHA256(NK) mismatch");
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: Received SHA256(NK)",
|
||||||
|
nk_hash, nk_hash_len);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: Calculated SHA256(NK)",
|
||||||
|
intro.pk_hash, SHA256_MAC_LEN);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = os_zalloc(sizeof(*entry));
|
||||||
|
if (!entry)
|
||||||
|
goto fail;
|
||||||
|
os_memcpy(entry->aa, src, ETH_ALEN);
|
||||||
|
os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
|
||||||
|
os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
|
||||||
|
entry->pmk_len = intro.pmk_len;
|
||||||
|
entry->akmp = WPA_KEY_MGMT_DPP;
|
||||||
|
/* TODO: expiration */
|
||||||
|
entry->network_ctx = ssid;
|
||||||
|
wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Try connection again after successful network introduction");
|
||||||
|
if (wpa_supplicant_fast_associate(wpa_s) != 1) {
|
||||||
|
wpa_supplicant_cancel_sched_scan(wpa_s);
|
||||||
|
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||||
|
}
|
||||||
|
fail:
|
||||||
|
os_memset(&intro, 0, sizeof(intro));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
|
void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||||
const u8 *buf, size_t len, unsigned int freq)
|
const u8 *buf, size_t len, unsigned int freq)
|
||||||
{
|
{
|
||||||
|
@ -1108,6 +1215,9 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||||
case DPP_PA_AUTHENTICATION_CONF:
|
case DPP_PA_AUTHENTICATION_CONF:
|
||||||
wpas_dpp_rx_auth_conf(wpa_s, src, buf, len);
|
wpas_dpp_rx_auth_conf(wpa_s, src, buf, len);
|
||||||
break;
|
break;
|
||||||
|
case DPP_PA_PEER_DISCOVERY_RESP:
|
||||||
|
wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"DPP: Ignored unsupported frame subtype %d", type);
|
"DPP: Ignored unsupported frame subtype %d", type);
|
||||||
|
@ -1265,6 +1375,92 @@ int wpas_dpp_configurator_remove(struct wpa_supplicant *wpa_s, const char *id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
|
||||||
|
unsigned int freq, const u8 *dst,
|
||||||
|
const u8 *src, const u8 *bssid,
|
||||||
|
const u8 *data, size_t data_len,
|
||||||
|
enum offchannel_send_action_result result)
|
||||||
|
{
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
|
||||||
|
" result=%s (DPP Peer Discovery Request)",
|
||||||
|
freq, MAC2STR(dst),
|
||||||
|
result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
|
||||||
|
(result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
|
||||||
|
"FAILED"));
|
||||||
|
/* TODO: Time out wait for response more quickly in error cases? */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
||||||
|
struct wpa_bss *bss)
|
||||||
|
{
|
||||||
|
struct os_time now;
|
||||||
|
struct wpabuf *msg;
|
||||||
|
unsigned int wait_time;
|
||||||
|
|
||||||
|
if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
|
||||||
|
return 0; /* Not using DPP AKM - continue */
|
||||||
|
if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
|
||||||
|
return 0; /* PMKSA exists for DPP AKM - continue */
|
||||||
|
|
||||||
|
if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
|
||||||
|
!ssid->dpp_csign) {
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
|
||||||
|
"missing %s",
|
||||||
|
!ssid->dpp_connector ? "Connector" :
|
||||||
|
(!ssid->dpp_netaccesskey ? "netAccessKey" :
|
||||||
|
"C-sign-key"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_get_time(&now);
|
||||||
|
|
||||||
|
if (ssid->dpp_csign_expiry && ssid->dpp_csign_expiry < now.sec) {
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
|
||||||
|
"C-sign-key expired");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssid->dpp_netaccesskey_expiry &&
|
||||||
|
ssid->dpp_netaccesskey_expiry < now.sec) {
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
|
||||||
|
"netAccessKey expired");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Starting network introduction protocol to derive PMKSA for "
|
||||||
|
MACSTR, MAC2STR(bss->bssid));
|
||||||
|
|
||||||
|
msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ,
|
||||||
|
4 + os_strlen(ssid->dpp_connector));
|
||||||
|
if (!msg)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* DPP Connector */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
|
||||||
|
wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
|
||||||
|
wpabuf_put_str(msg, ssid->dpp_connector);
|
||||||
|
|
||||||
|
/* TODO: Timeout on AP response */
|
||||||
|
wait_time = wpa_s->max_remain_on_chan;
|
||||||
|
if (wait_time > 2000)
|
||||||
|
wait_time = 2000;
|
||||||
|
offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
|
||||||
|
broadcast,
|
||||||
|
wpabuf_head(msg), wpabuf_len(msg),
|
||||||
|
wait_time, wpas_dpp_tx_introduction_status, 0);
|
||||||
|
wpabuf_free(msg);
|
||||||
|
|
||||||
|
/* Request this connection attempt to terminate - new one will be
|
||||||
|
* started when network introduction protocol completes */
|
||||||
|
os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
|
||||||
|
wpa_s->dpp_intro_network = ssid;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpas_dpp_init(struct wpa_supplicant *wpa_s)
|
int wpas_dpp_init(struct wpa_supplicant *wpa_s)
|
||||||
{
|
{
|
||||||
u8 adv_proto_id[7];
|
u8 adv_proto_id[7];
|
||||||
|
@ -1308,4 +1504,5 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
||||||
dpp_configurator_del(wpa_s, 0);
|
dpp_configurator_del(wpa_s, 0);
|
||||||
dpp_auth_deinit(wpa_s->dpp_auth);
|
dpp_auth_deinit(wpa_s->dpp_auth);
|
||||||
wpa_s->dpp_auth = NULL;
|
wpa_s->dpp_auth = NULL;
|
||||||
|
os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,5 +27,7 @@ int wpas_dpp_configurator_add(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||||
int wpas_dpp_configurator_remove(struct wpa_supplicant *wpa_s, const char *id);
|
int wpas_dpp_configurator_remove(struct wpa_supplicant *wpa_s, const char *id);
|
||||||
int wpas_dpp_init(struct wpa_supplicant *wpa_s);
|
int wpas_dpp_init(struct wpa_supplicant *wpa_s);
|
||||||
void wpas_dpp_deinit(struct wpa_supplicant *wpa_s);
|
void wpas_dpp_deinit(struct wpa_supplicant *wpa_s);
|
||||||
|
int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
||||||
|
struct wpa_bss *bss);
|
||||||
|
|
||||||
#endif /* DPP_SUPPLICANT_H */
|
#endif /* DPP_SUPPLICANT_H */
|
||||||
|
|
|
@ -1215,9 +1215,10 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
|
if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
|
||||||
!wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid)) {
|
!wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid) &&
|
||||||
/* TODO: Go through DPP network introduction to generate
|
(!ssid->dpp_connector ||
|
||||||
* PMKSA entry. */
|
!ssid->dpp_netaccesskey ||
|
||||||
|
!ssid->dpp_csign)) {
|
||||||
if (debug_print)
|
if (debug_print)
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG,
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
" skip - no PMKSA entry for DPP");
|
" skip - no PMKSA entry for DPP");
|
||||||
|
|
|
@ -1847,6 +1847,11 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP
|
||||||
|
if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
|
||||||
|
return;
|
||||||
|
#endif /* CONFIG_DPP */
|
||||||
|
|
||||||
#ifdef CONFIG_TDLS
|
#ifdef CONFIG_TDLS
|
||||||
if (bss)
|
if (bss)
|
||||||
wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
|
wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
|
||||||
|
|
|
@ -1171,6 +1171,8 @@ struct wpa_supplicant {
|
||||||
int dpp_netrole_ap;
|
int dpp_netrole_ap;
|
||||||
int dpp_auth_ok_on_ack;
|
int dpp_auth_ok_on_ack;
|
||||||
int dpp_gas_client;
|
int dpp_gas_client;
|
||||||
|
u8 dpp_intro_bssid[ETH_ALEN];
|
||||||
|
void *dpp_intro_network;
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
char *dpp_config_obj_override;
|
char *dpp_config_obj_override;
|
||||||
char *dpp_discovery_override;
|
char *dpp_discovery_override;
|
||||||
|
|
Loading…
Reference in a new issue