2 * EAPOL supplicant state machines
3 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "state_machine.h"
15 #include "crypto/crypto.h"
16 #include "crypto/md5.h"
17 #include "common/eapol_common.h"
18 #include "eap_peer/eap.h"
19 #include "eap_peer/eap_config.h"
20 #include "eap_peer/eap_proxy.h"
21 #include "eapol_supp_sm.h"
23 #define STATE_MACHINE_DATA struct eapol_sm
24 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
27 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
30 * struct eapol_sm - Internal data for EAPOL state machines
34 unsigned int authWhile
;
35 unsigned int heldWhile
;
36 unsigned int startWhen
;
37 unsigned int idleWhile
; /* for EAP state machine */
38 int timer_tick_enabled
;
40 /* Global variables */
47 PortControl portControl
;
49 PortStatus suppPortStatus
; /* dot1xSuppControlledPortStatus */
57 /* Supplicant PAE state machine */
60 SUPP_PAE_DISCONNECTED
= 1,
62 SUPP_PAE_CONNECTING
= 3,
63 SUPP_PAE_AUTHENTICATING
= 4,
64 SUPP_PAE_AUTHENTICATED
= 5,
68 SUPP_PAE_S_FORCE_AUTH
= 9,
69 SUPP_PAE_S_FORCE_UNAUTH
= 10
70 } SUPP_PAE_state
; /* dot1xSuppPaeState */
74 unsigned int startCount
;
76 PortControl sPortMode
;
78 unsigned int heldPeriod
; /* dot1xSuppHeldPeriod */
79 unsigned int startPeriod
; /* dot1xSuppStartPeriod */
80 unsigned int maxStart
; /* dot1xSuppMaxStart */
82 /* Key Receive state machine */
85 KEY_RX_NO_KEY_RECEIVE
, KEY_RX_KEY_RECEIVE
90 /* Supplicant Backend state machine */
93 SUPP_BE_INITIALIZE
= 1,
101 } SUPP_BE_state
; /* dot1xSuppBackendPaeState */
107 unsigned int authPeriod
; /* dot1xSuppAuthPeriod */
110 unsigned int dot1xSuppEapolFramesRx
;
111 unsigned int dot1xSuppEapolFramesTx
;
112 unsigned int dot1xSuppEapolStartFramesTx
;
113 unsigned int dot1xSuppEapolLogoffFramesTx
;
114 unsigned int dot1xSuppEapolRespFramesTx
;
115 unsigned int dot1xSuppEapolReqIdFramesRx
;
116 unsigned int dot1xSuppEapolReqFramesRx
;
117 unsigned int dot1xSuppInvalidEapolFramesRx
;
118 unsigned int dot1xSuppEapLengthErrorFramesRx
;
119 unsigned int dot1xSuppLastEapolFrameVersion
;
120 unsigned char dot1xSuppLastEapolFrameSource
[6];
122 /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
125 struct eap_peer_config
*config
;
128 size_t last_rx_key_len
;
129 struct wpabuf
*eapReqData
; /* for EAP */
130 Boolean altAccept
; /* for EAP */
131 Boolean altReject
; /* for EAP */
132 Boolean eapTriggerStart
;
133 Boolean replay_counter_valid
;
134 u8 last_replay_counter
[16];
135 struct eapol_config conf
;
136 struct eapol_ctx
*ctx
;
137 enum { EAPOL_CB_IN_PROGRESS
= 0, EAPOL_CB_SUCCESS
, EAPOL_CB_FAILURE
}
141 Boolean unicast_key_received
, broadcast_key_received
;
143 Boolean force_authorized_update
;
145 #ifdef CONFIG_EAP_PROXY
146 Boolean use_eap_proxy
;
147 struct eap_proxy_sm
*eap_proxy
;
148 #endif /* CONFIG_EAP_PROXY */
152 static void eapol_sm_txLogoff(struct eapol_sm
*sm
);
153 static void eapol_sm_txStart(struct eapol_sm
*sm
);
154 static void eapol_sm_processKey(struct eapol_sm
*sm
);
155 static void eapol_sm_getSuppRsp(struct eapol_sm
*sm
);
156 static void eapol_sm_txSuppRsp(struct eapol_sm
*sm
);
157 static void eapol_sm_abortSupp(struct eapol_sm
*sm
);
158 static void eapol_sm_abort_cached(struct eapol_sm
*sm
);
159 static void eapol_sm_step_timeout(void *eloop_ctx
, void *timeout_ctx
);
160 static void eapol_sm_set_port_authorized(struct eapol_sm
*sm
);
161 static void eapol_sm_set_port_unauthorized(struct eapol_sm
*sm
);
164 /* Port Timers state machine - implemented as a function that will be called
165 * once a second as a registered event loop timeout */
166 static void eapol_port_timers_tick(void *eloop_ctx
, void *timeout_ctx
)
168 struct eapol_sm
*sm
= timeout_ctx
;
170 if (sm
->authWhile
> 0) {
172 if (sm
->authWhile
== 0)
173 wpa_printf(MSG_DEBUG
, "EAPOL: authWhile --> 0");
175 if (sm
->heldWhile
> 0) {
177 if (sm
->heldWhile
== 0)
178 wpa_printf(MSG_DEBUG
, "EAPOL: heldWhile --> 0");
180 if (sm
->startWhen
> 0) {
182 if (sm
->startWhen
== 0)
183 wpa_printf(MSG_DEBUG
, "EAPOL: startWhen --> 0");
185 if (sm
->idleWhile
> 0) {
187 if (sm
->idleWhile
== 0)
188 wpa_printf(MSG_DEBUG
, "EAPOL: idleWhile --> 0");
191 if (sm
->authWhile
| sm
->heldWhile
| sm
->startWhen
| sm
->idleWhile
) {
192 if (eloop_register_timeout(1, 0, eapol_port_timers_tick
,
194 sm
->timer_tick_enabled
= 0;
196 wpa_printf(MSG_DEBUG
, "EAPOL: disable timer tick");
197 sm
->timer_tick_enabled
= 0;
203 static int eapol_sm_confirm_auth(struct eapol_sm
*sm
)
205 if (!sm
->ctx
->confirm_auth_cb
)
208 return sm
->ctx
->confirm_auth_cb(sm
->ctx
->ctx
);
212 static void eapol_enable_timer_tick(struct eapol_sm
*sm
)
214 if (sm
->timer_tick_enabled
)
216 wpa_printf(MSG_DEBUG
, "EAPOL: enable timer tick");
217 eloop_cancel_timeout(eapol_port_timers_tick
, NULL
, sm
);
218 if (eloop_register_timeout(1, 0, eapol_port_timers_tick
, NULL
, sm
) == 0)
219 sm
->timer_tick_enabled
= 1;
223 SM_STATE(SUPP_PAE
, LOGOFF
)
225 SM_ENTRY(SUPP_PAE
, LOGOFF
);
226 eapol_sm_txLogoff(sm
);
227 sm
->logoffSent
= TRUE
;
228 eapol_sm_set_port_unauthorized(sm
);
232 SM_STATE(SUPP_PAE
, DISCONNECTED
)
234 SM_ENTRY(SUPP_PAE
, DISCONNECTED
);
235 sm
->sPortMode
= Auto
;
237 sm
->eapTriggerStart
= FALSE
;
238 sm
->logoffSent
= FALSE
;
239 eapol_sm_set_port_unauthorized(sm
);
240 sm
->suppAbort
= TRUE
;
242 sm
->unicast_key_received
= FALSE
;
243 sm
->broadcast_key_received
= FALSE
;
246 * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so
247 * allows the timer tick to be stopped more quickly when the port is
248 * not enabled. Since this variable is used only within HELD state,
249 * clearing it on initialization does not change actual state machine
256 SM_STATE(SUPP_PAE
, CONNECTING
)
258 int send_start
= sm
->SUPP_PAE_state
== SUPP_PAE_CONNECTING
||
259 sm
->SUPP_PAE_state
== SUPP_PAE_HELD
;
260 SM_ENTRY(SUPP_PAE
, CONNECTING
);
262 if (sm
->eapTriggerStart
)
264 if (sm
->ctx
->preauth
)
266 sm
->eapTriggerStart
= FALSE
;
269 sm
->startWhen
= sm
->startPeriod
;
273 * Do not send EAPOL-Start immediately since in most cases,
274 * Authenticator is going to start authentication immediately
275 * after association and an extra EAPOL-Start is just going to
276 * delay authentication. Use a short timeout to send the first
277 * EAPOL-Start if Authenticator does not start authentication.
279 if (sm
->conf
.wps
&& !(sm
->conf
.wps
& EAPOL_PEER_IS_WPS20_AP
)) {
280 /* Reduce latency on starting WPS negotiation. */
281 wpa_printf(MSG_DEBUG
,
282 "EAPOL: Using shorter startWhen for WPS");
288 eapol_enable_timer_tick(sm
);
289 sm
->eapolEap
= FALSE
;
291 eapol_sm_txStart(sm
);
295 SM_STATE(SUPP_PAE
, AUTHENTICATING
)
297 SM_ENTRY(SUPP_PAE
, AUTHENTICATING
);
299 sm
->suppSuccess
= FALSE
;
300 sm
->suppFail
= FALSE
;
301 sm
->suppTimeout
= FALSE
;
304 sm
->suppStart
= TRUE
;
308 SM_STATE(SUPP_PAE
, HELD
)
310 SM_ENTRY(SUPP_PAE
, HELD
);
311 sm
->heldWhile
= sm
->heldPeriod
;
312 eapol_enable_timer_tick(sm
);
313 eapol_sm_set_port_unauthorized(sm
);
314 sm
->cb_status
= EAPOL_CB_FAILURE
;
318 SM_STATE(SUPP_PAE
, AUTHENTICATED
)
320 SM_ENTRY(SUPP_PAE
, AUTHENTICATED
);
321 eapol_sm_set_port_authorized(sm
);
322 sm
->cb_status
= EAPOL_CB_SUCCESS
;
326 SM_STATE(SUPP_PAE
, RESTART
)
328 if (eapol_sm_confirm_auth(sm
)) {
329 /* Don't process restart, we are already reconnecting */
333 SM_ENTRY(SUPP_PAE
, RESTART
);
334 sm
->eapRestart
= TRUE
;
337 * Prevent EAP peer state machine from failing due to prior
338 * external EAP success notification (altSuccess=TRUE in the
339 * IDLE state could result in a transition to the FAILURE state.
341 wpa_printf(MSG_DEBUG
, "EAPOL: Clearing prior altAccept TRUE");
342 sm
->eapSuccess
= FALSE
;
343 sm
->altAccept
= FALSE
;
348 SM_STATE(SUPP_PAE
, S_FORCE_AUTH
)
350 SM_ENTRY(SUPP_PAE
, S_FORCE_AUTH
);
351 eapol_sm_set_port_authorized(sm
);
352 sm
->sPortMode
= ForceAuthorized
;
356 SM_STATE(SUPP_PAE
, S_FORCE_UNAUTH
)
358 SM_ENTRY(SUPP_PAE
, S_FORCE_UNAUTH
);
359 eapol_sm_set_port_unauthorized(sm
);
360 sm
->sPortMode
= ForceUnauthorized
;
361 eapol_sm_txLogoff(sm
);
367 if ((sm
->userLogoff
&& !sm
->logoffSent
) &&
368 !(sm
->initialize
|| !sm
->portEnabled
))
369 SM_ENTER_GLOBAL(SUPP_PAE
, LOGOFF
);
370 else if (((sm
->portControl
== Auto
) &&
371 (sm
->sPortMode
!= sm
->portControl
)) ||
372 sm
->initialize
|| !sm
->portEnabled
)
373 SM_ENTER_GLOBAL(SUPP_PAE
, DISCONNECTED
);
374 else if ((sm
->portControl
== ForceAuthorized
) &&
375 (sm
->sPortMode
!= sm
->portControl
) &&
376 !(sm
->initialize
|| !sm
->portEnabled
))
377 SM_ENTER_GLOBAL(SUPP_PAE
, S_FORCE_AUTH
);
378 else if ((sm
->portControl
== ForceUnauthorized
) &&
379 (sm
->sPortMode
!= sm
->portControl
) &&
380 !(sm
->initialize
|| !sm
->portEnabled
))
381 SM_ENTER_GLOBAL(SUPP_PAE
, S_FORCE_UNAUTH
);
382 else switch (sm
->SUPP_PAE_state
) {
383 case SUPP_PAE_UNKNOWN
:
385 case SUPP_PAE_LOGOFF
:
387 SM_ENTER(SUPP_PAE
, DISCONNECTED
);
389 case SUPP_PAE_DISCONNECTED
:
390 SM_ENTER(SUPP_PAE
, CONNECTING
);
392 case SUPP_PAE_CONNECTING
:
393 if (sm
->startWhen
== 0 && sm
->startCount
< sm
->maxStart
)
394 SM_ENTER(SUPP_PAE
, CONNECTING
);
395 else if (sm
->startWhen
== 0 &&
396 sm
->startCount
>= sm
->maxStart
&&
398 SM_ENTER(SUPP_PAE
, AUTHENTICATED
);
399 else if (sm
->eapSuccess
|| sm
->eapFail
)
400 SM_ENTER(SUPP_PAE
, AUTHENTICATING
);
401 else if (sm
->eapolEap
)
402 SM_ENTER(SUPP_PAE
, RESTART
);
403 else if (sm
->startWhen
== 0 &&
404 sm
->startCount
>= sm
->maxStart
&&
406 SM_ENTER(SUPP_PAE
, HELD
);
408 case SUPP_PAE_AUTHENTICATING
:
409 if (sm
->eapSuccess
&& !sm
->portValid
&&
410 sm
->conf
.accept_802_1x_keys
&&
411 sm
->conf
.required_keys
== 0) {
412 wpa_printf(MSG_DEBUG
, "EAPOL: IEEE 802.1X for "
413 "plaintext connection; no EAPOL-Key frames "
415 sm
->portValid
= TRUE
;
416 if (sm
->ctx
->eapol_done_cb
)
417 sm
->ctx
->eapol_done_cb(sm
->ctx
->ctx
);
419 if (sm
->eapSuccess
&& sm
->portValid
)
420 SM_ENTER(SUPP_PAE
, AUTHENTICATED
);
421 else if (sm
->eapFail
|| (sm
->keyDone
&& !sm
->portValid
))
422 SM_ENTER(SUPP_PAE
, HELD
);
423 else if (sm
->suppTimeout
)
424 SM_ENTER(SUPP_PAE
, CONNECTING
);
425 else if (sm
->eapTriggerStart
)
426 SM_ENTER(SUPP_PAE
, CONNECTING
);
429 if (sm
->heldWhile
== 0)
430 SM_ENTER(SUPP_PAE
, CONNECTING
);
431 else if (sm
->eapolEap
)
432 SM_ENTER(SUPP_PAE
, RESTART
);
434 case SUPP_PAE_AUTHENTICATED
:
435 if (sm
->eapolEap
&& sm
->portValid
)
436 SM_ENTER(SUPP_PAE
, RESTART
);
437 else if (!sm
->portValid
)
438 SM_ENTER(SUPP_PAE
, DISCONNECTED
);
440 case SUPP_PAE_RESTART
:
442 SM_ENTER(SUPP_PAE
, AUTHENTICATING
);
444 case SUPP_PAE_S_FORCE_AUTH
:
446 case SUPP_PAE_S_FORCE_UNAUTH
:
452 SM_STATE(KEY_RX
, NO_KEY_RECEIVE
)
454 SM_ENTRY(KEY_RX
, NO_KEY_RECEIVE
);
458 SM_STATE(KEY_RX
, KEY_RECEIVE
)
460 SM_ENTRY(KEY_RX
, KEY_RECEIVE
);
461 eapol_sm_processKey(sm
);
468 if (sm
->initialize
|| !sm
->portEnabled
)
469 SM_ENTER_GLOBAL(KEY_RX
, NO_KEY_RECEIVE
);
470 switch (sm
->KEY_RX_state
) {
473 case KEY_RX_NO_KEY_RECEIVE
:
475 SM_ENTER(KEY_RX
, KEY_RECEIVE
);
477 case KEY_RX_KEY_RECEIVE
:
479 SM_ENTER(KEY_RX
, KEY_RECEIVE
);
485 SM_STATE(SUPP_BE
, REQUEST
)
487 SM_ENTRY(SUPP_BE
, REQUEST
);
490 eapol_sm_getSuppRsp(sm
);
494 SM_STATE(SUPP_BE
, RESPONSE
)
496 SM_ENTRY(SUPP_BE
, RESPONSE
);
497 eapol_sm_txSuppRsp(sm
);
502 SM_STATE(SUPP_BE
, SUCCESS
)
504 SM_ENTRY(SUPP_BE
, SUCCESS
);
506 sm
->suppSuccess
= TRUE
;
508 #ifdef CONFIG_EAP_PROXY
509 if (sm
->use_eap_proxy
) {
510 if (eap_proxy_key_available(sm
->eap_proxy
)) {
511 u8
*session_id
, *emsk
;
512 size_t session_id_len
, emsk_len
;
514 /* New key received - clear IEEE 802.1X EAPOL-Key replay
516 sm
->replay_counter_valid
= FALSE
;
518 session_id
= eap_proxy_get_eap_session_id(
519 sm
->eap_proxy
, &session_id_len
);
520 emsk
= eap_proxy_get_emsk(sm
->eap_proxy
, &emsk_len
);
521 if (sm
->config
->erp
&& session_id
&& emsk
) {
522 eap_peer_erp_init(sm
->eap
, session_id
,
523 session_id_len
, emsk
,
527 bin_clear_free(emsk
, emsk_len
);
532 #endif /* CONFIG_EAP_PROXY */
534 if (eap_key_available(sm
->eap
)) {
535 /* New key received - clear IEEE 802.1X EAPOL-Key replay
537 sm
->replay_counter_valid
= FALSE
;
542 SM_STATE(SUPP_BE
, FAIL
)
544 SM_ENTRY(SUPP_BE
, FAIL
);
549 SM_STATE(SUPP_BE
, TIMEOUT
)
551 SM_ENTRY(SUPP_BE
, TIMEOUT
);
552 sm
->suppTimeout
= TRUE
;
556 SM_STATE(SUPP_BE
, IDLE
)
558 SM_ENTRY(SUPP_BE
, IDLE
);
559 sm
->suppStart
= FALSE
;
560 sm
->initial_req
= TRUE
;
564 SM_STATE(SUPP_BE
, INITIALIZE
)
566 SM_ENTRY(SUPP_BE
, INITIALIZE
);
567 eapol_sm_abortSupp(sm
);
568 sm
->suppAbort
= FALSE
;
571 * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so
572 * allows the timer tick to be stopped more quickly when the port is
573 * not enabled. Since this variable is used only within RECEIVE state,
574 * clearing it on initialization does not change actual state machine
581 SM_STATE(SUPP_BE
, RECEIVE
)
583 SM_ENTRY(SUPP_BE
, RECEIVE
);
584 sm
->authWhile
= sm
->authPeriod
;
585 eapol_enable_timer_tick(sm
);
586 sm
->eapolEap
= FALSE
;
587 sm
->eapNoResp
= FALSE
;
588 sm
->initial_req
= FALSE
;
594 if (sm
->initialize
|| sm
->suppAbort
)
595 SM_ENTER_GLOBAL(SUPP_BE
, INITIALIZE
);
596 else switch (sm
->SUPP_BE_state
) {
597 case SUPP_BE_UNKNOWN
:
599 case SUPP_BE_REQUEST
:
601 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
602 * and SUCCESS based on eapFail and eapSuccess, respectively.
603 * However, IEEE Std 802.1X-2004 is also specifying that
604 * eapNoResp should be set in conjunction with eapSuccess and
605 * eapFail which would mean that more than one of the
606 * transitions here would be activated at the same time.
607 * Skipping RESPONSE and/or RECEIVE states in these cases can
608 * cause problems and the direct transitions to do not seem
609 * correct. Because of this, the conditions for these
610 * transitions are verified only after eapNoResp. They are
611 * unlikely to be used since eapNoResp should always be set if
612 * either of eapSuccess or eapFail is set.
614 if (sm
->eapResp
&& sm
->eapNoResp
) {
615 wpa_printf(MSG_DEBUG
, "EAPOL: SUPP_BE REQUEST: both "
616 "eapResp and eapNoResp set?!");
619 SM_ENTER(SUPP_BE
, RESPONSE
);
620 else if (sm
->eapNoResp
)
621 SM_ENTER(SUPP_BE
, RECEIVE
);
622 else if (sm
->eapFail
)
623 SM_ENTER(SUPP_BE
, FAIL
);
624 else if (sm
->eapSuccess
)
625 SM_ENTER(SUPP_BE
, SUCCESS
);
627 case SUPP_BE_RESPONSE
:
628 SM_ENTER(SUPP_BE
, RECEIVE
);
630 case SUPP_BE_SUCCESS
:
631 SM_ENTER(SUPP_BE
, IDLE
);
634 SM_ENTER(SUPP_BE
, IDLE
);
636 case SUPP_BE_TIMEOUT
:
637 SM_ENTER(SUPP_BE
, IDLE
);
640 if (sm
->eapFail
&& sm
->suppStart
)
641 SM_ENTER(SUPP_BE
, FAIL
);
642 else if (sm
->eapolEap
&& sm
->suppStart
)
643 SM_ENTER(SUPP_BE
, REQUEST
);
644 else if (sm
->eapSuccess
&& sm
->suppStart
)
645 SM_ENTER(SUPP_BE
, SUCCESS
);
647 case SUPP_BE_INITIALIZE
:
648 SM_ENTER(SUPP_BE
, IDLE
);
650 case SUPP_BE_RECEIVE
:
652 SM_ENTER(SUPP_BE
, REQUEST
);
653 else if (sm
->eapFail
)
654 SM_ENTER(SUPP_BE
, FAIL
);
655 else if (sm
->authWhile
== 0)
656 SM_ENTER(SUPP_BE
, TIMEOUT
);
657 else if (sm
->eapSuccess
)
658 SM_ENTER(SUPP_BE
, SUCCESS
);
664 static void eapol_sm_txLogoff(struct eapol_sm
*sm
)
666 wpa_printf(MSG_DEBUG
, "EAPOL: txLogoff");
667 sm
->ctx
->eapol_send(sm
->ctx
->eapol_send_ctx
,
668 IEEE802_1X_TYPE_EAPOL_LOGOFF
, (u8
*) "", 0);
669 sm
->dot1xSuppEapolLogoffFramesTx
++;
670 sm
->dot1xSuppEapolFramesTx
++;
674 static void eapol_sm_txStart(struct eapol_sm
*sm
)
676 wpa_printf(MSG_DEBUG
, "EAPOL: txStart");
677 sm
->ctx
->eapol_send(sm
->ctx
->eapol_send_ctx
,
678 IEEE802_1X_TYPE_EAPOL_START
, (u8
*) "", 0);
679 sm
->dot1xSuppEapolStartFramesTx
++;
680 sm
->dot1xSuppEapolFramesTx
++;
684 #define IEEE8021X_ENCR_KEY_LEN 32
685 #define IEEE8021X_SIGN_KEY_LEN 32
687 struct eap_key_data
{
688 u8 encr_key
[IEEE8021X_ENCR_KEY_LEN
];
689 u8 sign_key
[IEEE8021X_SIGN_KEY_LEN
];
693 static void eapol_sm_processKey(struct eapol_sm
*sm
)
696 struct ieee802_1x_hdr
*hdr
;
697 struct ieee802_1x_eapol_key
*key
;
698 struct eap_key_data keydata
;
699 u8 orig_key_sign
[IEEE8021X_KEY_SIGN_LEN
], datakey
[32];
700 #ifndef CONFIG_NO_RC4
701 u8 ekey
[IEEE8021X_KEY_IV_LEN
+ IEEE8021X_ENCR_KEY_LEN
];
702 #endif /* CONFIG_NO_RC4 */
703 int key_len
, res
, sign_key_len
, encr_key_len
;
707 wpa_printf(MSG_DEBUG
, "EAPOL: processKey");
708 if (sm
->last_rx_key
== NULL
)
711 if (!sm
->conf
.accept_802_1x_keys
) {
712 wpa_printf(MSG_WARNING
, "EAPOL: Received IEEE 802.1X EAPOL-Key"
713 " even though this was not accepted - "
714 "ignoring this packet");
718 if (sm
->last_rx_key_len
< sizeof(*hdr
) + sizeof(*key
))
720 hdr
= (struct ieee802_1x_hdr
*) sm
->last_rx_key
;
721 key
= (struct ieee802_1x_eapol_key
*) (hdr
+ 1);
722 plen
= be_to_host16(hdr
->length
);
723 if (sizeof(*hdr
) + plen
> sm
->last_rx_key_len
|| plen
< sizeof(*key
)) {
724 wpa_printf(MSG_WARNING
, "EAPOL: Too short EAPOL-Key frame");
727 rx_key_length
= WPA_GET_BE16(key
->key_length
);
728 wpa_printf(MSG_DEBUG
, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
729 "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
730 hdr
->version
, hdr
->type
, be_to_host16(hdr
->length
),
731 key
->type
, rx_key_length
, key
->key_index
);
733 eapol_sm_notify_lower_layer_success(sm
, 1);
734 sign_key_len
= IEEE8021X_SIGN_KEY_LEN
;
735 encr_key_len
= IEEE8021X_ENCR_KEY_LEN
;
736 res
= eapol_sm_get_key(sm
, (u8
*) &keydata
, sizeof(keydata
));
738 wpa_printf(MSG_DEBUG
, "EAPOL: Could not get master key for "
739 "decrypting EAPOL-Key keys");
743 /* LEAP derives only 16 bytes of keying material. */
744 res
= eapol_sm_get_key(sm
, (u8
*) &keydata
, 16);
746 wpa_printf(MSG_DEBUG
, "EAPOL: Could not get LEAP "
747 "master key for decrypting EAPOL-Key keys");
752 os_memcpy(keydata
.sign_key
, keydata
.encr_key
, 16);
754 wpa_printf(MSG_DEBUG
, "EAPOL: Could not get enough master key "
755 "data for decrypting EAPOL-Key keys (res=%d)", res
);
759 /* The key replay_counter must increase when same master key */
760 if (sm
->replay_counter_valid
&&
761 os_memcmp(sm
->last_replay_counter
, key
->replay_counter
,
762 IEEE8021X_REPLAY_COUNTER_LEN
) >= 0) {
763 wpa_printf(MSG_WARNING
, "EAPOL: EAPOL-Key replay counter did "
764 "not increase - ignoring key");
765 wpa_hexdump(MSG_DEBUG
, "EAPOL: last replay counter",
766 sm
->last_replay_counter
,
767 IEEE8021X_REPLAY_COUNTER_LEN
);
768 wpa_hexdump(MSG_DEBUG
, "EAPOL: received replay counter",
769 key
->replay_counter
, IEEE8021X_REPLAY_COUNTER_LEN
);
773 /* Verify key signature (HMAC-MD5) */
774 os_memcpy(orig_key_sign
, key
->key_signature
, IEEE8021X_KEY_SIGN_LEN
);
775 os_memset(key
->key_signature
, 0, IEEE8021X_KEY_SIGN_LEN
);
776 hmac_md5(keydata
.sign_key
, sign_key_len
,
777 sm
->last_rx_key
, sizeof(*hdr
) + be_to_host16(hdr
->length
),
779 if (os_memcmp_const(orig_key_sign
, key
->key_signature
,
780 IEEE8021X_KEY_SIGN_LEN
) != 0) {
781 wpa_printf(MSG_DEBUG
, "EAPOL: Invalid key signature in "
783 os_memcpy(key
->key_signature
, orig_key_sign
,
784 IEEE8021X_KEY_SIGN_LEN
);
787 wpa_printf(MSG_DEBUG
, "EAPOL: EAPOL-Key key signature verified");
789 key_len
= plen
- sizeof(*key
);
790 if (key_len
> 32 || rx_key_length
> 32) {
791 wpa_printf(MSG_WARNING
, "EAPOL: Too long key data length %d",
792 key_len
? key_len
: rx_key_length
);
795 if (key_len
== rx_key_length
) {
798 /* otherwise unused */
800 wpa_printf(MSG_ERROR
, "EAPOL: RC4 not supported in the build");
802 #else /* CONFIG_NO_RC4 */
803 os_memcpy(ekey
, key
->key_iv
, IEEE8021X_KEY_IV_LEN
);
804 os_memcpy(ekey
+ IEEE8021X_KEY_IV_LEN
, keydata
.encr_key
,
806 os_memcpy(datakey
, key
+ 1, key_len
);
807 rc4_skip(ekey
, IEEE8021X_KEY_IV_LEN
+ encr_key_len
, 0,
809 wpa_hexdump_key(MSG_DEBUG
, "EAPOL: Decrypted(RC4) key",
811 #endif /* CONFIG_NO_RC4 */
812 } else if (key_len
== 0) {
814 * IEEE 802.1X-2004 specifies that least significant Key Length
815 * octets from MS-MPPE-Send-Key are used as the key if the key
816 * data is not present. This seems to be meaning the beginning
817 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
818 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
819 * Anyway, taking the beginning of the keying material from EAP
820 * seems to interoperate with Authenticators.
822 key_len
= rx_key_length
;
823 os_memcpy(datakey
, keydata
.encr_key
, key_len
);
824 wpa_hexdump_key(MSG_DEBUG
, "EAPOL: using part of EAP keying "
825 "material data encryption key",
828 wpa_printf(MSG_DEBUG
, "EAPOL: Invalid key data length %d "
829 "(key_length=%d)", key_len
, rx_key_length
);
833 sm
->replay_counter_valid
= TRUE
;
834 os_memcpy(sm
->last_replay_counter
, key
->replay_counter
,
835 IEEE8021X_REPLAY_COUNTER_LEN
);
837 wpa_printf(MSG_DEBUG
, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
839 key
->key_index
& IEEE8021X_KEY_INDEX_FLAG
?
840 "unicast" : "broadcast",
841 key
->key_index
& IEEE8021X_KEY_INDEX_MASK
, key_len
);
843 if (sm
->ctx
->set_wep_key
&&
844 sm
->ctx
->set_wep_key(sm
->ctx
->ctx
,
845 key
->key_index
& IEEE8021X_KEY_INDEX_FLAG
,
846 key
->key_index
& IEEE8021X_KEY_INDEX_MASK
,
847 datakey
, key_len
) < 0) {
848 wpa_printf(MSG_WARNING
, "EAPOL: Failed to set WEP key to the "
851 if (key
->key_index
& IEEE8021X_KEY_INDEX_FLAG
)
852 sm
->unicast_key_received
= TRUE
;
854 sm
->broadcast_key_received
= TRUE
;
856 if ((sm
->unicast_key_received
||
857 !(sm
->conf
.required_keys
& EAPOL_REQUIRE_KEY_UNICAST
)) &&
858 (sm
->broadcast_key_received
||
859 !(sm
->conf
.required_keys
& EAPOL_REQUIRE_KEY_BROADCAST
)))
861 wpa_printf(MSG_DEBUG
, "EAPOL: all required EAPOL-Key "
863 sm
->portValid
= TRUE
;
864 if (sm
->ctx
->eapol_done_cb
)
865 sm
->ctx
->eapol_done_cb(sm
->ctx
->ctx
);
868 #endif /* CONFIG_FIPS */
872 static void eapol_sm_getSuppRsp(struct eapol_sm
*sm
)
874 wpa_printf(MSG_DEBUG
, "EAPOL: getSuppRsp");
875 /* EAP layer processing; no special code is needed, since Supplicant
876 * Backend state machine is waiting for eapNoResp or eapResp to be set
877 * and these are only set in the EAP state machine when the processing
882 static void eapol_sm_txSuppRsp(struct eapol_sm
*sm
)
886 wpa_printf(MSG_DEBUG
, "EAPOL: txSuppRsp");
888 #ifdef CONFIG_EAP_PROXY
889 if (sm
->use_eap_proxy
) {
890 /* Get EAP Response from EAP Proxy */
891 resp
= eap_proxy_get_eapRespData(sm
->eap_proxy
);
893 wpa_printf(MSG_WARNING
, "EAPOL: txSuppRsp - EAP Proxy "
894 "response data not available");
898 #endif /* CONFIG_EAP_PROXY */
900 resp
= eap_get_eapRespData(sm
->eap
);
902 wpa_printf(MSG_WARNING
, "EAPOL: txSuppRsp - EAP response data "
907 /* Send EAP-Packet from the EAP layer to the Authenticator */
908 sm
->ctx
->eapol_send(sm
->ctx
->eapol_send_ctx
,
909 IEEE802_1X_TYPE_EAP_PACKET
, wpabuf_head(resp
),
912 /* eapRespData is not used anymore, so free it here */
916 sm
->dot1xSuppEapolReqIdFramesRx
++;
918 sm
->dot1xSuppEapolReqFramesRx
++;
919 sm
->dot1xSuppEapolRespFramesTx
++;
920 sm
->dot1xSuppEapolFramesTx
++;
924 static void eapol_sm_abortSupp(struct eapol_sm
*sm
)
926 /* release system resources that may have been allocated for the
927 * authentication session */
928 os_free(sm
->last_rx_key
);
929 sm
->last_rx_key
= NULL
;
930 wpabuf_free(sm
->eapReqData
);
931 sm
->eapReqData
= NULL
;
932 eap_sm_abort(sm
->eap
);
933 #ifdef CONFIG_EAP_PROXY
934 eap_proxy_sm_abort(sm
->eap_proxy
);
935 #endif /* CONFIG_EAP_PROXY */
939 static void eapol_sm_step_timeout(void *eloop_ctx
, void *timeout_ctx
)
941 eapol_sm_step(timeout_ctx
);
945 static void eapol_sm_set_port_authorized(struct eapol_sm
*sm
)
949 cb
= sm
->suppPortStatus
!= Authorized
|| sm
->force_authorized_update
;
950 sm
->force_authorized_update
= FALSE
;
951 sm
->suppPortStatus
= Authorized
;
952 if (cb
&& sm
->ctx
->port_cb
)
953 sm
->ctx
->port_cb(sm
->ctx
->ctx
, 1);
957 static void eapol_sm_set_port_unauthorized(struct eapol_sm
*sm
)
961 cb
= sm
->suppPortStatus
!= Unauthorized
|| sm
->force_authorized_update
;
962 sm
->force_authorized_update
= FALSE
;
963 sm
->suppPortStatus
= Unauthorized
;
964 if (cb
&& sm
->ctx
->port_cb
)
965 sm
->ctx
->port_cb(sm
->ctx
->ctx
, 0);
970 * eapol_sm_step - EAPOL state machine step function
971 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
973 * This function is called to notify the state machine about changed external
974 * variables. It will step through the EAPOL state machines in loop to process
975 * all triggered state changes.
977 void eapol_sm_step(struct eapol_sm
*sm
)
981 /* In theory, it should be ok to run this in loop until !changed.
982 * However, it is better to use a limit on number of iterations to
983 * allow events (e.g., SIGTERM) to stop the program cleanly if the
984 * state machine were to generate a busy loop. */
985 for (i
= 0; i
< 100; i
++) {
987 SM_STEP_RUN(SUPP_PAE
);
989 SM_STEP_RUN(SUPP_BE
);
990 #ifdef CONFIG_EAP_PROXY
991 if (sm
->use_eap_proxy
) {
992 /* Drive the EAP proxy state machine */
993 if (eap_proxy_sm_step(sm
->eap_proxy
, sm
->eap
))
996 #endif /* CONFIG_EAP_PROXY */
997 if (eap_peer_sm_step(sm
->eap
))
1004 /* restart EAPOL state machine step from timeout call in order
1005 * to allow other events to be processed. */
1006 eloop_cancel_timeout(eapol_sm_step_timeout
, NULL
, sm
);
1007 eloop_register_timeout(0, 0, eapol_sm_step_timeout
, NULL
, sm
);
1010 if (sm
->ctx
->cb
&& sm
->cb_status
!= EAPOL_CB_IN_PROGRESS
) {
1011 enum eapol_supp_result result
;
1012 if (sm
->cb_status
== EAPOL_CB_SUCCESS
)
1013 result
= EAPOL_SUPP_RESULT_SUCCESS
;
1014 else if (eap_peer_was_failure_expected(sm
->eap
))
1015 result
= EAPOL_SUPP_RESULT_EXPECTED_FAILURE
;
1017 result
= EAPOL_SUPP_RESULT_FAILURE
;
1018 sm
->cb_status
= EAPOL_CB_IN_PROGRESS
;
1019 sm
->ctx
->cb(sm
, result
, sm
->ctx
->cb_ctx
);
1024 #ifdef CONFIG_CTRL_IFACE
1025 static const char *eapol_supp_pae_state(int state
)
1028 case SUPP_PAE_LOGOFF
:
1030 case SUPP_PAE_DISCONNECTED
:
1031 return "DISCONNECTED";
1032 case SUPP_PAE_CONNECTING
:
1033 return "CONNECTING";
1034 case SUPP_PAE_AUTHENTICATING
:
1035 return "AUTHENTICATING";
1038 case SUPP_PAE_AUTHENTICATED
:
1039 return "AUTHENTICATED";
1040 case SUPP_PAE_RESTART
:
1048 static const char *eapol_supp_be_state(int state
)
1051 case SUPP_BE_REQUEST
:
1053 case SUPP_BE_RESPONSE
:
1055 case SUPP_BE_SUCCESS
:
1059 case SUPP_BE_TIMEOUT
:
1063 case SUPP_BE_INITIALIZE
:
1064 return "INITIALIZE";
1065 case SUPP_BE_RECEIVE
:
1073 static const char * eapol_port_status(PortStatus status
)
1075 if (status
== Authorized
)
1076 return "Authorized";
1078 return "Unauthorized";
1080 #endif /* CONFIG_CTRL_IFACE */
1083 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1084 static const char * eapol_port_control(PortControl ctrl
)
1089 case ForceUnauthorized
:
1090 return "ForceUnauthorized";
1091 case ForceAuthorized
:
1092 return "ForceAuthorized";
1097 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1101 * eapol_sm_configure - Set EAPOL variables
1102 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1103 * @heldPeriod: dot1xSuppHeldPeriod
1104 * @authPeriod: dot1xSuppAuthPeriod
1105 * @startPeriod: dot1xSuppStartPeriod
1106 * @maxStart: dot1xSuppMaxStart
1108 * Set configurable EAPOL state machine variables. Each variable can be set to
1109 * the given value or ignored if set to -1 (to set only some of the variables).
1111 void eapol_sm_configure(struct eapol_sm
*sm
, int heldPeriod
, int authPeriod
,
1112 int startPeriod
, int maxStart
)
1116 if (heldPeriod
>= 0)
1117 sm
->heldPeriod
= heldPeriod
;
1118 if (authPeriod
>= 0)
1119 sm
->authPeriod
= authPeriod
;
1120 if (startPeriod
>= 0)
1121 sm
->startPeriod
= startPeriod
;
1123 sm
->maxStart
= maxStart
;
1128 * eapol_sm_get_method_name - Get EAPOL method name
1129 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1130 * Returns: Static string containing name of current eap method or NULL
1132 const char * eapol_sm_get_method_name(struct eapol_sm
*sm
)
1134 if (sm
->SUPP_PAE_state
!= SUPP_PAE_AUTHENTICATED
||
1135 sm
->suppPortStatus
!= Authorized
)
1138 return eap_sm_get_method_name(sm
->eap
);
1142 #ifdef CONFIG_CTRL_IFACE
1144 * eapol_sm_get_status - Get EAPOL state machine status
1145 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1146 * @buf: Buffer for status information
1147 * @buflen: Maximum buffer length
1148 * @verbose: Whether to include verbose status information
1149 * Returns: Number of bytes written to buf.
1151 * Query EAPOL state machine for status information. This function fills in a
1152 * text area with current status information from the EAPOL state machine. If
1153 * the buffer (buf) is not large enough, status information will be truncated
1154 * to fit the buffer.
1156 int eapol_sm_get_status(struct eapol_sm
*sm
, char *buf
, size_t buflen
,
1163 len
= os_snprintf(buf
, buflen
,
1164 "Supplicant PAE state=%s\n"
1165 "suppPortStatus=%s\n",
1166 eapol_supp_pae_state(sm
->SUPP_PAE_state
),
1167 eapol_port_status(sm
->suppPortStatus
));
1168 if (os_snprintf_error(buflen
, len
))
1172 ret
= os_snprintf(buf
+ len
, buflen
- len
,
1178 "Supplicant Backend state=%s\n",
1183 eapol_port_control(sm
->portControl
),
1184 eapol_supp_be_state(sm
->SUPP_BE_state
));
1185 if (os_snprintf_error(buflen
- len
, ret
))
1190 #ifdef CONFIG_EAP_PROXY
1191 if (sm
->use_eap_proxy
)
1192 len
+= eap_proxy_sm_get_status(sm
->eap_proxy
,
1193 buf
+ len
, buflen
- len
,
1196 #endif /* CONFIG_EAP_PROXY */
1197 len
+= eap_sm_get_status(sm
->eap
, buf
+ len
, buflen
- len
, verbose
);
1204 * eapol_sm_get_mib - Get EAPOL state machine MIBs
1205 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1206 * @buf: Buffer for MIB information
1207 * @buflen: Maximum buffer length
1208 * Returns: Number of bytes written to buf.
1210 * Query EAPOL state machine for MIB information. This function fills in a
1211 * text area with current MIB information from the EAPOL state machine. If
1212 * the buffer (buf) is not large enough, MIB information will be truncated to
1215 int eapol_sm_get_mib(struct eapol_sm
*sm
, char *buf
, size_t buflen
)
1222 ret
= os_snprintf(buf
, buflen
,
1223 "dot1xSuppPaeState=%d\n"
1224 "dot1xSuppHeldPeriod=%u\n"
1225 "dot1xSuppAuthPeriod=%u\n"
1226 "dot1xSuppStartPeriod=%u\n"
1227 "dot1xSuppMaxStart=%u\n"
1228 "dot1xSuppSuppControlledPortStatus=%s\n"
1229 "dot1xSuppBackendPaeState=%d\n",
1235 sm
->suppPortStatus
== Authorized
?
1236 "Authorized" : "Unauthorized",
1239 if (os_snprintf_error(buflen
, ret
))
1243 ret
= os_snprintf(buf
+ len
, buflen
- len
,
1244 "dot1xSuppEapolFramesRx=%u\n"
1245 "dot1xSuppEapolFramesTx=%u\n"
1246 "dot1xSuppEapolStartFramesTx=%u\n"
1247 "dot1xSuppEapolLogoffFramesTx=%u\n"
1248 "dot1xSuppEapolRespFramesTx=%u\n"
1249 "dot1xSuppEapolReqIdFramesRx=%u\n"
1250 "dot1xSuppEapolReqFramesRx=%u\n"
1251 "dot1xSuppInvalidEapolFramesRx=%u\n"
1252 "dot1xSuppEapLengthErrorFramesRx=%u\n"
1253 "dot1xSuppLastEapolFrameVersion=%u\n"
1254 "dot1xSuppLastEapolFrameSource=" MACSTR
"\n",
1255 sm
->dot1xSuppEapolFramesRx
,
1256 sm
->dot1xSuppEapolFramesTx
,
1257 sm
->dot1xSuppEapolStartFramesTx
,
1258 sm
->dot1xSuppEapolLogoffFramesTx
,
1259 sm
->dot1xSuppEapolRespFramesTx
,
1260 sm
->dot1xSuppEapolReqIdFramesRx
,
1261 sm
->dot1xSuppEapolReqFramesRx
,
1262 sm
->dot1xSuppInvalidEapolFramesRx
,
1263 sm
->dot1xSuppEapLengthErrorFramesRx
,
1264 sm
->dot1xSuppLastEapolFrameVersion
,
1265 MAC2STR(sm
->dot1xSuppLastEapolFrameSource
));
1267 if (os_snprintf_error(buflen
- len
, ret
))
1273 #endif /* CONFIG_CTRL_IFACE */
1277 * eapol_sm_rx_eapol - Process received EAPOL frames
1278 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1279 * @src: Source MAC address of the EAPOL packet
1280 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
1281 * @len: Length of the EAPOL frame
1282 * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
1285 int eapol_sm_rx_eapol(struct eapol_sm
*sm
, const u8
*src
, const u8
*buf
,
1288 const struct ieee802_1x_hdr
*hdr
;
1289 const struct ieee802_1x_eapol_key
*key
;
1296 sm
->dot1xSuppEapolFramesRx
++;
1297 if (len
< sizeof(*hdr
)) {
1298 sm
->dot1xSuppInvalidEapolFramesRx
++;
1301 hdr
= (const struct ieee802_1x_hdr
*) buf
;
1302 sm
->dot1xSuppLastEapolFrameVersion
= hdr
->version
;
1303 os_memcpy(sm
->dot1xSuppLastEapolFrameSource
, src
, ETH_ALEN
);
1304 if (hdr
->version
< EAPOL_VERSION
) {
1305 /* TODO: backwards compatibility */
1307 plen
= be_to_host16(hdr
->length
);
1308 if (plen
> len
- sizeof(*hdr
)) {
1309 sm
->dot1xSuppEapLengthErrorFramesRx
++;
1313 if (sm
->conf
.wps
&& sm
->conf
.workaround
&&
1314 plen
< len
- sizeof(*hdr
) &&
1315 hdr
->type
== IEEE802_1X_TYPE_EAP_PACKET
&&
1316 len
- sizeof(*hdr
) > sizeof(struct eap_hdr
)) {
1317 const struct eap_hdr
*ehdr
=
1318 (const struct eap_hdr
*) (hdr
+ 1);
1321 elen
= be_to_host16(ehdr
->length
);
1322 if (elen
> plen
&& elen
<= len
- sizeof(*hdr
)) {
1324 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
1325 * packets with too short EAPOL header length field
1326 * (14 octets). This is fixed in firmware Ver.1.49.
1327 * As a workaround, fix the EAPOL header based on the
1328 * correct length in the EAP packet.
1330 wpa_printf(MSG_DEBUG
, "EAPOL: Workaround - fix EAPOL "
1331 "payload length based on EAP header: "
1332 "%d -> %d", (int) plen
, elen
);
1336 #endif /* CONFIG_WPS */
1337 data_len
= plen
+ sizeof(*hdr
);
1339 switch (hdr
->type
) {
1340 case IEEE802_1X_TYPE_EAP_PACKET
:
1341 if (sm
->conf
.workaround
) {
1343 * An AP has been reported to send out EAP message with
1344 * undocumented code 10 at some point near the
1345 * completion of EAP authentication. This can result in
1346 * issues with the unexpected EAP message triggering
1347 * restart of EAPOL authentication. Avoid this by
1348 * skipping the message without advancing the state
1351 const struct eap_hdr
*ehdr
=
1352 (const struct eap_hdr
*) (hdr
+ 1);
1353 if (plen
>= sizeof(*ehdr
) && ehdr
->code
== 10) {
1354 wpa_printf(MSG_DEBUG
, "EAPOL: Ignore EAP packet with unknown code 10");
1359 if (sm
->cached_pmk
) {
1360 /* Trying to use PMKSA caching, but Authenticator did
1361 * not seem to have a matching entry. Need to restart
1362 * EAPOL state machines.
1364 eapol_sm_abort_cached(sm
);
1366 wpabuf_free(sm
->eapReqData
);
1367 sm
->eapReqData
= wpabuf_alloc_copy(hdr
+ 1, plen
);
1368 if (sm
->eapReqData
) {
1369 wpa_printf(MSG_DEBUG
, "EAPOL: Received EAP-Packet "
1371 sm
->eapolEap
= TRUE
;
1372 #ifdef CONFIG_EAP_PROXY
1373 if (sm
->use_eap_proxy
) {
1374 eap_proxy_packet_update(
1376 wpabuf_mhead_u8(sm
->eapReqData
),
1377 wpabuf_len(sm
->eapReqData
));
1378 wpa_printf(MSG_DEBUG
, "EAPOL: eap_proxy "
1381 #endif /* CONFIG_EAP_PROXY */
1385 case IEEE802_1X_TYPE_EAPOL_KEY
:
1386 if (plen
< sizeof(*key
)) {
1387 wpa_printf(MSG_DEBUG
, "EAPOL: Too short EAPOL-Key "
1391 key
= (const struct ieee802_1x_eapol_key
*) (hdr
+ 1);
1392 if (key
->type
== EAPOL_KEY_TYPE_WPA
||
1393 key
->type
== EAPOL_KEY_TYPE_RSN
) {
1394 /* WPA Supplicant takes care of this frame. */
1395 wpa_printf(MSG_DEBUG
, "EAPOL: Ignoring WPA EAPOL-Key "
1396 "frame in EAPOL state machines");
1400 if (key
->type
!= EAPOL_KEY_TYPE_RC4
) {
1401 wpa_printf(MSG_DEBUG
, "EAPOL: Ignored unknown "
1402 "EAPOL-Key type %d", key
->type
);
1405 os_free(sm
->last_rx_key
);
1406 sm
->last_rx_key
= os_malloc(data_len
);
1407 if (sm
->last_rx_key
) {
1408 wpa_printf(MSG_DEBUG
, "EAPOL: Received EAPOL-Key "
1410 os_memcpy(sm
->last_rx_key
, buf
, data_len
);
1411 sm
->last_rx_key_len
= data_len
;
1416 #ifdef CONFIG_MACSEC
1417 case IEEE802_1X_TYPE_EAPOL_MKA
:
1418 wpa_printf(MSG_EXCESSIVE
,
1419 "EAPOL type %d will be handled by MKA",
1422 #endif /* CONFIG_MACSEC */
1424 wpa_printf(MSG_DEBUG
, "EAPOL: Received unknown EAPOL type %d",
1426 sm
->dot1xSuppInvalidEapolFramesRx
++;
1435 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
1436 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1438 * Notify EAPOL state machine about transmitted EAPOL packet from an external
1439 * component, e.g., WPA. This will update the statistics.
1441 void eapol_sm_notify_tx_eapol_key(struct eapol_sm
*sm
)
1444 sm
->dot1xSuppEapolFramesTx
++;
1449 * eapol_sm_notify_portEnabled - Notification about portEnabled change
1450 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1451 * @enabled: New portEnabled value
1453 * Notify EAPOL state machine about new portEnabled value.
1455 void eapol_sm_notify_portEnabled(struct eapol_sm
*sm
, Boolean enabled
)
1459 wpa_printf(MSG_DEBUG
, "EAPOL: External notification - "
1460 "portEnabled=%d", enabled
);
1461 if (sm
->portEnabled
!= enabled
)
1462 sm
->force_authorized_update
= TRUE
;
1463 sm
->portEnabled
= enabled
;
1469 * eapol_sm_notify_portValid - Notification about portValid change
1470 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1471 * @valid: New portValid value
1473 * Notify EAPOL state machine about new portValid value.
1475 void eapol_sm_notify_portValid(struct eapol_sm
*sm
, Boolean valid
)
1479 wpa_printf(MSG_DEBUG
, "EAPOL: External notification - "
1480 "portValid=%d", valid
);
1481 sm
->portValid
= valid
;
1487 * eapol_sm_notify_eap_success - Notification of external EAP success trigger
1488 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1489 * @success: %TRUE = set success, %FALSE = clear success
1491 * Notify the EAPOL state machine that external event has forced EAP state to
1492 * success (success = %TRUE). This can be cleared by setting success = %FALSE.
1494 * This function is called to update EAP state when WPA-PSK key handshake has
1495 * been completed successfully since WPA-PSK does not use EAP state machine.
1497 void eapol_sm_notify_eap_success(struct eapol_sm
*sm
, Boolean success
)
1501 wpa_printf(MSG_DEBUG
, "EAPOL: External notification - "
1502 "EAP success=%d", success
);
1503 sm
->eapSuccess
= success
;
1504 sm
->altAccept
= success
;
1506 eap_notify_success(sm
->eap
);
1512 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
1513 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1514 * @fail: %TRUE = set failure, %FALSE = clear failure
1516 * Notify EAPOL state machine that external event has forced EAP state to
1517 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1519 void eapol_sm_notify_eap_fail(struct eapol_sm
*sm
, Boolean fail
)
1523 wpa_printf(MSG_DEBUG
, "EAPOL: External notification - "
1524 "EAP fail=%d", fail
);
1526 sm
->altReject
= fail
;
1532 * eapol_sm_notify_config - Notification of EAPOL configuration change
1533 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1534 * @config: Pointer to current network EAP configuration
1535 * @conf: Pointer to EAPOL configuration data
1537 * Notify EAPOL state machine that configuration has changed. config will be
1538 * stored as a backpointer to network configuration. This can be %NULL to clear
1539 * the stored pointed. conf will be copied to local EAPOL/EAP configuration
1540 * data. If conf is %NULL, this part of the configuration change will be
1543 void eapol_sm_notify_config(struct eapol_sm
*sm
,
1544 struct eap_peer_config
*config
,
1545 const struct eapol_config
*conf
)
1550 sm
->config
= config
;
1551 #ifdef CONFIG_EAP_PROXY
1552 sm
->use_eap_proxy
= eap_proxy_notify_config(sm
->eap_proxy
, config
) > 0;
1553 #endif /* CONFIG_EAP_PROXY */
1558 sm
->conf
.accept_802_1x_keys
= conf
->accept_802_1x_keys
;
1559 sm
->conf
.required_keys
= conf
->required_keys
;
1560 sm
->conf
.fast_reauth
= conf
->fast_reauth
;
1561 sm
->conf
.workaround
= conf
->workaround
;
1562 sm
->conf
.wps
= conf
->wps
;
1563 #ifdef CONFIG_EAP_PROXY
1564 if (sm
->use_eap_proxy
) {
1565 /* Using EAP Proxy, so skip EAP state machine update */
1568 #endif /* CONFIG_EAP_PROXY */
1570 eap_set_fast_reauth(sm
->eap
, conf
->fast_reauth
);
1571 eap_set_workaround(sm
->eap
, conf
->workaround
);
1572 eap_set_force_disabled(sm
->eap
, conf
->eap_disabled
);
1573 eap_set_external_sim(sm
->eap
, conf
->external_sim
);
1579 * eapol_sm_get_key - Get master session key (MSK) from EAP
1580 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1581 * @key: Pointer for key buffer
1582 * @len: Number of bytes to copy to key
1583 * Returns: 0 on success (len of key available), maximum available key len
1584 * (>0) if key is available but it is shorter than len, or -1 on failure.
1586 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
1587 * is available only after a successful authentication.
1589 int eapol_sm_get_key(struct eapol_sm
*sm
, u8
*key
, size_t len
)
1594 #ifdef CONFIG_EAP_PROXY
1595 if (sm
&& sm
->use_eap_proxy
) {
1596 /* Get key from EAP proxy */
1597 if (sm
== NULL
|| !eap_proxy_key_available(sm
->eap_proxy
)) {
1598 wpa_printf(MSG_DEBUG
, "EAPOL: EAP key not available");
1601 eap_key
= eap_proxy_get_eapKeyData(sm
->eap_proxy
, &eap_len
);
1602 if (eap_key
== NULL
) {
1603 wpa_printf(MSG_DEBUG
, "EAPOL: Failed to get "
1609 #endif /* CONFIG_EAP_PROXY */
1610 if (sm
== NULL
|| !eap_key_available(sm
->eap
)) {
1611 wpa_printf(MSG_DEBUG
, "EAPOL: EAP key not available");
1614 eap_key
= eap_get_eapKeyData(sm
->eap
, &eap_len
);
1615 if (eap_key
== NULL
) {
1616 wpa_printf(MSG_DEBUG
, "EAPOL: Failed to get eapKeyData");
1619 #ifdef CONFIG_EAP_PROXY
1621 #endif /* CONFIG_EAP_PROXY */
1622 if (len
> eap_len
) {
1623 wpa_printf(MSG_DEBUG
, "EAPOL: Requested key length (%lu) not "
1624 "available (len=%lu)",
1625 (unsigned long) len
, (unsigned long) eap_len
);
1628 os_memcpy(key
, eap_key
, len
);
1629 wpa_printf(MSG_DEBUG
, "EAPOL: Successfully fetched key (len=%lu)",
1630 (unsigned long) len
);
1636 * eapol_sm_get_session_id - Get EAP Session-Id
1637 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1638 * @len: Pointer to variable that will be set to number of bytes in the session
1639 * Returns: Pointer to the EAP Session-Id or %NULL on failure
1641 * The Session-Id is available only after a successful authentication.
1643 const u8
* eapol_sm_get_session_id(struct eapol_sm
*sm
, size_t *len
)
1645 if (sm
== NULL
|| !eap_key_available(sm
->eap
)) {
1646 wpa_printf(MSG_DEBUG
, "EAPOL: EAP Session-Id not available");
1649 return eap_get_eapSessionId(sm
->eap
, len
);
1654 * eapol_sm_notify_logoff - Notification of logon/logoff commands
1655 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1656 * @logoff: Whether command was logoff
1658 * Notify EAPOL state machines that user requested logon/logoff.
1660 void eapol_sm_notify_logoff(struct eapol_sm
*sm
, Boolean logoff
)
1663 sm
->userLogoff
= logoff
;
1665 /* If there is a delayed txStart queued, start now. */
1674 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
1675 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1677 * Notify EAPOL state machines that PMKSA caching was successful. This is used
1678 * to move EAPOL and EAP state machines into authenticated/successful state.
1680 void eapol_sm_notify_cached(struct eapol_sm
*sm
)
1684 wpa_printf(MSG_DEBUG
, "EAPOL: PMKSA caching was used - skip EAPOL");
1685 sm
->eapSuccess
= TRUE
;
1686 eap_notify_success(sm
->eap
);
1692 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
1693 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1695 * Notify EAPOL state machines if PMKSA caching is used.
1697 void eapol_sm_notify_pmkid_attempt(struct eapol_sm
*sm
)
1701 wpa_printf(MSG_DEBUG
, "RSN: Trying to use cached PMKSA");
1702 sm
->cached_pmk
= TRUE
;
1706 static void eapol_sm_abort_cached(struct eapol_sm
*sm
)
1708 wpa_printf(MSG_DEBUG
, "RSN: Authenticator did not accept PMKID, "
1709 "doing full EAP authentication");
1712 sm
->cached_pmk
= FALSE
;
1713 sm
->SUPP_PAE_state
= SUPP_PAE_CONNECTING
;
1714 eapol_sm_set_port_unauthorized(sm
);
1716 /* Make sure we do not start sending EAPOL-Start frames first, but
1717 * instead move to RESTART state to start EAPOL authentication. */
1719 eapol_enable_timer_tick(sm
);
1721 if (sm
->ctx
->aborted_cached
)
1722 sm
->ctx
->aborted_cached(sm
->ctx
->ctx
);
1727 * eapol_sm_register_scard_ctx - Notification of smart card context
1728 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1729 * @ctx: Context data for smart card operations
1731 * Notify EAPOL state machines of context data for smart card operations. This
1732 * context data will be used as a parameter for scard_*() functions.
1734 void eapol_sm_register_scard_ctx(struct eapol_sm
*sm
, void *ctx
)
1737 sm
->ctx
->scard_ctx
= ctx
;
1738 eap_register_scard_ctx(sm
->eap
, ctx
);
1744 * eapol_sm_notify_portControl - Notification of portControl changes
1745 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1746 * @portControl: New value for portControl variable
1748 * Notify EAPOL state machines that portControl variable has changed.
1750 void eapol_sm_notify_portControl(struct eapol_sm
*sm
, PortControl portControl
)
1754 wpa_printf(MSG_DEBUG
, "EAPOL: External notification - "
1755 "portControl=%s", eapol_port_control(portControl
));
1756 sm
->portControl
= portControl
;
1762 * eapol_sm_notify_ctrl_attached - Notification of attached monitor
1763 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1765 * Notify EAPOL state machines that a monitor was attached to the control
1766 * interface to trigger re-sending of pending requests for user input.
1768 void eapol_sm_notify_ctrl_attached(struct eapol_sm
*sm
)
1772 eap_sm_notify_ctrl_attached(sm
->eap
);
1777 * eapol_sm_notify_ctrl_response - Notification of received user input
1778 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1780 * Notify EAPOL state machines that a control response, i.e., user
1781 * input, was received in order to trigger retrying of a pending EAP request.
1783 void eapol_sm_notify_ctrl_response(struct eapol_sm
*sm
)
1787 if (sm
->eapReqData
&& !sm
->eapReq
) {
1788 wpa_printf(MSG_DEBUG
, "EAPOL: received control response (user "
1789 "input) notification - retrying pending EAP "
1791 sm
->eapolEap
= TRUE
;
1799 * eapol_sm_request_reauth - Request reauthentication
1800 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1802 * This function can be used to request EAPOL reauthentication, e.g., when the
1803 * current PMKSA entry is nearing expiration.
1805 void eapol_sm_request_reauth(struct eapol_sm
*sm
)
1807 if (sm
== NULL
|| sm
->SUPP_PAE_state
!= SUPP_PAE_AUTHENTICATED
)
1809 eapol_sm_txStart(sm
);
1814 * eapol_sm_notify_lower_layer_success - Notification of lower layer success
1815 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1816 * @in_eapol_sm: Whether the caller is already running inside EAPOL state
1817 * machine loop (eapol_sm_step())
1819 * Notify EAPOL (and EAP) state machines that a lower layer has detected a
1820 * successful authentication. This is used to recover from dropped EAP-Success
1823 void eapol_sm_notify_lower_layer_success(struct eapol_sm
*sm
, int in_eapol_sm
)
1827 eap_notify_lower_layer_success(sm
->eap
);
1834 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
1835 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1837 void eapol_sm_invalidate_cached_session(struct eapol_sm
*sm
)
1840 eap_invalidate_cached_session(sm
->eap
);
1844 static struct eap_peer_config
* eapol_sm_get_config(void *ctx
)
1846 struct eapol_sm
*sm
= ctx
;
1847 return sm
? sm
->config
: NULL
;
1851 static struct wpabuf
* eapol_sm_get_eapReqData(void *ctx
)
1853 struct eapol_sm
*sm
= ctx
;
1854 if (sm
== NULL
|| sm
->eapReqData
== NULL
)
1857 return sm
->eapReqData
;
1861 static Boolean
eapol_sm_get_bool(void *ctx
, enum eapol_bool_var variable
)
1863 struct eapol_sm
*sm
= ctx
;
1867 case EAPOL_eapSuccess
:
1868 return sm
->eapSuccess
;
1869 case EAPOL_eapRestart
:
1870 return sm
->eapRestart
;
1875 case EAPOL_eapNoResp
:
1876 return sm
->eapNoResp
;
1879 case EAPOL_portEnabled
:
1880 return sm
->portEnabled
;
1881 case EAPOL_altAccept
:
1882 return sm
->altAccept
;
1883 case EAPOL_altReject
:
1884 return sm
->altReject
;
1885 case EAPOL_eapTriggerStart
:
1886 return sm
->eapTriggerStart
;
1892 static void eapol_sm_set_bool(void *ctx
, enum eapol_bool_var variable
,
1895 struct eapol_sm
*sm
= ctx
;
1899 case EAPOL_eapSuccess
:
1900 sm
->eapSuccess
= value
;
1902 case EAPOL_eapRestart
:
1903 sm
->eapRestart
= value
;
1906 sm
->eapFail
= value
;
1909 sm
->eapResp
= value
;
1911 case EAPOL_eapNoResp
:
1912 sm
->eapNoResp
= value
;
1917 case EAPOL_portEnabled
:
1918 sm
->portEnabled
= value
;
1920 case EAPOL_altAccept
:
1921 sm
->altAccept
= value
;
1923 case EAPOL_altReject
:
1924 sm
->altReject
= value
;
1926 case EAPOL_eapTriggerStart
:
1927 sm
->eapTriggerStart
= value
;
1933 static unsigned int eapol_sm_get_int(void *ctx
, enum eapol_int_var variable
)
1935 struct eapol_sm
*sm
= ctx
;
1939 case EAPOL_idleWhile
:
1940 return sm
->idleWhile
;
1946 static void eapol_sm_set_int(void *ctx
, enum eapol_int_var variable
,
1949 struct eapol_sm
*sm
= ctx
;
1953 case EAPOL_idleWhile
:
1954 sm
->idleWhile
= value
;
1955 if (sm
->idleWhile
> 0)
1956 eapol_enable_timer_tick(sm
);
1962 static void eapol_sm_set_config_blob(void *ctx
, struct wpa_config_blob
*blob
)
1964 #ifndef CONFIG_NO_CONFIG_BLOBS
1965 struct eapol_sm
*sm
= ctx
;
1966 if (sm
&& sm
->ctx
&& sm
->ctx
->set_config_blob
)
1967 sm
->ctx
->set_config_blob(sm
->ctx
->ctx
, blob
);
1968 #endif /* CONFIG_NO_CONFIG_BLOBS */
1972 static const struct wpa_config_blob
*
1973 eapol_sm_get_config_blob(void *ctx
, const char *name
)
1975 #ifndef CONFIG_NO_CONFIG_BLOBS
1976 struct eapol_sm
*sm
= ctx
;
1977 if (sm
&& sm
->ctx
&& sm
->ctx
->get_config_blob
)
1978 return sm
->ctx
->get_config_blob(sm
->ctx
->ctx
, name
);
1981 #else /* CONFIG_NO_CONFIG_BLOBS */
1983 #endif /* CONFIG_NO_CONFIG_BLOBS */
1987 static void eapol_sm_notify_pending(void *ctx
)
1989 struct eapol_sm
*sm
= ctx
;
1992 if (sm
->eapReqData
&& !sm
->eapReq
) {
1993 wpa_printf(MSG_DEBUG
, "EAPOL: received notification from EAP "
1994 "state machine - retrying pending EAP Request");
1995 sm
->eapolEap
= TRUE
;
2002 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
2003 static void eapol_sm_eap_param_needed(void *ctx
, enum wpa_ctrl_req_type field
,
2006 struct eapol_sm
*sm
= ctx
;
2007 wpa_printf(MSG_DEBUG
, "EAPOL: EAP parameter needed");
2008 if (sm
->ctx
->eap_param_needed
)
2009 sm
->ctx
->eap_param_needed(sm
->ctx
->ctx
, field
, txt
);
2011 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
2012 #define eapol_sm_eap_param_needed NULL
2013 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
2015 static void eapol_sm_notify_cert(void *ctx
, struct tls_cert_data
*cert
,
2016 const char *cert_hash
)
2018 struct eapol_sm
*sm
= ctx
;
2019 if (sm
->ctx
->cert_cb
)
2020 sm
->ctx
->cert_cb(sm
->ctx
->ctx
, cert
, cert_hash
);
2024 static void eapol_sm_notify_status(void *ctx
, const char *status
,
2025 const char *parameter
)
2027 struct eapol_sm
*sm
= ctx
;
2029 if (sm
->ctx
->status_cb
)
2030 sm
->ctx
->status_cb(sm
->ctx
->ctx
, status
, parameter
);
2034 static void eapol_sm_notify_eap_error(void *ctx
, int error_code
)
2036 struct eapol_sm
*sm
= ctx
;
2038 if (sm
->ctx
->eap_error_cb
)
2039 sm
->ctx
->eap_error_cb(sm
->ctx
->ctx
, error_code
);
2043 #ifdef CONFIG_EAP_PROXY
2045 static void eapol_sm_eap_proxy_cb(void *ctx
)
2047 struct eapol_sm
*sm
= ctx
;
2049 if (sm
->ctx
->eap_proxy_cb
)
2050 sm
->ctx
->eap_proxy_cb(sm
->ctx
->ctx
);
2055 eapol_sm_eap_proxy_notify_sim_status(void *ctx
,
2056 enum eap_proxy_sim_state sim_state
)
2058 struct eapol_sm
*sm
= ctx
;
2060 if (sm
->ctx
->eap_proxy_notify_sim_status
)
2061 sm
->ctx
->eap_proxy_notify_sim_status(sm
->ctx
->ctx
, sim_state
);
2064 #endif /* CONFIG_EAP_PROXY */
2067 static void eapol_sm_set_anon_id(void *ctx
, const u8
*id
, size_t len
)
2069 struct eapol_sm
*sm
= ctx
;
2071 if (sm
->ctx
->set_anon_id
)
2072 sm
->ctx
->set_anon_id(sm
->ctx
->ctx
, id
, len
);
2076 static const struct eapol_callbacks eapol_cb
=
2078 eapol_sm_get_config
,
2083 eapol_sm_get_eapReqData
,
2084 eapol_sm_set_config_blob
,
2085 eapol_sm_get_config_blob
,
2086 eapol_sm_notify_pending
,
2087 eapol_sm_eap_param_needed
,
2088 eapol_sm_notify_cert
,
2089 eapol_sm_notify_status
,
2090 eapol_sm_notify_eap_error
,
2091 #ifdef CONFIG_EAP_PROXY
2092 eapol_sm_eap_proxy_cb
,
2093 eapol_sm_eap_proxy_notify_sim_status
,
2094 eapol_sm_get_eap_proxy_imsi
,
2095 #endif /* CONFIG_EAP_PROXY */
2096 eapol_sm_set_anon_id
2101 * eapol_sm_init - Initialize EAPOL state machine
2102 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
2103 * and EAPOL state machine will free it in eapol_sm_deinit()
2104 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
2106 * Allocate and initialize an EAPOL state machine.
2108 struct eapol_sm
*eapol_sm_init(struct eapol_ctx
*ctx
)
2110 struct eapol_sm
*sm
;
2111 struct eap_config conf
;
2112 sm
= os_zalloc(sizeof(*sm
));
2117 sm
->portControl
= Auto
;
2119 /* Supplicant PAE state machine */
2120 sm
->heldPeriod
= 60;
2121 sm
->startPeriod
= 30;
2124 /* Supplicant Backend state machine */
2125 sm
->authPeriod
= 30;
2127 os_memset(&conf
, 0, sizeof(conf
));
2128 conf
.opensc_engine_path
= ctx
->opensc_engine_path
;
2129 conf
.pkcs11_engine_path
= ctx
->pkcs11_engine_path
;
2130 conf
.pkcs11_module_path
= ctx
->pkcs11_module_path
;
2131 conf
.openssl_ciphers
= ctx
->openssl_ciphers
;
2132 conf
.wps
= ctx
->wps
;
2133 conf
.cert_in_cb
= ctx
->cert_in_cb
;
2135 sm
->eap
= eap_peer_sm_init(sm
, &eapol_cb
, sm
->ctx
->msg_ctx
, &conf
);
2136 if (sm
->eap
== NULL
) {
2141 #ifdef CONFIG_EAP_PROXY
2142 sm
->use_eap_proxy
= FALSE
;
2143 sm
->eap_proxy
= eap_proxy_init(sm
, &eapol_cb
, sm
->ctx
->msg_ctx
);
2144 if (sm
->eap_proxy
== NULL
) {
2145 wpa_printf(MSG_ERROR
, "Unable to initialize EAP Proxy");
2147 #endif /* CONFIG_EAP_PROXY */
2149 /* Initialize EAPOL state machines */
2150 sm
->force_authorized_update
= TRUE
;
2151 sm
->initialize
= TRUE
;
2153 sm
->initialize
= FALSE
;
2156 if (eloop_register_timeout(1, 0, eapol_port_timers_tick
, NULL
, sm
) == 0)
2157 sm
->timer_tick_enabled
= 1;
2164 * eapol_sm_deinit - Deinitialize EAPOL state machine
2165 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
2167 * Deinitialize and free EAPOL state machine.
2169 void eapol_sm_deinit(struct eapol_sm
*sm
)
2173 eloop_cancel_timeout(eapol_sm_step_timeout
, NULL
, sm
);
2174 eloop_cancel_timeout(eapol_port_timers_tick
, NULL
, sm
);
2175 eap_peer_sm_deinit(sm
->eap
);
2176 #ifdef CONFIG_EAP_PROXY
2177 eap_proxy_deinit(sm
->eap_proxy
);
2178 #endif /* CONFIG_EAP_PROXY */
2179 os_free(sm
->last_rx_key
);
2180 wpabuf_free(sm
->eapReqData
);
2186 void eapol_sm_set_ext_pw_ctx(struct eapol_sm
*sm
,
2187 struct ext_password_data
*ext
)
2190 eap_sm_set_ext_pw_ctx(sm
->eap
, ext
);
2194 int eapol_sm_failed(struct eapol_sm
*sm
)
2198 return !sm
->eapSuccess
&& sm
->eapFail
;
2202 #ifdef CONFIG_EAP_PROXY
2203 int eapol_sm_get_eap_proxy_imsi(void *ctx
, int sim_num
, char *imsi
, size_t *len
)
2205 struct eapol_sm
*sm
= ctx
;
2207 if (sm
->eap_proxy
== NULL
)
2209 return eap_proxy_get_imsi(sm
->eap_proxy
, sim_num
, imsi
, len
);
2211 #endif /* CONFIG_EAP_PROXY */
2214 void eapol_sm_erp_flush(struct eapol_sm
*sm
)
2217 eap_peer_erp_free_keys(sm
->eap
);
2221 struct wpabuf
* eapol_sm_build_erp_reauth_start(struct eapol_sm
*sm
)
2226 return eap_peer_build_erp_reauth_start(sm
->eap
, 0);
2227 #else /* CONFIG_ERP */
2229 #endif /* CONFIG_ERP */
2233 void eapol_sm_process_erp_finish(struct eapol_sm
*sm
, const u8
*buf
,
2239 eap_peer_finish(sm
->eap
, (const struct eap_hdr
*) buf
, len
);
2240 #endif /* CONFIG_ERP */
2244 int eapol_sm_update_erp_next_seq_num(struct eapol_sm
*sm
, u16 next_seq_num
)
2249 return eap_peer_update_erp_next_seq_num(sm
->eap
, next_seq_num
);
2250 #else /* CONFIG_ERP */
2252 #endif /* CONFIG_ERP */
2256 int eapol_sm_get_erp_info(struct eapol_sm
*sm
, struct eap_peer_config
*config
,
2257 const u8
**username
, size_t *username_len
,
2258 const u8
**realm
, size_t *realm_len
,
2259 u16
*erp_next_seq_num
, const u8
**rrk
,
2265 return eap_peer_get_erp_info(sm
->eap
, config
, username
, username_len
,
2266 realm
, realm_len
, erp_next_seq_num
, rrk
,
2268 #else /* CONFIG_ERP */
2270 #endif /* CONFIG_ERP */