static int WpaKeyMgmtToBitfield(const uint8 *s) { if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) return WPA_KEY_MGMT_IEEE8021X; if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) return WPA_KEY_MGMT_PSK; if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) return WPA_KEY_MGMT_WPA_NONE; return 0; }
static int wpa_key_mgmt_to_bitfield(const u8 *s) { if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) return WPA_KEY_MGMT_IEEE8021X; if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) return WPA_KEY_MGMT_PSK; if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) return WPA_KEY_MGMT_WPA_NONE; return 0; }
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_TKIP) return WPA_CIPHER_TKIP; if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP) return WPA_CIPHER_CCMP; return 0; }
static int RsnKeyMgmtToBitfield(const uint8 *s) { if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X) return WPA_KEY_MGMT_IEEE8021X; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X) return WPA_KEY_MGMT_PSK; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X) return WPA_KEY_MGMT_FT_IEEE8021X; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) return WPA_KEY_MGMT_FT_PSK; return 0; }
static int WpaSelectorToBitfield(const uint8 *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; }
static int rsn_key_mgmt_to_bitfield(const u8 *s) { if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X) return WPA_KEY_MGMT_IEEE8021X; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X) return WPA_KEY_MGMT_PSK; #ifdef CONFIG_IEEE80211R if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X) return WPA_KEY_MGMT_FT_IEEE8021X; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) return WPA_KEY_MGMT_FT_PSK; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) return WPA_KEY_MGMT_IEEE8021X_SHA256; 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; }
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; #endif /* CONFIG_IEEE80211W */ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP) return WPA_CIPHER_GCMP; return 0; }
/** * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs * @pos: Pointer to the IE header * @end: Pointer to the end of the Key Data buffer * @ie: Pointer to parsed IE data * Returns: 0 on success, 1 if end mark is found, -1 on failure */ static int wpa_parse_generic(const u8 *pos, const u8 *end, struct wpa_eapol_ie_parse *ie) { if (pos[1] == 0) return 1; if (pos[1] >= 6 && RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && pos[2 + WPA_SELECTOR_LEN] == 1 && pos[2 + WPA_SELECTOR_LEN + 1] == 0) { ie->wpa_ie = pos; ie->wpa_ie_len = pos[1] + 2; wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key", ie->wpa_ie, ie->wpa_ie_len); return 0; } if (pos + 1 + RSN_SELECTOR_LEN < end && pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", pos, pos[1] + 2); return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { ie->gtk = pos + 2 + RSN_SELECTOR_LEN; ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; wpa_hexdump_key(MSG_DEBUG, "WPA: GTK in EAPOL-Key", pos, pos[1] + 2); return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key", pos, pos[1] + 2); return 0; } #ifdef CONFIG_PEERKEY if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { ie->smk = pos + 2 + RSN_SELECTOR_LEN; ie->smk_len = pos[1] - RSN_SELECTOR_LEN; wpa_hexdump_key(MSG_DEBUG, "WPA: SMK in EAPOL-Key", pos, pos[1] + 2); return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { ie->nonce = pos + 2 + RSN_SELECTOR_LEN; ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: Nonce in EAPOL-Key", pos, pos[1] + 2); return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: Lifetime in EAPOL-Key", pos, pos[1] + 2); return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { ie->error = pos + 2 + RSN_SELECTOR_LEN; ie->error_len = pos[1] - RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: Error in EAPOL-Key", pos, pos[1] + 2); return 0; } #endif /* CONFIG_PEERKEY */ #ifdef CONFIG_IEEE80211W if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { ie->igtk = pos + 2 + RSN_SELECTOR_LEN; ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK in EAPOL-Key", pos, pos[1] + 2); return 0; } #endif /* CONFIG_IEEE80211W */ return 0; }
static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data) { const struct wpa_ie_hdr *hdr; const u8 *pos; int left; int i, count; os_memset(data, 0, sizeof(*data)); data->proto = WPA_PROTO_WPA; data->pairwise_cipher = WPA_CIPHER_TKIP; data->group_cipher = WPA_CIPHER_TKIP; data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; data->capabilities = 0; data->pmkid = NULL; 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); return -1; } hdr = (const struct wpa_ie_hdr *) wpa_ie; if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || hdr->len != wpa_ie_len - 2 || RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || WPA_GET_LE16(hdr->version) != WPA_VERSION) { wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", __func__); return -1; } pos = (const u8 *) (hdr + 1); left = wpa_ie_len - sizeof(*hdr); if (left >= WPA_SELECTOR_LEN) { data->group_cipher = wpa_selector_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } else if (left > 0) { wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", __func__, left); return -1; } if (left >= 2) { data->pairwise_cipher = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " "count %u left %u", __func__, count, left); return -1; } for (i = 0; i < count; i++) { data->pairwise_cipher |= wpa_selector_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } } else if (left == 1) { wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", __func__); return -1; } if (left >= 2) { data->key_mgmt = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " "count %u left %u", __func__, count, left); return -1; } for (i = 0; i < count; i++) { data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } } else if (left == 1) { wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", __func__); return -1; } if (left >= 2) { data->capabilities = WPA_GET_LE16(pos); pos += 2; left -= 2; } if (left > 0) { wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", __func__, left); } return 0; }
/** * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs * @pos: Pointer to the IE header * @end: Pointer to the end of the Key Data buffer * @ie: Pointer to parsed IE data * Returns: 0 on success, 1 if end mark is found, -1 on failure */ static int wpa_parse_generic(const u8 *pos, const u8 *end, struct wpa_eapol_ie_parse *ie) { if (pos[1] == 0) return 1; if (pos[1] >= 6 && RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && pos[2 + WPA_SELECTOR_LEN] == 1 && pos[2 + WPA_SELECTOR_LEN + 1] == 0) { ie->wpa_ie = pos; ie->wpa_ie_len = pos[1] + 2; return 0; } if (pos + 1 + RSN_SELECTOR_LEN < end && pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { ie->gtk = pos + 2 + RSN_SELECTOR_LEN; ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; return 0; } #ifdef CONFIG_PEERKEY if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { ie->smk = pos + 2 + RSN_SELECTOR_LEN; ie->smk_len = pos[1] - RSN_SELECTOR_LEN; return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { ie->nonce = pos + 2 + RSN_SELECTOR_LEN; ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { ie->error = pos + 2 + RSN_SELECTOR_LEN; ie->error_len = pos[1] - RSN_SELECTOR_LEN; return 0; } #endif /* CONFIG_PEERKEY */ #ifdef CONFIG_IEEE80211W if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { ie->igtk = pos + 2 + RSN_SELECTOR_LEN; ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; return 0; } #endif /* CONFIG_IEEE80211W */ return 0; }
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_TKIP) return WPA_CIPHER_TKIP; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP) return WPA_CIPHER_CCMP; #ifdef CONFIG_IEEE80211W if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) return WPA_CIPHER_AES_128_CMAC; #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; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED) return WPA_CIPHER_GTK_NOT_USED; return 0; }
static int ParseWpaIE(const uint8 *wpa_ie, size_t wpa_ie_len, WmWpaIEData& data) { const uint8 *pos; int left; int i, count; data.proto = WPA_PROTO_WPA; data.pairwise_cipher = WPA_CIPHER_TKIP; data.group_cipher = WPA_CIPHER_TKIP; data.key_mgmt = WPA_KEY_MGMT_IEEE8021X; data.capabilities = 0; //RR data.pmkid = NULL; //RR data.num_pmkid = 0; //RR data.mgmt_group_cipher = 0; if (wpa_ie_len < WPA_IE_HEADER_LENGTH) { INFRA_DLOG( ( LM_WIFIMGRLIB, LP_TRACE, "WmWpaParser::ParseWpaIE" " ie len too short %lu",(unsigned long) wpa_ie_len) ); return -1; } if (wpa_ie[0] != IE_VENDOR || wpa_ie[1] != wpa_ie_len || RSN_SELECTOR_GET(&(wpa_ie[2])) != WPA_OUI_TYPE || WM_BUF_GET_LE16(&(wpa_ie[6])) != WPA_VERSION) { INFRA_DLOG( ( LM_WIFIMGRLIB, LP_TRACE, "WmWpaParser::ParseWpaIE" " malformed ie or unknown version") ); return -1; } pos = (const uint8*)&(wpa_ie[WPA_IE_HEADER_LENGTH]); left = wpa_ie_len - WPA_IE_HEADER_LENGTH + 2; if (left >= WPA_SELECTOR_LEN) { data.group_cipher = WpaSelectorToBitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } else if (left > 0) { INFRA_DLOG( ( LM_WIFIMGRLIB, LP_TRACE, "WmWpaParser::ParseWpaIE" " ie length mismatch, %u too much",left) ); return -1; } if (left >= 2) { data.pairwise_cipher = 0; count = WM_BUF_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) { INFRA_DLOG( ( LM_WIFIMGRLIB, LP_TRACE, "WmWpaParser::ParseWpaIE" " ie count botch (pairwise)," "count %u left %u",count,left) ); return -1; } for (i = 0; i < count; i++) { data.pairwise_cipher |= WpaSelectorToBitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } } else if (left == 1) { INFRA_DLOG( ( LM_WIFIMGRLIB, LP_TRACE, "WmWpaParser::ParseWpaIE" " ie too short (for key mgmt)") ); return -1; } if (left >= 2) { data.key_mgmt = 0; count = WM_BUF_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) { INFRA_DLOG( ( LM_WIFIMGRLIB, LP_TRACE, "WmWpaParser::ParseWpaIE" " ie count botch (key_mgmt)," "count %u left %u",count,left) ); return -1; } for (i = 0; i < count; i++) { data.key_mgmt |= WpaKeyMgmtToBitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } } else if (left == 1) { INFRA_DLOG( ( LM_WIFIMGRLIB, LP_TRACE, "WmWpaParser::ParseWpaIE" " ie too short (for capabilities)") ); return -1; } if (left >= 2) { data.capabilities = WM_BUF_GET_LE16(pos); pos += 2; left -= 2; } if (left > 0) { INFRA_DLOG( ( LM_WIFIMGRLIB, LP_TRACE, "WmWpaParser::ParseWpaIE" " ie has %u trailing bytes - ignored",left) ); } return 0; }
static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data) { const struct wpa_ie_hdr *hdr; const u8 *pos; int left; int i, count; os_memset(data, 0, sizeof(*data)); data->pairwise_cipher = WPA_CIPHER_TKIP; data->group_cipher = WPA_CIPHER_TKIP; data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; data->mgmt_group_cipher = 0; if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) return -1; hdr = (const struct wpa_ie_hdr *) wpa_ie; if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || hdr->len != wpa_ie_len - 2 || RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || WPA_GET_LE16(hdr->version) != WPA_VERSION) { return -2; } pos = (const u8 *) (hdr + 1); left = wpa_ie_len - sizeof(*hdr); if (left >= WPA_SELECTOR_LEN) { data->group_cipher = wpa_selector_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } else if (left > 0) return -3; if (left >= 2) { data->pairwise_cipher = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) return -4; for (i = 0; i < count; i++) { data->pairwise_cipher |= wpa_selector_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } } else if (left == 1) return -5; if (left >= 2) { data->key_mgmt = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) return -6; for (i = 0; i < count; i++) { data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } } else if (left == 1) return -7; if (left >= 2) { data->capabilities = WPA_GET_LE16(pos); pos += 2; left -= 2; } if (left > 0) { return -8; } return 0; }
/** * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs * @pos: Pointer to the IE header * @end: Pointer to the end of the Key Data buffer * @ie: Pointer to parsed IE data * Returns: 0 on success, 1 if end mark is found, -1 on failure */ static int wpa_parse_generic(const u8 *pos, const u8 *end, struct wpa_eapol_ie_parse *ie) { if (pos[1] == 0) return 1; if (pos[1] >= 6 && RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && pos[2 + WPA_SELECTOR_LEN] == 1 && pos[2 + WPA_SELECTOR_LEN + 1] == 0) { ie->wpa_ie = pos; ie->wpa_ie_len = pos[1] + 2; return 0; } if (pos[1] >= 4 && WPA_GET_BE32(pos + 2) == OSEN_IE_VENDOR_TYPE) { ie->osen = pos; ie->osen_len = pos[1] + 2; return 0; } if (pos + 1 + RSN_SELECTOR_LEN < end && pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { ie->gtk = pos + 2 + RSN_SELECTOR_LEN; ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; return 0; } #ifdef CONFIG_PEERKEY if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { ie->smk = pos + 2 + RSN_SELECTOR_LEN; ie->smk_len = pos[1] - RSN_SELECTOR_LEN; return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { ie->nonce = pos + 2 + RSN_SELECTOR_LEN; ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { ie->error = pos + 2 + RSN_SELECTOR_LEN; ie->error_len = pos[1] - RSN_SELECTOR_LEN; return 0; } #endif /* CONFIG_PEERKEY */ #ifdef CONFIG_IEEE80211W if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { ie->igtk = pos + 2 + RSN_SELECTOR_LEN; ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; return 0; } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (pos[1] >= RSN_SELECTOR_LEN + 1 && RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key", ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN); return 0; } if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 && RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) { ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: IP Address Allocation in EAPOL-Key", ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN); return 0; } #endif /* CONFIG_P2P */ return 0; }
/** * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs * @pos: Pointer to the IE header * @end: Pointer to the end of the Key Data buffer * @ie: Pointer to parsed IE data * Returns: 0 on success, 1 if end mark is found, -1 on failure */ static int wpa_parse_generic(const u8 *pos, const u8 *end, struct wpa_eapol_ie_parse *ie) { if (pos[1] == 0) return 1; if (pos[1] >= 6 && RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && pos[2 + WPA_SELECTOR_LEN] == 1 && pos[2 + WPA_SELECTOR_LEN + 1] == 0) { ie->wpa_ie = pos; ie->wpa_ie_len = pos[1] + 2; wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key", ie->wpa_ie, ie->wpa_ie_len); return 0; } if (1 + RSN_SELECTOR_LEN < end - pos && pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", pos, pos[1] + 2); return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { ie->gtk = pos + 2 + RSN_SELECTOR_LEN; ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; wpa_hexdump_key(MSG_DEBUG, "WPA: GTK in EAPOL-Key", pos, pos[1] + 2); return 0; } if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key", pos, pos[1] + 2); return 0; } #ifdef CONFIG_IEEE80211W if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { ie->igtk = pos + 2 + RSN_SELECTOR_LEN; ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK in EAPOL-Key", pos, pos[1] + 2); return 0; } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (pos[1] >= RSN_SELECTOR_LEN + 1 && RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key", ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN); return 0; } if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 && RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) { ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: IP Address Allocation in EAPOL-Key", ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN); return 0; } #endif /* CONFIG_P2P */ return 0; }