Merge wpa_supplicant and hostapd EAPOL-Key KDE parsers
Use a single struct definition and a single shared implementation for parsing EAPOL-Key KDEs and IEs instead of maintaining more or less identical functionality separately for wpa_supplicant and hostapd. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
898b6d58f3
commit
865721c695
6 changed files with 317 additions and 496 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue