18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer state machines (RFC 4137)
3fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This file implements the Peer State Machine as defined in RFC 4137. The used
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * states and state transitions match mostly with the RFC. However, there are
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * couple of additional transitions for working around small issues noticed
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * during testing. These exceptions are explained in comments within the
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * functions in this file. The method functions, m.func(), are similar to the
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ones used in RFC 4137, but some small changes have used here to optimize
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * operations and to add functionality needed for fast re-authentication
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (session resumption).
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pcsc_funcs.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "state_machine.h"
2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "ext_password.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h"
266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "crypto/sha256.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_ctrl.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_wsc_common.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_config.h"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DATA struct eap_sm
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DEBUG_PREFIX "EAP"
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_MAX_AUTH_ROUNDS 50
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_CLIENT_TIMEOUT_DEFAULT 60
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  EapType method);
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id);
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_processIdentity(struct eap_sm *sm,
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const struct wpabuf *req);
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildNotify(int id);
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req);
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sm_method_state_txt(EapMethodState state);
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sm_decision_txt(EapDecision decision);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   Boolean value)
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var)
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol_cb->get_int(sm->eapol_ctx, var);
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var,
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  unsigned int value)
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb->set_int(sm->eapol_ctx, var, value);
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eapol_get_eapReqData(struct eap_sm *sm)
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol_cb->get_eapReqData(sm->eapol_ctx);
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void eap_notify_status(struct eap_sm *sm, const char *status,
8704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      const char *parameter)
8804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
8904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Status notification: %s (param=%s)",
9004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   status, parameter);
9104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (sm->eapol_cb->notify_status)
9204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		sm->eapol_cb->notify_status(sm->eapol_ctx, status, parameter);
9304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
9404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
9504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
96c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidtstatic void eap_sm_free_key(struct eap_sm *sm)
97c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt{
98c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (sm->eapKeyData) {
99c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		bin_clear_free(sm->eapKeyData, sm->eapKeyDataLen);
100c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		sm->eapKeyData = NULL;
101c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	}
102c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt}
103c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt
104c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ext_password_free(sm->ext_pw_buf);
10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	sm->ext_pw_buf = NULL;
10961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m == NULL || sm->eap_method_priv == NULL)
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method "
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->m->deinit(sm, sm->eap_method_priv);
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_method_priv = NULL;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->m = NULL;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_allowed_method - Check whether EAP method is allowed
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @method: EAP type
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 = allowed EAP method, 0 = not allowed
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method_type *m;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL || config->eap_methods == NULL)
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = config->eap_methods;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; m[i].vendor != EAP_VENDOR_IETF ||
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     m[i].method != EAP_TYPE_NONE; i++) {
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (m[i].vendor == vendor && m[i].method == method)
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state initializes state machine variables when the machine is
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * activated (portEnabled = TRUE). This is also used when re-starting
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication (eapRestart == TRUE).
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, INITIALIZE)
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, INITIALIZE);
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->fast_reauth && sm->m && sm->m->has_reauth_data &&
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->has_reauth_data(sm, sm->eap_method_priv) &&
1577f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt	    !sm->prev_failure &&
1587f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt	    sm->last_config == eap_get_config(sm)) {
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for "
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "fast reauthentication");
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->m->deinit_for_reauth(sm, sm->eap_method_priv);
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1637f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt		sm->last_config = eap_get_config(sm);
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_deinit_prev_method(sm, "INITIALIZE");
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->selectedMethod = EAP_TYPE_NONE;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->methodState = METHOD_NONE;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->allowNotifications = TRUE;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->decision = DECISION_FAIL;
1701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapFail, FALSE);
174c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	eap_sm_free_key(sm);
175f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	os_free(sm->eapSessionId);
176f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	sm->eapSessionId = NULL;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapKeyAvailable = FALSE;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->lastId = -1; /* new session - make sure this does not match with
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  * the first EAP-Packet */
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not reset eapResp and eapNoResp here. However, this
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * seemed to be able to trigger cases where both were set and if EAPOL
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * state machine uses eapNoResp first, it may end up not sending a real
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * reply correctly. This occurred when the workaround in FAIL state set
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * something else(?)
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapResp, FALSE);
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->num_rounds = 0;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->prev_failure = 0;
193344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	sm->expected_failure = 0;
1946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->reauthInit = FALSE;
1956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->erp_seq = (u32) -1;
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state is reached whenever service from the lower layer is interrupted
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * occurs when the port becomes enabled.
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, DISABLED)
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, DISABLED);
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->num_rounds = 0;
20861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/*
20961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * RFC 4137 does not describe clearing of idleWhile here, but doing so
21061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * allows the timer tick to be stopped more quickly when EAP is not in
21161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * use.
21261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 */
21361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	eapol_set_int(sm, EAPOL_idleWhile, 0);
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The state machine spends most of its time here, waiting for something to
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * happen. This state is entered unconditionally from INITIALIZE, DISCARD, and
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SEND_RESPONSE states.
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, IDLE)
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, IDLE);
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state is entered when an EAP packet is received (eapReq == TRUE) to
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parse the packet header.
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, RECEIVED)
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct wpabuf *eapReqData;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, RECEIVED);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapReqData = eapol_get_eapReqData(sm);
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_parseEapReq(sm, eapReqData);
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->num_rounds++;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state is entered when a request for a new type comes in. Either the
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * correct method is started, or a Nak response is built.
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, GET_METHOD)
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int reinit;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EapType method;
25204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	const struct eap_method *eap_method;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, GET_METHOD);
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->reqMethod == EAP_TYPE_EXPANDED)
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		method = sm->reqVendorMethod;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		method = sm->reqMethod;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	eap_method = eap_peer_get_eap_method(sm->reqVendor, method);
26204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->reqVendor, method);
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"vendor=%u method=%u -> NAK",
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->reqVendor, method);
26904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eap_notify_status(sm, "refuse proposed method",
27004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  eap_method ?  eap_method->name : "unknown");
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto nak;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"vendor=%u method=%u", sm->reqVendor, method);
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	eap_notify_status(sm, "accept proposed method",
27804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  eap_method ?  eap_method->name : "unknown");
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not define specific operation for fast
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * re-authentication (session resumption). The design here is to allow
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * the previously used method data to be maintained for
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * re-authentication if the method support session resumption.
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Otherwise, the previously used method data is freed and a new method
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * is allocated here.
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->fast_reauth &&
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m && sm->m->vendor == sm->reqVendor &&
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->method == method &&
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->has_reauth_data &&
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Using previous method data"
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " for fast re-authentication");
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reinit = 1;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_deinit_prev_method(sm, "GET_METHOD");
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reinit = 0;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->selectedMethod = sm->reqMethod;
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m == NULL)
30204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		sm->m = eap_method;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->m) {
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "vendor %d method %d",
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->reqVendor, method);
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto nak;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "vendor %u method %u (%s)",
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sm->reqVendor, method, sm->m->name);
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (reinit)
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_method_priv = sm->m->init_for_reauth(
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm, sm->eap_method_priv);
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_method_priv = sm->m->init(sm);
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_method_priv == NULL) {
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct eap_peer_config *config = eap_get_config(sm);
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->msg_ctx, MSG_INFO,
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"EAP: Failed to initialize EAP method: vendor %u "
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"method %u (%s)",
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->reqVendor, method, sm->m->name);
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->m = NULL;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->methodState = METHOD_NONE;
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->selectedMethod = EAP_TYPE_NONE;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->reqMethod == EAP_TYPE_TLS && config &&
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (config->pending_req_pin ||
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     config->pending_req_passphrase)) {
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Return without generating Nak in order to allow
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * entering of PIN code or passphrase to retry the
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * current EAP packet.
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase "
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "request - skip Nak");
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto nak;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->methodState = METHOD_INIT;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"EAP vendor %u method %u (%s) selected",
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->reqVendor, method, sm->m->name);
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnak:
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = eap_sm_buildNak(sm, sm->reqId);
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_ERP
3606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
3616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic char * eap_home_realm(struct eap_sm *sm)
3626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
3636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
3646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	char *realm;
3656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	size_t i, realm_len;
3666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
3676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!config)
3686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return NULL;
3696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
3706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (config->identity) {
3716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		for (i = 0; i < config->identity_len; i++) {
3726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			if (config->identity[i] == '@')
3736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				break;
3746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		}
3756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (i < config->identity_len) {
3766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			realm_len = config->identity_len - i - 1;
3776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			realm = os_malloc(realm_len + 1);
3786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			if (realm == NULL)
3796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				return NULL;
3806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			os_memcpy(realm, &config->identity[i + 1], realm_len);
3816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			realm[realm_len] = '\0';
3826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return realm;
3836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		}
3846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
3856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
3866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (config->anonymous_identity) {
3876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		for (i = 0; i < config->anonymous_identity_len; i++) {
3886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			if (config->anonymous_identity[i] == '@')
3896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				break;
3906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		}
3916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (i < config->anonymous_identity_len) {
3926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			realm_len = config->anonymous_identity_len - i - 1;
3936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			realm = os_malloc(realm_len + 1);
3946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			if (realm == NULL)
3956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				return NULL;
3966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			os_memcpy(realm, &config->anonymous_identity[i + 1],
3976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				  realm_len);
3986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			realm[realm_len] = '\0';
3996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return realm;
4006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		}
4016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
4026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return os_strdup("");
4046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
4056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic struct eap_erp_key *
4086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidteap_erp_get_key(struct eap_sm *sm, const char *realm)
4096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
4106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct eap_erp_key *erp;
4116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_for_each(erp, &sm->erp_keys, struct eap_erp_key, list) {
4136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		char *pos;
4146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		pos = os_strchr(erp->keyname_nai, '@');
4166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (!pos)
4176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			continue;
4186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		pos++;
4196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_strcmp(pos, realm) == 0)
4206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return erp;
4216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
4226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return NULL;
4246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
4256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic struct eap_erp_key *
4286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidteap_erp_get_key_nai(struct eap_sm *sm, const char *nai)
4296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
4306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct eap_erp_key *erp;
4316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_for_each(erp, &sm->erp_keys, struct eap_erp_key, list) {
4336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_strcmp(erp->keyname_nai, nai) == 0)
4346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return erp;
4356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
4366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return NULL;
4386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
4396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void eap_peer_erp_free_key(struct eap_erp_key *erp)
4426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
4436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_del(&erp->list);
4446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	bin_clear_free(erp, sizeof(*erp));
4456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
4466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void eap_erp_remove_keys_realm(struct eap_sm *sm, const char *realm)
4496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
4506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct eap_erp_key *erp;
4516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	while ((erp = eap_erp_get_key(sm, realm)) != NULL) {
4536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Delete old ERP key %s",
4546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   erp->keyname_nai);
4556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eap_peer_erp_free_key(erp);
4566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
4576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
4586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_ERP */
4606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid eap_peer_erp_free_keys(struct eap_sm *sm)
4636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
4646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_ERP
4656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct eap_erp_key *erp, *tmp;
4666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_for_each_safe(erp, tmp, &sm->erp_keys, struct eap_erp_key, list)
4686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eap_peer_erp_free_key(erp);
4696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_ERP */
4706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
4716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void eap_peer_erp_init(struct eap_sm *sm)
4746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
4756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_ERP
4766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u8 *emsk = NULL;
4776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	size_t emsk_len = 0;
4786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u8 EMSKname[EAP_EMSK_NAME_LEN];
4796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u8 len[2];
4806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	char *realm;
4816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	size_t realm_len, nai_buf_len;
4826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct eap_erp_key *erp = NULL;
4836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int pos;
4846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	realm = eap_home_realm(sm);
4866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!realm)
4876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
4886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	realm_len = os_strlen(realm);
4896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Realm for ERP keyName-NAI: %s", realm);
4906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eap_erp_remove_keys_realm(sm, realm);
4916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
4926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	nai_buf_len = 2 * EAP_EMSK_NAME_LEN + 1 + realm_len;
4936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (nai_buf_len > 253) {
4946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/*
4956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * keyName-NAI has a maximum length of 253 octet to fit in
4966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * RADIUS attributes.
4976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 */
4986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
4996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: Too long realm for ERP keyName-NAI maximum length");
5006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		goto fail;
5016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
5026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	nai_buf_len++; /* null termination */
5036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	erp = os_zalloc(sizeof(*erp) + nai_buf_len);
5046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (erp == NULL)
5056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		goto fail;
5066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len);
5086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!emsk || emsk_len == 0 || emsk_len > ERP_MAX_KEY_LEN) {
5096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
5106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: No suitable EMSK available for ERP");
5116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		goto fail;
5126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
5136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "EAP: EMSK", emsk, emsk_len);
5156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	WPA_PUT_BE16(len, 8);
5176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (hmac_sha256_kdf(sm->eapSessionId, sm->eapSessionIdLen, "EMSK",
5186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    len, sizeof(len),
5196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    EMSKname, EAP_EMSK_NAME_LEN) < 0) {
5206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Could not derive EMSKname");
5216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		goto fail;
5226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
5236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP: EMSKname", EMSKname, EAP_EMSK_NAME_LEN);
5246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	pos = wpa_snprintf_hex(erp->keyname_nai, nai_buf_len,
5266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			       EMSKname, EAP_EMSK_NAME_LEN);
5276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	erp->keyname_nai[pos] = '@';
5286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(&erp->keyname_nai[pos + 1], realm, realm_len);
5296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	WPA_PUT_BE16(len, emsk_len);
5316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (hmac_sha256_kdf(emsk, emsk_len,
5326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    "EAP Re-authentication Root Key@ietf.org",
5336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    len, sizeof(len), erp->rRK, emsk_len) < 0) {
5346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Could not derive rRK for ERP");
5356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		goto fail;
5366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
5376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	erp->rRK_len = emsk_len;
5386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rRK", erp->rRK, erp->rRK_len);
5396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (hmac_sha256_kdf(erp->rRK, erp->rRK_len,
5416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    "EAP Re-authentication Integrity Key@ietf.org",
5426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    len, sizeof(len), erp->rIK, erp->rRK_len) < 0) {
5436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Could not derive rIK for ERP");
5446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		goto fail;
5456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
5466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	erp->rIK_len = erp->rRK_len;
5476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rIK", erp->rIK, erp->rIK_len);
5486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Stored ERP keys %s", erp->keyname_nai);
5506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_add(&sm->erp_keys, &erp->list);
5516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	erp = NULL;
5526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail:
5536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	bin_clear_free(emsk, emsk_len);
5546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	bin_clear_free(erp, sizeof(*erp));
5556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_free(realm);
5566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_ERP */
5576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
5586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_ERP
5616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int eap_peer_erp_reauth_start(struct eap_sm *sm,
5626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				     const struct eap_hdr *hdr, size_t len)
5636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
5646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	char *realm;
5656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct eap_erp_key *erp;
5666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct wpabuf *msg;
5676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u8 hash[SHA256_MAC_LEN];
5686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	realm = eap_home_realm(sm);
5706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!realm)
5716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1;
5726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	erp = eap_erp_get_key(sm, realm);
5746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_free(realm);
5756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	realm = NULL;
5766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!erp)
5776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1;
5786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (erp->next_seq >= 65536)
5806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1; /* SEQ has range of 0..65535 */
5816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/* TODO: check rRK lifetime expiration */
5836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Valid ERP key found %s (SEQ=%u)",
5856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		   erp->keyname_nai, erp->next_seq);
5866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_ERP_TYPE_REAUTH,
5886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    1 + 2 + 2 + os_strlen(erp->keyname_nai) + 1 + 16,
5896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    EAP_CODE_INITIATE, hdr->identifier);
5906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (msg == NULL)
5916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1;
5926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpabuf_put_u8(msg, 0x20); /* Flags: R=0 B=0 L=1 */
5946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpabuf_put_be16(msg, erp->next_seq);
5956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpabuf_put_u8(msg, EAP_ERP_TLV_KEYNAME_NAI);
5976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpabuf_put_u8(msg, os_strlen(erp->keyname_nai));
5986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpabuf_put_str(msg, erp->keyname_nai);
5996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpabuf_put_u8(msg, EAP_ERP_CS_HMAC_SHA256_128); /* Cryptosuite */
6016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (hmac_sha256(erp->rIK, erp->rIK_len,
6036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			wpabuf_head(msg), wpabuf_len(msg), hash) < 0) {
6046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpabuf_free(msg);
6056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1;
6066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
6076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpabuf_put_data(msg, hash, 16);
6086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Sending EAP-Initiate/Re-auth");
6106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->erp_seq = erp->next_seq;
6116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	erp->next_seq++;
6126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpabuf_free(sm->eapRespData);
6136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->eapRespData = msg;
6146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->reauthInit = TRUE;
6156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return 0;
6166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
6176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_ERP */
6186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The method processing happens here. The request from the authenticator is
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * processed, and an appropriate response packet is built.
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, METHOD)
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *eapReqData;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method_ret ret;
628d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	int min_len = 1;
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, METHOD);
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m == NULL) {
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected");
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapReqData = eapol_get_eapReqData(sm);
637d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (sm->m->vendor == EAP_VENDOR_IETF && sm->m->method == EAP_TYPE_LEAP)
638d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		min_len = 0; /* LEAP uses EAP-Success without payload */
639d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (!eap_hdr_len_valid(eapReqData, min_len))
64061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Get ignore, methodState, decision, allowNotifications, and
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * eapRespData. RFC 4137 uses three separate method procedure (check,
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * process, and buildResp) in this state. These have been combined into
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * a single function call to m->process() in order to optimize EAP
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * method implementation interface a bit. These procedures are only
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * used from within this METHOD state, so there is no need to keep
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * these as separate C functions.
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * The RFC 4137 procedures return values as follows:
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * ignore = m.check(eapReqData)
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (methodState, decision, allowNotifications) = m.process(eapReqData)
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * eapRespData = m.buildResp(reqId)
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&ret, 0, sizeof(ret));
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret.ignore = sm->ignore;
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret.methodState = sm->methodState;
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret.decision = sm->decision;
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret.allowNotifications = sm->allowNotifications;
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret,
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 eapReqData);
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s "
666fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		   "methodState=%s decision=%s eapRespData=%p",
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   ret.ignore ? "TRUE" : "FALSE",
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   eap_sm_method_state_txt(ret.methodState),
669fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		   eap_sm_decision_txt(ret.decision),
670fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		   sm->eapRespData);
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ignore = ret.ignore;
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ignore)
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->methodState = ret.methodState;
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->decision = ret.decision;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->allowNotifications = ret.allowNotifications;
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m->isKeyAvailable && sm->m->getKey &&
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
6816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		struct eap_peer_config *config = eap_get_config(sm);
6826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
683c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		eap_sm_free_key(sm);
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &sm->eapKeyDataLen);
686f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		os_free(sm->eapSessionId);
6874b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		sm->eapSessionId = NULL;
6884b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		if (sm->m->getSessionId) {
6894b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt			sm->eapSessionId = sm->m->getSessionId(
6904b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt				sm, sm->eap_method_priv,
6914b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt				&sm->eapSessionIdLen);
692f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "EAP: Session-Id",
693f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt				    sm->eapSessionId, sm->eapSessionIdLen);
694f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		}
6956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (config->erp && sm->m->get_emsk && sm->eapSessionId)
6966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			eap_peer_erp_init(sm);
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state signals the lower layer that a response packet is ready to be
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sent.
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, SEND_RESPONSE)
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, SEND_RESPONSE);
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->lastRespData);
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eapRespData) {
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->workaround)
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(sm->last_md5, sm->req_md5, 16);
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->lastId = sm->reqId;
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->lastRespData = wpabuf_dup(sm->eapRespData);
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_set_bool(sm, EAPOL_eapResp, TRUE);
715fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	} else {
716fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: No eapRespData available");
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->lastRespData = NULL;
718fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
7216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->reauthInit = FALSE;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state signals the lower layer that the request was discarded, and no
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * response packet will be sent at this time.
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, DISCARD)
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, DISCARD);
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Handles requests for Identity method and builds a response.
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, IDENTITY)
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct wpabuf *eapReqData;
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, IDENTITY);
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapReqData = eapol_get_eapReqData(sm);
74661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!eap_hdr_len_valid(eapReqData, 1))
74761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_processIdentity(sm, eapReqData);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, 0);
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Handles requests for Notification method and builds a response.
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, NOTIFICATION)
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct wpabuf *eapReqData;
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, NOTIFICATION);
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapReqData = eapol_get_eapReqData(sm);
76461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!eap_hdr_len_valid(eapReqData, 1))
76561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_processNotify(sm, eapReqData);
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = eap_sm_buildNotify(sm->reqId);
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state retransmits the previous response packet.
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, RETRANSMIT)
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, RETRANSMIT);
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->lastRespData)
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapRespData = wpabuf_dup(sm->lastRespData);
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapRespData = NULL;
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state is entered in case of a successful completion of authentication
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and state machine waits here until port is disabled or EAP authentication is
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * restarted.
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, SUCCESS)
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, SUCCESS);
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eapKeyData != NULL)
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapKeyAvailable = TRUE;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not clear eapReq here, but this seems to be required
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to avoid processing the same request twice when state machine is
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * initialized.
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not set eapNoResp here, but this seems to be required
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to get EAPOL Supplicant backend state machine into SUCCESS state. In
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * addition, either eapResp or eapNoResp is required to be set after
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * processing the received EAP frame.
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"EAP authentication completed successfully");
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state is entered in case of a failure and state machine waits here
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * until port is disabled or EAP authentication is restarted.
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, FAILURE)
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, FAILURE);
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapFail, TRUE);
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not clear eapReq here, but this seems to be required
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to avoid processing the same request twice when state machine is
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * initialized.
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not set eapNoResp here. However, either eapResp or
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * eapNoResp is required to be set after processing the received EAP
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * frame.
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"EAP authentication failed");
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->prev_failure = 1;
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId)
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * At least Microsoft IAS and Meetinghouse Aegis seem to be sending
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EAP-Success/Failure with lastId + 1 even though RFC 3748 and
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 require that reqId == lastId. In addition, it looks like
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success.
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Accept this kind of Id if EAP workarounds are enabled. These are
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * unauthenticated plaintext messages, so this should have minimal
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * security implications (bit easier to fake EAP-Success/Failure).
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->workaround && (reqId == ((lastId + 1) & 0xff) ||
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       reqId == ((lastId + 2) & 0xff))) {
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected "
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "identifier field in EAP Success: "
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "reqId=%d lastId=%d (these are supposed to be "
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "same)", reqId, lastId);
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d "
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "lastId=%d", reqId, lastId);
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peer_sm_step_idle(struct eap_sm *sm)
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * The first three transitions are from RFC 4137. The last two are
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * local additions to handle special cases with LEAP and PEAP server
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * not sending EAP-Success in some cases.
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_get_bool(sm, EAPOL_eapReq))
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, RECEIVED);
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if ((eapol_get_bool(sm, EAPOL_altAccept) &&
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sm->decision != DECISION_FAIL) ||
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sm->decision == DECISION_UNCOND_SUCC))
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SUCCESS);
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (eapol_get_bool(sm, EAPOL_altReject) ||
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sm->decision != DECISION_UNCOND_SUCC) ||
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (eapol_get_bool(sm, EAPOL_altAccept) &&
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sm->methodState != METHOD_CONT &&
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sm->decision == DECISION_FAIL))
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, FAILURE);
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->selectedMethod == EAP_TYPE_LEAP &&
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->leap_done && sm->decision != DECISION_FAIL &&
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->methodState == METHOD_DONE)
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SUCCESS);
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->selectedMethod == EAP_TYPE_PEAP &&
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->peap_done && sm->decision != DECISION_FAIL &&
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->methodState == METHOD_DONE)
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SUCCESS);
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peer_req_is_duplicate(struct eap_sm *sm)
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int duplicate;
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->workaround && duplicate &&
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) {
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * RFC 4137 uses (reqId == lastId) as the only verification for
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * duplicate EAP requests. However, this misses cases where the
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * AS is incorrectly using the same id again; and
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * unfortunately, such implementations exist. Use MD5 hash as
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * an extra verification for the packets being duplicate to
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * workaround these issues.
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again, but "
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "EAP packets were not identical");
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: workaround - assume this is not a "
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "duplicate packet");
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		duplicate = 0;
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return duplicate;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
937216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidtstatic int eap_peer_sm_allow_canned(struct eap_sm *sm)
938216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt{
939216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
940216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
941216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	return config && config->phase1 &&
942216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		os_strstr(config->phase1, "allow_canned_success=1");
943216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt}
944216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
945216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peer_sm_step_received(struct eap_sm *sm)
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int duplicate = eap_peer_req_is_duplicate(sm);
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Two special cases below for LEAP are local additions to work around
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * odd LEAP behavior (EAP-Success in the middle of authentication and
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * then swapped roles). Other transitions are based on RFC 4137.
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->rxSuccess && sm->decision != DECISION_FAIL &&
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->reqId == sm->lastId ||
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     eap_success_workaround(sm, sm->reqId, sm->lastId)))
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SUCCESS);
959216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	else if (sm->workaround && sm->lastId == -1 && sm->rxSuccess &&
960216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 !sm->rxFailure && !sm->rxReq && eap_peer_sm_allow_canned(sm))
961216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		SM_ENTER(EAP, SUCCESS); /* EAP-Success prior any EAP method */
962216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	else if (sm->workaround && sm->lastId == -1 && sm->rxFailure &&
963216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 !sm->rxReq && sm->methodState != METHOD_CONT &&
964216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 eap_peer_sm_allow_canned(sm))
965216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		SM_ENTER(EAP, FAILURE); /* EAP-Failure prior any EAP method */
966216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	else if (sm->workaround && sm->rxSuccess && !sm->rxFailure &&
967216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 !sm->rxReq && sm->methodState != METHOD_CONT &&
968216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		 eap_peer_sm_allow_canned(sm))
969216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		SM_ENTER(EAP, SUCCESS); /* EAP-Success after Identity */
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->methodState != METHOD_CONT &&
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 ((sm->rxFailure &&
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sm->decision != DECISION_UNCOND_SUCC) ||
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  (sm->rxSuccess && sm->decision == DECISION_FAIL &&
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (sm->selectedMethod != EAP_TYPE_LEAP ||
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->methodState != METHOD_MAY_CONT))) &&
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (sm->reqId == sm->lastId ||
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  eap_success_workaround(sm, sm->reqId, sm->lastId)))
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, FAILURE);
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->rxReq && duplicate)
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, RETRANSMIT);
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->rxReq && !duplicate &&
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->reqMethod == EAP_TYPE_NOTIFICATION &&
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->allowNotifications)
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, NOTIFICATION);
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->rxReq && !duplicate &&
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->selectedMethod == EAP_TYPE_NONE &&
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->reqMethod == EAP_TYPE_IDENTITY)
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDENTITY);
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->rxReq && !duplicate &&
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->selectedMethod == EAP_TYPE_NONE &&
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->reqMethod != EAP_TYPE_IDENTITY &&
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->reqMethod != EAP_TYPE_NOTIFICATION)
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, GET_METHOD);
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->rxReq && !duplicate &&
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->reqMethod == sm->selectedMethod &&
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->methodState != METHOD_DONE)
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, METHOD);
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->selectedMethod == EAP_TYPE_LEAP &&
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (sm->rxSuccess || sm->rxResp))
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, METHOD);
10016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	else if (sm->reauthInit)
10026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		SM_ENTER(EAP, SEND_RESPONSE);
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, DISCARD);
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peer_sm_step_local(struct eap_sm *sm)
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sm->EAP_state) {
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_INITIALIZE:
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDLE);
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISABLED:
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eapol_get_bool(sm, EAPOL_portEnabled) &&
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    !sm->force_disabled)
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, INITIALIZE);
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_IDLE:
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_peer_sm_step_idle(sm);
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RECEIVED:
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_peer_sm_step_received(sm);
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_GET_METHOD:
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->selectedMethod == sm->reqMethod)
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, METHOD);
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, SEND_RESPONSE);
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_METHOD:
1032fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		/*
1033fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		 * Note: RFC 4137 uses methodState == DONE && decision == FAIL
1034fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		 * as the condition. eapRespData == NULL here is used to allow
1035fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		 * final EAP method response to be sent without having to change
1036fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		 * all methods to either use methodState MAY_CONT or leaving
1037fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		 * decision to something else than FAIL in cases where the only
1038fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		 * expected response is EAP-Failure.
1039fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		 */
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->ignore)
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, DISCARD);
1042fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		else if (sm->methodState == METHOD_DONE &&
1043fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			 sm->decision == DECISION_FAIL && !sm->eapRespData)
1044fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			SM_ENTER(EAP, FAILURE);
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, SEND_RESPONSE);
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SEND_RESPONSE:
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDLE);
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISCARD:
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDLE);
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_IDENTITY:
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SEND_RESPONSE);
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_NOTIFICATION:
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SEND_RESPONSE);
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RETRANSMIT:
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SEND_RESPONSE);
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SUCCESS:
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_FAILURE:
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(EAP)
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Global transitions */
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_get_bool(sm, EAPOL_eapRestart) &&
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    eapol_get_bool(sm, EAPOL_portEnabled))
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(EAP, INITIALIZE);
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(EAP, DISABLED);
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* RFC 4137 does not place any limit on number of EAP messages
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * in an authentication session. However, some error cases have
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * ended up in a state were EAP messages were sent between the
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer and server in a loop (e.g., TLS ACK frame in both
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * direction). Since this is quite undesired outcome, limit the
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * total number of EAP round-trips and abort authentication if
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * this limit is exceeded.
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"authentication rounds - abort",
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				EAP_MAX_AUTH_ROUNDS);
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->num_rounds++;
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER_GLOBAL(EAP, FAILURE);
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Local transitions */
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_peer_sm_step_local(sm);
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  EapType method)
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!eap_allowed_method(sm, vendor, method)) {
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "vendor %u method %u", vendor, method);
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return FALSE;
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_peer_get_eap_method(vendor, method))
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TRUE;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: not included in build: "
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "vendor %u method %u", vendor, method);
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return FALSE;
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_build_expanded_nak(
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sm *sm, int id, const struct eap_method *methods,
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count)
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0;
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_method *m;
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak");
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* RFC 3748 - 5.3.2: Expanded Nak */
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED,
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     8 + 8 * (count + 1), EAP_CODE_RESPONSE, id);
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be24(resp, EAP_VENDOR_IETF);
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be32(resp, EAP_TYPE_NAK);
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = methods; m; m = m->next) {
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->reqVendor == m->vendor &&
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->reqVendorMethod == m->method)
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue; /* do not allow the current method again */
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_allowed_method(sm, m->vendor, m->method)) {
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: allowed type: "
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "vendor=%u method=%u",
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   m->vendor, m->method);
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_be24(resp, m->vendor);
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_be32(resp, m->method);
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found++;
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: no more allowed methods");
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be24(resp, EAP_VENDOR_IETF);
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be32(resp, EAP_TYPE_NONE);
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_update_len(resp);
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id)
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *start;
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0, expanded_found = 0;
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count;
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_method *methods, *m;
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u "
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "vendor=%u method=%u not allowed)", sm->reqMethod,
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sm->reqVendor, sm->reqVendorMethod);
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	methods = eap_peer_get_methods(&count);
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (methods == NULL)
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->reqMethod == EAP_TYPE_EXPANDED)
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return eap_sm_build_expanded_nak(sm, id, methods, count);
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* RFC 3748 - 5.3.1: Legacy Nak */
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK,
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     sizeof(struct eap_hdr) + 1 + count + 1,
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     EAP_CODE_RESPONSE, id);
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = wpabuf_put(resp, 0);
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = methods; m; m = m->next) {
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod)
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue; /* do not allow the current method again */
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_allowed_method(sm, m->vendor, m->method)) {
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (m->vendor != EAP_VENDOR_IETF) {
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (expanded_found)
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					continue;
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				expanded_found = 1;
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_put_u8(resp, m->method);
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found++;
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found)
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, EAP_TYPE_NONE);
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP: allowed methods", start, found);
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_update_len(resp);
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req)
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
121661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const u8 *pos;
121761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t msg_len;
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"EAP authentication started");
1221a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	eap_notify_status(sm, "started", "");
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
122361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req,
122461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       &msg_len);
122561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (pos == NULL)
122661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
122761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 3748 - 5.1: Identity
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Data field may contain a displayable message in UTF-8. If this
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * includes NUL-character, only the data before that should be
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * displayed. Some EAP implementasitons may piggy-back additional
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * options after the NUL.
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: could save displayable message so that it can be shown to the
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * user in case of interaction is required */
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",
123861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			  pos, msg_len);
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PCSC_FUNCS
1243c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1244c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt/*
1245c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Rules for figuring out MNC length based on IMSI for SIM cards that do not
1246c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * include MNC length field.
1247c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */
1248c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int mnc_len_from_imsi(const char *imsi)
1249c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
1250c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	char mcc_str[4];
1251c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	unsigned int mcc;
1252c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1253c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memcpy(mcc_str, imsi, 3);
1254c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	mcc_str[3] = '\0';
1255c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	mcc = atoi(mcc_str);
1256c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1257391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (mcc == 228)
1258391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		return 2; /* Networks in Switzerland use 2-digit MNC */
1259c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (mcc == 244)
1260c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return 2; /* Networks in Finland use 2-digit MNC */
1261c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1262c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return -1;
1263c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
1264c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1265c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1266c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
1267c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				    size_t max_len, size_t *imsi_len)
1268c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
1269c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int mnc_len;
1270c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	char *pos, mnc[4];
1271c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1272c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (*imsi_len + 36 > max_len) {
1273c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
1274c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
1275c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
1276c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1277c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	/* MNC (2 or 3 digits) */
1278c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	mnc_len = scard_get_mnc_len(sm->scard_ctx);
1279c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (mnc_len < 0)
1280c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc_len = mnc_len_from_imsi(imsi);
1281c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (mnc_len < 0) {
1282c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
1283c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			   "assuming 3");
1284c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc_len = 3;
1285c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
1286c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1287c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (mnc_len == 2) {
1288c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[0] = '0';
1289c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[1] = imsi[3];
1290c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[2] = imsi[4];
1291c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	} else if (mnc_len == 3) {
1292c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[0] = imsi[3];
1293c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[1] = imsi[4];
1294c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[2] = imsi[5];
1295c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
1296c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	mnc[3] = '\0';
1297c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1298c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	pos = imsi + *imsi_len;
1299c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	pos += os_snprintf(pos, imsi + max_len - pos,
1300c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			   "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
1301c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			   mnc, imsi[0], imsi[1], imsi[2]);
1302c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	*imsi_len = pos - imsi;
1303c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1304c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return 0;
1305c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
1306c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1307c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_imsi_identity(struct eap_sm *sm,
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct eap_peer_config *conf)
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
131104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	enum { EAP_SM_SIM, EAP_SM_AKA, EAP_SM_AKA_PRIME } method = EAP_SM_SIM;
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char imsi[100];
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t imsi_len;
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method_type *m = conf->eap_methods;
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	imsi_len = sizeof(imsi);
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM");
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1325c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (imsi_len < 7) {
1326c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_printf(MSG_WARNING, "Too short IMSI for SIM identity");
1327c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
1328c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
1329c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1330c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len) < 0) {
1331c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_printf(MSG_WARNING, "Could not add realm to SIM identity");
1332c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
1333c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
1334c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "IMSI + realm", (u8 *) imsi, imsi_len);
1335c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF ||
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  m[i].method != EAP_TYPE_NONE); i++) {
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (m[i].vendor == EAP_VENDOR_IETF &&
133904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    m[i].method == EAP_TYPE_AKA_PRIME) {
134004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			method = EAP_SM_AKA_PRIME;
134104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			break;
134204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
134304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
134404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (m[i].vendor == EAP_VENDOR_IETF &&
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    m[i].method == EAP_TYPE_AKA) {
134604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			method = EAP_SM_AKA;
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conf->identity);
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conf->identity = os_malloc(1 + imsi_len);
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->identity == NULL) {
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "Failed to allocate buffer for "
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "IMSI-based identity");
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
135904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	switch (method) {
136004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SM_SIM:
136104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		conf->identity[0] = '1';
136204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
136304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SM_AKA:
136404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		conf->identity[0] = '0';
136504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
136604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SM_AKA_PRIME:
136704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		conf->identity[0] = '6';
136804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
136904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conf->identity + 1, imsi, imsi_len);
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conf->identity_len = 1 + imsi_len;
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1375c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PCSC_FUNCS */
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_set_scard_pin(struct eap_sm *sm,
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct eap_peer_config *conf)
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PCSC_FUNCS
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_set_pin(sm->scard_ctx, conf->pin)) {
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Make sure the same PIN is not tried again in order to avoid
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * blocking SIM.
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conf->pin);
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf->pin = NULL;
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "PIN validation failed");
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_pin(sm);
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* PCSC_FUNCS */
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PCSC_FUNCS */
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_get_scard_identity(struct eap_sm *sm,
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct eap_peer_config *conf)
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PCSC_FUNCS
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_sm_set_scard_pin(sm, conf))
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eap_sm_imsi_identity(sm, conf);
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* PCSC_FUNCS */
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PCSC_FUNCS */
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the packet
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2)
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * failure
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function allocates and builds an EAP-Identity/Response packet for the
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * current network. The caller is responsible for freeing the returned data.
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted)
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *identity;
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t identity_len;
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL) {
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration "
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "was not available");
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m && sm->m->get_identity &&
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (identity = sm->m->get_identity(sm, sm->eap_method_priv,
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &identity_len)) != NULL) {
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth "
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "identity", identity, identity_len);
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (!encrypted && config->anonymous_identity) {
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		identity = config->anonymous_identity;
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		identity_len = config->anonymous_identity_len;
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  identity, identity_len);
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		identity = config->identity;
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		identity_len = config->identity_len;
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  identity, identity_len);
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (identity == NULL) {
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "configuration was not available");
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (config->pcsc) {
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (eap_sm_get_scard_identity(sm, config) < 0)
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			identity = config->identity;
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			identity_len = config->identity_len;
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  "IMSI", identity, identity_len);
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sm_request_identity(sm);
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (config->pcsc) {
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sm_set_scard_pin(sm, config) < 0)
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len,
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     EAP_CODE_RESPONSE, id);
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(resp, identity, identity_len);
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req)
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *msg;
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, msg_len;
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, req,
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &msg_len);
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL)
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  pos, msg_len);
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = os_malloc(msg_len + 1);
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL)
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < msg_len; i++)
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg[i] = isprint(pos[i]) ? (char) pos[i] : '_';
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg[msg_len] = '\0';
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_EVENT_EAP_NOTIFICATION, msg);
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(msg);
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildNotify(int id)
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0,
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     EAP_CODE_RESPONSE, id);
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void eap_peer_initiate(struct eap_sm *sm, const struct eap_hdr *hdr,
15266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			      size_t len)
15276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
15286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_ERP
15296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const u8 *pos = (const u8 *) (hdr + 1);
15306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const u8 *end = ((const u8 *) hdr) + len;
15316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct erp_tlvs parse;
15326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (len < sizeof(*hdr) + 1) {
15346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Ignored too short EAP-Initiate");
15356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
15366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
15376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (*pos != EAP_ERP_TYPE_REAUTH_START) {
15396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
15406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: Ignored unexpected EAP-Initiate Type=%u",
15416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   *pos);
15426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
15436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
15446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	pos++;
15466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (pos >= end) {
15476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
15486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: Too short EAP-Initiate/Re-auth-Start");
15496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
15506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
15516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	pos++; /* Reserved */
15526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP: EAP-Initiate/Re-auth-Start TVs/TLVs",
15536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    pos, end - pos);
15546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (erp_parse_tlvs(pos, end, &parse, 0) < 0)
15566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		goto invalid;
15576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (parse.domain) {
15596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG,
15606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				  "EAP: EAP-Initiate/Re-auth-Start - Domain name",
15616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				  parse.domain, parse.domain_len);
15626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/* TODO: Derivation of domain specific keys for local ER */
15636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
15646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (eap_peer_erp_reauth_start(sm, hdr, len) == 0)
15666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
15676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtinvalid:
15696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_ERP */
15706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_printf(MSG_DEBUG,
15716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		   "EAP: EAP-Initiate/Re-auth-Start - No suitable ERP keys available - try to start full EAP authentication");
15726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eapol_set_bool(sm, EAPOL_eapTriggerStart, TRUE);
15736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
15746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void eap_peer_finish(struct eap_sm *sm, const struct eap_hdr *hdr,
15776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    size_t len)
15786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
15796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_ERP
15806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const u8 *pos = (const u8 *) (hdr + 1);
15816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const u8 *end = ((const u8 *) hdr) + len;
15826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const u8 *start;
15836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct erp_tlvs parse;
15846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u8 flags;
15856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u16 seq;
15866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u8 hash[SHA256_MAC_LEN];
15876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	size_t hash_len;
15886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct eap_erp_key *erp;
15896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int max_len;
15906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	char nai[254];
15916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u8 seed[4];
15926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int auth_tag_ok = 0;
15936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (len < sizeof(*hdr) + 1) {
15956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Ignored too short EAP-Finish");
15966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
15976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
15986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
15996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (*pos != EAP_ERP_TYPE_REAUTH) {
16006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
16016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: Ignored unexpected EAP-Finish Type=%u", *pos);
16026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
16046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (len < sizeof(*hdr) + 4) {
16066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
16076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: Ignored too short EAP-Finish/Re-auth");
16086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
16106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	pos++;
16126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	flags = *pos++;
16136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	seq = WPA_GET_BE16(pos);
16146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	pos += 2;
16156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Flags=0x%x SEQ=%u", flags, seq);
16166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (seq != sm->erp_seq) {
16186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
16196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: Unexpected EAP-Finish/Re-auth SEQ=%u", seq);
16206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
16226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/*
16246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * Parse TVs/TLVs. Since we do not yet know the length of the
16256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * Authentication Tag, stop parsing if an unknown TV/TLV is seen and
16266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * just try to find the keyName-NAI first so that we can check the
16276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * Authentication Tag.
16286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 */
16296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (erp_parse_tlvs(pos, end, &parse, 1) < 0)
16306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!parse.keyname) {
16336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
16346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: No keyName-NAI in EAP-Finish/Re-auth Packet");
16356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
16376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Finish/Re-auth - keyName-NAI",
16396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			  parse.keyname, parse.keyname_len);
16406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (parse.keyname_len > 253) {
16416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
16426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: Too long keyName-NAI in EAP-Finish/Re-auth");
16436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
16456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(nai, parse.keyname, parse.keyname_len);
16466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	nai[parse.keyname_len] = '\0';
16476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	erp = eap_erp_get_key_nai(sm, nai);
16496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!erp) {
16506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: No matching ERP key found for %s",
16516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   nai);
16526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
16546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/* Is there enough room for Cryptosuite and Authentication Tag? */
16566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	start = parse.keyname + parse.keyname_len;
16576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	max_len = end - start;
16586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	hash_len = 16;
16596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (max_len < 1 + (int) hash_len) {
16606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
16616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: Not enough room for Authentication Tag");
16626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (flags & 0x80)
16636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			goto no_auth_tag;
16646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
16666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (end[-17] != EAP_ERP_CS_HMAC_SHA256_128) {
16676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Different Cryptosuite used");
16686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (flags & 0x80)
16696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			goto no_auth_tag;
16706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
16726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (hmac_sha256(erp->rIK, erp->rIK_len, (const u8 *) hdr,
16746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			end - ((const u8 *) hdr) - hash_len, hash) < 0)
16756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_memcmp(end - hash_len, hash, hash_len) != 0) {
16776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
16786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: Authentication Tag mismatch");
16796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
16816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	auth_tag_ok = 1;
16826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	end -= 1 + hash_len;
16836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtno_auth_tag:
16856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/*
16866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * Parse TVs/TLVs again now that we know the exact part of the buffer
16876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * that contains them.
16886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 */
16896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP: EAP-Finish/Re-Auth TVs/TLVs",
16906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    pos, end - pos);
16916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (erp_parse_tlvs(pos, end, &parse, 0) < 0)
16926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
16936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
16946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (flags & 0x80 || !auth_tag_ok) {
16956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
16966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: EAP-Finish/Re-auth indicated failure");
16976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eapol_set_bool(sm, EAPOL_eapFail, TRUE);
16986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eapol_set_bool(sm, EAPOL_eapReq, FALSE);
16996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
17006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
17016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			"EAP authentication failed");
17026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		sm->prev_failure = 1;
17036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG,
17046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   "EAP: Drop ERP key to try full authentication on next attempt");
17056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eap_peer_erp_free_key(erp);
17066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
17076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
17086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
17096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eap_sm_free_key(sm);
17106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->eapKeyDataLen = 0;
17116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->eapKeyData = os_malloc(erp->rRK_len);
17126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!sm->eapKeyData)
17136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
17146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->eapKeyDataLen = erp->rRK_len;
17156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
17166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	WPA_PUT_BE16(seed, seq);
17176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	WPA_PUT_BE16(&seed[2], erp->rRK_len);
17186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (hmac_sha256_kdf(erp->rRK, erp->rRK_len,
17196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    "Re-authentication Master Session Key@ietf.org",
17206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    seed, sizeof(seed),
17216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    sm->eapKeyData, erp->rRK_len) < 0) {
17226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Could not derive rMSK for ERP");
17236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eap_sm_free_key(sm);
17246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
17256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
17266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rMSK",
17276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			sm->eapKeyData, sm->eapKeyDataLen);
17286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->eapKeyAvailable = TRUE;
17296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
17306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
17316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
17326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
17336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		"EAP re-authentication completed successfully");
17346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_ERP */
17356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
17366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
17376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_hdr *hdr;
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t plen;
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reqId = 0;
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reqMethod = EAP_TYPE_NONE;
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reqVendor = EAP_VENDOR_IETF;
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reqVendorMethod = EAP_TYPE_NONE;
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL || wpabuf_len(req) < sizeof(*hdr))
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = wpabuf_head(req);
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	plen = be_to_host16(hdr->length);
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (plen > wpabuf_len(req)) {
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(len=%lu plen=%lu)",
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) wpabuf_len(req),
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) plen);
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reqId = hdr->identifier;
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->workaround) {
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const u8 *addr[1];
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		addr[0] = wpabuf_head(req);
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		md5_vector(1, addr, &plen, sm->req_md5);
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (hdr->code) {
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_REQUEST:
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (plen < sizeof(*hdr) + 1) {
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Too short EAP-Request - "
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "no Type field");
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->rxReq = TRUE;
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (const u8 *) (hdr + 1);
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->reqMethod = *pos++;
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->reqMethod == EAP_TYPE_EXPANDED) {
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (plen < sizeof(*hdr) + 8) {
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "expanded EAP-Packet (plen=%lu)",
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (unsigned long) plen);
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->reqVendor = WPA_GET_BE24(pos);
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 3;
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->reqVendorMethod = WPA_GET_BE32(pos);
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request id=%d "
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "method=%u vendor=%u vendorMethod=%u",
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->reqId, sm->reqMethod, sm->reqVendor,
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->reqVendorMethod);
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_RESPONSE:
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->selectedMethod == EAP_TYPE_LEAP) {
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * LEAP differs from RFC 4137 by using reversed roles
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * for mutual authentication and because of this, we
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * need to accept EAP-Response frames if LEAP is used.
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (plen < sizeof(*hdr) + 1) {
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "EAP: Too short "
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "EAP-Response - no Type field");
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->rxResp = TRUE;
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos = (const u8 *) (hdr + 1);
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->reqMethod = *pos;
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for "
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "LEAP method=%d id=%d",
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   sm->reqMethod, sm->reqId);
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response");
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_SUCCESS:
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
182104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eap_notify_status(sm, "completion", "success");
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->rxSuccess = TRUE;
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_FAILURE:
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
182604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eap_notify_status(sm, "completion", "failure");
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->rxFailure = TRUE;
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case EAP_CODE_INITIATE:
18306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eap_peer_initiate(sm, hdr, plen);
18316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		break;
18326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case EAP_CODE_FINISH:
18336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		eap_peer_finish(sm, hdr, plen);
18346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		break;
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown "
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "code %d", hdr->code);
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  union tls_event_data *data)
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sm *sm = ctx;
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *hash_hex = NULL;
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (ev) {
185004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case TLS_CERT_CHAIN_SUCCESS:
185104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eap_notify_status(sm, "remote certificate verification",
185204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  "success");
185304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_CERT_CHAIN_FAILURE:
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"reason=%d depth=%d subject='%s' err='%s'",
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->cert_fail.reason,
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->cert_fail.depth,
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->cert_fail.subject,
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->cert_fail.reason_txt);
186104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eap_notify_status(sm, "remote certificate verification",
186204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  data->cert_fail.reason_txt);
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_PEER_CERTIFICATE:
1865c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		if (!sm->eapol_cb->notify_cert)
1866c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			break;
1867c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->peer_cert.hash) {
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t len = data->peer_cert.hash_len * 2 + 1;
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hash_hex = os_malloc(len);
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (hash_hex) {
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_snprintf_hex(hash_hex, len,
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 data->peer_cert.hash,
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 data->peer_cert.hash_len);
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1877c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
1878c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		sm->eapol_cb->notify_cert(sm->eapol_ctx,
1879c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					  data->peer_cert.depth,
1880c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					  data->peer_cert.subject,
18812f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt					  data->peer_cert.altsubject,
18822f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt					  data->peer_cert.num_altsubject,
1883c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					  hash_hex, data->peer_cert.cert);
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
188504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case TLS_ALERT:
188604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (data->alert.is_local)
188704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			eap_notify_status(sm, "local TLS alert",
188804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  data->alert.description);
188904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		else
189004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			eap_notify_status(sm, "remote TLS alert",
189104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  data->alert.description);
189204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(hash_hex);
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_sm_init - Allocate and initialize EAP peer state machine
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol_ctx: Context data to be used with eapol_cb calls
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol_cb: Pointer to EAPOL callback functions
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg_ctx: Context data for wpa_msg() calls
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: EAP configuration
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated EAP state machine or %NULL on failure
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function allocates and initializes an EAP state machine. In addition,
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this initializes TLS library for the new EAP state machine. eapol_cb pointer
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will be in use until eap_peer_sm_deinit() is used to deinitialize this EAP
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state machine. Consequently, the caller must make sure that this data
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * structure remains alive while the EAP state machine is active.
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sm * eap_peer_sm_init(void *eapol_ctx,
19141d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt				 const struct eapol_callbacks *eapol_cb,
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 void *msg_ctx, struct eap_config *conf)
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sm *sm;
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_config tlsconf;
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm = os_zalloc(sizeof(*sm));
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_ctx = eapol_ctx;
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb = eapol_cb;
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->msg_ctx = msg_ctx;
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->wps = conf->wps;
19286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_init(&sm->erp_keys);
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&tlsconf, 0, sizeof(tlsconf));
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.opensc_engine_path = conf->opensc_engine_path;
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
19346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	tlsconf.openssl_ciphers = conf->openssl_ciphers;
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_FIPS
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.fips_mode = 1;
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_FIPS */
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.event_cb = eap_peer_sm_tls_event;
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.cb_ctx = sm;
19401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tlsconf.cert_in_cb = conf->cert_in_cb;
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ssl_ctx = tls_init(&tlsconf);
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ssl_ctx == NULL) {
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "context.");
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sm);
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
194904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	sm->ssl_ctx2 = tls_init(&tlsconf);
195004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (sm->ssl_ctx2 == NULL) {
195104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_INFO, "SSL: Failed to initialize TLS "
195204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "context (2).");
195304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Run without separate TLS context within TLS tunnel */
195404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
195504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm;
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_sm_deinit - Deinitialize and free an EAP peer state machine
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function deinitializes EAP state machine and frees all allocated
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * resources.
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_peer_sm_deinit(struct eap_sm *sm)
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_deinit_prev_method(sm, "EAP deinit");
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_abort(sm);
197304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (sm->ssl_ctx2)
197404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		tls_deinit(sm->ssl_ctx2);
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_deinit(sm->ssl_ctx);
19766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	eap_peer_erp_free_keys(sm);
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm);
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_sm_step - Step EAP peer state machine
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if EAP state was changed or 0 if not
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function advances EAP state machine to a new state to match with the
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * current variables. This should be called whenever variables used by the EAP
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state machine have changed.
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_sm_step(struct eap_sm *sm)
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res = 0;
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	do {
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->changed = FALSE;
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_STEP_RUN(EAP);
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->changed)
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = 1;
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} while (sm->changed);
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_abort - Abort EAP authentication
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Release system resources that have been allocated for the authentication
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * session without fully deinitializing the EAP state machine.
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_abort(struct eap_sm *sm)
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->lastRespData);
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->lastRespData = NULL;
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
2016c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	eap_sm_free_key(sm);
2017f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	os_free(sm->eapSessionId);
2018f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	sm->eapSessionId = NULL;
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* This is not clearly specified in the EAP statemachines draft, but
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * it seems necessary to make sure that some of the EAPOL variables get
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * cleared for the next authentication. */
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sm_state_txt(int state)
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_INITIALIZE:
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INITIALIZE";
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISABLED:
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "DISABLED";
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_IDLE:
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "IDLE";
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RECEIVED:
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "RECEIVED";
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_GET_METHOD:
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "GET_METHOD";
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_METHOD:
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "METHOD";
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SEND_RESPONSE:
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SEND_RESPONSE";
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISCARD:
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "DISCARD";
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_IDENTITY:
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "IDENTITY";
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_NOTIFICATION:
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "NOTIFICATION";
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RETRANSMIT:
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "RETRANSMIT";
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SUCCESS:
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SUCCESS";
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_FAILURE:
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "FAILURE";
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "UNKNOWN";
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sm_method_state_txt(EapMethodState state)
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case METHOD_NONE:
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "NONE";
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case METHOD_INIT:
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INIT";
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case METHOD_CONT:
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONT";
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case METHOD_MAY_CONT:
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "MAY_CONT";
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case METHOD_DONE:
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "DONE";
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "UNKNOWN";
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sm_decision_txt(EapDecision decision)
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (decision) {
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case DECISION_FAIL:
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "FAIL";
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case DECISION_COND_SUCC:
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "COND_SUCC";
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case DECISION_UNCOND_SUCC:
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "UNCOND_SUCC";
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "UNKNOWN";
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_get_status - Get EAP state machine status
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf.
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Query EAP state machine for status information. This function fills in a
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * text area with current status information from the EAPOL state machine. If
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the buffer (buf) is not large enough, status information will be truncated
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to fit the buffer.
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len, ret;
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_snprintf(buf, buflen,
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "EAP state=%s\n",
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  eap_sm_state_txt(sm->EAP_state));
21256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(buflen, len))
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->selectedMethod != EAP_TYPE_NONE) {
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *name;
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->m) {
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			name = sm->m->name;
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const struct eap_method *m =
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				eap_peer_get_eap_method(EAP_VENDOR_IETF,
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							sm->selectedMethod);
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (m)
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				name = m->name;
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				name = "?";
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(buf + len, buflen - len,
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "selectedMethod=%d (EAP-%s)\n",
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sm->selectedMethod, name);
21446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(buflen - len, ret))
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return len;
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->m && sm->m->get_status) {
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len += sm->m->get_status(sm, sm->eap_method_priv,
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 buf + len, buflen - len,
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 verbose);
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (verbose) {
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(buf + len, buflen - len,
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "reqMethod=%d\n"
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "methodState=%s\n"
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "decision=%s\n"
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ClientTimeout=%d\n",
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sm->reqMethod,
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  eap_sm_method_state_txt(sm->methodState),
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  eap_sm_decision_txt(sm->decision),
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sm->ClientTimeout);
21656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (os_snprintf_error(buflen - len, ret))
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return len;
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return len;
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
21761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   const char *msg, size_t msglen)
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config;
2180051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	const char *txt = NULL;
2181051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	char *tmp;
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config = eap_get_config(sm);
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (field) {
21901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_IDENTITY:
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->pending_req_identity++;
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
21931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PASSWORD:
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->pending_req_password++;
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
21961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->pending_req_new_password++;
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
21991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PIN:
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->pending_req_pin++;
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
22021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_OTP:
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg) {
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp = os_malloc(msglen + 3);
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (tmp == NULL)
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp[0] = '[';
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(tmp + 1, msg, msglen);
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp[msglen + 1] = ']';
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp[msglen + 2] = '\0';
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			txt = tmp;
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(config->pending_req_otp);
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			config->pending_req_otp = tmp;
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			config->pending_req_otp_len = msglen + 3;
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (config->pending_req_otp == NULL)
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			txt = config->pending_req_otp;
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
22211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PASSPHRASE:
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->pending_req_passphrase++;
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2224051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	case WPA_CTRL_REQ_SIM:
2225051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		txt = msg;
2226051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		break;
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eapol_cb->eap_param_needed)
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt);
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define eap_sm_request(sm, type, msg, msglen) do { } while (0)
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * eap_sm_get_method_name(struct eap_sm *sm)
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m == NULL)
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "UNKNOWN";
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->m->name;
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_identity - Request identity from user (ctrl_iface)
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request identity information for the
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * current network. This is normally called when the identity is not included
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in the network configuration. The request will be sent to monitor programs
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * through the control interface.
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_identity(struct eap_sm *sm)
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_IDENTITY, NULL, 0);
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_password - Request password from user (ctrl_iface)
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request password information for the
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * current network. This is normally called when the password is not included
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in the network configuration. The request will be sent to monitor programs
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * through the control interface.
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_password(struct eap_sm *sm)
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSWORD, NULL, 0);
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_new_password - Request new password from user (ctrl_iface)
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request new password information for
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the current network. This is normally called when the EAP method indicates
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that the current password has expired and password change is required. The
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * request will be sent to monitor programs through the control interface.
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_new_password(struct eap_sm *sm)
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_NEW_PASSWORD, NULL, 0);
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface)
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request SIM or smart card PIN
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * information for the current network. This is normally called when the PIN is
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not included in the network configuration. The request will be sent to
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * monitor programs through the control interface.
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_pin(struct eap_sm *sm)
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_PIN, NULL, 0);
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_otp - Request one time password from user (ctrl_iface)
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: Message to be displayed to the user when asking for OTP
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg_len: Length of the user displayable message
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request open time password (OTP) for
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the current network. The request will be sent to monitor programs through
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the control interface.
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_OTP, msg, msg_len);
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface)
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request passphrase for a private key
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for the current network. This is normally called when the passphrase is not
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * included in the network configuration. The request will be sent to monitor
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * programs through the control interface.
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_passphrase(struct eap_sm *sm)
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSPHRASE, NULL, 0);
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2338051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * eap_sm_request_sim - Request external SIM processing
2339051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2340051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * @req: EAP method specific request
2341051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt */
2342051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtvoid eap_sm_request_sim(struct eap_sm *sm, const char *req)
2343051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
2344051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_SIM, req, os_strlen(req));
2345051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
2346051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
2347051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
2348051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt/**
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_notify_ctrl_attached - Notification of attached monitor
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify EAP state machines that a monitor was attached to the control
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * interface to trigger re-sending of pending requests for user input.
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_notify_ctrl_attached(struct eap_sm *sm)
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Re-send any pending requests for user data since a new control
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * interface was added. This handles cases where the EAP authentication
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * starts immediately after system startup when the user interface is
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * not yet running. */
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_identity)
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_identity(sm);
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_password)
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_password(sm);
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_new_password)
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_new_password(sm);
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_otp)
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_otp(sm, NULL, 0);
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_pin)
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_pin(sm);
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_passphrase)
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_passphrase(sm);
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_allowed_phase2_type(int vendor, int type)
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor != EAP_VENDOR_IETF)
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type != EAP_TYPE_FAST;
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @name: EAP method name, e.g., MD5
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @vendor: Buffer for returning EAP Vendor-Id
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: EAP method type or %EAP_TYPE_NONE if not found
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function maps EAP type names into EAP type numbers that are allowed for
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-PEAP, EAP-TTLS, and EAP-FAST.
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu32 eap_get_phase2_type(const char *name, int *vendor)
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int v;
2403af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt	u32 type = eap_peer_get_type(name, &v);
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_allowed_phase2_type(v, type)) {
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*vendor = v;
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return type;
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*vendor = EAP_VENDOR_IETF;
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EAP_TYPE_NONE;
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_phase2_types - Get list of allowed EAP phase 2 types
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to a network configuration
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @count: Pointer to a variable to be filled with number of returned EAP types
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to allocated type list or %NULL on failure
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function generates an array of allowed EAP phase 2 (tunneled) types for
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the given network configuration.
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config,
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      size_t *count)
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method_type *buf;
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 method;
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int vendor;
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t mcount;
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_method *methods, *m;
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	methods = eap_peer_get_methods(&mcount);
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (methods == NULL)
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*count = 0;
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(mcount * sizeof(struct eap_method_type));
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = methods; m; m = m->next) {
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		vendor = m->vendor;
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		method = m->method;
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_allowed_phase2_type(vendor, method)) {
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (vendor == EAP_VENDOR_IETF &&
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    method == EAP_TYPE_TLS && config &&
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    config->private_key2 == NULL)
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			buf[*count].vendor = vendor;
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			buf[*count].method = method;
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(*count)++;
24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_set_fast_reauth - Update fast_reauth setting
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @enabled: 1 = Fast reauthentication is enabled, 0 = Disabled
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_set_fast_reauth(struct eap_sm *sm, int enabled)
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->fast_reauth = enabled;
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_set_workaround - Update EAP workarounds setting
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @workaround: 1 = Enable EAP workarounds, 0 = Disable EAP workarounds
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_set_workaround(struct eap_sm *sm, unsigned int workaround)
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->workaround = workaround;
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config - Get current network configuration
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the current network configuration or %NULL if not found
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer methods should avoid using this function if they can use other
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * access functions, like eap_get_config_identity() and
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_password(), that do not require direct access to
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct eap_peer_config.
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_peer_config * eap_get_config(struct eap_sm *sm)
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol_cb->get_config(sm->eapol_ctx);
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_identity - Get identity from the network configuration
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for the length of the identity
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the identity or %NULL if not found
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = config->identity_len;
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->identity;
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
251161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int eap_get_ext_password(struct eap_sm *sm,
251261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				struct eap_peer_config *config)
251361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
251461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char *name;
251561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
251661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (config->password == NULL)
251761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
251861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
251961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	name = os_zalloc(config->password_len + 1);
252061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (name == NULL)
252161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
252261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_memcpy(name, config->password, config->password_len);
252361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
252461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ext_password_free(sm->ext_pw_buf);
252561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	sm->ext_pw_buf = ext_password_get(sm->ext_pw, name);
252661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(name);
252761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
252861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return sm->ext_pw_buf == NULL ? -1 : 0;
252961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
253061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
253161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_password - Get password from the network configuration
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for the length of the password
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the password or %NULL if not found
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
254361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
254461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
254561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (eap_get_ext_password(sm, config) < 0)
254661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return NULL;
254761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		*len = wpabuf_len(sm->ext_pw_buf);
254861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return wpabuf_head(sm->ext_pw_buf);
254961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
255061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = config->password_len;
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->password;
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_password2 - Get password from the network configuration
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for the length of the password
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hash: Buffer for returning whether the password is stored as a
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NtPasswordHash instead of plaintext password; can be %NULL if this
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * information is not needed
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the password or %NULL if not found
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
257061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
257161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
257261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (eap_get_ext_password(sm, config) < 0)
257361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return NULL;
2574344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt		if (hash)
2575344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt			*hash = 0;
257661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		*len = wpabuf_len(sm->ext_pw_buf);
257761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return wpabuf_head(sm->ext_pw_buf);
257861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
257961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = config->password_len;
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hash)
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH);
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->password;
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_new_password - Get new password from network configuration
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for the length of the new password
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the new password or %NULL if not found
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = config->new_password_len;
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->new_password;
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_otp - Get one-time password from the network configuration
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for the length of the one-time password
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the one-time password or %NULL if not found
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len)
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = config->otp_len;
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->otp;
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_clear_config_otp - Clear used one-time password
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function clears a used one-time password (OTP) from the current network
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration. This should be called when the OTP has been used and is not
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * needed anymore.
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_clear_config_otp(struct eap_sm *sm)
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(config->otp, 0, config->otp_len);
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->otp);
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->otp = NULL;
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->otp_len = 0;
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_phase1 - Get phase1 data from the network configuration
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the phase1 data or %NULL if not found
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * eap_get_config_phase1(struct eap_sm *sm)
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->phase1;
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_phase2 - Get phase2 data from the network configuration
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the phase1 data or %NULL if not found
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * eap_get_config_phase2(struct eap_sm *sm)
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->phase2;
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_get_config_fragment_size(struct eap_sm *sm)
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->fragment_size;
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_key_available - Get key availability (eapKeyAvailable variable)
26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if EAP keying material is available, 0 if not
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_key_available(struct eap_sm *sm)
26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm ? sm->eapKeyAvailable : 0;
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_notify_success - Notify EAP state machine about external success trigger
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called when external event, e.g., successful completion of
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA-PSK key handshake, is indicating that EAP state machine should move to
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * success state. This is mainly used with security modes that do not use EAP
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state machine (e.g., WPA-PSK).
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_notify_success(struct eap_sm *sm)
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm) {
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->decision = DECISION_COND_SUCC;
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->EAP_state = EAP_SUCCESS;
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_notify_lower_layer_success - Notification of lower layer success
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify EAP state machines that a lower layer has detected a successful
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication. This is used to recover from dropped EAP-Success messages.
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_notify_lower_layer_success(struct eap_sm *sm)
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_get_bool(sm, EAPOL_eapSuccess) ||
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->decision == DECISION_FAIL ||
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->methodState != METHOD_MAY_CONT &&
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     sm->methodState != METHOD_DONE))
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eapKeyData != NULL)
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapKeyAvailable = TRUE;
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"EAP authentication completed successfully (based on lower "
27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"layer success)");
27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2733f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * eap_get_eapSessionId - Get Session-Id from EAP state machine
2734f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2735f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * @len: Pointer to variable that will be set to number of bytes in the session
2736f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * Returns: Pointer to the EAP Session-Id or %NULL on failure
2737f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt *
2738f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * Fetch EAP Session-Id from the EAP state machine. The Session-Id is available
2739f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * only after a successful authentication. EAP state machine continues to manage
2740f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * the Session-Id and the caller must not change or free the returned data.
2741f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt */
2742f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtconst u8 * eap_get_eapSessionId(struct eap_sm *sm, size_t *len)
2743f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{
2744f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (sm == NULL || sm->eapSessionId == NULL) {
2745f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		*len = 0;
2746f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return NULL;
2747f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
2748f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
2749f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	*len = sm->eapSessionIdLen;
2750f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	return sm->eapSessionId;
2751f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt}
2752f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
2753f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
2754f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt/**
27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Pointer to variable that will be set to number of bytes in the key
27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the EAP keying data or %NULL on failure
27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The
27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * key is available only after a successful authentication. EAP state machine
27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * continues to manage the key data and the caller must not change or free the
27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * returned data.
27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL || sm->eapKeyData == NULL) {
27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = 0;
27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = sm->eapKeyDataLen;
27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapKeyData;
27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_eapKeyData - Get EAP response data
27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure
27818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
27828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Fetch EAP response (eapRespData) from the EAP state machine. This data is
27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available when EAP state machine has processed an incoming EAP request. The
27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP state machine does not maintain a reference to the response after this
27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function is called and the caller is responsible for freeing the data.
27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
27878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_get_eapRespData(struct eap_sm *sm)
27888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
27908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL || sm->eapRespData == NULL)
27928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
27938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = sm->eapRespData;
27958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
27968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_register_scard_ctx - Notification of smart card context
28038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
28048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context data for smart card operations
28058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
28068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify EAP state machines of context data for smart card operations. This
28078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * context data will be used as a parameter for scard_*() functions.
28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
28098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_register_scard_ctx(struct eap_sm *sm, void *ctx)
28108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->scard_ctx = ctx;
28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_set_config_blob - Set or add a named configuration blob
28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @blob: New value for the blob
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Adds a new configuration blob or replaces the current value of an existing
28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * blob.
28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob);
28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_blob - Get a named configuration blob
28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @name: Name of the blob
28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to blob data or %NULL if not found
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   const char *name)
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name);
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NO_CONFIG_BLOBS */
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_set_force_disabled - Set force_disabled flag
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @disabled: 1 = EAP disabled, 0 = EAP enabled
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to force EAP state machine to be disabled when it is
28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not in use (e.g., with WPA-PSK or plaintext connections).
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_set_force_disabled(struct eap_sm *sm, int disabled)
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->force_disabled = disabled;
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2863051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt/**
2864051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * eap_set_external_sim - Set external_sim flag
2865051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2866051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * @external_sim: Whether external SIM/USIM processing is used
2867051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt */
2868051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtvoid eap_set_external_sim(struct eap_sm *sm, int external_sim)
2869051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
2870051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	sm->external_sim = external_sim;
2871051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
2872051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
2873051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /**
28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_notify_pending - Notify that EAP method is ready to re-process a request
28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * An EAP method can perform a pending operation (e.g., to get a response from
28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * an external process). Once the response is available, this function can be
28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used to request EAPOL state machine to retry delivering the previously
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * received (and still unanswered) EAP request to EAP state machine.
28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_notify_pending(struct eap_sm *sm)
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb->notify_pending(sm->eapol_ctx);
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_invalidate_cached_session - Mark cached session data invalid
28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_invalidate_cached_session(struct eap_sm *sm)
28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_deinit_prev_method(sm, "invalidate");
28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_is_wps_pbc_enrollee(struct eap_peer_config *conf)
29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->identity_len != WSC_ID_ENROLLEE_LEN ||
29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN))
29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Not a WPS Enrollee */
29058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->phase1 == NULL || os_strstr(conf->phase1, "pbc=1") == NULL)
29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Not using PBC */
29088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_is_wps_pin_enrollee(struct eap_peer_config *conf)
29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->identity_len != WSC_ID_ENROLLEE_LEN ||
29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN))
29178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Not a WPS Enrollee */
29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->phase1 == NULL || os_strstr(conf->phase1, "pin=") == NULL)
29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Not using PIN */
29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
292461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
292561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
292661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext)
292761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
292861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ext_password_free(sm->ext_pw_buf);
292961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	sm->ext_pw_buf = NULL;
293061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	sm->ext_pw = ext;
293161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
29324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
29334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
29344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt/**
29354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * eap_set_anon_id - Set or add anonymous identity
29364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
29374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @id: Anonymous identity (e.g., EAP-SIM pseudonym) or %NULL to clear
29384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @len: Length of anonymous identity in octets
29394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */
29404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtvoid eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len)
29414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
29424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sm->eapol_cb->set_anon_id)
29434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sm->eapol_cb->set_anon_id(sm->eapol_ctx, id, len);
29444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2945344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt
2946344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt
2947344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidtint eap_peer_was_failure_expected(struct eap_sm *sm)
2948344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt{
2949344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	return sm->expected_failure;
2950344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt}
2951