]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP: NFC negotiated connection handover
authorJouni Malinen <jouni@codeaurora.org>
Mon, 27 Jan 2020 15:04:26 +0000 (17:04 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 27 Jan 2020 18:36:09 +0000 (20:36 +0200)
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>
hostapd/ctrl_iface.c
src/ap/dpp_hostapd.c
src/ap/dpp_hostapd.h
src/common/dpp.c
src/common/dpp.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dpp_supplicant.c
wpa_supplicant/dpp_supplicant.h

index 5eef75bf7ac0e0782f7903d9b3b351f4a12f0213..090d4f0f68ab3c2067dfc19c0b9cac2b529d7756 100644 (file)
@@ -3372,6 +3372,24 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
                        if (os_snprintf_error(reply_size, reply_len))
                                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) {
                res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
                if (res < 0) {
index 1a3a815cbef9d18ab713a7c328d5507d1512dc6f..48922516fa6ccd8e3dcbd8a4ebe42adf2f6ec56a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * hostapd / DPP integration
  * 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.
  * 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,
                                                void *timeout_ctx)
 {
index e151c2fc633705edbfa9e042099262dd07eacc15..b1fa99ed0bc29856d8b67b2a5a7e1e2a4a232469 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * hostapd / DPP integration
  * 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.
  * See README for more details.
@@ -12,6 +12,8 @@
 
 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_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_listen(struct hostapd_data *hapd, const char *cmd);
 void hostapd_dpp_listen_stop(struct hostapd_data *hapd);
index 4b36c1efcce5af930fb70d038050ba64d4282d1e..4a0bdf06eae1f9e0bd2ee94aec654ecd5e3fe3db 100644 (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)
 {
        struct dpp_configurator *conf;
index 70d88b5dd9300ed0c24054dec72287fcbc3710a1..d59e5a4265bcc0252f4543a87756a77259bb6a4b 100644 (file)
@@ -418,6 +418,8 @@ int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
                            const char *chan_list);
 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_nfc_update_bi(struct dpp_bootstrap_info *own_bi,
+                     struct dpp_bootstrap_info *peer_bi);
 struct hostapd_hw_modes;
 struct dpp_authentication * dpp_auth_init(void *msg_ctx,
                                          struct dpp_bootstrap_info *peer_bi,
index 65dcb90f1647679c1024eb43d7d5a390b3b46dd1..8d75c80b277dff98174d5a47ab0866276373b960 100644 (file)
@@ -10811,6 +10811,28 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                        if (os_snprintf_error(reply_size, reply_len))
                                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) {
                int res;
 
index c01ff94982796743ce37056c6ec4a809fb82450d..f147afd9d20a1c138e1f4679dbe9462d0a39bcc4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * wpa_supplicant - DPP
  * 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.
  * 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)
 {
        struct wpa_supplicant *wpa_s = eloop_ctx;
index 607036a38205794c34d9763017fd465eebbce17c..5c3397a241048dbf022b6b1c05bb1216789ed38e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * wpa_supplicant - DPP
  * 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.
  * 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_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_listen(struct wpa_supplicant *wpa_s, const char *cmd);
 void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);