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