From dc4d271c6dc48254b7a1f547955bdd68a76e04f0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 18 Oct 2017 22:51:30 +0300 Subject: [PATCH] DPP: Update AES-SIV AD for DPP Authentication frames The protocol design was updated to protect the six octets in the header before the attributes. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 74 ++++-------- src/ap/drv_callbacks.c | 2 +- src/ap/ieee802_11.c | 2 +- src/common/dpp.c | 202 +++++++++++++++++++++----------- src/common/dpp.h | 16 +-- wpa_supplicant/dpp_supplicant.c | 74 ++++-------- wpa_supplicant/events.c | 4 +- 7 files changed, 196 insertions(+), 178 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index df0231ae2..a97ab1968 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -73,23 +73,14 @@ int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd) if (auth && auth->response_pending && dpp_notify_new_qr_code(auth, bi) == 1) { - struct wpabuf *msg; - wpa_printf(MSG_DEBUG, "DPP: Sending out pending authentication response"); - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, - wpabuf_len(auth->resp_attr)); - if (!msg) - goto out; - wpabuf_put_buf(msg, hapd->dpp_auth->resp_attr); - hostapd_drv_send_action(hapd, auth->curr_freq, 0, auth->peer_mac_addr, - wpabuf_head(msg), wpabuf_len(msg)); - wpabuf_free(msg); + wpabuf_head(hapd->dpp_auth->resp_msg), + wpabuf_len(hapd->dpp_auth->resp_msg)); } -out: return bi->id; } @@ -459,7 +450,6 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) { const char *pos; struct dpp_bootstrap_info *peer_bi, *own_bi = NULL; - struct wpabuf *msg; const u8 *dst; int res; int configurator = 1; @@ -521,12 +511,6 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) else hapd->dpp_auth->curr_freq = 2412; - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, - wpabuf_len(hapd->dpp_auth->req_attr)); - if (!msg) - return -1; - wpabuf_put_buf(msg, hapd->dpp_auth->req_attr); - if (is_zero_ether_addr(peer_bi->mac_addr)) { dst = broadcast; } else { @@ -537,8 +521,8 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) hapd->dpp_auth_ok_on_ack = 0; res = hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0, - dst, wpabuf_head(msg), wpabuf_len(msg)); - wpabuf_free(msg); + dst, wpabuf_head(hapd->dpp_auth->req_msg), + wpabuf_len(hapd->dpp_auth->req_msg)); return res; fail: @@ -549,12 +533,12 @@ fail: static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, - const u8 *buf, size_t len, unsigned int freq) + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) { const u8 *r_bootstrap, *i_bootstrap, *wrapped_data; u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len; struct dpp_bootstrap_info *bi, *own_bi = NULL, *peer_bi = NULL; - struct wpabuf *msg; wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR, MAC2STR(src)); @@ -630,7 +614,7 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, hapd->dpp_auth_ok_on_ack = 0; hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles, hapd->dpp_qr_mutual, - peer_bi, own_bi, freq, buf, + peer_bi, own_bi, freq, hdr, buf, wrapped_data, wrapped_data_len); if (!hapd->dpp_auth) { wpa_printf(MSG_DEBUG, "DPP: No response generated"); @@ -641,15 +625,9 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, hapd->dpp_configurator_params); os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN); - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, - wpabuf_len(hapd->dpp_auth->resp_attr)); - if (!msg) - return; - wpabuf_put_buf(msg, hapd->dpp_auth->resp_attr); - hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0, - src, wpabuf_head(msg), wpabuf_len(msg)); - wpabuf_free(msg); + src, wpabuf_head(hapd->dpp_auth->resp_msg), + wpabuf_len(hapd->dpp_auth->resp_msg)); } @@ -840,10 +818,10 @@ static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator) static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src, - const u8 *buf, size_t len) + const u8 *hdr, const u8 *buf, size_t len) { struct dpp_authentication *auth = hapd->dpp_auth; - struct wpabuf *msg, *attr; + struct wpabuf *msg; wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR, MAC2STR(src)); @@ -861,8 +839,8 @@ static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src, return; } - attr = dpp_auth_resp_rx(auth, buf, len); - if (!attr) { + msg = dpp_auth_resp_rx(auth, hdr, buf, len); + if (!msg) { if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) { wpa_printf(MSG_DEBUG, "DPP: Wait for full response"); return; @@ -872,14 +850,6 @@ static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src, } os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, wpabuf_len(attr)); - if (!msg) { - wpabuf_free(attr); - return; - } - wpabuf_put_buf(msg, attr); - wpabuf_free(attr); - hostapd_drv_send_action(hapd, auth->curr_freq, 0, src, wpabuf_head(msg), wpabuf_len(msg)); wpabuf_free(msg); @@ -888,7 +858,7 @@ static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src, static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src, - const u8 *buf, size_t len) + const u8 *hdr, const u8 *buf, size_t len) { struct dpp_authentication *auth = hapd->dpp_auth; @@ -907,7 +877,7 @@ static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src, return; } - if (dpp_auth_conf_rx(auth, buf, len) < 0) { + if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) { wpa_printf(MSG_DEBUG, "DPP: Authentication failed"); return; } @@ -1206,9 +1176,15 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, { u8 crypto_suite; enum dpp_public_action_frame_type type; + const u8 *hdr; - if (len < 2) + if (len < DPP_HDR_LEN) return; + if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE) + return; + hdr = buf; + buf += 4; + len -= 4; crypto_suite = *buf++; type = *buf++; len -= 2; @@ -1228,13 +1204,13 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, switch (type) { case DPP_PA_AUTHENTICATION_REQ: - hostapd_dpp_rx_auth_req(hapd, src, buf, len, freq); + hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq); break; case DPP_PA_AUTHENTICATION_RESP: - hostapd_dpp_rx_auth_resp(hapd, src, buf, len); + hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len); break; case DPP_PA_AUTHENTICATION_CONF: - hostapd_dpp_rx_auth_conf(hapd, src, buf, len); + hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len); break; case DPP_PA_PEER_DISCOVERY_REQ: hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq); diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 8841e843a..648f20e8e 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1005,7 +1005,7 @@ static void hostapd_action_rx(struct hostapd_data *hapd, DPP_OUI_TYPE) { const u8 *pos, *end; - pos = &mgmt->u.action.u.vs_public_action.variable[1]; + pos = mgmt->u.action.u.vs_public_action.oui; end = drv_mgmt->frame + drv_mgmt->frame_len; hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos, drv_mgmt->freq); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 6740241e1..65c4d8857 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3618,7 +3618,7 @@ static int handle_action(struct hostapd_data *hapd, DPP_OUI_TYPE) { const u8 *pos, *end; - pos = &mgmt->u.action.u.vs_public_action.variable[1]; + pos = mgmt->u.action.u.vs_public_action.oui; end = ((const u8 *) mgmt) + len; hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos, hapd->iface->freq); diff --git a/src/common/dpp.c b/src/common/dpp.c index 79ac49a7d..c1906791f 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1340,8 +1340,9 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1]; u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE]; u8 *pos; - const u8 *addr[1]; - size_t len[1], siv_len; + const u8 *addr[2]; + size_t len[2], siv_len, attr_len; + u8 *attr_start, *attr_end; auth = os_zalloc(sizeof(*auth)); if (!auth) @@ -1393,11 +1394,14 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, goto fail; /* Build DPP Authentication Request frame attributes */ - msg = wpabuf_alloc(2 * (4 + SHA256_MAC_LEN) + 4 + wpabuf_len(pi) + - 4 + sizeof(wrapped_data)); + attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + wpabuf_len(pi) + + 4 + sizeof(wrapped_data); + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len); if (!msg) goto fail; - auth->req_attr = msg; + auth->req_msg = msg; + + attr_start = wpabuf_put(msg, 0); /* Responder Bootstrapping Key Hash */ wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH); @@ -1437,13 +1441,22 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, DPP_CAPAB_ENROLLEE; *pos++ = auth->i_capab; - addr[0] = wpabuf_head(msg); - len[0] = wpabuf_len(msg); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + siv_len = pos - clear; wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len, - 1, addr, len, wrapped_data) < 0) + 2, addr, len, wrapped_data) < 0) goto fail; siv_len += AES_BLOCK_SIZE; wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", @@ -1859,8 +1872,9 @@ static int dpp_auth_build_resp(struct dpp_authentication *auth) u8 clear[DPP_AUTH_RESP_CLEAR_LEN]; u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE]; u8 *pos; - const u8 *addr[1]; - size_t len[1], siv_len; + const u8 *addr[2]; + size_t len[2], siv_len, attr_len; + u8 *attr_start, *attr_end; wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); @@ -1924,12 +1938,15 @@ static int dpp_auth_build_resp(struct dpp_authentication *auth) wrapped_r_auth, wrapped_r_auth_len); /* Build DPP Authentication Response frame attributes */ - msg = wpabuf_alloc(4 + 1 + 2 * (4 + SHA256_MAC_LEN) + - 4 + wpabuf_len(pr) + 4 + sizeof(wrapped_data)); + attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + + 4 + wpabuf_len(pr) + 4 + sizeof(wrapped_data); + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len); if (!msg) goto fail; - wpabuf_free(auth->resp_attr); - auth->resp_attr = msg; + wpabuf_free(auth->resp_msg); + auth->resp_msg = msg; + + attr_start = wpabuf_put(msg, 0); /* DPP Status */ wpabuf_put_le16(msg, DPP_ATTR_STATUS); @@ -1957,6 +1974,8 @@ static int dpp_auth_build_resp(struct dpp_authentication *auth) wpabuf_free(pr); pr = NULL; + attr_end = wpabuf_put(msg, 0); + /* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */ pos = clear; /* R-nonce */ @@ -1989,13 +2008,20 @@ static int dpp_auth_build_resp(struct dpp_authentication *auth) os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len); pos += wrapped_r_auth_len; - addr[0] = wpabuf_head(msg); - len[0] = wpabuf_len(msg); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + siv_len = pos - clear; wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); if (aes_siv_encrypt(auth->k2, auth->curve->hash_len, clear, siv_len, - 1, addr, len, wrapped_data) < 0) + 2, addr, len, wrapped_data) < 0) goto fail; siv_len += AES_BLOCK_SIZE; wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", @@ -2025,18 +2051,21 @@ static int dpp_auth_build_resp_status(struct dpp_authentication *auth, u8 clear[DPP_AUTH_RESP_CLEAR_LEN2]; u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN2 + AES_BLOCK_SIZE]; u8 *pos; - const u8 *addr[1]; - size_t len[1], siv_len; + const u8 *addr[2]; + size_t len[2], siv_len, attr_len; + u8 *attr_start, *attr_end; wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); /* Build DPP Authentication Response frame attributes */ - msg = wpabuf_alloc(4 + 1 + 2 * (4 + SHA256_MAC_LEN) + - 4 + sizeof(wrapped_data)); + attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + 4 + sizeof(wrapped_data); + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len); if (!msg) goto fail; - wpabuf_free(auth->resp_attr); - auth->resp_attr = msg; + wpabuf_free(auth->resp_msg); + auth->resp_msg = msg; + + attr_start = wpabuf_put(msg, 0); /* DPP Status */ wpabuf_put_le16(msg, DPP_ATTR_STATUS); @@ -2057,6 +2086,8 @@ static int dpp_auth_build_resp_status(struct dpp_authentication *auth, SHA256_MAC_LEN); } + attr_end = wpabuf_put(msg, 0); + /* Wrapped data ({I-nonce, R-capabilities}k1) */ pos = clear; /* I-nonce */ @@ -2076,13 +2107,20 @@ static int dpp_auth_build_resp_status(struct dpp_authentication *auth, DPP_CAPAB_ENROLLEE; *pos++ = auth->r_capab; - addr[0] = wpabuf_head(msg); - len[0] = wpabuf_len(msg); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + siv_len = pos - clear; wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len, - 1, addr, len, wrapped_data) < 0) + 2, addr, len, wrapped_data) < 0) goto fail; siv_len += AES_BLOCK_SIZE; wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", @@ -2106,14 +2144,14 @@ struct dpp_authentication * dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *own_bi, - unsigned int freq, const u8 *attr_start, + unsigned int freq, const u8 *hdr, const u8 *attr_start, const u8 *wrapped_data, u16 wrapped_data_len) { EVP_PKEY *pi = NULL; EVP_PKEY_CTX *ctx = NULL; size_t secret_len; - const u8 *addr[1]; - size_t len[1]; + const u8 *addr[2]; + size_t len[2]; u8 *unwrapped = NULL; size_t unwrapped_len = 0; const u8 *i_proto, *i_nonce, *i_capab, *i_bootstrap; @@ -2176,9 +2214,12 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, auth->curve->hash_len) < 0) goto fail; - addr[0] = attr_start; - len[0] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); + 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; @@ -2187,7 +2228,7 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, goto fail; if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, wrapped_data, wrapped_data_len, - 1, addr, len, unwrapped) < 0) { + 2, addr, len, unwrapped) < 0) { wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed"); goto fail; } @@ -2326,19 +2367,23 @@ static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth) struct wpabuf *msg; u8 i_auth[4 + DPP_MAX_HASH_LEN]; size_t i_auth_len; - const u8 *addr[1]; - size_t len[1]; + const u8 *addr[2]; + size_t len[2], attr_len; u8 *wrapped_i_auth; + u8 *attr_start, *attr_end; wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation"); i_auth_len = 4 + auth->curve->hash_len; /* Build DPP Authentication Confirmation frame attributes */ - msg = wpabuf_alloc(4 + 1 + 2 * (4 + SHA256_MAC_LEN) + - 4 + i_auth_len + AES_BLOCK_SIZE); + attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + + 4 + i_auth_len + AES_BLOCK_SIZE; + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len); if (!msg) goto fail; + attr_start = wpabuf_put(msg, 0); + /* DPP Status */ wpabuf_put_le16(msg, DPP_ATTR_STATUS); wpabuf_put_le16(msg, 1); @@ -2357,8 +2402,18 @@ static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth) wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN); } - addr[0] = wpabuf_head(msg); - len[0] = wpabuf_len(msg); + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE); wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE); @@ -2368,7 +2423,7 @@ static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth) if (dpp_gen_i_auth(auth, i_auth + 4) < 0 || aes_siv_encrypt(auth->ke, auth->curve->hash_len, i_auth, i_auth_len, - 1, addr, len, wrapped_i_auth) < 0) + 2, addr, len, wrapped_i_auth) < 0) goto fail; wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke", wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE); @@ -2386,13 +2441,13 @@ fail: static void -dpp_auth_resp_rx_status(struct dpp_authentication *auth, +dpp_auth_resp_rx_status(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[1]; - size_t len[1]; + const u8 *addr[2]; + size_t len[2]; u8 *unwrapped = NULL; size_t unwrapped_len = 0; const u8 *i_nonce, *r_capab; @@ -2411,9 +2466,12 @@ dpp_auth_resp_rx_status(struct dpp_authentication *auth, return; } - addr[0] = attr_start; - len[0] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); + 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; @@ -2422,7 +2480,7 @@ dpp_auth_resp_rx_status(struct dpp_authentication *auth, goto fail; if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, wrapped_data, wrapped_data_len, - 1, addr, len, unwrapped) < 0) { + 2, addr, len, unwrapped) < 0) { wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed"); goto fail; } @@ -2470,14 +2528,14 @@ fail: struct wpabuf * -dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *attr_start, - size_t attr_len) +dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) { EVP_PKEY *pr; EVP_PKEY_CTX *ctx = NULL; size_t secret_len; - const u8 *addr[1]; - size_t len[1]; + const u8 *addr[2]; + size_t len[2]; u8 *unwrapped = NULL, *unwrapped2 = NULL; size_t unwrapped_len = 0, unwrapped2_len = 0; const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto, @@ -2551,7 +2609,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *attr_start, wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); auth->auth_resp_status = status[0]; if (status[0] != DPP_STATUS_OK) { - dpp_auth_resp_rx_status(auth, attr_start, + dpp_auth_resp_rx_status(auth, hdr, attr_start, attr_len, wrapped_data, wrapped_data_len, status[0]); return NULL; @@ -2599,9 +2657,12 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *attr_start, auth->curve->hash_len) < 0) goto fail; - addr[0] = attr_start; - len[0] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); + 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; @@ -2610,7 +2671,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *attr_start, goto fail; if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, wrapped_data, wrapped_data_len, - 1, addr, len, unwrapped) < 0) { + 2, addr, len, unwrapped) < 0) { wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed"); goto fail; } @@ -2731,14 +2792,14 @@ fail: } -int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *attr_start, - size_t attr_len) +int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) { const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth; u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, i_auth_len; - const u8 *addr[1]; - size_t len[1]; + const u8 *addr[2]; + size_t len[2]; u8 *unwrapped = NULL; size_t unwrapped_len = 0; u8 i_auth2[DPP_MAX_HASH_LEN]; @@ -2812,9 +2873,12 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *attr_start, return -1; } - addr[0] = attr_start; - len[0] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); + 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; @@ -2823,7 +2887,7 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *attr_start, return -1; if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, wrapped_data, wrapped_data_len, - 1, addr, len, unwrapped) < 0) { + 2, addr, len, unwrapped) < 0) { wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed"); goto fail; } @@ -2882,8 +2946,8 @@ void dpp_auth_deinit(struct dpp_authentication *auth) dpp_configuration_free(auth->conf_sta); EVP_PKEY_free(auth->own_protocol_key); EVP_PKEY_free(auth->peer_protocol_key); - wpabuf_free(auth->req_attr); - wpabuf_free(auth->resp_attr); + wpabuf_free(auth->req_msg); + wpabuf_free(auth->resp_msg); wpabuf_free(auth->conf_req); os_free(auth->connector); wpabuf_free(auth->net_access_key); diff --git a/src/common/dpp.h b/src/common/dpp.h index 534036aa3..4011696ed 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -15,6 +15,8 @@ #include "common/wpa_common.h" #include "crypto/sha256.h" +#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */ + enum dpp_public_action_frame_type { DPP_PA_AUTHENTICATION_REQ = 0, DPP_PA_AUTHENTICATION_RESP = 1, @@ -151,8 +153,8 @@ struct dpp_authentication { u8 r_capab; EVP_PKEY *own_protocol_key; EVP_PKEY *peer_protocol_key; - struct wpabuf *req_attr; - struct wpabuf *resp_attr; + struct wpabuf *req_msg; + struct wpabuf *resp_msg; unsigned int curr_freq; size_t secret_len; u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; @@ -219,15 +221,15 @@ struct dpp_authentication * dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *own_bi, - unsigned int freq, const u8 *attr_start, + unsigned int freq, const u8 *hdr, const u8 *attr_start, const u8 *wrapped_data, u16 wrapped_data_len); struct wpabuf * -dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *attr_start, - size_t attr_len); +dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len); struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth, const char *json); -int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *attr_start, - size_t attr_len); +int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len); int dpp_notify_new_qr_code(struct dpp_authentication *auth, struct dpp_bootstrap_info *peer_bi); void dpp_configuration_free(struct dpp_configuration *conf); diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 50003e87e..1eb6fb35d 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -91,25 +91,16 @@ int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd) if (auth && auth->response_pending && dpp_notify_new_qr_code(auth, bi) == 1) { - struct wpabuf *msg; - wpa_printf(MSG_DEBUG, "DPP: Sending out pending authentication response"); - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, - wpabuf_len(auth->resp_attr)); - if (!msg) - goto out; - wpabuf_put_buf(msg, wpa_s->dpp_auth->resp_attr); - offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr, wpa_s->own_addr, broadcast, - wpabuf_head(msg), wpabuf_len(msg), + wpabuf_head(auth->resp_msg), + wpabuf_len(auth->resp_msg), 500, wpas_dpp_tx_status, 0); - wpabuf_free(msg); } -out: return bi->id; } @@ -508,7 +499,6 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) { const char *pos; struct dpp_bootstrap_info *peer_bi, *own_bi = NULL; - struct wpabuf *msg; const u8 *dst; int res; int configurator = 1; @@ -581,12 +571,6 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) else wpa_s->dpp_auth->curr_freq = 2412; - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, - wpabuf_len(wpa_s->dpp_auth->req_attr)); - if (!msg) - return -1; - wpabuf_put_buf(msg, wpa_s->dpp_auth->req_attr); - if (is_zero_ether_addr(peer_bi->mac_addr)) { dst = broadcast; } else { @@ -604,9 +588,9 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) wpa_s, NULL); res = offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq, dst, wpa_s->own_addr, broadcast, - wpabuf_head(msg), wpabuf_len(msg), + wpabuf_head(wpa_s->dpp_auth->req_msg), + wpabuf_len(wpa_s->dpp_auth->req_msg), wait_time, wpas_dpp_tx_status, 0); - wpabuf_free(msg); return res; fail: @@ -790,12 +774,12 @@ void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, - const u8 *buf, size_t len, unsigned int freq) + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) { const u8 *r_bootstrap, *i_bootstrap, *wrapped_data; u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len; struct dpp_bootstrap_info *bi, *own_bi = NULL, *peer_bi = NULL; - struct wpabuf *msg; wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR, MAC2STR(src)); @@ -872,7 +856,7 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, wpa_s->dpp_auth_ok_on_ack = 0; wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s, wpa_s->dpp_allowed_roles, wpa_s->dpp_qr_mutual, - peer_bi, own_bi, freq, buf, + peer_bi, own_bi, freq, hdr, buf, wrapped_data, wrapped_data_len); if (!wpa_s->dpp_auth) { wpa_printf(MSG_DEBUG, "DPP: No response generated"); @@ -883,17 +867,11 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, wpa_s->dpp_configurator_params); os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN); - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, - wpabuf_len(wpa_s->dpp_auth->resp_attr)); - if (!msg) - return; - wpabuf_put_buf(msg, wpa_s->dpp_auth->resp_attr); - offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq, src, wpa_s->own_addr, broadcast, - wpabuf_head(msg), wpabuf_len(msg), + wpabuf_head(wpa_s->dpp_auth->resp_msg), + wpabuf_len(wpa_s->dpp_auth->resp_msg), 500, wpas_dpp_tx_status, 0); - wpabuf_free(msg); } @@ -1183,10 +1161,10 @@ static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator) static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src, - const u8 *buf, size_t len) + const u8 *hdr, const u8 *buf, size_t len) { struct dpp_authentication *auth = wpa_s->dpp_auth; - struct wpabuf *msg, *attr; + struct wpabuf *msg; wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR, MAC2STR(src)); @@ -1206,8 +1184,8 @@ static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src, eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); - attr = dpp_auth_resp_rx(auth, buf, len); - if (!attr) { + msg = dpp_auth_resp_rx(auth, hdr, buf, len); + if (!msg) { if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) { wpa_printf(MSG_DEBUG, "DPP: Start wait for full response"); @@ -1220,14 +1198,6 @@ static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src, } os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, wpabuf_len(attr)); - if (!msg) { - wpabuf_free(attr); - return; - } - wpabuf_put_buf(msg, attr); - wpabuf_free(attr); - offchannel_send_action(wpa_s, auth->curr_freq, src, wpa_s->own_addr, broadcast, wpabuf_head(msg), wpabuf_len(msg), @@ -1238,7 +1208,7 @@ static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src, static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src, - const u8 *buf, size_t len) + const u8 *hdr, const u8 *buf, size_t len) { struct dpp_authentication *auth = wpa_s->dpp_auth; @@ -1257,7 +1227,7 @@ static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src, return; } - if (dpp_auth_conf_rx(auth, buf, len) < 0) { + if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) { wpa_printf(MSG_DEBUG, "DPP: Authentication failed"); return; } @@ -1589,9 +1559,15 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, { u8 crypto_suite; enum dpp_public_action_frame_type type; + const u8 *hdr; - if (len < 2) + if (len < DPP_HDR_LEN) return; + if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE) + return; + hdr = buf; + buf += 4; + len -= 4; crypto_suite = *buf++; type = *buf++; len -= 2; @@ -1611,13 +1587,13 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, switch (type) { case DPP_PA_AUTHENTICATION_REQ: - wpas_dpp_rx_auth_req(wpa_s, src, buf, len, freq); + wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq); break; case DPP_PA_AUTHENTICATION_RESP: - wpas_dpp_rx_auth_resp(wpa_s, src, buf, len); + wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len); break; case DPP_PA_AUTHENTICATION_CONF: - wpas_dpp_rx_auth_conf(wpa_s, src, buf, len); + wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len); break; case DPP_PA_PEER_DISCOVERY_RESP: wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 79df9b38a..820cc5265 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -3696,8 +3696,8 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s, payload[0] == WLAN_PA_VENDOR_SPECIFIC && WPA_GET_BE24(&payload[1]) == OUI_WFA && payload[4] == DPP_OUI_TYPE) { - payload += 5; - plen -= 5; + payload++; + plen--; wpas_dpp_rx_action(wpa_s, mgmt->sa, payload, plen, freq); return; }