From 666497c8e65c3e6981d0c142a442dd7202c5d0b4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Nov 2014 13:20:51 +0200 Subject: [PATCH] Suite B: Add AKM 00-0F-AC:11 This adds definitions for the 128-bit level Suite B AKM 00-0F-AC:11. The functionality itself is not yet complete, i.e., this commit only includes parts to negotiate the new AKM. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 2 ++ hostapd/ctrl_iface.c | 6 ++++++ src/ap/wpa_auth_ie.c | 9 +++++++++ src/common/defs.h | 12 ++++++++++-- src/common/ieee802_11_defs.h | 1 + src/common/wpa_common.c | 6 ++++++ src/drivers/driver_nl80211.c | 6 +++++- src/rsn_supp/peerkey.c | 3 ++- src/rsn_supp/preauth.c | 3 ++- src/rsn_supp/wpa.c | 2 ++ src/rsn_supp/wpa_ie.c | 2 ++ wlantest/ctrl.c | 3 +++ wlantest/sta.c | 4 +++- wpa_supplicant/config.c | 12 ++++++++++++ wpa_supplicant/ctrl_iface.c | 8 ++++++++ wpa_supplicant/dbus/dbus_new_handlers.c | 4 +++- wpa_supplicant/wpa_supplicant.c | 7 ++++++- 17 files changed, 82 insertions(+), 8 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index f98e957a6..ea7a018e8 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -680,6 +680,8 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value) else if (os_strcmp(start, "FT-SAE") == 0) val |= WPA_KEY_MGMT_FT_SAE; #endif /* CONFIG_SAE */ + else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B; else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index c04565884..162a642e1 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -977,6 +977,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, pos += ret; } #endif /* CONFIG_SAE */ + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { + ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } ret = os_snprintf(pos, end - pos, "\n"); if (ret < 0 || ret >= end - pos) diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 1e4defcf1..c926765d0 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -200,6 +200,11 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, num_suites++; } #endif /* CONFIG_SAE */ + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B); + pos += RSN_SELECTOR_LEN; + num_suites++; + } #ifdef CONFIG_RSN_TESTING if (rsn_testing) { @@ -477,6 +482,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; if (0) { } + else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) + selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B; #ifdef CONFIG_IEEE80211R else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) selector = RSN_AUTH_KEY_MGMT_FT_802_1X; @@ -555,6 +562,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, } if (0) { } + else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) + sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B; #ifdef CONFIG_IEEE80211R else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; diff --git a/src/common/defs.h b/src/common/defs.h index bf992e00b..2efb98577 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -49,6 +49,7 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_KEY_MGMT_WAPI_CERT BIT(13) #define WPA_KEY_MGMT_CCKM BIT(14) #define WPA_KEY_MGMT_OSEN BIT(15) +#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16) static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) { @@ -56,7 +57,8 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_CCKM | WPA_KEY_MGMT_OSEN | - WPA_KEY_MGMT_IEEE8021X_SHA256)); + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SUITE_B)); } static inline int wpa_key_mgmt_wpa_psk(int akm) @@ -85,7 +87,13 @@ static inline int wpa_key_mgmt_sha256(int akm) { return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_IEEE8021X_SHA256 | - WPA_KEY_MGMT_OSEN)); + WPA_KEY_MGMT_OSEN | + WPA_KEY_MGMT_IEEE8021X_SUITE_B)); +} + +static inline int wpa_key_mgmt_suite_b(int akm) +{ + return !!(akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B); } static inline int wpa_key_mgmt_wpa(int akm) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index f5adbc026..8bcd109fe 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1164,6 +1164,7 @@ enum plink_action_field { #define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 #define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05 #define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06 +#define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC11 #define WLAN_AKM_SUITE_CCKM 0x00409600 #define WLAN_AKM_SUITE_OSEN 0x506f9a01 diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 7aeb706c2..897f726ee 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -398,6 +398,8 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE) return WPA_KEY_MGMT_FT_SAE; #endif /* CONFIG_SAE */ + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B) + return WPA_KEY_MGMT_IEEE8021X_SUITE_B; return 0; } @@ -996,6 +998,8 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto) case WPA_KEY_MGMT_PSK_SHA256: return "WPA2-PSK-SHA256"; #endif /* CONFIG_IEEE80211W */ + case WPA_KEY_MGMT_IEEE8021X_SUITE_B: + return "WPA2-EAP-SUITE-B"; default: return "UNKNOWN"; } @@ -1022,6 +1026,8 @@ u32 wpa_akm_to_suite(int akm) return WLAN_AKM_SUITE_CCKM; if (akm & WPA_KEY_MGMT_OSEN) return WLAN_AKM_SUITE_OSEN; + if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B) + return WLAN_AKM_SUITE_8021X_SUITE_B; return 0; } diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 68afcf01e..cf4e540b1 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5237,7 +5237,8 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, params->key_mgmt_suite == WPA_KEY_MGMT_CCKM || params->key_mgmt_suite == WPA_KEY_MGMT_OSEN || params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || - params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256) { + params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 || + params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B) { int mgmt = WLAN_AKM_SUITE_PSK; switch (params->key_mgmt_suite) { @@ -5262,6 +5263,9 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, case WPA_KEY_MGMT_OSEN: mgmt = WLAN_AKM_SUITE_OSEN; break; + case WPA_KEY_MGMT_IEEE8021X_SUITE_B: + mgmt = WLAN_AKM_SUITE_8021X_SUITE_B; + break; case WPA_KEY_MGMT_PSK: default: mgmt = WLAN_AKM_SUITE_PSK; diff --git a/src/rsn_supp/peerkey.c b/src/rsn_supp/peerkey.c index aab8b7e67..48b6f13bd 100644 --- a/src/rsn_supp/peerkey.c +++ b/src/rsn_supp/peerkey.c @@ -242,7 +242,8 @@ static int wpa_supplicant_process_smk_m2( peerkey->cipher = cipher; #ifdef CONFIG_IEEE80211W if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 | - WPA_KEY_MGMT_PSK_SHA256)) + WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SUITE_B)) peerkey->use_sha256 = 1; #endif /* CONFIG_IEEE80211W */ diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c index 0e4f01239..e3921254c 100644 --- a/src/rsn_supp/preauth.c +++ b/src/rsn_supp/preauth.c @@ -298,7 +298,8 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm) sm->proto != WPA_PROTO_RSN || wpa_sm_get_state(sm) != WPA_COMPLETED || (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X && - sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256)) { + sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256 && + sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SUITE_B)) { wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable " "state for new pre-authentication"); return; /* invalid state for new pre-auth */ diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index f8825d254..47e360731 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1925,6 +1925,8 @@ static u32 wpa_key_mgmt_suite(struct wpa_sm *sm) WPA_AUTH_KEY_MGMT_CCKM); case WPA_KEY_MGMT_WPA_NONE: return WPA_AUTH_KEY_MGMT_NONE; + case WPA_KEY_MGMT_IEEE8021X_SUITE_B: + return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B; default: return 0; } diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 93e8cf692..51876eda2 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -173,6 +173,8 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, } else if (key_mgmt == WPA_KEY_MGMT_FT_SAE) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); #endif /* CONFIG_SAE */ + } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B); } else { wpa_printf(MSG_WARNING, "Invalid key management type (%d).", key_mgmt); diff --git a/wlantest/ctrl.c b/wlantest/ctrl.c index 7507c2f81..2b6d45396 100644 --- a/wlantest/ctrl.c +++ b/wlantest/ctrl.c @@ -942,6 +942,9 @@ static void info_print_key_mgmt(char *buf, size_t len, int key_mgmt) if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) pos += os_snprintf(pos, end - pos, "%sPSK-SHA256", pos == buf ? "" : " "); + if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) + pos += os_snprintf(pos, end - pos, "%sEAP-SUITE-B", + pos == buf ? "" : " "); } diff --git a/wlantest/sta.c b/wlantest/sta.c index 178c28f74..0cd5bd30d 100644 --- a/wlantest/sta.c +++ b/wlantest/sta.c @@ -170,7 +170,7 @@ skip_rsn_wpa: wpa_printf(MSG_INFO, "STA " MACSTR " proto=%s%s%s%s" "pairwise=%s%s%s%s%s%s%s" - "key_mgmt=%s%s%s%s%s%s%s%s%s" + "key_mgmt=%s%s%s%s%s%s%s%s%s%s" "rsn_capab=%s%s%s%s%s", MAC2STR(sta->addr), sta->proto == 0 ? "OPEN " : "", @@ -197,6 +197,8 @@ skip_rsn_wpa: sta->key_mgmt & WPA_KEY_MGMT_PSK_SHA256 ? "PSK-SHA256 " : "", sta->key_mgmt & WPA_KEY_MGMT_OSEN ? "OSEN " : "", + sta->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B ? + "EAP-SUITE-B " : "", sta->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "", sta->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ? "NO_PAIRWISE " : "", diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 8d1e1e072..637cdf11c 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -535,6 +535,8 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data, else if (os_strcmp(start, "OSEN") == 0) val |= WPA_KEY_MGMT_OSEN; #endif /* CONFIG_HS20 */ + else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B; else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); @@ -711,6 +713,16 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, } #endif /* CONFIG_HS20 */ + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { + ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B", + pos == buf ? "" : " "); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + if (pos == buf) { os_free(buf); buf = NULL; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 58480a7c0..1c4844ce3 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2155,6 +2155,14 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, } #endif /* CONFIG_IEEE80211W */ + if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { + ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B", + pos == start ? "" : "+"); + if (ret < 0 || ret >= end - pos) + return pos; + pos += ret; + } + pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); if (data.capabilities & WPA_CAPABILITY_PREAUTH) { diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index aaaf4f00d..eefc15d1d 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -3775,7 +3775,7 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter, DBusMessageIter iter_dict, variant_iter; const char *group; const char *pairwise[5]; /* max 5 pairwise ciphers is supported */ - const char *key_mgmt[7]; /* max 7 key managements may be supported */ + const char *key_mgmt[8]; /* max 8 key managements may be supported */ int n; if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, @@ -3799,6 +3799,8 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter, key_mgmt[n++] = "wpa-ft-eap"; if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) key_mgmt[n++] = "wpa-eap-sha256"; + if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) + key_mgmt[n++] = "wpa-eap-suite-b"; if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE) key_mgmt[n++] = "wpa-none"; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 5a4d8dc60..902102d4c 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1091,6 +1091,10 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE); #endif /* CONFIG_SAE */ if (0) { + } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { + wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B; + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: using KEY_MGMT 802.1X with Suite B"); #ifdef CONFIG_IEEE80211R } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) { wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; @@ -1927,7 +1931,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) if (wpa_s->conf->key_mgmt_offload) { if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X || - params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256) + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B) params.req_key_mgmt_offload = ssid->proactive_key_caching < 0 ? wpa_s->conf->okc : ssid->proactive_key_caching;