static void eap_fast_process_phase2_tlvs(struct eap_sm *sm, struct eap_fast_data *data, struct wpabuf *in_data) { struct eap_fast_tlv_parse tlv; int check_crypto_binding = data->state == CRYPTO_BINDING; if (eap_fast_parse_tlvs(in_data, &tlv) < 0) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to parse received " "Phase 2 TLVs"); return; } if (tlv.result == EAP_TLV_RESULT_FAILURE) { wpa_printf(MSG_DEBUG, "EAP-FAST: Result TLV indicated " "failure"); eap_fast_state(data, FAILURE); return; } if (data->state == REQUEST_PAC) { u16 type, len, res; if (tlv.pac == NULL || tlv.pac_len < 6) { wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC " "Acknowledgement received"); eap_fast_state(data, FAILURE); return; } type = WPA_GET_BE16(tlv.pac); len = WPA_GET_BE16(tlv.pac + 2); res = WPA_GET_BE16(tlv.pac + 4); if (type != PAC_TYPE_PAC_ACKNOWLEDGEMENT || len != 2 || res != EAP_TLV_RESULT_SUCCESS) { wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV did not " "contain acknowledgement"); eap_fast_state(data, FAILURE); return; } wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Acknowledgement received " "- PAC provisioning succeeded"); eap_fast_state(data, (data->anon_provisioning || data->send_new_pac == 2) ? FAILURE : SUCCESS); return; } if (check_crypto_binding) { if (tlv.crypto_binding == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: No Crypto-Binding " "TLV received"); eap_fast_state(data, FAILURE); return; } if (data->final_result && tlv.result != EAP_TLV_RESULT_SUCCESS) { wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV " "without Success Result"); eap_fast_state(data, FAILURE); return; } if (!data->final_result && tlv.iresult != EAP_TLV_RESULT_SUCCESS) { wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV " "without intermediate Success Result"); eap_fast_state(data, FAILURE); return; } if (eap_fast_validate_crypto_binding(data, tlv.crypto_binding, tlv.crypto_binding_len)) { eap_fast_state(data, FAILURE); return; } wpa_printf(MSG_DEBUG, "EAP-FAST: Valid Crypto-Binding TLV " "received"); if (data->final_result) { wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication " "completed successfully"); } if (data->anon_provisioning && sm->eap_fast_prov != ANON_PROV && sm->eap_fast_prov != BOTH_PROV) { wpa_printf(MSG_DEBUG, "EAP-FAST: Client is trying to " "use unauthenticated provisioning which is " "disabled"); eap_fast_state(data, FAILURE); return; } if (sm->eap_fast_prov != AUTH_PROV && sm->eap_fast_prov != BOTH_PROV && tlv.request_action == EAP_TLV_ACTION_PROCESS_TLV && eap_fast_pac_type(tlv.pac, tlv.pac_len, PAC_TYPE_TUNNEL_PAC)) { wpa_printf(MSG_DEBUG, "EAP-FAST: Client is trying to " "use authenticated provisioning which is " "disabled"); eap_fast_state(data, FAILURE); return; } if (data->anon_provisioning || (tlv.request_action == EAP_TLV_ACTION_PROCESS_TLV && eap_fast_pac_type(tlv.pac, tlv.pac_len, PAC_TYPE_TUNNEL_PAC))) { wpa_printf(MSG_DEBUG, "EAP-FAST: Requested a new " "Tunnel PAC"); eap_fast_state(data, REQUEST_PAC); } else if (data->send_new_pac) { wpa_printf(MSG_DEBUG, "EAP-FAST: Server triggered " "re-keying of Tunnel PAC"); eap_fast_state(data, REQUEST_PAC); } else if (data->final_result) eap_fast_state(data, SUCCESS); } if (tlv.eap_payload_tlv) { eap_fast_process_phase2_eap(sm, data, tlv.eap_payload_tlv, tlv.eap_payload_tlv_len); } }
static struct wpabuf * eap_fast_process_crypto_binding( struct eap_sm *sm, struct eap_fast_data *data, struct eap_method_ret *ret, struct eap_tlv_crypto_binding_tlv *_bind, size_t bind_len) { struct wpabuf *resp; u8 *pos; u8 cmk[EAP_FAST_CMK_LEN], cmac[SHA1_MAC_LEN]; int res; size_t len; if (eap_fast_validate_crypto_binding(_bind) < 0) return NULL; if (eap_fast_get_cmk(sm, data, cmk) < 0) return NULL; /* Validate received Compound MAC */ os_memcpy(cmac, _bind->compound_mac, sizeof(cmac)); os_memset(_bind->compound_mac, 0, sizeof(cmac)); wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for Compound " "MAC calculation", (u8 *) _bind, bind_len); hmac_sha1(cmk, EAP_FAST_CMK_LEN, (u8 *) _bind, bind_len, _bind->compound_mac); res = os_memcmp(cmac, _bind->compound_mac, sizeof(cmac)); wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Received Compound MAC", cmac, sizeof(cmac)); wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Calculated Compound MAC", _bind->compound_mac, sizeof(cmac)); if (res != 0) { wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not match"); os_memcpy(_bind->compound_mac, cmac, sizeof(cmac)); return NULL; } /* * Compound MAC was valid, so authentication succeeded. Reply with * crypto binding to allow server to complete authentication. */ len = sizeof(struct eap_tlv_crypto_binding_tlv); resp = wpabuf_alloc(len); if (resp == NULL) return NULL; if (!data->anon_provisioning && data->phase2_success && eap_fast_derive_msk(data) < 0) { wpa_printf(MSG_INFO, "EAP-FAST: Failed to generate MSK"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; data->phase2_success = 0; wpabuf_free(resp); return NULL; } pos = wpabuf_put(resp, sizeof(struct eap_tlv_crypto_binding_tlv)); eap_fast_write_crypto_binding((struct eap_tlv_crypto_binding_tlv *) pos, _bind, cmk); return resp; }