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