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
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
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 */
--- /dev/null
+/*
+ * 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 */
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
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
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
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 {
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);
}
int c;
struct wpa_bss *bss;
- if (!bi)
+ if (!bi && !wpa_s->dpp_reconfig_announcement)
return;
wpa_s->dpp_chirp_scan_done = 1;
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);
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;
}
}
+
+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 */
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 */
#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;
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;