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