eapol_supp_sm.c revision 344abd362cfe2d03ed956666527352826b67bde5
19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * EAPOL supplicant state machines
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * This software may be distributed under the terms of the BSD license.
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * See README for more details.
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "includes.h"
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "common.h"
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "state_machine.h"
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "wpabuf.h"
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "eloop.h"
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "crypto/crypto.h"
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "crypto/md5.h"
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "common/eapol_common.h"
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "eap_peer/eap.h"
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "eap_peer/eap_proxy.h"
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "eapol_supp_sm.h"
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define STATE_MACHINE_DATA struct eapol_sm
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/**
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * struct eapol_sm - Internal data for EAPOL state machines
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct eapol_sm {
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Timers */
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int authWhile;
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int heldWhile;
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int startWhen;
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int idleWhile; /* for EAP state machine */
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int timer_tick_enabled;
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Global variables */
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean eapFail;
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean eapolEap;
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean eapSuccess;
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean initialize;
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean keyDone;
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean keyRun;
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	PortControl portControl;
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean portEnabled;
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	PortStatus suppPortStatus;  /* dot1xSuppControlledPortStatus */
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean portValid;
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean suppAbort;
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean suppFail;
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean suppStart;
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean suppSuccess;
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean suppTimeout;
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Supplicant PAE state machine */
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	enum {
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_PAE_UNKNOWN = 0,
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_PAE_DISCONNECTED = 1,
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_PAE_LOGOFF = 2,
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_PAE_CONNECTING = 3,
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_PAE_AUTHENTICATING = 4,
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_PAE_AUTHENTICATED = 5,
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* unused(6) */
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_PAE_HELD = 7,
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_PAE_RESTART = 8,
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_PAE_S_FORCE_AUTH = 9,
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_PAE_S_FORCE_UNAUTH = 10
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} SUPP_PAE_state; /* dot1xSuppPaeState */
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Variables */
719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean userLogoff;
729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean logoffSent;
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int startCount;
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean eapRestart;
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	PortControl sPortMode;
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Constants */
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int heldPeriod; /* dot1xSuppHeldPeriod */
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int startPeriod; /* dot1xSuppStartPeriod */
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int maxStart; /* dot1xSuppMaxStart */
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Key Receive state machine */
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	enum {
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		KEY_RX_UNKNOWN = 0,
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} KEY_RX_state;
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Variables */
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean rxKey;
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Supplicant Backend state machine */
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	enum {
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_BE_UNKNOWN = 0,
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_BE_INITIALIZE = 1,
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_BE_IDLE = 2,
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_BE_REQUEST = 3,
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_BE_RECEIVE = 4,
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_BE_RESPONSE = 5,
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_BE_FAIL = 6,
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_BE_TIMEOUT = 7,
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SUPP_BE_SUCCESS = 8
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} SUPP_BE_state; /* dot1xSuppBackendPaeState */
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Variables */
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean eapNoResp;
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean eapReq;
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean eapResp;
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Constants */
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int authPeriod; /* dot1xSuppAuthPeriod */
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Statistics */
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int dot1xSuppEapolFramesRx;
1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int dot1xSuppEapolFramesTx;
1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int dot1xSuppEapolStartFramesTx;
1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int dot1xSuppEapolLogoffFramesTx;
1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int dot1xSuppEapolRespFramesTx;
1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int dot1xSuppEapolReqIdFramesRx;
1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int dot1xSuppEapolReqFramesRx;
1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int dot1xSuppInvalidEapolFramesRx;
1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int dot1xSuppEapLengthErrorFramesRx;
1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int dot1xSuppLastEapolFrameVersion;
1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned char dot1xSuppLastEapolFrameSource[6];
1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean changed;
1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct eap_sm *eap;
1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct eap_peer_config *config;
1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean initial_req;
1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	u8 *last_rx_key;
1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	size_t last_rx_key_len;
1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct wpabuf *eapReqData; /* for EAP */
1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean altAccept; /* for EAP */
1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean altReject; /* for EAP */
1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean replay_counter_valid;
1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	u8 last_replay_counter[16];
1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct eapol_config conf;
1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct eapol_ctx *ctx;
1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		cb_status;
1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean cached_pmk;
1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean unicast_key_received, broadcast_key_received;
1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean force_authorized_update;
1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef CONFIG_EAP_PROXY
1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Boolean use_eap_proxy;
1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct eap_proxy_sm *eap_proxy;
1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* CONFIG_EAP_PROXY */
147};
148
149
150static void eapol_sm_txLogoff(struct eapol_sm *sm);
151static void eapol_sm_txStart(struct eapol_sm *sm);
152static void eapol_sm_processKey(struct eapol_sm *sm);
153static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
154static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
155static void eapol_sm_abortSupp(struct eapol_sm *sm);
156static void eapol_sm_abort_cached(struct eapol_sm *sm);
157static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
158static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
159static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
160
161
162/* Port Timers state machine - implemented as a function that will be called
163 * once a second as a registered event loop timeout */
164static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
165{
166	struct eapol_sm *sm = timeout_ctx;
167
168	if (sm->authWhile > 0) {
169		sm->authWhile--;
170		if (sm->authWhile == 0)
171			wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
172	}
173	if (sm->heldWhile > 0) {
174		sm->heldWhile--;
175		if (sm->heldWhile == 0)
176			wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
177	}
178	if (sm->startWhen > 0) {
179		sm->startWhen--;
180		if (sm->startWhen == 0)
181			wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
182	}
183	if (sm->idleWhile > 0) {
184		sm->idleWhile--;
185		if (sm->idleWhile == 0)
186			wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
187	}
188
189	if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
190		eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,
191				       sm);
192	} else {
193		wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
194		sm->timer_tick_enabled = 0;
195	}
196	eapol_sm_step(sm);
197}
198
199
200static void eapol_enable_timer_tick(struct eapol_sm *sm)
201{
202	if (sm->timer_tick_enabled)
203		return;
204	wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
205	sm->timer_tick_enabled = 1;
206	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
207	eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
208}
209
210
211SM_STATE(SUPP_PAE, LOGOFF)
212{
213	SM_ENTRY(SUPP_PAE, LOGOFF);
214	eapol_sm_txLogoff(sm);
215	sm->logoffSent = TRUE;
216	eapol_sm_set_port_unauthorized(sm);
217}
218
219
220SM_STATE(SUPP_PAE, DISCONNECTED)
221{
222	SM_ENTRY(SUPP_PAE, DISCONNECTED);
223	sm->sPortMode = Auto;
224	sm->startCount = 0;
225	sm->logoffSent = FALSE;
226	eapol_sm_set_port_unauthorized(sm);
227	sm->suppAbort = TRUE;
228
229	sm->unicast_key_received = FALSE;
230	sm->broadcast_key_received = FALSE;
231
232	/*
233	 * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so
234	 * allows the timer tick to be stopped more quickly when the port is
235	 * not enabled. Since this variable is used only within HELD state,
236	 * clearing it on initialization does not change actual state machine
237	 * behavior.
238	 */
239	sm->heldWhile = 0;
240}
241
242
243SM_STATE(SUPP_PAE, CONNECTING)
244{
245	int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING;
246	SM_ENTRY(SUPP_PAE, CONNECTING);
247	if (send_start) {
248		sm->startWhen = sm->startPeriod;
249		sm->startCount++;
250	} else {
251		/*
252		 * Do not send EAPOL-Start immediately since in most cases,
253		 * Authenticator is going to start authentication immediately
254		 * after association and an extra EAPOL-Start is just going to
255		 * delay authentication. Use a short timeout to send the first
256		 * EAPOL-Start if Authenticator does not start authentication.
257		 */
258#ifdef CONFIG_WPS
259		/* Reduce latency on starting WPS negotiation. */
260		sm->startWhen = 1;
261#else /* CONFIG_WPS */
262		sm->startWhen = 3;
263#endif /* CONFIG_WPS */
264	}
265	eapol_enable_timer_tick(sm);
266	sm->eapolEap = FALSE;
267	if (send_start)
268		eapol_sm_txStart(sm);
269}
270
271
272SM_STATE(SUPP_PAE, AUTHENTICATING)
273{
274	SM_ENTRY(SUPP_PAE, AUTHENTICATING);
275	sm->startCount = 0;
276	sm->suppSuccess = FALSE;
277	sm->suppFail = FALSE;
278	sm->suppTimeout = FALSE;
279	sm->keyRun = FALSE;
280	sm->keyDone = FALSE;
281	sm->suppStart = TRUE;
282}
283
284
285SM_STATE(SUPP_PAE, HELD)
286{
287	SM_ENTRY(SUPP_PAE, HELD);
288	sm->heldWhile = sm->heldPeriod;
289	eapol_enable_timer_tick(sm);
290	eapol_sm_set_port_unauthorized(sm);
291	sm->cb_status = EAPOL_CB_FAILURE;
292}
293
294
295SM_STATE(SUPP_PAE, AUTHENTICATED)
296{
297	SM_ENTRY(SUPP_PAE, AUTHENTICATED);
298	eapol_sm_set_port_authorized(sm);
299	sm->cb_status = EAPOL_CB_SUCCESS;
300}
301
302
303SM_STATE(SUPP_PAE, RESTART)
304{
305	SM_ENTRY(SUPP_PAE, RESTART);
306	sm->eapRestart = TRUE;
307}
308
309
310SM_STATE(SUPP_PAE, S_FORCE_AUTH)
311{
312	SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
313	eapol_sm_set_port_authorized(sm);
314	sm->sPortMode = ForceAuthorized;
315}
316
317
318SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
319{
320	SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
321	eapol_sm_set_port_unauthorized(sm);
322	sm->sPortMode = ForceUnauthorized;
323	eapol_sm_txLogoff(sm);
324}
325
326
327SM_STEP(SUPP_PAE)
328{
329	if ((sm->userLogoff && !sm->logoffSent) &&
330	    !(sm->initialize || !sm->portEnabled))
331		SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
332	else if (((sm->portControl == Auto) &&
333		  (sm->sPortMode != sm->portControl)) ||
334		 sm->initialize || !sm->portEnabled)
335		SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
336	else if ((sm->portControl == ForceAuthorized) &&
337		 (sm->sPortMode != sm->portControl) &&
338		 !(sm->initialize || !sm->portEnabled))
339		SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
340	else if ((sm->portControl == ForceUnauthorized) &&
341		 (sm->sPortMode != sm->portControl) &&
342		 !(sm->initialize || !sm->portEnabled))
343		SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
344	else switch (sm->SUPP_PAE_state) {
345	case SUPP_PAE_UNKNOWN:
346		break;
347	case SUPP_PAE_LOGOFF:
348		if (!sm->userLogoff)
349			SM_ENTER(SUPP_PAE, DISCONNECTED);
350		break;
351	case SUPP_PAE_DISCONNECTED:
352		SM_ENTER(SUPP_PAE, CONNECTING);
353		break;
354	case SUPP_PAE_CONNECTING:
355		if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
356			SM_ENTER(SUPP_PAE, CONNECTING);
357		else if (sm->startWhen == 0 &&
358			 sm->startCount >= sm->maxStart &&
359			 sm->portValid)
360			SM_ENTER(SUPP_PAE, AUTHENTICATED);
361		else if (sm->eapSuccess || sm->eapFail)
362			SM_ENTER(SUPP_PAE, AUTHENTICATING);
363		else if (sm->eapolEap)
364			SM_ENTER(SUPP_PAE, RESTART);
365		else if (sm->startWhen == 0 &&
366			 sm->startCount >= sm->maxStart &&
367			 !sm->portValid)
368			SM_ENTER(SUPP_PAE, HELD);
369		break;
370	case SUPP_PAE_AUTHENTICATING:
371		if (sm->eapSuccess && !sm->portValid &&
372		    sm->conf.accept_802_1x_keys &&
373		    sm->conf.required_keys == 0) {
374			wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
375				   "plaintext connection; no EAPOL-Key frames "
376				   "required");
377			sm->portValid = TRUE;
378			if (sm->ctx->eapol_done_cb)
379				sm->ctx->eapol_done_cb(sm->ctx->ctx);
380		}
381		if (sm->eapSuccess && sm->portValid)
382			SM_ENTER(SUPP_PAE, AUTHENTICATED);
383		else if (sm->eapFail || (sm->keyDone && !sm->portValid))
384			SM_ENTER(SUPP_PAE, HELD);
385		else if (sm->suppTimeout)
386			SM_ENTER(SUPP_PAE, CONNECTING);
387		break;
388	case SUPP_PAE_HELD:
389		if (sm->heldWhile == 0)
390			SM_ENTER(SUPP_PAE, CONNECTING);
391		else if (sm->eapolEap)
392			SM_ENTER(SUPP_PAE, RESTART);
393		break;
394	case SUPP_PAE_AUTHENTICATED:
395		if (sm->eapolEap && sm->portValid)
396			SM_ENTER(SUPP_PAE, RESTART);
397		else if (!sm->portValid)
398			SM_ENTER(SUPP_PAE, DISCONNECTED);
399		break;
400	case SUPP_PAE_RESTART:
401		if (!sm->eapRestart)
402			SM_ENTER(SUPP_PAE, AUTHENTICATING);
403		break;
404	case SUPP_PAE_S_FORCE_AUTH:
405		break;
406	case SUPP_PAE_S_FORCE_UNAUTH:
407		break;
408	}
409}
410
411
412SM_STATE(KEY_RX, NO_KEY_RECEIVE)
413{
414	SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
415}
416
417
418SM_STATE(KEY_RX, KEY_RECEIVE)
419{
420	SM_ENTRY(KEY_RX, KEY_RECEIVE);
421	eapol_sm_processKey(sm);
422	sm->rxKey = FALSE;
423}
424
425
426SM_STEP(KEY_RX)
427{
428	if (sm->initialize || !sm->portEnabled)
429		SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
430	switch (sm->KEY_RX_state) {
431	case KEY_RX_UNKNOWN:
432		break;
433	case KEY_RX_NO_KEY_RECEIVE:
434		if (sm->rxKey)
435			SM_ENTER(KEY_RX, KEY_RECEIVE);
436		break;
437	case KEY_RX_KEY_RECEIVE:
438		if (sm->rxKey)
439			SM_ENTER(KEY_RX, KEY_RECEIVE);
440		break;
441	}
442}
443
444
445SM_STATE(SUPP_BE, REQUEST)
446{
447	SM_ENTRY(SUPP_BE, REQUEST);
448	sm->authWhile = 0;
449	sm->eapReq = TRUE;
450	eapol_sm_getSuppRsp(sm);
451}
452
453
454SM_STATE(SUPP_BE, RESPONSE)
455{
456	SM_ENTRY(SUPP_BE, RESPONSE);
457	eapol_sm_txSuppRsp(sm);
458	sm->eapResp = FALSE;
459}
460
461
462SM_STATE(SUPP_BE, SUCCESS)
463{
464	SM_ENTRY(SUPP_BE, SUCCESS);
465	sm->keyRun = TRUE;
466	sm->suppSuccess = TRUE;
467
468#ifdef CONFIG_EAP_PROXY
469	if (sm->use_eap_proxy) {
470		if (eap_proxy_key_available(sm->eap_proxy)) {
471			/* New key received - clear IEEE 802.1X EAPOL-Key replay
472			 * counter */
473			sm->replay_counter_valid = FALSE;
474		}
475		return;
476	}
477#endif /* CONFIG_EAP_PROXY */
478
479	if (eap_key_available(sm->eap)) {
480		/* New key received - clear IEEE 802.1X EAPOL-Key replay
481		 * counter */
482		sm->replay_counter_valid = FALSE;
483	}
484}
485
486
487SM_STATE(SUPP_BE, FAIL)
488{
489	SM_ENTRY(SUPP_BE, FAIL);
490	sm->suppFail = TRUE;
491}
492
493
494SM_STATE(SUPP_BE, TIMEOUT)
495{
496	SM_ENTRY(SUPP_BE, TIMEOUT);
497	sm->suppTimeout = TRUE;
498}
499
500
501SM_STATE(SUPP_BE, IDLE)
502{
503	SM_ENTRY(SUPP_BE, IDLE);
504	sm->suppStart = FALSE;
505	sm->initial_req = TRUE;
506}
507
508
509SM_STATE(SUPP_BE, INITIALIZE)
510{
511	SM_ENTRY(SUPP_BE, INITIALIZE);
512	eapol_sm_abortSupp(sm);
513	sm->suppAbort = FALSE;
514
515	/*
516	 * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so
517	 * allows the timer tick to be stopped more quickly when the port is
518	 * not enabled. Since this variable is used only within RECEIVE state,
519	 * clearing it on initialization does not change actual state machine
520	 * behavior.
521	 */
522	sm->authWhile = 0;
523}
524
525
526SM_STATE(SUPP_BE, RECEIVE)
527{
528	SM_ENTRY(SUPP_BE, RECEIVE);
529	sm->authWhile = sm->authPeriod;
530	eapol_enable_timer_tick(sm);
531	sm->eapolEap = FALSE;
532	sm->eapNoResp = FALSE;
533	sm->initial_req = FALSE;
534}
535
536
537SM_STEP(SUPP_BE)
538{
539	if (sm->initialize || sm->suppAbort)
540		SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
541	else switch (sm->SUPP_BE_state) {
542	case SUPP_BE_UNKNOWN:
543		break;
544	case SUPP_BE_REQUEST:
545		/*
546		 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
547		 * and SUCCESS based on eapFail and eapSuccess, respectively.
548		 * However, IEEE Std 802.1X-2004 is also specifying that
549		 * eapNoResp should be set in conjunction with eapSuccess and
550		 * eapFail which would mean that more than one of the
551		 * transitions here would be activated at the same time.
552		 * Skipping RESPONSE and/or RECEIVE states in these cases can
553		 * cause problems and the direct transitions to do not seem
554		 * correct. Because of this, the conditions for these
555		 * transitions are verified only after eapNoResp. They are
556		 * unlikely to be used since eapNoResp should always be set if
557		 * either of eapSuccess or eapFail is set.
558		 */
559		if (sm->eapResp && sm->eapNoResp) {
560			wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
561				   "eapResp and eapNoResp set?!");
562		}
563		if (sm->eapResp)
564			SM_ENTER(SUPP_BE, RESPONSE);
565		else if (sm->eapNoResp)
566			SM_ENTER(SUPP_BE, RECEIVE);
567		else if (sm->eapFail)
568			SM_ENTER(SUPP_BE, FAIL);
569		else if (sm->eapSuccess)
570			SM_ENTER(SUPP_BE, SUCCESS);
571		break;
572	case SUPP_BE_RESPONSE:
573		SM_ENTER(SUPP_BE, RECEIVE);
574		break;
575	case SUPP_BE_SUCCESS:
576		SM_ENTER(SUPP_BE, IDLE);
577		break;
578	case SUPP_BE_FAIL:
579		SM_ENTER(SUPP_BE, IDLE);
580		break;
581	case SUPP_BE_TIMEOUT:
582		SM_ENTER(SUPP_BE, IDLE);
583		break;
584	case SUPP_BE_IDLE:
585		if (sm->eapFail && sm->suppStart)
586			SM_ENTER(SUPP_BE, FAIL);
587		else if (sm->eapolEap && sm->suppStart)
588			SM_ENTER(SUPP_BE, REQUEST);
589		else if (sm->eapSuccess && sm->suppStart)
590			SM_ENTER(SUPP_BE, SUCCESS);
591		break;
592	case SUPP_BE_INITIALIZE:
593		SM_ENTER(SUPP_BE, IDLE);
594		break;
595	case SUPP_BE_RECEIVE:
596		if (sm->eapolEap)
597			SM_ENTER(SUPP_BE, REQUEST);
598		else if (sm->eapFail)
599			SM_ENTER(SUPP_BE, FAIL);
600		else if (sm->authWhile == 0)
601			SM_ENTER(SUPP_BE, TIMEOUT);
602		else if (sm->eapSuccess)
603			SM_ENTER(SUPP_BE, SUCCESS);
604		break;
605	}
606}
607
608
609static void eapol_sm_txLogoff(struct eapol_sm *sm)
610{
611	wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
612	sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
613			    IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
614	sm->dot1xSuppEapolLogoffFramesTx++;
615	sm->dot1xSuppEapolFramesTx++;
616}
617
618
619static void eapol_sm_txStart(struct eapol_sm *sm)
620{
621	wpa_printf(MSG_DEBUG, "EAPOL: txStart");
622	sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
623			    IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
624	sm->dot1xSuppEapolStartFramesTx++;
625	sm->dot1xSuppEapolFramesTx++;
626}
627
628
629#define IEEE8021X_ENCR_KEY_LEN 32
630#define IEEE8021X_SIGN_KEY_LEN 32
631
632struct eap_key_data {
633	u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
634	u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
635};
636
637
638static void eapol_sm_processKey(struct eapol_sm *sm)
639{
640#ifndef CONFIG_FIPS
641	struct ieee802_1x_hdr *hdr;
642	struct ieee802_1x_eapol_key *key;
643	struct eap_key_data keydata;
644	u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
645	u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
646	int key_len, res, sign_key_len, encr_key_len;
647	u16 rx_key_length;
648	size_t plen;
649
650	wpa_printf(MSG_DEBUG, "EAPOL: processKey");
651	if (sm->last_rx_key == NULL)
652		return;
653
654	if (!sm->conf.accept_802_1x_keys) {
655		wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
656			   " even though this was not accepted - "
657			   "ignoring this packet");
658		return;
659	}
660
661	if (sm->last_rx_key_len < sizeof(*hdr) + sizeof(*key))
662		return;
663	hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
664	key = (struct ieee802_1x_eapol_key *) (hdr + 1);
665	plen = be_to_host16(hdr->length);
666	if (sizeof(*hdr) + plen > sm->last_rx_key_len || plen < sizeof(*key)) {
667		wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
668		return;
669	}
670	rx_key_length = WPA_GET_BE16(key->key_length);
671	wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
672		   "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
673		   hdr->version, hdr->type, be_to_host16(hdr->length),
674		   key->type, rx_key_length, key->key_index);
675
676	eapol_sm_notify_lower_layer_success(sm, 1);
677	sign_key_len = IEEE8021X_SIGN_KEY_LEN;
678	encr_key_len = IEEE8021X_ENCR_KEY_LEN;
679	res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
680	if (res < 0) {
681		wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
682			   "decrypting EAPOL-Key keys");
683		return;
684	}
685	if (res == 16) {
686		/* LEAP derives only 16 bytes of keying material. */
687		res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
688		if (res) {
689			wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
690				   "master key for decrypting EAPOL-Key keys");
691			return;
692		}
693		sign_key_len = 16;
694		encr_key_len = 16;
695		os_memcpy(keydata.sign_key, keydata.encr_key, 16);
696	} else if (res) {
697		wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
698			   "data for decrypting EAPOL-Key keys (res=%d)", res);
699		return;
700	}
701
702	/* The key replay_counter must increase when same master key */
703	if (sm->replay_counter_valid &&
704	    os_memcmp(sm->last_replay_counter, key->replay_counter,
705		      IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
706		wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
707			   "not increase - ignoring key");
708		wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
709			    sm->last_replay_counter,
710			    IEEE8021X_REPLAY_COUNTER_LEN);
711		wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
712			    key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
713		return;
714	}
715
716	/* Verify key signature (HMAC-MD5) */
717	os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
718	os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
719	hmac_md5(keydata.sign_key, sign_key_len,
720		 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
721		 key->key_signature);
722	if (os_memcmp(orig_key_sign, key->key_signature,
723		      IEEE8021X_KEY_SIGN_LEN) != 0) {
724		wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
725			   "EAPOL-Key packet");
726		os_memcpy(key->key_signature, orig_key_sign,
727			  IEEE8021X_KEY_SIGN_LEN);
728		return;
729	}
730	wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
731
732	key_len = plen - sizeof(*key);
733	if (key_len > 32 || rx_key_length > 32) {
734		wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
735			   key_len ? key_len : rx_key_length);
736		return;
737	}
738	if (key_len == rx_key_length) {
739		os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
740		os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
741			  encr_key_len);
742		os_memcpy(datakey, key + 1, key_len);
743		rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
744			 datakey, key_len);
745		wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
746				datakey, key_len);
747	} else if (key_len == 0) {
748		/*
749		 * IEEE 802.1X-2004 specifies that least significant Key Length
750		 * octets from MS-MPPE-Send-Key are used as the key if the key
751		 * data is not present. This seems to be meaning the beginning
752		 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
753		 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
754		 * Anyway, taking the beginning of the keying material from EAP
755		 * seems to interoperate with Authenticators.
756		 */
757		key_len = rx_key_length;
758		os_memcpy(datakey, keydata.encr_key, key_len);
759		wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
760				"material data encryption key",
761				datakey, key_len);
762	} else {
763		wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
764			   "(key_length=%d)", key_len, rx_key_length);
765		return;
766	}
767
768	sm->replay_counter_valid = TRUE;
769	os_memcpy(sm->last_replay_counter, key->replay_counter,
770		  IEEE8021X_REPLAY_COUNTER_LEN);
771
772	wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
773		   "len %d",
774		   key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
775		   "unicast" : "broadcast",
776		   key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
777
778	if (sm->ctx->set_wep_key &&
779	    sm->ctx->set_wep_key(sm->ctx->ctx,
780				 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
781				 key->key_index & IEEE8021X_KEY_INDEX_MASK,
782				 datakey, key_len) < 0) {
783		wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
784			   " driver.");
785	} else {
786		if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
787			sm->unicast_key_received = TRUE;
788		else
789			sm->broadcast_key_received = TRUE;
790
791		if ((sm->unicast_key_received ||
792		     !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
793		    (sm->broadcast_key_received ||
794		     !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
795		{
796			wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
797				   "frames received");
798			sm->portValid = TRUE;
799			if (sm->ctx->eapol_done_cb)
800				sm->ctx->eapol_done_cb(sm->ctx->ctx);
801		}
802	}
803#endif /* CONFIG_FIPS */
804}
805
806
807static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
808{
809	wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
810	/* EAP layer processing; no special code is needed, since Supplicant
811	 * Backend state machine is waiting for eapNoResp or eapResp to be set
812	 * and these are only set in the EAP state machine when the processing
813	 * has finished. */
814}
815
816
817static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
818{
819	struct wpabuf *resp;
820
821	wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
822
823#ifdef CONFIG_EAP_PROXY
824	if (sm->use_eap_proxy) {
825		/* Get EAP Response from EAP Proxy */
826		resp = eap_proxy_get_eapRespData(sm->eap_proxy);
827		if (resp == NULL) {
828			wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP Proxy "
829				   "response data not available");
830			return;
831		}
832	} else
833#endif /* CONFIG_EAP_PROXY */
834
835	resp = eap_get_eapRespData(sm->eap);
836	if (resp == NULL) {
837		wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
838			   "not available");
839		return;
840	}
841
842	/* Send EAP-Packet from the EAP layer to the Authenticator */
843	sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
844			    IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
845			    wpabuf_len(resp));
846
847	/* eapRespData is not used anymore, so free it here */
848	wpabuf_free(resp);
849
850	if (sm->initial_req)
851		sm->dot1xSuppEapolReqIdFramesRx++;
852	else
853		sm->dot1xSuppEapolReqFramesRx++;
854	sm->dot1xSuppEapolRespFramesTx++;
855	sm->dot1xSuppEapolFramesTx++;
856}
857
858
859static void eapol_sm_abortSupp(struct eapol_sm *sm)
860{
861	/* release system resources that may have been allocated for the
862	 * authentication session */
863	os_free(sm->last_rx_key);
864	sm->last_rx_key = NULL;
865	wpabuf_free(sm->eapReqData);
866	sm->eapReqData = NULL;
867	eap_sm_abort(sm->eap);
868}
869
870
871static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
872{
873	eapol_sm_step(timeout_ctx);
874}
875
876
877static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
878{
879	int cb;
880
881	cb = sm->suppPortStatus != Authorized || sm->force_authorized_update;
882	sm->force_authorized_update = FALSE;
883	sm->suppPortStatus = Authorized;
884	if (cb && sm->ctx->port_cb)
885		sm->ctx->port_cb(sm->ctx->ctx, 1);
886}
887
888
889static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
890{
891	int cb;
892
893	cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update;
894	sm->force_authorized_update = FALSE;
895	sm->suppPortStatus = Unauthorized;
896	if (cb && sm->ctx->port_cb)
897		sm->ctx->port_cb(sm->ctx->ctx, 0);
898}
899
900
901/**
902 * eapol_sm_step - EAPOL state machine step function
903 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
904 *
905 * This function is called to notify the state machine about changed external
906 * variables. It will step through the EAPOL state machines in loop to process
907 * all triggered state changes.
908 */
909void eapol_sm_step(struct eapol_sm *sm)
910{
911	int i;
912
913	/* In theory, it should be ok to run this in loop until !changed.
914	 * However, it is better to use a limit on number of iterations to
915	 * allow events (e.g., SIGTERM) to stop the program cleanly if the
916	 * state machine were to generate a busy loop. */
917	for (i = 0; i < 100; i++) {
918		sm->changed = FALSE;
919		SM_STEP_RUN(SUPP_PAE);
920		SM_STEP_RUN(KEY_RX);
921		SM_STEP_RUN(SUPP_BE);
922#ifdef CONFIG_EAP_PROXY
923		if (sm->use_eap_proxy) {
924			/* Drive the EAP proxy state machine */
925			if (eap_proxy_sm_step(sm->eap_proxy, sm->eap))
926				sm->changed = TRUE;
927		} else
928#endif /* CONFIG_EAP_PROXY */
929		if (eap_peer_sm_step(sm->eap))
930			sm->changed = TRUE;
931		if (!sm->changed)
932			break;
933	}
934
935	if (sm->changed) {
936		/* restart EAPOL state machine step from timeout call in order
937		 * to allow other events to be processed. */
938		eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
939		eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
940	}
941
942	if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
943		enum eapol_supp_result result;
944		if (sm->cb_status == EAPOL_CB_SUCCESS)
945			result = EAPOL_SUPP_RESULT_SUCCESS;
946		else if (eap_peer_was_failure_expected(sm->eap))
947			result = EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
948		else
949			result = EAPOL_SUPP_RESULT_FAILURE;
950		sm->cb_status = EAPOL_CB_IN_PROGRESS;
951		sm->ctx->cb(sm, result, sm->ctx->cb_ctx);
952	}
953}
954
955
956#ifdef CONFIG_CTRL_IFACE
957static const char *eapol_supp_pae_state(int state)
958{
959	switch (state) {
960	case SUPP_PAE_LOGOFF:
961		return "LOGOFF";
962	case SUPP_PAE_DISCONNECTED:
963		return "DISCONNECTED";
964	case SUPP_PAE_CONNECTING:
965		return "CONNECTING";
966	case SUPP_PAE_AUTHENTICATING:
967		return "AUTHENTICATING";
968	case SUPP_PAE_HELD:
969		return "HELD";
970	case SUPP_PAE_AUTHENTICATED:
971		return "AUTHENTICATED";
972	case SUPP_PAE_RESTART:
973		return "RESTART";
974	default:
975		return "UNKNOWN";
976	}
977}
978
979
980static const char *eapol_supp_be_state(int state)
981{
982	switch (state) {
983	case SUPP_BE_REQUEST:
984		return "REQUEST";
985	case SUPP_BE_RESPONSE:
986		return "RESPONSE";
987	case SUPP_BE_SUCCESS:
988		return "SUCCESS";
989	case SUPP_BE_FAIL:
990		return "FAIL";
991	case SUPP_BE_TIMEOUT:
992		return "TIMEOUT";
993	case SUPP_BE_IDLE:
994		return "IDLE";
995	case SUPP_BE_INITIALIZE:
996		return "INITIALIZE";
997	case SUPP_BE_RECEIVE:
998		return "RECEIVE";
999	default:
1000		return "UNKNOWN";
1001	}
1002}
1003
1004
1005static const char * eapol_port_status(PortStatus status)
1006{
1007	if (status == Authorized)
1008		return "Authorized";
1009	else
1010		return "Unauthorized";
1011}
1012#endif /* CONFIG_CTRL_IFACE */
1013
1014
1015#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1016static const char * eapol_port_control(PortControl ctrl)
1017{
1018	switch (ctrl) {
1019	case Auto:
1020		return "Auto";
1021	case ForceUnauthorized:
1022		return "ForceUnauthorized";
1023	case ForceAuthorized:
1024		return "ForceAuthorized";
1025	default:
1026		return "Unknown";
1027	}
1028}
1029#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1030
1031
1032/**
1033 * eapol_sm_configure - Set EAPOL variables
1034 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1035 * @heldPeriod: dot1xSuppHeldPeriod
1036 * @authPeriod: dot1xSuppAuthPeriod
1037 * @startPeriod: dot1xSuppStartPeriod
1038 * @maxStart: dot1xSuppMaxStart
1039 *
1040 * Set configurable EAPOL state machine variables. Each variable can be set to
1041 * the given value or ignored if set to -1 (to set only some of the variables).
1042 */
1043void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
1044			int startPeriod, int maxStart)
1045{
1046	if (sm == NULL)
1047		return;
1048	if (heldPeriod >= 0)
1049		sm->heldPeriod = heldPeriod;
1050	if (authPeriod >= 0)
1051		sm->authPeriod = authPeriod;
1052	if (startPeriod >= 0)
1053		sm->startPeriod = startPeriod;
1054	if (maxStart >= 0)
1055		sm->maxStart = maxStart;
1056}
1057
1058
1059/**
1060 * eapol_sm_get_method_name - Get EAPOL method name
1061 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1062 * Returns: Static string containing name of current eap method or NULL
1063 */
1064const char * eapol_sm_get_method_name(struct eapol_sm *sm)
1065{
1066	if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED ||
1067	    sm->suppPortStatus != Authorized)
1068		return NULL;
1069
1070	return eap_sm_get_method_name(sm->eap);
1071}
1072
1073
1074#ifdef CONFIG_CTRL_IFACE
1075/**
1076 * eapol_sm_get_status - Get EAPOL state machine status
1077 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1078 * @buf: Buffer for status information
1079 * @buflen: Maximum buffer length
1080 * @verbose: Whether to include verbose status information
1081 * Returns: Number of bytes written to buf.
1082 *
1083 * Query EAPOL state machine for status information. This function fills in a
1084 * text area with current status information from the EAPOL state machine. If
1085 * the buffer (buf) is not large enough, status information will be truncated
1086 * to fit the buffer.
1087 */
1088int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
1089			int verbose)
1090{
1091	int len, ret;
1092	if (sm == NULL)
1093		return 0;
1094
1095	len = os_snprintf(buf, buflen,
1096			  "Supplicant PAE state=%s\n"
1097			  "suppPortStatus=%s\n",
1098			  eapol_supp_pae_state(sm->SUPP_PAE_state),
1099			  eapol_port_status(sm->suppPortStatus));
1100	if (len < 0 || (size_t) len >= buflen)
1101		return 0;
1102
1103	if (verbose) {
1104		ret = os_snprintf(buf + len, buflen - len,
1105				  "heldPeriod=%u\n"
1106				  "authPeriod=%u\n"
1107				  "startPeriod=%u\n"
1108				  "maxStart=%u\n"
1109				  "portControl=%s\n"
1110				  "Supplicant Backend state=%s\n",
1111				  sm->heldPeriod,
1112				  sm->authPeriod,
1113				  sm->startPeriod,
1114				  sm->maxStart,
1115				  eapol_port_control(sm->portControl),
1116				  eapol_supp_be_state(sm->SUPP_BE_state));
1117		if (ret < 0 || (size_t) ret >= buflen - len)
1118			return len;
1119		len += ret;
1120	}
1121
1122#ifdef CONFIG_EAP_PROXY
1123	if (sm->use_eap_proxy)
1124		len += eap_proxy_sm_get_status(sm->eap_proxy,
1125					       buf + len, buflen - len,
1126					       verbose);
1127	else
1128#endif /* CONFIG_EAP_PROXY */
1129	len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
1130
1131	return len;
1132}
1133
1134
1135/**
1136 * eapol_sm_get_mib - Get EAPOL state machine MIBs
1137 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1138 * @buf: Buffer for MIB information
1139 * @buflen: Maximum buffer length
1140 * Returns: Number of bytes written to buf.
1141 *
1142 * Query EAPOL state machine for MIB information. This function fills in a
1143 * text area with current MIB information from the EAPOL state machine. If
1144 * the buffer (buf) is not large enough, MIB information will be truncated to
1145 * fit the buffer.
1146 */
1147int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
1148{
1149	size_t len;
1150	int ret;
1151
1152	if (sm == NULL)
1153		return 0;
1154	ret = os_snprintf(buf, buflen,
1155			  "dot1xSuppPaeState=%d\n"
1156			  "dot1xSuppHeldPeriod=%u\n"
1157			  "dot1xSuppAuthPeriod=%u\n"
1158			  "dot1xSuppStartPeriod=%u\n"
1159			  "dot1xSuppMaxStart=%u\n"
1160			  "dot1xSuppSuppControlledPortStatus=%s\n"
1161			  "dot1xSuppBackendPaeState=%d\n",
1162			  sm->SUPP_PAE_state,
1163			  sm->heldPeriod,
1164			  sm->authPeriod,
1165			  sm->startPeriod,
1166			  sm->maxStart,
1167			  sm->suppPortStatus == Authorized ?
1168			  "Authorized" : "Unauthorized",
1169			  sm->SUPP_BE_state);
1170
1171	if (ret < 0 || (size_t) ret >= buflen)
1172		return 0;
1173	len = ret;
1174
1175	ret = os_snprintf(buf + len, buflen - len,
1176			  "dot1xSuppEapolFramesRx=%u\n"
1177			  "dot1xSuppEapolFramesTx=%u\n"
1178			  "dot1xSuppEapolStartFramesTx=%u\n"
1179			  "dot1xSuppEapolLogoffFramesTx=%u\n"
1180			  "dot1xSuppEapolRespFramesTx=%u\n"
1181			  "dot1xSuppEapolReqIdFramesRx=%u\n"
1182			  "dot1xSuppEapolReqFramesRx=%u\n"
1183			  "dot1xSuppInvalidEapolFramesRx=%u\n"
1184			  "dot1xSuppEapLengthErrorFramesRx=%u\n"
1185			  "dot1xSuppLastEapolFrameVersion=%u\n"
1186			  "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
1187			  sm->dot1xSuppEapolFramesRx,
1188			  sm->dot1xSuppEapolFramesTx,
1189			  sm->dot1xSuppEapolStartFramesTx,
1190			  sm->dot1xSuppEapolLogoffFramesTx,
1191			  sm->dot1xSuppEapolRespFramesTx,
1192			  sm->dot1xSuppEapolReqIdFramesRx,
1193			  sm->dot1xSuppEapolReqFramesRx,
1194			  sm->dot1xSuppInvalidEapolFramesRx,
1195			  sm->dot1xSuppEapLengthErrorFramesRx,
1196			  sm->dot1xSuppLastEapolFrameVersion,
1197			  MAC2STR(sm->dot1xSuppLastEapolFrameSource));
1198
1199	if (ret < 0 || (size_t) ret >= buflen - len)
1200		return len;
1201	len += ret;
1202
1203	return len;
1204}
1205#endif /* CONFIG_CTRL_IFACE */
1206
1207
1208/**
1209 * eapol_sm_rx_eapol - Process received EAPOL frames
1210 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1211 * @src: Source MAC address of the EAPOL packet
1212 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
1213 * @len: Length of the EAPOL frame
1214 * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
1215 * -1 failure
1216 */
1217int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
1218		      size_t len)
1219{
1220	const struct ieee802_1x_hdr *hdr;
1221	const struct ieee802_1x_eapol_key *key;
1222	int data_len;
1223	int res = 1;
1224	size_t plen;
1225
1226	if (sm == NULL)
1227		return 0;
1228	sm->dot1xSuppEapolFramesRx++;
1229	if (len < sizeof(*hdr)) {
1230		sm->dot1xSuppInvalidEapolFramesRx++;
1231		return 0;
1232	}
1233	hdr = (const struct ieee802_1x_hdr *) buf;
1234	sm->dot1xSuppLastEapolFrameVersion = hdr->version;
1235	os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
1236	if (hdr->version < EAPOL_VERSION) {
1237		/* TODO: backwards compatibility */
1238	}
1239	plen = be_to_host16(hdr->length);
1240	if (plen > len - sizeof(*hdr)) {
1241		sm->dot1xSuppEapLengthErrorFramesRx++;
1242		return 0;
1243	}
1244#ifdef CONFIG_WPS
1245	if (sm->conf.workaround &&
1246	    plen < len - sizeof(*hdr) &&
1247	    hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
1248	    len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
1249		const struct eap_hdr *ehdr =
1250			(const struct eap_hdr *) (hdr + 1);
1251		u16 elen;
1252
1253		elen = be_to_host16(ehdr->length);
1254		if (elen > plen && elen <= len - sizeof(*hdr)) {
1255			/*
1256			 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
1257			 * packets with too short EAPOL header length field
1258			 * (14 octets). This is fixed in firmware Ver.1.49.
1259			 * As a workaround, fix the EAPOL header based on the
1260			 * correct length in the EAP packet.
1261			 */
1262			wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
1263				   "payload length based on EAP header: "
1264				   "%d -> %d", (int) plen, elen);
1265			plen = elen;
1266		}
1267	}
1268#endif /* CONFIG_WPS */
1269	data_len = plen + sizeof(*hdr);
1270
1271	switch (hdr->type) {
1272	case IEEE802_1X_TYPE_EAP_PACKET:
1273		if (sm->conf.workaround) {
1274			/*
1275			 * An AP has been reported to send out EAP message with
1276			 * undocumented code 10 at some point near the
1277			 * completion of EAP authentication. This can result in
1278			 * issues with the unexpected EAP message triggering
1279			 * restart of EAPOL authentication. Avoid this by
1280			 * skipping the message without advancing the state
1281			 * machine.
1282			 */
1283			const struct eap_hdr *ehdr =
1284				(const struct eap_hdr *) (hdr + 1);
1285			if (plen >= sizeof(*ehdr) && ehdr->code == 10) {
1286				wpa_printf(MSG_DEBUG, "EAPOL: Ignore EAP packet with unknown code 10");
1287				break;
1288			}
1289		}
1290
1291		if (sm->cached_pmk) {
1292			/* Trying to use PMKSA caching, but Authenticator did
1293			 * not seem to have a matching entry. Need to restart
1294			 * EAPOL state machines.
1295			 */
1296			eapol_sm_abort_cached(sm);
1297		}
1298		wpabuf_free(sm->eapReqData);
1299		sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
1300		if (sm->eapReqData) {
1301			wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
1302				   "frame");
1303			sm->eapolEap = TRUE;
1304#ifdef CONFIG_EAP_PROXY
1305			if (sm->use_eap_proxy) {
1306				eap_proxy_packet_update(
1307					sm->eap_proxy,
1308					wpabuf_mhead_u8(sm->eapReqData),
1309					wpabuf_len(sm->eapReqData));
1310				wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy "
1311					   "EAP Req updated");
1312			}
1313#endif /* CONFIG_EAP_PROXY */
1314			eapol_sm_step(sm);
1315		}
1316		break;
1317	case IEEE802_1X_TYPE_EAPOL_KEY:
1318		if (plen < sizeof(*key)) {
1319			wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
1320				   "frame received");
1321			break;
1322		}
1323		key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
1324		if (key->type == EAPOL_KEY_TYPE_WPA ||
1325		    key->type == EAPOL_KEY_TYPE_RSN) {
1326			/* WPA Supplicant takes care of this frame. */
1327			wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
1328				   "frame in EAPOL state machines");
1329			res = 0;
1330			break;
1331		}
1332		if (key->type != EAPOL_KEY_TYPE_RC4) {
1333			wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
1334				   "EAPOL-Key type %d", key->type);
1335			break;
1336		}
1337		os_free(sm->last_rx_key);
1338		sm->last_rx_key = os_malloc(data_len);
1339		if (sm->last_rx_key) {
1340			wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
1341				   "frame");
1342			os_memcpy(sm->last_rx_key, buf, data_len);
1343			sm->last_rx_key_len = data_len;
1344			sm->rxKey = TRUE;
1345			eapol_sm_step(sm);
1346		}
1347		break;
1348	default:
1349		wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
1350			   hdr->type);
1351		sm->dot1xSuppInvalidEapolFramesRx++;
1352		break;
1353	}
1354
1355	return res;
1356}
1357
1358
1359/**
1360 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
1361 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1362 *
1363 * Notify EAPOL state machine about transmitted EAPOL packet from an external
1364 * component, e.g., WPA. This will update the statistics.
1365 */
1366void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
1367{
1368	if (sm)
1369		sm->dot1xSuppEapolFramesTx++;
1370}
1371
1372
1373/**
1374 * eapol_sm_notify_portEnabled - Notification about portEnabled change
1375 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1376 * @enabled: New portEnabled value
1377 *
1378 * Notify EAPOL state machine about new portEnabled value.
1379 */
1380void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
1381{
1382	if (sm == NULL)
1383		return;
1384	wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1385		   "portEnabled=%d", enabled);
1386	if (sm->portEnabled != enabled)
1387		sm->force_authorized_update = TRUE;
1388	sm->portEnabled = enabled;
1389	eapol_sm_step(sm);
1390}
1391
1392
1393/**
1394 * eapol_sm_notify_portValid - Notification about portValid change
1395 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1396 * @valid: New portValid value
1397 *
1398 * Notify EAPOL state machine about new portValid value.
1399 */
1400void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
1401{
1402	if (sm == NULL)
1403		return;
1404	wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1405		   "portValid=%d", valid);
1406	sm->portValid = valid;
1407	eapol_sm_step(sm);
1408}
1409
1410
1411/**
1412 * eapol_sm_notify_eap_success - Notification of external EAP success trigger
1413 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1414 * @success: %TRUE = set success, %FALSE = clear success
1415 *
1416 * Notify the EAPOL state machine that external event has forced EAP state to
1417 * success (success = %TRUE). This can be cleared by setting success = %FALSE.
1418 *
1419 * This function is called to update EAP state when WPA-PSK key handshake has
1420 * been completed successfully since WPA-PSK does not use EAP state machine.
1421 */
1422void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
1423{
1424	if (sm == NULL)
1425		return;
1426	wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1427		   "EAP success=%d", success);
1428	sm->eapSuccess = success;
1429	sm->altAccept = success;
1430	if (success)
1431		eap_notify_success(sm->eap);
1432	eapol_sm_step(sm);
1433}
1434
1435
1436/**
1437 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
1438 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1439 * @fail: %TRUE = set failure, %FALSE = clear failure
1440 *
1441 * Notify EAPOL state machine that external event has forced EAP state to
1442 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1443 */
1444void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
1445{
1446	if (sm == NULL)
1447		return;
1448	wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1449		   "EAP fail=%d", fail);
1450	sm->eapFail = fail;
1451	sm->altReject = fail;
1452	eapol_sm_step(sm);
1453}
1454
1455
1456/**
1457 * eapol_sm_notify_config - Notification of EAPOL configuration change
1458 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1459 * @config: Pointer to current network EAP configuration
1460 * @conf: Pointer to EAPOL configuration data
1461 *
1462 * Notify EAPOL state machine that configuration has changed. config will be
1463 * stored as a backpointer to network configuration. This can be %NULL to clear
1464 * the stored pointed. conf will be copied to local EAPOL/EAP configuration
1465 * data. If conf is %NULL, this part of the configuration change will be
1466 * skipped.
1467 */
1468void eapol_sm_notify_config(struct eapol_sm *sm,
1469			    struct eap_peer_config *config,
1470			    const struct eapol_config *conf)
1471{
1472	if (sm == NULL)
1473		return;
1474
1475	sm->config = config;
1476#ifdef CONFIG_EAP_PROXY
1477	sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0;
1478#endif /* CONFIG_EAP_PROXY */
1479
1480	if (conf == NULL)
1481		return;
1482
1483	sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
1484	sm->conf.required_keys = conf->required_keys;
1485	sm->conf.fast_reauth = conf->fast_reauth;
1486	sm->conf.workaround = conf->workaround;
1487#ifdef CONFIG_EAP_PROXY
1488	if (sm->use_eap_proxy) {
1489		/* Using EAP Proxy, so skip EAP state machine update */
1490		return;
1491	}
1492#endif /* CONFIG_EAP_PROXY */
1493	if (sm->eap) {
1494		eap_set_fast_reauth(sm->eap, conf->fast_reauth);
1495		eap_set_workaround(sm->eap, conf->workaround);
1496		eap_set_force_disabled(sm->eap, conf->eap_disabled);
1497		eap_set_external_sim(sm->eap, conf->external_sim);
1498	}
1499}
1500
1501
1502/**
1503 * eapol_sm_get_key - Get master session key (MSK) from EAP
1504 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1505 * @key: Pointer for key buffer
1506 * @len: Number of bytes to copy to key
1507 * Returns: 0 on success (len of key available), maximum available key len
1508 * (>0) if key is available but it is shorter than len, or -1 on failure.
1509 *
1510 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
1511 * is available only after a successful authentication.
1512 */
1513int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
1514{
1515	const u8 *eap_key;
1516	size_t eap_len;
1517
1518#ifdef CONFIG_EAP_PROXY
1519	if (sm->use_eap_proxy) {
1520		/* Get key from EAP proxy */
1521		if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
1522			wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1523			return -1;
1524		}
1525		eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len);
1526		if (eap_key == NULL) {
1527			wpa_printf(MSG_DEBUG, "EAPOL: Failed to get "
1528				   "eapKeyData");
1529			return -1;
1530		}
1531		goto key_fetched;
1532	}
1533#endif /* CONFIG_EAP_PROXY */
1534	if (sm == NULL || !eap_key_available(sm->eap)) {
1535		wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1536		return -1;
1537	}
1538	eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
1539	if (eap_key == NULL) {
1540		wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
1541		return -1;
1542	}
1543#ifdef CONFIG_EAP_PROXY
1544key_fetched:
1545#endif /* CONFIG_EAP_PROXY */
1546	if (len > eap_len) {
1547		wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
1548			   "available (len=%lu)",
1549			   (unsigned long) len, (unsigned long) eap_len);
1550		return eap_len;
1551	}
1552	os_memcpy(key, eap_key, len);
1553	wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
1554		   (unsigned long) len);
1555	return 0;
1556}
1557
1558
1559/**
1560 * eapol_sm_notify_logoff - Notification of logon/logoff commands
1561 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1562 * @logoff: Whether command was logoff
1563 *
1564 * Notify EAPOL state machines that user requested logon/logoff.
1565 */
1566void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
1567{
1568	if (sm) {
1569		sm->userLogoff = logoff;
1570		if (!logoff) {
1571			/* If there is a delayed txStart queued, start now. */
1572			sm->startWhen = 0;
1573		}
1574		eapol_sm_step(sm);
1575	}
1576}
1577
1578
1579/**
1580 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
1581 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1582 *
1583 * Notify EAPOL state machines that PMKSA caching was successful. This is used
1584 * to move EAPOL and EAP state machines into authenticated/successful state.
1585 */
1586void eapol_sm_notify_cached(struct eapol_sm *sm)
1587{
1588	if (sm == NULL)
1589		return;
1590	wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
1591	sm->eapSuccess = TRUE;
1592	eap_notify_success(sm->eap);
1593	eapol_sm_step(sm);
1594}
1595
1596
1597/**
1598 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
1599 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1600 * @attempt: Whether PMKSA caching is tried
1601 *
1602 * Notify EAPOL state machines whether PMKSA caching is used.
1603 */
1604void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt)
1605{
1606	if (sm == NULL)
1607		return;
1608	if (attempt) {
1609		wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
1610		sm->cached_pmk = TRUE;
1611	} else {
1612		wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA");
1613		sm->cached_pmk = FALSE;
1614	}
1615}
1616
1617
1618static void eapol_sm_abort_cached(struct eapol_sm *sm)
1619{
1620	wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
1621		   "doing full EAP authentication");
1622	if (sm == NULL)
1623		return;
1624	sm->cached_pmk = FALSE;
1625	sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
1626	eapol_sm_set_port_unauthorized(sm);
1627
1628	/* Make sure we do not start sending EAPOL-Start frames first, but
1629	 * instead move to RESTART state to start EAPOL authentication. */
1630	sm->startWhen = 3;
1631	eapol_enable_timer_tick(sm);
1632
1633	if (sm->ctx->aborted_cached)
1634		sm->ctx->aborted_cached(sm->ctx->ctx);
1635}
1636
1637
1638/**
1639 * eapol_sm_register_scard_ctx - Notification of smart card context
1640 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1641 * @ctx: Context data for smart card operations
1642 *
1643 * Notify EAPOL state machines of context data for smart card operations. This
1644 * context data will be used as a parameter for scard_*() functions.
1645 */
1646void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
1647{
1648	if (sm) {
1649		sm->ctx->scard_ctx = ctx;
1650		eap_register_scard_ctx(sm->eap, ctx);
1651	}
1652}
1653
1654
1655/**
1656 * eapol_sm_notify_portControl - Notification of portControl changes
1657 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1658 * @portControl: New value for portControl variable
1659 *
1660 * Notify EAPOL state machines that portControl variable has changed.
1661 */
1662void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
1663{
1664	if (sm == NULL)
1665		return;
1666	wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1667		   "portControl=%s", eapol_port_control(portControl));
1668	sm->portControl = portControl;
1669	eapol_sm_step(sm);
1670}
1671
1672
1673/**
1674 * eapol_sm_notify_ctrl_attached - Notification of attached monitor
1675 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1676 *
1677 * Notify EAPOL state machines that a monitor was attached to the control
1678 * interface to trigger re-sending of pending requests for user input.
1679 */
1680void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
1681{
1682	if (sm == NULL)
1683		return;
1684	eap_sm_notify_ctrl_attached(sm->eap);
1685}
1686
1687
1688/**
1689 * eapol_sm_notify_ctrl_response - Notification of received user input
1690 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1691 *
1692 * Notify EAPOL state machines that a control response, i.e., user
1693 * input, was received in order to trigger retrying of a pending EAP request.
1694 */
1695void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
1696{
1697	if (sm == NULL)
1698		return;
1699	if (sm->eapReqData && !sm->eapReq) {
1700		wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
1701			   "input) notification - retrying pending EAP "
1702			   "Request");
1703		sm->eapolEap = TRUE;
1704		sm->eapReq = TRUE;
1705		eapol_sm_step(sm);
1706	}
1707}
1708
1709
1710/**
1711 * eapol_sm_request_reauth - Request reauthentication
1712 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1713 *
1714 * This function can be used to request EAPOL reauthentication, e.g., when the
1715 * current PMKSA entry is nearing expiration.
1716 */
1717void eapol_sm_request_reauth(struct eapol_sm *sm)
1718{
1719	if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
1720		return;
1721	eapol_sm_txStart(sm);
1722}
1723
1724
1725/**
1726 * eapol_sm_notify_lower_layer_success - Notification of lower layer success
1727 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1728 * @in_eapol_sm: Whether the caller is already running inside EAPOL state
1729 * machine loop (eapol_sm_step())
1730 *
1731 * Notify EAPOL (and EAP) state machines that a lower layer has detected a
1732 * successful authentication. This is used to recover from dropped EAP-Success
1733 * messages.
1734 */
1735void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
1736{
1737	if (sm == NULL)
1738		return;
1739	eap_notify_lower_layer_success(sm->eap);
1740	if (!in_eapol_sm)
1741		eapol_sm_step(sm);
1742}
1743
1744
1745/**
1746 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
1747 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1748 */
1749void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
1750{
1751	if (sm)
1752		eap_invalidate_cached_session(sm->eap);
1753}
1754
1755
1756static struct eap_peer_config * eapol_sm_get_config(void *ctx)
1757{
1758	struct eapol_sm *sm = ctx;
1759	return sm ? sm->config : NULL;
1760}
1761
1762
1763static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
1764{
1765	struct eapol_sm *sm = ctx;
1766	if (sm == NULL || sm->eapReqData == NULL)
1767		return NULL;
1768
1769	return sm->eapReqData;
1770}
1771
1772
1773static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1774{
1775	struct eapol_sm *sm = ctx;
1776	if (sm == NULL)
1777		return FALSE;
1778	switch (variable) {
1779	case EAPOL_eapSuccess:
1780		return sm->eapSuccess;
1781	case EAPOL_eapRestart:
1782		return sm->eapRestart;
1783	case EAPOL_eapFail:
1784		return sm->eapFail;
1785	case EAPOL_eapResp:
1786		return sm->eapResp;
1787	case EAPOL_eapNoResp:
1788		return sm->eapNoResp;
1789	case EAPOL_eapReq:
1790		return sm->eapReq;
1791	case EAPOL_portEnabled:
1792		return sm->portEnabled;
1793	case EAPOL_altAccept:
1794		return sm->altAccept;
1795	case EAPOL_altReject:
1796		return sm->altReject;
1797	}
1798	return FALSE;
1799}
1800
1801
1802static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1803			      Boolean value)
1804{
1805	struct eapol_sm *sm = ctx;
1806	if (sm == NULL)
1807		return;
1808	switch (variable) {
1809	case EAPOL_eapSuccess:
1810		sm->eapSuccess = value;
1811		break;
1812	case EAPOL_eapRestart:
1813		sm->eapRestart = value;
1814		break;
1815	case EAPOL_eapFail:
1816		sm->eapFail = value;
1817		break;
1818	case EAPOL_eapResp:
1819		sm->eapResp = value;
1820		break;
1821	case EAPOL_eapNoResp:
1822		sm->eapNoResp = value;
1823		break;
1824	case EAPOL_eapReq:
1825		sm->eapReq = value;
1826		break;
1827	case EAPOL_portEnabled:
1828		sm->portEnabled = value;
1829		break;
1830	case EAPOL_altAccept:
1831		sm->altAccept = value;
1832		break;
1833	case EAPOL_altReject:
1834		sm->altReject = value;
1835		break;
1836	}
1837}
1838
1839
1840static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
1841{
1842	struct eapol_sm *sm = ctx;
1843	if (sm == NULL)
1844		return 0;
1845	switch (variable) {
1846	case EAPOL_idleWhile:
1847		return sm->idleWhile;
1848	}
1849	return 0;
1850}
1851
1852
1853static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
1854			     unsigned int value)
1855{
1856	struct eapol_sm *sm = ctx;
1857	if (sm == NULL)
1858		return;
1859	switch (variable) {
1860	case EAPOL_idleWhile:
1861		sm->idleWhile = value;
1862		if (sm->idleWhile > 0)
1863			eapol_enable_timer_tick(sm);
1864		break;
1865	}
1866}
1867
1868
1869static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
1870{
1871#ifndef CONFIG_NO_CONFIG_BLOBS
1872	struct eapol_sm *sm = ctx;
1873	if (sm && sm->ctx && sm->ctx->set_config_blob)
1874		sm->ctx->set_config_blob(sm->ctx->ctx, blob);
1875#endif /* CONFIG_NO_CONFIG_BLOBS */
1876}
1877
1878
1879static const struct wpa_config_blob *
1880eapol_sm_get_config_blob(void *ctx, const char *name)
1881{
1882#ifndef CONFIG_NO_CONFIG_BLOBS
1883	struct eapol_sm *sm = ctx;
1884	if (sm && sm->ctx && sm->ctx->get_config_blob)
1885		return sm->ctx->get_config_blob(sm->ctx->ctx, name);
1886	else
1887		return NULL;
1888#else /* CONFIG_NO_CONFIG_BLOBS */
1889	return NULL;
1890#endif /* CONFIG_NO_CONFIG_BLOBS */
1891}
1892
1893
1894static void eapol_sm_notify_pending(void *ctx)
1895{
1896	struct eapol_sm *sm = ctx;
1897	if (sm == NULL)
1898		return;
1899	if (sm->eapReqData && !sm->eapReq) {
1900		wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
1901			   "state machine - retrying pending EAP Request");
1902		sm->eapolEap = TRUE;
1903		sm->eapReq = TRUE;
1904		eapol_sm_step(sm);
1905	}
1906}
1907
1908
1909#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1910static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
1911				      const char *txt)
1912{
1913	struct eapol_sm *sm = ctx;
1914	wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
1915	if (sm->ctx->eap_param_needed)
1916		sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
1917}
1918#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1919#define eapol_sm_eap_param_needed NULL
1920#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1921
1922static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
1923				 const char *cert_hash,
1924				 const struct wpabuf *cert)
1925{
1926	struct eapol_sm *sm = ctx;
1927	if (sm->ctx->cert_cb)
1928		sm->ctx->cert_cb(sm->ctx->ctx, depth, subject,
1929				 cert_hash, cert);
1930}
1931
1932
1933static void eapol_sm_notify_status(void *ctx, const char *status,
1934				   const char *parameter)
1935{
1936	struct eapol_sm *sm = ctx;
1937
1938	if (sm->ctx->status_cb)
1939		sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
1940}
1941
1942
1943static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len)
1944{
1945	struct eapol_sm *sm = ctx;
1946
1947	if (sm->ctx->set_anon_id)
1948		sm->ctx->set_anon_id(sm->ctx->ctx, id, len);
1949}
1950
1951
1952static struct eapol_callbacks eapol_cb =
1953{
1954	eapol_sm_get_config,
1955	eapol_sm_get_bool,
1956	eapol_sm_set_bool,
1957	eapol_sm_get_int,
1958	eapol_sm_set_int,
1959	eapol_sm_get_eapReqData,
1960	eapol_sm_set_config_blob,
1961	eapol_sm_get_config_blob,
1962	eapol_sm_notify_pending,
1963	eapol_sm_eap_param_needed,
1964	eapol_sm_notify_cert,
1965	eapol_sm_notify_status,
1966	eapol_sm_set_anon_id
1967};
1968
1969
1970/**
1971 * eapol_sm_init - Initialize EAPOL state machine
1972 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
1973 * and EAPOL state machine will free it in eapol_sm_deinit()
1974 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
1975 *
1976 * Allocate and initialize an EAPOL state machine.
1977 */
1978struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
1979{
1980	struct eapol_sm *sm;
1981	struct eap_config conf;
1982	sm = os_zalloc(sizeof(*sm));
1983	if (sm == NULL)
1984		return NULL;
1985	sm->ctx = ctx;
1986
1987	sm->portControl = Auto;
1988
1989	/* Supplicant PAE state machine */
1990	sm->heldPeriod = 60;
1991	sm->startPeriod = 30;
1992	sm->maxStart = 3;
1993
1994	/* Supplicant Backend state machine */
1995	sm->authPeriod = 30;
1996
1997	os_memset(&conf, 0, sizeof(conf));
1998	conf.opensc_engine_path = ctx->opensc_engine_path;
1999	conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
2000	conf.pkcs11_module_path = ctx->pkcs11_module_path;
2001	conf.wps = ctx->wps;
2002	conf.cert_in_cb = ctx->cert_in_cb;
2003
2004	sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
2005	if (sm->eap == NULL) {
2006		os_free(sm);
2007		return NULL;
2008	}
2009
2010#ifdef CONFIG_EAP_PROXY
2011	sm->use_eap_proxy = FALSE;
2012	sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx);
2013	if (sm->eap_proxy == NULL) {
2014		wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy");
2015	}
2016#endif /* CONFIG_EAP_PROXY */
2017
2018	/* Initialize EAPOL state machines */
2019	sm->force_authorized_update = TRUE;
2020	sm->initialize = TRUE;
2021	eapol_sm_step(sm);
2022	sm->initialize = FALSE;
2023	eapol_sm_step(sm);
2024
2025	sm->timer_tick_enabled = 1;
2026	eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
2027
2028	return sm;
2029}
2030
2031
2032/**
2033 * eapol_sm_deinit - Deinitialize EAPOL state machine
2034 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
2035 *
2036 * Deinitialize and free EAPOL state machine.
2037 */
2038void eapol_sm_deinit(struct eapol_sm *sm)
2039{
2040	if (sm == NULL)
2041		return;
2042	eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
2043	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
2044	eap_peer_sm_deinit(sm->eap);
2045#ifdef CONFIG_EAP_PROXY
2046	eap_proxy_deinit(sm->eap_proxy);
2047#endif /* CONFIG_EAP_PROXY */
2048	os_free(sm->last_rx_key);
2049	wpabuf_free(sm->eapReqData);
2050	os_free(sm->ctx);
2051	os_free(sm);
2052}
2053
2054
2055void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
2056			     struct ext_password_data *ext)
2057{
2058	if (sm && sm->eap)
2059		eap_sm_set_ext_pw_ctx(sm->eap, ext);
2060}
2061
2062
2063int eapol_sm_failed(struct eapol_sm *sm)
2064{
2065	if (sm == NULL)
2066		return 0;
2067	return !sm->eapSuccess && sm->eapFail;
2068}
2069
2070
2071int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len)
2072{
2073#ifdef CONFIG_EAP_PROXY
2074	if (sm->eap_proxy == NULL)
2075		return -1;
2076	return eap_proxy_get_imsi(sm->eap_proxy, imsi, len);
2077#else /* CONFIG_EAP_PROXY */
2078	return -1;
2079#endif /* CONFIG_EAP_PROXY */
2080}
2081