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