SAE: Add processing of the confirm message
This adds validation of the received confirm messages for SAE. Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
fb8fcc2950
commit
f2e9818f73
4 changed files with 56 additions and 36 deletions
|
@ -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,
|
static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
const struct ieee80211_mgmt *mgmt, size_t len,
|
const struct ieee80211_mgmt *mgmt, size_t len,
|
||||||
u8 auth_transaction)
|
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_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||||
HOSTAPD_LEVEL_DEBUG,
|
HOSTAPD_LEVEL_DEBUG,
|
||||||
"SAE authentication (RX confirm)");
|
"SAE authentication (RX confirm)");
|
||||||
resp = handle_sae_confirm(hapd, sta, mgmt->u.auth.variable,
|
if (sae_check_confirm(sta->sae, mgmt->u.auth.variable,
|
||||||
((u8 *) mgmt) + len -
|
((u8 *) mgmt) + len -
|
||||||
mgmt->u.auth.variable);
|
mgmt->u.auth.variable) < 0) {
|
||||||
if (resp == WLAN_STATUS_SUCCESS) {
|
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
} else {
|
||||||
|
resp = WLAN_STATUS_SUCCESS;
|
||||||
sta->flags |= WLAN_STA_AUTH;
|
sta->flags |= WLAN_STA_AUTH;
|
||||||
wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
|
wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
|
||||||
sta->auth_alg = WLAN_AUTH_SAE;
|
sta->auth_alg = WLAN_AUTH_SAE;
|
||||||
|
|
|
@ -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,
|
hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, len,
|
||||||
wpabuf_put(buf, SHA256_MAC_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;
|
||||||
|
}
|
||||||
|
|
|
@ -32,5 +32,6 @@ int sae_process_commit(struct sae_data *sae);
|
||||||
void sae_write_commit(struct sae_data *sae, struct wpabuf *buf);
|
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);
|
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);
|
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 */
|
#endif /* SAE_H */
|
||||||
|
|
|
@ -399,21 +399,6 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
#ifdef CONFIG_SAE
|
#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,
|
static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
|
||||||
u16 status_code, const u8 *data, size_t len)
|
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");
|
wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
|
||||||
if (wpa_s->sme.sae.state != SAE_CONFIRM)
|
if (wpa_s->sme.sae.state != SAE_CONFIRM)
|
||||||
return -1;
|
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;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue