]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP: Negotiation channel change request from Initiator
authorJouni Malinen <jouni@qca.qualcomm.com>
Sun, 29 Oct 2017 14:08:02 +0000 (16:08 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 29 Oct 2017 14:08:02 +0000 (16:08 +0200)
Allow the Initiator to request a different channel to be used for DPP
Authentication and DPP Configuration exchanges. This commit adds support
for this in wpa_supplicant with the optional neg_freq=<freq in MHz>
parameter in DPP_AUTH_INIT.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/ap/dpp_hostapd.c
src/common/dpp.c
src/common/dpp.h
wpa_supplicant/dpp_supplicant.c

index 943e20648db9a7ce55b4d6026144ba5743c93059..6c45ee3820061103e8a8743dbc56f533e2838dad 100644 (file)
@@ -503,7 +503,7 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
 
        if (hapd->dpp_auth)
                dpp_auth_deinit(hapd->dpp_auth);
-       hapd->dpp_auth = dpp_auth_init(hapd, peer_bi, own_bi, configurator);
+       hapd->dpp_auth = dpp_auth_init(hapd, peer_bi, own_bi, configurator, 0);
        if (!hapd->dpp_auth)
                goto fail;
        hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
index f969cb35f018d0af7b4d84e01c14a08505618ef2..00e7b479336c5a82f0f2c65bea4219aed6ff348c 100644 (file)
@@ -1349,7 +1349,8 @@ static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth,
                                          const struct wpabuf *pi,
                                          size_t nonce_len,
                                          const u8 *r_pubkey_hash,
-                                         const u8 *i_pubkey_hash)
+                                         const u8 *i_pubkey_hash,
+                                         unsigned int neg_freq)
 {
        struct wpabuf *msg;
        u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1];
@@ -1362,6 +1363,8 @@ static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth,
        /* Build DPP Authentication Request frame attributes */
        attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) +
                4 + sizeof(wrapped_data);
+       if (neg_freq > 0)
+               attr_len += 4 + 2;
 #ifdef CONFIG_TESTING_OPTIONS
        if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ)
                attr_len += 4;
@@ -1393,6 +1396,25 @@ static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth,
                wpabuf_put_buf(msg, pi);
        }
 
+       /* Channel */
+       if (neg_freq > 0) {
+               u8 op_class, channel;
+
+               if (ieee80211_freq_to_channel_ext(neg_freq, 0, 0, &op_class,
+                                                 &channel) ==
+                   NUM_HOSTAPD_MODES) {
+                       wpa_printf(MSG_INFO,
+                                  "DPP: Unsupported negotiation frequency request: %d",
+                                  neg_freq);
+                       wpabuf_free(msg);
+                       return NULL;
+               }
+               wpabuf_put_le16(msg, DPP_ATTR_CHANNEL);
+               wpabuf_put_le16(msg, 2);
+               wpabuf_put_u8(msg, op_class);
+               wpabuf_put_u8(msg, channel);
+       }
+
 #ifdef CONFIG_TESTING_OPTIONS
        if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ) {
                wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
@@ -1668,7 +1690,8 @@ skip_wrapped_data:
 struct dpp_authentication * dpp_auth_init(void *msg_ctx,
                                          struct dpp_bootstrap_info *peer_bi,
                                          struct dpp_bootstrap_info *own_bi,
-                                         int configurator)
+                                         int configurator,
+                                         unsigned int neg_freq)
 {
        struct dpp_authentication *auth;
        size_t nonce_len;
@@ -1751,7 +1774,7 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx,
 #endif /* CONFIG_TESTING_OPTIONS */
 
        auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash,
-                                          i_pubkey_hash);
+                                          i_pubkey_hash, neg_freq);
        if (!auth->req_msg)
                goto fail;
 
@@ -2349,9 +2372,10 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
        size_t len[2];
        u8 *unwrapped = NULL;
        size_t unwrapped_len = 0;
-       const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap;
+       const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap,
+               *channel;
        u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len,
-               i_bootstrap_len;
+               i_bootstrap_len, channel_len;
        struct dpp_authentication *auth = NULL;
 
        wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
@@ -2374,6 +2398,34 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
        auth->curve = own_bi->curve;
        auth->curr_freq = freq;
 
+       channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL,
+                              &channel_len);
+       if (channel) {
+               int neg_freq;
+
+               if (channel_len < 2) {
+                       dpp_auth_fail(auth, "Too short Channel attribute");
+                       goto fail;
+               }
+
+               neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]);
+               wpa_printf(MSG_DEBUG,
+                          "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d",
+                          channel[0], channel[1], neg_freq);
+               if (neg_freq < 0) {
+                       dpp_auth_fail(auth,
+                                     "Unsupported Channel attribute value");
+                       goto fail;
+               }
+
+               if (auth->curr_freq != (unsigned int) neg_freq) {
+                       wpa_printf(MSG_DEBUG,
+                                  "DPP: Changing negotiation channel from %u MHz to %u MHz",
+                                  freq, neg_freq);
+                       auth->curr_freq = neg_freq;
+               }
+       }
+
        i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY,
                               &i_proto_len);
        if (!i_proto) {
index 905d1f138223bf26ad89e70a487cb0edb949da51..a86b5787bb58ab51d297273f6c5b8d77da67d00f 100644 (file)
@@ -52,6 +52,8 @@ enum dpp_attribute_id {
        DPP_ATTR_ENROLLEE_NONCE = 0x1014,
        DPP_ATTR_CODE_IDENTIFIER = 0x1015,
        DPP_ATTR_TRANSACTION_ID = 0x1016,
+       DPP_ATTR_BOOTSTRAP_INFO = 0x1017,
+       DPP_ATTR_CHANNEL = 0x1018,
        DPP_ATTR_TESTING = 0x10ff, /* not defined in the DPP tech spec */
 };
 
@@ -159,6 +161,7 @@ struct dpp_authentication {
        struct wpabuf *req_msg;
        struct wpabuf *resp_msg;
        unsigned int curr_freq;
+       unsigned int neg_freq;
        size_t secret_len;
        u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
        u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
@@ -260,7 +263,8 @@ char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
 struct dpp_authentication * dpp_auth_init(void *msg_ctx,
                                          struct dpp_bootstrap_info *peer_bi,
                                          struct dpp_bootstrap_info *own_bi,
-                                         int configurator);
+                                         int configurator,
+                                         unsigned int neg_freq);
 struct dpp_authentication *
 dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
                struct dpp_bootstrap_info *peer_bi,
index 874b90992883f487729deeb0ccccd88d31dc32ea..1d920b487c9252e399ef84ac09ff4b640f6c614e 100644 (file)
@@ -340,18 +340,32 @@ static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
                /* TODO: In case of DPP Authentication Request frame, move to
                 * the next channel immediately */
        }
+
+       if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
+           wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
+               wpa_printf(MSG_DEBUG,
+                          "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
+                          wpa_s->dpp_auth->curr_freq,
+                          wpa_s->dpp_auth->neg_freq);
+               offchannel_send_action_done(wpa_s);
+               wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
+       }
 }
 
 
 static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
 {
        struct wpa_supplicant *wpa_s = eloop_ctx;
+       unsigned int freq;
 
        if (!wpa_s->dpp_auth)
                return;
+       freq = wpa_s->dpp_auth->curr_freq;
+       if (wpa_s->dpp_auth->neg_freq > 0)
+               freq = wpa_s->dpp_auth->neg_freq;
        wpa_printf(MSG_DEBUG, "DPP: Continue reply wait on channel %u MHz",
-                  wpa_s->dpp_auth->curr_freq);
-       wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->curr_freq);
+                  freq);
+       wpas_dpp_listen_start(wpa_s, freq);
 }
 
 
@@ -510,6 +524,7 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
        int res;
        int configurator = 1;
        unsigned int wait_time;
+       unsigned int neg_freq = 0;
 
        wpa_s->dpp_gas_client = 0;
 
@@ -559,12 +574,17 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
                wpa_s->dpp_netrole_ap = os_strncmp(pos, "ap", 2) == 0;
        }
 
+       pos = os_strstr(cmd, " neg_freq=");
+       if (pos)
+               neg_freq = atoi(pos + 10);
+
        if (wpa_s->dpp_auth) {
                eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
                offchannel_send_action_done(wpa_s);
                dpp_auth_deinit(wpa_s->dpp_auth);
        }
-       wpa_s->dpp_auth = dpp_auth_init(wpa_s, peer_bi, own_bi, configurator);
+       wpa_s->dpp_auth = dpp_auth_init(wpa_s, peer_bi, own_bi, configurator,
+                                       neg_freq);
        if (!wpa_s->dpp_auth)
                goto fail;
        wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
@@ -577,6 +597,7 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
                wpa_s->dpp_auth->curr_freq = peer_bi->freq[0];
        else
                wpa_s->dpp_auth->curr_freq = 2412;
+       wpa_s->dpp_auth->neg_freq = neg_freq;
 
        if (is_zero_ether_addr(peer_bi->mac_addr)) {
                dst = broadcast;
@@ -593,6 +614,12 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
        eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
                               wpas_dpp_reply_wait_timeout,
                               wpa_s, NULL);
+       if (neg_freq > 0 && wpa_s->dpp_auth->curr_freq != neg_freq) {
+               wpa_printf(MSG_DEBUG,
+                          "DPP: Initiate on curr_freq %u MHz and move to neg_freq %u MHz for response",
+                          wpa_s->dpp_auth->curr_freq,
+                          wpa_s->dpp_auth->neg_freq);
+       }
        wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
                MAC2STR(dst), wpa_s->dpp_auth->curr_freq,
                DPP_PA_AUTHENTICATION_REQ);
@@ -864,6 +891,14 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
                                  wpa_s->dpp_configurator_params);
        os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
 
+       if (wpa_s->dpp_listen_freq &&
+           wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
+               wpa_printf(MSG_DEBUG,
+                          "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
+                          wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
+               wpas_dpp_listen_stop(wpa_s);
+       }
+
        wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
                MAC2STR(src), wpa_s->dpp_auth->curr_freq,
                DPP_PA_AUTHENTICATION_RESP);
@@ -1161,13 +1196,14 @@ static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
 
 
 static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
-                                 const u8 *hdr, const u8 *buf, size_t len)
+                                 const u8 *hdr, const u8 *buf, size_t len,
+                                 unsigned int freq)
 {
        struct dpp_authentication *auth = wpa_s->dpp_auth;
        struct wpabuf *msg;
 
-       wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
-                  MAC2STR(src));
+       wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
+                  " (freq %u MHz)", MAC2STR(src), freq);
 
        if (!auth) {
                wpa_printf(MSG_DEBUG,
@@ -1184,6 +1220,12 @@ static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
 
        eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
 
+       if (auth->curr_freq != freq && auth->neg_freq == freq) {
+               wpa_printf(MSG_DEBUG,
+                          "DPP: Responder accepted request for different negotiation channel");
+               auth->curr_freq = freq;
+       }
+
        msg = dpp_auth_resp_rx(auth, hdr, buf, len);
        if (!msg) {
                if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
@@ -1641,7 +1683,7 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
                wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
                break;
        case DPP_PA_AUTHENTICATION_RESP:
-               wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len);
+               wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
                break;
        case DPP_PA_AUTHENTICATION_CONF:
                wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);