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:
parent
24b01c706b
commit
3e48c5d4b4
4 changed files with 169 additions and 2 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue