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