/*
* 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.
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;
}
#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)
#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;
}
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 */
/**
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;
}
return 0;
-#else /* CONFIG_NO_WPA2 */
- return -1;
-#endif /* CONFIG_NO_WPA2 */
}
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";
}
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;
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:
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:
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;
}
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);
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;
}
{
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;
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;
+}