Add initial parts for SAE
This introduces new AKM for SAE and FT-SAE and adds the initial parts for going through the SAE Authentication frame exchange. The actual SAE algorithm and new fields in Authentication frames are not yet included in this commit and will be added separately. This version is able to complete a dummy authentication with the correct authentication algorithm and transaction values to allow cfg80211/mac80211 drivers to be tested (all the missing parts can be handled with hostapd/wpa_supplicant changes). Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
905029097c
commit
c10347f246
19 changed files with 301 additions and 8 deletions
|
@ -199,6 +199,10 @@ NEED_AES_OMAC1=y
|
||||||
NEED_AES_UNWRAP=y
|
NEED_AES_UNWRAP=y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_SAE
|
||||||
|
L_CFLAGS += -DCONFIG_SAE
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_IEEE80211N
|
ifdef CONFIG_IEEE80211N
|
||||||
L_CFLAGS += -DCONFIG_IEEE80211N
|
L_CFLAGS += -DCONFIG_IEEE80211N
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -171,6 +171,10 @@ NEED_AES_OMAC1=y
|
||||||
NEED_AES_UNWRAP=y
|
NEED_AES_UNWRAP=y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_SAE
|
||||||
|
CFLAGS += -DCONFIG_SAE
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_IEEE80211V
|
ifdef CONFIG_IEEE80211V
|
||||||
CFLAGS += -DCONFIG_IEEE80211V
|
CFLAGS += -DCONFIG_IEEE80211V
|
||||||
OBJS += ../src/ap/wnm_ap.o
|
OBJS += ../src/ap/wnm_ap.o
|
||||||
|
|
|
@ -624,6 +624,12 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value)
|
||||||
else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
|
else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
|
||||||
val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
|
val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
else if (os_strcmp(start, "SAE") == 0)
|
||||||
|
val |= WPA_KEY_MGMT_SAE;
|
||||||
|
else if (os_strcmp(start, "FT-SAE") == 0)
|
||||||
|
val |= WPA_KEY_MGMT_FT_SAE;
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
else {
|
else {
|
||||||
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
|
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
|
||||||
line, start);
|
line, start);
|
||||||
|
|
|
@ -296,6 +296,51 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
} else if (auth_transaction == 2) {
|
||||||
|
if (sta->sae_state != SAE_COMMIT) {
|
||||||
|
hostapd_logger(hapd, sta->addr,
|
||||||
|
HOSTAPD_MODULE_IEEE80211,
|
||||||
|
HOSTAPD_LEVEL_DEBUG,
|
||||||
|
"SAE confirm before commit");
|
||||||
|
resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||||
|
HOSTAPD_LEVEL_DEBUG,
|
||||||
|
"unexpected SAE authentication transaction %u",
|
||||||
|
auth_transaction);
|
||||||
|
resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
sta->auth_alg = WLAN_AUTH_SAE;
|
||||||
|
|
||||||
|
send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
|
||||||
|
auth_transaction, resp, data, data_len);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
|
|
||||||
static void handle_auth(struct hostapd_data *hapd,
|
static void handle_auth(struct hostapd_data *hapd,
|
||||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -348,6 +393,10 @@ static void handle_auth(struct hostapd_data *hapd,
|
||||||
(hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
|
(hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
|
||||||
auth_alg == WLAN_AUTH_FT) ||
|
auth_alg == WLAN_AUTH_FT) ||
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
(hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
||||||
|
auth_alg == WLAN_AUTH_SAE) ||
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
|
((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
|
||||||
auth_alg == WLAN_AUTH_SHARED_KEY))) {
|
auth_alg == WLAN_AUTH_SHARED_KEY))) {
|
||||||
printf("Unsupported authentication algorithm (%d)\n",
|
printf("Unsupported authentication algorithm (%d)\n",
|
||||||
|
@ -356,7 +405,7 @@ static void handle_auth(struct hostapd_data *hapd,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(auth_transaction == 1 ||
|
if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
|
||||||
(auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
|
(auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
|
||||||
printf("Unknown authentication transaction number (%d)\n",
|
printf("Unknown authentication transaction number (%d)\n",
|
||||||
auth_transaction);
|
auth_transaction);
|
||||||
|
@ -486,6 +535,11 @@ static void handle_auth(struct hostapd_data *hapd,
|
||||||
/* handle_auth_ft_finish() callback will complete auth. */
|
/* handle_auth_ft_finish() callback will complete auth. */
|
||||||
return;
|
return;
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
case WLAN_AUTH_SAE:
|
||||||
|
handle_auth_sae(hapd, sta, mgmt, len, auth_transaction);
|
||||||
|
return;
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -779,6 +833,16 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
if (wpa_auth_uses_sae(sta->wpa_sm) &&
|
||||||
|
sta->auth_alg != WLAN_AUTH_SAE) {
|
||||||
|
wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
|
||||||
|
"SAE AKM after non-SAE auth_alg %u",
|
||||||
|
MAC2STR(sta->addr), sta->auth_alg);
|
||||||
|
return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
#ifdef CONFIG_IEEE80211N
|
||||||
if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
|
if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
|
||||||
wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
|
wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
|
||||||
|
|
|
@ -123,6 +123,10 @@ struct sta_info {
|
||||||
struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
|
struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
|
||||||
|
|
||||||
struct os_time connected_time;
|
struct os_time connected_time;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
enum { SAE_INIT, SAE_COMMIT, SAE_CONFIRM } sae_state;
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3056,3 +3056,11 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
|
||||||
wpa_send_eapol_timeout, wpa_auth, sm);
|
wpa_send_eapol_timeout, wpa_auth, sm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_auth_uses_sae(struct wpa_state_machine *sm)
|
||||||
|
{
|
||||||
|
if (sm == NULL)
|
||||||
|
return 0;
|
||||||
|
return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
|
||||||
|
}
|
||||||
|
|
|
@ -291,4 +291,6 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
#endif /* CONFIG_IEEE80211V */
|
#endif /* CONFIG_IEEE80211V */
|
||||||
|
|
||||||
|
int wpa_auth_uses_sae(struct wpa_state_machine *sm);
|
||||||
|
|
||||||
#endif /* WPA_AUTH_H */
|
#endif /* WPA_AUTH_H */
|
||||||
|
|
|
@ -188,6 +188,18 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||||
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
|
||||||
|
pos += RSN_SELECTOR_LEN;
|
||||||
|
num_suites++;
|
||||||
|
}
|
||||||
|
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
|
||||||
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
|
||||||
|
pos += RSN_SELECTOR_LEN;
|
||||||
|
num_suites++;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
#ifdef CONFIG_RSN_TESTING
|
#ifdef CONFIG_RSN_TESTING
|
||||||
if (rsn_testing) {
|
if (rsn_testing) {
|
||||||
|
@ -407,6 +419,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||||
selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
|
selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
|
||||||
|
selector = RSN_AUTH_KEY_MGMT_SAE;
|
||||||
|
else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE)
|
||||||
|
selector = RSN_AUTH_KEY_MGMT_FT_SAE;
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||||
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
|
else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
|
||||||
|
@ -479,6 +497,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||||
else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
|
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
else if (key_mgmt & WPA_KEY_MGMT_SAE)
|
||||||
|
sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE;
|
||||||
|
else if (key_mgmt & WPA_KEY_MGMT_FT_SAE)
|
||||||
|
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE;
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||||
else
|
else
|
||||||
|
|
|
@ -38,6 +38,8 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
|
||||||
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
|
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
|
||||||
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
|
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
|
||||||
#define WPA_KEY_MGMT_WPS BIT(9)
|
#define WPA_KEY_MGMT_WPS BIT(9)
|
||||||
|
#define WPA_KEY_MGMT_SAE BIT(10)
|
||||||
|
#define WPA_KEY_MGMT_FT_SAE BIT(11)
|
||||||
|
|
||||||
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
|
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
|
||||||
{
|
{
|
||||||
|
@ -50,13 +52,21 @@ static inline int wpa_key_mgmt_wpa_psk(int akm)
|
||||||
{
|
{
|
||||||
return !!(akm & (WPA_KEY_MGMT_PSK |
|
return !!(akm & (WPA_KEY_MGMT_PSK |
|
||||||
WPA_KEY_MGMT_FT_PSK |
|
WPA_KEY_MGMT_FT_PSK |
|
||||||
WPA_KEY_MGMT_PSK_SHA256));
|
WPA_KEY_MGMT_PSK_SHA256 |
|
||||||
|
WPA_KEY_MGMT_SAE));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int wpa_key_mgmt_ft(int akm)
|
static inline int wpa_key_mgmt_ft(int akm)
|
||||||
{
|
{
|
||||||
return !!(akm & (WPA_KEY_MGMT_FT_PSK |
|
return !!(akm & (WPA_KEY_MGMT_FT_PSK |
|
||||||
WPA_KEY_MGMT_FT_IEEE8021X));
|
WPA_KEY_MGMT_FT_IEEE8021X |
|
||||||
|
WPA_KEY_MGMT_FT_SAE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_key_mgmt_sae(int akm)
|
||||||
|
{
|
||||||
|
return !!(akm & (WPA_KEY_MGMT_SAE |
|
||||||
|
WPA_KEY_MGMT_FT_SAE));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int wpa_key_mgmt_sha256(int akm)
|
static inline int wpa_key_mgmt_sha256(int akm)
|
||||||
|
@ -84,6 +94,7 @@ static inline int wpa_key_mgmt_wpa_any(int akm)
|
||||||
#define WPA_AUTH_ALG_SHARED BIT(1)
|
#define WPA_AUTH_ALG_SHARED BIT(1)
|
||||||
#define WPA_AUTH_ALG_LEAP BIT(2)
|
#define WPA_AUTH_ALG_LEAP BIT(2)
|
||||||
#define WPA_AUTH_ALG_FT BIT(3)
|
#define WPA_AUTH_ALG_FT BIT(3)
|
||||||
|
#define WPA_AUTH_ALG_SAE BIT(4)
|
||||||
|
|
||||||
|
|
||||||
enum wpa_alg {
|
enum wpa_alg {
|
||||||
|
@ -121,7 +132,9 @@ enum wpa_key_mgmt {
|
||||||
KEY_MGMT_FT_PSK,
|
KEY_MGMT_FT_PSK,
|
||||||
KEY_MGMT_802_1X_SHA256,
|
KEY_MGMT_802_1X_SHA256,
|
||||||
KEY_MGMT_PSK_SHA256,
|
KEY_MGMT_PSK_SHA256,
|
||||||
KEY_MGMT_WPS
|
KEY_MGMT_WPS,
|
||||||
|
KEY_MGMT_SAE,
|
||||||
|
KEY_MGMT_FT_SAE
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
#define WLAN_AUTH_OPEN 0
|
#define WLAN_AUTH_OPEN 0
|
||||||
#define WLAN_AUTH_SHARED_KEY 1
|
#define WLAN_AUTH_SHARED_KEY 1
|
||||||
#define WLAN_AUTH_FT 2
|
#define WLAN_AUTH_FT 2
|
||||||
|
#define WLAN_AUTH_SAE 3
|
||||||
#define WLAN_AUTH_LEAP 128
|
#define WLAN_AUTH_LEAP 128
|
||||||
|
|
||||||
#define WLAN_AUTH_CHALLENGE_LEN 128
|
#define WLAN_AUTH_CHALLENGE_LEN 128
|
||||||
|
@ -157,6 +158,8 @@
|
||||||
#define WLAN_STATUS_REQ_REFUSED_SSPN 67
|
#define WLAN_STATUS_REQ_REFUSED_SSPN 67
|
||||||
#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68
|
#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68
|
||||||
#define WLAN_STATUS_INVALID_RSNIE 72
|
#define WLAN_STATUS_INVALID_RSNIE 72
|
||||||
|
#define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76
|
||||||
|
#define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77
|
||||||
#define WLAN_STATUS_TRANSMISSION_FAILURE 79
|
#define WLAN_STATUS_TRANSMISSION_FAILURE 79
|
||||||
|
|
||||||
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
|
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
|
||||||
|
|
|
@ -376,6 +376,12 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
|
||||||
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
|
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
|
||||||
return WPA_KEY_MGMT_PSK_SHA256;
|
return WPA_KEY_MGMT_PSK_SHA256;
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
|
||||||
|
return WPA_KEY_MGMT_SAE;
|
||||||
|
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
|
||||||
|
return WPA_KEY_MGMT_FT_SAE;
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NO_WPA2 */
|
#endif /* CONFIG_NO_WPA2 */
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
#define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
|
#define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
|
||||||
#define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
|
#define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
|
||||||
#define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
|
#define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
|
||||||
|
#define RSN_AUTH_KEY_MGMT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
|
||||||
|
#define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
|
||||||
|
|
||||||
#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
|
#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
|
||||||
#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
|
#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
|
||||||
|
|
|
@ -314,6 +314,9 @@ struct wpa_driver_auth_params {
|
||||||
*/
|
*/
|
||||||
int p2p;
|
int p2p;
|
||||||
|
|
||||||
|
const u8 *sae_data;
|
||||||
|
size_t sae_data_len;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum wps_mode {
|
enum wps_mode {
|
||||||
|
@ -834,6 +837,8 @@ struct wpa_driver_capa {
|
||||||
#define WPA_DRIVER_FLAGS_INACTIVITY_TIMER 0x00800000
|
#define WPA_DRIVER_FLAGS_INACTIVITY_TIMER 0x00800000
|
||||||
/* Driver expects user space implementation of MLME in AP mode */
|
/* Driver expects user space implementation of MLME in AP mode */
|
||||||
#define WPA_DRIVER_FLAGS_AP_MLME 0x01000000
|
#define WPA_DRIVER_FLAGS_AP_MLME 0x01000000
|
||||||
|
/* Driver supports SAE with user space SME */
|
||||||
|
#define WPA_DRIVER_FLAGS_SAE 0x02000000
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
int max_scan_ssids;
|
int max_scan_ssids;
|
||||||
|
|
|
@ -164,6 +164,12 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
|
||||||
} else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) {
|
} else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
} else if (key_mgmt == WPA_KEY_MGMT_SAE) {
|
||||||
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
|
||||||
|
} else if (key_mgmt == WPA_KEY_MGMT_FT_SAE) {
|
||||||
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
|
wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
|
||||||
key_mgmt);
|
key_mgmt);
|
||||||
|
|
|
@ -179,6 +179,10 @@ NEED_SHA256=y
|
||||||
NEED_AES_OMAC1=y
|
NEED_AES_OMAC1=y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_SAE
|
||||||
|
L_CFLAGS += -DCONFIG_SAE
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_TDLS
|
ifdef CONFIG_TDLS
|
||||||
L_CFLAGS += -DCONFIG_TDLS
|
L_CFLAGS += -DCONFIG_TDLS
|
||||||
OBJS += src/rsn_supp/tdls.c
|
OBJS += src/rsn_supp/tdls.c
|
||||||
|
|
|
@ -172,6 +172,10 @@ NEED_SHA256=y
|
||||||
NEED_AES_OMAC1=y
|
NEED_AES_OMAC1=y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_SAE
|
||||||
|
CFLAGS += -DCONFIG_SAE
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_IEEE80211V
|
ifdef CONFIG_IEEE80211V
|
||||||
CFLAGS += -DCONFIG_IEEE80211V
|
CFLAGS += -DCONFIG_IEEE80211V
|
||||||
OBJS += wnm_sta.o
|
OBJS += wnm_sta.o
|
||||||
|
|
|
@ -504,6 +504,12 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
|
||||||
else if (os_strcmp(start, "WPS") == 0)
|
else if (os_strcmp(start, "WPS") == 0)
|
||||||
val |= WPA_KEY_MGMT_WPS;
|
val |= WPA_KEY_MGMT_WPS;
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
else if (os_strcmp(start, "SAE") == 0)
|
||||||
|
val |= WPA_KEY_MGMT_SAE;
|
||||||
|
else if (os_strcmp(start, "FT-SAE") == 0)
|
||||||
|
val |= WPA_KEY_MGMT_FT_SAE;
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
else {
|
else {
|
||||||
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
|
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
|
||||||
line, start);
|
line, start);
|
||||||
|
|
|
@ -39,8 +39,47 @@ static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
|
||||||
|
|
||||||
void sme_authenticate(struct wpa_supplicant *wpa_s,
|
#ifdef CONFIG_SAE
|
||||||
struct wpa_bss *bss, struct wpa_ssid *ssid)
|
|
||||||
|
static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct wpabuf *buf;
|
||||||
|
|
||||||
|
buf = wpabuf_alloc(4 + 4);
|
||||||
|
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 */
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct wpabuf *buf;
|
||||||
|
|
||||||
|
buf = wpabuf_alloc(4 + 4);
|
||||||
|
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 */
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
|
|
||||||
|
void sme_send_authentication(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss, struct wpa_ssid *ssid,
|
||||||
|
int start)
|
||||||
{
|
{
|
||||||
struct wpa_driver_auth_params params;
|
struct wpa_driver_auth_params params;
|
||||||
struct wpa_ssid *old_ssid;
|
struct wpa_ssid *old_ssid;
|
||||||
|
@ -51,6 +90,7 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *md = NULL;
|
const u8 *md = NULL;
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
int i, bssid_changed;
|
int i, bssid_changed;
|
||||||
|
struct wpabuf *resp = NULL;
|
||||||
|
|
||||||
if (bss == NULL) {
|
if (bss == NULL) {
|
||||||
wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
|
wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
|
||||||
|
@ -95,6 +135,21 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
|
wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
|
||||||
"0x%x", params.auth_alg);
|
"0x%x", params.auth_alg);
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
|
||||||
|
const u8 *rsn;
|
||||||
|
struct wpa_ie_data ied;
|
||||||
|
|
||||||
|
rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
|
||||||
|
if (rsn &&
|
||||||
|
wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0) {
|
||||||
|
if (wpa_key_mgmt_sae(ied.key_mgmt)) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
|
||||||
|
params.auth_alg = WPA_AUTH_ALG_SAE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
for (i = 0; i < NUM_WEP_KEYS; i++) {
|
for (i = 0; i < NUM_WEP_KEYS; i++) {
|
||||||
if (ssid->wep_key_len[i])
|
if (ssid->wep_key_len[i])
|
||||||
|
@ -265,6 +320,19 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_INTERWORKING */
|
#endif /* CONFIG_INTERWORKING */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
if (params.auth_alg == WPA_AUTH_ALG_SAE) {
|
||||||
|
if (start)
|
||||||
|
resp = sme_auth_build_sae_commit(wpa_s);
|
||||||
|
else
|
||||||
|
resp = sme_auth_build_sae_confirm(wpa_s);
|
||||||
|
if (resp == NULL)
|
||||||
|
return;
|
||||||
|
params.sae_data = wpabuf_head(resp);
|
||||||
|
params.sae_data_len = wpabuf_len(resp);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
wpa_supplicant_cancel_sched_scan(wpa_s);
|
wpa_supplicant_cancel_sched_scan(wpa_s);
|
||||||
wpa_supplicant_cancel_scan(wpa_s);
|
wpa_supplicant_cancel_scan(wpa_s);
|
||||||
|
|
||||||
|
@ -287,6 +355,7 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
|
||||||
"driver failed");
|
"driver failed");
|
||||||
wpas_connection_failed(wpa_s, bss->bssid);
|
wpas_connection_failed(wpa_s, bss->bssid);
|
||||||
wpa_supplicant_mark_disassoc(wpa_s);
|
wpa_supplicant_mark_disassoc(wpa_s);
|
||||||
|
wpabuf_free(resp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,9 +366,47 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
|
||||||
* Association will be started based on the authentication event from
|
* Association will be started based on the authentication event from
|
||||||
* the driver.
|
* the driver.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
wpabuf_free(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sme_authenticate(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss, struct wpa_ssid *ssid)
|
||||||
|
{
|
||||||
|
sme_send_authentication(wpa_s, bss, ssid, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
|
||||||
|
u16 status_code, const u8 *data, size_t len)
|
||||||
|
{
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
|
||||||
|
"status code %u", auth_transaction, status_code);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "SME: SAE fields", data, len);
|
||||||
|
|
||||||
|
if (status_code != WLAN_STATUS_SUCCESS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (auth_transaction == 1) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
|
||||||
|
if (wpa_s->current_bss == NULL ||
|
||||||
|
wpa_s->current_ssid == NULL)
|
||||||
|
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");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
|
|
||||||
void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
|
void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
|
||||||
{
|
{
|
||||||
struct wpa_ssid *ssid = wpa_s->current_ssid;
|
struct wpa_ssid *ssid = wpa_s->current_ssid;
|
||||||
|
@ -324,14 +431,23 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
|
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
|
||||||
" auth_type=%d status_code=%d",
|
" auth_type=%d auth_transaction=%d status_code=%d",
|
||||||
MAC2STR(data->auth.peer), data->auth.auth_type,
|
MAC2STR(data->auth.peer), data->auth.auth_type,
|
||||||
data->auth.status_code);
|
data->auth.auth_transaction, data->auth.status_code);
|
||||||
wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
|
wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
|
||||||
data->auth.ies, data->auth.ies_len);
|
data->auth.ies, data->auth.ies_len);
|
||||||
|
|
||||||
eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
|
eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
|
||||||
|
|
||||||
|
#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)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
|
if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status "
|
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status "
|
||||||
"code %d)", data->auth.status_code);
|
"code %d)", data->auth.status_code);
|
||||||
|
|
|
@ -1073,6 +1073,10 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
sel = ie.key_mgmt & ssid->key_mgmt;
|
sel = ie.key_mgmt & ssid->key_mgmt;
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
|
||||||
|
sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
if (0) {
|
if (0) {
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
} else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
|
} else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
|
||||||
|
@ -1082,6 +1086,14 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
||||||
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
|
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
|
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
} else if (sel & WPA_KEY_MGMT_SAE) {
|
||||||
|
wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
|
||||||
|
} else if (sel & WPA_KEY_MGMT_FT_SAE) {
|
||||||
|
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
|
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
|
||||||
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
|
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||||
|
|
Loading…
Reference in a new issue