DPP2: Reconfig Announcement transmission
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>
This commit is contained in:
parent
92492dd3ac
commit
0c043d9de7
11 changed files with 144 additions and 8 deletions
|
@ -539,6 +539,7 @@ L_CFLAGS += -DCONFIG_DPP
|
||||||
OBJS += src/common/dpp.c
|
OBJS += src/common/dpp.c
|
||||||
OBJS += src/common/dpp_crypto.c
|
OBJS += src/common/dpp_crypto.c
|
||||||
OBJS += src/common/dpp_pkex.c
|
OBJS += src/common/dpp_pkex.c
|
||||||
|
OBJS += src/common/dpp_reconfig.c
|
||||||
OBJS += src/ap/dpp_hostapd.c
|
OBJS += src/ap/dpp_hostapd.c
|
||||||
OBJS += src/ap/gas_query_ap.c
|
OBJS += src/ap/gas_query_ap.c
|
||||||
NEED_AES_SIV=y
|
NEED_AES_SIV=y
|
||||||
|
|
|
@ -570,6 +570,7 @@ CFLAGS += -DCONFIG_DPP
|
||||||
OBJS += ../src/common/dpp.o
|
OBJS += ../src/common/dpp.o
|
||||||
OBJS += ../src/common/dpp_crypto.o
|
OBJS += ../src/common/dpp_crypto.o
|
||||||
OBJS += ../src/common/dpp_pkex.o
|
OBJS += ../src/common/dpp_pkex.o
|
||||||
|
OBJS += ../src/common/dpp_reconfig.o
|
||||||
OBJS += ../src/ap/dpp_hostapd.o
|
OBJS += ../src/ap/dpp_hostapd.o
|
||||||
OBJS += ../src/ap/gas_query_ap.o
|
OBJS += ../src/ap/gas_query_ap.o
|
||||||
NEED_AES_SIV=y
|
NEED_AES_SIV=y
|
||||||
|
|
|
@ -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_clear(struct dpp_global *dpp);
|
||||||
void dpp_global_deinit(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 /* CONFIG_DPP */
|
||||||
#endif /* DPP_H */
|
#endif /* DPP_H */
|
||||||
|
|
76
src/common/dpp_reconfig.c
Normal file
76
src/common/dpp_reconfig.c
Normal file
|
@ -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 */
|
|
@ -23,6 +23,7 @@ OBJS += $(SRC)/tls/asn1.o
|
||||||
OBJS += $(SRC)/common/dpp.o
|
OBJS += $(SRC)/common/dpp.o
|
||||||
OBJS += $(SRC)/common/dpp_crypto.o
|
OBJS += $(SRC)/common/dpp_crypto.o
|
||||||
OBJS += $(SRC)/common/dpp_pkex.o
|
OBJS += $(SRC)/common/dpp_pkex.o
|
||||||
|
OBJS += $(SRC)/common/dpp_reconfig.o
|
||||||
|
|
||||||
dpp-uri: dpp-uri.o $(OBJS) $(LIBS)
|
dpp-uri: dpp-uri.o $(OBJS) $(LIBS)
|
||||||
$(LDO) $(LDFLAGS) -o $@ $^ -lcrypto
|
$(LDO) $(LDFLAGS) -o $@ $^ -lcrypto
|
||||||
|
|
|
@ -249,6 +249,7 @@ L_CFLAGS += -DCONFIG_DPP
|
||||||
OBJS += src/common/dpp.c
|
OBJS += src/common/dpp.c
|
||||||
OBJS += src/common/dpp_crypto.c
|
OBJS += src/common/dpp_crypto.c
|
||||||
OBJS += src/common/dpp_pkex.c
|
OBJS += src/common/dpp_pkex.c
|
||||||
|
OBJS += src/common/dpp_reconfig.c
|
||||||
OBJS += dpp_supplicant.c
|
OBJS += dpp_supplicant.c
|
||||||
NEED_AES_SIV=y
|
NEED_AES_SIV=y
|
||||||
NEED_HMAC_SHA256_KDF=y
|
NEED_HMAC_SHA256_KDF=y
|
||||||
|
|
|
@ -281,6 +281,7 @@ CFLAGS += -DCONFIG_DPP
|
||||||
OBJS += ../src/common/dpp.o
|
OBJS += ../src/common/dpp.o
|
||||||
OBJS += ../src/common/dpp_crypto.o
|
OBJS += ../src/common/dpp_crypto.o
|
||||||
OBJS += ../src/common/dpp_pkex.o
|
OBJS += ../src/common/dpp_pkex.o
|
||||||
|
OBJS += ../src/common/dpp_reconfig.o
|
||||||
OBJS += dpp_supplicant.o
|
OBJS += dpp_supplicant.o
|
||||||
NEED_AES_SIV=y
|
NEED_AES_SIV=y
|
||||||
NEED_HMAC_SHA256_KDF=y
|
NEED_HMAC_SHA256_KDF=y
|
||||||
|
|
|
@ -11013,6 +11013,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
|
} else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
|
||||||
wpas_dpp_chirp_stop(wpa_s);
|
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_DPP2 */
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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)
|
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_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",
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
|
||||||
MAC2STR(broadcast), wpa_s->dpp_chirp_freq,
|
MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
|
||||||
DPP_PA_PRESENCE_ANNOUNCEMENT);
|
|
||||||
if (offchannel_send_action(
|
if (offchannel_send_action(
|
||||||
wpa_s, wpa_s->dpp_chirp_freq, broadcast,
|
wpa_s, wpa_s->dpp_chirp_freq, broadcast,
|
||||||
wpa_s->own_addr, broadcast,
|
wpa_s->own_addr, broadcast,
|
||||||
wpabuf_head(wpa_s->dpp_presence_announcement),
|
wpabuf_head(msg), wpabuf_len(msg),
|
||||||
wpabuf_len(wpa_s->dpp_presence_announcement),
|
|
||||||
2000, wpas_dpp_chirp_tx_status, 0) < 0)
|
2000, wpas_dpp_chirp_tx_status, 0) < 0)
|
||||||
wpas_dpp_chirp_stop(wpa_s);
|
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;
|
int c;
|
||||||
struct wpa_bss *bss;
|
struct wpa_bss *bss;
|
||||||
|
|
||||||
if (!bi)
|
if (!bi && !wpa_s->dpp_reconfig_announcement)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wpa_s->dpp_chirp_scan_done = 1;
|
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;
|
wpa_s->dpp_chirp_freqs = NULL;
|
||||||
|
|
||||||
/* Channels from own bootstrapping info */
|
/* Channels from own bootstrapping info */
|
||||||
|
if (bi) {
|
||||||
for (i = 0; i < bi->num_freq; i++)
|
for (i = 0; i < bi->num_freq; i++)
|
||||||
int_array_add_unique(&wpa_s->dpp_chirp_freqs, bi->freq[i]);
|
int_array_add_unique(&wpa_s->dpp_chirp_freqs,
|
||||||
|
bi->freq[i]);
|
||||||
|
}
|
||||||
|
|
||||||
/* Preferred chirping channels */
|
/* Preferred chirping channels */
|
||||||
int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437);
|
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)
|
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);
|
offchannel_send_action_done(wpa_s);
|
||||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
|
||||||
}
|
}
|
||||||
wpa_s->dpp_chirp_bi = NULL;
|
wpa_s->dpp_chirp_bi = NULL;
|
||||||
wpabuf_free(wpa_s->dpp_presence_announcement);
|
wpabuf_free(wpa_s->dpp_presence_announcement);
|
||||||
wpa_s->dpp_presence_announcement = NULL;
|
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)
|
if (wpa_s->dpp_chirp_listen)
|
||||||
wpas_dpp_listen_stop(wpa_s);
|
wpas_dpp_listen_stop(wpa_s);
|
||||||
wpa_s->dpp_chirp_listen = 0;
|
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 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
|
@ -39,5 +39,6 @@ void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
|
||||||
enum dpp_status_error result);
|
enum dpp_status_error result);
|
||||||
int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd);
|
int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||||
void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s);
|
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 */
|
#endif /* DPP_SUPPLICANT_H */
|
||||||
|
|
|
@ -1277,6 +1277,7 @@ struct wpa_supplicant {
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
struct dpp_pfs *dpp_pfs;
|
struct dpp_pfs *dpp_pfs;
|
||||||
int dpp_pfs_fallback;
|
int dpp_pfs_fallback;
|
||||||
|
struct wpabuf *dpp_reconfig_announcement;
|
||||||
struct wpabuf *dpp_presence_announcement;
|
struct wpabuf *dpp_presence_announcement;
|
||||||
struct dpp_bootstrap_info *dpp_chirp_bi;
|
struct dpp_bootstrap_info *dpp_chirp_bi;
|
||||||
int dpp_chirp_freq;
|
int dpp_chirp_freq;
|
||||||
|
@ -1285,6 +1286,8 @@ struct wpa_supplicant {
|
||||||
int dpp_chirp_round;
|
int dpp_chirp_round;
|
||||||
int dpp_chirp_scan_done;
|
int dpp_chirp_scan_done;
|
||||||
int dpp_chirp_listen;
|
int dpp_chirp_listen;
|
||||||
|
struct wpa_ssid *dpp_reconfig_ssid;
|
||||||
|
int dpp_reconfig_ssid_id;
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
char *dpp_config_obj_override;
|
char *dpp_config_obj_override;
|
||||||
|
|
Loading…
Reference in a new issue