static void eap_eke_process_identity(struct eap_sm *sm, struct eap_eke_data *data, const struct wpabuf *respData, const u8 *payload, size_t payloadlen) { const u8 *pos, *end; int i; wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Identity"); if (data->state != IDENTITY) { eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); return; } pos = payload; end = payload + payloadlen; if (pos + 2 + 4 + 1 > end) { wpa_printf(MSG_INFO, "EAP-EKE: Too short EAP-EKE-ID payload"); eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); return; } if (*pos != 1) { wpa_printf(MSG_INFO, "EAP-EKE: Unexpected NumProposals %d (expected 1)", *pos); eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); return; } pos += 2; if (!supported_proposal(pos)) { wpa_printf(MSG_INFO, "EAP-EKE: Unexpected Proposal (%u:%u:%u:%u)", pos[0], pos[1], pos[2], pos[3]); eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); return; } wpa_printf(MSG_DEBUG, "EAP-EKE: Selected Proposal (%u:%u:%u:%u)", pos[0], pos[1], pos[2], pos[3]); if (eap_eke_session_init(&data->sess, pos[0], pos[1], pos[2], pos[3]) < 0) { eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); return; } pos += 4; data->peerid_type = *pos++; os_free(data->peerid); data->peerid = os_memdup(pos, end - pos); if (data->peerid == NULL) { wpa_printf(MSG_INFO, "EAP-EKE: Failed to allocate memory for peerid"); eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); return; } data->peerid_len = end - pos; wpa_printf(MSG_DEBUG, "EAP-EKE: Peer IDType %u", data->peerid_type); wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Peer Identity", data->peerid, data->peerid_len); if (eap_user_get(sm, data->peerid, data->peerid_len, data->phase2)) { wpa_printf(MSG_INFO, "EAP-EKE: Peer Identity not found from user database"); eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); return; } for (i = 0; i < EAP_MAX_METHODS; i++) { if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && sm->user->methods[i].method == EAP_TYPE_EKE) break; } if (i == EAP_MAX_METHODS) { wpa_printf(MSG_INFO, "EAP-EKE: Matching user entry does not allow EAP-EKE"); eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); return; } if (sm->user->password == NULL || sm->user->password_len == 0) { wpa_printf(MSG_INFO, "EAP-EKE: No password configured for peer"); eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); return; } if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) { eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); return; } wpabuf_put_buf(data->msgs, respData); eap_eke_state(data, COMMIT); }
static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, struct eap_method_ret *ret, const struct wpabuf *reqData, const u8 *payload, size_t payload_len) { struct wpabuf *resp; unsigned num_prop, i; const u8 *pos, *end; const u8 *prop = NULL; u8 idtype; u8 id = eap_get_id(reqData); if (data->state != IDENTITY) { return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-ID/Request"); if (payload_len < 2 + 4) { wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data"); return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } pos = payload; end = payload + payload_len; num_prop = *pos++; pos++; /* Ignore Reserved field */ if (pos + num_prop * 4 > end) { wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data (num_prop=%u)", num_prop); return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } for (i = 0; i < num_prop; i++) { const u8 *tmp = pos; wpa_printf(MSG_DEBUG, "EAP-EKE: Proposal #%u: dh=%u encr=%u prf=%u mac=%u", i, pos[0], pos[1], pos[2], pos[3]); pos += 4; if ((data->dhgroup && data->dhgroup != *tmp) || !eap_eke_supp_dhgroup(*tmp)) continue; tmp++; if ((data->encr && data->encr != *tmp) || !eap_eke_supp_encr(*tmp)) continue; tmp++; if ((data->prf && data->prf != *tmp) || !eap_eke_supp_prf(*tmp)) continue; tmp++; if ((data->mac && data->mac != *tmp) || !eap_eke_supp_mac(*tmp)) continue; prop = tmp - 3; if (eap_eke_session_init(&data->sess, prop[0], prop[1], prop[2], prop[3]) < 0) { prop = NULL; continue; } wpa_printf(MSG_DEBUG, "EAP-EKE: Selected proposal"); break; } if (prop == NULL) { wpa_printf(MSG_DEBUG, "EAP-EKE: No acceptable proposal found"); return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_NO_PROPOSAL_CHOSEN); } pos += (num_prop - i - 1) * 4; if (pos == end) { wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data to include IDType/Identity"); return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PROTO_ERROR); } idtype = *pos++; wpa_printf(MSG_DEBUG, "EAP-EKE: Server IDType %u", idtype); wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Server Identity", pos, end - pos); os_free(data->serverid); data->serverid = os_malloc(end - pos); if (data->serverid == NULL) { return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } os_memcpy(data->serverid, pos, end - pos); data->serverid_len = end - pos; wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-ID/Response"); resp = eap_eke_build_msg(data, id, 2 + 4 + 1 + data->peerid_len, EAP_EKE_ID); if (resp == NULL) { return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } wpabuf_put_u8(resp, 1); /* NumProposals */ wpabuf_put_u8(resp, 0); /* Reserved */ wpabuf_put_data(resp, prop, 4); /* Selected Proposal */ wpabuf_put_u8(resp, EAP_EKE_ID_NAI); if (data->peerid) wpabuf_put_data(resp, data->peerid, data->peerid_len); wpabuf_free(data->msgs); data->msgs = wpabuf_alloc(wpabuf_len(reqData) + wpabuf_len(resp)); if (data->msgs == NULL) { wpabuf_free(resp); return eap_eke_build_fail(data, ret, id, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); } wpabuf_put_buf(data->msgs, reqData); wpabuf_put_buf(data->msgs, resp); eap_eke_state(data, COMMIT); return resp; }