aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2012-12-30 20:31:19 (GMT)
committerJouni Malinen <j@w1.fi>2013-01-12 15:51:52 (GMT)
commitf2e9818f73215024944b2db648a03c64ba1b8cc5 (patch)
tree840b301df298eaad7564d68dcfc281ef2f05583c
parentfb8fcc2950009dcc65aa25564267147c5ec1b2b0 (diff)
downloadhostap-f2e9818f73215024944b2db648a03c64ba1b8cc5.zip
hostap-f2e9818f73215024944b2db648a03c64ba1b8cc5.tar.gz
hostap-f2e9818f73215024944b2db648a03c64ba1b8cc5.tar.bz2
SAE: Add processing of the confirm message
This adds validation of the received confirm messages for SAE. Signed-hostap: Jouni Malinen <j@w1.fi>
-rw-r--r--src/ap/ieee802_11.c26
-rw-r--r--src/common/sae.c48
-rw-r--r--src/common/sae.h1
-rw-r--r--wpa_supplicant/sme.c17
4 files changed, 56 insertions, 36 deletions
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 8deb3f3..3ecac91 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 0adf0c0..19aa7af 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 7b5a124..bfefd5d 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 a4a29dc..870313d 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;
}