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