summaryrefslogtreecommitdiff
path: root/src/common/wpa_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/wpa_common.c')
-rw-r--r--src/common/wpa_common.c182
1 files changed, 85 insertions, 97 deletions
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index de81d53694c29..e9d4248d72d45 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -170,6 +170,12 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
ptk->tk_len = wpa_cipher_key_len(cipher);
ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
+#ifdef CONFIG_SUITEB192
+ if (wpa_key_mgmt_sha384(akmp))
+ sha384_prf(pmk, pmk_len, label, data, sizeof(data),
+ tmp, ptk_len);
+ else
+#endif /* CONFIG_SUITEB192 */
#ifdef CONFIG_IEEE80211W
if (wpa_key_mgmt_sha256(akmp))
sha256_prf(pmk, pmk_len, label, data, sizeof(data),
@@ -207,8 +213,10 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
const u8 *rsnie, size_t rsnie_len,
const u8 *ric, size_t ric_len, u8 *mic)
{
- u8 *buf, *pos;
- size_t buf_len;
+ const u8 *addr[9];
+ size_t len[9];
+ size_t i, num_elem = 0;
+ u8 zero_mic[16];
if (kck_len != 16) {
wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u",
@@ -216,48 +224,58 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
return -1;
}
- buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
- buf = os_malloc(buf_len);
- if (buf == NULL)
- return -1;
+ addr[num_elem] = sta_addr;
+ len[num_elem] = ETH_ALEN;
+ num_elem++;
+
+ addr[num_elem] = ap_addr;
+ len[num_elem] = ETH_ALEN;
+ num_elem++;
+
+ addr[num_elem] = &transaction_seqnum;
+ len[num_elem] = 1;
+ num_elem++;
- pos = buf;
- os_memcpy(pos, sta_addr, ETH_ALEN);
- pos += ETH_ALEN;
- os_memcpy(pos, ap_addr, ETH_ALEN);
- pos += ETH_ALEN;
- *pos++ = transaction_seqnum;
if (rsnie) {
- os_memcpy(pos, rsnie, rsnie_len);
- pos += rsnie_len;
+ addr[num_elem] = rsnie;
+ len[num_elem] = rsnie_len;
+ num_elem++;
}
if (mdie) {
- os_memcpy(pos, mdie, mdie_len);
- pos += mdie_len;
+ addr[num_elem] = mdie;
+ len[num_elem] = mdie_len;
+ num_elem++;
}
if (ftie) {
- struct rsn_ftie *_ftie;
- os_memcpy(pos, ftie, ftie_len);
- if (ftie_len < 2 + sizeof(*_ftie)) {
- os_free(buf);
+ if (ftie_len < 2 + sizeof(struct rsn_ftie))
return -1;
- }
- _ftie = (struct rsn_ftie *) (pos + 2);
- os_memset(_ftie->mic, 0, sizeof(_ftie->mic));
- pos += ftie_len;
+
+ /* IE hdr and mic_control */
+ addr[num_elem] = ftie;
+ len[num_elem] = 2 + 2;
+ num_elem++;
+
+ /* MIC field with all zeros */
+ os_memset(zero_mic, 0, sizeof(zero_mic));
+ addr[num_elem] = zero_mic;
+ len[num_elem] = sizeof(zero_mic);
+ num_elem++;
+
+ /* Rest of FTIE */
+ addr[num_elem] = ftie + 2 + 2 + 16;
+ len[num_elem] = ftie_len - (2 + 2 + 16);
+ num_elem++;
}
if (ric) {
- os_memcpy(pos, ric, ric_len);
- pos += ric_len;
+ addr[num_elem] = ric;
+ len[num_elem] = ric_len;
+ num_elem++;
}
- wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
- if (omac1_aes_128(kck, buf, pos - buf, mic)) {
- os_free(buf);
+ for (i = 0; i < num_elem; i++)
+ wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", addr[i], len[i]);
+ if (omac1_aes_128_vector(kck, num_elem, addr, len, mic))
return -1;
- }
-
- os_free(buf);
return 0;
}
@@ -344,6 +362,8 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
parse->rsn_pmkid = data.pmkid;
break;
case WLAN_EID_MOBILITY_DOMAIN:
+ if (pos[1] < sizeof(struct rsn_mdie))
+ return -1;
parse->mdie = pos + 2;
parse->mdie_len = pos[1];
break;
@@ -356,6 +376,8 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
return -1;
break;
case WLAN_EID_TIMEOUT_INTERVAL:
+ if (pos[1] != 5)
+ break;
parse->tie = pos + 2;
parse->tie_len = pos[1];
break;
@@ -416,14 +438,10 @@ static int rsn_selector_to_bitfield(const u8 *s)
{
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
return WPA_CIPHER_NONE;
- if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40)
- return WPA_CIPHER_WEP40;
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
return WPA_CIPHER_TKIP;
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
return WPA_CIPHER_CCMP;
- if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104)
- return WPA_CIPHER_WEP104;
#ifdef CONFIG_IEEE80211W
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
return WPA_CIPHER_AES_128_CMAC;
@@ -474,15 +492,15 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN)
+ return WPA_KEY_MGMT_OSEN;
return 0;
}
-static int wpa_cipher_valid_group(int cipher)
+int wpa_cipher_valid_group(int cipher)
{
return wpa_cipher_valid_pairwise(cipher) ||
- cipher == WPA_CIPHER_WEP104 ||
- cipher == WPA_CIPHER_WEP40 ||
cipher == WPA_CIPHER_GTK_NOT_USED;
}
@@ -508,7 +526,6 @@ int wpa_cipher_valid_mgmt_group(int cipher)
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data)
{
- const struct rsn_ie_hdr *hdr;
const u8 *pos;
int left;
int i, count;
@@ -538,18 +555,29 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
return -1;
}
- hdr = (const struct rsn_ie_hdr *) rsn_ie;
+ if (rsn_ie_len >= 6 && rsn_ie[1] >= 4 &&
+ rsn_ie[1] == rsn_ie_len - 2 &&
+ WPA_GET_BE32(&rsn_ie[2]) == OSEN_IE_VENDOR_TYPE) {
+ pos = rsn_ie + 6;
+ left = rsn_ie_len - 6;
- if (hdr->elem_id != WLAN_EID_RSN ||
- hdr->len != rsn_ie_len - 2 ||
- WPA_GET_LE16(hdr->version) != RSN_VERSION) {
- wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
- __func__);
- return -2;
- }
+ data->proto = WPA_PROTO_OSEN;
+ } else {
+ const struct rsn_ie_hdr *hdr;
- pos = (const u8 *) (hdr + 1);
- left = rsn_ie_len - sizeof(*hdr);
+ hdr = (const struct rsn_ie_hdr *) rsn_ie;
+
+ if (hdr->elem_id != WLAN_EID_RSN ||
+ hdr->len != rsn_ie_len - 2 ||
+ WPA_GET_LE16(hdr->version) != RSN_VERSION) {
+ wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
+ __func__);
+ return -2;
+ }
+
+ pos = (const u8 *) (hdr + 1);
+ left = rsn_ie_len - sizeof(*hdr);
+ }
if (left >= RSN_SELECTOR_LEN) {
data->group_cipher = rsn_selector_to_bitfield(pos);
@@ -667,14 +695,10 @@ static int wpa_selector_to_bitfield(const u8 *s)
{
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
return WPA_CIPHER_NONE;
- if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
- return WPA_CIPHER_WEP40;
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
return WPA_CIPHER_TKIP;
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
return WPA_CIPHER_CCMP;
- if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
- return WPA_CIPHER_WEP104;
return 0;
}
@@ -709,11 +733,6 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
data->num_pmkid = 0;
data->mgmt_group_cipher = 0;
- if (wpa_ie_len == 0) {
- /* No WPA IE - fail silently */
- return -1;
- }
-
if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
__func__, (unsigned long) wpa_ie_len);
@@ -814,7 +833,7 @@ void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
{
- u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
+ u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
FT_R0KH_ID_MAX_LEN + ETH_ALEN];
u8 *pos, r0_key_data[48], hash[32];
const u8 *addr[2];
@@ -828,7 +847,7 @@ void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
* PMK-R0 = L(R0-Key-Data, 0, 256)
* PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
*/
- if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
+ if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
return;
pos = buf;
*pos++ = ssid_len;
@@ -1279,6 +1298,9 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
os_memmove(rpos + 2, rpos, end - rpos);
*rpos++ = 0;
*rpos++ = 0;
+ added += 2;
+ start[1] += 2;
+ rend = rpos;
} else {
/* Skip RSN Capabilities */
rpos += 2;
@@ -1291,7 +1313,7 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
if (rpos == rend) {
/* No PMKID-Count field included; add it */
- os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
+ os_memmove(rpos + 2 + PMKID_LEN, rpos, end + added - rpos);
WPA_PUT_LE16(rpos, 1);
rpos += 2;
os_memcpy(rpos, pmkid, PMKID_LEN);
@@ -1306,7 +1328,7 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
}
WPA_PUT_LE16(rpos, 1);
rpos += 2;
- os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
+ os_memmove(rpos + PMKID_LEN, rpos, end + added - rpos);
os_memcpy(rpos, pmkid, PMKID_LEN);
added += PMKID_LEN;
start[1] += PMKID_LEN;
@@ -1335,10 +1357,6 @@ int wpa_cipher_key_len(int cipher)
return 16;
case WPA_CIPHER_TKIP:
return 32;
- case WPA_CIPHER_WEP104:
- return 13;
- case WPA_CIPHER_WEP40:
- return 5;
}
return 0;
@@ -1354,9 +1372,6 @@ int wpa_cipher_rsc_len(int cipher)
case WPA_CIPHER_GCMP:
case WPA_CIPHER_TKIP:
return 6;
- case WPA_CIPHER_WEP104:
- case WPA_CIPHER_WEP40:
- return 0;
}
return 0;
@@ -1376,9 +1391,6 @@ int wpa_cipher_to_alg(int cipher)
return WPA_ALG_GCMP;
case WPA_CIPHER_TKIP:
return WPA_ALG_TKIP;
- case WPA_CIPHER_WEP104:
- case WPA_CIPHER_WEP40:
- return WPA_ALG_WEP;
case WPA_CIPHER_AES_128_CMAC:
return WPA_ALG_IGTK;
case WPA_CIPHER_BIP_GMAC_128:
@@ -1416,12 +1428,6 @@ u32 wpa_cipher_to_suite(int proto, int cipher)
if (cipher & WPA_CIPHER_TKIP)
return (proto == WPA_PROTO_RSN ?
RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
- if (cipher & WPA_CIPHER_WEP104)
- return (proto == WPA_PROTO_RSN ?
- RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104);
- if (cipher & WPA_CIPHER_WEP40)
- return (proto == WPA_PROTO_RSN ?
- RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40);
if (cipher & WPA_CIPHER_NONE)
return (proto == WPA_PROTO_RSN ?
RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
@@ -1525,10 +1531,6 @@ int wpa_pick_group_cipher(int ciphers)
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;
}
@@ -1626,20 +1628,6 @@ int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
return -1;
pos += ret;
}
- if (ciphers & WPA_CIPHER_WEP104) {
- ret = os_snprintf(pos, end - pos, "%sWEP104",
- pos == start ? "" : delim);
- if (os_snprintf_error(end - pos, ret))
- return -1;
- pos += ret;
- }
- if (ciphers & WPA_CIPHER_WEP40) {
- ret = os_snprintf(pos, end - pos, "%sWEP40",
- pos == start ? "" : delim);
- if (os_snprintf_error(end - pos, ret))
- return -1;
- pos += ret;
- }
if (ciphers & WPA_CIPHER_NONE) {
ret = os_snprintf(pos, end - pos, "%sNONE",
pos == start ? "" : delim);