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