Suite B: Add AKM 00-0F-AC:11
authorJouni Malinen <j@w1.fi>
Sun, 16 Nov 2014 11:20:51 +0000 (13:20 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 16 Nov 2014 11:20:51 +0000 (13:20 +0200)
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 <j@w1.fi>
17 files changed:
hostapd/config_file.c
hostapd/ctrl_iface.c
src/ap/wpa_auth_ie.c
src/common/defs.h
src/common/ieee802_11_defs.h
src/common/wpa_common.c
src/drivers/driver_nl80211.c
src/rsn_supp/peerkey.c
src/rsn_supp/preauth.c
src/rsn_supp/wpa.c
src/rsn_supp/wpa_ie.c
wlantest/ctrl.c
wlantest/sta.c
wpa_supplicant/config.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new_handlers.c
wpa_supplicant/wpa_supplicant.c

index f98e957..ea7a018 100644 (file)
@@ -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);
index c045658..162a642 100644 (file)
@@ -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)
index 1e4defc..c926765 100644 (file)
@@ -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;
index bf992e0..2efb985 100644 (file)
@@ -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)
index f5adbc0..8bcd109 100644 (file)
@@ -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
 
index 7aeb706..897f726 100644 (file)
@@ -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;
 }
 
index 68afcf0..cf4e540 100644 (file)
@@ -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;
index aab8b7e..48b6f13 100644 (file)
@@ -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 */
 
index 0e4f012..e392125 100644 (file)
@@ -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 */
index f8825d2..47e3607 100644 (file)
@@ -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;
        }
index 93e8cf6..51876ed 100644 (file)
@@ -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);
index 7507c2f..2b6d453 100644 (file)
@@ -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 ? "" : " ");
 }
 
 
index 178c28f..0cd5bd3 100644 (file)
@@ -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 " : "",
index 8d1e1e0..637cdf1 100644 (file)
@@ -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;
index 58480a7..1c4844c 100644 (file)
@@ -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) {
index aaaf4f0..eefc15d 100644 (file)
@@ -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";
 
index 5a4d8dc..902102d 100644 (file)
@@ -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;