HS 2.0R2: Add common OSEN definitions
[mech_eap.git] / src / common / wpa_common.c
index 36c308a..c9d0ccb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA/RSN - Shared functions for supplicant and authenticator
- * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -56,6 +56,11 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
        case WPA_KEY_INFO_TYPE_AES_128_CMAC:
                return omac1_aes_128(key, buf, len, mic);
 #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
+#ifdef CONFIG_HS20
+       case WPA_KEY_INFO_TYPE_AKM_DEFINED:
+               /* FIX: This should be based on negotiated AKM */
+               return omac1_aes_128(key, buf, len, mic);
+#endif /* CONFIG_HS20 */
        default:
                return -1;
        }
@@ -335,7 +340,6 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
 #endif /* CONFIG_IEEE80211R */
 
 
-#ifndef CONFIG_NO_WPA2
 static int rsn_selector_to_bitfield(const u8 *s)
 {
        if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
@@ -354,6 +358,16 @@ static int rsn_selector_to_bitfield(const u8 *s)
 #endif /* CONFIG_IEEE80211W */
        if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
                return WPA_CIPHER_GCMP;
+       if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256)
+               return WPA_CIPHER_CCMP_256;
+       if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256)
+               return WPA_CIPHER_GCMP_256;
+       if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128)
+               return WPA_CIPHER_BIP_GMAC_128;
+       if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256)
+               return WPA_CIPHER_BIP_GMAC_256;
+       if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256)
+               return WPA_CIPHER_BIP_CMAC_256;
        return 0;
 }
 
@@ -376,9 +390,14 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
        if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
                return WPA_KEY_MGMT_PSK_SHA256;
 #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;
 }
-#endif /* CONFIG_NO_WPA2 */
 
 
 /**
@@ -391,7 +410,6 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
 int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
                         struct wpa_ie_data *data)
 {
-#ifndef CONFIG_NO_WPA2
        const struct rsn_ie_hdr *hdr;
        const u8 *pos;
        int left;
@@ -545,9 +563,6 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
        }
 
        return 0;
-#else /* CONFIG_NO_WPA2 */
-       return -1;
-#endif /* CONFIG_NO_WPA2 */
 }
 
 
@@ -912,6 +927,12 @@ const char * wpa_cipher_txt(int cipher)
                return "CCMP+TKIP";
        case WPA_CIPHER_GCMP:
                return "GCMP";
+       case WPA_CIPHER_GCMP_256:
+               return "GCMP-256";
+       case WPA_CIPHER_CCMP_256:
+               return "CCMP-256";
+       case WPA_CIPHER_GTK_NOT_USED:
+               return "GTK_NOT_USED";
        default:
                return "UNKNOWN";
        }
@@ -1078,6 +1099,9 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
 int wpa_cipher_key_len(int cipher)
 {
        switch (cipher) {
+       case WPA_CIPHER_CCMP_256:
+       case WPA_CIPHER_GCMP_256:
+               return 32;
        case WPA_CIPHER_CCMP:
        case WPA_CIPHER_GCMP:
                return 16;
@@ -1096,6 +1120,8 @@ int wpa_cipher_key_len(int cipher)
 int wpa_cipher_rsc_len(int cipher)
 {
        switch (cipher) {
+       case WPA_CIPHER_CCMP_256:
+       case WPA_CIPHER_GCMP_256:
        case WPA_CIPHER_CCMP:
        case WPA_CIPHER_GCMP:
        case WPA_CIPHER_TKIP:
@@ -1112,6 +1138,10 @@ int wpa_cipher_rsc_len(int cipher)
 int wpa_cipher_to_alg(int cipher)
 {
        switch (cipher) {
+       case WPA_CIPHER_CCMP_256:
+               return WPA_ALG_CCMP_256;
+       case WPA_CIPHER_GCMP_256:
+               return WPA_ALG_GCMP_256;
        case WPA_CIPHER_CCMP:
                return WPA_ALG_CCMP;
        case WPA_CIPHER_GCMP:
@@ -1128,7 +1158,9 @@ int wpa_cipher_to_alg(int cipher)
 
 int wpa_cipher_valid_pairwise(int cipher)
 {
-       return cipher == WPA_CIPHER_CCMP ||
+       return cipher == WPA_CIPHER_CCMP_256 ||
+               cipher == WPA_CIPHER_GCMP_256 ||
+               cipher == WPA_CIPHER_CCMP ||
                cipher == WPA_CIPHER_GCMP ||
                cipher == WPA_CIPHER_TKIP;
 }
@@ -1136,6 +1168,10 @@ int wpa_cipher_valid_pairwise(int cipher)
 
 u32 wpa_cipher_to_suite(int proto, int cipher)
 {
+       if (cipher & WPA_CIPHER_CCMP_256)
+               return RSN_CIPHER_SUITE_CCMP_256;
+       if (cipher & WPA_CIPHER_GCMP_256)
+               return RSN_CIPHER_SUITE_GCMP_256;
        if (cipher & WPA_CIPHER_CCMP)
                return (proto == WPA_PROTO_RSN ?
                        RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
@@ -1153,6 +1189,8 @@ u32 wpa_cipher_to_suite(int proto, int cipher)
        if (cipher & WPA_CIPHER_NONE)
                return (proto == WPA_PROTO_RSN ?
                        RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
+       if (cipher & WPA_CIPHER_GTK_NOT_USED)
+               return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
        return 0;
 }
 
@@ -1161,6 +1199,16 @@ int rsn_cipher_put_suites(u8 *pos, int ciphers)
 {
        int num_suites = 0;
 
+       if (ciphers & WPA_CIPHER_CCMP_256) {
+               RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
+               pos += RSN_SELECTOR_LEN;
+               num_suites++;
+       }
+       if (ciphers & WPA_CIPHER_GCMP_256) {
+               RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
+               pos += RSN_SELECTOR_LEN;
+               num_suites++;
+       }
        if (ciphers & WPA_CIPHER_CCMP) {
                RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
                pos += RSN_SELECTOR_LEN;
@@ -1208,3 +1256,186 @@ int wpa_cipher_put_suites(u8 *pos, int ciphers)
 
        return num_suites;
 }
+
+
+int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
+{
+       if (ciphers & WPA_CIPHER_CCMP_256)
+               return WPA_CIPHER_CCMP_256;
+       if (ciphers & WPA_CIPHER_GCMP_256)
+               return WPA_CIPHER_GCMP_256;
+       if (ciphers & WPA_CIPHER_CCMP)
+               return WPA_CIPHER_CCMP;
+       if (ciphers & WPA_CIPHER_GCMP)
+               return WPA_CIPHER_GCMP;
+       if (ciphers & WPA_CIPHER_TKIP)
+               return WPA_CIPHER_TKIP;
+       if (none_allowed && (ciphers & WPA_CIPHER_NONE))
+               return WPA_CIPHER_NONE;
+       return -1;
+}
+
+
+int wpa_pick_group_cipher(int ciphers)
+{
+       if (ciphers & WPA_CIPHER_CCMP_256)
+               return WPA_CIPHER_CCMP_256;
+       if (ciphers & WPA_CIPHER_GCMP_256)
+               return WPA_CIPHER_GCMP_256;
+       if (ciphers & WPA_CIPHER_CCMP)
+               return WPA_CIPHER_CCMP;
+       if (ciphers & WPA_CIPHER_GCMP)
+               return WPA_CIPHER_GCMP;
+       if (ciphers & WPA_CIPHER_GTK_NOT_USED)
+               return WPA_CIPHER_GTK_NOT_USED;
+       if (ciphers & WPA_CIPHER_TKIP)
+               return WPA_CIPHER_TKIP;
+       if (ciphers & WPA_CIPHER_WEP104)
+               return WPA_CIPHER_WEP104;
+       if (ciphers & WPA_CIPHER_WEP40)
+               return WPA_CIPHER_WEP40;
+       return -1;
+}
+
+
+int wpa_parse_cipher(const char *value)
+{
+       int val = 0, last;
+       char *start, *end, *buf;
+
+       buf = os_strdup(value);
+       if (buf == NULL)
+               return -1;
+       start = buf;
+
+       while (*start != '\0') {
+               while (*start == ' ' || *start == '\t')
+                       start++;
+               if (*start == '\0')
+                       break;
+               end = start;
+               while (*end != ' ' && *end != '\t' && *end != '\0')
+                       end++;
+               last = *end == '\0';
+               *end = '\0';
+               if (os_strcmp(start, "CCMP-256") == 0)
+                       val |= WPA_CIPHER_CCMP_256;
+               else if (os_strcmp(start, "GCMP-256") == 0)
+                       val |= WPA_CIPHER_GCMP_256;
+               else if (os_strcmp(start, "CCMP") == 0)
+                       val |= WPA_CIPHER_CCMP;
+               else if (os_strcmp(start, "GCMP") == 0)
+                       val |= WPA_CIPHER_GCMP;
+               else if (os_strcmp(start, "TKIP") == 0)
+                       val |= WPA_CIPHER_TKIP;
+               else if (os_strcmp(start, "WEP104") == 0)
+                       val |= WPA_CIPHER_WEP104;
+               else if (os_strcmp(start, "WEP40") == 0)
+                       val |= WPA_CIPHER_WEP40;
+               else if (os_strcmp(start, "NONE") == 0)
+                       val |= WPA_CIPHER_NONE;
+               else if (os_strcmp(start, "GTK_NOT_USED") == 0)
+                       val |= WPA_CIPHER_GTK_NOT_USED;
+               else {
+                       os_free(buf);
+                       return -1;
+               }
+
+               if (last)
+                       break;
+               start = end + 1;
+       }
+       os_free(buf);
+
+       return val;
+}
+
+
+int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
+{
+       char *pos = start;
+       int ret;
+
+       if (ciphers & WPA_CIPHER_CCMP_256) {
+               ret = os_snprintf(pos, end - pos, "%sCCMP-256",
+                                 pos == start ? "" : delim);
+               if (ret < 0 || ret >= end - pos)
+                       return -1;
+               pos += ret;
+       }
+       if (ciphers & WPA_CIPHER_GCMP_256) {
+               ret = os_snprintf(pos, end - pos, "%sGCMP-256",
+                                 pos == start ? "" : delim);
+               if (ret < 0 || ret >= end - pos)
+                       return -1;
+               pos += ret;
+       }
+       if (ciphers & WPA_CIPHER_CCMP) {
+               ret = os_snprintf(pos, end - pos, "%sCCMP",
+                                 pos == start ? "" : delim);
+               if (ret < 0 || ret >= end - pos)
+                       return -1;
+               pos += ret;
+       }
+       if (ciphers & WPA_CIPHER_GCMP) {
+               ret = os_snprintf(pos, end - pos, "%sGCMP",
+                                 pos == start ? "" : delim);
+               if (ret < 0 || ret >= end - pos)
+                       return -1;
+               pos += ret;
+       }
+       if (ciphers & WPA_CIPHER_TKIP) {
+               ret = os_snprintf(pos, end - pos, "%sTKIP",
+                                 pos == start ? "" : delim);
+               if (ret < 0 || ret >= end - pos)
+                       return -1;
+               pos += ret;
+       }
+       if (ciphers & WPA_CIPHER_WEP104) {
+               ret = os_snprintf(pos, end - pos, "%sWEP104",
+                                 pos == start ? "" : delim);
+               if (ret < 0 || ret >= end - pos)
+                       return -1;
+               pos += ret;
+       }
+       if (ciphers & WPA_CIPHER_WEP40) {
+               ret = os_snprintf(pos, end - pos, "%sWEP40",
+                                 pos == start ? "" : delim);
+               if (ret < 0 || ret >= end - pos)
+                       return -1;
+               pos += ret;
+       }
+       if (ciphers & WPA_CIPHER_NONE) {
+               ret = os_snprintf(pos, end - pos, "%sNONE",
+                                 pos == start ? "" : delim);
+               if (ret < 0 || ret >= end - pos)
+                       return -1;
+               pos += ret;
+       }
+
+       return pos - start;
+}
+
+
+int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
+{
+       int pairwise = 0;
+
+       /* Select group cipher based on the enabled pairwise cipher suites */
+       if (wpa & 1)
+               pairwise |= wpa_pairwise;
+       if (wpa & 2)
+               pairwise |= rsn_pairwise;
+
+       if (pairwise & WPA_CIPHER_TKIP)
+               return WPA_CIPHER_TKIP;
+       if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
+               return WPA_CIPHER_GCMP;
+       if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
+                        WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
+               return WPA_CIPHER_GCMP_256;
+       if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
+                        WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
+               return WPA_CIPHER_CCMP_256;
+       return WPA_CIPHER_CCMP;
+}