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