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