diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 8deb3f358..3ecac9108 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -365,22 +365,6 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd, } -static u16 handle_sae_confirm(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *data, size_t len) -{ - u16 rc; - - wpa_hexdump(MSG_DEBUG, "SAE confirm fields", data, len); - - if (len < 2) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - rc = WPA_GET_LE16(data); - wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc); - - return WLAN_STATUS_SUCCESS; -} - - static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, const struct ieee80211_mgmt *mgmt, size_t len, u8 auth_transaction) @@ -418,10 +402,12 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "SAE authentication (RX confirm)"); - resp = handle_sae_confirm(hapd, sta, mgmt->u.auth.variable, - ((u8 *) mgmt) + len - - mgmt->u.auth.variable); - if (resp == WLAN_STATUS_SUCCESS) { + if (sae_check_confirm(sta->sae, mgmt->u.auth.variable, + ((u8 *) mgmt) + len - + mgmt->u.auth.variable) < 0) { + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + } else { + resp = WLAN_STATUS_SUCCESS; sta->flags |= WLAN_STA_AUTH; wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); sta->auth_alg = WLAN_AUTH_SAE; diff --git a/src/common/sae.c b/src/common/sae.c index 0adf0c011..19aa7afca 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -574,3 +574,51 @@ void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, len, wpabuf_put(buf, SHA256_MAC_LEN)); } + + +int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len) +{ + u16 rc; + const u8 *addr[5]; + size_t elen[5]; + u8 verifier[SHA256_MAC_LEN]; + + wpa_hexdump(MSG_DEBUG, "SAE: Confirm fields", data, len); + + if (len < 2 + SHA256_MAC_LEN) { + wpa_printf(MSG_DEBUG, "SAE: Too short confirm message"); + return -1; + } + + rc = WPA_GET_LE16(data); + wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc); + + /* Confirm + * CN(key, X, Y, Z, ...) = + * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...) + * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar, + * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT) + */ + addr[0] = data; + elen[0] = 2; + addr[1] = sae->peer_commit_scalar; + elen[1] = 32; + addr[2] = sae->peer_commit_element; + elen[2] = 2 * 32; + addr[3] = sae->own_commit_scalar; + elen[3] = 32; + addr[4] = sae->own_commit_element; + elen[4] = 2 * 32; + hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, elen, verifier); + + if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) { + wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch"); + wpa_hexdump(MSG_DEBUG, "SAE: Received confirm", + data + 2, SHA256_MAC_LEN); + wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier", + verifier, SHA256_MAC_LEN); + return -1; + } + + return 0; +} diff --git a/src/common/sae.h b/src/common/sae.h index 7b5a1241c..bfefd5da6 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -32,5 +32,6 @@ int sae_process_commit(struct sae_data *sae); void sae_write_commit(struct sae_data *sae, struct wpabuf *buf); u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len); void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf); +int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len); #endif /* SAE_H */ diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index a4a29dc9e..870313dae 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -399,21 +399,6 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, #ifdef CONFIG_SAE -static int sme_sae_process_confirm(struct wpa_supplicant *wpa_s, const u8 *data, - size_t len) -{ - u16 rc; - - if (len < 2) - return -1; - rc = WPA_GET_LE16(data); - wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc); - - /* TODO */ - return 0; -} - - static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, u16 status_code, const u8 *data, size_t len) { @@ -448,7 +433,7 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm"); if (wpa_s->sme.sae.state != SAE_CONFIRM) return -1; - if (sme_sae_process_confirm(wpa_s, data, len) < 0) + if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0) return -1; return 1; }