]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP: Process Authentication Confirm failure cases
authorJouni Malinen <jouni@qca.qualcomm.com>
Sat, 28 Oct 2017 14:40:06 +0000 (17:40 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 28 Oct 2017 14:44:14 +0000 (17:44 +0300)
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>
src/common/dpp.c

index 154722b1217e4034898d923a1ae48b16ed6342b2..ae5fbd384748cdad4c2e6ee033e693390426bc77 100644 (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;