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