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