SAE: Add Finite Cyclic Group negotiation and Send-Confirm
This replaces the previously used bogus test data in SAE messages with the first real field. The actual SAE authentication mechanism is still missing and the Scaler, Element, and Confirm fields are not included. Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
6d22a377bd
commit
21af6d15a8
4 changed files with 170 additions and 17 deletions
|
@ -297,19 +297,92 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
|
|||
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
|
||||
static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = wpabuf_alloc(2);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_le16(buf, 19); /* Finite Cyclic Group */
|
||||
/* TODO: Anti-Clogging Token (if requested) */
|
||||
/* TODO: Scalar */
|
||||
/* TODO: Element */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = wpabuf_alloc(2);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_le16(buf, sta->sae_send_confirm);
|
||||
sta->sae_send_confirm++;
|
||||
/* TODO: Confirm */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static u16 handle_sae_commit(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *data, size_t len)
|
||||
{
|
||||
wpa_hexdump(MSG_DEBUG, "SAE commit fields", data, len);
|
||||
|
||||
/* Check Finite Cyclic Group */
|
||||
if (len < 2)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
if (WPA_GET_LE16(data) != 19) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
|
||||
WPA_GET_LE16(data));
|
||||
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
u16 resp = WLAN_STATUS_SUCCESS;
|
||||
u8 *data = (u8 *) "TEST"; /* TODO */
|
||||
size_t data_len = 4;
|
||||
struct wpabuf *data;
|
||||
|
||||
if (auth_transaction == 1) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
"start SAE authentication (RX commit)");
|
||||
sta->sae_state = SAE_COMMIT;
|
||||
resp = handle_sae_commit(hapd, sta, mgmt->u.auth.variable,
|
||||
((u8 *) mgmt) + len -
|
||||
mgmt->u.auth.variable);
|
||||
if (resp == WLAN_STATUS_SUCCESS)
|
||||
sta->sae_state = SAE_COMMIT;
|
||||
} else if (auth_transaction == 2) {
|
||||
if (sta->sae_state != SAE_COMMIT) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
|
@ -321,10 +394,15 @@ 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)");
|
||||
sta->flags |= WLAN_STA_AUTH;
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
|
||||
sta->auth_alg = WLAN_AUTH_SAE;
|
||||
mlme_authenticate_indication(hapd, sta);
|
||||
resp = handle_sae_confirm(hapd, sta, mgmt->u.auth.variable,
|
||||
((u8 *) mgmt) + len -
|
||||
mgmt->u.auth.variable);
|
||||
if (resp == WLAN_STATUS_SUCCESS) {
|
||||
sta->flags |= WLAN_STA_AUTH;
|
||||
wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
|
||||
sta->auth_alg = WLAN_AUTH_SAE;
|
||||
mlme_authenticate_indication(hapd, sta);
|
||||
}
|
||||
} else {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG,
|
||||
|
@ -335,8 +413,21 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
|
||||
sta->auth_alg = WLAN_AUTH_SAE;
|
||||
|
||||
if (resp == WLAN_STATUS_SUCCESS) {
|
||||
if (auth_transaction == 1)
|
||||
data = auth_build_sae_commit(hapd, sta);
|
||||
else
|
||||
data = auth_build_sae_confirm(hapd, sta);
|
||||
if (data == NULL)
|
||||
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
} else
|
||||
data = NULL;
|
||||
|
||||
send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
|
||||
auth_transaction, resp, data, data_len);
|
||||
auth_transaction, resp,
|
||||
data ? wpabuf_head(data) : (u8 *) "",
|
||||
data ? wpabuf_len(data) : 0);
|
||||
wpabuf_free(data);
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
|
|
|
@ -126,6 +126,7 @@ struct sta_info {
|
|||
|
||||
#ifdef CONFIG_SAE
|
||||
enum { SAE_INIT, SAE_COMMIT, SAE_CONFIRM } sae_state;
|
||||
u16 sae_send_confirm;
|
||||
#endif /* CONFIG_SAE */
|
||||
};
|
||||
|
||||
|
|
|
@ -45,14 +45,16 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s)
|
|||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = wpabuf_alloc(4 + 4);
|
||||
buf = wpabuf_alloc(4 + 2);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_le16(buf, 1); /* Transaction seq# */
|
||||
wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
|
||||
wpabuf_put_str(buf, "TEST");
|
||||
/* TODO: full SAE commit */
|
||||
wpabuf_put_le16(buf, 19); /* Finite Cyclic Group */
|
||||
/* TODO: Anti-Clogging Token (if requested) */
|
||||
/* TODO: Scalar */
|
||||
/* TODO: Element */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -62,14 +64,15 @@ static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s)
|
|||
{
|
||||
struct wpabuf *buf;
|
||||
|
||||
buf = wpabuf_alloc(4 + 4);
|
||||
buf = wpabuf_alloc(4 + 2);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_put_le16(buf, 2); /* Transaction seq# */
|
||||
wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
|
||||
wpabuf_put_str(buf, "TEST");
|
||||
/* TODO: full SAE confirm */
|
||||
wpabuf_put_le16(buf, wpa_s->sme.sae_send_confirm);
|
||||
wpa_s->sme.sae_send_confirm++;
|
||||
/* TODO: Confirm */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -330,6 +333,7 @@ void sme_send_authentication(struct wpa_supplicant *wpa_s,
|
|||
return;
|
||||
params.sae_data = wpabuf_head(resp);
|
||||
params.sae_data_len = wpabuf_len(resp);
|
||||
wpa_s->sme.sae_state = start ? SME_SAE_COMMIT : SME_SAE_CONFIRM;
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
|
@ -374,11 +378,47 @@ void sme_send_authentication(struct wpa_supplicant *wpa_s,
|
|||
void sme_authenticate(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_bss *bss, struct wpa_ssid *ssid)
|
||||
{
|
||||
wpa_s->sme.sae_state = SME_SAE_INIT;
|
||||
wpa_s->sme.sae_send_confirm = 0;
|
||||
sme_send_authentication(wpa_s, bss, ssid, 1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
|
||||
static int sme_sae_process_commit(struct wpa_supplicant *wpa_s, const u8 *data,
|
||||
size_t len)
|
||||
{
|
||||
/* Check Finite Cyclic Group */
|
||||
if (len < 2)
|
||||
return -1;
|
||||
if (WPA_GET_LE16(data) != 19) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
|
||||
WPA_GET_LE16(data));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -394,11 +434,19 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
|
|||
if (wpa_s->current_bss == NULL ||
|
||||
wpa_s->current_ssid == NULL)
|
||||
return -1;
|
||||
if (wpa_s->sme.sae_state != SME_SAE_COMMIT)
|
||||
return -1;
|
||||
if (sme_sae_process_commit(wpa_s, data, len) < 0)
|
||||
return -1;
|
||||
sme_send_authentication(wpa_s, wpa_s->current_bss,
|
||||
wpa_s->current_ssid, 0);
|
||||
return 0;
|
||||
} else if (auth_transaction == 2) {
|
||||
wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
|
||||
if (wpa_s->sme.sae_state != SME_SAE_CONFIRM)
|
||||
return -1;
|
||||
if (sme_sae_process_confirm(wpa_s, data, len) < 0)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -441,9 +489,16 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
|
|||
|
||||
#ifdef CONFIG_SAE
|
||||
if (data->auth.auth_type == WLAN_AUTH_SAE) {
|
||||
if (sme_sae_auth(wpa_s, data->auth.auth_transaction,
|
||||
data->auth.status_code, data->auth.ies,
|
||||
data->auth.ies_len) != 1)
|
||||
int res;
|
||||
res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
|
||||
data->auth.status_code, data->auth.ies,
|
||||
data->auth.ies_len);
|
||||
if (res < 0) {
|
||||
wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
|
||||
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
|
||||
|
||||
}
|
||||
if (res != 1)
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
|
|
@ -467,6 +467,12 @@ struct wpa_supplicant {
|
|||
u8 sched_obss_scan;
|
||||
u16 obss_scan_int;
|
||||
u16 bss_max_idle_period;
|
||||
enum {
|
||||
SME_SAE_INIT,
|
||||
SME_SAE_COMMIT,
|
||||
SME_SAE_CONFIRM
|
||||
} sae_state;
|
||||
u16 sae_send_confirm;
|
||||
} sme;
|
||||
#endif /* CONFIG_SME */
|
||||
|
||||
|
|
Loading…
Reference in a new issue