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