]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP2: Reconfig Announcement transmission
authorJouni Malinen <jouni@codeaurora.org>
Fri, 1 May 2020 21:02:15 +0000 (00:02 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 11 May 2020 13:41:33 +0000 (16:41 +0300)
Extend DPP chirping mechanism to allow Reconfig Announcement frames to
be transmitted instead of the Presence Announcement frames. Add a new
wpa_supplicant control interface command "DPP_RECONFIG <network id>" to
initiate reconfiguration for a specific network profile.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
hostapd/Android.mk
hostapd/Makefile
src/common/dpp.h
src/common/dpp_reconfig.c [new file with mode: 0644]
tests/fuzzing/dpp-uri/Makefile
wpa_supplicant/Android.mk
wpa_supplicant/Makefile
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dpp_supplicant.c
wpa_supplicant/dpp_supplicant.h
wpa_supplicant/wpa_supplicant_i.h

index c581f5d892244b7910cb5f0179c7ba01a1b11744..f33163057437dbb4833836be6df2d1958516972f 100644 (file)
@@ -539,6 +539,7 @@ L_CFLAGS += -DCONFIG_DPP
 OBJS += src/common/dpp.c
 OBJS += src/common/dpp_crypto.c
 OBJS += src/common/dpp_pkex.c
+OBJS += src/common/dpp_reconfig.c
 OBJS += src/ap/dpp_hostapd.c
 OBJS += src/ap/gas_query_ap.c
 NEED_AES_SIV=y
index c20a1a822db99e40e015385acd52e936881fe5e5..ded784f0368fb5d28da9380669980376b8ec58ed 100644 (file)
@@ -570,6 +570,7 @@ CFLAGS += -DCONFIG_DPP
 OBJS += ../src/common/dpp.o
 OBJS += ../src/common/dpp_crypto.o
 OBJS += ../src/common/dpp_pkex.o
+OBJS += ../src/common/dpp_reconfig.o
 OBJS += ../src/ap/dpp_hostapd.o
 OBJS += ../src/ap/gas_query_ap.o
 NEED_AES_SIV=y
index e81526fc867dcfb3f2edc9e3823e65ffd3e8ec3f..988c6fc2c77b35ed24344bd19a0b7bcc10f5eb70 100644 (file)
@@ -626,5 +626,10 @@ struct dpp_global * dpp_global_init(struct dpp_global_config *config);
 void dpp_global_clear(struct dpp_global *dpp);
 void dpp_global_deinit(struct dpp_global *dpp);
 
+/* dpp_reconfig.c */
+
+struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
+                                               size_t csign_key_len);
+
 #endif /* CONFIG_DPP */
 #endif /* DPP_H */
diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c
new file mode 100644 (file)
index 0000000..597963f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * DPP reconfiguration
+ * Copyright (c) 2020, The Linux Foundation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "crypto/crypto.h"
+#include "dpp.h"
+#include "dpp_i.h"
+
+
+#ifdef CONFIG_DPP2
+
+static void dpp_build_attr_csign_key_hash(struct wpabuf *msg, const u8 *hash)
+{
+       if (hash) {
+               wpa_printf(MSG_DEBUG, "DPP: Configurator C-sign key Hash");
+               wpabuf_put_le16(msg, DPP_ATTR_C_SIGN_KEY_HASH);
+               wpabuf_put_le16(msg, SHA256_MAC_LEN);
+               wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
+       }
+}
+
+
+struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
+                                               size_t csign_key_len)
+{
+       struct wpabuf *msg;
+       EVP_PKEY *csign = NULL;
+       const unsigned char *p;
+       struct wpabuf *uncomp;
+       u8 hash[SHA256_MAC_LEN];
+       const u8 *addr[1];
+       size_t len[1];
+       int res;
+
+       wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame");
+
+       p = csign_key;
+       csign = d2i_PUBKEY(NULL, &p, csign_key_len);
+       if (!csign) {
+               wpa_printf(MSG_ERROR,
+                          "DPP: Failed to parse local C-sign-key information");
+               return NULL;
+       }
+
+       uncomp = dpp_get_pubkey_point(csign, 1);
+       EVP_PKEY_free(csign);
+       if (!uncomp)
+               return NULL;
+       addr[0] = wpabuf_head(uncomp);
+       len[0] = wpabuf_len(uncomp);
+       wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed C-sign key", addr[0], len[0]);
+       res = sha256_vector(1, addr, len, hash);
+       wpabuf_free(uncomp);
+       if (res < 0)
+               return NULL;
+       wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)",
+                   hash, SHA256_MAC_LEN);
+
+       msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, 4 + SHA256_MAC_LEN);
+       if (!msg)
+               return NULL;
+
+       /* Configurator C-sign key Hash */
+       dpp_build_attr_csign_key_hash(msg, hash);
+       wpa_hexdump_buf(MSG_DEBUG,
+                       "DPP: Reconfig Announcement frame attributes", msg);
+       return msg;
+}
+#endif /* CONFIG_DPP2 */
index e5788a833f3fcce39496a0af2e5af06bfb1c6716..6125e4b36d73cf7222671d6cf8d795b90d0a0a35 100644 (file)
@@ -23,6 +23,7 @@ OBJS += $(SRC)/tls/asn1.o
 OBJS += $(SRC)/common/dpp.o
 OBJS += $(SRC)/common/dpp_crypto.o
 OBJS += $(SRC)/common/dpp_pkex.o
+OBJS += $(SRC)/common/dpp_reconfig.o
 
 dpp-uri: dpp-uri.o $(OBJS) $(LIBS)
        $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto
index a589b2774832f6a865cf13c38c1fd9dbc7af7dc6..0b091d7566a24893ca446847880c428a3ef265bb 100644 (file)
@@ -249,6 +249,7 @@ L_CFLAGS += -DCONFIG_DPP
 OBJS += src/common/dpp.c
 OBJS += src/common/dpp_crypto.c
 OBJS += src/common/dpp_pkex.c
+OBJS += src/common/dpp_reconfig.c
 OBJS += dpp_supplicant.c
 NEED_AES_SIV=y
 NEED_HMAC_SHA256_KDF=y
index 441a7db1acb61d9bf686889917aebc2898784814..d2bdbc47ce0c3e23f435cf458f496ccea6222931 100644 (file)
@@ -281,6 +281,7 @@ CFLAGS += -DCONFIG_DPP
 OBJS += ../src/common/dpp.o
 OBJS += ../src/common/dpp_crypto.o
 OBJS += ../src/common/dpp_pkex.o
+OBJS += ../src/common/dpp_reconfig.o
 OBJS += dpp_supplicant.o
 NEED_AES_SIV=y
 NEED_HMAC_SHA256_KDF=y
index 6e673fe3609b8c98176d107df7d0e3436e847e16..5c99735c8c35a1757e2727f2ef1a2cdd49f20824 100644 (file)
@@ -11013,6 +11013,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                        reply_len = -1;
        } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
                wpas_dpp_chirp_stop(wpa_s);
+       } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) {
+               struct wpa_ssid *ssid;
+
+               ssid = wpa_config_get_network(wpa_s->conf, atoi(buf + 13));
+               if (!ssid || wpas_dpp_reconfig(wpa_s, ssid) < 0)
+                       reply_len = -1;
 #endif /* CONFIG_DPP2 */
 #endif /* CONFIG_DPP */
        } else {
index 837ddbe049b15268284d5ae31a3aaa80f3475a2a..f74f1d69537b2b774d3ed04d57e524b2aecc1ac4 100644 (file)
@@ -2878,15 +2878,24 @@ static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
 
 static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
 {
+       struct wpabuf *msg;
+       int type;
+
+       msg = wpa_s->dpp_presence_announcement;
+       type = DPP_PA_PRESENCE_ANNOUNCEMENT;
+       if (!msg) {
+               msg = wpa_s->dpp_reconfig_announcement;
+               if (!msg)
+                       return;
+               type = DPP_PA_RECONFIG_ANNOUNCEMENT;
+       }
        wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
        wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
-               MAC2STR(broadcast), wpa_s->dpp_chirp_freq,
-               DPP_PA_PRESENCE_ANNOUNCEMENT);
+               MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
        if (offchannel_send_action(
                    wpa_s, wpa_s->dpp_chirp_freq, broadcast,
                    wpa_s->own_addr, broadcast,
-                   wpabuf_head(wpa_s->dpp_presence_announcement),
-                   wpabuf_len(wpa_s->dpp_presence_announcement),
+                   wpabuf_head(msg), wpabuf_len(msg),
                    2000, wpas_dpp_chirp_tx_status, 0) < 0)
                wpas_dpp_chirp_stop(wpa_s);
 }
@@ -2901,7 +2910,7 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
        int c;
        struct wpa_bss *bss;
 
-       if (!bi)
+       if (!bi && !wpa_s->dpp_reconfig_announcement)
                return;
 
        wpa_s->dpp_chirp_scan_done = 1;
@@ -2910,8 +2919,11 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
        wpa_s->dpp_chirp_freqs = NULL;
 
        /* Channels from own bootstrapping info */
-       for (i = 0; i < bi->num_freq; i++)
-               int_array_add_unique(&wpa_s->dpp_chirp_freqs, bi->freq[i]);
+       if (bi) {
+               for (i = 0; i < bi->num_freq; i++)
+                       int_array_add_unique(&wpa_s->dpp_chirp_freqs,
+                                            bi->freq[i]);
+       }
 
        /* Preferred chirping channels */
        int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437);
@@ -3085,13 +3097,16 @@ int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
 
 void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
 {
-       if (wpa_s->dpp_presence_announcement) {
+       if (wpa_s->dpp_presence_announcement ||
+           wpa_s->dpp_reconfig_announcement) {
                offchannel_send_action_done(wpa_s);
                wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
        }
        wpa_s->dpp_chirp_bi = NULL;
        wpabuf_free(wpa_s->dpp_presence_announcement);
        wpa_s->dpp_presence_announcement = NULL;
+       wpabuf_free(wpa_s->dpp_reconfig_announcement);
+       wpa_s->dpp_reconfig_announcement = NULL;
        if (wpa_s->dpp_chirp_listen)
                wpas_dpp_listen_stop(wpa_s);
        wpa_s->dpp_chirp_listen = 0;
@@ -3106,4 +3121,29 @@ void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
        }
 }
 
+
+int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+       if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
+           !ssid->dpp_csign)
+               return -1;
+
+       wpas_dpp_chirp_stop(wpa_s);
+       wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
+       wpa_s->dpp_qr_mutual = 0;
+       wpa_s->dpp_reconfig_announcement =
+               dpp_build_reconfig_announcement(ssid->dpp_csign,
+                                               ssid->dpp_csign_len);
+       if (!wpa_s->dpp_reconfig_announcement)
+               return -1;
+       wpa_s->dpp_reconfig_ssid = ssid;
+       wpa_s->dpp_reconfig_ssid_id = ssid->id;
+       wpa_s->dpp_chirp_iter = 1;
+       wpa_s->dpp_chirp_round = 0;
+       wpa_s->dpp_chirp_scan_done = 0;
+       wpa_s->dpp_chirp_listen = 0;
+
+       return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
+}
+
 #endif /* CONFIG_DPP2 */
index 6d70874c43a99ad8aea4683d0f649af2c318637f..2dc86e09e0ec25d18aef731c779c59c7dc2e6545 100644 (file)
@@ -39,5 +39,6 @@ void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
                                      enum dpp_status_error result);
 int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd);
 void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s);
+int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
 
 #endif /* DPP_SUPPLICANT_H */
index 2ed8e2f85b5bd2e604efb4a5b024a59dbe8795cd..734ba0797f900d7529cc673d396861916a3e950a 100644 (file)
@@ -1277,6 +1277,7 @@ struct wpa_supplicant {
 #ifdef CONFIG_DPP2
        struct dpp_pfs *dpp_pfs;
        int dpp_pfs_fallback;
+       struct wpabuf *dpp_reconfig_announcement;
        struct wpabuf *dpp_presence_announcement;
        struct dpp_bootstrap_info *dpp_chirp_bi;
        int dpp_chirp_freq;
@@ -1285,6 +1286,8 @@ struct wpa_supplicant {
        int dpp_chirp_round;
        int dpp_chirp_scan_done;
        int dpp_chirp_listen;
+       struct wpa_ssid *dpp_reconfig_ssid;
+       int dpp_reconfig_ssid_id;
 #endif /* CONFIG_DPP2 */
 #ifdef CONFIG_TESTING_OPTIONS
        char *dpp_config_obj_override;