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