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:
parent
7eb06a3369
commit
52d469de11
4 changed files with 192 additions and 104 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
117
src/common/dpp.c
117
src/common/dpp.c
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue