2 * hostapd / EAP Full Authenticator state machine (RFC 4137)
3 * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
8 * This state machine is based on the full authenticator state machine defined
9 * in RFC 4137. However, to support backend authentication in RADIUS
10 * authentication server functionality, parts of backend authenticator (also
11 * from RFC 4137) are mixed in. This functionality is enabled by setting
12 * backend_auth configuration variable to TRUE.
18 #include "crypto/sha256.h"
20 #include "state_machine.h"
21 #include "common/wpa_ctrl.h"
23 #define STATE_MACHINE_DATA struct eap_sm
24 #define STATE_MACHINE_DEBUG_PREFIX "EAP"
26 #define EAP_MAX_AUTH_ROUNDS 50
28 static void eap_user_free(struct eap_user
*user
);
31 /* EAP state machines are described in RFC 4137 */
33 static int eap_sm_calculateTimeout(struct eap_sm
*sm
, int retransCount
,
34 int eapSRTT
, int eapRTTVAR
,
36 static void eap_sm_parseEapResp(struct eap_sm
*sm
, const struct wpabuf
*resp
);
37 static int eap_sm_getId(const struct wpabuf
*data
);
38 static struct wpabuf
* eap_sm_buildSuccess(struct eap_sm
*sm
, u8 id
);
39 static struct wpabuf
* eap_sm_buildFailure(struct eap_sm
*sm
, u8 id
);
40 static int eap_sm_nextId(struct eap_sm
*sm
, int id
);
41 static void eap_sm_Policy_update(struct eap_sm
*sm
, const u8
*nak_list
,
43 static EapType
eap_sm_Policy_getNextMethod(struct eap_sm
*sm
, int *vendor
);
44 static int eap_sm_Policy_getDecision(struct eap_sm
*sm
);
45 static Boolean
eap_sm_Policy_doPickUp(struct eap_sm
*sm
, EapType method
);
48 static int eap_get_erp_send_reauth_start(struct eap_sm
*sm
)
50 if (sm
->eapol_cb
->get_erp_send_reauth_start
)
51 return sm
->eapol_cb
->get_erp_send_reauth_start(sm
->eapol_ctx
);
56 static const char * eap_get_erp_domain(struct eap_sm
*sm
)
58 if (sm
->eapol_cb
->get_erp_domain
)
59 return sm
->eapol_cb
->get_erp_domain(sm
->eapol_ctx
);
66 static struct eap_server_erp_key
* eap_erp_get_key(struct eap_sm
*sm
,
69 if (sm
->eapol_cb
->erp_get_key
)
70 return sm
->eapol_cb
->erp_get_key(sm
->eapol_ctx
, keyname
);
75 static int eap_erp_add_key(struct eap_sm
*sm
, struct eap_server_erp_key
*erp
)
77 if (sm
->eapol_cb
->erp_add_key
)
78 return sm
->eapol_cb
->erp_add_key(sm
->eapol_ctx
, erp
);
82 #endif /* CONFIG_ERP */
85 static struct wpabuf
* eap_sm_buildInitiateReauthStart(struct eap_sm
*sm
,
91 size_t domain_len
= 0;
93 domain
= eap_get_erp_domain(sm
);
95 domain_len
= os_strlen(domain
);
96 plen
+= 2 + domain_len
;
99 msg
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_ERP_TYPE_REAUTH_START
, plen
,
100 EAP_CODE_INITIATE
, id
);
103 wpabuf_put_u8(msg
, 0); /* Reserved */
105 /* Domain name TLV */
106 wpabuf_put_u8(msg
, EAP_ERP_TLV_DOMAIN_NAME
);
107 wpabuf_put_u8(msg
, domain_len
);
108 wpabuf_put_data(msg
, domain
, domain_len
);
115 static int eap_copy_buf(struct wpabuf
**dst
, const struct wpabuf
*src
)
121 *dst
= wpabuf_dup(src
);
122 return *dst
? 0 : -1;
126 static int eap_copy_data(u8
**dst
, size_t *dst_len
,
127 const u8
*src
, size_t src_len
)
133 *dst
= os_malloc(src_len
);
135 os_memcpy(*dst
, src
, src_len
);
144 #define EAP_COPY(dst, src) \
145 eap_copy_data((dst), (dst ## Len), (src), (src ## Len))
149 * eap_user_get - Fetch user information from the database
150 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
151 * @identity: Identity (User-Name) of the user
152 * @identity_len: Length of identity in bytes
153 * @phase2: 0 = EAP phase1 user, 1 = EAP phase2 (tunneled) user
154 * Returns: 0 on success, or -1 on failure
156 * This function is used to fetch user information for EAP. The user will be
157 * selected based on the specified identity. sm->user and
158 * sm->user_eap_method_index are updated for the new user when a matching user
159 * is found. sm->user can be used to get user information (e.g., password).
161 int eap_user_get(struct eap_sm
*sm
, const u8
*identity
, size_t identity_len
,
164 struct eap_user
*user
;
166 if (sm
== NULL
|| sm
->eapol_cb
== NULL
||
167 sm
->eapol_cb
->get_eap_user
== NULL
)
170 eap_user_free(sm
->user
);
173 user
= os_zalloc(sizeof(*user
));
177 if (sm
->eapol_cb
->get_eap_user(sm
->eapol_ctx
, identity
,
178 identity_len
, phase2
, user
) != 0) {
184 sm
->user_eap_method_index
= 0;
190 void eap_log_msg(struct eap_sm
*sm
, const char *fmt
, ...)
196 if (sm
== NULL
|| sm
->eapol_cb
== NULL
|| sm
->eapol_cb
->log_msg
== NULL
)
200 buflen
= vsnprintf(NULL
, 0, fmt
, ap
) + 1;
203 buf
= os_malloc(buflen
);
207 vsnprintf(buf
, buflen
, fmt
, ap
);
210 sm
->eapol_cb
->log_msg(sm
->eapol_ctx
, buf
);
216 SM_STATE(EAP
, DISABLED
)
218 SM_ENTRY(EAP
, DISABLED
);
223 SM_STATE(EAP
, INITIALIZE
)
225 SM_ENTRY(EAP
, INITIALIZE
);
227 if (sm
->eap_if
.eapRestart
&& !sm
->eap_server
&& sm
->identity
) {
229 * Need to allow internal Identity method to be used instead
230 * of passthrough at the beginning of reauthentication.
232 eap_server_clear_identity(sm
);
235 sm
->try_initiate_reauth
= FALSE
;
237 sm
->eap_if
.eapSuccess
= FALSE
;
238 sm
->eap_if
.eapFail
= FALSE
;
239 sm
->eap_if
.eapTimeout
= FALSE
;
240 bin_clear_free(sm
->eap_if
.eapKeyData
, sm
->eap_if
.eapKeyDataLen
);
241 sm
->eap_if
.eapKeyData
= NULL
;
242 sm
->eap_if
.eapKeyDataLen
= 0;
243 os_free(sm
->eap_if
.eapSessionId
);
244 sm
->eap_if
.eapSessionId
= NULL
;
245 sm
->eap_if
.eapSessionIdLen
= 0;
246 sm
->eap_if
.eapKeyAvailable
= FALSE
;
247 sm
->eap_if
.eapRestart
= FALSE
;
250 * This is not defined in RFC 4137, but method state needs to be
251 * reseted here so that it does not remain in success state when
252 * re-authentication starts.
254 if (sm
->m
&& sm
->eap_method_priv
) {
255 sm
->m
->reset(sm
, sm
->eap_method_priv
);
256 sm
->eap_method_priv
= NULL
;
259 sm
->user_eap_method_index
= 0;
261 if (sm
->backend_auth
) {
262 sm
->currentMethod
= EAP_TYPE_NONE
;
263 /* parse rxResp, respId, respMethod */
264 eap_sm_parseEapResp(sm
, sm
->eap_if
.eapRespData
);
266 sm
->currentId
= sm
->respId
;
270 sm
->method_pending
= METHOD_PENDING_NONE
;
272 wpa_msg(sm
->msg_ctx
, MSG_INFO
, WPA_EVENT_EAP_STARTED
273 MACSTR
, MAC2STR(sm
->peer_addr
));
277 SM_STATE(EAP
, PICK_UP_METHOD
)
279 SM_ENTRY(EAP
, PICK_UP_METHOD
);
281 if (eap_sm_Policy_doPickUp(sm
, sm
->respMethod
)) {
282 sm
->currentMethod
= sm
->respMethod
;
283 if (sm
->m
&& sm
->eap_method_priv
) {
284 sm
->m
->reset(sm
, sm
->eap_method_priv
);
285 sm
->eap_method_priv
= NULL
;
287 sm
->m
= eap_server_get_eap_method(EAP_VENDOR_IETF
,
289 if (sm
->m
&& sm
->m
->initPickUp
) {
290 sm
->eap_method_priv
= sm
->m
->initPickUp(sm
);
291 if (sm
->eap_method_priv
== NULL
) {
292 wpa_printf(MSG_DEBUG
, "EAP: Failed to "
293 "initialize EAP method %d",
296 sm
->currentMethod
= EAP_TYPE_NONE
;
300 sm
->currentMethod
= EAP_TYPE_NONE
;
304 wpa_msg(sm
->msg_ctx
, MSG_INFO
, WPA_EVENT_EAP_PROPOSED_METHOD
305 "method=%u", sm
->currentMethod
);
313 sm
->eap_if
.retransWhile
= eap_sm_calculateTimeout(
314 sm
, sm
->retransCount
, sm
->eap_if
.eapSRTT
, sm
->eap_if
.eapRTTVAR
,
319 SM_STATE(EAP
, RETRANSMIT
)
321 SM_ENTRY(EAP
, RETRANSMIT
);
324 if (sm
->retransCount
<= sm
->MaxRetrans
&& sm
->lastReqData
) {
325 if (eap_copy_buf(&sm
->eap_if
.eapReqData
, sm
->lastReqData
) == 0)
326 sm
->eap_if
.eapReq
= TRUE
;
331 SM_STATE(EAP
, RECEIVED
)
333 SM_ENTRY(EAP
, RECEIVED
);
335 /* parse rxResp, respId, respMethod */
336 eap_sm_parseEapResp(sm
, sm
->eap_if
.eapRespData
);
341 SM_STATE(EAP
, DISCARD
)
343 SM_ENTRY(EAP
, DISCARD
);
344 sm
->eap_if
.eapResp
= FALSE
;
345 sm
->eap_if
.eapNoReq
= TRUE
;
349 SM_STATE(EAP
, SEND_REQUEST
)
351 SM_ENTRY(EAP
, SEND_REQUEST
);
353 sm
->retransCount
= 0;
354 if (sm
->eap_if
.eapReqData
) {
355 if (eap_copy_buf(&sm
->lastReqData
, sm
->eap_if
.eapReqData
) == 0)
357 sm
->eap_if
.eapResp
= FALSE
;
358 sm
->eap_if
.eapReq
= TRUE
;
360 sm
->eap_if
.eapResp
= FALSE
;
361 sm
->eap_if
.eapReq
= FALSE
;
364 wpa_printf(MSG_INFO
, "EAP: SEND_REQUEST - no eapReqData");
365 sm
->eap_if
.eapResp
= FALSE
;
366 sm
->eap_if
.eapReq
= FALSE
;
367 sm
->eap_if
.eapNoReq
= TRUE
;
372 SM_STATE(EAP
, INTEGRITY_CHECK
)
374 SM_ENTRY(EAP
, INTEGRITY_CHECK
);
376 if (!eap_hdr_len_valid(sm
->eap_if
.eapRespData
, 1)) {
382 sm
->ignore
= sm
->m
->check(sm
, sm
->eap_method_priv
,
383 sm
->eap_if
.eapRespData
);
388 SM_STATE(EAP
, METHOD_REQUEST
)
390 SM_ENTRY(EAP
, METHOD_REQUEST
);
393 wpa_printf(MSG_DEBUG
, "EAP: method not initialized");
397 sm
->currentId
= eap_sm_nextId(sm
, sm
->currentId
);
398 wpa_printf(MSG_DEBUG
, "EAP: building EAP-Request: Identifier %d",
400 sm
->lastId
= sm
->currentId
;
401 wpabuf_free(sm
->eap_if
.eapReqData
);
402 sm
->eap_if
.eapReqData
= sm
->m
->buildReq(sm
, sm
->eap_method_priv
,
404 if (sm
->m
->getTimeout
)
405 sm
->methodTimeout
= sm
->m
->getTimeout(sm
, sm
->eap_method_priv
);
407 sm
->methodTimeout
= 0;
411 static void eap_server_erp_init(struct eap_sm
*sm
)
416 u8 EMSKname
[EAP_EMSK_NAME_LEN
];
419 size_t domain_len
, nai_buf_len
;
420 struct eap_server_erp_key
*erp
= NULL
;
423 domain
= eap_get_erp_domain(sm
);
427 domain_len
= os_strlen(domain
);
429 nai_buf_len
= 2 * EAP_EMSK_NAME_LEN
+ 1 + domain_len
;
430 if (nai_buf_len
> 253) {
432 * keyName-NAI has a maximum length of 253 octet to fit in
435 wpa_printf(MSG_DEBUG
,
436 "EAP: Too long realm for ERP keyName-NAI maximum length");
439 nai_buf_len
++; /* null termination */
440 erp
= os_zalloc(sizeof(*erp
) + nai_buf_len
);
443 erp
->recv_seq
= (u32
) -1;
445 emsk
= sm
->m
->get_emsk(sm
, sm
->eap_method_priv
, &emsk_len
);
446 if (!emsk
|| emsk_len
== 0 || emsk_len
> ERP_MAX_KEY_LEN
) {
447 wpa_printf(MSG_DEBUG
,
448 "EAP: No suitable EMSK available for ERP");
452 wpa_hexdump_key(MSG_DEBUG
, "EAP: EMSK", emsk
, emsk_len
);
454 WPA_PUT_BE16(len
, 8);
455 if (hmac_sha256_kdf(sm
->eap_if
.eapSessionId
, sm
->eap_if
.eapSessionIdLen
,
456 "EMSK", len
, sizeof(len
),
457 EMSKname
, EAP_EMSK_NAME_LEN
) < 0) {
458 wpa_printf(MSG_DEBUG
, "EAP: Could not derive EMSKname");
461 wpa_hexdump(MSG_DEBUG
, "EAP: EMSKname", EMSKname
, EAP_EMSK_NAME_LEN
);
463 pos
= wpa_snprintf_hex(erp
->keyname_nai
, nai_buf_len
,
464 EMSKname
, EAP_EMSK_NAME_LEN
);
465 erp
->keyname_nai
[pos
] = '@';
466 os_memcpy(&erp
->keyname_nai
[pos
+ 1], domain
, domain_len
);
468 WPA_PUT_BE16(len
, emsk_len
);
469 if (hmac_sha256_kdf(emsk
, emsk_len
,
470 "EAP Re-authentication Root Key@ietf.org",
471 len
, sizeof(len
), erp
->rRK
, emsk_len
) < 0) {
472 wpa_printf(MSG_DEBUG
, "EAP: Could not derive rRK for ERP");
475 erp
->rRK_len
= emsk_len
;
476 wpa_hexdump_key(MSG_DEBUG
, "EAP: ERP rRK", erp
->rRK
, erp
->rRK_len
);
478 if (hmac_sha256_kdf(erp
->rRK
, erp
->rRK_len
,
479 "EAP Re-authentication Integrity Key@ietf.org",
480 len
, sizeof(len
), erp
->rIK
, erp
->rRK_len
) < 0) {
481 wpa_printf(MSG_DEBUG
, "EAP: Could not derive rIK for ERP");
484 erp
->rIK_len
= erp
->rRK_len
;
485 wpa_hexdump_key(MSG_DEBUG
, "EAP: ERP rIK", erp
->rIK
, erp
->rIK_len
);
487 if (eap_erp_add_key(sm
, erp
) == 0) {
488 wpa_printf(MSG_DEBUG
, "EAP: Stored ERP keys %s",
494 bin_clear_free(emsk
, emsk_len
);
495 bin_clear_free(erp
, sizeof(*erp
));
496 #endif /* CONFIG_ERP */
500 SM_STATE(EAP
, METHOD_RESPONSE
)
502 SM_ENTRY(EAP
, METHOD_RESPONSE
);
504 if (!eap_hdr_len_valid(sm
->eap_if
.eapRespData
, 1))
507 sm
->m
->process(sm
, sm
->eap_method_priv
, sm
->eap_if
.eapRespData
);
508 if (sm
->m
->isDone(sm
, sm
->eap_method_priv
)) {
509 eap_sm_Policy_update(sm
, NULL
, 0);
510 bin_clear_free(sm
->eap_if
.eapKeyData
, sm
->eap_if
.eapKeyDataLen
);
512 sm
->eap_if
.eapKeyData
= sm
->m
->getKey(
513 sm
, sm
->eap_method_priv
,
514 &sm
->eap_if
.eapKeyDataLen
);
516 sm
->eap_if
.eapKeyData
= NULL
;
517 sm
->eap_if
.eapKeyDataLen
= 0;
519 os_free(sm
->eap_if
.eapSessionId
);
520 sm
->eap_if
.eapSessionId
= NULL
;
521 if (sm
->m
->getSessionId
) {
522 sm
->eap_if
.eapSessionId
= sm
->m
->getSessionId(
523 sm
, sm
->eap_method_priv
,
524 &sm
->eap_if
.eapSessionIdLen
);
525 wpa_hexdump(MSG_DEBUG
, "EAP: Session-Id",
526 sm
->eap_if
.eapSessionId
,
527 sm
->eap_if
.eapSessionIdLen
);
529 if (sm
->erp
&& sm
->m
->get_emsk
&& sm
->eap_if
.eapSessionId
)
530 eap_server_erp_init(sm
);
531 sm
->methodState
= METHOD_END
;
533 sm
->methodState
= METHOD_CONTINUE
;
538 SM_STATE(EAP
, PROPOSE_METHOD
)
543 SM_ENTRY(EAP
, PROPOSE_METHOD
);
545 sm
->try_initiate_reauth
= FALSE
;
547 type
= eap_sm_Policy_getNextMethod(sm
, &vendor
);
548 if (vendor
== EAP_VENDOR_IETF
)
549 sm
->currentMethod
= type
;
551 sm
->currentMethod
= EAP_TYPE_EXPANDED
;
552 if (sm
->m
&& sm
->eap_method_priv
) {
553 sm
->m
->reset(sm
, sm
->eap_method_priv
);
554 sm
->eap_method_priv
= NULL
;
556 sm
->m
= eap_server_get_eap_method(vendor
, type
);
558 sm
->eap_method_priv
= sm
->m
->init(sm
);
559 if (sm
->eap_method_priv
== NULL
) {
560 wpa_printf(MSG_DEBUG
, "EAP: Failed to initialize EAP "
561 "method %d", sm
->currentMethod
);
563 sm
->currentMethod
= EAP_TYPE_NONE
;
564 goto try_another_method
;
568 wpa_printf(MSG_DEBUG
, "EAP: Could not find suitable EAP method");
569 eap_log_msg(sm
, "Could not find suitable EAP method");
570 sm
->decision
= DECISION_FAILURE
;
573 if (sm
->currentMethod
== EAP_TYPE_IDENTITY
||
574 sm
->currentMethod
== EAP_TYPE_NOTIFICATION
)
575 sm
->methodState
= METHOD_CONTINUE
;
577 sm
->methodState
= METHOD_PROPOSED
;
579 wpa_msg(sm
->msg_ctx
, MSG_INFO
, WPA_EVENT_EAP_PROPOSED_METHOD
580 "vendor=%u method=%u", vendor
, sm
->currentMethod
);
581 eap_log_msg(sm
, "Propose EAP method vendor=%u method=%u",
582 vendor
, sm
->currentMethod
);
588 const struct eap_hdr
*nak
;
591 const u8
*nak_list
= NULL
;
595 if (sm
->eap_method_priv
) {
596 sm
->m
->reset(sm
, sm
->eap_method_priv
);
597 sm
->eap_method_priv
= NULL
;
601 if (!eap_hdr_len_valid(sm
->eap_if
.eapRespData
, 1))
604 nak
= wpabuf_head(sm
->eap_if
.eapRespData
);
605 if (nak
&& wpabuf_len(sm
->eap_if
.eapRespData
) > sizeof(*nak
)) {
606 len
= be_to_host16(nak
->length
);
607 if (len
> wpabuf_len(sm
->eap_if
.eapRespData
))
608 len
= wpabuf_len(sm
->eap_if
.eapRespData
);
609 pos
= (const u8
*) (nak
+ 1);
611 if (*pos
== EAP_TYPE_NAK
) {
617 eap_sm_Policy_update(sm
, nak_list
, len
);
621 SM_STATE(EAP
, SELECT_ACTION
)
623 SM_ENTRY(EAP
, SELECT_ACTION
);
625 sm
->decision
= eap_sm_Policy_getDecision(sm
);
629 SM_STATE(EAP
, TIMEOUT_FAILURE
)
631 SM_ENTRY(EAP
, TIMEOUT_FAILURE
);
633 sm
->eap_if
.eapTimeout
= TRUE
;
637 SM_STATE(EAP
, FAILURE
)
639 SM_ENTRY(EAP
, FAILURE
);
641 wpabuf_free(sm
->eap_if
.eapReqData
);
642 sm
->eap_if
.eapReqData
= eap_sm_buildFailure(sm
, sm
->currentId
);
643 wpabuf_free(sm
->lastReqData
);
644 sm
->lastReqData
= NULL
;
645 sm
->eap_if
.eapFail
= TRUE
;
647 wpa_msg(sm
->msg_ctx
, MSG_INFO
, WPA_EVENT_EAP_FAILURE
648 MACSTR
, MAC2STR(sm
->peer_addr
));
652 SM_STATE(EAP
, SUCCESS
)
654 SM_ENTRY(EAP
, SUCCESS
);
656 wpabuf_free(sm
->eap_if
.eapReqData
);
657 sm
->eap_if
.eapReqData
= eap_sm_buildSuccess(sm
, sm
->currentId
);
658 wpabuf_free(sm
->lastReqData
);
659 sm
->lastReqData
= NULL
;
660 if (sm
->eap_if
.eapKeyData
)
661 sm
->eap_if
.eapKeyAvailable
= TRUE
;
662 sm
->eap_if
.eapSuccess
= TRUE
;
664 wpa_msg(sm
->msg_ctx
, MSG_INFO
, WPA_EVENT_EAP_SUCCESS
665 MACSTR
, MAC2STR(sm
->peer_addr
));
669 SM_STATE(EAP
, INITIATE_REAUTH_START
)
671 SM_ENTRY(EAP
, INITIATE_REAUTH_START
);
673 sm
->initiate_reauth_start_sent
= TRUE
;
674 sm
->try_initiate_reauth
= TRUE
;
675 sm
->currentId
= eap_sm_nextId(sm
, sm
->currentId
);
676 wpa_printf(MSG_DEBUG
,
677 "EAP: building EAP-Initiate-Re-auth-Start: Identifier %d",
679 sm
->lastId
= sm
->currentId
;
680 wpabuf_free(sm
->eap_if
.eapReqData
);
681 sm
->eap_if
.eapReqData
= eap_sm_buildInitiateReauthStart(sm
,
683 wpabuf_free(sm
->lastReqData
);
684 sm
->lastReqData
= NULL
;
690 static void erp_send_finish_reauth(struct eap_sm
*sm
,
691 struct eap_server_erp_key
*erp
, u8 id
,
692 u8 flags
, u16 seq
, const char *nai
)
696 u8 hash
[SHA256_MAC_LEN
];
701 switch (erp
->cryptosuite
) {
702 case EAP_ERP_CS_HMAC_SHA256_256
:
705 case EAP_ERP_CS_HMAC_SHA256_128
:
714 plen
= 1 + 2 + 2 + os_strlen(nai
);
716 plen
+= 1 + hash_len
;
717 msg
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_ERP_TYPE_REAUTH
, plen
,
718 EAP_CODE_FINISH
, id
);
721 wpabuf_put_u8(msg
, flags
);
722 wpabuf_put_be16(msg
, seq
);
724 wpabuf_put_u8(msg
, EAP_ERP_TLV_KEYNAME_NAI
);
725 wpabuf_put_u8(msg
, os_strlen(nai
));
726 wpabuf_put_str(msg
, nai
);
729 wpabuf_put_u8(msg
, erp
->cryptosuite
);
730 if (hmac_sha256(erp
->rIK
, erp
->rIK_len
,
731 wpabuf_head(msg
), wpabuf_len(msg
), hash
) < 0) {
735 wpabuf_put_data(msg
, hash
, hash_len
);
738 wpa_printf(MSG_DEBUG
, "EAP: Send EAP-Finish/Re-auth (%s)",
739 flags
& 0x80 ? "failure" : "success");
741 sm
->lastId
= sm
->currentId
;
743 wpabuf_free(sm
->eap_if
.eapReqData
);
744 sm
->eap_if
.eapReqData
= msg
;
745 wpabuf_free(sm
->lastReqData
);
746 sm
->lastReqData
= NULL
;
749 sm
->eap_if
.eapFail
= TRUE
;
750 wpa_msg(sm
->msg_ctx
, MSG_INFO
, WPA_EVENT_EAP_FAILURE
751 MACSTR
, MAC2STR(sm
->peer_addr
));
755 bin_clear_free(sm
->eap_if
.eapKeyData
, sm
->eap_if
.eapKeyDataLen
);
756 sm
->eap_if
.eapKeyDataLen
= 0;
757 sm
->eap_if
.eapKeyData
= os_malloc(erp
->rRK_len
);
758 if (!sm
->eap_if
.eapKeyData
)
761 WPA_PUT_BE16(seed
, seq
);
762 WPA_PUT_BE16(&seed
[2], erp
->rRK_len
);
763 if (hmac_sha256_kdf(erp
->rRK
, erp
->rRK_len
,
764 "Re-authentication Master Session Key@ietf.org",
766 sm
->eap_if
.eapKeyData
, erp
->rRK_len
) < 0) {
767 wpa_printf(MSG_DEBUG
, "EAP: Could not derive rMSK for ERP");
768 bin_clear_free(sm
->eap_if
.eapKeyData
, erp
->rRK_len
);
769 sm
->eap_if
.eapKeyData
= NULL
;
772 sm
->eap_if
.eapKeyDataLen
= erp
->rRK_len
;
773 sm
->eap_if
.eapKeyAvailable
= TRUE
;
774 wpa_hexdump_key(MSG_DEBUG
, "EAP: ERP rMSK",
775 sm
->eap_if
.eapKeyData
, sm
->eap_if
.eapKeyDataLen
);
776 sm
->eap_if
.eapSuccess
= TRUE
;
778 wpa_msg(sm
->msg_ctx
, MSG_INFO
, WPA_EVENT_EAP_SUCCESS
779 MACSTR
, MAC2STR(sm
->peer_addr
));
783 SM_STATE(EAP
, INITIATE_RECEIVED
)
785 const u8
*pos
, *end
, *start
, *tlvs
, *hdr
;
786 const struct eap_hdr
*ehdr
;
791 struct eap_server_erp_key
*erp
;
793 u8 hash
[SHA256_MAC_LEN
];
795 struct erp_tlvs parse
;
796 u8 resp_flags
= 0x80; /* default to failure; cleared on success */
798 SM_ENTRY(EAP
, INITIATE_RECEIVED
);
800 sm
->rxInitiate
= FALSE
;
802 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_ERP_TYPE_REAUTH
,
803 sm
->eap_if
.eapRespData
, &len
);
805 wpa_printf(MSG_INFO
, "EAP-Initiate: Invalid frame");
808 hdr
= wpabuf_head(sm
->eap_if
.eapRespData
);
809 ehdr
= wpabuf_head(sm
->eap_if
.eapRespData
);
811 wpa_hexdump(MSG_DEBUG
, "EAP: EAP-Initiate/Re-Auth", pos
, len
);
813 wpa_printf(MSG_INFO
, "EAP: Too short EAP-Initiate/Re-auth");
819 seq
= WPA_GET_BE16(pos
);
821 wpa_printf(MSG_DEBUG
, "EAP: Flags=0x%x SEQ=%u", flags
, seq
);
825 * Parse TVs/TLVs. Since we do not yet know the length of the
826 * Authentication Tag, stop parsing if an unknown TV/TLV is seen and
827 * just try to find the keyName-NAI first so that we can check the
828 * Authentication Tag.
830 if (erp_parse_tlvs(tlvs
, end
, &parse
, 1) < 0)
833 if (!parse
.keyname
) {
834 wpa_printf(MSG_DEBUG
,
835 "EAP: No keyName-NAI in EAP-Initiate/Re-auth Packet");
839 wpa_hexdump_ascii(MSG_DEBUG
, "EAP: EAP-Initiate/Re-auth - keyName-NAI",
840 parse
.keyname
, parse
.keyname_len
);
841 if (parse
.keyname_len
> 253) {
842 wpa_printf(MSG_DEBUG
,
843 "EAP: Too long keyName-NAI in EAP-Initiate/Re-auth");
846 os_memcpy(nai
, parse
.keyname
, parse
.keyname_len
);
847 nai
[parse
.keyname_len
] = '\0';
849 if (!sm
->eap_server
) {
851 * In passthrough case, EAP-Initiate/Re-auth replaces
852 * EAP Identity exchange. Use keyName-NAI as the user identity
853 * and forward EAP-Initiate/Re-auth to the backend
854 * authentication server.
856 wpa_printf(MSG_DEBUG
,
857 "EAP: Use keyName-NAI as user identity for backend authentication");
858 eap_server_clear_identity(sm
);
859 sm
->identity
= (u8
*) dup_binstr(parse
.keyname
,
863 sm
->identity_len
= parse
.keyname_len
;
867 erp
= eap_erp_get_key(sm
, nai
);
869 wpa_printf(MSG_DEBUG
, "EAP: No matching ERP key found for %s",
874 if (erp
->recv_seq
!= (u32
) -1 && erp
->recv_seq
>= seq
) {
875 wpa_printf(MSG_DEBUG
,
876 "EAP: SEQ=%u replayed (already received SEQ=%u)",
881 /* Is there enough room for Cryptosuite and Authentication Tag? */
882 start
= parse
.keyname
+ parse
.keyname_len
;
883 max_len
= end
- start
;
885 1 + (erp
->cryptosuite
== EAP_ERP_CS_HMAC_SHA256_256
? 32 : 16)) {
886 wpa_printf(MSG_DEBUG
,
887 "EAP: Not enough room for Authentication Tag");
891 switch (erp
->cryptosuite
) {
892 case EAP_ERP_CS_HMAC_SHA256_256
:
893 if (end
[-33] != erp
->cryptosuite
) {
894 wpa_printf(MSG_DEBUG
,
895 "EAP: Different Cryptosuite used");
900 case EAP_ERP_CS_HMAC_SHA256_128
:
901 if (end
[-17] != erp
->cryptosuite
) {
902 wpa_printf(MSG_DEBUG
,
903 "EAP: Different Cryptosuite used");
914 if (hmac_sha256(erp
->rIK
, erp
->rIK_len
, hdr
,
915 end
- hdr
- hash_len
, hash
) < 0)
917 if (os_memcmp(end
- hash_len
, hash
, hash_len
) != 0) {
918 wpa_printf(MSG_DEBUG
,
919 "EAP: Authentication Tag mismatch");
924 /* Check if any supported CS results in matching tag */
925 if (!hash_len
&& max_len
>= 1 + 32 &&
926 end
[-33] == EAP_ERP_CS_HMAC_SHA256_256
) {
927 if (hmac_sha256(erp
->rIK
, erp
->rIK_len
, hdr
,
928 end
- hdr
- 32, hash
) < 0)
930 if (os_memcmp(end
- 32, hash
, 32) == 0) {
931 wpa_printf(MSG_DEBUG
,
932 "EAP: Authentication Tag match using HMAC-SHA256-256");
934 erp
->cryptosuite
= EAP_ERP_CS_HMAC_SHA256_256
;
938 if (!hash_len
&& end
[-17] == EAP_ERP_CS_HMAC_SHA256_128
) {
939 if (hmac_sha256(erp
->rIK
, erp
->rIK_len
, hdr
,
940 end
- hdr
- 16, hash
) < 0)
942 if (os_memcmp(end
- 16, hash
, 16) == 0) {
943 wpa_printf(MSG_DEBUG
,
944 "EAP: Authentication Tag match using HMAC-SHA256-128");
946 erp
->cryptosuite
= EAP_ERP_CS_HMAC_SHA256_128
;
951 wpa_printf(MSG_DEBUG
,
952 "EAP: No supported cryptosuite matched Authentication Tag");
958 * Parse TVs/TLVs again now that we know the exact part of the buffer
959 * that contains them.
961 wpa_hexdump(MSG_DEBUG
, "EAP: EAP-Initiate/Re-Auth TVs/TLVs",
963 if (erp_parse_tlvs(tlvs
, end
, &parse
, 0) < 0)
966 wpa_printf(MSG_DEBUG
, "EAP: ERP key %s SEQ updated to %u",
967 erp
->keyname_nai
, seq
);
969 resp_flags
&= ~0x80; /* R=0 - success */
972 erp_send_finish_reauth(sm
, erp
, ehdr
->identifier
, resp_flags
, seq
, nai
);
979 #endif /* CONFIG_ERP */
982 SM_STATE(EAP
, INITIALIZE_PASSTHROUGH
)
984 SM_ENTRY(EAP
, INITIALIZE_PASSTHROUGH
);
986 wpabuf_free(sm
->eap_if
.aaaEapRespData
);
987 sm
->eap_if
.aaaEapRespData
= NULL
;
988 sm
->try_initiate_reauth
= FALSE
;
994 SM_ENTRY(EAP
, IDLE2
);
996 sm
->eap_if
.retransWhile
= eap_sm_calculateTimeout(
997 sm
, sm
->retransCount
, sm
->eap_if
.eapSRTT
, sm
->eap_if
.eapRTTVAR
,
1002 SM_STATE(EAP
, RETRANSMIT2
)
1004 SM_ENTRY(EAP
, RETRANSMIT2
);
1007 if (sm
->retransCount
<= sm
->MaxRetrans
&& sm
->lastReqData
) {
1008 if (eap_copy_buf(&sm
->eap_if
.eapReqData
, sm
->lastReqData
) == 0)
1009 sm
->eap_if
.eapReq
= TRUE
;
1014 SM_STATE(EAP
, RECEIVED2
)
1016 SM_ENTRY(EAP
, RECEIVED2
);
1018 /* parse rxResp, respId, respMethod */
1019 eap_sm_parseEapResp(sm
, sm
->eap_if
.eapRespData
);
1023 SM_STATE(EAP
, DISCARD2
)
1025 SM_ENTRY(EAP
, DISCARD2
);
1026 sm
->eap_if
.eapResp
= FALSE
;
1027 sm
->eap_if
.eapNoReq
= TRUE
;
1031 SM_STATE(EAP
, SEND_REQUEST2
)
1033 SM_ENTRY(EAP
, SEND_REQUEST2
);
1035 sm
->retransCount
= 0;
1036 if (sm
->eap_if
.eapReqData
) {
1037 if (eap_copy_buf(&sm
->lastReqData
, sm
->eap_if
.eapReqData
) == 0)
1039 sm
->eap_if
.eapResp
= FALSE
;
1040 sm
->eap_if
.eapReq
= TRUE
;
1042 sm
->eap_if
.eapResp
= FALSE
;
1043 sm
->eap_if
.eapReq
= FALSE
;
1046 wpa_printf(MSG_INFO
, "EAP: SEND_REQUEST2 - no eapReqData");
1047 sm
->eap_if
.eapResp
= FALSE
;
1048 sm
->eap_if
.eapReq
= FALSE
;
1049 sm
->eap_if
.eapNoReq
= TRUE
;
1054 SM_STATE(EAP
, AAA_REQUEST
)
1056 SM_ENTRY(EAP
, AAA_REQUEST
);
1058 if (sm
->eap_if
.eapRespData
== NULL
) {
1059 wpa_printf(MSG_INFO
, "EAP: AAA_REQUEST - no eapRespData");
1064 * if (respMethod == IDENTITY)
1065 * aaaIdentity = eapRespData
1066 * This is already taken care of by the EAP-Identity method which
1067 * stores the identity into sm->identity.
1070 eap_copy_buf(&sm
->eap_if
.aaaEapRespData
, sm
->eap_if
.eapRespData
);
1074 SM_STATE(EAP
, AAA_RESPONSE
)
1076 SM_ENTRY(EAP
, AAA_RESPONSE
);
1078 eap_copy_buf(&sm
->eap_if
.eapReqData
, sm
->eap_if
.aaaEapReqData
);
1079 sm
->currentId
= eap_sm_getId(sm
->eap_if
.eapReqData
);
1080 sm
->methodTimeout
= sm
->eap_if
.aaaMethodTimeout
;
1084 SM_STATE(EAP
, AAA_IDLE
)
1086 SM_ENTRY(EAP
, AAA_IDLE
);
1088 sm
->eap_if
.aaaFail
= FALSE
;
1089 sm
->eap_if
.aaaSuccess
= FALSE
;
1090 sm
->eap_if
.aaaEapReq
= FALSE
;
1091 sm
->eap_if
.aaaEapNoReq
= FALSE
;
1092 sm
->eap_if
.aaaEapResp
= TRUE
;
1096 SM_STATE(EAP
, TIMEOUT_FAILURE2
)
1098 SM_ENTRY(EAP
, TIMEOUT_FAILURE2
);
1100 sm
->eap_if
.eapTimeout
= TRUE
;
1104 SM_STATE(EAP
, FAILURE2
)
1106 SM_ENTRY(EAP
, FAILURE2
);
1108 eap_copy_buf(&sm
->eap_if
.eapReqData
, sm
->eap_if
.aaaEapReqData
);
1109 sm
->eap_if
.eapFail
= TRUE
;
1113 SM_STATE(EAP
, SUCCESS2
)
1115 SM_ENTRY(EAP
, SUCCESS2
);
1117 eap_copy_buf(&sm
->eap_if
.eapReqData
, sm
->eap_if
.aaaEapReqData
);
1119 sm
->eap_if
.eapKeyAvailable
= sm
->eap_if
.aaaEapKeyAvailable
;
1120 if (sm
->eap_if
.aaaEapKeyAvailable
) {
1121 EAP_COPY(&sm
->eap_if
.eapKeyData
, sm
->eap_if
.aaaEapKeyData
);
1123 bin_clear_free(sm
->eap_if
.eapKeyData
, sm
->eap_if
.eapKeyDataLen
);
1124 sm
->eap_if
.eapKeyData
= NULL
;
1125 sm
->eap_if
.eapKeyDataLen
= 0;
1128 sm
->eap_if
.eapSuccess
= TRUE
;
1131 * Start reauthentication with identity request even though we know the
1132 * previously used identity. This is needed to get reauthentication
1135 sm
->start_reauth
= TRUE
;
1141 if (sm
->eap_if
.eapRestart
&& sm
->eap_if
.portEnabled
)
1142 SM_ENTER_GLOBAL(EAP
, INITIALIZE
);
1143 else if (!sm
->eap_if
.portEnabled
)
1144 SM_ENTER_GLOBAL(EAP
, DISABLED
);
1145 else if (sm
->num_rounds
> EAP_MAX_AUTH_ROUNDS
) {
1146 if (sm
->num_rounds
== EAP_MAX_AUTH_ROUNDS
+ 1) {
1147 wpa_printf(MSG_DEBUG
, "EAP: more than %d "
1148 "authentication rounds - abort",
1149 EAP_MAX_AUTH_ROUNDS
);
1151 SM_ENTER_GLOBAL(EAP
, FAILURE
);
1153 } else switch (sm
->EAP_state
) {
1154 case EAP_INITIALIZE
:
1155 if (sm
->backend_auth
) {
1157 SM_ENTER(EAP
, SELECT_ACTION
);
1158 else if (sm
->rxResp
&&
1159 (sm
->respMethod
== EAP_TYPE_NAK
||
1160 (sm
->respMethod
== EAP_TYPE_EXPANDED
&&
1161 sm
->respVendor
== EAP_VENDOR_IETF
&&
1162 sm
->respVendorMethod
== EAP_TYPE_NAK
)))
1165 SM_ENTER(EAP
, PICK_UP_METHOD
);
1167 SM_ENTER(EAP
, SELECT_ACTION
);
1170 case EAP_PICK_UP_METHOD
:
1171 if (sm
->currentMethod
== EAP_TYPE_NONE
) {
1172 SM_ENTER(EAP
, SELECT_ACTION
);
1174 SM_ENTER(EAP
, METHOD_RESPONSE
);
1178 if (sm
->eap_if
.portEnabled
)
1179 SM_ENTER(EAP
, INITIALIZE
);
1182 if (sm
->eap_if
.retransWhile
== 0) {
1183 if (sm
->try_initiate_reauth
) {
1184 sm
->try_initiate_reauth
= FALSE
;
1185 SM_ENTER(EAP
, SELECT_ACTION
);
1187 SM_ENTER(EAP
, RETRANSMIT
);
1189 } else if (sm
->eap_if
.eapResp
)
1190 SM_ENTER(EAP
, RECEIVED
);
1192 case EAP_RETRANSMIT
:
1193 if (sm
->retransCount
> sm
->MaxRetrans
)
1194 SM_ENTER(EAP
, TIMEOUT_FAILURE
);
1196 SM_ENTER(EAP
, IDLE
);
1199 if (sm
->rxResp
&& (sm
->respId
== sm
->currentId
) &&
1200 (sm
->respMethod
== EAP_TYPE_NAK
||
1201 (sm
->respMethod
== EAP_TYPE_EXPANDED
&&
1202 sm
->respVendor
== EAP_VENDOR_IETF
&&
1203 sm
->respVendorMethod
== EAP_TYPE_NAK
))
1204 && (sm
->methodState
== METHOD_PROPOSED
))
1206 else if (sm
->rxResp
&& (sm
->respId
== sm
->currentId
) &&
1207 ((sm
->respMethod
== sm
->currentMethod
) ||
1208 (sm
->respMethod
== EAP_TYPE_EXPANDED
&&
1209 sm
->respVendor
== EAP_VENDOR_IETF
&&
1210 sm
->respVendorMethod
== sm
->currentMethod
)))
1211 SM_ENTER(EAP
, INTEGRITY_CHECK
);
1213 else if (sm
->rxInitiate
)
1214 SM_ENTER(EAP
, INITIATE_RECEIVED
);
1215 #endif /* CONFIG_ERP */
1217 wpa_printf(MSG_DEBUG
, "EAP: RECEIVED->DISCARD: "
1218 "rxResp=%d respId=%d currentId=%d "
1219 "respMethod=%d currentMethod=%d",
1220 sm
->rxResp
, sm
->respId
, sm
->currentId
,
1221 sm
->respMethod
, sm
->currentMethod
);
1222 eap_log_msg(sm
, "Discard received EAP message");
1223 SM_ENTER(EAP
, DISCARD
);
1227 SM_ENTER(EAP
, IDLE
);
1229 case EAP_SEND_REQUEST
:
1230 SM_ENTER(EAP
, IDLE
);
1232 case EAP_INTEGRITY_CHECK
:
1234 SM_ENTER(EAP
, DISCARD
);
1236 SM_ENTER(EAP
, METHOD_RESPONSE
);
1238 case EAP_METHOD_REQUEST
:
1239 if (sm
->m
== NULL
) {
1241 * This transition is not mentioned in RFC 4137, but it
1242 * is needed to handle cleanly a case where EAP method
1243 * initialization fails.
1245 SM_ENTER(EAP
, FAILURE
);
1248 SM_ENTER(EAP
, SEND_REQUEST
);
1250 case EAP_METHOD_RESPONSE
:
1252 * Note: Mechanism to allow EAP methods to wait while going
1253 * through pending processing is an extension to RFC 4137
1254 * which only defines the transits to SELECT_ACTION and
1255 * METHOD_REQUEST from this METHOD_RESPONSE state.
1257 if (sm
->methodState
== METHOD_END
)
1258 SM_ENTER(EAP
, SELECT_ACTION
);
1259 else if (sm
->method_pending
== METHOD_PENDING_WAIT
) {
1260 wpa_printf(MSG_DEBUG
, "EAP: Method has pending "
1261 "processing - wait before proceeding to "
1262 "METHOD_REQUEST state");
1263 } else if (sm
->method_pending
== METHOD_PENDING_CONT
) {
1264 wpa_printf(MSG_DEBUG
, "EAP: Method has completed "
1265 "pending processing - reprocess pending "
1267 sm
->method_pending
= METHOD_PENDING_NONE
;
1268 SM_ENTER(EAP
, METHOD_RESPONSE
);
1270 SM_ENTER(EAP
, METHOD_REQUEST
);
1272 case EAP_PROPOSE_METHOD
:
1274 * Note: Mechanism to allow EAP methods to wait while going
1275 * through pending processing is an extension to RFC 4137
1276 * which only defines the transit to METHOD_REQUEST from this
1277 * PROPOSE_METHOD state.
1279 if (sm
->method_pending
== METHOD_PENDING_WAIT
) {
1280 wpa_printf(MSG_DEBUG
, "EAP: Method has pending "
1281 "processing - wait before proceeding to "
1282 "METHOD_REQUEST state");
1283 if (sm
->user_eap_method_index
> 0)
1284 sm
->user_eap_method_index
--;
1285 } else if (sm
->method_pending
== METHOD_PENDING_CONT
) {
1286 wpa_printf(MSG_DEBUG
, "EAP: Method has completed "
1287 "pending processing - reprocess pending "
1289 sm
->method_pending
= METHOD_PENDING_NONE
;
1290 SM_ENTER(EAP
, PROPOSE_METHOD
);
1292 SM_ENTER(EAP
, METHOD_REQUEST
);
1295 SM_ENTER(EAP
, SELECT_ACTION
);
1297 case EAP_SELECT_ACTION
:
1298 if (sm
->decision
== DECISION_FAILURE
)
1299 SM_ENTER(EAP
, FAILURE
);
1300 else if (sm
->decision
== DECISION_SUCCESS
)
1301 SM_ENTER(EAP
, SUCCESS
);
1302 else if (sm
->decision
== DECISION_PASSTHROUGH
)
1303 SM_ENTER(EAP
, INITIALIZE_PASSTHROUGH
);
1304 else if (sm
->decision
== DECISION_INITIATE_REAUTH_START
)
1305 SM_ENTER(EAP
, INITIATE_REAUTH_START
);
1307 else if (sm
->eap_server
&& sm
->erp
&& sm
->rxInitiate
)
1308 SM_ENTER(EAP
, INITIATE_RECEIVED
);
1309 #endif /* CONFIG_ERP */
1311 SM_ENTER(EAP
, PROPOSE_METHOD
);
1313 case EAP_INITIATE_REAUTH_START
:
1314 SM_ENTER(EAP
, SEND_REQUEST
);
1316 case EAP_INITIATE_RECEIVED
:
1317 if (!sm
->eap_server
)
1318 SM_ENTER(EAP
, SELECT_ACTION
);
1320 case EAP_TIMEOUT_FAILURE
:
1327 case EAP_INITIALIZE_PASSTHROUGH
:
1328 if (sm
->currentId
== -1)
1329 SM_ENTER(EAP
, AAA_IDLE
);
1331 SM_ENTER(EAP
, AAA_REQUEST
);
1334 if (sm
->eap_if
.eapResp
)
1335 SM_ENTER(EAP
, RECEIVED2
);
1336 else if (sm
->eap_if
.retransWhile
== 0)
1337 SM_ENTER(EAP
, RETRANSMIT2
);
1339 case EAP_RETRANSMIT2
:
1340 if (sm
->retransCount
> sm
->MaxRetrans
)
1341 SM_ENTER(EAP
, TIMEOUT_FAILURE2
);
1343 SM_ENTER(EAP
, IDLE2
);
1346 if (sm
->rxResp
&& (sm
->respId
== sm
->currentId
))
1347 SM_ENTER(EAP
, AAA_REQUEST
);
1349 SM_ENTER(EAP
, DISCARD2
);
1352 SM_ENTER(EAP
, IDLE2
);
1354 case EAP_SEND_REQUEST2
:
1355 SM_ENTER(EAP
, IDLE2
);
1357 case EAP_AAA_REQUEST
:
1358 SM_ENTER(EAP
, AAA_IDLE
);
1360 case EAP_AAA_RESPONSE
:
1361 SM_ENTER(EAP
, SEND_REQUEST2
);
1364 if (sm
->eap_if
.aaaFail
)
1365 SM_ENTER(EAP
, FAILURE2
);
1366 else if (sm
->eap_if
.aaaSuccess
)
1367 SM_ENTER(EAP
, SUCCESS2
);
1368 else if (sm
->eap_if
.aaaEapReq
)
1369 SM_ENTER(EAP
, AAA_RESPONSE
);
1370 else if (sm
->eap_if
.aaaTimeout
)
1371 SM_ENTER(EAP
, TIMEOUT_FAILURE2
);
1373 case EAP_TIMEOUT_FAILURE2
:
1383 static int eap_sm_calculateTimeout(struct eap_sm
*sm
, int retransCount
,
1384 int eapSRTT
, int eapRTTVAR
,
1389 if (sm
->try_initiate_reauth
) {
1390 wpa_printf(MSG_DEBUG
,
1391 "EAP: retransmit timeout 1 second for EAP-Initiate-Re-auth-Start");
1395 if (methodTimeout
) {
1397 * EAP method (either internal or through AAA server, provided
1398 * timeout hint. Use that as-is as a timeout for retransmitting
1399 * the EAP request if no response is received.
1401 wpa_printf(MSG_DEBUG
, "EAP: retransmit timeout %d seconds "
1402 "(from EAP method hint)", methodTimeout
);
1403 return methodTimeout
;
1407 * RFC 3748 recommends algorithms described in RFC 2988 for estimation
1408 * of the retransmission timeout. This should be implemented once
1409 * round-trip time measurements are available. For nowm a simple
1410 * backoff mechanism is used instead if there are no EAP method
1413 * SRTT = smoothed round-trip time
1414 * RTTVAR = round-trip time variation
1415 * RTO = retransmission timeout
1419 * RFC 2988, 2.1: before RTT measurement, set RTO to 3 seconds for
1420 * initial retransmission and then double the RTO to provide back off
1421 * per 5.5. Limit the maximum RTO to 20 seconds per RFC 3748, 4.3
1425 for (i
= 0; i
< retransCount
; i
++) {
1433 wpa_printf(MSG_DEBUG
, "EAP: retransmit timeout %d seconds "
1434 "(from dynamic back off; retransCount=%d)",
1441 static void eap_sm_parseEapResp(struct eap_sm
*sm
, const struct wpabuf
*resp
)
1443 const struct eap_hdr
*hdr
;
1446 /* parse rxResp, respId, respMethod */
1448 sm
->rxInitiate
= FALSE
;
1450 sm
->respMethod
= EAP_TYPE_NONE
;
1451 sm
->respVendor
= EAP_VENDOR_IETF
;
1452 sm
->respVendorMethod
= EAP_TYPE_NONE
;
1454 if (resp
== NULL
|| wpabuf_len(resp
) < sizeof(*hdr
)) {
1455 wpa_printf(MSG_DEBUG
, "EAP: parseEapResp: invalid resp=%p "
1457 resp
? (unsigned long) wpabuf_len(resp
) : 0);
1461 hdr
= wpabuf_head(resp
);
1462 plen
= be_to_host16(hdr
->length
);
1463 if (plen
> wpabuf_len(resp
)) {
1464 wpa_printf(MSG_DEBUG
, "EAP: Ignored truncated EAP-Packet "
1465 "(len=%lu plen=%lu)",
1466 (unsigned long) wpabuf_len(resp
),
1467 (unsigned long) plen
);
1471 sm
->respId
= hdr
->identifier
;
1473 if (hdr
->code
== EAP_CODE_RESPONSE
)
1475 else if (hdr
->code
== EAP_CODE_INITIATE
)
1476 sm
->rxInitiate
= TRUE
;
1478 if (plen
> sizeof(*hdr
)) {
1479 u8
*pos
= (u8
*) (hdr
+ 1);
1480 sm
->respMethod
= *pos
++;
1481 if (sm
->respMethod
== EAP_TYPE_EXPANDED
) {
1482 if (plen
< sizeof(*hdr
) + 8) {
1483 wpa_printf(MSG_DEBUG
, "EAP: Ignored truncated "
1484 "expanded EAP-Packet (plen=%lu)",
1485 (unsigned long) plen
);
1488 sm
->respVendor
= WPA_GET_BE24(pos
);
1490 sm
->respVendorMethod
= WPA_GET_BE32(pos
);
1494 wpa_printf(MSG_DEBUG
,
1495 "EAP: parseEapResp: rxResp=%d rxInitiate=%d respId=%d respMethod=%u respVendor=%u respVendorMethod=%u",
1496 sm
->rxResp
, sm
->rxInitiate
, sm
->respId
, sm
->respMethod
,
1497 sm
->respVendor
, sm
->respVendorMethod
);
1501 static int eap_sm_getId(const struct wpabuf
*data
)
1503 const struct eap_hdr
*hdr
;
1505 if (data
== NULL
|| wpabuf_len(data
) < sizeof(*hdr
))
1508 hdr
= wpabuf_head(data
);
1509 wpa_printf(MSG_DEBUG
, "EAP: getId: id=%d", hdr
->identifier
);
1510 return hdr
->identifier
;
1514 static struct wpabuf
* eap_sm_buildSuccess(struct eap_sm
*sm
, u8 id
)
1517 struct eap_hdr
*resp
;
1518 wpa_printf(MSG_DEBUG
, "EAP: Building EAP-Success (id=%d)", id
);
1520 msg
= wpabuf_alloc(sizeof(*resp
));
1523 resp
= wpabuf_put(msg
, sizeof(*resp
));
1524 resp
->code
= EAP_CODE_SUCCESS
;
1525 resp
->identifier
= id
;
1526 resp
->length
= host_to_be16(sizeof(*resp
));
1532 static struct wpabuf
* eap_sm_buildFailure(struct eap_sm
*sm
, u8 id
)
1535 struct eap_hdr
*resp
;
1536 wpa_printf(MSG_DEBUG
, "EAP: Building EAP-Failure (id=%d)", id
);
1538 msg
= wpabuf_alloc(sizeof(*resp
));
1541 resp
= wpabuf_put(msg
, sizeof(*resp
));
1542 resp
->code
= EAP_CODE_FAILURE
;
1543 resp
->identifier
= id
;
1544 resp
->length
= host_to_be16(sizeof(*resp
));
1550 static int eap_sm_nextId(struct eap_sm
*sm
, int id
)
1553 /* RFC 3748 Ch 4.1: recommended to initialize Identifier with a
1556 if (id
!= sm
->lastId
)
1559 return (id
+ 1) & 0xff;
1564 * eap_sm_process_nak - Process EAP-Response/Nak
1565 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1566 * @nak_list: Nak list (allowed methods) from the supplicant
1567 * @len: Length of nak_list in bytes
1569 * This function is called when EAP-Response/Nak is received from the
1570 * supplicant. This can happen for both phase 1 and phase 2 authentications.
1572 void eap_sm_process_nak(struct eap_sm
*sm
, const u8
*nak_list
, size_t len
)
1577 if (sm
->user
== NULL
)
1580 wpa_printf(MSG_MSGDUMP
, "EAP: processing NAK (current EAP method "
1581 "index %d)", sm
->user_eap_method_index
);
1583 wpa_hexdump(MSG_MSGDUMP
, "EAP: configured methods",
1584 (u8
*) sm
->user
->methods
,
1585 EAP_MAX_METHODS
* sizeof(sm
->user
->methods
[0]));
1586 wpa_hexdump(MSG_MSGDUMP
, "EAP: list of methods supported by the peer",
1589 i
= sm
->user_eap_method_index
;
1590 while (i
< EAP_MAX_METHODS
&&
1591 (sm
->user
->methods
[i
].vendor
!= EAP_VENDOR_IETF
||
1592 sm
->user
->methods
[i
].method
!= EAP_TYPE_NONE
)) {
1593 if (sm
->user
->methods
[i
].vendor
!= EAP_VENDOR_IETF
)
1595 for (j
= 0; j
< len
; j
++) {
1596 if (nak_list
[j
] == sm
->user
->methods
[i
].method
) {
1608 /* not found - remove from the list */
1609 if (i
+ 1 < EAP_MAX_METHODS
) {
1610 os_memmove(&sm
->user
->methods
[i
],
1611 &sm
->user
->methods
[i
+ 1],
1612 (EAP_MAX_METHODS
- i
- 1) *
1613 sizeof(sm
->user
->methods
[0]));
1615 sm
->user
->methods
[EAP_MAX_METHODS
- 1].vendor
=
1617 sm
->user
->methods
[EAP_MAX_METHODS
- 1].method
= EAP_TYPE_NONE
;
1620 wpa_hexdump(MSG_MSGDUMP
, "EAP: new list of configured methods",
1621 (u8
*) sm
->user
->methods
, EAP_MAX_METHODS
*
1622 sizeof(sm
->user
->methods
[0]));
1626 static void eap_sm_Policy_update(struct eap_sm
*sm
, const u8
*nak_list
,
1629 if (nak_list
== NULL
|| sm
== NULL
|| sm
->user
== NULL
)
1632 if (sm
->user
->phase2
) {
1633 wpa_printf(MSG_DEBUG
, "EAP: EAP-Nak received after Phase2 user"
1634 " info was selected - reject");
1635 sm
->decision
= DECISION_FAILURE
;
1639 eap_sm_process_nak(sm
, nak_list
, len
);
1643 static EapType
eap_sm_Policy_getNextMethod(struct eap_sm
*sm
, int *vendor
)
1646 int idx
= sm
->user_eap_method_index
;
1648 /* In theory, there should be no problems with starting
1649 * re-authentication with something else than EAP-Request/Identity and
1650 * this does indeed work with wpa_supplicant. However, at least Funk
1651 * Supplicant seemed to ignore re-auth if it skipped
1652 * EAP-Request/Identity.
1653 * Re-auth sets currentId == -1, so that can be used here to select
1654 * whether Identity needs to be requested again. */
1655 if (sm
->identity
== NULL
|| sm
->currentId
== -1) {
1656 *vendor
= EAP_VENDOR_IETF
;
1657 next
= EAP_TYPE_IDENTITY
;
1658 sm
->update_user
= TRUE
;
1659 } else if (sm
->user
&& idx
< EAP_MAX_METHODS
&&
1660 (sm
->user
->methods
[idx
].vendor
!= EAP_VENDOR_IETF
||
1661 sm
->user
->methods
[idx
].method
!= EAP_TYPE_NONE
)) {
1662 *vendor
= sm
->user
->methods
[idx
].vendor
;
1663 next
= sm
->user
->methods
[idx
].method
;
1664 sm
->user_eap_method_index
++;
1666 *vendor
= EAP_VENDOR_IETF
;
1667 next
= EAP_TYPE_NONE
;
1669 wpa_printf(MSG_DEBUG
, "EAP: getNextMethod: vendor %d type %d",
1675 static int eap_sm_Policy_getDecision(struct eap_sm
*sm
)
1677 if (!sm
->eap_server
&& sm
->identity
&& !sm
->start_reauth
) {
1678 wpa_printf(MSG_DEBUG
, "EAP: getDecision: -> PASSTHROUGH");
1679 return DECISION_PASSTHROUGH
;
1682 if (sm
->m
&& sm
->currentMethod
!= EAP_TYPE_IDENTITY
&&
1683 sm
->m
->isSuccess(sm
, sm
->eap_method_priv
)) {
1684 wpa_printf(MSG_DEBUG
, "EAP: getDecision: method succeeded -> "
1686 sm
->update_user
= TRUE
;
1687 return DECISION_SUCCESS
;
1690 if (sm
->m
&& sm
->m
->isDone(sm
, sm
->eap_method_priv
) &&
1691 !sm
->m
->isSuccess(sm
, sm
->eap_method_priv
)) {
1692 wpa_printf(MSG_DEBUG
, "EAP: getDecision: method failed -> "
1694 sm
->update_user
= TRUE
;
1695 return DECISION_FAILURE
;
1698 if ((sm
->user
== NULL
|| sm
->update_user
) && sm
->identity
&&
1699 !sm
->start_reauth
) {
1701 * Allow Identity method to be started once to allow identity
1702 * selection hint to be sent from the authentication server,
1703 * but prevent a loop of Identity requests by only allowing
1704 * this to happen once.
1707 if (sm
->user
&& sm
->currentMethod
== EAP_TYPE_IDENTITY
&&
1708 sm
->user
->methods
[0].vendor
== EAP_VENDOR_IETF
&&
1709 sm
->user
->methods
[0].method
== EAP_TYPE_IDENTITY
)
1711 if (eap_user_get(sm
, sm
->identity
, sm
->identity_len
, 0) != 0) {
1712 wpa_printf(MSG_DEBUG
, "EAP: getDecision: user not "
1713 "found from database -> FAILURE");
1714 return DECISION_FAILURE
;
1716 if (id_req
&& sm
->user
&&
1717 sm
->user
->methods
[0].vendor
== EAP_VENDOR_IETF
&&
1718 sm
->user
->methods
[0].method
== EAP_TYPE_IDENTITY
) {
1719 wpa_printf(MSG_DEBUG
, "EAP: getDecision: stop "
1720 "identity request loop -> FAILURE");
1721 sm
->update_user
= TRUE
;
1722 return DECISION_FAILURE
;
1724 sm
->update_user
= FALSE
;
1726 sm
->start_reauth
= FALSE
;
1728 if (sm
->user
&& sm
->user_eap_method_index
< EAP_MAX_METHODS
&&
1729 (sm
->user
->methods
[sm
->user_eap_method_index
].vendor
!=
1731 sm
->user
->methods
[sm
->user_eap_method_index
].method
!=
1733 wpa_printf(MSG_DEBUG
, "EAP: getDecision: another method "
1734 "available -> CONTINUE");
1735 return DECISION_CONTINUE
;
1738 if (!sm
->identity
&& eap_get_erp_send_reauth_start(sm
) &&
1739 !sm
->initiate_reauth_start_sent
) {
1740 wpa_printf(MSG_DEBUG
,
1741 "EAP: getDecision: send EAP-Initiate/Re-auth-Start");
1742 return DECISION_INITIATE_REAUTH_START
;
1745 if (sm
->identity
== NULL
|| sm
->currentId
== -1) {
1746 wpa_printf(MSG_DEBUG
, "EAP: getDecision: no identity known "
1748 return DECISION_CONTINUE
;
1751 wpa_printf(MSG_DEBUG
, "EAP: getDecision: no more methods available -> "
1753 return DECISION_FAILURE
;
1757 static Boolean
eap_sm_Policy_doPickUp(struct eap_sm
*sm
, EapType method
)
1759 return method
== EAP_TYPE_IDENTITY
? TRUE
: FALSE
;
1764 * eap_server_sm_step - Step EAP server state machine
1765 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1766 * Returns: 1 if EAP state was changed or 0 if not
1768 * This function advances EAP state machine to a new state to match with the
1769 * current variables. This should be called whenever variables used by the EAP
1770 * state machine have changed.
1772 int eap_server_sm_step(struct eap_sm
*sm
)
1776 sm
->changed
= FALSE
;
1780 } while (sm
->changed
);
1785 static void eap_user_free(struct eap_user
*user
)
1789 bin_clear_free(user
->password
, user
->password_len
);
1790 user
->password
= NULL
;
1796 * eap_server_sm_init - Allocate and initialize EAP server state machine
1797 * @eapol_ctx: Context data to be used with eapol_cb calls
1798 * @eapol_cb: Pointer to EAPOL callback functions
1799 * @conf: EAP configuration
1800 * Returns: Pointer to the allocated EAP state machine or %NULL on failure
1802 * This function allocates and initializes an EAP state machine.
1804 struct eap_sm
* eap_server_sm_init(void *eapol_ctx
,
1805 struct eapol_callbacks
*eapol_cb
,
1806 struct eap_config
*conf
)
1810 sm
= os_zalloc(sizeof(*sm
));
1813 sm
->eapol_ctx
= eapol_ctx
;
1814 sm
->eapol_cb
= eapol_cb
;
1815 sm
->MaxRetrans
= 5; /* RFC 3748: max 3-5 retransmissions suggested */
1816 sm
->ssl_ctx
= conf
->ssl_ctx
;
1817 sm
->msg_ctx
= conf
->msg_ctx
;
1818 sm
->eap_sim_db_priv
= conf
->eap_sim_db_priv
;
1819 sm
->backend_auth
= conf
->backend_auth
;
1820 sm
->eap_server
= conf
->eap_server
;
1821 if (conf
->pac_opaque_encr_key
) {
1822 sm
->pac_opaque_encr_key
= os_malloc(16);
1823 if (sm
->pac_opaque_encr_key
) {
1824 os_memcpy(sm
->pac_opaque_encr_key
,
1825 conf
->pac_opaque_encr_key
, 16);
1828 if (conf
->eap_fast_a_id
) {
1829 sm
->eap_fast_a_id
= os_malloc(conf
->eap_fast_a_id_len
);
1830 if (sm
->eap_fast_a_id
) {
1831 os_memcpy(sm
->eap_fast_a_id
, conf
->eap_fast_a_id
,
1832 conf
->eap_fast_a_id_len
);
1833 sm
->eap_fast_a_id_len
= conf
->eap_fast_a_id_len
;
1836 if (conf
->eap_fast_a_id_info
)
1837 sm
->eap_fast_a_id_info
= os_strdup(conf
->eap_fast_a_id_info
);
1838 sm
->eap_fast_prov
= conf
->eap_fast_prov
;
1839 sm
->pac_key_lifetime
= conf
->pac_key_lifetime
;
1840 sm
->pac_key_refresh_time
= conf
->pac_key_refresh_time
;
1841 sm
->eap_sim_aka_result_ind
= conf
->eap_sim_aka_result_ind
;
1842 sm
->tnc
= conf
->tnc
;
1843 sm
->wps
= conf
->wps
;
1844 if (conf
->assoc_wps_ie
)
1845 sm
->assoc_wps_ie
= wpabuf_dup(conf
->assoc_wps_ie
);
1846 if (conf
->assoc_p2p_ie
)
1847 sm
->assoc_p2p_ie
= wpabuf_dup(conf
->assoc_p2p_ie
);
1848 if (conf
->peer_addr
)
1849 os_memcpy(sm
->peer_addr
, conf
->peer_addr
, ETH_ALEN
);
1850 sm
->fragment_size
= conf
->fragment_size
;
1851 sm
->pwd_group
= conf
->pwd_group
;
1852 sm
->pbc_in_m1
= conf
->pbc_in_m1
;
1853 sm
->server_id
= conf
->server_id
;
1854 sm
->server_id_len
= conf
->server_id_len
;
1855 sm
->erp
= conf
->erp
;
1857 #ifdef CONFIG_TESTING_OPTIONS
1858 sm
->tls_test_flags
= conf
->tls_test_flags
;
1859 #endif /* CONFIG_TESTING_OPTIONS */
1861 wpa_printf(MSG_DEBUG
, "EAP: Server state machine created");
1868 * eap_server_sm_deinit - Deinitialize and free an EAP server state machine
1869 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1871 * This function deinitializes EAP state machine and frees all allocated
1874 void eap_server_sm_deinit(struct eap_sm
*sm
)
1878 wpa_printf(MSG_DEBUG
, "EAP: Server state machine removed");
1879 if (sm
->m
&& sm
->eap_method_priv
)
1880 sm
->m
->reset(sm
, sm
->eap_method_priv
);
1881 wpabuf_free(sm
->eap_if
.eapReqData
);
1882 bin_clear_free(sm
->eap_if
.eapKeyData
, sm
->eap_if
.eapKeyDataLen
);
1883 os_free(sm
->eap_if
.eapSessionId
);
1884 wpabuf_free(sm
->lastReqData
);
1885 wpabuf_free(sm
->eap_if
.eapRespData
);
1886 os_free(sm
->identity
);
1887 os_free(sm
->pac_opaque_encr_key
);
1888 os_free(sm
->eap_fast_a_id
);
1889 os_free(sm
->eap_fast_a_id_info
);
1890 wpabuf_free(sm
->eap_if
.aaaEapReqData
);
1891 wpabuf_free(sm
->eap_if
.aaaEapRespData
);
1892 bin_clear_free(sm
->eap_if
.aaaEapKeyData
, sm
->eap_if
.aaaEapKeyDataLen
);
1893 eap_user_free(sm
->user
);
1894 wpabuf_free(sm
->assoc_wps_ie
);
1895 wpabuf_free(sm
->assoc_p2p_ie
);
1901 * eap_sm_notify_cached - Notify EAP state machine of cached PMK
1902 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1904 * This function is called when PMKSA caching is used to skip EAP
1907 void eap_sm_notify_cached(struct eap_sm
*sm
)
1912 sm
->EAP_state
= EAP_SUCCESS
;
1917 * eap_sm_pending_cb - EAP state machine callback for a pending EAP request
1918 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1920 * This function is called when data for a pending EAP-Request is received.
1922 void eap_sm_pending_cb(struct eap_sm
*sm
)
1926 wpa_printf(MSG_DEBUG
, "EAP: Callback for pending request received");
1927 if (sm
->method_pending
== METHOD_PENDING_WAIT
)
1928 sm
->method_pending
= METHOD_PENDING_CONT
;
1933 * eap_sm_method_pending - Query whether EAP method is waiting for pending data
1934 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1935 * Returns: 1 if method is waiting for pending data or 0 if not
1937 int eap_sm_method_pending(struct eap_sm
*sm
)
1941 return sm
->method_pending
== METHOD_PENDING_WAIT
;
1946 * eap_get_identity - Get the user identity (from EAP-Response/Identity)
1947 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1948 * @len: Buffer for returning identity length
1949 * Returns: Pointer to the user identity or %NULL if not available
1951 const u8
* eap_get_identity(struct eap_sm
*sm
, size_t *len
)
1953 *len
= sm
->identity_len
;
1954 return sm
->identity
;
1959 * eap_get_interface - Get pointer to EAP-EAPOL interface data
1960 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1961 * Returns: Pointer to the EAP-EAPOL interface data
1963 struct eap_eapol_interface
* eap_get_interface(struct eap_sm
*sm
)
1970 * eap_server_clear_identity - Clear EAP identity information
1971 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1973 * This function can be used to clear the EAP identity information in the EAP
1974 * server context. This allows the EAP/Identity method to be used again after
1975 * EAPOL-Start or EAPOL-Logoff.
1977 void eap_server_clear_identity(struct eap_sm
*sm
)
1979 os_free(sm
->identity
);
1980 sm
->identity
= NULL
;