DPP2: Support multiple Config Objects in Enrollee

Process all received DPP Configuration Object attributes from
Configuration Result in Enrollee STA case. If wpa_supplicant is
configured to add networks automatically, this results in one network
being added for each included Configuration Object.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2019-09-27 01:08:56 +03:00 committed by Jouni Malinen
parent 7eb06a3369
commit 52d469de11
4 changed files with 192 additions and 104 deletions

View file

@ -607,47 +607,48 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd, static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
struct dpp_authentication *auth) struct dpp_authentication *auth,
struct dpp_config_obj *conf)
{ {
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED); wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s", wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
dpp_akm_str(auth->akm)); dpp_akm_str(conf->akm));
if (auth->ssid_len) if (conf->ssid_len)
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s", wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
wpa_ssid_txt(auth->ssid, auth->ssid_len)); wpa_ssid_txt(conf->ssid, conf->ssid_len));
if (auth->connector) { if (conf->connector) {
/* TODO: Save the Connector and consider using a command /* TODO: Save the Connector and consider using a command
* to fetch the value instead of sending an event with * to fetch the value instead of sending an event with
* it. The Connector could end up being larger than what * it. The Connector could end up being larger than what
* most clients are ready to receive as an event * most clients are ready to receive as an event
* message. */ * message. */
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s", wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
auth->connector); conf->connector);
} else if (auth->passphrase[0]) { } else if (conf->passphrase[0]) {
char hex[64 * 2 + 1]; char hex[64 * 2 + 1];
wpa_snprintf_hex(hex, sizeof(hex), wpa_snprintf_hex(hex, sizeof(hex),
(const u8 *) auth->passphrase, (const u8 *) conf->passphrase,
os_strlen(auth->passphrase)); os_strlen(conf->passphrase));
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s", wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
hex); hex);
} else if (auth->psk_set) { } else if (conf->psk_set) {
char hex[PMK_LEN * 2 + 1]; char hex[PMK_LEN * 2 + 1];
wpa_snprintf_hex(hex, sizeof(hex), auth->psk, PMK_LEN); wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s", wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
hex); hex);
} }
if (auth->c_sign_key) { if (conf->c_sign_key) {
char *hex; char *hex;
size_t hexlen; size_t hexlen;
hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1; hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
hex = os_malloc(hexlen); hex = os_malloc(hexlen);
if (hex) { if (hex) {
wpa_snprintf_hex(hex, hexlen, wpa_snprintf_hex(hex, hexlen,
wpabuf_head(auth->c_sign_key), wpabuf_head(conf->c_sign_key),
wpabuf_len(auth->c_sign_key)); wpabuf_len(conf->c_sign_key));
wpa_msg(hapd->msg_ctx, MSG_INFO, wpa_msg(hapd->msg_ctx, MSG_INFO,
DPP_EVENT_C_SIGN_KEY "%s", hex); DPP_EVENT_C_SIGN_KEY "%s", hex);
os_free(hex); os_free(hex);
@ -720,7 +721,7 @@ static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
goto fail; goto fail;
} }
hostapd_dpp_handle_config_obj(hapd, auth); hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
status = DPP_STATUS_OK; status = DPP_STATUS_OK;
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
if (dpp_test == DPP_TEST_REJECT_CONFIG) { if (dpp_test == DPP_TEST_REJECT_CONFIG) {
@ -1568,7 +1569,7 @@ int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx, if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
auth, cmd) == 0 && 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, &auth->conf_obj[0]);
ret = 0; ret = 0;
} }

View file

@ -742,6 +742,34 @@ const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len)
} }
static const u8 * dpp_get_attr_next(const u8 *prev, const u8 *buf, size_t len,
u16 req_id, u16 *ret_len)
{
u16 id, alen;
const u8 *pos, *end = buf + len;
if (!prev)
pos = buf;
else
pos = prev + WPA_GET_LE16(prev - 2);
while (end - pos >= 4) {
id = WPA_GET_LE16(pos);
pos += 2;
alen = WPA_GET_LE16(pos);
pos += 2;
if (alen > end - pos)
return NULL;
if (id == req_id) {
*ret_len = alen;
return pos;
}
pos += alen;
}
return NULL;
}
int dpp_check_attrs(const u8 *buf, size_t len) int dpp_check_attrs(const u8 *buf, size_t len)
{ {
const u8 *pos, *end; const u8 *pos, *end;
@ -4568,6 +4596,8 @@ int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx,
void dpp_auth_deinit(struct dpp_authentication *auth) void dpp_auth_deinit(struct dpp_authentication *auth)
{ {
unsigned int i;
if (!auth) if (!auth)
return; return;
dpp_configuration_free(auth->conf_ap); dpp_configuration_free(auth->conf_ap);
@ -4579,9 +4609,13 @@ void dpp_auth_deinit(struct dpp_authentication *auth)
wpabuf_free(auth->req_msg); wpabuf_free(auth->req_msg);
wpabuf_free(auth->resp_msg); wpabuf_free(auth->resp_msg);
wpabuf_free(auth->conf_req); wpabuf_free(auth->conf_req);
os_free(auth->connector); for (i = 0; i < auth->num_conf_obj; i++) {
struct dpp_config_obj *conf = &auth->conf_obj[i];
os_free(conf->connector);
wpabuf_free(conf->c_sign_key);
}
wpabuf_free(auth->net_access_key); wpabuf_free(auth->net_access_key);
wpabuf_free(auth->c_sign_key);
dpp_bootstrap_info_free(auth->tmp_own_bi); dpp_bootstrap_info_free(auth->tmp_own_bi);
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
os_free(auth->config_obj_override); os_free(auth->config_obj_override);
@ -5352,7 +5386,7 @@ fail:
} }
static int dpp_parse_cred_legacy(struct dpp_authentication *auth, static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
struct json_token *cred) struct json_token *cred)
{ {
struct json_token *pass, *psk_hex; struct json_token *pass, *psk_hex;
@ -5369,28 +5403,28 @@ static int dpp_parse_cred_legacy(struct dpp_authentication *auth,
pass->string, len); pass->string, len);
if (len < 8 || len > 63) if (len < 8 || len > 63)
return -1; return -1;
os_strlcpy(auth->passphrase, pass->string, os_strlcpy(conf->passphrase, pass->string,
sizeof(auth->passphrase)); sizeof(conf->passphrase));
} else if (psk_hex && psk_hex->type == JSON_STRING) { } else if (psk_hex && psk_hex->type == JSON_STRING) {
if (dpp_akm_sae(auth->akm) && !dpp_akm_psk(auth->akm)) { if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"DPP: Unexpected psk_hex with akm=sae"); "DPP: Unexpected psk_hex with akm=sae");
return -1; return -1;
} }
if (os_strlen(psk_hex->string) != PMK_LEN * 2 || if (os_strlen(psk_hex->string) != PMK_LEN * 2 ||
hexstr2bin(psk_hex->string, auth->psk, PMK_LEN) < 0) { hexstr2bin(psk_hex->string, conf->psk, PMK_LEN) < 0) {
wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding"); wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding");
return -1; return -1;
} }
wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK", wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK",
auth->psk, PMK_LEN); conf->psk, PMK_LEN);
auth->psk_set = 1; conf->psk_set = 1;
} else { } else {
wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found"); wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found");
return -1; return -1;
} }
if (dpp_akm_sae(auth->akm) && !auth->passphrase[0]) { if (dpp_akm_sae(conf->akm) && !conf->passphrase[0]) {
wpa_printf(MSG_DEBUG, "DPP: No pass for sae found"); wpa_printf(MSG_DEBUG, "DPP: No pass for sae found");
return -1; return -1;
} }
@ -5558,6 +5592,7 @@ int dpp_key_expired(const char *timestamp, os_time_t *expiry)
static int dpp_parse_connector(struct dpp_authentication *auth, static int dpp_parse_connector(struct dpp_authentication *auth,
struct dpp_config_obj *conf,
const unsigned char *payload, const unsigned char *payload,
u16 payload_len) u16 payload_len)
{ {
@ -5685,7 +5720,7 @@ static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash)
} }
static void dpp_copy_csign(struct dpp_authentication *auth, EVP_PKEY *csign) static void dpp_copy_csign(struct dpp_config_obj *conf, EVP_PKEY *csign)
{ {
unsigned char *der = NULL; unsigned char *der = NULL;
int der_len; int der_len;
@ -5693,13 +5728,14 @@ static void dpp_copy_csign(struct dpp_authentication *auth, EVP_PKEY *csign)
der_len = i2d_PUBKEY(csign, &der); der_len = i2d_PUBKEY(csign, &der);
if (der_len <= 0) if (der_len <= 0)
return; return;
wpabuf_free(auth->c_sign_key); wpabuf_free(conf->c_sign_key);
auth->c_sign_key = wpabuf_alloc_copy(der, der_len); conf->c_sign_key = wpabuf_alloc_copy(der, der_len);
OPENSSL_free(der); OPENSSL_free(der);
} }
static void dpp_copy_netaccesskey(struct dpp_authentication *auth) static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
struct dpp_config_obj *conf)
{ {
unsigned char *der = NULL; unsigned char *der = NULL;
int der_len; int der_len;
@ -5893,6 +5929,7 @@ fail:
static int dpp_parse_cred_dpp(struct dpp_authentication *auth, static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
struct dpp_config_obj *conf,
struct json_token *cred) struct json_token *cred)
{ {
struct dpp_signed_connector_info info; struct dpp_signed_connector_info info;
@ -5904,10 +5941,10 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
os_memset(&info, 0, sizeof(info)); os_memset(&info, 0, sizeof(info));
if (dpp_akm_psk(auth->akm) || dpp_akm_sae(auth->akm)) { if (dpp_akm_psk(conf->akm) || dpp_akm_sae(conf->akm)) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"DPP: Legacy credential included in Connector credential"); "DPP: Legacy credential included in Connector credential");
if (dpp_parse_cred_legacy(auth, cred) < 0) if (dpp_parse_cred_legacy(conf, cred) < 0)
return -1; return -1;
} }
@ -5946,16 +5983,17 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
signed_connector) != DPP_STATUS_OK) signed_connector) != DPP_STATUS_OK)
goto fail; goto fail;
if (dpp_parse_connector(auth, info.payload, info.payload_len) < 0) { if (dpp_parse_connector(auth, conf,
info.payload, info.payload_len) < 0) {
wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector"); wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector");
goto fail; goto fail;
} }
os_free(auth->connector); os_free(conf->connector);
auth->connector = os_strdup(signed_connector); conf->connector = os_strdup(signed_connector);
dpp_copy_csign(auth, csign_pub); dpp_copy_csign(conf, csign_pub);
dpp_copy_netaccesskey(auth); dpp_copy_netaccesskey(auth, conf);
ret = 0; ret = 0;
fail: fail:
@ -6009,6 +6047,7 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth,
{ {
int ret = -1; int ret = -1;
struct json_token *root, *token, *discovery, *cred; struct json_token *root, *token, *discovery, *cred;
struct dpp_config_obj *conf;
root = json_parse((const char *) conf_obj, conf_obj_len); root = json_parse((const char *) conf_obj, conf_obj_len);
if (!root) if (!root)
@ -6047,8 +6086,17 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth,
dpp_auth_fail(auth, "Too long discovery::ssid string value"); dpp_auth_fail(auth, "Too long discovery::ssid string value");
goto fail; goto fail;
} }
auth->ssid_len = os_strlen(token->string);
os_memcpy(auth->ssid, token->string, auth->ssid_len); if (auth->num_conf_obj == DPP_MAX_CONF_OBJ) {
wpa_printf(MSG_DEBUG,
"DPP: No room for this many Config Objects - ignore this one");
json_free(root);
return 0;
}
conf = &auth->conf_obj[auth->num_conf_obj++];
conf->ssid_len = os_strlen(token->string);
os_memcpy(conf->ssid, token->string, conf->ssid_len);
cred = json_get_member(root, "cred"); cred = json_get_member(root, "cred");
if (!cred || cred->type != JSON_OBJECT) { if (!cred || cred->type != JSON_OBJECT) {
@ -6061,13 +6109,13 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth,
dpp_auth_fail(auth, "No cred::akm string value found"); dpp_auth_fail(auth, "No cred::akm string value found");
goto fail; goto fail;
} }
auth->akm = dpp_akm_from_str(token->string); conf->akm = dpp_akm_from_str(token->string);
if (dpp_akm_legacy(auth->akm)) { if (dpp_akm_legacy(conf->akm)) {
if (dpp_parse_cred_legacy(auth, cred) < 0) if (dpp_parse_cred_legacy(conf, cred) < 0)
goto fail; goto fail;
} else if (dpp_akm_dpp(auth->akm)) { } else if (dpp_akm_dpp(conf->akm)) {
if (dpp_parse_cred_dpp(auth, cred) < 0) if (dpp_parse_cred_dpp(auth, conf, cred) < 0)
goto fail; goto fail;
} else { } else {
wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s", wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
@ -6164,17 +6212,22 @@ int dpp_conf_resp_rx(struct dpp_authentication *auth,
goto fail; goto fail;
} }
conf_obj = dpp_get_attr(unwrapped, unwrapped_len, conf_obj = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONFIG_OBJ,
DPP_ATTR_CONFIG_OBJ, &conf_obj_len); &conf_obj_len);
if (!conf_obj) { if (!conf_obj) {
dpp_auth_fail(auth, dpp_auth_fail(auth,
"Missing required Configuration Object attribute"); "Missing required Configuration Object attribute");
goto fail; goto fail;
} }
while (conf_obj) {
wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON", wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
conf_obj, conf_obj_len); conf_obj, conf_obj_len);
if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0) if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0)
goto fail; goto fail;
conf_obj = dpp_get_attr_next(conf_obj, unwrapped, unwrapped_len,
DPP_ATTR_CONFIG_OBJ,
&conf_obj_len);
}
#ifdef CONFIG_DPP2 #ifdef CONFIG_DPP2
status = dpp_get_attr(unwrapped, unwrapped_len, status = dpp_get_attr(unwrapped, unwrapped_len,
@ -6672,9 +6725,9 @@ int dpp_configurator_own_config(struct dpp_authentication *auth,
auth->own_protocol_key = dpp_gen_keypair(auth->curve); auth->own_protocol_key = dpp_gen_keypair(auth->curve);
if (!auth->own_protocol_key) if (!auth->own_protocol_key)
return -1; return -1;
dpp_copy_netaccesskey(auth); dpp_copy_netaccesskey(auth, &auth->conf_obj[0]);
auth->peer_protocol_key = auth->own_protocol_key; auth->peer_protocol_key = auth->own_protocol_key;
dpp_copy_csign(auth, auth->conf->csign); dpp_copy_csign(&auth->conf_obj[0], auth->conf->csign);
conf_obj = dpp_build_conf_obj(auth, ap, 0); conf_obj = dpp_build_conf_obj(auth, ap, 0);
if (!conf_obj) if (!conf_obj)

View file

@ -184,6 +184,8 @@ struct dpp_configuration {
int psk_set; int psk_set;
}; };
#define DPP_MAX_CONF_OBJ 10
struct dpp_authentication { struct dpp_authentication {
void *msg_ctx; void *msg_ctx;
u8 peer_version; u8 peer_version;
@ -241,6 +243,7 @@ struct dpp_authentication {
struct dpp_configuration *conf_sta; struct dpp_configuration *conf_sta;
struct dpp_configuration *conf2_sta; struct dpp_configuration *conf2_sta;
struct dpp_configurator *conf; struct dpp_configurator *conf;
struct dpp_config_obj {
char *connector; /* received signedConnector */ char *connector; /* received signedConnector */
u8 ssid[SSID_MAX_LEN]; u8 ssid[SSID_MAX_LEN];
u8 ssid_len; u8 ssid_len;
@ -248,9 +251,11 @@ struct dpp_authentication {
u8 psk[PMK_LEN]; u8 psk[PMK_LEN];
int psk_set; int psk_set;
enum dpp_akm akm; enum dpp_akm akm;
struct wpabuf *c_sign_key;
} conf_obj[DPP_MAX_CONF_OBJ];
unsigned int num_conf_obj;
struct wpabuf *net_access_key; struct wpabuf *net_access_key;
os_time_t net_access_key_expiry; os_time_t net_access_key_expiry;
struct wpabuf *c_sign_key;
int send_conn_status; int send_conn_status;
int conn_status_requested; int conn_status_requested;
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS

View file

@ -958,12 +958,13 @@ static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
struct dpp_authentication *auth) struct dpp_authentication *auth,
struct dpp_config_obj *conf)
{ {
struct wpa_ssid *ssid; struct wpa_ssid *ssid;
#ifdef CONFIG_DPP2 #ifdef CONFIG_DPP2
if (auth->akm == DPP_AKM_SAE) { if (conf->akm == DPP_AKM_SAE) {
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
struct wpa_driver_capa capa; struct wpa_driver_capa capa;
int res; int res;
@ -990,27 +991,27 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
wpa_config_set_network_defaults(ssid); wpa_config_set_network_defaults(ssid);
ssid->disabled = 1; ssid->disabled = 1;
ssid->ssid = os_malloc(auth->ssid_len); ssid->ssid = os_malloc(conf->ssid_len);
if (!ssid->ssid) if (!ssid->ssid)
goto fail; goto fail;
os_memcpy(ssid->ssid, auth->ssid, auth->ssid_len); os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
ssid->ssid_len = auth->ssid_len; ssid->ssid_len = conf->ssid_len;
if (auth->connector) { if (conf->connector) {
ssid->key_mgmt = WPA_KEY_MGMT_DPP; ssid->key_mgmt = WPA_KEY_MGMT_DPP;
ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
ssid->dpp_connector = os_strdup(auth->connector); ssid->dpp_connector = os_strdup(conf->connector);
if (!ssid->dpp_connector) if (!ssid->dpp_connector)
goto fail; goto fail;
} }
if (auth->c_sign_key) { if (conf->c_sign_key) {
ssid->dpp_csign = os_malloc(wpabuf_len(auth->c_sign_key)); ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
if (!ssid->dpp_csign) if (!ssid->dpp_csign)
goto fail; goto fail;
os_memcpy(ssid->dpp_csign, wpabuf_head(auth->c_sign_key), os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
wpabuf_len(auth->c_sign_key)); wpabuf_len(conf->c_sign_key));
ssid->dpp_csign_len = wpabuf_len(auth->c_sign_key); ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
} }
if (auth->net_access_key) { if (auth->net_access_key) {
@ -1025,31 +1026,31 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry; ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
} }
if (!auth->connector || dpp_akm_psk(auth->akm) || if (!conf->connector || dpp_akm_psk(conf->akm) ||
dpp_akm_sae(auth->akm)) { dpp_akm_sae(conf->akm)) {
if (!auth->connector) if (!conf->connector)
ssid->key_mgmt = 0; ssid->key_mgmt = 0;
if (dpp_akm_psk(auth->akm)) if (dpp_akm_psk(conf->akm))
ssid->key_mgmt |= WPA_KEY_MGMT_PSK | ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK; WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
if (dpp_akm_sae(auth->akm)) if (dpp_akm_sae(conf->akm))
ssid->key_mgmt |= WPA_KEY_MGMT_SAE | ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
WPA_KEY_MGMT_FT_SAE; WPA_KEY_MGMT_FT_SAE;
ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
if (auth->passphrase[0]) { if (conf->passphrase[0]) {
if (wpa_config_set_quoted(ssid, "psk", if (wpa_config_set_quoted(ssid, "psk",
auth->passphrase) < 0) conf->passphrase) < 0)
goto fail; goto fail;
wpa_config_update_psk(ssid); wpa_config_update_psk(ssid);
ssid->export_keys = 1; ssid->export_keys = 1;
} else { } else {
ssid->psk_set = auth->psk_set; ssid->psk_set = conf->psk_set;
os_memcpy(ssid->psk, auth->psk, PMK_LEN); os_memcpy(ssid->psk, conf->psk, PMK_LEN);
} }
} }
os_memcpy(wpa_s->dpp_last_ssid, auth->ssid, auth->ssid_len); os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
wpa_s->dpp_last_ssid_len = auth->ssid_len; wpa_s->dpp_last_ssid_len = conf->ssid_len;
return ssid; return ssid;
fail: fail:
@ -1060,14 +1061,15 @@ fail:
static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s, static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
struct dpp_authentication *auth) struct dpp_authentication *auth,
struct dpp_config_obj *conf)
{ {
struct wpa_ssid *ssid; struct wpa_ssid *ssid;
if (wpa_s->conf->dpp_config_processing < 1) if (wpa_s->conf->dpp_config_processing < 1)
return 0; return 0;
ssid = wpas_dpp_add_network(wpa_s, auth); ssid = wpas_dpp_add_network(wpa_s, auth, conf);
if (!ssid) if (!ssid)
return -1; return -1;
@ -1081,49 +1083,56 @@ static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration"); wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
#endif /* CONFIG_NO_CONFIG_WRITE */ #endif /* CONFIG_NO_CONFIG_WRITE */
if (wpa_s->conf->dpp_config_processing < 2)
return 0; return 0;
}
static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
struct dpp_authentication *auth)
{
if (wpa_s->conf->dpp_config_processing < 2)
return;
#ifdef CONFIG_DPP2 #ifdef CONFIG_DPP2
if (auth->peer_version >= 2) { if (auth->peer_version >= 2) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"DPP: Postpone connection attempt to wait for completion of DPP Configuration Result"); "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
auth->connect_on_tx_status = 1; auth->connect_on_tx_status = 1;
return 0; return;
} }
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
wpas_dpp_try_to_connect(wpa_s); wpas_dpp_try_to_connect(wpa_s);
return 0;
} }
static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s, static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
struct dpp_authentication *auth) struct dpp_authentication *auth,
struct dpp_config_obj *conf)
{ {
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED); wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
if (auth->ssid_len) if (conf->ssid_len)
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s", wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
wpa_ssid_txt(auth->ssid, auth->ssid_len)); wpa_ssid_txt(conf->ssid, conf->ssid_len));
if (auth->connector) { if (conf->connector) {
/* TODO: Save the Connector and consider using a command /* TODO: Save the Connector and consider using a command
* to fetch the value instead of sending an event with * to fetch the value instead of sending an event with
* it. The Connector could end up being larger than what * it. The Connector could end up being larger than what
* most clients are ready to receive as an event * most clients are ready to receive as an event
* message. */ * message. */
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s", wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
auth->connector); conf->connector);
} }
if (auth->c_sign_key) { if (conf->c_sign_key) {
char *hex; char *hex;
size_t hexlen; size_t hexlen;
hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1; hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
hex = os_malloc(hexlen); hex = os_malloc(hexlen);
if (hex) { if (hex) {
wpa_snprintf_hex(hex, hexlen, wpa_snprintf_hex(hex, hexlen,
wpabuf_head(auth->c_sign_key), wpabuf_head(conf->c_sign_key),
wpabuf_len(auth->c_sign_key)); wpabuf_len(conf->c_sign_key));
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s", wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
hex); hex);
os_free(hex); os_free(hex);
@ -1151,7 +1160,7 @@ static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
} }
} }
return wpas_dpp_process_config(wpa_s, auth); return wpas_dpp_process_config(wpa_s, auth, conf);
} }
@ -1165,6 +1174,7 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
struct dpp_authentication *auth = wpa_s->dpp_auth; struct dpp_authentication *auth = wpa_s->dpp_auth;
int res; int res;
enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED; enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
unsigned int i;
wpa_s->dpp_gas_dialog_token = -1; wpa_s->dpp_gas_dialog_token = -1;
@ -1202,9 +1212,14 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
goto fail; goto fail;
} }
res = wpas_dpp_handle_config_obj(wpa_s, auth); for (i = 0; i < auth->num_conf_obj; i++) {
res = wpas_dpp_handle_config_obj(wpa_s, auth,
&auth->conf_obj[i]);
if (res < 0) if (res < 0)
goto fail; goto fail;
}
if (auth->num_conf_obj)
wpas_dpp_post_process_config(wpa_s, auth);
status = DPP_STATUS_OK; status = DPP_STATUS_OK;
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
@ -1522,8 +1537,19 @@ static int wpas_dpp_process_conf_obj(void *ctx,
struct dpp_authentication *auth) struct dpp_authentication *auth)
{ {
struct wpa_supplicant *wpa_s = ctx; struct wpa_supplicant *wpa_s = ctx;
unsigned int i;
int res = -1;
return wpas_dpp_handle_config_obj(wpa_s, auth); for (i = 0; i < auth->num_conf_obj; i++) {
res = wpas_dpp_handle_config_obj(wpa_s, auth,
&auth->conf_obj[i]);
if (res)
break;
}
if (!res)
wpas_dpp_post_process_config(wpa_s, auth);
return res;
} }
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
@ -2193,7 +2219,10 @@ int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
wpas_dpp_set_testing_options(wpa_s, auth); wpas_dpp_set_testing_options(wpa_s, auth);
if (dpp_set_configurator(wpa_s->dpp, 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,
&auth->conf_obj[0]);
if (!ret)
wpas_dpp_post_process_config(wpa_s, auth);
dpp_auth_deinit(auth); dpp_auth_deinit(auth);
os_free(curve); os_free(curve);