DPP: Support multiple channels for initiating DPP Authentication
This extends wpa_supplicant to iterate over all available channels from the intersection of what the peer indicates and the local device supports when initiating DPP Authentication. In addition, retry DPP Authentication Request frame up to five times if no response is received. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
de02986189
commit
f97ace34cb
7 changed files with 307 additions and 48 deletions
|
@ -503,8 +503,9 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
|
|||
|
||||
if (hapd->dpp_auth)
|
||||
dpp_auth_deinit(hapd->dpp_auth);
|
||||
/* TODO: hw_modes */
|
||||
hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi,
|
||||
configurator, 0);
|
||||
configurator, 0, NULL, 0);
|
||||
if (!hapd->dpp_auth)
|
||||
goto fail;
|
||||
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
|
||||
|
@ -513,10 +514,6 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
|
|||
/* TODO: Support iteration over all frequencies and filtering of
|
||||
* frequencies based on locally enabled channels that allow initiation
|
||||
* of transmission. */
|
||||
if (peer_bi->num_freq > 0)
|
||||
hapd->dpp_auth->curr_freq = peer_bi->freq[0];
|
||||
else
|
||||
hapd->dpp_auth->curr_freq = 2412;
|
||||
|
||||
if (is_zero_ether_addr(peer_bi->mac_addr)) {
|
||||
dst = broadcast;
|
||||
|
|
169
src/common/dpp.c
169
src/common/dpp.c
|
@ -22,6 +22,7 @@
|
|||
#include "crypto/aes_siv.h"
|
||||
#include "crypto/sha384.h"
|
||||
#include "crypto/sha512.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "dpp.h"
|
||||
|
||||
|
||||
|
@ -1701,11 +1702,171 @@ skip_wrapped_data:
|
|||
}
|
||||
|
||||
|
||||
static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes,
|
||||
u16 num_modes, unsigned int freq)
|
||||
{
|
||||
u16 m;
|
||||
int c, flag;
|
||||
|
||||
if (!own_modes || !num_modes)
|
||||
return 1;
|
||||
|
||||
for (m = 0; m < num_modes; m++) {
|
||||
for (c = 0; c < own_modes[m].num_channels; c++) {
|
||||
if ((unsigned int) own_modes[m].channels[c].freq !=
|
||||
freq)
|
||||
continue;
|
||||
flag = own_modes[m].channels[c].flag;
|
||||
if (!(flag & (HOSTAPD_CHAN_DISABLED |
|
||||
HOSTAPD_CHAN_NO_IR |
|
||||
HOSTAPD_CHAN_RADAR)))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Peer channel %u MHz not supported", freq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int freq_included(const unsigned int freqs[], unsigned int num,
|
||||
unsigned int freq)
|
||||
{
|
||||
while (num > 0) {
|
||||
if (freqs[--num] == freq)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void freq_to_start(unsigned int freqs[], unsigned int num,
|
||||
unsigned int freq)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (freqs[i] == freq)
|
||||
break;
|
||||
}
|
||||
if (i == 0 || i >= num)
|
||||
return;
|
||||
os_memmove(&freqs[1], &freqs[0], i * sizeof(freqs[0]));
|
||||
freqs[0] = freq;
|
||||
}
|
||||
|
||||
|
||||
static int dpp_channel_intersect(struct dpp_authentication *auth,
|
||||
struct hostapd_hw_modes *own_modes,
|
||||
u16 num_modes)
|
||||
{
|
||||
struct dpp_bootstrap_info *peer_bi = auth->peer_bi;
|
||||
unsigned int i, freq;
|
||||
|
||||
for (i = 0; i < peer_bi->num_freq; i++) {
|
||||
freq = peer_bi->freq[i];
|
||||
if (freq_included(auth->freq, auth->num_freq, freq))
|
||||
continue;
|
||||
if (dpp_channel_ok_init(own_modes, num_modes, freq))
|
||||
auth->freq[auth->num_freq++] = freq;
|
||||
}
|
||||
if (!auth->num_freq) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"DPP: No available channels for initiating DPP Authentication");
|
||||
return -1;
|
||||
}
|
||||
auth->curr_freq = auth->freq[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dpp_channel_local_list(struct dpp_authentication *auth,
|
||||
struct hostapd_hw_modes *own_modes,
|
||||
u16 num_modes)
|
||||
{
|
||||
u16 m;
|
||||
int c, flag;
|
||||
unsigned int freq;
|
||||
|
||||
auth->num_freq = 0;
|
||||
|
||||
if (!own_modes || !num_modes) {
|
||||
auth->freq[0] = 2412;
|
||||
auth->freq[1] = 2437;
|
||||
auth->freq[2] = 2462;
|
||||
auth->num_freq = 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (m = 0; m < num_modes; m++) {
|
||||
for (c = 0; c < own_modes[m].num_channels; c++) {
|
||||
freq = own_modes[m].channels[c].freq;
|
||||
flag = own_modes[m].channels[c].flag;
|
||||
if (flag & (HOSTAPD_CHAN_DISABLED |
|
||||
HOSTAPD_CHAN_NO_IR |
|
||||
HOSTAPD_CHAN_RADAR))
|
||||
continue;
|
||||
if (freq_included(auth->freq, auth->num_freq, freq))
|
||||
continue;
|
||||
auth->freq[auth->num_freq++] = freq;
|
||||
if (auth->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
|
||||
m = num_modes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return auth->num_freq == 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static int dpp_prepare_channel_list(struct dpp_authentication *auth,
|
||||
struct hostapd_hw_modes *own_modes,
|
||||
u16 num_modes)
|
||||
{
|
||||
int res;
|
||||
char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end;
|
||||
unsigned int i;
|
||||
|
||||
if (auth->peer_bi->num_freq > 0)
|
||||
res = dpp_channel_intersect(auth, own_modes, num_modes);
|
||||
else
|
||||
res = dpp_channel_local_list(auth, own_modes, num_modes);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
/* Prioritize 2.4 GHz channels 6, 1, 11 (in this order) to hit the most
|
||||
* likely channels first. */
|
||||
freq_to_start(auth->freq, auth->num_freq, 2462);
|
||||
freq_to_start(auth->freq, auth->num_freq, 2412);
|
||||
freq_to_start(auth->freq, auth->num_freq, 2437);
|
||||
|
||||
auth->freq_idx = 0;
|
||||
auth->curr_freq = auth->freq[0];
|
||||
|
||||
pos = freqs;
|
||||
end = pos + sizeof(freqs);
|
||||
for (i = 0; i < auth->num_freq; i++) {
|
||||
res = os_snprintf(pos, end - pos, " %u", auth->freq[i]);
|
||||
if (os_snprintf_error(end - pos, res))
|
||||
break;
|
||||
pos += res;
|
||||
}
|
||||
*pos = '\0';
|
||||
wpa_printf(MSG_DEBUG, "DPP: Possible frequencies for initiating:%s",
|
||||
freqs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct dpp_authentication * dpp_auth_init(void *msg_ctx,
|
||||
struct dpp_bootstrap_info *peer_bi,
|
||||
struct dpp_bootstrap_info *own_bi,
|
||||
int configurator,
|
||||
unsigned int neg_freq)
|
||||
unsigned int neg_freq,
|
||||
struct hostapd_hw_modes *own_modes,
|
||||
u16 num_modes)
|
||||
{
|
||||
struct dpp_authentication *auth;
|
||||
size_t nonce_len;
|
||||
|
@ -1720,11 +1881,15 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx,
|
|||
return NULL;
|
||||
auth->msg_ctx = msg_ctx;
|
||||
auth->initiator = 1;
|
||||
auth->waiting_auth_resp = 1;
|
||||
auth->configurator = configurator;
|
||||
auth->peer_bi = peer_bi;
|
||||
auth->own_bi = own_bi;
|
||||
auth->curve = peer_bi->curve;
|
||||
|
||||
if (dpp_prepare_channel_list(auth, own_modes, num_modes) < 0)
|
||||
goto fail;
|
||||
|
||||
nonce_len = auth->curve->nonce_len;
|
||||
if (random_get_bytes(auth->i_nonce, nonce_len)) {
|
||||
wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce");
|
||||
|
@ -2910,6 +3075,8 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
|
|||
u8 r_auth2[DPP_MAX_HASH_LEN];
|
||||
u8 role;
|
||||
|
||||
auth->waiting_auth_resp = 0;
|
||||
|
||||
wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
|
||||
&wrapped_data_len);
|
||||
if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
|
||||
|
|
|
@ -167,8 +167,13 @@ struct dpp_authentication {
|
|||
EVP_PKEY *peer_protocol_key;
|
||||
struct wpabuf *req_msg;
|
||||
struct wpabuf *resp_msg;
|
||||
/* Intersection of possible frequencies for initiating DPP
|
||||
* Authentication exchange */
|
||||
unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
|
||||
unsigned int num_freq, freq_idx;
|
||||
unsigned int curr_freq;
|
||||
unsigned int neg_freq;
|
||||
unsigned int num_freq_iters;
|
||||
size_t secret_len;
|
||||
u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
|
||||
u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
|
||||
|
@ -177,6 +182,7 @@ struct dpp_authentication {
|
|||
u8 k2[DPP_MAX_HASH_LEN];
|
||||
u8 ke[DPP_MAX_HASH_LEN];
|
||||
int initiator;
|
||||
int waiting_auth_resp;
|
||||
int configurator;
|
||||
int remove_on_tx_status;
|
||||
int auth_success;
|
||||
|
@ -298,11 +304,14 @@ int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
|
|||
struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri);
|
||||
char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
|
||||
const u8 *privkey, size_t privkey_len);
|
||||
struct hostapd_hw_modes;
|
||||
struct dpp_authentication * dpp_auth_init(void *msg_ctx,
|
||||
struct dpp_bootstrap_info *peer_bi,
|
||||
struct dpp_bootstrap_info *own_bi,
|
||||
int configurator,
|
||||
unsigned int neg_freq);
|
||||
unsigned int neg_freq,
|
||||
struct hostapd_hw_modes *own_modes,
|
||||
u16 num_modes);
|
||||
struct dpp_authentication *
|
||||
dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
|
||||
struct dpp_bootstrap_info *peer_bi,
|
||||
|
|
|
@ -153,6 +153,7 @@ extern "C" {
|
|||
|
||||
/* DPP events */
|
||||
#define DPP_EVENT_AUTH_SUCCESS "DPP-AUTH-SUCCESS "
|
||||
#define DPP_EVENT_AUTH_INIT_FAILED "DPP-AUTH-INIT-FAILED "
|
||||
#define DPP_EVENT_NOT_COMPATIBLE "DPP-NOT-COMPATIBLE "
|
||||
#define DPP_EVENT_RESPONSE_PENDING "DPP-RESPONSE-PENDING "
|
||||
#define DPP_EVENT_SCAN_PEER_QR_CODE "DPP-SCAN-PEER-QR-CODE "
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue