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