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:
Jouni Malinen 2020-05-02 00:02:15 +03:00 committed by Jouni Malinen
parent 92492dd3ac
commit 0c043d9de7
11 changed files with 144 additions and 8 deletions

View file

@ -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

View file

@ -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

View 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_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
View 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 */

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 {

View 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) 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 */

View file

@ -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 */

View file

@ -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;