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