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