static int eap_fast_parse_decrypted(struct wpabuf *decrypted, struct eap_fast_tlv_parse *tlv, struct wpabuf **resp) { int mandatory, tlv_type, res; size_t len; u8 *pos, *end; os_memset(tlv, 0, sizeof(*tlv)); /* Parse TLVs from the decrypted Phase 2 data */ pos = wpabuf_mhead(decrypted); end = pos + wpabuf_len(decrypted); while (end - pos > 4) { mandatory = pos[0] & 0x80; tlv_type = WPA_GET_BE16(pos) & 0x3fff; pos += 2; len = WPA_GET_BE16(pos); pos += 2; if (len > (size_t) (end - pos)) { wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow"); return -1; } wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: " "TLV type %d length %u%s", tlv_type, (unsigned int) len, mandatory ? " (mandatory)" : ""); res = eap_fast_parse_tlv(tlv, tlv_type, pos, len); if (res == -2) break; if (res < 0) { if (mandatory) { wpa_printf(MSG_DEBUG, "EAP-FAST: Nak unknown " "mandatory TLV type %d", tlv_type); *resp = eap_fast_tlv_nak(0, tlv_type); break; } else { wpa_printf(MSG_DEBUG, "EAP-FAST: ignored " "unknown optional TLV type %d", tlv_type); } } pos += len; } return 0; }
static int eap_fast_parse_tlvs(struct wpabuf *data, struct eap_fast_tlv_parse *tlv) { int mandatory, tlv_type, len, res; u8 *pos, *end; os_memset(tlv, 0, sizeof(*tlv)); pos = wpabuf_mhead(data); end = pos + wpabuf_len(data); while (pos + 4 < end) { mandatory = pos[0] & 0x80; tlv_type = WPA_GET_BE16(pos) & 0x3fff; pos += 2; len = WPA_GET_BE16(pos); pos += 2; if (pos + len > end) { wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow"); return -1; } wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: " "TLV type %d length %d%s", tlv_type, len, mandatory ? " (mandatory)" : ""); res = eap_fast_parse_tlv(tlv, tlv_type, pos, len); if (res == -2) break; if (res < 0) { if (mandatory) { wpa_printf(MSG_DEBUG, "EAP-FAST: Nak unknown " "mandatory TLV type %d", tlv_type); /* TODO: generate Nak TLV */ break; } else { wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored " "unknown optional TLV type %d", tlv_type); } } pos += len; } return 0; }