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