DPP2: Reconfig Authentication Confirm processing

Extend Enrollee functionality to process Reconfig Authentication
Confirm message and start GAS client.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2020-05-10 23:46:41 +03:00 committed by Jouni Malinen
parent 24b01c706b
commit 3e48c5d4b4
4 changed files with 169 additions and 2 deletions

View file

@ -4756,8 +4756,15 @@ static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
unsigned char *der = NULL; unsigned char *der = NULL;
int der_len; int der_len;
EC_KEY *eckey; EC_KEY *eckey;
EVP_PKEY *own_key;
eckey = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key); own_key = auth->own_protocol_key;
#ifdef CONFIG_DPP2
if (auth->reconfig_connector_key == DPP_CONFIG_REUSEKEY &&
auth->reconfig_old_protocol_key)
own_key = auth->reconfig_old_protocol_key;
#endif /* CONFIG_DPP2 */
eckey = EVP_PKEY_get1_EC_KEY(own_key);
if (!eckey) if (!eckey)
return; return;

View file

@ -243,6 +243,7 @@ struct dpp_authentication {
u8 waiting_pubkey_hash[SHA256_MAC_LEN]; u8 waiting_pubkey_hash[SHA256_MAC_LEN];
int response_pending; int response_pending;
int reconfig; int reconfig;
enum dpp_connector_key reconfig_connector_key;
enum dpp_status_error auth_resp_status; enum dpp_status_error auth_resp_status;
enum dpp_status_error conf_resp_status; enum dpp_status_error conf_resp_status;
u8 peer_mac_addr[ETH_ALEN]; u8 peer_mac_addr[ETH_ALEN];
@ -661,6 +662,8 @@ dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx,
struct wpabuf * struct wpabuf *
dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
const u8 *attr_start, size_t attr_len); const u8 *attr_start, size_t attr_len);
int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
const u8 *attr_start, size_t attr_len);
#endif /* CONFIG_DPP */ #endif /* CONFIG_DPP */
#endif /* DPP_H */ #endif /* DPP_H */

View file

@ -754,4 +754,128 @@ fail:
goto out; goto out;
} }
int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
const u8 *attr_start, size_t attr_len)
{
const u8 *trans_id, *version, *wrapped_data, *i_nonce, *r_nonce,
*reconfig_flags;
u16 trans_id_len, version_len, wrapped_data_len, i_nonce_len,
r_nonce_len, reconfig_flags_len;
const u8 *addr[2];
size_t len[2];
u8 *unwrapped = NULL;
size_t unwrapped_len = 0;
struct json_token *root = NULL, *token;
int res = -1;
if (!auth->reconfig || auth->configurator)
goto fail;
wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
&wrapped_data_len);
if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
dpp_auth_fail(auth,
"Missing or invalid required Wrapped Data attribute");
goto fail;
}
wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data",
wrapped_data, wrapped_data_len);
addr[0] = hdr;
len[0] = DPP_HDR_LEN;
addr[1] = attr_start;
len[1] = 0;
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
wrapped_data, wrapped_data_len);
unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
unwrapped = os_malloc(unwrapped_len);
if (!unwrapped)
goto fail;
if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
wrapped_data, wrapped_data_len,
2, addr, len, unwrapped) < 0) {
dpp_auth_fail(auth, "AES-SIV decryption failed");
goto fail;
}
wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
unwrapped, unwrapped_len);
if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
goto fail;
}
trans_id = dpp_get_attr(unwrapped, unwrapped_len,
DPP_ATTR_TRANSACTION_ID, &trans_id_len);
if (!trans_id || trans_id_len != 1 ||
trans_id[0] != auth->transaction_id) {
dpp_auth_fail(auth,
"Peer did not include valid Transaction ID");
goto fail;
}
version = dpp_get_attr(unwrapped, unwrapped_len,
DPP_ATTR_PROTOCOL_VERSION, &version_len);
if (!version || version_len < 1 || version[0] != DPP_VERSION) {
dpp_auth_fail(auth,
"Missing or invalid Protocol Version attribute");
goto fail;
}
i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
&i_nonce_len);
if (!i_nonce || i_nonce_len != auth->curve->nonce_len ||
os_memcmp(i_nonce, auth->i_nonce, i_nonce_len) != 0) {
dpp_auth_fail(auth, "Missing or invalid I-nonce");
goto fail;
}
wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
&r_nonce_len);
if (!r_nonce || r_nonce_len != auth->curve->nonce_len ||
os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) {
dpp_auth_fail(auth, "Missing or invalid R-nonce");
goto fail;
}
wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len);
reconfig_flags = dpp_get_attr(unwrapped, unwrapped_len,
DPP_ATTR_RECONFIG_FLAGS,
&reconfig_flags_len);
if (!reconfig_flags) {
dpp_auth_fail(auth, "Missing or invalid Reconfig-Flags");
goto fail;
}
wpa_hexdump_ascii(MSG_DEBUG, "DPP: Reconfig-Flags",
reconfig_flags, reconfig_flags_len);
root = json_parse((const char *) reconfig_flags, reconfig_flags_len);
if (!root) {
dpp_auth_fail(auth, "Could not parse Reconfig-Flags");
goto fail;
}
token = json_get_member(root, "connectorKey");
if (!token || token->type != JSON_NUMBER) {
dpp_auth_fail(auth, "No connectorKey in Reconfig-Flags");
goto fail;
}
if (token->number != DPP_CONFIG_REUSEKEY &&
token->number != DPP_CONFIG_REPLACEKEY) {
dpp_auth_fail(auth,
"Unsupported connectorKey value in Reconfig-Flags");
goto fail;
}
auth->reconfig_connector_key = token->number;
auth->reconfig_success = true;
res = 0;
fail:
json_free(root);
bin_clear_free(unwrapped, unwrapped_len);
return res;
}
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */

View file

@ -1374,7 +1374,8 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
wpa_s->dpp_gas_dialog_token = -1; wpa_s->dpp_gas_dialog_token = -1;
if (!auth || !auth->auth_success) { if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
return; return;
} }
@ -2007,6 +2008,35 @@ wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
wpas_dpp_start_gas_server(wpa_s); wpas_dpp_start_gas_server(wpa_s);
} }
static void
wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
const u8 *hdr, const u8 *buf, size_t len,
unsigned int freq)
{
struct dpp_authentication *auth = wpa_s->dpp_auth;
wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
MACSTR, MAC2STR(src));
if (!auth || !auth->reconfig || auth->configurator) {
wpa_printf(MSG_DEBUG,
"DPP: No DPP Reconfig Authentication in progress - drop");
return;
}
if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
return;
}
if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
return;
wpas_dpp_start_gas_client(wpa_s);
}
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
@ -2578,6 +2608,9 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
case DPP_PA_RECONFIG_AUTH_RESP: case DPP_PA_RECONFIG_AUTH_RESP:
wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq); wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
break; break;
case DPP_PA_RECONFIG_AUTH_CONF:
wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
break;
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
default: default:
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,