|
@@ -0,0 +1,941 @@
|
|
|
+From d7be749335f2585658cf98c4f0e7d6cd5ac06865 Mon Sep 17 00:00:00 2001
|
|
|
+From: Jouni Malinen <jouni@qca.qualcomm.com>
|
|
|
+Date: Tue, 25 Jan 2022 00:35:36 +0200
|
|
|
+Subject: [PATCH] DPP3: PKEX over TCP
|
|
|
+
|
|
|
+Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
|
|
|
+
|
|
|
+CVE: CVE-2022-37660
|
|
|
+
|
|
|
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?id=d7be749335f2585658cf98c4f0e7d6cd5ac06865]
|
|
|
+
|
|
|
+Signed-off-by: Divya Chellam <divya.chellam@windriver.com>
|
|
|
+---
|
|
|
+ src/ap/dpp_hostapd.c | 155 ++++++++++++++--
|
|
|
+ src/common/dpp.h | 13 ++
|
|
|
+ src/common/dpp_pkex.c | 18 +-
|
|
|
+ src/common/dpp_tcp.c | 308 +++++++++++++++++++++++++++++++-
|
|
|
+ wpa_supplicant/dpp_supplicant.c | 122 ++++++++++++-
|
|
|
+ 5 files changed, 580 insertions(+), 36 deletions(-)
|
|
|
+
|
|
|
+diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
|
|
|
+index fdfdcf9..d956be9 100644
|
|
|
+--- a/src/ap/dpp_hostapd.c
|
|
|
++++ b/src/ap/dpp_hostapd.c
|
|
|
+@@ -28,12 +28,16 @@ static void hostapd_dpp_auth_conf_wait_timeout(void *eloop_ctx,
|
|
|
+ static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
|
|
|
+ static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
|
|
|
+ static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
|
|
|
++static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
|
|
|
++ struct dpp_authentication *auth);
|
|
|
+ #ifdef CONFIG_DPP2
|
|
|
+ static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
|
|
|
+ void *timeout_ctx);
|
|
|
+ static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
|
|
|
+ struct dpp_authentication *auth,
|
|
|
+ struct dpp_config_obj *conf);
|
|
|
++static int hostapd_dpp_process_conf_obj(void *ctx,
|
|
|
++ struct dpp_authentication *auth);
|
|
|
+ #endif /* CONFIG_DPP2 */
|
|
|
+
|
|
|
+ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
|
+@@ -272,6 +276,75 @@ static int hostapd_dpp_pkex_next_channel(struct hostapd_data *hapd,
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
++#ifdef CONFIG_DPP2
|
|
|
++static int hostapd_dpp_pkex_done(void *ctx, void *conn,
|
|
|
++ struct dpp_bootstrap_info *peer_bi)
|
|
|
++{
|
|
|
++ struct hostapd_data *hapd = ctx;
|
|
|
++ const char *cmd = hapd->dpp_pkex_auth_cmd;
|
|
|
++ const char *pos;
|
|
|
++ u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
|
|
|
++ struct dpp_bootstrap_info *own_bi = NULL;
|
|
|
++ struct dpp_authentication *auth;
|
|
|
++
|
|
|
++ if (!cmd)
|
|
|
++ cmd = "";
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
|
|
|
++ cmd);
|
|
|
++
|
|
|
++ pos = os_strstr(cmd, " own=");
|
|
|
++ if (pos) {
|
|
|
++ pos += 5;
|
|
|
++ own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
|
|
|
++ atoi(pos));
|
|
|
++ if (!own_bi) {
|
|
|
++ wpa_printf(MSG_INFO,
|
|
|
++ "DPP: Could not find bootstrapping info for the identified local entry");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (peer_bi->curve != own_bi->curve) {
|
|
|
++ wpa_printf(MSG_INFO,
|
|
|
++ "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
|
|
|
++ peer_bi->curve->name, own_bi->curve->name);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ pos = os_strstr(cmd, " role=");
|
|
|
++ if (pos) {
|
|
|
++ pos += 6;
|
|
|
++ if (os_strncmp(pos, "configurator", 12) == 0)
|
|
|
++ allowed_roles = DPP_CAPAB_CONFIGURATOR;
|
|
|
++ else if (os_strncmp(pos, "enrollee", 8) == 0)
|
|
|
++ allowed_roles = DPP_CAPAB_ENROLLEE;
|
|
|
++ else if (os_strncmp(pos, "either", 6) == 0)
|
|
|
++ allowed_roles = DPP_CAPAB_CONFIGURATOR |
|
|
|
++ DPP_CAPAB_ENROLLEE;
|
|
|
++ else
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
|
|
++ peer_bi, own_bi, allowed_roles, 0,
|
|
|
++ hapd->iface->hw_features,
|
|
|
++ hapd->iface->num_hw_features);
|
|
|
++ if (!auth)
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ hostapd_dpp_set_testing_options(hapd, auth);
|
|
|
++ if (dpp_set_configurator(auth, cmd) < 0) {
|
|
|
++ dpp_auth_deinit(auth);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ return dpp_tcp_auth(hapd->iface->interfaces->dpp, conn, auth,
|
|
|
++ hapd->conf->dpp_name, DPP_NETROLE_AP,
|
|
|
++ hostapd_dpp_process_conf_obj);
|
|
|
++}
|
|
|
++#endif /* CONFIG_DPP2 */
|
|
|
++
|
|
|
++
|
|
|
+ enum hostapd_dpp_pkex_ver {
|
|
|
+ PKEX_VER_AUTO,
|
|
|
+ PKEX_VER_ONLY_1,
|
|
|
+@@ -279,7 +352,9 @@ enum hostapd_dpp_pkex_ver {
|
|
|
+ };
|
|
|
+
|
|
|
+ static int hostapd_dpp_pkex_init(struct hostapd_data *hapd,
|
|
|
+- enum hostapd_dpp_pkex_ver ver)
|
|
|
++ enum hostapd_dpp_pkex_ver ver,
|
|
|
++ const struct hostapd_ip_addr *ipaddr,
|
|
|
++ int tcp_port)
|
|
|
+ {
|
|
|
+ struct dpp_pkex *pkex;
|
|
|
+ struct wpabuf *msg;
|
|
|
+@@ -288,15 +363,26 @@ static int hostapd_dpp_pkex_init(struct hostapd_data *hapd,
|
|
|
+
|
|
|
+ wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
|
|
|
+ dpp_pkex_free(hapd->dpp_pkex);
|
|
|
+- hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi,
|
|
|
+- hapd->own_addr,
|
|
|
+- hapd->dpp_pkex_identifier,
|
|
|
+- hapd->dpp_pkex_code, v2);
|
|
|
+- pkex = hapd->dpp_pkex;
|
|
|
++ hapd->dpp_pkex = NULL;
|
|
|
++ pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi, hapd->own_addr,
|
|
|
++ hapd->dpp_pkex_identifier,
|
|
|
++ hapd->dpp_pkex_code, v2);
|
|
|
+ if (!pkex)
|
|
|
+ return -1;
|
|
|
+ pkex->forced_ver = ver != PKEX_VER_AUTO;
|
|
|
+
|
|
|
++ if (ipaddr) {
|
|
|
++#ifdef CONFIG_DPP2
|
|
|
++ return dpp_tcp_pkex_init(hapd->iface->interfaces->dpp, pkex,
|
|
|
++ ipaddr, tcp_port,
|
|
|
++ hapd->msg_ctx, hapd,
|
|
|
++ hostapd_dpp_pkex_done);
|
|
|
++#else /* CONFIG_DPP2 */
|
|
|
++ return -1;
|
|
|
++#endif /* CONFIG_DPP2 */
|
|
|
++ }
|
|
|
++
|
|
|
++ hapd->dpp_pkex = pkex;
|
|
|
+ msg = hapd->dpp_pkex->exchange_req;
|
|
|
+ wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
|
|
|
+ pkex->freq = 2437;
|
|
|
+@@ -326,7 +412,8 @@ static void hostapd_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
|
|
|
+ if (pkex->v2 && !pkex->forced_ver) {
|
|
|
+ wpa_printf(MSG_DEBUG,
|
|
|
+ "DPP: Fall back to PKEXv1");
|
|
|
+- hostapd_dpp_pkex_init(hapd, PKEX_VER_ONLY_1);
|
|
|
++ hostapd_dpp_pkex_init(hapd, PKEX_VER_ONLY_1,
|
|
|
++ NULL, 0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ #endif /* CONFIG_DPP3 */
|
|
|
+@@ -1883,7 +1970,7 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
|
|
|
+
|
|
|
+ static void
|
|
|
+ hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
|
|
|
+- const u8 *buf, size_t len,
|
|
|
++ const u8 *hdr, const u8 *buf, size_t len,
|
|
|
+ unsigned int freq, bool v2)
|
|
|
+ {
|
|
|
+ struct wpabuf *msg;
|
|
|
+@@ -1897,14 +1984,14 @@ hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
|
|
|
+ if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
|
|
|
+ wpa_printf(MSG_DEBUG,
|
|
|
+ "DPP: No PKEX code configured - ignore request");
|
|
|
+- return;
|
|
|
++ goto try_relay;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hapd->dpp_pkex) {
|
|
|
+ /* TODO: Support parallel operations */
|
|
|
+ wpa_printf(MSG_DEBUG,
|
|
|
+ "DPP: Already in PKEX session - ignore new request");
|
|
|
+- return;
|
|
|
++ goto try_relay;
|
|
|
+ }
|
|
|
+
|
|
|
+ hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
|
|
|
+@@ -1916,7 +2003,7 @@ hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
|
|
|
+ if (!hapd->dpp_pkex) {
|
|
|
+ wpa_printf(MSG_DEBUG,
|
|
|
+ "DPP: Failed to process the request - ignore it");
|
|
|
+- return;
|
|
|
++ goto try_relay;
|
|
|
+ }
|
|
|
+
|
|
|
+ msg = hapd->dpp_pkex->exchange_resp;
|
|
|
+@@ -1933,6 +2020,17 @@ hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
|
|
|
+ dpp_pkex_free(hapd->dpp_pkex);
|
|
|
+ hapd->dpp_pkex = NULL;
|
|
|
+ }
|
|
|
++
|
|
|
++ return;
|
|
|
++
|
|
|
++try_relay:
|
|
|
++#ifdef CONFIG_DPP2
|
|
|
++ if (v2)
|
|
|
++ dpp_relay_rx_action(hapd->iface->interfaces->dpp,
|
|
|
++ src, hdr, buf, len, freq, NULL, NULL, hapd);
|
|
|
++#else /* CONFIG_DPP2 */
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: No relay functionality included - skip");
|
|
|
++#endif /* CONFIG_DPP2 */
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+@@ -2132,12 +2230,12 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
|
|
|
+ /* This is for PKEXv2, but for now, process only with
|
|
|
+ * CONFIG_DPP3 to avoid issues with a capability that has not
|
|
|
+ * been tested with other implementations. */
|
|
|
+- hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq,
|
|
|
++ hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
|
|
|
+ true);
|
|
|
+ break;
|
|
|
+ #endif /* CONFIG_DPP3 */
|
|
|
+ case DPP_PA_PKEX_V1_EXCHANGE_REQ:
|
|
|
+- hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq,
|
|
|
++ hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
|
|
|
+ false);
|
|
|
+ break;
|
|
|
+ case DPP_PA_PKEX_EXCHANGE_RESP:
|
|
|
+@@ -2303,6 +2401,29 @@ int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
|
|
|
+ {
|
|
|
+ struct dpp_bootstrap_info *own_bi;
|
|
|
+ const char *pos, *end;
|
|
|
++ int tcp_port = DPP_TCP_PORT;
|
|
|
++ struct hostapd_ip_addr *ipaddr = NULL;
|
|
|
++#ifdef CONFIG_DPP2
|
|
|
++ struct hostapd_ip_addr ipaddr_buf;
|
|
|
++ char *addr;
|
|
|
++
|
|
|
++ pos = os_strstr(cmd, " tcp_port=");
|
|
|
++ if (pos) {
|
|
|
++ pos += 10;
|
|
|
++ tcp_port = atoi(pos);
|
|
|
++ }
|
|
|
++
|
|
|
++ addr = get_param(cmd, " tcp_addr=");
|
|
|
++ if (addr) {
|
|
|
++ int res;
|
|
|
++
|
|
|
++ res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
|
|
|
++ os_free(addr);
|
|
|
++ if (res)
|
|
|
++ return -1;
|
|
|
++ ipaddr = &ipaddr_buf;
|
|
|
++ }
|
|
|
++#endif /* CONFIG_DPP2 */
|
|
|
+
|
|
|
+ pos = os_strstr(cmd, " own=");
|
|
|
+ if (!pos)
|
|
|
+@@ -2366,8 +2487,14 @@ int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+- if (hostapd_dpp_pkex_init(hapd, ver) < 0)
|
|
|
++ if (hostapd_dpp_pkex_init(hapd, ver, ipaddr, tcp_port) < 0)
|
|
|
+ return -1;
|
|
|
++ } else {
|
|
|
++#ifdef CONFIG_DPP2
|
|
|
++ dpp_controller_pkex_add(hapd->iface->interfaces->dpp, own_bi,
|
|
|
++ hapd->dpp_pkex_code,
|
|
|
++ hapd->dpp_pkex_identifier);
|
|
|
++#endif /* CONFIG_DPP2 */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* TODO: Support multiple PKEX info entries */
|
|
|
+diff --git a/src/common/dpp.h b/src/common/dpp.h
|
|
|
+index bfea446..ca33fe3 100644
|
|
|
+--- a/src/common/dpp.h
|
|
|
++++ b/src/common/dpp.h
|
|
|
+@@ -550,6 +550,9 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
|
|
|
+ const u8 *attr_start, size_t attr_len);
|
|
|
+ int dpp_notify_new_qr_code(struct dpp_authentication *auth,
|
|
|
+ struct dpp_bootstrap_info *peer_bi);
|
|
|
++void dpp_controller_pkex_add(struct dpp_global *dpp,
|
|
|
++ struct dpp_bootstrap_info *bi,
|
|
|
++ const char *code, const char *identifier);
|
|
|
+ struct dpp_configuration * dpp_configuration_alloc(const char *type);
|
|
|
+ int dpp_akm_psk(enum dpp_akm akm);
|
|
|
+ int dpp_akm_sae(enum dpp_akm akm);
|
|
|
+@@ -688,12 +691,22 @@ struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp,
|
|
|
+ unsigned int id);
|
|
|
+ void dpp_controller_new_qr_code(struct dpp_global *dpp,
|
|
|
+ struct dpp_bootstrap_info *bi);
|
|
|
++int dpp_tcp_pkex_init(struct dpp_global *dpp, struct dpp_pkex *pkex,
|
|
|
++ const struct hostapd_ip_addr *addr, int port,
|
|
|
++ void *msg_ctx, void *cb_ctx,
|
|
|
++ int (*pkex_done)(void *ctx, void *conn,
|
|
|
++ struct dpp_bootstrap_info *bi));
|
|
|
+ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
|
|
|
+ const struct hostapd_ip_addr *addr, int port,
|
|
|
+ const char *name, enum dpp_netrole netrole, void *msg_ctx,
|
|
|
+ void *cb_ctx,
|
|
|
+ int (*process_conf_obj)(void *ctx,
|
|
|
+ struct dpp_authentication *auth));
|
|
|
++int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
|
|
|
++ struct dpp_authentication *auth, const char *name,
|
|
|
++ enum dpp_netrole netrole,
|
|
|
++ int (*process_conf_obj)(void *ctx,
|
|
|
++ struct dpp_authentication *auth));
|
|
|
+
|
|
|
+ struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi);
|
|
|
+ void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src,
|
|
|
+diff --git a/src/common/dpp_pkex.c b/src/common/dpp_pkex.c
|
|
|
+index 38349fa..72084d9 100644
|
|
|
+--- a/src/common/dpp_pkex.c
|
|
|
++++ b/src/common/dpp_pkex.c
|
|
|
+@@ -469,8 +469,10 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|
|
+ pkex->t = bi->pkex_t;
|
|
|
+ pkex->msg_ctx = msg_ctx;
|
|
|
+ pkex->own_bi = bi;
|
|
|
+- os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
|
|
|
+- os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
|
|
|
++ if (own_mac)
|
|
|
++ os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
|
|
|
++ if (peer_mac)
|
|
|
++ os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
|
|
|
+ if (identifier) {
|
|
|
+ pkex->identifier = os_strdup(identifier);
|
|
|
+ if (!pkex->identifier)
|
|
|
+@@ -742,7 +744,8 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
|
|
|
+ }
|
|
|
+ #endif /* CONFIG_DPP2 */
|
|
|
+
|
|
|
+- os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
|
|
|
++ if (peer_mac)
|
|
|
++ os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
|
|
|
+
|
|
|
+ attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
|
|
|
+ &attr_status_len);
|
|
|
+@@ -1341,9 +1344,12 @@ dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer,
|
|
|
+ return NULL;
|
|
|
+ bi->id = dpp_next_id(dpp);
|
|
|
+ bi->type = DPP_BOOTSTRAP_PKEX;
|
|
|
+- os_memcpy(bi->mac_addr, peer, ETH_ALEN);
|
|
|
+- bi->num_freq = 1;
|
|
|
+- bi->freq[0] = freq;
|
|
|
++ if (peer)
|
|
|
++ os_memcpy(bi->mac_addr, peer, ETH_ALEN);
|
|
|
++ if (freq) {
|
|
|
++ bi->num_freq = 1;
|
|
|
++ bi->freq[0] = freq;
|
|
|
++ }
|
|
|
+ bi->curve = pkex->own_bi->curve;
|
|
|
+ bi->pubkey = pkex->peer_bootstrap_key;
|
|
|
+ pkex->peer_bootstrap_key = NULL;
|
|
|
+diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c
|
|
|
+index fb8ef1c..1a8a7c7 100644
|
|
|
+--- a/src/common/dpp_tcp.c
|
|
|
++++ b/src/common/dpp_tcp.c
|
|
|
+@@ -24,10 +24,12 @@ struct dpp_connection {
|
|
|
+ struct dpp_controller *ctrl;
|
|
|
+ struct dpp_relay_controller *relay;
|
|
|
+ struct dpp_global *global;
|
|
|
++ struct dpp_pkex *pkex;
|
|
|
+ struct dpp_authentication *auth;
|
|
|
+ void *msg_ctx;
|
|
|
+ void *cb_ctx;
|
|
|
+ int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
|
|
|
++ int (*pkex_done)(void *ctx, void *conn, struct dpp_bootstrap_info *bi);
|
|
|
+ int sock;
|
|
|
+ u8 mac_addr[ETH_ALEN];
|
|
|
+ unsigned int freq;
|
|
|
+@@ -71,6 +73,9 @@ struct dpp_controller {
|
|
|
+ struct dl_list conn; /* struct dpp_connection */
|
|
|
+ char *configurator_params;
|
|
|
+ enum dpp_netrole netrole;
|
|
|
++ struct dpp_bootstrap_info *pkex_bi;
|
|
|
++ char *pkex_code;
|
|
|
++ char *pkex_identifier;
|
|
|
+ void *msg_ctx;
|
|
|
+ void *cb_ctx;
|
|
|
+ int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
|
|
|
+@@ -102,6 +107,7 @@ static void dpp_connection_free(struct dpp_connection *conn)
|
|
|
+ wpabuf_free(conn->msg);
|
|
|
+ wpabuf_free(conn->msg_out);
|
|
|
+ dpp_auth_deinit(conn->auth);
|
|
|
++ dpp_pkex_free(conn->pkex);
|
|
|
+ os_free(conn->name);
|
|
|
+ os_free(conn);
|
|
|
+ }
|
|
|
+@@ -525,6 +531,8 @@ int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
|
|
|
+ /* TODO: Could send this to all configured Controllers. For now,
|
|
|
+ * only the first Controller is supported. */
|
|
|
+ ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx);
|
|
|
++ } else if (type == DPP_PA_PKEX_EXCHANGE_REQ) {
|
|
|
++ ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx);
|
|
|
+ } else {
|
|
|
+ if (!r_bootstrap)
|
|
|
+ return -1;
|
|
|
+@@ -609,6 +617,8 @@ static void dpp_controller_free(struct dpp_controller *ctrl)
|
|
|
+ eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ);
|
|
|
+ }
|
|
|
+ os_free(ctrl->configurator_params);
|
|
|
++ os_free(ctrl->pkex_code);
|
|
|
++ os_free(ctrl->pkex_identifier);
|
|
|
+ os_free(ctrl);
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -955,6 +965,143 @@ static int dpp_controller_rx_reconfig_auth_resp(struct dpp_connection *conn,
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
++static int dpp_controller_rx_pkex_exchange_req(struct dpp_connection *conn,
|
|
|
++ const u8 *hdr, const u8 *buf,
|
|
|
++ size_t len)
|
|
|
++{
|
|
|
++ struct dpp_controller *ctrl = conn->ctrl;
|
|
|
++
|
|
|
++ if (!ctrl)
|
|
|
++ return 0;
|
|
|
++
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request");
|
|
|
++
|
|
|
++ /* TODO: Support multiple PKEX codes by iterating over all the enabled
|
|
|
++ * values here */
|
|
|
++
|
|
|
++ if (!ctrl->pkex_code || !ctrl->pkex_bi) {
|
|
|
++ wpa_printf(MSG_DEBUG,
|
|
|
++ "DPP: No PKEX code configured - ignore request");
|
|
|
++ return 0;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (conn->pkex || conn->auth) {
|
|
|
++ wpa_printf(MSG_DEBUG,
|
|
|
++ "DPP: Already in PKEX/Authentication session - ignore new PKEX request");
|
|
|
++ return 0;
|
|
|
++ }
|
|
|
++
|
|
|
++ conn->pkex = dpp_pkex_rx_exchange_req(conn->ctrl->global, ctrl->pkex_bi,
|
|
|
++ NULL, NULL,
|
|
|
++ ctrl->pkex_identifier,
|
|
|
++ ctrl->pkex_code,
|
|
|
++ buf, len, true);
|
|
|
++ if (!conn->pkex) {
|
|
|
++ wpa_printf(MSG_DEBUG,
|
|
|
++ "DPP: Failed to process the request");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ return dpp_tcp_send_msg(conn, conn->pkex->exchange_resp);
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
++static int dpp_controller_rx_pkex_exchange_resp(struct dpp_connection *conn,
|
|
|
++ const u8 *hdr, const u8 *buf,
|
|
|
++ size_t len)
|
|
|
++{
|
|
|
++ struct dpp_pkex *pkex = conn->pkex;
|
|
|
++ struct wpabuf *msg;
|
|
|
++ int res;
|
|
|
++
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response");
|
|
|
++
|
|
|
++ if (!pkex || !pkex->initiator || pkex->exchange_done) {
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
|
|
|
++ return 0;
|
|
|
++ }
|
|
|
++
|
|
|
++ msg = dpp_pkex_rx_exchange_resp(pkex, NULL, buf, len);
|
|
|
++ if (!msg) {
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request");
|
|
|
++ res = dpp_tcp_send_msg(conn, msg);
|
|
|
++ wpabuf_free(msg);
|
|
|
++ return res;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
++static int dpp_controller_rx_pkex_commit_reveal_req(struct dpp_connection *conn,
|
|
|
++ const u8 *hdr,
|
|
|
++ const u8 *buf, size_t len)
|
|
|
++{
|
|
|
++ struct dpp_pkex *pkex = conn->pkex;
|
|
|
++ struct wpabuf *msg;
|
|
|
++ int res;
|
|
|
++ struct dpp_bootstrap_info *bi;
|
|
|
++
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request");
|
|
|
++
|
|
|
++ if (!pkex || pkex->initiator || !pkex->exchange_done) {
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
|
|
|
++ return 0;
|
|
|
++ }
|
|
|
++
|
|
|
++ msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
|
|
|
++ if (!msg) {
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response");
|
|
|
++ res = dpp_tcp_send_msg(conn, msg);
|
|
|
++ wpabuf_free(msg);
|
|
|
++ if (res < 0)
|
|
|
++ return res;
|
|
|
++ bi = dpp_pkex_finish(conn->global, pkex, NULL, 0);
|
|
|
++ if (!bi)
|
|
|
++ return -1;
|
|
|
++ conn->pkex = NULL;
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
++static int
|
|
|
++dpp_controller_rx_pkex_commit_reveal_resp(struct dpp_connection *conn,
|
|
|
++ const u8 *hdr,
|
|
|
++ const u8 *buf, size_t len)
|
|
|
++{
|
|
|
++ struct dpp_pkex *pkex = conn->pkex;
|
|
|
++ int res;
|
|
|
++ struct dpp_bootstrap_info *bi;
|
|
|
++
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response");
|
|
|
++
|
|
|
++ if (!pkex || !pkex->initiator || !pkex->exchange_done) {
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
|
|
|
++ return 0;
|
|
|
++ }
|
|
|
++
|
|
|
++ res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
|
|
|
++ if (res < 0) {
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
|
|
|
++ return res;
|
|
|
++ }
|
|
|
++
|
|
|
++ bi = dpp_pkex_finish(conn->global, pkex, NULL, 0);
|
|
|
++ if (!bi)
|
|
|
++ return -1;
|
|
|
++ conn->pkex = NULL;
|
|
|
++
|
|
|
++ if (!conn->pkex_done)
|
|
|
++ return -1;
|
|
|
++ return conn->pkex_done(conn->cb_ctx, conn, bi);
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
+ static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
|
|
|
+ size_t len)
|
|
|
+ {
|
|
|
+@@ -1014,6 +1161,22 @@ static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
|
|
|
+ case DPP_PA_RECONFIG_AUTH_RESP:
|
|
|
+ return dpp_controller_rx_reconfig_auth_resp(conn, msg, pos,
|
|
|
+ end - pos);
|
|
|
++ case DPP_PA_PKEX_V1_EXCHANGE_REQ:
|
|
|
++ wpa_printf(MSG_DEBUG,
|
|
|
++ "DPP: Ignore PKEXv1 Exchange Request - not supported over TCP");
|
|
|
++ return -1;
|
|
|
++ case DPP_PA_PKEX_EXCHANGE_REQ:
|
|
|
++ return dpp_controller_rx_pkex_exchange_req(conn, msg, pos,
|
|
|
++ end - pos);
|
|
|
++ case DPP_PA_PKEX_EXCHANGE_RESP:
|
|
|
++ return dpp_controller_rx_pkex_exchange_resp(conn, msg, pos,
|
|
|
++ end - pos);
|
|
|
++ case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
|
|
|
++ return dpp_controller_rx_pkex_commit_reveal_req(conn, msg, pos,
|
|
|
++ end - pos);
|
|
|
++ case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
|
|
|
++ return dpp_controller_rx_pkex_commit_reveal_resp(conn, msg, pos,
|
|
|
++ end - pos);
|
|
|
+ default:
|
|
|
+ /* TODO: missing messages types */
|
|
|
+ wpa_printf(MSG_DEBUG,
|
|
|
+@@ -1559,6 +1722,101 @@ fail:
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
++int dpp_tcp_pkex_init(struct dpp_global *dpp, struct dpp_pkex *pkex,
|
|
|
++ const struct hostapd_ip_addr *addr, int port,
|
|
|
++ void *msg_ctx, void *cb_ctx,
|
|
|
++ int (*pkex_done)(void *ctx, void *conn,
|
|
|
++ struct dpp_bootstrap_info *bi))
|
|
|
++{
|
|
|
++ struct dpp_connection *conn;
|
|
|
++ struct sockaddr_storage saddr;
|
|
|
++ socklen_t addrlen;
|
|
|
++ const u8 *hdr, *pos, *end;
|
|
|
++ char txt[100];
|
|
|
++
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
|
|
|
++ hostapd_ip_txt(addr, txt, sizeof(txt)), port);
|
|
|
++ if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
|
|
|
++ addr, port) < 0) {
|
|
|
++ dpp_pkex_free(pkex);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ conn = os_zalloc(sizeof(*conn));
|
|
|
++ if (!conn) {
|
|
|
++ dpp_pkex_free(pkex);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ conn->msg_ctx = msg_ctx;
|
|
|
++ conn->cb_ctx = cb_ctx;
|
|
|
++ conn->pkex_done = pkex_done;
|
|
|
++ conn->global = dpp;
|
|
|
++ conn->pkex = pkex;
|
|
|
++ conn->sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
++ if (conn->sock < 0)
|
|
|
++ goto fail;
|
|
|
++
|
|
|
++ if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
|
|
|
++ strerror(errno));
|
|
|
++ goto fail;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
|
|
|
++ if (errno != EINPROGRESS) {
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
|
|
|
++ strerror(errno));
|
|
|
++ goto fail;
|
|
|
++ }
|
|
|
++
|
|
|
++ /*
|
|
|
++ * Continue connecting in the background; eloop will call us
|
|
|
++ * once the connection is ready (or failed).
|
|
|
++ */
|
|
|
++ }
|
|
|
++
|
|
|
++ if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
|
|
|
++ dpp_conn_tx_ready, conn, NULL) < 0)
|
|
|
++ goto fail;
|
|
|
++ conn->write_eloop = 1;
|
|
|
++
|
|
|
++ hdr = wpabuf_head(pkex->exchange_req);
|
|
|
++ end = hdr + wpabuf_len(pkex->exchange_req);
|
|
|
++ hdr += 2; /* skip Category and Actiom */
|
|
|
++ pos = hdr + DPP_HDR_LEN;
|
|
|
++ conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
|
|
|
++ if (!conn->msg_out)
|
|
|
++ goto fail;
|
|
|
++ /* Message will be sent in dpp_conn_tx_ready() */
|
|
|
++
|
|
|
++ /* TODO: eloop timeout to clear a connection if it does not complete
|
|
|
++ * properly */
|
|
|
++ dl_list_add(&dpp->tcp_init, &conn->list);
|
|
|
++ return 0;
|
|
|
++fail:
|
|
|
++ dpp_connection_free(conn);
|
|
|
++ return -1;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
++static int dpp_tcp_auth_start(struct dpp_connection *conn,
|
|
|
++ struct dpp_authentication *auth)
|
|
|
++{
|
|
|
++ const u8 *hdr, *pos, *end;
|
|
|
++
|
|
|
++ hdr = wpabuf_head(auth->req_msg);
|
|
|
++ end = hdr + wpabuf_len(auth->req_msg);
|
|
|
++ hdr += 2; /* skip Category and Actiom */
|
|
|
++ pos = hdr + DPP_HDR_LEN;
|
|
|
++ conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
|
|
|
++ if (!conn->msg_out)
|
|
|
++ return -1;
|
|
|
++ /* Message will be sent in dpp_conn_tx_ready() */
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
+ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
|
|
|
+ const struct hostapd_ip_addr *addr, int port, const char *name,
|
|
|
+ enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx,
|
|
|
+@@ -1568,7 +1826,6 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
|
|
|
+ struct dpp_connection *conn;
|
|
|
+ struct sockaddr_storage saddr;
|
|
|
+ socklen_t addrlen;
|
|
|
+- const u8 *hdr, *pos, *end;
|
|
|
+ char txt[100];
|
|
|
+
|
|
|
+ wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
|
|
|
+@@ -1620,14 +1877,8 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
|
|
|
+ goto fail;
|
|
|
+ conn->write_eloop = 1;
|
|
|
+
|
|
|
+- hdr = wpabuf_head(auth->req_msg);
|
|
|
+- end = hdr + wpabuf_len(auth->req_msg);
|
|
|
+- hdr += 2; /* skip Category and Actiom */
|
|
|
+- pos = hdr + DPP_HDR_LEN;
|
|
|
+- conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
|
|
|
+- if (!conn->msg_out)
|
|
|
++ if (dpp_tcp_auth_start(conn, auth) < 0)
|
|
|
+ goto fail;
|
|
|
+- /* Message will be sent in dpp_conn_tx_ready() */
|
|
|
+
|
|
|
+ /* TODO: eloop timeout to clear a connection if it does not complete
|
|
|
+ * properly */
|
|
|
+@@ -1639,6 +1890,30 @@ fail:
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
++int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
|
|
|
++ struct dpp_authentication *auth, const char *name,
|
|
|
++ enum dpp_netrole netrole,
|
|
|
++ int (*process_conf_obj)(void *ctx,
|
|
|
++ struct dpp_authentication *auth))
|
|
|
++{
|
|
|
++ struct dpp_connection *conn = _conn;
|
|
|
++
|
|
|
++ /* Continue with Authentication exchange on an existing TCP connection.
|
|
|
++ */
|
|
|
++ conn->process_conf_obj = process_conf_obj;
|
|
|
++ os_free(conn->name);
|
|
|
++ conn->name = os_strdup(name ? name : "Test");
|
|
|
++ conn->netrole = netrole;
|
|
|
++ conn->auth = auth;
|
|
|
++
|
|
|
++ if (dpp_tcp_auth_start(conn, auth) < 0)
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ dpp_conn_tx_ready(conn->sock, conn, NULL);
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
+ int dpp_controller_start(struct dpp_global *dpp,
|
|
|
+ struct dpp_controller_config *config)
|
|
|
+ {
|
|
|
+@@ -1789,6 +2064,23 @@ void dpp_controller_new_qr_code(struct dpp_global *dpp,
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
++void dpp_controller_pkex_add(struct dpp_global *dpp,
|
|
|
++ struct dpp_bootstrap_info *bi,
|
|
|
++ const char *code, const char *identifier)
|
|
|
++{
|
|
|
++ struct dpp_controller *ctrl = dpp->controller;
|
|
|
++
|
|
|
++ if (!ctrl)
|
|
|
++ return;
|
|
|
++
|
|
|
++ ctrl->pkex_bi = bi;
|
|
|
++ os_free(ctrl->pkex_code);
|
|
|
++ ctrl->pkex_code = code ? os_strdup(code) : NULL;
|
|
|
++ os_free(ctrl->pkex_identifier);
|
|
|
++ ctrl->pkex_identifier = identifier ? os_strdup(identifier) : NULL;
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
+ void dpp_tcp_init_flush(struct dpp_global *dpp)
|
|
|
+ {
|
|
|
+ struct dpp_connection *conn, *tmp;
|
|
|
+diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
|
|
|
+index 61b300f..aab94cb 100644
|
|
|
+--- a/wpa_supplicant/dpp_supplicant.c
|
|
|
++++ b/wpa_supplicant/dpp_supplicant.c
|
|
|
+@@ -2557,6 +2557,71 @@ static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
++#ifdef CONFIG_DPP2
|
|
|
++static int wpas_dpp_pkex_done(void *ctx, void *conn,
|
|
|
++ struct dpp_bootstrap_info *peer_bi)
|
|
|
++{
|
|
|
++ struct wpa_supplicant *wpa_s = ctx;
|
|
|
++ const char *cmd = wpa_s->dpp_pkex_auth_cmd;
|
|
|
++ const char *pos;
|
|
|
++ u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
|
|
|
++ struct dpp_bootstrap_info *own_bi = NULL;
|
|
|
++ struct dpp_authentication *auth;
|
|
|
++
|
|
|
++ if (!cmd)
|
|
|
++ cmd = "";
|
|
|
++ wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
|
|
|
++ cmd);
|
|
|
++
|
|
|
++ pos = os_strstr(cmd, " own=");
|
|
|
++ if (pos) {
|
|
|
++ pos += 5;
|
|
|
++ own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
|
|
|
++ if (!own_bi) {
|
|
|
++ wpa_printf(MSG_INFO,
|
|
|
++ "DPP: Could not find bootstrapping info for the identified local entry");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (peer_bi->curve != own_bi->curve) {
|
|
|
++ wpa_printf(MSG_INFO,
|
|
|
++ "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
|
|
|
++ peer_bi->curve->name, own_bi->curve->name);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ pos = os_strstr(cmd, " role=");
|
|
|
++ if (pos) {
|
|
|
++ pos += 6;
|
|
|
++ if (os_strncmp(pos, "configurator", 12) == 0)
|
|
|
++ allowed_roles = DPP_CAPAB_CONFIGURATOR;
|
|
|
++ else if (os_strncmp(pos, "enrollee", 8) == 0)
|
|
|
++ allowed_roles = DPP_CAPAB_ENROLLEE;
|
|
|
++ else if (os_strncmp(pos, "either", 6) == 0)
|
|
|
++ allowed_roles = DPP_CAPAB_CONFIGURATOR |
|
|
|
++ DPP_CAPAB_ENROLLEE;
|
|
|
++ else
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
|
|
|
++ 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
|
|
|
++ if (!auth)
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ wpas_dpp_set_testing_options(wpa_s, auth);
|
|
|
++ if (dpp_set_configurator(auth, cmd) < 0) {
|
|
|
++ dpp_auth_deinit(auth);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
|
|
|
++ DPP_NETROLE_STA, wpas_dpp_process_conf_obj);
|
|
|
++}
|
|
|
++#endif /* CONFIG_DPP2 */
|
|
|
++
|
|
|
++
|
|
|
+ enum wpas_dpp_pkex_ver {
|
|
|
+ PKEX_VER_AUTO,
|
|
|
+ PKEX_VER_ONLY_1,
|
|
|
+@@ -2564,7 +2629,9 @@ enum wpas_dpp_pkex_ver {
|
|
|
+ };
|
|
|
+
|
|
|
+ static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
|
|
|
+- enum wpas_dpp_pkex_ver ver)
|
|
|
++ enum wpas_dpp_pkex_ver ver,
|
|
|
++ const struct hostapd_ip_addr *ipaddr,
|
|
|
++ int tcp_port)
|
|
|
+ {
|
|
|
+ struct dpp_pkex *pkex;
|
|
|
+ struct wpabuf *msg;
|
|
|
+@@ -2573,15 +2640,24 @@ static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
|
|
|
+
|
|
|
+ wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
|
|
|
+ dpp_pkex_free(wpa_s->dpp_pkex);
|
|
|
+- wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi,
|
|
|
+- wpa_s->own_addr,
|
|
|
+- wpa_s->dpp_pkex_identifier,
|
|
|
+- wpa_s->dpp_pkex_code, v2);
|
|
|
+- pkex = wpa_s->dpp_pkex;
|
|
|
++ wpa_s->dpp_pkex = NULL;
|
|
|
++ pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
|
|
|
++ wpa_s->dpp_pkex_identifier,
|
|
|
++ wpa_s->dpp_pkex_code, v2);
|
|
|
+ if (!pkex)
|
|
|
+ return -1;
|
|
|
+ pkex->forced_ver = ver != PKEX_VER_AUTO;
|
|
|
+
|
|
|
++ if (ipaddr) {
|
|
|
++#ifdef CONFIG_DPP2
|
|
|
++ return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
|
|
|
++ wpa_s, wpa_s, wpas_dpp_pkex_done);
|
|
|
++#else /* CONFIG_DPP2 */
|
|
|
++ return -1;
|
|
|
++#endif /* CONFIG_DPP2 */
|
|
|
++ }
|
|
|
++
|
|
|
++ wpa_s->dpp_pkex = pkex;
|
|
|
+ msg = pkex->exchange_req;
|
|
|
+ wait_time = wpa_s->max_remain_on_chan;
|
|
|
+ if (wait_time > 2000)
|
|
|
+@@ -2618,7 +2694,8 @@ static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
|
|
|
+ if (pkex->v2 && !pkex->forced_ver) {
|
|
|
+ wpa_printf(MSG_DEBUG,
|
|
|
+ "DPP: Fall back to PKEXv1");
|
|
|
+- wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1);
|
|
|
++ wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
|
|
|
++ NULL, 0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ #endif /* CONFIG_DPP3 */
|
|
|
+@@ -3327,6 +3404,29 @@ int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
|
|
|
+ {
|
|
|
+ struct dpp_bootstrap_info *own_bi;
|
|
|
+ const char *pos, *end;
|
|
|
++ int tcp_port = DPP_TCP_PORT;
|
|
|
++ struct hostapd_ip_addr *ipaddr = NULL;
|
|
|
++#ifdef CONFIG_DPP2
|
|
|
++ struct hostapd_ip_addr ipaddr_buf;
|
|
|
++ char *addr;
|
|
|
++
|
|
|
++ pos = os_strstr(cmd, " tcp_port=");
|
|
|
++ if (pos) {
|
|
|
++ pos += 10;
|
|
|
++ tcp_port = atoi(pos);
|
|
|
++ }
|
|
|
++
|
|
|
++ addr = get_param(cmd, " tcp_addr=");
|
|
|
++ if (addr) {
|
|
|
++ int res;
|
|
|
++
|
|
|
++ res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
|
|
|
++ os_free(addr);
|
|
|
++ if (res)
|
|
|
++ return -1;
|
|
|
++ ipaddr = &ipaddr_buf;
|
|
|
++ }
|
|
|
++#endif /* CONFIG_DPP2 */
|
|
|
+
|
|
|
+ pos = os_strstr(cmd, " own=");
|
|
|
+ if (!pos)
|
|
|
+@@ -3390,8 +3490,14 @@ int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+- if (wpas_dpp_pkex_init(wpa_s, ver) < 0)
|
|
|
++ if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
|
|
|
+ return -1;
|
|
|
++ } else {
|
|
|
++#ifdef CONFIG_DPP2
|
|
|
++ dpp_controller_pkex_add(wpa_s->dpp, own_bi,
|
|
|
++ wpa_s->dpp_pkex_code,
|
|
|
++ wpa_s->dpp_pkex_identifier);
|
|
|
++#endif /* CONFIG_DPP2 */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* TODO: Support multiple PKEX info entries */
|
|
|
+--
|
|
|
+2.40.0
|
|
|
+
|