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