DPP: Common configurator/bootstrapping data management
Merge the practically copy-pasted implementations in wpa_supplicant and hostapd into a single shared implementation in dpp.c for managing configurator and boostrapping information. This avoid unnecessary code duplication and provides a convenient location for adding new global DPP data. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
74cb18c6b0
commit
87d8435cf9
14 changed files with 585 additions and 884 deletions
|
@ -3270,7 +3270,7 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
}
|
}
|
||||||
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
|
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
|
||||||
res = hostapd_dpp_bootstrap_gen(hapd, buf + 18);
|
res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -3279,12 +3279,14 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
}
|
}
|
||||||
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
|
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
|
||||||
if (hostapd_dpp_bootstrap_remove(hapd, buf + 21) < 0)
|
if (dpp_bootstrap_remove(hapd->iface->interfaces->dpp,
|
||||||
|
buf + 21) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
|
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
|
||||||
const char *uri;
|
const char *uri;
|
||||||
|
|
||||||
uri = hostapd_dpp_bootstrap_get_uri(hapd, atoi(buf + 22));
|
uri = dpp_bootstrap_get_uri(hapd->iface->interfaces->dpp,
|
||||||
|
atoi(buf + 22));
|
||||||
if (!uri) {
|
if (!uri) {
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -3293,8 +3295,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
}
|
}
|
||||||
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
|
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
|
||||||
reply_len = hostapd_dpp_bootstrap_info(hapd, atoi(buf + 19),
|
reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp,
|
||||||
reply, reply_size);
|
atoi(buf + 19),
|
||||||
|
reply, reply_size);
|
||||||
} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
|
} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
|
||||||
if (hostapd_dpp_auth_init(hapd, buf + 13) < 0)
|
if (hostapd_dpp_auth_init(hapd, buf + 13) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
@ -3305,7 +3308,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
||||||
hostapd_dpp_stop(hapd);
|
hostapd_dpp_stop(hapd);
|
||||||
hostapd_dpp_listen_stop(hapd);
|
hostapd_dpp_listen_stop(hapd);
|
||||||
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
|
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
|
||||||
res = hostapd_dpp_configurator_add(hapd, buf + 20);
|
res = dpp_configurator_add(hapd->iface->interfaces->dpp,
|
||||||
|
buf + 20);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -3314,15 +3318,17 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
}
|
}
|
||||||
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
|
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
|
||||||
if (hostapd_dpp_configurator_remove(hapd, buf + 24) < 0)
|
if (dpp_configurator_remove(hapd->iface->interfaces->dpp,
|
||||||
|
buf + 24) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
|
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
|
||||||
if (hostapd_dpp_configurator_sign(hapd, buf + 21) < 0)
|
if (hostapd_dpp_configurator_sign(hapd, buf + 21) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
|
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
|
||||||
reply_len = hostapd_dpp_configurator_get_key(hapd,
|
reply_len = dpp_configurator_get_key_id(
|
||||||
atoi(buf + 25),
|
hapd->iface->interfaces->dpp,
|
||||||
reply, reply_size);
|
atoi(buf + 25),
|
||||||
|
reply, reply_size);
|
||||||
} else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
|
} else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
|
||||||
res = hostapd_dpp_pkex_add(hapd, buf + 12);
|
res = hostapd_dpp_pkex_add(hapd, buf + 12);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
@ -3824,7 +3830,7 @@ static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
hostapd_dpp_deinit_global(interfaces);
|
dpp_global_clear(interfaces->dpp);
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "crypto/random.h"
|
#include "crypto/random.h"
|
||||||
#include "crypto/tls.h"
|
#include "crypto/tls.h"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
|
#include "common/dpp.h"
|
||||||
#include "drivers/driver.h"
|
#include "drivers/driver.h"
|
||||||
#include "eap_server/eap.h"
|
#include "eap_server/eap.h"
|
||||||
#include "eap_server/tncs.h"
|
#include "eap_server/tncs.h"
|
||||||
|
@ -671,7 +672,9 @@ int main(int argc, char *argv[])
|
||||||
dl_list_init(&interfaces.eth_p_oui);
|
dl_list_init(&interfaces.eth_p_oui);
|
||||||
#endif /* CONFIG_ETH_P_OUI */
|
#endif /* CONFIG_ETH_P_OUI */
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
hostapd_dpp_init_global(&interfaces);
|
interfaces.dpp = dpp_global_init();
|
||||||
|
if (!interfaces.dpp)
|
||||||
|
return -1;
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -901,7 +904,7 @@ int main(int argc, char *argv[])
|
||||||
os_free(interfaces.iface);
|
os_free(interfaces.iface);
|
||||||
|
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
hostapd_dpp_deinit_global(&interfaces);
|
dpp_global_deinit(interfaces.dpp);
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
|
|
||||||
if (interfaces.eloop_initialized)
|
if (interfaces.eloop_initialized)
|
||||||
|
|
|
@ -28,34 +28,6 @@ static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
|
||||||
static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
|
||||||
|
|
||||||
static struct dpp_configurator *
|
|
||||||
hostapd_dpp_configurator_get_id(struct hostapd_data *hapd, unsigned int id)
|
|
||||||
{
|
|
||||||
struct dpp_configurator *conf;
|
|
||||||
|
|
||||||
dl_list_for_each(conf, &hapd->iface->interfaces->dpp_configurator,
|
|
||||||
struct dpp_configurator, list) {
|
|
||||||
if (conf->id == id)
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned int hapd_dpp_next_id(struct hostapd_data *hapd)
|
|
||||||
{
|
|
||||||
struct dpp_bootstrap_info *bi;
|
|
||||||
unsigned int max_id = 0;
|
|
||||||
|
|
||||||
dl_list_for_each(bi, &hapd->iface->interfaces->dpp_bootstrap,
|
|
||||||
struct dpp_bootstrap_info, list) {
|
|
||||||
if (bi->id > max_id)
|
|
||||||
max_id = bi->id;
|
|
||||||
}
|
|
||||||
return max_id + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
|
* hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
|
||||||
* @hapd: Pointer to hostapd_data
|
* @hapd: Pointer to hostapd_data
|
||||||
|
@ -67,13 +39,10 @@ int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
|
||||||
struct dpp_bootstrap_info *bi;
|
struct dpp_bootstrap_info *bi;
|
||||||
struct dpp_authentication *auth = hapd->dpp_auth;
|
struct dpp_authentication *auth = hapd->dpp_auth;
|
||||||
|
|
||||||
bi = dpp_parse_qr_code(cmd);
|
bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd);
|
||||||
if (!bi)
|
if (!bi)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
bi->id = hapd_dpp_next_id(hapd);
|
|
||||||
dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
|
|
||||||
|
|
||||||
if (auth && auth->response_pending &&
|
if (auth && auth->response_pending &&
|
||||||
dpp_notify_new_qr_code(auth, bi) == 1) {
|
dpp_notify_new_qr_code(auth, bi) == 1) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
|
@ -92,195 +61,6 @@ int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char * get_param(const char *cmd, const char *param)
|
|
||||||
{
|
|
||||||
const char *pos, *end;
|
|
||||||
char *val;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
pos = os_strstr(cmd, param);
|
|
||||||
if (!pos)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
pos += os_strlen(param);
|
|
||||||
end = os_strchr(pos, ' ');
|
|
||||||
if (end)
|
|
||||||
len = end - pos;
|
|
||||||
else
|
|
||||||
len = os_strlen(pos);
|
|
||||||
val = os_malloc(len + 1);
|
|
||||||
if (!val)
|
|
||||||
return NULL;
|
|
||||||
os_memcpy(val, pos, len);
|
|
||||||
val[len] = '\0';
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int hostapd_dpp_bootstrap_gen(struct hostapd_data *hapd, const char *cmd)
|
|
||||||
{
|
|
||||||
char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
|
|
||||||
char *key = NULL;
|
|
||||||
u8 *privkey = NULL;
|
|
||||||
size_t privkey_len = 0;
|
|
||||||
size_t len;
|
|
||||||
int ret = -1;
|
|
||||||
struct dpp_bootstrap_info *bi;
|
|
||||||
|
|
||||||
bi = os_zalloc(sizeof(*bi));
|
|
||||||
if (!bi)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (os_strstr(cmd, "type=qrcode"))
|
|
||||||
bi->type = DPP_BOOTSTRAP_QR_CODE;
|
|
||||||
else if (os_strstr(cmd, "type=pkex"))
|
|
||||||
bi->type = DPP_BOOTSTRAP_PKEX;
|
|
||||||
else
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
chan = get_param(cmd, " chan=");
|
|
||||||
mac = get_param(cmd, " mac=");
|
|
||||||
info = get_param(cmd, " info=");
|
|
||||||
curve = get_param(cmd, " curve=");
|
|
||||||
key = get_param(cmd, " key=");
|
|
||||||
|
|
||||||
if (key) {
|
|
||||||
privkey_len = os_strlen(key) / 2;
|
|
||||||
privkey = os_malloc(privkey_len);
|
|
||||||
if (!privkey ||
|
|
||||||
hexstr2bin(key, privkey, privkey_len) < 0)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
pk = dpp_keygen(bi, curve, privkey, privkey_len);
|
|
||||||
if (!pk)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
len = 4; /* "DPP:" */
|
|
||||||
if (chan) {
|
|
||||||
if (dpp_parse_uri_chan_list(bi, chan) < 0)
|
|
||||||
goto fail;
|
|
||||||
len += 3 + os_strlen(chan); /* C:...; */
|
|
||||||
}
|
|
||||||
if (mac) {
|
|
||||||
if (dpp_parse_uri_mac(bi, mac) < 0)
|
|
||||||
goto fail;
|
|
||||||
len += 3 + os_strlen(mac); /* M:...; */
|
|
||||||
}
|
|
||||||
if (info) {
|
|
||||||
if (dpp_parse_uri_info(bi, info) < 0)
|
|
||||||
goto fail;
|
|
||||||
len += 3 + os_strlen(info); /* I:...; */
|
|
||||||
}
|
|
||||||
len += 4 + os_strlen(pk);
|
|
||||||
bi->uri = os_malloc(len + 1);
|
|
||||||
if (!bi->uri)
|
|
||||||
goto fail;
|
|
||||||
os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
|
|
||||||
chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
|
|
||||||
mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
|
|
||||||
info ? "I:" : "", info ? info : "", info ? ";" : "",
|
|
||||||
pk);
|
|
||||||
bi->id = hapd_dpp_next_id(hapd);
|
|
||||||
dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
|
|
||||||
ret = bi->id;
|
|
||||||
bi = NULL;
|
|
||||||
fail:
|
|
||||||
os_free(curve);
|
|
||||||
os_free(pk);
|
|
||||||
os_free(chan);
|
|
||||||
os_free(mac);
|
|
||||||
os_free(info);
|
|
||||||
str_clear_free(key);
|
|
||||||
bin_clear_free(privkey, privkey_len);
|
|
||||||
dpp_bootstrap_info_free(bi);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct dpp_bootstrap_info *
|
|
||||||
dpp_bootstrap_get_id(struct hostapd_data *hapd, unsigned int id)
|
|
||||||
{
|
|
||||||
struct dpp_bootstrap_info *bi;
|
|
||||||
|
|
||||||
dl_list_for_each(bi, &hapd->iface->interfaces->dpp_bootstrap,
|
|
||||||
struct dpp_bootstrap_info, list) {
|
|
||||||
if (bi->id == id)
|
|
||||||
return bi;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int dpp_bootstrap_del(struct hapd_interfaces *ifaces, unsigned int id)
|
|
||||||
{
|
|
||||||
struct dpp_bootstrap_info *bi, *tmp;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
dl_list_for_each_safe(bi, tmp, &ifaces->dpp_bootstrap,
|
|
||||||
struct dpp_bootstrap_info, list) {
|
|
||||||
if (id && bi->id != id)
|
|
||||||
continue;
|
|
||||||
found = 1;
|
|
||||||
dl_list_del(&bi->list);
|
|
||||||
dpp_bootstrap_info_free(bi);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == 0)
|
|
||||||
return 0; /* flush succeeds regardless of entries found */
|
|
||||||
return found ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int hostapd_dpp_bootstrap_remove(struct hostapd_data *hapd, const char *id)
|
|
||||||
{
|
|
||||||
unsigned int id_val;
|
|
||||||
|
|
||||||
if (os_strcmp(id, "*") == 0) {
|
|
||||||
id_val = 0;
|
|
||||||
} else {
|
|
||||||
id_val = atoi(id);
|
|
||||||
if (id_val == 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dpp_bootstrap_del(hapd->iface->interfaces, id_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char * hostapd_dpp_bootstrap_get_uri(struct hostapd_data *hapd,
|
|
||||||
unsigned int id)
|
|
||||||
{
|
|
||||||
struct dpp_bootstrap_info *bi;
|
|
||||||
|
|
||||||
bi = dpp_bootstrap_get_id(hapd, id);
|
|
||||||
if (!bi)
|
|
||||||
return NULL;
|
|
||||||
return bi->uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int hostapd_dpp_bootstrap_info(struct hostapd_data *hapd, int id,
|
|
||||||
char *reply, int reply_size)
|
|
||||||
{
|
|
||||||
struct dpp_bootstrap_info *bi;
|
|
||||||
|
|
||||||
bi = dpp_bootstrap_get_id(hapd, id);
|
|
||||||
if (!bi)
|
|
||||||
return -1;
|
|
||||||
return os_snprintf(reply, reply_size, "type=%s\n"
|
|
||||||
"mac_addr=" MACSTR "\n"
|
|
||||||
"info=%s\n"
|
|
||||||
"num_freq=%u\n"
|
|
||||||
"curve=%s\n",
|
|
||||||
dpp_bootstrap_type_txt(bi->type),
|
|
||||||
MAC2STR(bi->mac_addr),
|
|
||||||
bi->info ? bi->info : "",
|
|
||||||
bi->num_freq,
|
|
||||||
bi->curve->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -515,38 +295,6 @@ static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_dpp_set_configurator(struct hostapd_data *hapd,
|
|
||||||
struct dpp_authentication *auth,
|
|
||||||
const char *cmd)
|
|
||||||
{
|
|
||||||
const char *pos;
|
|
||||||
|
|
||||||
if (!cmd)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
|
|
||||||
|
|
||||||
pos = os_strstr(cmd, " configurator=");
|
|
||||||
if (pos) {
|
|
||||||
auth->configurator = 1;
|
|
||||||
pos += 14;
|
|
||||||
auth->conf = hostapd_dpp_configurator_get_id(hapd, atoi(pos));
|
|
||||||
if (!auth->conf) {
|
|
||||||
wpa_printf(MSG_INFO,
|
|
||||||
"DPP: Could not find the specified configurator");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dpp_configuration_parse(auth, cmd) < 0) {
|
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
|
||||||
"DPP: Failed to set configurator parameters");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
|
static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = eloop_ctx;
|
struct hostapd_data *hapd = eloop_ctx;
|
||||||
|
@ -656,7 +404,7 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
|
||||||
if (!pos)
|
if (!pos)
|
||||||
return -1;
|
return -1;
|
||||||
pos += 6;
|
pos += 6;
|
||||||
peer_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
|
peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
|
||||||
if (!peer_bi) {
|
if (!peer_bi) {
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"DPP: Could not find bootstrapping info for the identified peer");
|
"DPP: Could not find bootstrapping info for the identified peer");
|
||||||
|
@ -666,7 +414,8 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
|
||||||
pos = os_strstr(cmd, " own=");
|
pos = os_strstr(cmd, " own=");
|
||||||
if (pos) {
|
if (pos) {
|
||||||
pos += 5;
|
pos += 5;
|
||||||
own_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
|
own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
|
||||||
|
atoi(pos));
|
||||||
if (!own_bi) {
|
if (!own_bi) {
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"DPP: Could not find bootstrapping info for the identified local entry");
|
"DPP: Could not find bootstrapping info for the identified local entry");
|
||||||
|
@ -716,7 +465,8 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
|
||||||
if (!hapd->dpp_auth)
|
if (!hapd->dpp_auth)
|
||||||
goto fail;
|
goto fail;
|
||||||
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
|
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
|
||||||
if (hostapd_dpp_set_configurator(hapd, hapd->dpp_auth, cmd) < 0) {
|
if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
||||||
|
hapd->dpp_auth, cmd) < 0) {
|
||||||
dpp_auth_deinit(hapd->dpp_auth);
|
dpp_auth_deinit(hapd->dpp_auth);
|
||||||
hapd->dpp_auth = NULL;
|
hapd->dpp_auth = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -775,7 +525,10 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
|
||||||
{
|
{
|
||||||
const u8 *r_bootstrap, *i_bootstrap;
|
const u8 *r_bootstrap, *i_bootstrap;
|
||||||
u16 r_bootstrap_len, i_bootstrap_len;
|
u16 r_bootstrap_len, i_bootstrap_len;
|
||||||
struct dpp_bootstrap_info *bi, *own_bi = NULL, *peer_bi = NULL;
|
struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
|
||||||
|
|
||||||
|
if (!hapd->iface->interfaces->dpp)
|
||||||
|
return;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
|
wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
|
||||||
MAC2STR(src));
|
MAC2STR(src));
|
||||||
|
@ -802,28 +555,8 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
|
||||||
|
|
||||||
/* Try to find own and peer bootstrapping key matches based on the
|
/* Try to find own and peer bootstrapping key matches based on the
|
||||||
* received hash values */
|
* received hash values */
|
||||||
dl_list_for_each(bi, &hapd->iface->interfaces->dpp_bootstrap,
|
dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
|
||||||
struct dpp_bootstrap_info, list) {
|
r_bootstrap, &own_bi, &peer_bi);
|
||||||
if (!own_bi && bi->own &&
|
|
||||||
os_memcmp(bi->pubkey_hash, r_bootstrap,
|
|
||||||
SHA256_MAC_LEN) == 0) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"DPP: Found matching own bootstrapping information");
|
|
||||||
own_bi = bi;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!peer_bi && !bi->own &&
|
|
||||||
os_memcmp(bi->pubkey_hash, i_bootstrap,
|
|
||||||
SHA256_MAC_LEN) == 0) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"DPP: Found matching peer bootstrapping information");
|
|
||||||
peer_bi = bi;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (own_bi && peer_bi)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!own_bi) {
|
if (!own_bi) {
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
|
||||||
"No matching own bootstrapping key found - ignore message");
|
"No matching own bootstrapping key found - ignore message");
|
||||||
|
@ -845,8 +578,9 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
|
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
|
||||||
if (hostapd_dpp_set_configurator(hapd, hapd->dpp_auth,
|
if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
||||||
hapd->dpp_configurator_params) < 0) {
|
hapd->dpp_auth,
|
||||||
|
hapd->dpp_configurator_params) < 0) {
|
||||||
dpp_auth_deinit(hapd->dpp_auth);
|
dpp_auth_deinit(hapd->dpp_auth);
|
||||||
hapd->dpp_auth = NULL;
|
hapd->dpp_auth = NULL;
|
||||||
return;
|
return;
|
||||||
|
@ -1553,24 +1287,10 @@ hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
|
||||||
wpabuf_head(msg), wpabuf_len(msg));
|
wpabuf_head(msg), wpabuf_len(msg));
|
||||||
wpabuf_free(msg);
|
wpabuf_free(msg);
|
||||||
|
|
||||||
bi = os_zalloc(sizeof(*bi));
|
bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
|
||||||
if (!bi)
|
if (!bi)
|
||||||
return;
|
return;
|
||||||
bi->id = hapd_dpp_next_id(hapd);
|
|
||||||
bi->type = DPP_BOOTSTRAP_PKEX;
|
|
||||||
os_memcpy(bi->mac_addr, src, ETH_ALEN);
|
|
||||||
bi->num_freq = 1;
|
|
||||||
bi->freq[0] = freq;
|
|
||||||
bi->curve = pkex->own_bi->curve;
|
|
||||||
bi->pubkey = pkex->peer_bootstrap_key;
|
|
||||||
pkex->peer_bootstrap_key = NULL;
|
|
||||||
dpp_pkex_free(pkex);
|
|
||||||
hapd->dpp_pkex = NULL;
|
hapd->dpp_pkex = NULL;
|
||||||
if (dpp_bootstrap_key_hash(bi) < 0) {
|
|
||||||
dpp_bootstrap_info_free(bi);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1580,7 +1300,7 @@ hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
|
||||||
unsigned int freq)
|
unsigned int freq)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
struct dpp_bootstrap_info *bi, *own_bi;
|
struct dpp_bootstrap_info *bi;
|
||||||
struct dpp_pkex *pkex = hapd->dpp_pkex;
|
struct dpp_pkex *pkex = hapd->dpp_pkex;
|
||||||
char cmd[500];
|
char cmd[500];
|
||||||
|
|
||||||
|
@ -1598,26 +1318,10 @@ hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
own_bi = pkex->own_bi;
|
bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
|
||||||
|
|
||||||
bi = os_zalloc(sizeof(*bi));
|
|
||||||
if (!bi)
|
if (!bi)
|
||||||
return;
|
return;
|
||||||
bi->id = hapd_dpp_next_id(hapd);
|
|
||||||
bi->type = DPP_BOOTSTRAP_PKEX;
|
|
||||||
os_memcpy(bi->mac_addr, src, ETH_ALEN);
|
|
||||||
bi->num_freq = 1;
|
|
||||||
bi->freq[0] = freq;
|
|
||||||
bi->curve = own_bi->curve;
|
|
||||||
bi->pubkey = pkex->peer_bootstrap_key;
|
|
||||||
pkex->peer_bootstrap_key = NULL;
|
|
||||||
dpp_pkex_free(pkex);
|
|
||||||
hapd->dpp_pkex = NULL;
|
hapd->dpp_pkex = NULL;
|
||||||
if (dpp_bootstrap_key_hash(bi) < 0) {
|
|
||||||
dpp_bootstrap_info_free(bi);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
|
|
||||||
|
|
||||||
os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
|
os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
|
||||||
bi->id,
|
bi->id,
|
||||||
|
@ -1785,93 +1489,6 @@ void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned int hostapd_dpp_next_configurator_id(struct hostapd_data *hapd)
|
|
||||||
{
|
|
||||||
struct dpp_configurator *conf;
|
|
||||||
unsigned int max_id = 0;
|
|
||||||
|
|
||||||
dl_list_for_each(conf, &hapd->iface->interfaces->dpp_configurator,
|
|
||||||
struct dpp_configurator, list) {
|
|
||||||
if (conf->id > max_id)
|
|
||||||
max_id = conf->id;
|
|
||||||
}
|
|
||||||
return max_id + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int hostapd_dpp_configurator_add(struct hostapd_data *hapd, const char *cmd)
|
|
||||||
{
|
|
||||||
char *curve = NULL;
|
|
||||||
char *key = NULL;
|
|
||||||
u8 *privkey = NULL;
|
|
||||||
size_t privkey_len = 0;
|
|
||||||
int ret = -1;
|
|
||||||
struct dpp_configurator *conf = NULL;
|
|
||||||
|
|
||||||
curve = get_param(cmd, " curve=");
|
|
||||||
key = get_param(cmd, " key=");
|
|
||||||
|
|
||||||
if (key) {
|
|
||||||
privkey_len = os_strlen(key) / 2;
|
|
||||||
privkey = os_malloc(privkey_len);
|
|
||||||
if (!privkey ||
|
|
||||||
hexstr2bin(key, privkey, privkey_len) < 0)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
conf = dpp_keygen_configurator(curve, privkey, privkey_len);
|
|
||||||
if (!conf)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
conf->id = hostapd_dpp_next_configurator_id(hapd);
|
|
||||||
dl_list_add(&hapd->iface->interfaces->dpp_configurator, &conf->list);
|
|
||||||
ret = conf->id;
|
|
||||||
conf = NULL;
|
|
||||||
fail:
|
|
||||||
os_free(curve);
|
|
||||||
str_clear_free(key);
|
|
||||||
bin_clear_free(privkey, privkey_len);
|
|
||||||
dpp_configurator_free(conf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int dpp_configurator_del(struct hapd_interfaces *ifaces, unsigned int id)
|
|
||||||
{
|
|
||||||
struct dpp_configurator *conf, *tmp;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
dl_list_for_each_safe(conf, tmp, &ifaces->dpp_configurator,
|
|
||||||
struct dpp_configurator, list) {
|
|
||||||
if (id && conf->id != id)
|
|
||||||
continue;
|
|
||||||
found = 1;
|
|
||||||
dl_list_del(&conf->list);
|
|
||||||
dpp_configurator_free(conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == 0)
|
|
||||||
return 0; /* flush succeeds regardless of entries found */
|
|
||||||
return found ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int hostapd_dpp_configurator_remove(struct hostapd_data *hapd, const char *id)
|
|
||||||
{
|
|
||||||
unsigned int id_val;
|
|
||||||
|
|
||||||
if (os_strcmp(id, "*") == 0) {
|
|
||||||
id_val = 0;
|
|
||||||
} else {
|
|
||||||
id_val = atoi(id);
|
|
||||||
if (id_val == 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dpp_configurator_del(hapd->iface->interfaces, id_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
|
int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
|
||||||
{
|
{
|
||||||
struct dpp_authentication *auth;
|
struct dpp_authentication *auth;
|
||||||
|
@ -1884,7 +1501,8 @@ int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
|
||||||
|
|
||||||
curve = get_param(cmd, " curve=");
|
curve = get_param(cmd, " curve=");
|
||||||
hostapd_dpp_set_testing_options(hapd, auth);
|
hostapd_dpp_set_testing_options(hapd, auth);
|
||||||
if (hostapd_dpp_set_configurator(hapd, auth, cmd) == 0 &&
|
if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
||||||
|
auth, cmd) == 0 &&
|
||||||
dpp_configurator_own_config(auth, curve, 1) == 0) {
|
dpp_configurator_own_config(auth, curve, 1) == 0) {
|
||||||
hostapd_dpp_handle_config_obj(hapd, auth);
|
hostapd_dpp_handle_config_obj(hapd, auth);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -1897,19 +1515,6 @@ int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int hostapd_dpp_configurator_get_key(struct hostapd_data *hapd, unsigned int id,
|
|
||||||
char *buf, size_t buflen)
|
|
||||||
{
|
|
||||||
struct dpp_configurator *conf;
|
|
||||||
|
|
||||||
conf = hostapd_dpp_configurator_get_id(hapd, id);
|
|
||||||
if (!conf)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return dpp_configurator_get_key(conf, buf, buflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
|
int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
|
||||||
{
|
{
|
||||||
struct dpp_bootstrap_info *own_bi;
|
struct dpp_bootstrap_info *own_bi;
|
||||||
|
@ -1919,7 +1524,7 @@ int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
|
||||||
if (!pos)
|
if (!pos)
|
||||||
return -1;
|
return -1;
|
||||||
pos += 5;
|
pos += 5;
|
||||||
own_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
|
own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
|
||||||
if (!own_bi) {
|
if (!own_bi) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"DPP: Identified bootstrap info not found");
|
"DPP: Identified bootstrap info not found");
|
||||||
|
@ -2060,20 +1665,3 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
|
||||||
os_free(hapd->dpp_configurator_params);
|
os_free(hapd->dpp_configurator_params);
|
||||||
hapd->dpp_configurator_params = NULL;
|
hapd->dpp_configurator_params = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void hostapd_dpp_init_global(struct hapd_interfaces *ifaces)
|
|
||||||
{
|
|
||||||
dl_list_init(&ifaces->dpp_bootstrap);
|
|
||||||
dl_list_init(&ifaces->dpp_configurator);
|
|
||||||
ifaces->dpp_init_done = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void hostapd_dpp_deinit_global(struct hapd_interfaces *ifaces)
|
|
||||||
{
|
|
||||||
if (!ifaces->dpp_init_done)
|
|
||||||
return;
|
|
||||||
dpp_bootstrap_del(ifaces, 0);
|
|
||||||
dpp_configurator_del(ifaces, 0);
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,12 +10,6 @@
|
||||||
#define DPP_HOSTAPD_H
|
#define DPP_HOSTAPD_H
|
||||||
|
|
||||||
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_bootstrap_gen(struct hostapd_data *hapd, const char *cmd);
|
|
||||||
int hostapd_dpp_bootstrap_remove(struct hostapd_data *hapd, const char *id);
|
|
||||||
const char * hostapd_dpp_bootstrap_get_uri(struct hostapd_data *hapd,
|
|
||||||
unsigned int id);
|
|
||||||
int hostapd_dpp_bootstrap_info(struct hostapd_data *hapd, int id,
|
|
||||||
char *reply, int reply_size);
|
|
||||||
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);
|
||||||
|
|
|
@ -66,9 +66,7 @@ struct hapd_interfaces {
|
||||||
int eloop_initialized;
|
int eloop_initialized;
|
||||||
|
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
int dpp_init_done;
|
struct dpp_global *dpp;
|
||||||
struct dl_list dpp_bootstrap; /* struct dpp_bootstrap_info */
|
|
||||||
struct dl_list dpp_configurator; /* struct dpp_configurator */
|
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
456
src/common/dpp.c
456
src/common/dpp.c
|
@ -69,6 +69,11 @@ static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct dpp_global {
|
||||||
|
struct dl_list bootstrap; /* struct dpp_bootstrap_info */
|
||||||
|
struct dl_list configurator; /* struct dpp_configurator */
|
||||||
|
};
|
||||||
|
|
||||||
static const struct dpp_curve_params dpp_curves[] = {
|
static const struct dpp_curve_params dpp_curves[] = {
|
||||||
/* The mandatory to support and the default NIST P-256 curve needs to
|
/* The mandatory to support and the default NIST P-256 curve needs to
|
||||||
* be the first entry on this list. */
|
* be the first entry on this list. */
|
||||||
|
@ -4151,7 +4156,8 @@ void dpp_configuration_free(struct dpp_configuration *conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int dpp_configuration_parse(struct dpp_authentication *auth, const char *cmd)
|
static int dpp_configuration_parse(struct dpp_authentication *auth,
|
||||||
|
const char *cmd)
|
||||||
{
|
{
|
||||||
const char *pos, *end;
|
const char *pos, *end;
|
||||||
struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
|
struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
|
||||||
|
@ -4258,6 +4264,54 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct dpp_configurator *
|
||||||
|
dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id)
|
||||||
|
{
|
||||||
|
struct dpp_configurator *conf;
|
||||||
|
|
||||||
|
if (!dpp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dl_list_for_each(conf, &dpp->configurator,
|
||||||
|
struct dpp_configurator, list) {
|
||||||
|
if (conf->id == id)
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx,
|
||||||
|
struct dpp_authentication *auth,
|
||||||
|
const char *cmd)
|
||||||
|
{
|
||||||
|
const char *pos;
|
||||||
|
|
||||||
|
if (!cmd)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
|
||||||
|
|
||||||
|
pos = os_strstr(cmd, " configurator=");
|
||||||
|
if (pos) {
|
||||||
|
pos += 14;
|
||||||
|
auth->conf = dpp_configurator_get_id(dpp, atoi(pos));
|
||||||
|
if (!auth->conf) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"DPP: Could not find the specified configurator");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dpp_configuration_parse(auth, cmd) < 0) {
|
||||||
|
wpa_msg(msg_ctx, MSG_INFO,
|
||||||
|
"DPP: Failed to set configurator parameters");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dpp_auth_deinit(struct dpp_authentication *auth)
|
void dpp_auth_deinit(struct dpp_authentication *auth)
|
||||||
{
|
{
|
||||||
if (!auth)
|
if (!auth)
|
||||||
|
@ -8215,3 +8269,403 @@ void dpp_pfs_free(struct dpp_pfs *pfs)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int dpp_next_id(struct dpp_global *dpp)
|
||||||
|
{
|
||||||
|
struct dpp_bootstrap_info *bi;
|
||||||
|
unsigned int max_id = 0;
|
||||||
|
|
||||||
|
dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
|
||||||
|
if (bi->id > max_id)
|
||||||
|
max_id = bi->id;
|
||||||
|
}
|
||||||
|
return max_id + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id)
|
||||||
|
{
|
||||||
|
struct dpp_bootstrap_info *bi, *tmp;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
if (!dpp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dl_list_for_each_safe(bi, tmp, &dpp->bootstrap,
|
||||||
|
struct dpp_bootstrap_info, list) {
|
||||||
|
if (id && bi->id != id)
|
||||||
|
continue;
|
||||||
|
found = 1;
|
||||||
|
dl_list_del(&bi->list);
|
||||||
|
dpp_bootstrap_info_free(bi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id == 0)
|
||||||
|
return 0; /* flush succeeds regardless of entries found */
|
||||||
|
return found ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
|
||||||
|
const char *uri)
|
||||||
|
{
|
||||||
|
struct dpp_bootstrap_info *bi;
|
||||||
|
|
||||||
|
if (!dpp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
bi = dpp_parse_qr_code(uri);
|
||||||
|
if (!bi)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
bi->id = dpp_next_id(dpp);
|
||||||
|
dl_list_add(&dpp->bootstrap, &bi->list);
|
||||||
|
return bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
|
||||||
|
{
|
||||||
|
char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
|
||||||
|
char *key = NULL;
|
||||||
|
u8 *privkey = NULL;
|
||||||
|
size_t privkey_len = 0;
|
||||||
|
size_t len;
|
||||||
|
int ret = -1;
|
||||||
|
struct dpp_bootstrap_info *bi;
|
||||||
|
|
||||||
|
if (!dpp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bi = os_zalloc(sizeof(*bi));
|
||||||
|
if (!bi)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (os_strstr(cmd, "type=qrcode"))
|
||||||
|
bi->type = DPP_BOOTSTRAP_QR_CODE;
|
||||||
|
else if (os_strstr(cmd, "type=pkex"))
|
||||||
|
bi->type = DPP_BOOTSTRAP_PKEX;
|
||||||
|
else
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
chan = get_param(cmd, " chan=");
|
||||||
|
mac = get_param(cmd, " mac=");
|
||||||
|
info = get_param(cmd, " info=");
|
||||||
|
curve = get_param(cmd, " curve=");
|
||||||
|
key = get_param(cmd, " key=");
|
||||||
|
|
||||||
|
if (key) {
|
||||||
|
privkey_len = os_strlen(key) / 2;
|
||||||
|
privkey = os_malloc(privkey_len);
|
||||||
|
if (!privkey ||
|
||||||
|
hexstr2bin(key, privkey, privkey_len) < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
pk = dpp_keygen(bi, curve, privkey, privkey_len);
|
||||||
|
if (!pk)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
len = 4; /* "DPP:" */
|
||||||
|
if (chan) {
|
||||||
|
if (dpp_parse_uri_chan_list(bi, chan) < 0)
|
||||||
|
goto fail;
|
||||||
|
len += 3 + os_strlen(chan); /* C:...; */
|
||||||
|
}
|
||||||
|
if (mac) {
|
||||||
|
if (dpp_parse_uri_mac(bi, mac) < 0)
|
||||||
|
goto fail;
|
||||||
|
len += 3 + os_strlen(mac); /* M:...; */
|
||||||
|
}
|
||||||
|
if (info) {
|
||||||
|
if (dpp_parse_uri_info(bi, info) < 0)
|
||||||
|
goto fail;
|
||||||
|
len += 3 + os_strlen(info); /* I:...; */
|
||||||
|
}
|
||||||
|
len += 4 + os_strlen(pk);
|
||||||
|
bi->uri = os_malloc(len + 1);
|
||||||
|
if (!bi->uri)
|
||||||
|
goto fail;
|
||||||
|
os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
|
||||||
|
chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
|
||||||
|
mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
|
||||||
|
info ? "I:" : "", info ? info : "", info ? ";" : "",
|
||||||
|
pk);
|
||||||
|
bi->id = dpp_next_id(dpp);
|
||||||
|
dl_list_add(&dpp->bootstrap, &bi->list);
|
||||||
|
ret = bi->id;
|
||||||
|
bi = NULL;
|
||||||
|
fail:
|
||||||
|
os_free(curve);
|
||||||
|
os_free(pk);
|
||||||
|
os_free(chan);
|
||||||
|
os_free(mac);
|
||||||
|
os_free(info);
|
||||||
|
str_clear_free(key);
|
||||||
|
bin_clear_free(privkey, privkey_len);
|
||||||
|
dpp_bootstrap_info_free(bi);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct dpp_bootstrap_info *
|
||||||
|
dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id)
|
||||||
|
{
|
||||||
|
struct dpp_bootstrap_info *bi;
|
||||||
|
|
||||||
|
if (!dpp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
|
||||||
|
if (bi->id == id)
|
||||||
|
return bi;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id)
|
||||||
|
{
|
||||||
|
unsigned int id_val;
|
||||||
|
|
||||||
|
if (os_strcmp(id, "*") == 0) {
|
||||||
|
id_val = 0;
|
||||||
|
} else {
|
||||||
|
id_val = atoi(id);
|
||||||
|
if (id_val == 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dpp_bootstrap_del(dpp, id_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct dpp_bootstrap_info *
|
||||||
|
dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer,
|
||||||
|
unsigned int freq)
|
||||||
|
{
|
||||||
|
struct dpp_bootstrap_info *bi;
|
||||||
|
|
||||||
|
bi = os_zalloc(sizeof(*bi));
|
||||||
|
if (!bi)
|
||||||
|
return NULL;
|
||||||
|
bi->id = dpp_next_id(dpp);
|
||||||
|
bi->type = DPP_BOOTSTRAP_PKEX;
|
||||||
|
os_memcpy(bi->mac_addr, peer, ETH_ALEN);
|
||||||
|
bi->num_freq = 1;
|
||||||
|
bi->freq[0] = freq;
|
||||||
|
bi->curve = pkex->own_bi->curve;
|
||||||
|
bi->pubkey = pkex->peer_bootstrap_key;
|
||||||
|
pkex->peer_bootstrap_key = NULL;
|
||||||
|
if (dpp_bootstrap_key_hash(bi) < 0) {
|
||||||
|
dpp_bootstrap_info_free(bi);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dpp_pkex_free(pkex);
|
||||||
|
dl_list_add(&dpp->bootstrap, &bi->list);
|
||||||
|
return bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id)
|
||||||
|
{
|
||||||
|
struct dpp_bootstrap_info *bi;
|
||||||
|
|
||||||
|
bi = dpp_bootstrap_get_id(dpp, id);
|
||||||
|
if (!bi)
|
||||||
|
return NULL;
|
||||||
|
return bi->uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dpp_bootstrap_info(struct dpp_global *dpp, int id,
|
||||||
|
char *reply, int reply_size)
|
||||||
|
{
|
||||||
|
struct dpp_bootstrap_info *bi;
|
||||||
|
|
||||||
|
bi = dpp_bootstrap_get_id(dpp, id);
|
||||||
|
if (!bi)
|
||||||
|
return -1;
|
||||||
|
return os_snprintf(reply, reply_size, "type=%s\n"
|
||||||
|
"mac_addr=" MACSTR "\n"
|
||||||
|
"info=%s\n"
|
||||||
|
"num_freq=%u\n"
|
||||||
|
"curve=%s\n",
|
||||||
|
dpp_bootstrap_type_txt(bi->type),
|
||||||
|
MAC2STR(bi->mac_addr),
|
||||||
|
bi->info ? bi->info : "",
|
||||||
|
bi->num_freq,
|
||||||
|
bi->curve->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
|
||||||
|
const u8 *r_bootstrap,
|
||||||
|
struct dpp_bootstrap_info **own_bi,
|
||||||
|
struct dpp_bootstrap_info **peer_bi)
|
||||||
|
{
|
||||||
|
struct dpp_bootstrap_info *bi;
|
||||||
|
|
||||||
|
*own_bi = NULL;
|
||||||
|
*peer_bi = NULL;
|
||||||
|
if (!dpp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
|
||||||
|
if (!*own_bi && bi->own &&
|
||||||
|
os_memcmp(bi->pubkey_hash, r_bootstrap,
|
||||||
|
SHA256_MAC_LEN) == 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Found matching own bootstrapping information");
|
||||||
|
*own_bi = bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*peer_bi && !bi->own &&
|
||||||
|
os_memcmp(bi->pubkey_hash, i_bootstrap,
|
||||||
|
SHA256_MAC_LEN) == 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Found matching peer bootstrapping information");
|
||||||
|
*peer_bi = bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*own_bi && *peer_bi)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int dpp_next_configurator_id(struct dpp_global *dpp)
|
||||||
|
{
|
||||||
|
struct dpp_configurator *conf;
|
||||||
|
unsigned int max_id = 0;
|
||||||
|
|
||||||
|
dl_list_for_each(conf, &dpp->configurator, struct dpp_configurator,
|
||||||
|
list) {
|
||||||
|
if (conf->id > max_id)
|
||||||
|
max_id = conf->id;
|
||||||
|
}
|
||||||
|
return max_id + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dpp_configurator_add(struct dpp_global *dpp, const char *cmd)
|
||||||
|
{
|
||||||
|
char *curve = NULL;
|
||||||
|
char *key = NULL;
|
||||||
|
u8 *privkey = NULL;
|
||||||
|
size_t privkey_len = 0;
|
||||||
|
int ret = -1;
|
||||||
|
struct dpp_configurator *conf = NULL;
|
||||||
|
|
||||||
|
curve = get_param(cmd, " curve=");
|
||||||
|
key = get_param(cmd, " key=");
|
||||||
|
|
||||||
|
if (key) {
|
||||||
|
privkey_len = os_strlen(key) / 2;
|
||||||
|
privkey = os_malloc(privkey_len);
|
||||||
|
if (!privkey ||
|
||||||
|
hexstr2bin(key, privkey, privkey_len) < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf = dpp_keygen_configurator(curve, privkey, privkey_len);
|
||||||
|
if (!conf)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
conf->id = dpp_next_configurator_id(dpp);
|
||||||
|
dl_list_add(&dpp->configurator, &conf->list);
|
||||||
|
ret = conf->id;
|
||||||
|
conf = NULL;
|
||||||
|
fail:
|
||||||
|
os_free(curve);
|
||||||
|
str_clear_free(key);
|
||||||
|
bin_clear_free(privkey, privkey_len);
|
||||||
|
dpp_configurator_free(conf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id)
|
||||||
|
{
|
||||||
|
struct dpp_configurator *conf, *tmp;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
if (!dpp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dl_list_for_each_safe(conf, tmp, &dpp->configurator,
|
||||||
|
struct dpp_configurator, list) {
|
||||||
|
if (id && conf->id != id)
|
||||||
|
continue;
|
||||||
|
found = 1;
|
||||||
|
dl_list_del(&conf->list);
|
||||||
|
dpp_configurator_free(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id == 0)
|
||||||
|
return 0; /* flush succeeds regardless of entries found */
|
||||||
|
return found ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dpp_configurator_remove(struct dpp_global *dpp, const char *id)
|
||||||
|
{
|
||||||
|
unsigned int id_val;
|
||||||
|
|
||||||
|
if (os_strcmp(id, "*") == 0) {
|
||||||
|
id_val = 0;
|
||||||
|
} else {
|
||||||
|
id_val = atoi(id);
|
||||||
|
if (id_val == 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dpp_configurator_del(dpp, id_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
|
||||||
|
char *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
struct dpp_configurator *conf;
|
||||||
|
|
||||||
|
conf = dpp_configurator_get_id(dpp, id);
|
||||||
|
if (!conf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return dpp_configurator_get_key(conf, buf, buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct dpp_global * dpp_global_init(void)
|
||||||
|
{
|
||||||
|
struct dpp_global *dpp;
|
||||||
|
|
||||||
|
dpp = os_zalloc(sizeof(*dpp));
|
||||||
|
if (!dpp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dl_list_init(&dpp->bootstrap);
|
||||||
|
dl_list_init(&dpp->configurator);
|
||||||
|
|
||||||
|
return dpp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dpp_global_clear(struct dpp_global *dpp)
|
||||||
|
{
|
||||||
|
if (!dpp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dpp_bootstrap_del(dpp, 0);
|
||||||
|
dpp_configurator_del(dpp, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dpp_global_deinit(struct dpp_global *dpp)
|
||||||
|
{
|
||||||
|
dpp_global_clear(dpp);
|
||||||
|
os_free(dpp);
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "crypto/sha256.h"
|
#include "crypto/sha256.h"
|
||||||
|
|
||||||
struct crypto_ecdh;
|
struct crypto_ecdh;
|
||||||
|
struct dpp_global;
|
||||||
|
|
||||||
#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */
|
#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */
|
||||||
|
|
||||||
|
@ -405,7 +406,9 @@ int dpp_akm_dpp(enum dpp_akm akm);
|
||||||
int dpp_akm_ver2(enum dpp_akm akm);
|
int dpp_akm_ver2(enum dpp_akm akm);
|
||||||
int dpp_configuration_valid(const struct dpp_configuration *conf);
|
int dpp_configuration_valid(const struct dpp_configuration *conf);
|
||||||
void dpp_configuration_free(struct dpp_configuration *conf);
|
void dpp_configuration_free(struct dpp_configuration *conf);
|
||||||
int dpp_configuration_parse(struct dpp_authentication *auth, const char *cmd);
|
int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx,
|
||||||
|
struct dpp_authentication *auth,
|
||||||
|
const char *cmd);
|
||||||
void dpp_auth_deinit(struct dpp_authentication *auth);
|
void dpp_auth_deinit(struct dpp_authentication *auth);
|
||||||
struct wpabuf *
|
struct wpabuf *
|
||||||
dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
||||||
|
@ -473,4 +476,28 @@ struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
|
||||||
int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len);
|
int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len);
|
||||||
void dpp_pfs_free(struct dpp_pfs *pfs);
|
void dpp_pfs_free(struct dpp_pfs *pfs);
|
||||||
|
|
||||||
|
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
|
||||||
|
const char *uri);
|
||||||
|
int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd);
|
||||||
|
struct dpp_bootstrap_info *
|
||||||
|
dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id);
|
||||||
|
int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id);
|
||||||
|
struct dpp_bootstrap_info *
|
||||||
|
dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer,
|
||||||
|
unsigned int freq);
|
||||||
|
const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id);
|
||||||
|
int dpp_bootstrap_info(struct dpp_global *dpp, int id,
|
||||||
|
char *reply, int reply_size);
|
||||||
|
void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
|
||||||
|
const u8 *r_bootstrap,
|
||||||
|
struct dpp_bootstrap_info **own_bi,
|
||||||
|
struct dpp_bootstrap_info **peer_bi);
|
||||||
|
int dpp_configurator_add(struct dpp_global *dpp, const char *cmd);
|
||||||
|
int dpp_configurator_remove(struct dpp_global *dpp, const char *id);
|
||||||
|
int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
|
||||||
|
char *buf, size_t buflen);
|
||||||
|
struct dpp_global * dpp_global_init(void);
|
||||||
|
void dpp_global_clear(struct dpp_global *dpp);
|
||||||
|
void dpp_global_deinit(struct dpp_global *dpp);
|
||||||
|
|
||||||
#endif /* DPP_H */
|
#endif /* DPP_H */
|
||||||
|
|
|
@ -1224,3 +1224,28 @@ u8 rssi_to_rcpi(int rssi)
|
||||||
return 220;
|
return 220;
|
||||||
return (rssi + 110) * 2;
|
return (rssi + 110) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char * get_param(const char *cmd, const char *param)
|
||||||
|
{
|
||||||
|
const char *pos, *end;
|
||||||
|
char *val;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
pos = os_strstr(cmd, param);
|
||||||
|
if (!pos)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pos += os_strlen(param);
|
||||||
|
end = os_strchr(pos, ' ');
|
||||||
|
if (end)
|
||||||
|
len = end - pos;
|
||||||
|
else
|
||||||
|
len = os_strlen(pos);
|
||||||
|
val = os_malloc(len + 1);
|
||||||
|
if (!val)
|
||||||
|
return NULL;
|
||||||
|
os_memcpy(val, pos, len);
|
||||||
|
val[len] = '\0';
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
|
@ -567,6 +567,7 @@ int is_ctrl_char(char c);
|
||||||
int str_starts(const char *str, const char *start);
|
int str_starts(const char *str, const char *start);
|
||||||
|
|
||||||
u8 rssi_to_rcpi(int rssi);
|
u8 rssi_to_rcpi(int rssi);
|
||||||
|
char * get_param(const char *cmd, const char *param);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gcc 4.4 ends up generating strict-aliasing warnings about some very common
|
* gcc 4.4 ends up generating strict-aliasing warnings about some very common
|
||||||
|
|
|
@ -10676,7 +10676,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
|
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = wpas_dpp_bootstrap_gen(wpa_s, buf + 18);
|
res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -10685,12 +10685,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
}
|
}
|
||||||
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
|
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
|
||||||
if (wpas_dpp_bootstrap_remove(wpa_s, buf + 21) < 0)
|
if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
|
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
|
||||||
const char *uri;
|
const char *uri;
|
||||||
|
|
||||||
uri = wpas_dpp_bootstrap_get_uri(wpa_s, atoi(buf + 22));
|
uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
|
||||||
if (!uri) {
|
if (!uri) {
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -10699,8 +10699,8 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
}
|
}
|
||||||
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
|
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
|
||||||
reply_len = wpas_dpp_bootstrap_info(wpa_s, atoi(buf + 19),
|
reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
|
||||||
reply, reply_size);
|
reply, reply_size);
|
||||||
} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
|
} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
|
||||||
if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
|
if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
@ -10713,7 +10713,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
|
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = wpas_dpp_configurator_add(wpa_s, buf + 20);
|
res = dpp_configurator_add(wpa_s->dpp, buf + 20);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -10722,14 +10722,15 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
}
|
}
|
||||||
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
|
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
|
||||||
if (wpas_dpp_configurator_remove(wpa_s, buf + 24) < 0)
|
if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
|
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
|
||||||
if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
|
if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
|
} else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
|
||||||
reply_len = wpas_dpp_configurator_get_key(wpa_s, atoi(buf + 25),
|
reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
|
||||||
reply, reply_size);
|
atoi(buf + 25),
|
||||||
|
reply, reply_size);
|
||||||
} else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
|
} else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
|
|
@ -52,34 +52,6 @@ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
static const u8 TRANSACTION_ID = 1;
|
static const u8 TRANSACTION_ID = 1;
|
||||||
|
|
||||||
|
|
||||||
static struct dpp_configurator *
|
|
||||||
dpp_configurator_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
|
|
||||||
{
|
|
||||||
struct dpp_configurator *conf;
|
|
||||||
|
|
||||||
dl_list_for_each(conf, &wpa_s->dpp_configurator,
|
|
||||||
struct dpp_configurator, list) {
|
|
||||||
if (conf->id == id)
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned int wpas_dpp_next_id(struct wpa_supplicant *wpa_s)
|
|
||||||
{
|
|
||||||
struct dpp_bootstrap_info *bi;
|
|
||||||
unsigned int max_id = 0;
|
|
||||||
|
|
||||||
dl_list_for_each(bi, &wpa_s->dpp_bootstrap, struct dpp_bootstrap_info,
|
|
||||||
list) {
|
|
||||||
if (bi->id > max_id)
|
|
||||||
max_id = bi->id;
|
|
||||||
}
|
|
||||||
return max_id + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
|
* wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
|
||||||
* @wpa_s: Pointer to wpa_supplicant data
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
@ -91,13 +63,10 @@ int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
|
||||||
struct dpp_bootstrap_info *bi;
|
struct dpp_bootstrap_info *bi;
|
||||||
struct dpp_authentication *auth = wpa_s->dpp_auth;
|
struct dpp_authentication *auth = wpa_s->dpp_auth;
|
||||||
|
|
||||||
bi = dpp_parse_qr_code(cmd);
|
bi = dpp_add_qr_code(wpa_s->dpp, cmd);
|
||||||
if (!bi)
|
if (!bi)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
bi->id = wpas_dpp_next_id(wpa_s);
|
|
||||||
dl_list_add(&wpa_s->dpp_bootstrap, &bi->list);
|
|
||||||
|
|
||||||
if (auth && auth->response_pending &&
|
if (auth && auth->response_pending &&
|
||||||
dpp_notify_new_qr_code(auth, bi) == 1) {
|
dpp_notify_new_qr_code(auth, bi) == 1) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
|
@ -118,195 +87,6 @@ int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char * get_param(const char *cmd, const char *param)
|
|
||||||
{
|
|
||||||
const char *pos, *end;
|
|
||||||
char *val;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
pos = os_strstr(cmd, param);
|
|
||||||
if (!pos)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
pos += os_strlen(param);
|
|
||||||
end = os_strchr(pos, ' ');
|
|
||||||
if (end)
|
|
||||||
len = end - pos;
|
|
||||||
else
|
|
||||||
len = os_strlen(pos);
|
|
||||||
val = os_malloc(len + 1);
|
|
||||||
if (!val)
|
|
||||||
return NULL;
|
|
||||||
os_memcpy(val, pos, len);
|
|
||||||
val[len] = '\0';
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int wpas_dpp_bootstrap_gen(struct wpa_supplicant *wpa_s, const char *cmd)
|
|
||||||
{
|
|
||||||
char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
|
|
||||||
char *key = NULL;
|
|
||||||
u8 *privkey = NULL;
|
|
||||||
size_t privkey_len = 0;
|
|
||||||
size_t len;
|
|
||||||
int ret = -1;
|
|
||||||
struct dpp_bootstrap_info *bi;
|
|
||||||
|
|
||||||
bi = os_zalloc(sizeof(*bi));
|
|
||||||
if (!bi)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (os_strstr(cmd, "type=qrcode"))
|
|
||||||
bi->type = DPP_BOOTSTRAP_QR_CODE;
|
|
||||||
else if (os_strstr(cmd, "type=pkex"))
|
|
||||||
bi->type = DPP_BOOTSTRAP_PKEX;
|
|
||||||
else
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
chan = get_param(cmd, " chan=");
|
|
||||||
mac = get_param(cmd, " mac=");
|
|
||||||
info = get_param(cmd, " info=");
|
|
||||||
curve = get_param(cmd, " curve=");
|
|
||||||
key = get_param(cmd, " key=");
|
|
||||||
|
|
||||||
if (key) {
|
|
||||||
privkey_len = os_strlen(key) / 2;
|
|
||||||
privkey = os_malloc(privkey_len);
|
|
||||||
if (!privkey ||
|
|
||||||
hexstr2bin(key, privkey, privkey_len) < 0)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
pk = dpp_keygen(bi, curve, privkey, privkey_len);
|
|
||||||
if (!pk)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
len = 4; /* "DPP:" */
|
|
||||||
if (chan) {
|
|
||||||
if (dpp_parse_uri_chan_list(bi, chan) < 0)
|
|
||||||
goto fail;
|
|
||||||
len += 3 + os_strlen(chan); /* C:...; */
|
|
||||||
}
|
|
||||||
if (mac) {
|
|
||||||
if (dpp_parse_uri_mac(bi, mac) < 0)
|
|
||||||
goto fail;
|
|
||||||
len += 3 + os_strlen(mac); /* M:...; */
|
|
||||||
}
|
|
||||||
if (info) {
|
|
||||||
if (dpp_parse_uri_info(bi, info) < 0)
|
|
||||||
goto fail;
|
|
||||||
len += 3 + os_strlen(info); /* I:...; */
|
|
||||||
}
|
|
||||||
len += 4 + os_strlen(pk);
|
|
||||||
bi->uri = os_malloc(len + 1);
|
|
||||||
if (!bi->uri)
|
|
||||||
goto fail;
|
|
||||||
os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
|
|
||||||
chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
|
|
||||||
mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
|
|
||||||
info ? "I:" : "", info ? info : "", info ? ";" : "",
|
|
||||||
pk);
|
|
||||||
bi->id = wpas_dpp_next_id(wpa_s);
|
|
||||||
dl_list_add(&wpa_s->dpp_bootstrap, &bi->list);
|
|
||||||
ret = bi->id;
|
|
||||||
bi = NULL;
|
|
||||||
fail:
|
|
||||||
os_free(curve);
|
|
||||||
os_free(pk);
|
|
||||||
os_free(chan);
|
|
||||||
os_free(mac);
|
|
||||||
os_free(info);
|
|
||||||
str_clear_free(key);
|
|
||||||
bin_clear_free(privkey, privkey_len);
|
|
||||||
dpp_bootstrap_info_free(bi);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct dpp_bootstrap_info *
|
|
||||||
dpp_bootstrap_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
|
|
||||||
{
|
|
||||||
struct dpp_bootstrap_info *bi;
|
|
||||||
|
|
||||||
dl_list_for_each(bi, &wpa_s->dpp_bootstrap, struct dpp_bootstrap_info,
|
|
||||||
list) {
|
|
||||||
if (bi->id == id)
|
|
||||||
return bi;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int dpp_bootstrap_del(struct wpa_supplicant *wpa_s, unsigned int id)
|
|
||||||
{
|
|
||||||
struct dpp_bootstrap_info *bi, *tmp;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
dl_list_for_each_safe(bi, tmp, &wpa_s->dpp_bootstrap,
|
|
||||||
struct dpp_bootstrap_info, list) {
|
|
||||||
if (id && bi->id != id)
|
|
||||||
continue;
|
|
||||||
found = 1;
|
|
||||||
dl_list_del(&bi->list);
|
|
||||||
dpp_bootstrap_info_free(bi);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == 0)
|
|
||||||
return 0; /* flush succeeds regardless of entries found */
|
|
||||||
return found ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int wpas_dpp_bootstrap_remove(struct wpa_supplicant *wpa_s, const char *id)
|
|
||||||
{
|
|
||||||
unsigned int id_val;
|
|
||||||
|
|
||||||
if (os_strcmp(id, "*") == 0) {
|
|
||||||
id_val = 0;
|
|
||||||
} else {
|
|
||||||
id_val = atoi(id);
|
|
||||||
if (id_val == 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dpp_bootstrap_del(wpa_s, id_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char * wpas_dpp_bootstrap_get_uri(struct wpa_supplicant *wpa_s,
|
|
||||||
unsigned int id)
|
|
||||||
{
|
|
||||||
struct dpp_bootstrap_info *bi;
|
|
||||||
|
|
||||||
bi = dpp_bootstrap_get_id(wpa_s, id);
|
|
||||||
if (!bi)
|
|
||||||
return NULL;
|
|
||||||
return bi->uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int wpas_dpp_bootstrap_info(struct wpa_supplicant *wpa_s, int id,
|
|
||||||
char *reply, int reply_size)
|
|
||||||
{
|
|
||||||
struct dpp_bootstrap_info *bi;
|
|
||||||
|
|
||||||
bi = dpp_bootstrap_get_id(wpa_s, id);
|
|
||||||
if (!bi)
|
|
||||||
return -1;
|
|
||||||
return os_snprintf(reply, reply_size, "type=%s\n"
|
|
||||||
"mac_addr=" MACSTR "\n"
|
|
||||||
"info=%s\n"
|
|
||||||
"num_freq=%u\n"
|
|
||||||
"curve=%s\n",
|
|
||||||
dpp_bootstrap_type_txt(bi->type),
|
|
||||||
MAC2STR(bi->mac_addr),
|
|
||||||
bi->info ? bi->info : "",
|
|
||||||
bi->num_freq,
|
|
||||||
bi->curve->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
|
@ -550,37 +330,6 @@ static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpas_dpp_set_configurator(struct wpa_supplicant *wpa_s,
|
|
||||||
struct dpp_authentication *auth,
|
|
||||||
const char *cmd)
|
|
||||||
{
|
|
||||||
const char *pos;
|
|
||||||
|
|
||||||
if (!cmd)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
|
|
||||||
|
|
||||||
pos = os_strstr(cmd, " configurator=");
|
|
||||||
if (pos) {
|
|
||||||
pos += 14;
|
|
||||||
auth->conf = dpp_configurator_get_id(wpa_s, atoi(pos));
|
|
||||||
if (!auth->conf) {
|
|
||||||
wpa_printf(MSG_INFO,
|
|
||||||
"DPP: Could not find the specified configurator");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dpp_configuration_parse(auth, cmd) < 0) {
|
|
||||||
wpa_msg(wpa_s, MSG_INFO,
|
|
||||||
"DPP: Failed to set configurator parameters");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
|
static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
{
|
{
|
||||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||||
|
@ -693,7 +442,7 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
|
||||||
if (!pos)
|
if (!pos)
|
||||||
return -1;
|
return -1;
|
||||||
pos += 6;
|
pos += 6;
|
||||||
peer_bi = dpp_bootstrap_get_id(wpa_s, atoi(pos));
|
peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
|
||||||
if (!peer_bi) {
|
if (!peer_bi) {
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"DPP: Could not find bootstrapping info for the identified peer");
|
"DPP: Could not find bootstrapping info for the identified peer");
|
||||||
|
@ -703,7 +452,7 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
|
||||||
pos = os_strstr(cmd, " own=");
|
pos = os_strstr(cmd, " own=");
|
||||||
if (pos) {
|
if (pos) {
|
||||||
pos += 5;
|
pos += 5;
|
||||||
own_bi = dpp_bootstrap_get_id(wpa_s, atoi(pos));
|
own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
|
||||||
if (!own_bi) {
|
if (!own_bi) {
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"DPP: Could not find bootstrapping info for the identified local entry");
|
"DPP: Could not find bootstrapping info for the identified local entry");
|
||||||
|
@ -756,7 +505,7 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
|
||||||
if (!wpa_s->dpp_auth)
|
if (!wpa_s->dpp_auth)
|
||||||
goto fail;
|
goto fail;
|
||||||
wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
|
wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
|
||||||
if (wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth, cmd) < 0) {
|
if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth, cmd) < 0) {
|
||||||
dpp_auth_deinit(wpa_s->dpp_auth);
|
dpp_auth_deinit(wpa_s->dpp_auth);
|
||||||
wpa_s->dpp_auth = NULL;
|
wpa_s->dpp_auth = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -940,7 +689,10 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||||
{
|
{
|
||||||
const u8 *r_bootstrap, *i_bootstrap;
|
const u8 *r_bootstrap, *i_bootstrap;
|
||||||
u16 r_bootstrap_len, i_bootstrap_len;
|
u16 r_bootstrap_len, i_bootstrap_len;
|
||||||
struct dpp_bootstrap_info *bi, *own_bi = NULL, *peer_bi = NULL;
|
struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
|
||||||
|
|
||||||
|
if (!wpa_s->dpp)
|
||||||
|
return;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
|
wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
|
||||||
MAC2STR(src));
|
MAC2STR(src));
|
||||||
|
@ -967,28 +719,8 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||||
|
|
||||||
/* Try to find own and peer bootstrapping key matches based on the
|
/* Try to find own and peer bootstrapping key matches based on the
|
||||||
* received hash values */
|
* received hash values */
|
||||||
dl_list_for_each(bi, &wpa_s->dpp_bootstrap, struct dpp_bootstrap_info,
|
dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
|
||||||
list) {
|
&own_bi, &peer_bi);
|
||||||
if (!own_bi && bi->own &&
|
|
||||||
os_memcmp(bi->pubkey_hash, r_bootstrap,
|
|
||||||
SHA256_MAC_LEN) == 0) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"DPP: Found matching own bootstrapping information");
|
|
||||||
own_bi = bi;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!peer_bi && !bi->own &&
|
|
||||||
os_memcmp(bi->pubkey_hash, i_bootstrap,
|
|
||||||
SHA256_MAC_LEN) == 0) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"DPP: Found matching peer bootstrapping information");
|
|
||||||
peer_bi = bi;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (own_bi && peer_bi)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!own_bi) {
|
if (!own_bi) {
|
||||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
|
||||||
"No matching own bootstrapping key found - ignore message");
|
"No matching own bootstrapping key found - ignore message");
|
||||||
|
@ -1011,8 +743,8 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
|
wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
|
||||||
if (wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth,
|
if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth,
|
||||||
wpa_s->dpp_configurator_params) < 0) {
|
wpa_s->dpp_configurator_params) < 0) {
|
||||||
dpp_auth_deinit(wpa_s->dpp_auth);
|
dpp_auth_deinit(wpa_s->dpp_auth);
|
||||||
wpa_s->dpp_auth = NULL;
|
wpa_s->dpp_auth = NULL;
|
||||||
return;
|
return;
|
||||||
|
@ -1924,27 +1656,12 @@ static struct dpp_bootstrap_info *
|
||||||
wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
|
wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
|
||||||
unsigned int freq)
|
unsigned int freq)
|
||||||
{
|
{
|
||||||
struct dpp_pkex *pkex = wpa_s->dpp_pkex;
|
|
||||||
struct dpp_bootstrap_info *bi;
|
struct dpp_bootstrap_info *bi;
|
||||||
|
|
||||||
bi = os_zalloc(sizeof(*bi));
|
bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
|
||||||
if (!bi)
|
if (!bi)
|
||||||
return NULL;
|
return NULL;
|
||||||
bi->id = wpas_dpp_next_id(wpa_s);
|
|
||||||
bi->type = DPP_BOOTSTRAP_PKEX;
|
|
||||||
os_memcpy(bi->mac_addr, peer, ETH_ALEN);
|
|
||||||
bi->num_freq = 1;
|
|
||||||
bi->freq[0] = freq;
|
|
||||||
bi->curve = pkex->own_bi->curve;
|
|
||||||
bi->pubkey = pkex->peer_bootstrap_key;
|
|
||||||
pkex->peer_bootstrap_key = NULL;
|
|
||||||
dpp_pkex_free(pkex);
|
|
||||||
wpa_s->dpp_pkex = NULL;
|
wpa_s->dpp_pkex = NULL;
|
||||||
if (dpp_bootstrap_key_hash(bi) < 0) {
|
|
||||||
dpp_bootstrap_info_free(bi);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
dl_list_add(&wpa_s->dpp_bootstrap, &bi->list);
|
|
||||||
return bi;
|
return bi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2208,93 +1925,6 @@ wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned int wpas_dpp_next_configurator_id(struct wpa_supplicant *wpa_s)
|
|
||||||
{
|
|
||||||
struct dpp_configurator *conf;
|
|
||||||
unsigned int max_id = 0;
|
|
||||||
|
|
||||||
dl_list_for_each(conf, &wpa_s->dpp_configurator,
|
|
||||||
struct dpp_configurator, list) {
|
|
||||||
if (conf->id > max_id)
|
|
||||||
max_id = conf->id;
|
|
||||||
}
|
|
||||||
return max_id + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int wpas_dpp_configurator_add(struct wpa_supplicant *wpa_s, const char *cmd)
|
|
||||||
{
|
|
||||||
char *curve = NULL;
|
|
||||||
char *key = NULL;
|
|
||||||
u8 *privkey = NULL;
|
|
||||||
size_t privkey_len = 0;
|
|
||||||
int ret = -1;
|
|
||||||
struct dpp_configurator *conf = NULL;
|
|
||||||
|
|
||||||
curve = get_param(cmd, " curve=");
|
|
||||||
key = get_param(cmd, " key=");
|
|
||||||
|
|
||||||
if (key) {
|
|
||||||
privkey_len = os_strlen(key) / 2;
|
|
||||||
privkey = os_malloc(privkey_len);
|
|
||||||
if (!privkey ||
|
|
||||||
hexstr2bin(key, privkey, privkey_len) < 0)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
conf = dpp_keygen_configurator(curve, privkey, privkey_len);
|
|
||||||
if (!conf)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
conf->id = wpas_dpp_next_configurator_id(wpa_s);
|
|
||||||
dl_list_add(&wpa_s->dpp_configurator, &conf->list);
|
|
||||||
ret = conf->id;
|
|
||||||
conf = NULL;
|
|
||||||
fail:
|
|
||||||
os_free(curve);
|
|
||||||
str_clear_free(key);
|
|
||||||
bin_clear_free(privkey, privkey_len);
|
|
||||||
dpp_configurator_free(conf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int dpp_configurator_del(struct wpa_supplicant *wpa_s, unsigned int id)
|
|
||||||
{
|
|
||||||
struct dpp_configurator *conf, *tmp;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
dl_list_for_each_safe(conf, tmp, &wpa_s->dpp_configurator,
|
|
||||||
struct dpp_configurator, list) {
|
|
||||||
if (id && conf->id != id)
|
|
||||||
continue;
|
|
||||||
found = 1;
|
|
||||||
dl_list_del(&conf->list);
|
|
||||||
dpp_configurator_free(conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == 0)
|
|
||||||
return 0; /* flush succeeds regardless of entries found */
|
|
||||||
return found ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int wpas_dpp_configurator_remove(struct wpa_supplicant *wpa_s, const char *id)
|
|
||||||
{
|
|
||||||
unsigned int id_val;
|
|
||||||
|
|
||||||
if (os_strcmp(id, "*") == 0) {
|
|
||||||
id_val = 0;
|
|
||||||
} else {
|
|
||||||
id_val = atoi(id);
|
|
||||||
if (id_val == 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dpp_configurator_del(wpa_s, id_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
|
int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
|
||||||
{
|
{
|
||||||
struct dpp_authentication *auth;
|
struct dpp_authentication *auth;
|
||||||
|
@ -2307,7 +1937,7 @@ int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
|
||||||
|
|
||||||
curve = get_param(cmd, " curve=");
|
curve = get_param(cmd, " curve=");
|
||||||
wpas_dpp_set_testing_options(wpa_s, auth);
|
wpas_dpp_set_testing_options(wpa_s, auth);
|
||||||
if (wpas_dpp_set_configurator(wpa_s, auth, cmd) == 0 &&
|
if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) == 0 &&
|
||||||
dpp_configurator_own_config(auth, curve, 0) == 0)
|
dpp_configurator_own_config(auth, curve, 0) == 0)
|
||||||
ret = wpas_dpp_handle_config_obj(wpa_s, auth);
|
ret = wpas_dpp_handle_config_obj(wpa_s, auth);
|
||||||
|
|
||||||
|
@ -2318,19 +1948,6 @@ int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpas_dpp_configurator_get_key(struct wpa_supplicant *wpa_s, unsigned int id,
|
|
||||||
char *buf, size_t buflen)
|
|
||||||
{
|
|
||||||
struct dpp_configurator *conf;
|
|
||||||
|
|
||||||
conf = dpp_configurator_get_id(wpa_s, id);
|
|
||||||
if (!conf)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return dpp_configurator_get_key(conf, buf, buflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
|
wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
|
||||||
unsigned int freq, const u8 *dst,
|
unsigned int freq, const u8 *dst,
|
||||||
|
@ -2479,7 +2096,7 @@ int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
|
||||||
if (!pos)
|
if (!pos)
|
||||||
return -1;
|
return -1;
|
||||||
pos += 5;
|
pos += 5;
|
||||||
own_bi = dpp_bootstrap_get_id(wpa_s, atoi(pos));
|
own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
|
||||||
if (!own_bi) {
|
if (!own_bi) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"DPP: Identified bootstrap info not found");
|
"DPP: Identified bootstrap info not found");
|
||||||
|
@ -2612,10 +2229,8 @@ int wpas_dpp_init(struct wpa_supplicant *wpa_s)
|
||||||
sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
|
sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
|
||||||
wpas_dpp_gas_status_handler, wpa_s) < 0)
|
wpas_dpp_gas_status_handler, wpa_s) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
dl_list_init(&wpa_s->dpp_bootstrap);
|
wpa_s->dpp = dpp_global_init();
|
||||||
dl_list_init(&wpa_s->dpp_configurator);
|
return wpa_s->dpp ? 0 : -1;
|
||||||
wpa_s->dpp_init_done = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2630,8 +2245,9 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
||||||
wpa_s->dpp_groups_override = NULL;
|
wpa_s->dpp_groups_override = NULL;
|
||||||
wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
|
wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
if (!wpa_s->dpp_init_done)
|
if (!wpa_s->dpp)
|
||||||
return;
|
return;
|
||||||
|
dpp_global_clear(wpa_s->dpp);
|
||||||
eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
|
eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
|
||||||
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
|
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
|
||||||
eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
|
eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
|
||||||
|
@ -2643,8 +2259,6 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
offchannel_send_action_done(wpa_s);
|
offchannel_send_action_done(wpa_s);
|
||||||
wpas_dpp_listen_stop(wpa_s);
|
wpas_dpp_listen_stop(wpa_s);
|
||||||
dpp_bootstrap_del(wpa_s, 0);
|
|
||||||
dpp_configurator_del(wpa_s, 0);
|
|
||||||
wpas_dpp_stop(wpa_s);
|
wpas_dpp_stop(wpa_s);
|
||||||
wpas_dpp_pkex_remove(wpa_s, "*");
|
wpas_dpp_pkex_remove(wpa_s, "*");
|
||||||
os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
|
os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
|
||||||
|
|
|
@ -10,12 +10,6 @@
|
||||||
#define DPP_SUPPLICANT_H
|
#define DPP_SUPPLICANT_H
|
||||||
|
|
||||||
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_bootstrap_gen(struct wpa_supplicant *wpa_s, const char *cmd);
|
|
||||||
int wpas_dpp_bootstrap_remove(struct wpa_supplicant *wpa_s, const char *id);
|
|
||||||
const char * wpas_dpp_bootstrap_get_uri(struct wpa_supplicant *wpa_s,
|
|
||||||
unsigned int id);
|
|
||||||
int wpas_dpp_bootstrap_info(struct wpa_supplicant *wpa_s, int id,
|
|
||||||
char *reply, int reply_size);
|
|
||||||
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);
|
||||||
|
@ -23,11 +17,7 @@ void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
||||||
unsigned int freq);
|
unsigned int freq);
|
||||||
void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
|
void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||||
const u8 *buf, size_t len, unsigned int freq);
|
const u8 *buf, size_t len, unsigned int freq);
|
||||||
int wpas_dpp_configurator_add(struct wpa_supplicant *wpa_s, const char *cmd);
|
|
||||||
int wpas_dpp_configurator_remove(struct wpa_supplicant *wpa_s, const char *id);
|
|
||||||
int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd);
|
int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||||
int wpas_dpp_configurator_get_key(struct wpa_supplicant *wpa_s, unsigned int id,
|
|
||||||
char *buf, size_t buflen);
|
|
||||||
int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd);
|
int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||||
int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id);
|
int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id);
|
||||||
void wpas_dpp_stop(struct wpa_supplicant *wpa_s);
|
void wpas_dpp_stop(struct wpa_supplicant *wpa_s);
|
||||||
|
|
|
@ -673,6 +673,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
|
||||||
|
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
wpas_dpp_deinit(wpa_s);
|
wpas_dpp_deinit(wpa_s);
|
||||||
|
dpp_global_deinit(wpa_s->dpp);
|
||||||
|
wpa_s->dpp = NULL;
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1207,9 +1207,7 @@ struct wpa_supplicant {
|
||||||
int last_auth_timeout_sec;
|
int last_auth_timeout_sec;
|
||||||
|
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
struct dl_list dpp_bootstrap; /* struct dpp_bootstrap_info */
|
struct dpp_global *dpp;
|
||||||
struct dl_list dpp_configurator; /* struct dpp_configurator */
|
|
||||||
int dpp_init_done;
|
|
||||||
struct dpp_authentication *dpp_auth;
|
struct dpp_authentication *dpp_auth;
|
||||||
struct wpa_radio_work *dpp_listen_work;
|
struct wpa_radio_work *dpp_listen_work;
|
||||||
unsigned int dpp_pending_listen_freq;
|
unsigned int dpp_pending_listen_freq;
|
||||||
|
|
Loading…
Reference in a new issue