Home | History | Annotate | Download | only in eapol_supp
      1 /*
      2  * EAPOL supplicant state machines
      3  * Copyright (c) 2004-2012, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "state_machine.h"
     13 #include "wpabuf.h"
     14 #include "eloop.h"
     15 #include "crypto/crypto.h"
     16 #include "crypto/md5.h"
     17 #include "common/eapol_common.h"
     18 #include "eap_peer/eap.h"
     19 #include "eap_peer/eap_proxy.h"
     20 #include "eapol_supp_sm.h"
     21 
     22 #define STATE_MACHINE_DATA struct eapol_sm
     23 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
     24 
     25 
     26 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
     27 
     28 /**
     29  * struct eapol_sm - Internal data for EAPOL state machines
     30  */
     31 struct eapol_sm {
     32 	/* Timers */
     33 	unsigned int authWhile;
     34 	unsigned int heldWhile;
     35 	unsigned int startWhen;
     36 	unsigned int idleWhile; /* for EAP state machine */
     37 	int timer_tick_enabled;
     38 
     39 	/* Global variables */
     40 	Boolean eapFail;
     41 	Boolean eapolEap;
     42 	Boolean eapSuccess;
     43 	Boolean initialize;
     44 	Boolean keyDone;
     45 	Boolean keyRun;
     46 	PortControl portControl;
     47 	Boolean portEnabled;
     48 	PortStatus suppPortStatus;  /* dot1xSuppControlledPortStatus */
     49 	Boolean portValid;
     50 	Boolean suppAbort;
     51 	Boolean suppFail;
     52 	Boolean suppStart;
     53 	Boolean suppSuccess;
     54 	Boolean suppTimeout;
     55 
     56 	/* Supplicant PAE state machine */
     57 	enum {
     58 		SUPP_PAE_UNKNOWN = 0,
     59 		SUPP_PAE_DISCONNECTED = 1,
     60 		SUPP_PAE_LOGOFF = 2,
     61 		SUPP_PAE_CONNECTING = 3,
     62 		SUPP_PAE_AUTHENTICATING = 4,
     63 		SUPP_PAE_AUTHENTICATED = 5,
     64 		/* unused(6) */
     65 		SUPP_PAE_HELD = 7,
     66 		SUPP_PAE_RESTART = 8,
     67 		SUPP_PAE_S_FORCE_AUTH = 9,
     68 		SUPP_PAE_S_FORCE_UNAUTH = 10
     69 	} SUPP_PAE_state; /* dot1xSuppPaeState */
     70 	/* Variables */
     71 	Boolean userLogoff;
     72 	Boolean logoffSent;
     73 	unsigned int startCount;
     74 	Boolean eapRestart;
     75 	PortControl sPortMode;
     76 	/* Constants */
     77 	unsigned int heldPeriod; /* dot1xSuppHeldPeriod */
     78 	unsigned int startPeriod; /* dot1xSuppStartPeriod */
     79 	unsigned int maxStart; /* dot1xSuppMaxStart */
     80 
     81 	/* Key Receive state machine */
     82 	enum {
     83 		KEY_RX_UNKNOWN = 0,
     84 		KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
     85 	} KEY_RX_state;
     86 	/* Variables */
     87 	Boolean rxKey;
     88 
     89 	/* Supplicant Backend state machine */
     90 	enum {
     91 		SUPP_BE_UNKNOWN = 0,
     92 		SUPP_BE_INITIALIZE = 1,
     93 		SUPP_BE_IDLE = 2,
     94 		SUPP_BE_REQUEST = 3,
     95 		SUPP_BE_RECEIVE = 4,
     96 		SUPP_BE_RESPONSE = 5,
     97 		SUPP_BE_FAIL = 6,
     98 		SUPP_BE_TIMEOUT = 7,
     99 		SUPP_BE_SUCCESS = 8
    100 	} SUPP_BE_state; /* dot1xSuppBackendPaeState */
    101 	/* Variables */
    102 	Boolean eapNoResp;
    103 	Boolean eapReq;
    104 	Boolean eapResp;
    105 	/* Constants */
    106 	unsigned int authPeriod; /* dot1xSuppAuthPeriod */
    107 
    108 	/* Statistics */
    109 	unsigned int dot1xSuppEapolFramesRx;
    110 	unsigned int dot1xSuppEapolFramesTx;
    111 	unsigned int dot1xSuppEapolStartFramesTx;
    112 	unsigned int dot1xSuppEapolLogoffFramesTx;
    113 	unsigned int dot1xSuppEapolRespFramesTx;
    114 	unsigned int dot1xSuppEapolReqIdFramesRx;
    115 	unsigned int dot1xSuppEapolReqFramesRx;
    116 	unsigned int dot1xSuppInvalidEapolFramesRx;
    117 	unsigned int dot1xSuppEapLengthErrorFramesRx;
    118 	unsigned int dot1xSuppLastEapolFrameVersion;
    119 	unsigned char dot1xSuppLastEapolFrameSource[6];
    120 
    121 	/* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
    122 	Boolean changed;
    123 	struct eap_sm *eap;
    124 	struct eap_peer_config *config;
    125 	Boolean initial_req;
    126 	u8 *last_rx_key;
    127 	size_t last_rx_key_len;
    128 	struct wpabuf *eapReqData; /* for EAP */
    129 	Boolean altAccept; /* for EAP */
    130 	Boolean altReject; /* for EAP */
    131 	Boolean eapTriggerStart;
    132 	Boolean replay_counter_valid;
    133 	u8 last_replay_counter[16];
    134 	struct eapol_config conf;
    135 	struct eapol_ctx *ctx;
    136 	enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
    137 		cb_status;
    138 	Boolean cached_pmk;
    139 
    140 	Boolean unicast_key_received, broadcast_key_received;
    141 
    142 	Boolean force_authorized_update;
    143 
    144 #ifdef CONFIG_EAP_PROXY
    145 	Boolean use_eap_proxy;
    146 	struct eap_proxy_sm *eap_proxy;
    147 #endif /* CONFIG_EAP_PROXY */
    148 };
    149 
    150 
    151 static void eapol_sm_txLogoff(struct eapol_sm *sm);
    152 static void eapol_sm_txStart(struct eapol_sm *sm);
    153 static void eapol_sm_processKey(struct eapol_sm *sm);
    154 static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
    155 static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
    156 static void eapol_sm_abortSupp(struct eapol_sm *sm);
    157 static void eapol_sm_abort_cached(struct eapol_sm *sm);
    158 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
    159 static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
    160 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
    161 
    162 
    163 /* Port Timers state machine - implemented as a function that will be called
    164  * once a second as a registered event loop timeout */
    165 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
    166 {
    167 	struct eapol_sm *sm = timeout_ctx;
    168 
    169 	if (sm->authWhile > 0) {
    170 		sm->authWhile--;
    171 		if (sm->authWhile == 0)
    172 			wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
    173 	}
    174 	if (sm->heldWhile > 0) {
    175 		sm->heldWhile--;
    176 		if (sm->heldWhile == 0)
    177 			wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
    178 	}
    179 	if (sm->startWhen > 0) {
    180 		sm->startWhen--;
    181 		if (sm->startWhen == 0)
    182 			wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
    183 	}
    184 	if (sm->idleWhile > 0) {
    185 		sm->idleWhile--;
    186 		if (sm->idleWhile == 0)
    187 			wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
    188 	}
    189 
    190 	if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
    191 		eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,
    192 				       sm);
    193 	} else {
    194 		wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
    195 		sm->timer_tick_enabled = 0;
    196 	}
    197 	eapol_sm_step(sm);
    198 }
    199 
    200 
    201 static void eapol_enable_timer_tick(struct eapol_sm *sm)
    202 {
    203 	if (sm->timer_tick_enabled)
    204 		return;
    205 	wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
    206 	sm->timer_tick_enabled = 1;
    207 	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
    208 	eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
    209 }
    210 
    211 
    212 SM_STATE(SUPP_PAE, LOGOFF)
    213 {
    214 	SM_ENTRY(SUPP_PAE, LOGOFF);
    215 	eapol_sm_txLogoff(sm);
    216 	sm->logoffSent = TRUE;
    217 	eapol_sm_set_port_unauthorized(sm);
    218 }
    219 
    220 
    221 SM_STATE(SUPP_PAE, DISCONNECTED)
    222 {
    223 	SM_ENTRY(SUPP_PAE, DISCONNECTED);
    224 	sm->sPortMode = Auto;
    225 	sm->startCount = 0;
    226 	sm->eapTriggerStart = FALSE;
    227 	sm->logoffSent = FALSE;
    228 	eapol_sm_set_port_unauthorized(sm);
    229 	sm->suppAbort = TRUE;
    230 
    231 	sm->unicast_key_received = FALSE;
    232 	sm->broadcast_key_received = FALSE;
    233 
    234 	/*
    235 	 * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so
    236 	 * allows the timer tick to be stopped more quickly when the port is
    237 	 * not enabled. Since this variable is used only within HELD state,
    238 	 * clearing it on initialization does not change actual state machine
    239 	 * behavior.
    240 	 */
    241 	sm->heldWhile = 0;
    242 }
    243 
    244 
    245 SM_STATE(SUPP_PAE, CONNECTING)
    246 {
    247 	int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING ||
    248 		sm->SUPP_PAE_state == SUPP_PAE_HELD;
    249 	SM_ENTRY(SUPP_PAE, CONNECTING);
    250 
    251 	if (sm->eapTriggerStart)
    252 		send_start = 1;
    253 	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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    436 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
    437 {
    438 	SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
    439 }
    440 
    441 
    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 
    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 
    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 
    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 
    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 
    511 SM_STATE(SUPP_BE, FAIL)
    512 {
    513 	SM_ENTRY(SUPP_BE, FAIL);
    514 	sm->suppFail = TRUE;
    515 }
    516 
    517 
    518 SM_STATE(SUPP_BE, TIMEOUT)
    519 {
    520 	SM_ENTRY(SUPP_BE, TIMEOUT);
    521 	sm->suppTimeout = TRUE;
    522 }
    523 
    524 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    905 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
    906 {
    907 	eapol_sm_step(timeout_ctx);
    908 }
    909 
    910 
    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 
    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  */
    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
    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 
   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 
   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)
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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 
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 *
   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 
   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)
   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 
   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 
   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 
   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
   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 
   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  */
   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  */
   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 
   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 
   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
   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 
   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 
   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 
   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