DPP: NFC negotiated connection handover

Add new control interface commands "DPP_NFC_HANDOVER_REQ own=<id>
uri=<URI>" and "DPP_NFC_HANDOVER_SEL own=<id> uri=<URI>" to support NFC
negotiated connection handover. These commands are used to report a DPP
URI received from a peer NFC Device in Handover Request and Handover
Select messages. The commands return peer bootstrapping information ID
or FAIL on failure. The returned ID is used similarly to any other
bootstrapping information to initiate DPP authentication.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2020-01-27 17:04:26 +02:00 committed by Jouni Malinen
parent 2bbe6ad3aa
commit 5e287724ee
8 changed files with 262 additions and 4 deletions

View file

@ -3372,6 +3372,24 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
if (os_snprintf_error(reply_size, reply_len)) if (os_snprintf_error(reply_size, reply_len))
reply_len = -1; reply_len = -1;
} }
} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
res = hostapd_dpp_nfc_handover_req(hapd, buf + 20);
if (res < 0) {
reply_len = -1;
} else {
reply_len = os_snprintf(reply, reply_size, "%d", res);
if (os_snprintf_error(reply_size, reply_len))
reply_len = -1;
}
} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
res = hostapd_dpp_nfc_handover_sel(hapd, buf + 20);
if (res < 0) {
reply_len = -1;
} else {
reply_len = os_snprintf(reply, reply_size, "%d", res);
if (os_snprintf_error(reply_size, reply_len))
reply_len = -1;
}
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) { } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18); res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
if (res < 0) { if (res < 0) {

View file

@ -1,7 +1,7 @@
/* /*
* hostapd / DPP integration * hostapd / DPP integration
* Copyright (c) 2017, Qualcomm Atheros, Inc. * Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation * Copyright (c) 2018-2020, The Linux Foundation
* *
* This software may be distributed under the terms of the BSD license. * This software may be distributed under the terms of the BSD license.
* See README for more details. * See README for more details.
@ -81,6 +81,71 @@ int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd)
} }
int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd)
{
const char *pos;
struct dpp_bootstrap_info *peer_bi, *own_bi;
pos = os_strstr(cmd, " own=");
if (!pos)
return -1;
pos += 5;
own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
if (!own_bi)
return -1;
pos = os_strstr(cmd, " uri=");
if (!pos)
return -1;
pos += 5;
peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
if (!peer_bi) {
wpa_printf(MSG_INFO,
"DPP: Failed to parse URI from NFC Handover Request");
return -1;
}
if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
return -1;
return peer_bi->id;
}
int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd)
{
const char *pos;
struct dpp_bootstrap_info *peer_bi, *own_bi;
pos = os_strstr(cmd, " own=");
if (!pos)
return -1;
pos += 5;
own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
if (!own_bi)
return -1;
pos = os_strstr(cmd, " uri=");
if (!pos)
return -1;
pos += 5;
peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
if (!peer_bi) {
wpa_printf(MSG_INFO,
"DPP: Failed to parse URI from NFC Handover Select");
return -1;
}
if (peer_bi->curve != own_bi->curve) {
wpa_printf(MSG_INFO,
"DPP: Peer (NFC Handover Selector) used different curve");
return -1;
}
return peer_bi->id;
}
static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx, static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
void *timeout_ctx) void *timeout_ctx)
{ {

View file

@ -1,7 +1,7 @@
/* /*
* hostapd / DPP integration * hostapd / DPP integration
* Copyright (c) 2017, Qualcomm Atheros, Inc. * Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation * Copyright (c) 2018-2020, The Linux Foundation
* *
* This software may be distributed under the terms of the BSD license. * This software may be distributed under the terms of the BSD license.
* See README for more details. * See README for more details.
@ -12,6 +12,8 @@
int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd); int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd); int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd); int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd); int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd);
void hostapd_dpp_listen_stop(struct hostapd_data *hapd); void hostapd_dpp_listen_stop(struct hostapd_data *hapd);

View file

@ -9216,6 +9216,88 @@ void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
} }
static int dpp_nfc_update_bi_channel(struct dpp_bootstrap_info *own_bi,
struct dpp_bootstrap_info *peer_bi)
{
unsigned int i, freq = 0;
enum hostapd_hw_mode mode;
u8 op_class, channel;
char chan[20];
if (peer_bi->num_freq == 0)
return 0; /* no channel preference/constraint */
for (i = 0; i < peer_bi->num_freq; i++) {
if (own_bi->num_freq == 0 ||
freq_included(own_bi->freq, own_bi->num_freq,
peer_bi->freq[i])) {
freq = peer_bi->freq[i];
break;
}
}
if (!freq) {
wpa_printf(MSG_DEBUG, "DPP: No common channel found");
return -1;
}
mode = ieee80211_freq_to_channel_ext(freq, 0, 0, &op_class, &channel);
if (mode == NUM_HOSTAPD_MODES) {
wpa_printf(MSG_DEBUG,
"DPP: Could not determine operating class or channel number for %u MHz",
freq);
}
wpa_printf(MSG_DEBUG,
"DPP: Selected %u MHz (op_class %u channel %u) as the negotiation channel based on information from NFC negotiated handover",
freq, op_class, channel);
os_snprintf(chan, sizeof(chan), "%u/%u", op_class, channel);
os_free(own_bi->chan);
own_bi->chan = os_strdup(chan);
own_bi->freq[0] = freq;
own_bi->num_freq = 1;
os_free(peer_bi->chan);
peer_bi->chan = os_strdup(chan);
peer_bi->freq[0] = freq;
peer_bi->num_freq = 1;
return dpp_gen_uri(own_bi);
}
static int dpp_nfc_update_bi_key(struct dpp_bootstrap_info *own_bi,
struct dpp_bootstrap_info *peer_bi)
{
if (peer_bi->curve == own_bi->curve)
return 0;
wpa_printf(MSG_DEBUG,
"DPP: Update own bootstrapping key to match peer curve from NFC handover");
EVP_PKEY_free(own_bi->pubkey);
own_bi->pubkey = NULL;
if (dpp_keygen(own_bi, peer_bi->curve->name, NULL, 0) < 0 ||
dpp_gen_uri(own_bi) < 0)
goto fail;
return 0;
fail:
dl_list_del(&own_bi->list);
dpp_bootstrap_info_free(own_bi);
return -1;
}
int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi,
struct dpp_bootstrap_info *peer_bi)
{
if (dpp_nfc_update_bi_channel(own_bi, peer_bi) < 0 ||
dpp_nfc_update_bi_key(own_bi, peer_bi) < 0)
return -1;
return 0;
}
static unsigned int dpp_next_configurator_id(struct dpp_global *dpp) static unsigned int dpp_next_configurator_id(struct dpp_global *dpp)
{ {
struct dpp_configurator *conf; struct dpp_configurator *conf;

View file

@ -418,6 +418,8 @@ int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
const char *chan_list); const char *chan_list);
int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac); int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac);
int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info); int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi,
struct dpp_bootstrap_info *peer_bi);
struct hostapd_hw_modes; struct hostapd_hw_modes;
struct dpp_authentication * dpp_auth_init(void *msg_ctx, struct dpp_authentication * dpp_auth_init(void *msg_ctx,
struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *peer_bi,

View file

@ -10811,6 +10811,28 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (os_snprintf_error(reply_size, reply_len)) if (os_snprintf_error(reply_size, reply_len))
reply_len = -1; reply_len = -1;
} }
} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
int res;
res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20);
if (res < 0) {
reply_len = -1;
} else {
reply_len = os_snprintf(reply, reply_size, "%d", res);
if (os_snprintf_error(reply_size, reply_len))
reply_len = -1;
}
} else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
int res;
res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20);
if (res < 0) {
reply_len = -1;
} else {
reply_len = os_snprintf(reply, reply_size, "%d", res);
if (os_snprintf_error(reply_size, reply_len))
reply_len = -1;
}
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) { } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
int res; int res;

View file

@ -1,7 +1,7 @@
/* /*
* wpa_supplicant - DPP * wpa_supplicant - DPP
* Copyright (c) 2017, Qualcomm Atheros, Inc. * Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation * Copyright (c) 2018-2020, The Linux Foundation
* *
* This software may be distributed under the terms of the BSD license. * This software may be distributed under the terms of the BSD license.
* See README for more details. * See README for more details.
@ -106,6 +106,71 @@ int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
} }
int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd)
{
const char *pos;
struct dpp_bootstrap_info *peer_bi, *own_bi;
pos = os_strstr(cmd, " own=");
if (!pos)
return -1;
pos += 5;
own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
if (!own_bi)
return -1;
pos = os_strstr(cmd, " uri=");
if (!pos)
return -1;
pos += 5;
peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
if (!peer_bi) {
wpa_printf(MSG_INFO,
"DPP: Failed to parse URI from NFC Handover Request");
return -1;
}
if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
return -1;
return peer_bi->id;
}
int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd)
{
const char *pos;
struct dpp_bootstrap_info *peer_bi, *own_bi;
pos = os_strstr(cmd, " own=");
if (!pos)
return -1;
pos += 5;
own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
if (!own_bi)
return -1;
pos = os_strstr(cmd, " uri=");
if (!pos)
return -1;
pos += 5;
peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
if (!peer_bi) {
wpa_printf(MSG_INFO,
"DPP: Failed to parse URI from NFC Handover Select");
return -1;
}
if (peer_bi->curve != own_bi->curve) {
wpa_printf(MSG_INFO,
"DPP: Peer (NFC Handover Selector) used different curve");
return -1;
}
return peer_bi->id;
}
static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx) static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
{ {
struct wpa_supplicant *wpa_s = eloop_ctx; struct wpa_supplicant *wpa_s = eloop_ctx;

View file

@ -1,7 +1,7 @@
/* /*
* wpa_supplicant - DPP * wpa_supplicant - DPP
* Copyright (c) 2017, Qualcomm Atheros, Inc. * Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation * Copyright (c) 2018-2020, The Linux Foundation
* *
* This software may be distributed under the terms of the BSD license. * This software may be distributed under the terms of the BSD license.
* See README for more details. * See README for more details.
@ -14,6 +14,8 @@ enum dpp_status_error;
int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd); int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd); int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd); int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd); int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd);
void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s); void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);