134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt/*
234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * hostapd / EAP-EKE (RFC 6124) server
334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt *
534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * See README for more details.
734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */
834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "includes.h"
1034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
1134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "common.h"
1234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "crypto/random.h"
1334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "eap_server/eap_i.h"
1434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "eap_common/eap_eke_common.h"
1534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
1634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
1734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstruct eap_eke_data {
1834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	enum {
1934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		IDENTITY, COMMIT, CONFIRM, FAILURE_REPORT, SUCCESS, FAILURE
2034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	} state;
2134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 msk[EAP_MSK_LEN];
2234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 emsk[EAP_EMSK_LEN];
2334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 *peerid;
2434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t peerid_len;
2534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 peerid_type;
2634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 serverid_type;
2734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 dh_priv[EAP_EKE_MAX_DH_LEN];
2834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 key[EAP_EKE_MAX_KEY_LEN];
2934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_eke_session sess;
3034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 nonce_p[EAP_EKE_MAX_NONCE_LEN];
3134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 nonce_s[EAP_EKE_MAX_NONCE_LEN];
3234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct wpabuf *msgs;
3334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	int phase2;
3434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u32 failure_code;
3534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt};
3634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
3734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
3834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic const char * eap_eke_state_txt(int state)
3934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
4034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	switch (state) {
4134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case IDENTITY:
4234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return "IDENTITY";
4334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case COMMIT:
4434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return "COMMIT";
4534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case CONFIRM:
4634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return "CONFIRM";
4734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case FAILURE_REPORT:
4834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return "FAILURE_REPORT";
4934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case SUCCESS:
5034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return "SUCCESS";
5134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case FAILURE:
5234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return "FAILURE";
5334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	default:
5434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return "?";
5534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
5634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
5734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
5834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
5934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_state(struct eap_eke_data *data, int state)
6034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
6134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: %s -> %s",
6234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		   eap_eke_state_txt(data->state),
6334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		   eap_eke_state_txt(state));
6434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	data->state = state;
6534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
6634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
6734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
6834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_fail(struct eap_eke_data *data, u32 code)
6934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
7034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Failure - code 0x%x", code);
7134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	data->failure_code = code;
7234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap_eke_state(data, FAILURE_REPORT);
7334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
7434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
7534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
7634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void * eap_eke_init(struct eap_sm *sm)
7734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
7834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_eke_data *data;
7934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t i;
8034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
8134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	data = os_zalloc(sizeof(*data));
8234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data == NULL)
8334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return NULL;
8434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap_eke_state(data, IDENTITY);
8534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
8634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	data->serverid_type = EAP_EKE_ID_OPAQUE;
8734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	for (i = 0; i < sm->server_id_len; i++) {
8834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		if (sm->server_id[i] == '.' &&
8934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		    data->serverid_type == EAP_EKE_ID_OPAQUE)
9034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			data->serverid_type = EAP_EKE_ID_FQDN;
9134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		if (sm->server_id[i] == '@')
9234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			data->serverid_type = EAP_EKE_ID_NAI;
9334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
9434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
9534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	data->phase2 = sm->init_phase2;
9634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
9734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return data;
9834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
9934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
10034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
10134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_reset(struct eap_sm *sm, void *priv)
10234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
10334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_eke_data *data = priv;
10434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap_eke_session_clean(&data->sess);
10534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_free(data->peerid);
10634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_free(data->msgs);
107c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	bin_clear_free(data, sizeof(*data));
10834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
10934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
11034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
11134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_msg(struct eap_eke_data *data,
11234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt					 u8 id, size_t length, u8 eke_exch)
11334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
11434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct wpabuf *msg;
11534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t plen;
11634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
11734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	plen = 1 + length;
11834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
11934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EKE, plen,
12034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			    EAP_CODE_REQUEST, id);
12134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (msg == NULL) {
12234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-EKE: Failed to allocate memory");
12334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return NULL;
12434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
12534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
12634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, eke_exch);
12734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
12834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return msg;
12934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
13034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
13134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
13234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int supported_proposal(const u8 *pos)
13334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
13434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (pos[0] == EAP_EKE_DHGROUP_EKE_16 &&
13534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[1] == EAP_EKE_ENCR_AES128_CBC &&
13634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 &&
13734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[3] == EAP_EKE_MAC_HMAC_SHA2_256)
13834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 1;
13934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
14034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (pos[0] == EAP_EKE_DHGROUP_EKE_15 &&
14134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[1] == EAP_EKE_ENCR_AES128_CBC &&
14234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 &&
14334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[3] == EAP_EKE_MAC_HMAC_SHA2_256)
14434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 1;
14534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
14634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (pos[0] == EAP_EKE_DHGROUP_EKE_14 &&
14734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[1] == EAP_EKE_ENCR_AES128_CBC &&
14834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 &&
14934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[3] == EAP_EKE_MAC_HMAC_SHA2_256)
15034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 1;
15134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
15234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (pos[0] == EAP_EKE_DHGROUP_EKE_14 &&
15334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[1] == EAP_EKE_ENCR_AES128_CBC &&
15434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[2] == EAP_EKE_PRF_HMAC_SHA1 &&
15534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    pos[3] == EAP_EKE_MAC_HMAC_SHA1)
15634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return 1;
15734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
15834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return 0;
15934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
16034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
16134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
16234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_failure(struct eap_eke_data *data, u8 id)
16334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
16434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct wpabuf *msg;
16534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
16634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Failure: Failure-Code=0x%x",
16734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		   data->failure_code);
16834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
16934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	msg = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE);
17034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (msg == NULL) {
17134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_state(data, FAILURE);
17234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return NULL;
17334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
17434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_be32(msg, data->failure_code);
17534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
17634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return msg;
17734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
17834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
17934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
18034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_identity(struct eap_sm *sm,
18134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt					      struct eap_eke_data *data,
18234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt					      u8 id)
18334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
18434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct wpabuf *msg;
18534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t plen;
18634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
18734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Identity");
18834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
18934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	plen = 2 + 4 * 4 + 1 + sm->server_id_len;
19034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	msg = eap_eke_build_msg(data, id, plen, EAP_EKE_ID);
19134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (msg == NULL)
19234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return NULL;
19334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
19434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, 4); /* NumProposals */
19534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, 0); /* Reserved */
19634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
19734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	/* Proposal - DH Group 16 with AES128-CBC and SHA256 */
19834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_16); /* Group Description */
19934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
20034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */
20134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */
20234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
20334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	/* Proposal - DH Group 15 with AES128-CBC and SHA256 */
20434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_15); /* Group Description */
20534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
20634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */
20734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */
20834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
20934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	/* Proposal - DH Group 14 with AES128-CBC and SHA256 */
21034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */
21134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
21234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */
21334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */
21434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
21534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	/*
21634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	 * Proposal - DH Group 14 with AES128-CBC and SHA1
21734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	 * (mandatory to implement algorithms)
21834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	 */
21934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */
22034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */
22134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA1); /* PRF */
22234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA1); /* MAC */
22334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
22434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	/* Server IDType + Identity */
22534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_u8(msg, data->serverid_type);
22634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_data(msg, sm->server_id, sm->server_id_len);
22734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
22834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_free(data->msgs);
22934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	data->msgs = wpabuf_dup(msg);
23034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data->msgs == NULL) {
23134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpabuf_free(msg);
23234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return NULL;
23334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
23434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
23534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return msg;
23634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
23734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
23834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
23934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_commit(struct eap_sm *sm,
24034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt					    struct eap_eke_data *data, u8 id)
24134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
24234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct wpabuf *msg;
24334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 pub[EAP_EKE_MAX_DH_LEN];
24434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
24534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Commit");
24634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
24734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (sm->user == NULL || sm->user->password == NULL) {
24834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Password with not configured");
24934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
25034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
25134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
25234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
25334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_derive_key(&data->sess, sm->user->password,
25434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			       sm->user->password_len,
25534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			       sm->server_id, sm->server_id_len,
25634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			       data->peerid, data->peerid_len, data->key) < 0) {
25734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key");
25834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
25934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
26034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
26134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
26234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	msg = eap_eke_build_msg(data, id, data->sess.dhcomp_len,
26334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				EAP_EKE_COMMIT);
26434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (msg == NULL) {
26534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
26634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
26734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
26834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
26934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	/*
27034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	 * y_s = g ^ x_s (mod p)
27134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	 * x_s = random number 2 .. p-1
27234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	 * temp = prf(0+, password)
27334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	 * key = prf+(temp, ID_S | ID_P)
27434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	 * DHComponent_S = Encr(key, y_s)
27534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	 */
27634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
27734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) {
27834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH");
27934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
28034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
28134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
28234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
28334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_dhcomp(&data->sess, data->key, pub,
28434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			   wpabuf_put(msg, data->sess.dhcomp_len))
28534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    < 0) {
28634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_S");
28734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpabuf_free(msg);
28834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
28934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
29034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
29134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
29234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (wpabuf_resize(&data->msgs, wpabuf_len(msg)) < 0) {
29334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpabuf_free(msg);
29434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
29534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
29634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
29734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_buf(data->msgs, msg);
29834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
29934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return msg;
30034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
30134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
30234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
30334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_confirm(struct eap_sm *sm,
30434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt					     struct eap_eke_data *data, u8 id)
30534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
30634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct wpabuf *msg;
30734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t plen, prot_len;
30834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN];
30934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 *auth;
31034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
31134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Confirm");
31234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
31334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	plen = data->sess.pnonce_ps_len + data->sess.prf_len;
31434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	msg = eap_eke_build_msg(data, id, plen, EAP_EKE_CONFIRM);
31534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (msg == NULL) {
31634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
31734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
31834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
31934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
32034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (random_get_bytes(data->nonce_s, data->sess.nonce_len)) {
32134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpabuf_free(msg);
32234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
32334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
32434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
32534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S",
32634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			data->nonce_s, data->sess.nonce_len);
32734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
32834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_memcpy(nonces, data->nonce_p, data->sess.nonce_len);
32934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_memcpy(nonces + data->sess.nonce_len, data->nonce_s,
33034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		  data->sess.nonce_len);
33134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	prot_len = wpabuf_tailroom(msg);
33234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_prot(&data->sess, nonces, 2 * data->sess.nonce_len,
33334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			 wpabuf_put(msg, 0), &prot_len) < 0) {
33434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpabuf_free(msg);
33534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
33634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
33734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
33834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put(msg, prot_len);
33934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
34034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_derive_ka(&data->sess,
34134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			      sm->server_id, sm->server_id_len,
34234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			      data->peerid, data->peerid_len,
34334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			      data->nonce_p, data->nonce_s) < 0) {
34434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpabuf_free(msg);
34534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
34634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
34734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
34834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
34934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	auth = wpabuf_put(msg, data->sess.prf_len);
35034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth) < 0) {
35134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpabuf_free(msg);
35234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
35334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
35434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
35534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth, data->sess.prf_len);
35634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
35734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return msg;
35834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
35934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
36034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
36134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_buildReq(struct eap_sm *sm, void *priv, u8 id)
36234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
36334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_eke_data *data = priv;
36434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
36534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	switch (data->state) {
36634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case IDENTITY:
36734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_identity(sm, data, id);
36834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case COMMIT:
36934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_commit(sm, data, id);
37034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case CONFIRM:
37134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_confirm(sm, data, id);
37234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case FAILURE_REPORT:
37334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return eap_eke_build_failure(data, id);
37434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	default:
37534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-EKE: Unknown state %d in buildReq",
37634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			   data->state);
37734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		break;
37834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
37934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return NULL;
38034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
38134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
38234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
38334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic Boolean eap_eke_check(struct eap_sm *sm, void *priv,
38434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			     struct wpabuf *respData)
38534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
38634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_eke_data *data = priv;
38734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t len;
38834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	const u8 *pos;
38934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 eke_exch;
39034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
39134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len);
39234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (pos == NULL || len < 1) {
39334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Invalid frame");
39434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return TRUE;
39534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
39634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
39734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eke_exch = *pos;
39834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: EKE-Exch=%d", eke_exch);
39934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
40034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data->state == IDENTITY && eke_exch == EAP_EKE_ID)
40134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return FALSE;
40234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
40334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data->state == COMMIT && eke_exch == EAP_EKE_COMMIT)
40434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return FALSE;
40534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
40634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data->state == CONFIRM && eke_exch == EAP_EKE_CONFIRM)
40734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return FALSE;
40834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
40934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eke_exch == EAP_EKE_FAILURE)
41034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return FALSE;
41134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
41234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_INFO, "EAP-EKE: Unexpected EKE-Exch=%d in state=%d",
41334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		   eke_exch, data->state);
41434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
41534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return TRUE;
41634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
41734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
41834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
41934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_process_identity(struct eap_sm *sm,
42034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				     struct eap_eke_data *data,
42134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				     const struct wpabuf *respData,
42234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				     const u8 *payload, size_t payloadlen)
42334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
42434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	const u8 *pos, *end;
42534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	int i;
42634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
42734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Identity");
42834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
42934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data->state != IDENTITY) {
43034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
43134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
43234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
43334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
43434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	pos = payload;
43534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	end = payload + payloadlen;
43634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
43734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (pos + 2 + 4 + 1 > end) {
43834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Too short EAP-EKE-ID payload");
43934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
44034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
44134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
44234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
44334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (*pos != 1) {
44434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Unexpected NumProposals %d (expected 1)",
44534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			   *pos);
44634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
44734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
44834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
44934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
45034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	pos += 2;
45134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
45234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (!supported_proposal(pos)) {
45334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Unexpected Proposal (%u:%u:%u:%u)",
45434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			   pos[0], pos[1], pos[2], pos[3]);
45534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
45634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
45734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
45834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
45934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Selected Proposal (%u:%u:%u:%u)",
46034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		   pos[0], pos[1], pos[2], pos[3]);
46134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_session_init(&data->sess, pos[0], pos[1], pos[2], pos[3]) <
46234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    0) {
46334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
46434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
46534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
46634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	pos += 4;
46734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
46834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	data->peerid_type = *pos++;
46934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_free(data->peerid);
47034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	data->peerid = os_malloc(end - pos);
47134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data->peerid == NULL) {
47234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Failed to allocate memory for peerid");
47334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
47434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
47534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
47634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_memcpy(data->peerid, pos, end - pos);
47734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	data->peerid_len = end - pos;
47834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Peer IDType %u", data->peerid_type);
47934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Peer Identity",
48034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			  data->peerid, data->peerid_len);
48134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
48234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_user_get(sm, data->peerid, data->peerid_len, data->phase2)) {
48334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Peer Identity not found from user database");
48434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
48534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
48634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
48734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
48834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	for (i = 0; i < EAP_MAX_METHODS; i++) {
48934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		if (sm->user->methods[i].vendor == EAP_VENDOR_IETF &&
49034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		    sm->user->methods[i].method == EAP_TYPE_EKE)
49134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			break;
49234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
49334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (i == EAP_MAX_METHODS) {
49434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Matching user entry does not allow EAP-EKE");
49534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
49634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
49734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
49834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
49934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (sm->user->password == NULL || sm->user->password_len == 0) {
50034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: No password configured for peer");
50134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
50234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
50334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
50434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
50534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) {
50634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
50734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
50834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
50934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_buf(data->msgs, respData);
51034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
51134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap_eke_state(data, COMMIT);
51234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
51334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
51434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
51534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_process_commit(struct eap_sm *sm,
51634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				   struct eap_eke_data *data,
51734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				   const struct wpabuf *respData,
51834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				   const u8 *payload, size_t payloadlen)
51934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
52034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	const u8 *pos, *end, *dhcomp, *pnonce;
52134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t decrypt_len;
52234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
52334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Commit");
52434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
52534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data->state != COMMIT) {
52634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
52734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
52834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
52934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
53034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	pos = payload;
53134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	end = payload + payloadlen;
53234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
53334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (pos + data->sess.dhcomp_len + data->sess.pnonce_len > end) {
53434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit");
53534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
53634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
53734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
53834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
53934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P",
54034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		    pos, data->sess.dhcomp_len);
54134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	dhcomp = pos;
54234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	pos += data->sess.dhcomp_len;
54334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP-EKE: PNonce_P", pos, data->sess.pnonce_len);
54434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	pnonce = pos;
54534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	pos += data->sess.pnonce_len;
54634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP-EKE: CBValue", pos, end - pos);
54734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
54834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_shared_secret(&data->sess, data->key, data->dh_priv, dhcomp)
54934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	    < 0) {
55034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret");
55134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
55234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
55334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
55434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
55534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_derive_ke_ki(&data->sess,
55634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				 sm->server_id, sm->server_id_len,
55734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				 data->peerid, data->peerid_len) < 0) {
55834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki");
55934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
56034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
56134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
56234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
56334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	decrypt_len = sizeof(data->nonce_p);
56434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_decrypt_prot(&data->sess, pnonce, data->sess.pnonce_len,
56534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				 data->nonce_p, &decrypt_len) < 0) {
56634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_P");
56734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
56834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
56934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
57034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (decrypt_len < (size_t) data->sess.nonce_len) {
57134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: PNonce_P protected data too short to include Nonce_P");
57234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
57334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
57434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
57534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_P",
57634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			data->nonce_p, data->sess.nonce_len);
57734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
57834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) {
57934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
58034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
58134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
58234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpabuf_put_buf(data->msgs, respData);
58334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
58434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap_eke_state(data, CONFIRM);
58534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
58634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
58734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
58834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_process_confirm(struct eap_sm *sm,
58934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				    struct eap_eke_data *data,
59034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				    const struct wpabuf *respData,
59134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				    const u8 *payload, size_t payloadlen)
59234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
59334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t decrypt_len;
59434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 nonce[EAP_EKE_MAX_NONCE_LEN];
59534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 auth_p[EAP_EKE_MAX_HASH_LEN];
59634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
59734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm");
59834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
59934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data->state != CONFIRM) {
60034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
60134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
60234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
60334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
60434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm");
60534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
60634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (payloadlen < (size_t) data->sess.pnonce_len + data->sess.prf_len) {
60734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm");
60834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
60934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
61034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
61134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
61234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	decrypt_len = sizeof(nonce);
61334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_decrypt_prot(&data->sess, payload, data->sess.pnonce_len,
61434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				 nonce, &decrypt_len) < 0) {
61534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_S");
61634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
61734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
61834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
61934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (decrypt_len < (size_t) data->sess.nonce_len) {
62034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: PNonce_S protected data too short to include Nonce_S");
62134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
62234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
62334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
62434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_S",
62534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			nonce, data->sess.nonce_len);
62634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (os_memcmp(nonce, data->nonce_s, data->sess.nonce_len) != 0) {
62734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_S does not match previously sent Nonce_S");
62834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
62934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
63034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
63134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
63234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth_p) < 0) {
63334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Could not derive Auth_P");
63434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
63534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
63634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
63734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth_p, data->sess.prf_len);
638c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(auth_p, payload + data->sess.pnonce_len,
639c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt			    data->sess.prf_len) != 0) {
64034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Auth_P does not match");
64134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
64234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
64334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
64434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
64534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap_eke_derive_msk(&data->sess, sm->server_id, sm->server_id_len,
64634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			       data->peerid, data->peerid_len,
64734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			       data->nonce_s, data->nonce_p,
64834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			       data->msk, data->emsk) < 0) {
64934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK");
65034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
65134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
65234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
65334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
65434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_memset(data->dh_priv, 0, sizeof(data->dh_priv));
65534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_memset(data->key, 0, sizeof(data->key));
65634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap_eke_session_clean(&data->sess);
65734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
65834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap_eke_state(data, SUCCESS);
65934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
66034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
66134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
66234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_process_failure(struct eap_sm *sm,
66334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				    struct eap_eke_data *data,
66434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				    const struct wpabuf *respData,
66534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				    const u8 *payload, size_t payloadlen)
66634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
66734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u32 code;
66834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
66934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Failure");
67034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
67134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (payloadlen < 4) {
67234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Failure");
67334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_state(data, FAILURE);
67434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
67534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
67634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
67734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	code = WPA_GET_BE32(payload);
67834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-EKE: Peer reported failure code 0x%x", code);
67934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
68034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap_eke_state(data, FAILURE);
68134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
68234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
68334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
68434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_process(struct eap_sm *sm, void *priv,
68534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt			     struct wpabuf *respData)
68634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
68734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_eke_data *data = priv;
68834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 eke_exch;
68934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	size_t len;
69034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	const u8 *pos, *end;
69134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
69234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len);
69334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (pos == NULL || len < 1)
69434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return;
69534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
69634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eke_exch = *pos;
69734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	end = pos + len;
69834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	pos++;
69934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
70034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received payload", pos, end - pos);
70134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
70234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	switch (eke_exch) {
70334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case EAP_EKE_ID:
70434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_process_identity(sm, data, respData, pos, end - pos);
70534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		break;
70634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case EAP_EKE_COMMIT:
70734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_process_commit(sm, data, respData, pos, end - pos);
70834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		break;
70934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case EAP_EKE_CONFIRM:
71034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_process_confirm(sm, data, respData, pos, end - pos);
71134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		break;
71234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	case EAP_EKE_FAILURE:
71334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_eke_process_failure(sm, data, respData, pos, end - pos);
71434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		break;
71534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	}
71634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
71734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
71834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
71934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic Boolean eap_eke_isDone(struct eap_sm *sm, void *priv)
72034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
72134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_eke_data *data = priv;
72234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return data->state == SUCCESS || data->state == FAILURE;
72334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
72434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
72534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
72634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic u8 * eap_eke_getKey(struct eap_sm *sm, void *priv, size_t *len)
72734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
72834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_eke_data *data = priv;
72934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 *key;
73034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
73134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data->state != SUCCESS)
73234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return NULL;
73334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
73434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	key = os_malloc(EAP_MSK_LEN);
73534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (key == NULL)
73634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return NULL;
73734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_memcpy(key, data->msk, EAP_MSK_LEN);
73834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	*len = EAP_MSK_LEN;
73934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
74034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return key;
74134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
74234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
74334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
74434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
74534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
74634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_eke_data *data = priv;
74734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u8 *key;
74834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
74934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (data->state != SUCCESS)
75034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return NULL;
75134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
75234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	key = os_malloc(EAP_EMSK_LEN);
75334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (key == NULL)
75434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return NULL;
75534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
75634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	*len = EAP_EMSK_LEN;
75734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
75834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return key;
75934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
76034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
76134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
76234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic Boolean eap_eke_isSuccess(struct eap_sm *sm, void *priv)
76334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
76434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_eke_data *data = priv;
76534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return data->state == SUCCESS;
76634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
76734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
76834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
76934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtint eap_server_eke_register(void)
77034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{
77134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	struct eap_method *eap;
77234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	int ret;
77334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
77434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
77534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt				      EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE");
77634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (eap == NULL)
77734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		return -1;
77834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
77934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap->init = eap_eke_init;
78034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap->reset = eap_eke_reset;
78134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap->buildReq = eap_eke_buildReq;
78234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap->check = eap_eke_check;
78334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap->process = eap_eke_process;
78434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap->isDone = eap_eke_isDone;
78534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap->getKey = eap_eke_getKey;
78634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap->isSuccess = eap_eke_isSuccess;
78734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap->get_emsk = eap_eke_get_emsk;
78834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
78934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	ret = eap_server_method_register(eap);
79034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	if (ret)
79134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		eap_server_method_free(eap);
79234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	return ret;
79334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}
794