From 87d8435cf9fd033defafd952cf80090cc9a1cb2d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 24 Mar 2019 16:44:21 +0200 Subject: [PATCH] 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 --- hostapd/ctrl_iface.c | 28 +- hostapd/main.c | 7 +- src/ap/dpp_hostapd.c | 454 ++--------------------------- src/ap/dpp_hostapd.h | 6 - src/ap/hostapd.h | 4 +- src/common/dpp.c | 456 +++++++++++++++++++++++++++++- src/common/dpp.h | 29 +- src/utils/common.c | 25 ++ src/utils/common.h | 1 + wpa_supplicant/ctrl_iface.c | 19 +- wpa_supplicant/dpp_supplicant.c | 424 ++------------------------- wpa_supplicant/dpp_supplicant.h | 10 - wpa_supplicant/wpa_supplicant.c | 2 + wpa_supplicant/wpa_supplicant_i.h | 4 +- 14 files changed, 585 insertions(+), 884 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 3a3105073..78e52a6fe 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -3270,7 +3270,7 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_len = -1; } } 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) { reply_len = -1; } else { @@ -3279,12 +3279,14 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_len = -1; } } 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; } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) { 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) { reply_len = -1; } else { @@ -3293,8 +3295,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_len = -1; } } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { - reply_len = hostapd_dpp_bootstrap_info(hapd, atoi(buf + 19), - reply, reply_size); + reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp, + atoi(buf + 19), + reply, reply_size); } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { if (hostapd_dpp_auth_init(hapd, buf + 13) < 0) reply_len = -1; @@ -3305,7 +3308,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, hostapd_dpp_stop(hapd); hostapd_dpp_listen_stop(hapd); } 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) { reply_len = -1; } else { @@ -3314,15 +3318,17 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_len = -1; } } 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; } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) { if (hostapd_dpp_configurator_sign(hapd, buf + 21) < 0) reply_len = -1; } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) { - reply_len = hostapd_dpp_configurator_get_key(hapd, - atoi(buf + 25), - reply, reply_size); + reply_len = dpp_configurator_get_key_id( + hapd->iface->interfaces->dpp, + atoi(buf + 25), + reply, reply_size); } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) { res = hostapd_dpp_pkex_add(hapd, buf + 12); if (res < 0) { @@ -3824,7 +3830,7 @@ static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces) #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_DPP - hostapd_dpp_deinit_global(interfaces); + dpp_global_clear(interfaces->dpp); #endif /* CONFIG_DPP */ } diff --git a/hostapd/main.c b/hostapd/main.c index bfc8acd5e..93d2dd34c 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -18,6 +18,7 @@ #include "crypto/random.h" #include "crypto/tls.h" #include "common/version.h" +#include "common/dpp.h" #include "drivers/driver.h" #include "eap_server/eap.h" #include "eap_server/tncs.h" @@ -671,7 +672,9 @@ int main(int argc, char *argv[]) dl_list_init(&interfaces.eth_p_oui); #endif /* CONFIG_ETH_P_OUI */ #ifdef CONFIG_DPP - hostapd_dpp_init_global(&interfaces); + interfaces.dpp = dpp_global_init(); + if (!interfaces.dpp) + return -1; #endif /* CONFIG_DPP */ for (;;) { @@ -901,7 +904,7 @@ int main(int argc, char *argv[]) os_free(interfaces.iface); #ifdef CONFIG_DPP - hostapd_dpp_deinit_global(&interfaces); + dpp_global_deinit(interfaces.dpp); #endif /* CONFIG_DPP */ if (interfaces.eloop_initialized) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 0305283b6..a169f8fd1 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -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); -} diff --git a/src/ap/dpp_hostapd.h b/src/ap/dpp_hostapd.h index 3ef7c1456..449ca16d1 100644 --- a/src/ap/dpp_hostapd.h +++ b/src/ap/dpp_hostapd.h @@ -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); diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index b8637c46a..790d37754 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -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 */ }; diff --git a/src/common/dpp.c b/src/common/dpp.c index 58a39f9dc..f64711fca 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -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); +} diff --git a/src/common/dpp.h b/src/common/dpp.h index 2a6f72dda..0a8122685 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -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 */ diff --git a/src/utils/common.c b/src/utils/common.c index f58d2351b..b9c8bfdb9 100644 --- a/src/utils/common.c +++ b/src/utils/common.c @@ -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; +} diff --git a/src/utils/common.h b/src/utils/common.h index f824d001a..792a30ab9 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -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 diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index e8f38752b..564f32b85 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -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) { int res; - res = wpas_dpp_bootstrap_gen(wpa_s, buf + 18); + res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18); if (res < 0) { reply_len = -1; } else { @@ -10685,12 +10685,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = -1; } } 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; } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) { 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) { reply_len = -1; } else { @@ -10699,8 +10699,8 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = -1; } } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { - reply_len = wpas_dpp_bootstrap_info(wpa_s, atoi(buf + 19), - reply, reply_size); + reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19), + reply, reply_size); } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0) 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) { int res; - res = wpas_dpp_configurator_add(wpa_s, buf + 20); + res = dpp_configurator_add(wpa_s->dpp, buf + 20); if (res < 0) { reply_len = -1; } else { @@ -10722,14 +10722,15 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = -1; } } 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; } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) { if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0) reply_len = -1; } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) { - reply_len = wpas_dpp_configurator_get_key(wpa_s, atoi(buf + 25), - reply, reply_size); + reply_len = dpp_configurator_get_key_id(wpa_s->dpp, + atoi(buf + 25), + reply, reply_size); } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) { int res; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index db8699117..17527263b 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -52,34 +52,6 @@ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 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 * @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_authentication *auth = wpa_s->dpp_auth; - bi = dpp_parse_qr_code(cmd); + bi = dpp_add_qr_code(wpa_s->dpp, cmd); if (!bi) return -1; - bi->id = wpas_dpp_next_id(wpa_s); - dl_list_add(&wpa_s->dpp_bootstrap, &bi->list); - if (auth && auth->response_pending && dpp_notify_new_qr_code(auth, bi) == 1) { 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) { 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) { 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) return -1; 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) { wpa_printf(MSG_INFO, "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="); if (pos) { 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) { wpa_printf(MSG_INFO, "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) goto fail; 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); wpa_s->dpp_auth = NULL; 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; 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, 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 * received hash values */ - dl_list_for_each(bi, &wpa_s->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(wpa_s->dpp, i_bootstrap, r_bootstrap, + &own_bi, &peer_bi); if (!own_bi) { wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "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; } wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth); - if (wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth, - wpa_s->dpp_configurator_params) < 0) { + if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth, + wpa_s->dpp_configurator_params) < 0) { dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; return; @@ -1924,27 +1656,12 @@ static struct dpp_bootstrap_info * wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer, unsigned int freq) { - struct dpp_pkex *pkex = wpa_s->dpp_pkex; 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) 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; - 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; } @@ -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) { 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="); 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) 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 wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s, 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) return -1; 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) { wpa_printf(MSG_DEBUG, "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, wpas_dpp_gas_status_handler, wpa_s) < 0) return -1; - dl_list_init(&wpa_s->dpp_bootstrap); - dl_list_init(&wpa_s->dpp_configurator); - wpa_s->dpp_init_done = 1; - return 0; + wpa_s->dpp = dpp_global_init(); + return wpa_s->dpp ? 0 : -1; } @@ -2630,8 +2245,9 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) wpa_s->dpp_groups_override = NULL; wpa_s->dpp_ignore_netaccesskey_mismatch = 0; #endif /* CONFIG_TESTING_OPTIONS */ - if (!wpa_s->dpp_init_done) + if (!wpa_s->dpp) return; + dpp_global_clear(wpa_s->dpp); 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_init_timeout, wpa_s, NULL); @@ -2643,8 +2259,6 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) #endif /* CONFIG_DPP2 */ offchannel_send_action_done(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_pkex_remove(wpa_s, "*"); os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN); diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h index 5a4f06e2e..ecb7a7d68 100644 --- a/wpa_supplicant/dpp_supplicant.h +++ b/wpa_supplicant/dpp_supplicant.h @@ -10,12 +10,6 @@ #define DPP_SUPPLICANT_H 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_listen(struct wpa_supplicant *wpa_s, const char *cmd); 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); void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, 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_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_remove(struct wpa_supplicant *wpa_s, const char *id); void wpas_dpp_stop(struct wpa_supplicant *wpa_s); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index bcc0693ea..b15877eaa 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -673,6 +673,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) #ifdef CONFIG_DPP wpas_dpp_deinit(wpa_s); + dpp_global_deinit(wpa_s->dpp); + wpa_s->dpp = NULL; #endif /* CONFIG_DPP */ } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 0db6e551d..267a09eb0 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1207,9 +1207,7 @@ struct wpa_supplicant { int last_auth_timeout_sec; #ifdef CONFIG_DPP - struct dl_list dpp_bootstrap; /* struct dpp_bootstrap_info */ - struct dl_list dpp_configurator; /* struct dpp_configurator */ - int dpp_init_done; + struct dpp_global *dpp; struct dpp_authentication *dpp_auth; struct wpa_radio_work *dpp_listen_work; unsigned int dpp_pending_listen_freq;