diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 506b781ab..8deb3f358 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -355,13 +355,11 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd, { struct wpabuf *buf; - buf = wpabuf_alloc(2); + buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN); if (buf == NULL) return NULL; - wpabuf_put_le16(buf, sta->sae->send_confirm); - sta->sae->send_confirm++; - /* TODO: Confirm */ + sae_write_confirm(sta->sae, buf); return buf; } diff --git a/src/common/sae.c b/src/common/sae.c index e628d4694..0adf0c011 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -542,3 +542,35 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len) return WLAN_STATUS_SUCCESS; } + + +void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) +{ + const u8 *sc; + const u8 *addr[5]; + size_t len[5]; + + /* Send-Confirm */ + sc = wpabuf_put(buf, 0); + wpabuf_put_le16(buf, sae->send_confirm); + sae->send_confirm++; + + /* Confirm + * CN(key, X, Y, Z, ...) = + * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...) + * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT, + * peer-commit-scalar, PEER-COMMIT-ELEMENT) + */ + addr[0] = sc; + len[0] = 2; + addr[1] = sae->own_commit_scalar; + len[1] = 32; + addr[2] = sae->own_commit_element; + len[2] = 2 * 32; + addr[3] = sae->peer_commit_scalar; + len[3] = 32; + addr[4] = sae->peer_commit_element; + len[4] = 2 * 32; + hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, len, + wpabuf_put(buf, SHA256_MAC_LEN)); +} diff --git a/src/common/sae.h b/src/common/sae.h index 4f689ed09..7b5a1241c 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -10,6 +10,7 @@ #define SAE_H #define SAE_COMMIT_MAX_LEN (2 + 3 * 32) +#define SAE_CONFIRM_MAX_LEN (2 + 32) struct sae_data { enum { SAE_INIT, SAE_COMMIT, SAE_CONFIRM } state; @@ -30,5 +31,6 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2, 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); #endif /* SAE_H */ diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index a5a90b5f8..a4a29dc9e 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -77,15 +77,13 @@ static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s) { struct wpabuf *buf; - buf = wpabuf_alloc(4 + 2); + buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN); if (buf == NULL) return NULL; wpabuf_put_le16(buf, 2); /* Transaction seq# */ wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); - wpabuf_put_le16(buf, wpa_s->sme.sae.send_confirm); - wpa_s->sme.sae.send_confirm++; - /* TODO: Confirm */ + sae_write_confirm(&wpa_s->sme.sae, buf); return buf; }