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];
/* 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;
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");
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;
#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;
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,
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) {
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 */
};
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];
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,
/* 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);
}
int res;
int configurator = 1;
unsigned int wait_time;
+ unsigned int neg_freq = 0;
wpa_s->dpp_gas_client = 0;
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);
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;
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);
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);
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,
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) {
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);