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