/*
 * hostapd / EAP-EKE (RFC 6124) server
 * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "includes.h"

#include "common.h"
#include "crypto/random.h"
#include "eap_server/eap_i.h"
#include "eap_common/eap_eke_common.h"


struct eap_eke_data {
	enum {
		IDENTITY, COMMIT, CONFIRM, FAILURE_REPORT, SUCCESS, FAILURE
	} state;
	u8 msk[EAP_MSK_LEN];
	u8 emsk[EAP_EMSK_LEN];
	u8 *peerid;
	size_t peerid_len;
	u8 peerid_type;
	u8 serverid_type;
	u8 dh_priv[EAP_EKE_MAX_DH_LEN];
	u8 key[EAP_EKE_MAX_KEY_LEN];
	struct eap_eke_session sess;
	u8 nonce_p[EAP_EKE_MAX_NONCE_LEN];
	u8 nonce_s[EAP_EKE_MAX_NONCE_LEN];
	struct wpabuf *msgs;
	int phase2;
	u32 failure_code;
};


static const char * eap_eke_state_txt(int state)
{
	switch (state) {
	case IDENTITY:
		return "IDENTITY";
	case COMMIT:
		return "COMMIT";
	case CONFIRM:
		return "CONFIRM";
	case FAILURE_REPORT:
		return "FAILURE_REPORT";
	case SUCCESS:
		return "SUCCESS";
	case FAILURE:
		return "FAILURE";
	default:
		return "?";
	}
}


static void eap_eke_state(struct eap_eke_data *data, int state)
{
	wpa_printf(MSG_DEBUG, "EAP-EKE: %s -> %s",
		   eap_eke_state_txt(data->state),
		   eap_eke_state_txt(state));
	data->state = state;
}


static void eap_eke_fail(struct eap_eke_data *data, u32 code)
{
	wpa_printf(MSG_DEBUG, "EAP-EKE: Failure - code 0x%x", code);
	data->failure_code = code;
	eap_eke_state(data, FAILURE_REPORT);
}


static void * eap_eke_init(struct eap_sm *sm)
{
	struct eap_eke_data *data;
	size_t i;

	data = os_zalloc(sizeof(*data));
	if (data == NULL)
		return NULL;
	eap_eke_state(data, IDENTITY);

	data->serverid_type = EAP_EKE_ID_OPAQUE;
	for (i = 0; i < sm->server_id_len; i++) {
		if (sm->server_id[i] == '.' &&
		    data->serverid_type == EAP_EKE_ID_OPAQUE)
			data->serverid_type = EAP_EKE_ID_FQDN;
		if (sm->server_id[i] == '@')
			data->serverid_type = EAP_EKE_ID_NAI;
	}

	data->phase2 = sm->init_phase2;

	return data;
}


static void eap_eke_reset(struct eap_sm *sm, void *priv)
{
	struct eap_eke_data *data = priv;
	eap_eke_session_clean(&data->sess);
	os_free(data->peerid);
	wpabuf_free(data->msgs);
	bin_clear_free(data, sizeof(*data));
}


static struct wpabuf * eap_eke_build_msg(struct eap_eke_data *data,
					 u8 id, size_t length, u8 eke_exch)
{
	struct wpabuf *msg;
	size_t plen;

	plen = 1 + length;

	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EKE, plen,
			    EAP_CODE_REQUEST, id);
	if (msg == NULL) {
		wpa_printf(MSG_ERROR, "EAP-EKE: Failed to allocate memory");
		return NULL;
	}

	wpabuf_put_u8(msg, eke_exch);

	return msg;
}


static int supported_proposal(const u8 *pos)
{
	if (pos[0] == EAP_EKE_DHGROUP_EKE_16 &&
	    pos[1] == EAP_EKE_ENCR_AES128_CBC &&
	    pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 &&
	    pos[3] == EAP_EKE_MAC_HMAC_SHA2_256)
		return 1;

	if (pos[0] == EAP_EKE_DHGROUP_EKE_15 &&
	    pos[1] == EAP_EKE_ENCR_AES128_CBC &&
	    pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 &&
	    pos[3] == EAP_EKE_MAC_HMAC_SHA2_256)
		return 1;

	if (pos[0] == EAP_EKE_DHGROUP_EKE_14 &&
	    pos[1] == EAP_EKE_ENCR_AES128_CBC &&
	    pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 &&
	    pos[3] == EAP_EKE_MAC_HMAC_SHA2_256)
		return 1;

	if (pos[0] == EAP_EKE_DHGROUP_EKE_14 &&
	    pos[1] == EAP_EKE_ENCR_AES128_CBC &&
	    pos[2] == EAP_EKE_PRF_HMAC_SHA1 &&
	    pos[3] == EAP_EKE_MAC_HMAC_SHA1)
		return 1;

	return 0;
}


static struct wpabuf * eap_eke_build_failure(struct eap_eke_data *data, u8 id)
{
	struct wpabuf *msg;

	wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Failure: Failure-Code=0x%x",
		   data->failure_code);

	msg = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE);
	if (msg == NULL) {
		eap_eke_state(data, FAILURE);
		return NULL;
	}
	wpabuf_put_be32(msg, data->failure_code);

	return msg;
}


static struct wpabuf * eap_eke_build_identity(struct eap_sm *sm,
					      struct eap_eke_data *data,
					      u8 id)
{
	struct wpabuf *msg;
	size_t plen;

	wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Identity");

	plen = 2 + 4 * 4 + 1 + sm->server_id_len;
	msg = eap_eke_build_msg(data, id, plen, EAP_EKE_ID);
	if (msg == NULL)
		return NULL;

	wpabuf_put_u8(msg, 4); /* NumProposals */
	wpabuf_put_u8(msg, 0); /* Reserved */

	/* Proposal - DH Group 16 with AES128-CBC and SHA256 */
	wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_16); /* Group Description */
	wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
	wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */
	wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */

	/* Proposal - DH Group 15 with AES128-CBC and SHA256 */
	wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_15); /* Group Description */
	wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
	wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */
	wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */

	/* Proposal - DH Group 14 with AES128-CBC and SHA256 */
	wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */
	wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
	wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */
	wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */

	/*
	 * Proposal - DH Group 14 with AES128-CBC and SHA1
	 * (mandatory to implement algorithms)
	 */
	wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */
	wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
	wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA1); /* PRF */
	wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA1); /* MAC */

	/* Server IDType + Identity */
	wpabuf_put_u8(msg, data->serverid_type);
	wpabuf_put_data(msg, sm->server_id, sm->server_id_len);

	wpabuf_free(data->msgs);
	data->msgs = wpabuf_dup(msg);
	if (data->msgs == NULL) {
		wpabuf_free(msg);
		return NULL;
	}

	return msg;
}


static struct wpabuf * eap_eke_build_commit(struct eap_sm *sm,
					    struct eap_eke_data *data, u8 id)
{
	struct wpabuf *msg;
	u8 pub[EAP_EKE_MAX_DH_LEN];

	wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Commit");

	if (sm->user == NULL || sm->user->password == NULL) {
		wpa_printf(MSG_INFO, "EAP-EKE: Password with not configured");
		eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
		return eap_eke_build_failure(data, id);
	}

	if (eap_eke_derive_key(&data->sess, sm->user->password,
			       sm->user->password_len,
			       sm->server_id, sm->server_id_len,
			       data->peerid, data->peerid_len, data->key) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key");
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}

	msg = eap_eke_build_msg(data, id, data->sess.dhcomp_len,
				EAP_EKE_COMMIT);
	if (msg == NULL) {
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}

	/*
	 * y_s = g ^ x_s (mod p)
	 * x_s = random number 2 .. p-1
	 * temp = prf(0+, password)
	 * key = prf+(temp, ID_S | ID_P)
	 * DHComponent_S = Encr(key, y_s)
	 */

	if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH");
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}

	if (eap_eke_dhcomp(&data->sess, data->key, pub,
			   wpabuf_put(msg, data->sess.dhcomp_len))
	    < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_S");
		wpabuf_free(msg);
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}

	if (wpabuf_resize(&data->msgs, wpabuf_len(msg)) < 0) {
		wpabuf_free(msg);
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}
	wpabuf_put_buf(data->msgs, msg);

	return msg;
}


static struct wpabuf * eap_eke_build_confirm(struct eap_sm *sm,
					     struct eap_eke_data *data, u8 id)
{
	struct wpabuf *msg;
	size_t plen, prot_len;
	u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN];
	u8 *auth;

	wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Confirm");

	plen = data->sess.pnonce_ps_len + data->sess.prf_len;
	msg = eap_eke_build_msg(data, id, plen, EAP_EKE_CONFIRM);
	if (msg == NULL) {
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}

	if (random_get_bytes(data->nonce_s, data->sess.nonce_len)) {
		wpabuf_free(msg);
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}
	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S",
			data->nonce_s, data->sess.nonce_len);

	os_memcpy(nonces, data->nonce_p, data->sess.nonce_len);
	os_memcpy(nonces + data->sess.nonce_len, data->nonce_s,
		  data->sess.nonce_len);
	prot_len = wpabuf_tailroom(msg);
	if (eap_eke_prot(&data->sess, nonces, 2 * data->sess.nonce_len,
			 wpabuf_put(msg, 0), &prot_len) < 0) {
		wpabuf_free(msg);
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}
	wpabuf_put(msg, prot_len);

	if (eap_eke_derive_ka(&data->sess,
			      sm->server_id, sm->server_id_len,
			      data->peerid, data->peerid_len,
			      data->nonce_p, data->nonce_s) < 0) {
		wpabuf_free(msg);
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}

	auth = wpabuf_put(msg, data->sess.prf_len);
	if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth) < 0) {
		wpabuf_free(msg);
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}
	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth, data->sess.prf_len);

	return msg;
}


static struct wpabuf * eap_eke_buildReq(struct eap_sm *sm, void *priv, u8 id)
{
	struct eap_eke_data *data = priv;

	switch (data->state) {
	case IDENTITY:
		return eap_eke_build_identity(sm, data, id);
	case COMMIT:
		return eap_eke_build_commit(sm, data, id);
	case CONFIRM:
		return eap_eke_build_confirm(sm, data, id);
	case FAILURE_REPORT:
		return eap_eke_build_failure(data, id);
	default:
		wpa_printf(MSG_DEBUG, "EAP-EKE: Unknown state %d in buildReq",
			   data->state);
		break;
	}
	return NULL;
}


static Boolean eap_eke_check(struct eap_sm *sm, void *priv,
			     struct wpabuf *respData)
{
	struct eap_eke_data *data = priv;
	size_t len;
	const u8 *pos;
	u8 eke_exch;

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len);
	if (pos == NULL || len < 1) {
		wpa_printf(MSG_INFO, "EAP-EKE: Invalid frame");
		return TRUE;
	}

	eke_exch = *pos;
	wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: EKE-Exch=%d", eke_exch);

	if (data->state == IDENTITY && eke_exch == EAP_EKE_ID)
		return FALSE;

	if (data->state == COMMIT && eke_exch == EAP_EKE_COMMIT)
		return FALSE;

	if (data->state == CONFIRM && eke_exch == EAP_EKE_CONFIRM)
		return FALSE;

	if (eke_exch == EAP_EKE_FAILURE)
		return FALSE;

	wpa_printf(MSG_INFO, "EAP-EKE: Unexpected EKE-Exch=%d in state=%d",
		   eke_exch, data->state);

	return TRUE;
}


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_malloc(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;
	}
	os_memcpy(data->peerid, pos, end - pos);
	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 void eap_eke_process_commit(struct eap_sm *sm,
				   struct eap_eke_data *data,
				   const struct wpabuf *respData,
				   const u8 *payload, size_t payloadlen)
{
	const u8 *pos, *end, *dhcomp, *pnonce;
	size_t decrypt_len;

	wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Commit");

	if (data->state != COMMIT) {
		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
		return;
	}

	pos = payload;
	end = payload + payloadlen;

	if (pos + data->sess.dhcomp_len + data->sess.pnonce_len > end) {
		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit");
		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
		return;
	}

	wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P",
		    pos, data->sess.dhcomp_len);
	dhcomp = pos;
	pos += data->sess.dhcomp_len;
	wpa_hexdump(MSG_DEBUG, "EAP-EKE: PNonce_P", pos, data->sess.pnonce_len);
	pnonce = pos;
	pos += data->sess.pnonce_len;
	wpa_hexdump(MSG_DEBUG, "EAP-EKE: CBValue", pos, end - pos);

	if (eap_eke_shared_secret(&data->sess, data->key, data->dh_priv, dhcomp)
	    < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret");
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return;
	}

	if (eap_eke_derive_ke_ki(&data->sess,
				 sm->server_id, sm->server_id_len,
				 data->peerid, data->peerid_len) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki");
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return;
	}

	decrypt_len = sizeof(data->nonce_p);
	if (eap_eke_decrypt_prot(&data->sess, pnonce, data->sess.pnonce_len,
				 data->nonce_p, &decrypt_len) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_P");
		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
		return;
	}
	if (decrypt_len < (size_t) data->sess.nonce_len) {
		wpa_printf(MSG_INFO, "EAP-EKE: PNonce_P protected data too short to include Nonce_P");
		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
		return;
	}
	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_P",
			data->nonce_p, data->sess.nonce_len);

	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, CONFIRM);
}


static void eap_eke_process_confirm(struct eap_sm *sm,
				    struct eap_eke_data *data,
				    const struct wpabuf *respData,
				    const u8 *payload, size_t payloadlen)
{
	size_t decrypt_len;
	u8 nonce[EAP_EKE_MAX_NONCE_LEN];
	u8 auth_p[EAP_EKE_MAX_HASH_LEN];

	wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm");

	if (data->state != CONFIRM) {
		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
		return;
	}

	wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm");

	if (payloadlen < (size_t) data->sess.pnonce_len + data->sess.prf_len) {
		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm");
		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
		return;
	}

	decrypt_len = sizeof(nonce);
	if (eap_eke_decrypt_prot(&data->sess, payload, data->sess.pnonce_len,
				 nonce, &decrypt_len) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_S");
		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
		return;
	}
	if (decrypt_len < (size_t) data->sess.nonce_len) {
		wpa_printf(MSG_INFO, "EAP-EKE: PNonce_S protected data too short to include Nonce_S");
		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
		return;
	}
	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_S",
			nonce, data->sess.nonce_len);
	if (os_memcmp(nonce, data->nonce_s, data->sess.nonce_len) != 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_S does not match previously sent Nonce_S");
		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
		return;
	}

	if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth_p) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Could not derive Auth_P");
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return;
	}
	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth_p, data->sess.prf_len);
	if (os_memcmp_const(auth_p, payload + data->sess.pnonce_len,
			    data->sess.prf_len) != 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Auth_P does not match");
		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
		return;
	}

	if (eap_eke_derive_msk(&data->sess, sm->server_id, sm->server_id_len,
			       data->peerid, data->peerid_len,
			       data->nonce_s, data->nonce_p,
			       data->msk, data->emsk) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK");
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return;
	}

	os_memset(data->dh_priv, 0, sizeof(data->dh_priv));
	os_memset(data->key, 0, sizeof(data->key));
	eap_eke_session_clean(&data->sess);

	eap_eke_state(data, SUCCESS);
}


static void eap_eke_process_failure(struct eap_sm *sm,
				    struct eap_eke_data *data,
				    const struct wpabuf *respData,
				    const u8 *payload, size_t payloadlen)
{
	u32 code;

	wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Failure");

	if (payloadlen < 4) {
		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Failure");
		eap_eke_state(data, FAILURE);
		return;
	}

	code = WPA_GET_BE32(payload);
	wpa_printf(MSG_DEBUG, "EAP-EKE: Peer reported failure code 0x%x", code);

	eap_eke_state(data, FAILURE);
}


static void eap_eke_process(struct eap_sm *sm, void *priv,
			     struct wpabuf *respData)
{
	struct eap_eke_data *data = priv;
	u8 eke_exch;
	size_t len;
	const u8 *pos, *end;

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len);
	if (pos == NULL || len < 1)
		return;

	eke_exch = *pos;
	end = pos + len;
	pos++;

	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received payload", pos, end - pos);

	switch (eke_exch) {
	case EAP_EKE_ID:
		eap_eke_process_identity(sm, data, respData, pos, end - pos);
		break;
	case EAP_EKE_COMMIT:
		eap_eke_process_commit(sm, data, respData, pos, end - pos);
		break;
	case EAP_EKE_CONFIRM:
		eap_eke_process_confirm(sm, data, respData, pos, end - pos);
		break;
	case EAP_EKE_FAILURE:
		eap_eke_process_failure(sm, data, respData, pos, end - pos);
		break;
	}
}


static Boolean eap_eke_isDone(struct eap_sm *sm, void *priv)
{
	struct eap_eke_data *data = priv;
	return data->state == SUCCESS || data->state == FAILURE;
}


static u8 * eap_eke_getKey(struct eap_sm *sm, void *priv, size_t *len)
{
	struct eap_eke_data *data = priv;
	u8 *key;

	if (data->state != SUCCESS)
		return NULL;

	key = os_malloc(EAP_MSK_LEN);
	if (key == NULL)
		return NULL;
	os_memcpy(key, data->msk, EAP_MSK_LEN);
	*len = EAP_MSK_LEN;

	return key;
}


static u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
	struct eap_eke_data *data = priv;
	u8 *key;

	if (data->state != SUCCESS)
		return NULL;

	key = os_malloc(EAP_EMSK_LEN);
	if (key == NULL)
		return NULL;
	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
	*len = EAP_EMSK_LEN;

	return key;
}


static Boolean eap_eke_isSuccess(struct eap_sm *sm, void *priv)
{
	struct eap_eke_data *data = priv;
	return data->state == SUCCESS;
}


int eap_server_eke_register(void)
{
	struct eap_method *eap;
	int ret;

	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
				      EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE");
	if (eap == NULL)
		return -1;

	eap->init = eap_eke_init;
	eap->reset = eap_eke_reset;
	eap->buildReq = eap_eke_buildReq;
	eap->check = eap_eke_check;
	eap->process = eap_eke_process;
	eap->isDone = eap_eke_isDone;
	eap->getKey = eap_eke_getKey;
	eap->isSuccess = eap_eke_isSuccess;
	eap->get_emsk = eap_eke_get_emsk;

	ret = eap_server_method_register(eap);
	if (ret)
		eap_server_method_free(eap);
	return ret;
}
