diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 76f3aa972..2e6d05910 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -1002,154 +1002,6 @@ int wpa_validate_osen(struct wpa_authenticator *wpa_auth, #endif /* CONFIG_HS20 */ -/** - * 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 (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; - 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; - } - - 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; - } - -#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 */ - -#ifdef CONFIG_OCV - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_OCI) { - ie->oci = pos + 2 + RSN_SELECTOR_LEN; - ie->oci_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } -#endif /* CONFIG_OCV */ - - return 0; -} - - -/** - * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs - * @buf: Pointer to the Key Data buffer - * @len: Key Data Length - * @ie: Pointer to parsed IE data - * Returns: 0 on success, -1 on failure - */ -int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) -{ - const u8 *pos, *end; - int ret = 0; - - os_memset(ie, 0, sizeof(*ie)); - for (pos = buf, end = pos + len; end - pos > 1; pos += 2 + pos[1]) { - if (pos[0] == 0xdd && - ((pos == buf + len - 1) || pos[1] == 0)) { - /* Ignore padding */ - break; - } - if (2 + pos[1] > end - pos) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " - "underflow (ie=%d len=%d pos=%d)", - pos[0], pos[1], (int) (pos - buf)); - wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", - buf, len); - ret = -1; - break; - } - if (*pos == WLAN_EID_RSN) { - ie->rsn_ie = pos; - ie->rsn_ie_len = pos[1] + 2; - } else if (*pos == WLAN_EID_RSNX) { - ie->rsnxe = pos; - ie->rsnxe_len = pos[1] + 2; -#ifdef CONFIG_IEEE80211R_AP - } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { - ie->mdie = pos; - ie->mdie_len = pos[1] + 2; - } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { - ie->ftie = pos; - ie->ftie_len = pos[1] + 2; -#endif /* CONFIG_IEEE80211R_AP */ - } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { - ret = wpa_parse_generic(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; - } - } else { - wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " - "Key Data IE", pos, 2 + pos[1]); - } - } - - return ret; -} - - int wpa_auth_uses_mfp(struct wpa_state_machine *sm) { return sm ? sm->mgmt_frame_prot : 0; diff --git a/src/ap/wpa_auth_ie.h b/src/ap/wpa_auth_ie.h index e29e49681..dd44b9efe 100644 --- a/src/ap/wpa_auth_ie.h +++ b/src/ap/wpa_auth_ie.h @@ -9,41 +9,6 @@ #ifndef WPA_AUTH_IE_H #define WPA_AUTH_IE_H -struct wpa_eapol_ie_parse { - const u8 *wpa_ie; - size_t wpa_ie_len; - const u8 *rsn_ie; - size_t rsn_ie_len; - const u8 *pmkid; - const u8 *gtk; - size_t gtk_len; - const u8 *mac_addr; - size_t mac_addr_len; - const u8 *igtk; - size_t igtk_len; -#ifdef CONFIG_IEEE80211R_AP - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; -#endif /* CONFIG_IEEE80211R_AP */ -#ifdef CONFIG_P2P - const u8 *ip_addr_req; - const u8 *ip_addr_alloc; -#endif /* CONFIG_P2P */ -#ifdef CONFIG_OCV - const u8 *oci; - size_t oci_len; -#endif /* CONFIG_OCV */ - - const u8 *osen; - size_t osen_len; - const u8 *rsnxe; - size_t rsnxe_len; -}; - -int wpa_parse_kde_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie); u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, const u8 *data2, size_t data2_len); int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth); diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 142dace4a..1f8f18e90 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -2586,3 +2586,266 @@ int fils_domain_name_hash(const char *domain, u8 *hash) return 0; } #endif /* CONFIG_FILS */ + + +/** + * wpa_parse_vendor_specific - Parse Vendor Specific 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_vendor_specific(const u8 *pos, const u8 *end, + struct wpa_eapol_ie_parse *ie) +{ + unsigned int oui; + + if (pos[1] < 4) { + wpa_printf(MSG_MSGDUMP, + "Too short vendor specific IE ignored (len=%u)", + pos[1]); + return 1; + } + + oui = WPA_GET_BE24(&pos[2]); + if (oui == OUI_MICROSOFT && pos[5] == WMM_OUI_TYPE && pos[1] > 4) { + if (pos[6] == WMM_OUI_SUBTYPE_INFORMATION_ELEMENT) { + ie->wmm = &pos[2]; + ie->wmm_len = pos[1]; + wpa_hexdump(MSG_DEBUG, "WPA: WMM IE", + ie->wmm, ie->wmm_len); + } else if (pos[6] == WMM_OUI_SUBTYPE_PARAMETER_ELEMENT) { + ie->wmm = &pos[2]; + ie->wmm_len = pos[1]; + wpa_hexdump(MSG_DEBUG, "WPA: WMM Parameter Element", + ie->wmm, ie->wmm_len); + } + } + 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] >= 4 && WPA_GET_BE32(pos + 2) == OSEN_IE_VENDOR_TYPE) { + ie->osen = pos; + ie->osen_len = pos[1] + 2; + 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; + } + + 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; + } + + 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; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_OCI) { + ie->oci = pos + 2 + RSN_SELECTOR_LEN; + ie->oci_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: OCI KDE in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + + return 0; +} + + +/** + * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs + * @buf: Pointer to the Key Data buffer + * @len: Key Data Length + * @ie: Pointer to parsed IE data + * Returns: 0 on success, -1 on failure + */ +int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) +{ + const u8 *pos, *end; + int ret = 0; + + os_memset(ie, 0, sizeof(*ie)); + for (pos = buf, end = pos + len; end - pos > 1; pos += 2 + pos[1]) { + if (pos[0] == 0xdd && + ((pos == buf + len - 1) || pos[1] == 0)) { + /* Ignore padding */ + break; + } + if (2 + pos[1] > end - pos) { + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key Key Data underflow (ie=%d len=%d pos=%d)", + pos[0], pos[1], (int) (pos - buf)); + wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", buf, len); + ret = -1; + break; + } + if (*pos == WLAN_EID_RSN) { + ie->rsn_ie = pos; + ie->rsn_ie_len = pos[1] + 2; + wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key", + ie->rsn_ie, ie->rsn_ie_len); + } else if (*pos == WLAN_EID_RSNX) { + ie->rsnxe = pos; + ie->rsnxe_len = pos[1] + 2; + wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key", + ie->rsnxe, ie->rsnxe_len); + } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { + ie->mdie = pos; + ie->mdie_len = pos[1] + 2; + wpa_hexdump(MSG_DEBUG, "WPA: MDIE in EAPOL-Key", + ie->mdie, ie->mdie_len); + } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { + ie->ftie = pos; + ie->ftie_len = pos[1] + 2; + wpa_hexdump(MSG_DEBUG, "WPA: FTIE in EAPOL-Key", + ie->ftie, ie->ftie_len); + } else if (*pos == WLAN_EID_TIMEOUT_INTERVAL && pos[1] >= 5) { + if (pos[2] == WLAN_TIMEOUT_REASSOC_DEADLINE) { + ie->reassoc_deadline = pos; + wpa_hexdump(MSG_DEBUG, "WPA: Reassoc Deadline " + "in EAPOL-Key", + ie->reassoc_deadline, pos[1] + 2); + } else if (pos[2] == WLAN_TIMEOUT_KEY_LIFETIME) { + ie->key_lifetime = pos; + wpa_hexdump(MSG_DEBUG, "WPA: KeyLifetime " + "in EAPOL-Key", + ie->key_lifetime, pos[1] + 2); + } else { + wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized " + "EAPOL-Key Key Data IE", + pos, 2 + pos[1]); + } + } else if (*pos == WLAN_EID_LINK_ID) { + if (pos[1] >= 18) { + ie->lnkid = pos; + ie->lnkid_len = pos[1] + 2; + } + } else if (*pos == WLAN_EID_EXT_CAPAB) { + ie->ext_capab = pos; + ie->ext_capab_len = pos[1] + 2; + } else if (*pos == WLAN_EID_SUPP_RATES) { + ie->supp_rates = pos; + ie->supp_rates_len = pos[1] + 2; + } else if (*pos == WLAN_EID_EXT_SUPP_RATES) { + ie->ext_supp_rates = pos; + ie->ext_supp_rates_len = pos[1] + 2; + } else if (*pos == WLAN_EID_HT_CAP && + pos[1] >= sizeof(struct ieee80211_ht_capabilities)) { + ie->ht_capabilities = pos + 2; + } else if (*pos == WLAN_EID_VHT_AID) { + if (pos[1] >= 2) + ie->aid = WPA_GET_LE16(pos + 2) & 0x3fff; + } else if (*pos == WLAN_EID_VHT_CAP && + pos[1] >= sizeof(struct ieee80211_vht_capabilities)) + { + ie->vht_capabilities = pos + 2; + } else if (*pos == WLAN_EID_QOS && pos[1] >= 1) { + ie->qosinfo = pos[2]; + } else if (*pos == WLAN_EID_SUPPORTED_CHANNELS) { + ie->supp_channels = pos + 2; + ie->supp_channels_len = pos[1]; + } else if (*pos == WLAN_EID_SUPPORTED_OPERATING_CLASSES) { + /* + * The value of the Length field of the Supported + * Operating Classes element is between 2 and 253. + * Silently skip invalid elements to avoid interop + * issues when trying to use the value. + */ + if (pos[1] >= 2 && pos[1] <= 253) { + ie->supp_oper_classes = pos + 2; + ie->supp_oper_classes_len = pos[1]; + } + } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { + ret = wpa_parse_generic(pos, end, ie); + if (ret < 0) + break; + if (ret > 0) { + ret = 0; + break; + } + + ret = wpa_parse_vendor_specific(pos, end, ie); + if (ret < 0) + break; + if (ret > 0) { + ret = 0; + break; + } + } else { + wpa_hexdump(MSG_DEBUG, + "WPA: Unrecognized EAPOL-Key Key Data IE", + pos, 2 + pos[1]); + } + } + + return ret; +} diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 35bec0415..c7711f168 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -466,6 +466,60 @@ struct wpa_ft_ies { int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, int use_sha384); +struct wpa_eapol_ie_parse { + const u8 *wpa_ie; + size_t wpa_ie_len; + const u8 *rsn_ie; + size_t rsn_ie_len; + const u8 *pmkid; + const u8 *gtk; + size_t gtk_len; + const u8 *mac_addr; + size_t mac_addr_len; + const u8 *igtk; + size_t igtk_len; + const u8 *mdie; + size_t mdie_len; + const u8 *ftie; + size_t ftie_len; + const u8 *ip_addr_req; + const u8 *ip_addr_alloc; + const u8 *oci; + size_t oci_len; + const u8 *osen; + size_t osen_len; + const u8 *rsnxe; + size_t rsnxe_len; + const u8 *reassoc_deadline; + const u8 *key_lifetime; + const u8 *lnkid; + size_t lnkid_len; + const u8 *ext_capab; + size_t ext_capab_len; + const u8 *supp_rates; + size_t supp_rates_len; + const u8 *ext_supp_rates; + size_t ext_supp_rates_len; + const u8 *ht_capabilities; + const u8 *vht_capabilities; + const u8 *supp_channels; + size_t supp_channels_len; + const u8 *supp_oper_classes; + size_t supp_oper_classes_len; + u8 qosinfo; + u16 aid; + const u8 *wmm; + size_t wmm_len; +}; + +int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie); +static inline int wpa_supplicant_parse_ies(const u8 *buf, size_t len, + struct wpa_eapol_ie_parse *ie) +{ + return wpa_parse_kde_ies(buf, len, ie); +} + + int wpa_cipher_key_len(int cipher); int wpa_cipher_rsc_len(int cipher); enum wpa_alg wpa_cipher_to_alg(int cipher); diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index f4ac25c05..03c0d7e85 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -362,266 +362,3 @@ int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len) return pos - rsnxe; } - - -/** - * wpa_parse_vendor_specific - Parse Vendor Specific 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_vendor_specific(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) -{ - unsigned int oui; - - if (pos[1] < 4) { - wpa_printf(MSG_MSGDUMP, "Too short vendor specific IE ignored (len=%u)", - pos[1]); - return 1; - } - - oui = WPA_GET_BE24(&pos[2]); - if (oui == OUI_MICROSOFT && pos[5] == WMM_OUI_TYPE && pos[1] > 4) { - if (pos[6] == WMM_OUI_SUBTYPE_INFORMATION_ELEMENT) { - ie->wmm = &pos[2]; - ie->wmm_len = pos[1]; - wpa_hexdump(MSG_DEBUG, "WPA: WMM IE", - ie->wmm, ie->wmm_len); - } else if (pos[6] == WMM_OUI_SUBTYPE_PARAMETER_ELEMENT) { - ie->wmm = &pos[2]; - ie->wmm_len = pos[1]; - wpa_hexdump(MSG_DEBUG, "WPA: WMM Parameter Element", - ie->wmm, ie->wmm_len); - } - } - 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; - } - - 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; - } - -#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 */ - -#ifdef CONFIG_OCV - if (pos[1] >= RSN_SELECTOR_LEN + 1 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_OCI) { - ie->oci = pos + 2 + RSN_SELECTOR_LEN; - ie->oci_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: OCI KDE in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } -#endif /* CONFIG_OCV */ - - return 0; -} - - -/** - * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs - * @buf: Pointer to the Key Data buffer - * @len: Key Data Length - * @ie: Pointer to parsed IE data - * Returns: 0 on success, -1 on failure - */ -int wpa_supplicant_parse_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie) -{ - const u8 *pos, *end; - int ret = 0; - - os_memset(ie, 0, sizeof(*ie)); - for (pos = buf, end = pos + len; end - pos > 1; pos += 2 + pos[1]) { - if (pos[0] == 0xdd && - ((pos == buf + len - 1) || pos[1] == 0)) { - /* Ignore padding */ - break; - } - if (2 + pos[1] > end - pos) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " - "underflow (ie=%d len=%d pos=%d)", - pos[0], pos[1], (int) (pos - buf)); - wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", - buf, len); - ret = -1; - break; - } - if (*pos == WLAN_EID_RSN) { - ie->rsn_ie = pos; - ie->rsn_ie_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key", - ie->rsn_ie, ie->rsn_ie_len); - } else if (*pos == WLAN_EID_RSNX) { - ie->rsnxe = pos; - ie->rsnxe_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key", - ie->rsnxe, ie->rsnxe_len); - } else if (*pos == WLAN_EID_MOBILITY_DOMAIN && - pos[1] >= sizeof(struct rsn_mdie)) { - ie->mdie = pos; - ie->mdie_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: MDIE in EAPOL-Key", - ie->mdie, ie->mdie_len); - } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION && - pos[1] >= sizeof(struct rsn_ftie)) { - ie->ftie = pos; - ie->ftie_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: FTIE in EAPOL-Key", - ie->ftie, ie->ftie_len); - } else if (*pos == WLAN_EID_TIMEOUT_INTERVAL && pos[1] >= 5) { - if (pos[2] == WLAN_TIMEOUT_REASSOC_DEADLINE) { - ie->reassoc_deadline = pos; - wpa_hexdump(MSG_DEBUG, "WPA: Reassoc Deadline " - "in EAPOL-Key", - ie->reassoc_deadline, pos[1] + 2); - } else if (pos[2] == WLAN_TIMEOUT_KEY_LIFETIME) { - ie->key_lifetime = pos; - wpa_hexdump(MSG_DEBUG, "WPA: KeyLifetime " - "in EAPOL-Key", - ie->key_lifetime, pos[1] + 2); - } else { - wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized " - "EAPOL-Key Key Data IE", - pos, 2 + pos[1]); - } - } else if (*pos == WLAN_EID_LINK_ID) { - if (pos[1] >= 18) { - ie->lnkid = pos; - ie->lnkid_len = pos[1] + 2; - } - } else if (*pos == WLAN_EID_EXT_CAPAB) { - ie->ext_capab = pos; - ie->ext_capab_len = pos[1] + 2; - } else if (*pos == WLAN_EID_SUPP_RATES) { - ie->supp_rates = pos; - ie->supp_rates_len = pos[1] + 2; - } else if (*pos == WLAN_EID_EXT_SUPP_RATES) { - ie->ext_supp_rates = pos; - ie->ext_supp_rates_len = pos[1] + 2; - } else if (*pos == WLAN_EID_HT_CAP && - pos[1] >= sizeof(struct ieee80211_ht_capabilities)) { - ie->ht_capabilities = pos + 2; - } else if (*pos == WLAN_EID_VHT_AID) { - if (pos[1] >= 2) - ie->aid = WPA_GET_LE16(pos + 2) & 0x3fff; - } else if (*pos == WLAN_EID_VHT_CAP && - pos[1] >= sizeof(struct ieee80211_vht_capabilities)) - { - ie->vht_capabilities = pos + 2; - } else if (*pos == WLAN_EID_QOS && pos[1] >= 1) { - ie->qosinfo = pos[2]; - } else if (*pos == WLAN_EID_SUPPORTED_CHANNELS) { - ie->supp_channels = pos + 2; - ie->supp_channels_len = pos[1]; - } else if (*pos == WLAN_EID_SUPPORTED_OPERATING_CLASSES) { - /* - * The value of the Length field of the Supported - * Operating Classes element is between 2 and 253. - * Silently skip invalid elements to avoid interop - * issues when trying to use the value. - */ - if (pos[1] >= 2 && pos[1] <= 253) { - ie->supp_oper_classes = pos + 2; - ie->supp_oper_classes_len = pos[1]; - } - } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { - ret = wpa_parse_generic(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; - } - - ret = wpa_parse_vendor_specific(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; - } - } else { - wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " - "Key Data IE", pos, 2 + pos[1]); - } - } - - return ret; -} diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h index fa7d0a317..6dc6cf560 100644 --- a/src/rsn_supp/wpa_ie.h +++ b/src/rsn_supp/wpa_ie.h @@ -11,56 +11,6 @@ struct wpa_sm; -struct wpa_eapol_ie_parse { - const u8 *wpa_ie; - size_t wpa_ie_len; - const u8 *rsn_ie; - size_t rsn_ie_len; - const u8 *pmkid; - const u8 *gtk; - size_t gtk_len; - const u8 *mac_addr; - size_t mac_addr_len; - const u8 *igtk; - size_t igtk_len; - const u8 *rsnxe; - size_t rsnxe_len; - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; - const u8 *reassoc_deadline; - const u8 *key_lifetime; - const u8 *lnkid; - size_t lnkid_len; - const u8 *ext_capab; - size_t ext_capab_len; - const u8 *supp_rates; - size_t supp_rates_len; - const u8 *ext_supp_rates; - size_t ext_supp_rates_len; - const u8 *ht_capabilities; - const u8 *vht_capabilities; - const u8 *supp_channels; - size_t supp_channels_len; - const u8 *supp_oper_classes; - size_t supp_oper_classes_len; - u8 qosinfo; - u16 aid; - const u8 *wmm; - size_t wmm_len; -#ifdef CONFIG_P2P - const u8 *ip_addr_req; - const u8 *ip_addr_alloc; -#endif /* CONFIG_P2P */ -#ifdef CONFIG_OCV - const u8 *oci; - size_t oci_len; -#endif /* CONFIG_OCV */ -}; - -int wpa_supplicant_parse_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie); int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len); int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len);