DPP: Process Authentication Confirm failure cases

Process Authentication Confirm with the two failure cases defined in the
spec: STATUS_NOT_COMPATIBLE and STATUS_AUTH_FAILURE. This verifies the
{R-nonce}k2 part and reports more detailed failure reason if the message
is valid.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2017-10-28 17:40:06 +03:00 committed by Jouni Malinen
parent 7d917ab048
commit 19ef4289ca

View File

@ -3107,6 +3107,77 @@ fail:
}
static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth,
const u8 *hdr,
const u8 *attr_start, size_t attr_len,
const u8 *wrapped_data,
u16 wrapped_data_len,
enum dpp_status_error status)
{
const u8 *addr[2];
size_t len[2];
u8 *unwrapped = NULL;
size_t unwrapped_len = 0;
const u8 *r_nonce;
u16 r_nonce_len;
/* Authentication Confirm failure cases are expected to include
* {R-nonce}k2 in the Wrapped Data attribute. */
addr[0] = hdr;
len[0] = DPP_HDR_LEN;
addr[1] = attr_start;
len[1] = attr_len;
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) {
dpp_auth_fail(auth, "Authentication failed");
goto fail;
}
if (aes_siv_decrypt(auth->k2, 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;
}
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) {
dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce");
goto fail;
}
if (os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) {
wpa_hexdump(MSG_DEBUG, "DPP: Received R-nonce",
r_nonce, r_nonce_len);
wpa_hexdump(MSG_DEBUG, "DPP: Expected R-nonce",
auth->r_nonce, r_nonce_len);
dpp_auth_fail(auth, "R-nonce mismatch");
goto fail;
}
if (status == DPP_STATUS_NOT_COMPATIBLE)
dpp_auth_fail(auth, "Peer reported incompatible R-capab role");
else if (status == DPP_STATUS_AUTH_FAILURE)
dpp_auth_fail(auth, "Peer reported authentication failure)");
fail:
bin_clear_free(unwrapped, unwrapped_len);
return -1;
}
int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
const u8 *attr_start, size_t attr_len)
{
@ -3186,6 +3257,12 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
return -1;
}
wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
if (status[0] == DPP_STATUS_NOT_COMPATIBLE ||
status[0] == DPP_STATUS_AUTH_FAILURE)
return dpp_auth_conf_rx_failure(auth, hdr, attr_start,
attr_len, wrapped_data,
wrapped_data_len, status[0]);
if (status[0] != DPP_STATUS_OK) {
dpp_auth_fail(auth, "Authentication failed");
return -1;