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:
Jouni Malinen 2019-03-24 16:44:21 +02:00
parent 74cb18c6b0
commit 87d8435cf9
14 changed files with 585 additions and 884 deletions

View file

@ -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 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
* @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_authentication *auth = hapd->dpp_auth;
bi = dpp_parse_qr_code(cmd);
bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd);
if (!bi)
return -1;
bi->id = hapd_dpp_next_id(hapd);
dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
if (auth && auth->response_pending &&
dpp_notify_new_qr_code(auth, bi) == 1) {
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,
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)
{
struct hostapd_data *hapd = eloop_ctx;
@ -656,7 +404,7 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
if (!pos)
return -1;
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) {
wpa_printf(MSG_INFO,
"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=");
if (pos) {
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) {
wpa_printf(MSG_INFO,
"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)
goto fail;
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);
hapd->dpp_auth = NULL;
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;
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,
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
* received hash values */
dl_list_for_each(bi, &hapd->iface->interfaces->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;
}
dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
r_bootstrap, &own_bi, &peer_bi);
if (!own_bi) {
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
"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;
}
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
if (hostapd_dpp_set_configurator(hapd, hapd->dpp_auth,
hapd->dpp_configurator_params) < 0) {
if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
hapd->dpp_auth,
hapd->dpp_configurator_params) < 0) {
dpp_auth_deinit(hapd->dpp_auth);
hapd->dpp_auth = NULL;
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_free(msg);
bi = os_zalloc(sizeof(*bi));
bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
if (!bi)
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;
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)
{
int res;
struct dpp_bootstrap_info *bi, *own_bi;
struct dpp_bootstrap_info *bi;
struct dpp_pkex *pkex = hapd->dpp_pkex;
char cmd[500];
@ -1598,26 +1318,10 @@ hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
return;
}
own_bi = pkex->own_bi;
bi = os_zalloc(sizeof(*bi));
bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
if (!bi)
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;
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",
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)
{
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=");
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) {
hostapd_dpp_handle_config_obj(hapd, auth);
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)
{
struct dpp_bootstrap_info *own_bi;
@ -1919,7 +1524,7 @@ int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
if (!pos)
return -1;
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) {
wpa_printf(MSG_DEBUG,
"DPP: Identified bootstrap info not found");
@ -2060,20 +1665,3 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
os_free(hapd->dpp_configurator_params);
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);
}

View file

@ -10,12 +10,6 @@
#define DPP_HOSTAPD_H
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_listen(struct hostapd_data *hapd, const char *cmd);
void hostapd_dpp_listen_stop(struct hostapd_data *hapd);

View file

@ -66,9 +66,7 @@ struct hapd_interfaces {
int eloop_initialized;
#ifdef CONFIG_DPP
int dpp_init_done;
struct dl_list dpp_bootstrap; /* struct dpp_bootstrap_info */
struct dl_list dpp_configurator; /* struct dpp_configurator */
struct dpp_global *dpp;
#endif /* CONFIG_DPP */
};

View file

@ -69,6 +69,11 @@ static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
#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[] = {
/* The mandatory to support and the default NIST P-256 curve needs to
* 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;
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)
{
if (!auth)
@ -8215,3 +8269,403 @@ void dpp_pfs_free(struct dpp_pfs *pfs)
}
#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);
}

View file

@ -17,6 +17,7 @@
#include "crypto/sha256.h"
struct crypto_ecdh;
struct dpp_global;
#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_configuration_valid(const 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);
struct wpabuf *
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);
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 */

View file

@ -1224,3 +1224,28 @@ u8 rssi_to_rcpi(int rssi)
return 220;
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;
}

View file

@ -567,6 +567,7 @@ int is_ctrl_char(char c);
int str_starts(const char *str, const char *start);
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