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