2 * hostapd / EAP-AKA (RFC 4187)
3 * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
21 #include "eap_sim_common.h"
22 #include "eap_sim_db.h"
26 u8 mk[EAP_SIM_MK_LEN];
27 u8 nonce_s[EAP_SIM_NONCE_S_LEN];
28 u8 k_aut[EAP_SIM_K_AUT_LEN];
29 u8 k_encr[EAP_SIM_K_ENCR_LEN];
30 u8 msk[EAP_SIM_KEYING_DATA_LEN];
31 u8 emsk[EAP_EMSK_LEN];
32 u8 rand[EAP_AKA_RAND_LEN];
33 u8 autn[EAP_AKA_AUTN_LEN];
34 u8 ck[EAP_AKA_CK_LEN];
35 u8 ik[EAP_AKA_IK_LEN];
36 u8 res[EAP_AKA_RES_MAX_LEN];
39 IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
44 struct eap_sim_reauth *reauth;
45 int auts_reported; /* whether the current AUTS has been reported to the
51 static void eap_aka_determine_identity(struct eap_sm *sm,
52 struct eap_aka_data *data,
53 int before_identity, int after_reauth);
56 static const char * eap_aka_state_txt(int state)
70 return "NOTIFICATION";
77 static void eap_aka_state(struct eap_aka_data *data, int state)
79 wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
80 eap_aka_state_txt(data->state),
81 eap_aka_state_txt(state));
86 static void * eap_aka_init(struct eap_sm *sm)
88 struct eap_aka_data *data;
90 if (sm->eap_sim_db_priv == NULL) {
91 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
95 data = wpa_zalloc(sizeof(*data));
98 data->state = IDENTITY;
99 eap_aka_determine_identity(sm, data, 1, 0);
105 static void eap_aka_reset(struct eap_sm *sm, void *priv)
107 struct eap_aka_data *data = priv;
108 free(data->next_pseudonym);
109 free(data->next_reauth_id);
114 static u8 * eap_aka_build_identity(struct eap_sm *sm,
115 struct eap_aka_data *data,
116 int id, size_t *reqDataLen)
118 struct eap_sim_msg *msg;
120 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity");
121 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_AKA,
122 EAP_AKA_SUBTYPE_IDENTITY);
123 if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
125 wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ");
126 eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
129 * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is
130 * ignored and the AKA/Identity is used to request the
133 wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ");
134 eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
136 return eap_sim_msg_finish(msg, reqDataLen, NULL, NULL, 0);
140 static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
141 struct eap_sim_msg *msg, u16 counter,
144 free(data->next_pseudonym);
145 data->next_pseudonym =
146 eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1);
147 free(data->next_reauth_id);
148 if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
149 data->next_reauth_id =
150 eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 1);
152 wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication "
153 "count exceeded - force full authentication");
154 data->next_reauth_id = NULL;
157 if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
158 counter == 0 && nonce_s == NULL)
161 wpa_printf(MSG_DEBUG, " AT_IV");
162 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
163 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
166 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter);
167 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
171 wpa_printf(MSG_DEBUG, " *AT_NONCE_S");
172 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
173 EAP_SIM_NONCE_S_LEN);
176 if (data->next_pseudonym) {
177 wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)",
178 data->next_pseudonym);
179 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
180 strlen(data->next_pseudonym),
181 (u8 *) data->next_pseudonym,
182 strlen(data->next_pseudonym));
185 if (data->next_reauth_id) {
186 wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)",
187 data->next_reauth_id);
188 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
189 strlen(data->next_reauth_id),
190 (u8 *) data->next_reauth_id,
191 strlen(data->next_reauth_id));
194 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
195 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
204 static u8 * eap_aka_build_challenge(struct eap_sm *sm,
205 struct eap_aka_data *data,
206 int id, size_t *reqDataLen)
208 struct eap_sim_msg *msg;
210 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge");
211 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_AKA,
212 EAP_AKA_SUBTYPE_CHALLENGE);
213 wpa_printf(MSG_DEBUG, " AT_RAND");
214 eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN);
215 eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN);
217 if (eap_aka_build_encr(sm, data, msg, 0, NULL)) {
218 eap_sim_msg_free(msg);
222 wpa_printf(MSG_DEBUG, " AT_MAC");
223 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
224 return eap_sim_msg_finish(msg, reqDataLen, data->k_aut, NULL, 0);
228 static u8 * eap_aka_build_reauth(struct eap_sm *sm,
229 struct eap_aka_data *data,
230 int id, size_t *reqDataLen)
232 struct eap_sim_msg *msg;
234 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication");
236 if (hostapd_get_rand(data->nonce_s, EAP_SIM_NONCE_S_LEN))
238 wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
239 data->nonce_s, EAP_SIM_NONCE_S_LEN);
241 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
243 eap_sim_derive_keys_reauth(data->counter, sm->identity,
244 sm->identity_len, data->nonce_s, data->mk,
245 data->msk, data->emsk);
247 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_AKA,
248 EAP_AKA_SUBTYPE_REAUTHENTICATION);
250 if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
251 eap_sim_msg_free(msg);
255 wpa_printf(MSG_DEBUG, " AT_MAC");
256 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
257 return eap_sim_msg_finish(msg, reqDataLen, data->k_aut, NULL, 0);
261 static u8 * eap_aka_build_notification(struct eap_sm *sm,
262 struct eap_aka_data *data,
263 int id, size_t *reqDataLen)
265 struct eap_sim_msg *msg;
267 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification");
268 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_AKA,
269 EAP_AKA_SUBTYPE_NOTIFICATION);
270 wpa_printf(MSG_DEBUG, " AT_NOTIFICATION");
271 eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
273 return eap_sim_msg_finish(msg, reqDataLen, NULL, NULL, 0);
277 static u8 * eap_aka_buildReq(struct eap_sm *sm, void *priv, int id,
280 struct eap_aka_data *data = priv;
282 data->auts_reported = 0;
283 switch (data->state) {
285 return eap_aka_build_identity(sm, data, id, reqDataLen);
287 return eap_aka_build_challenge(sm, data, id, reqDataLen);
289 return eap_aka_build_reauth(sm, data, id, reqDataLen);
291 return eap_aka_build_notification(sm, data, id, reqDataLen);
293 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
294 "buildReq", data->state);
301 static Boolean eap_aka_check(struct eap_sm *sm, void *priv,
302 u8 *respData, size_t respDataLen)
304 struct eap_hdr *resp;
307 resp = (struct eap_hdr *) respData;
308 pos = (u8 *) (resp + 1);
309 if (respDataLen < sizeof(*resp) + 4 || *pos != EAP_TYPE_AKA ||
310 (ntohs(resp->length)) > respDataLen) {
311 wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
319 static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
321 if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR ||
322 subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT)
325 switch (data->state) {
327 if (subtype != EAP_AKA_SUBTYPE_IDENTITY) {
328 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
329 "subtype %d", subtype);
334 if (subtype != EAP_AKA_SUBTYPE_CHALLENGE &&
335 subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
336 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
337 "subtype %d", subtype);
342 if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) {
343 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
344 "subtype %d", subtype);
349 if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) {
350 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
351 "subtype %d", subtype);
356 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for "
357 "processing a response", data->state);
365 static void eap_aka_determine_identity(struct eap_sm *sm,
366 struct eap_aka_data *data,
367 int before_identity, int after_reauth)
376 if (after_reauth && data->reauth) {
377 identity = data->reauth->identity;
378 identity_len = data->reauth->identity_len;
379 } else if (sm->identity && sm->identity_len > 0 &&
380 sm->identity[0] == EAP_AKA_PERMANENT_PREFIX) {
381 identity = sm->identity;
382 identity_len = sm->identity_len;
384 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv,
388 if (identity == NULL) {
389 data->reauth = eap_sim_db_get_reauth_entry(
390 sm->eap_sim_db_priv, sm->identity,
393 wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast "
394 "re-authentication");
395 identity = data->reauth->identity;
396 identity_len = data->reauth->identity_len;
397 data->counter = data->reauth->counter;
398 memcpy(data->mk, data->reauth->mk,
404 if (identity == NULL ||
405 eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
406 sm->identity_len) < 0) {
407 if (before_identity) {
408 wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name "
409 "not known - send AKA-Identity request");
410 eap_aka_state(data, IDENTITY);
413 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the "
414 "permanent user name is known; try to use "
416 /* eap_sim_db_get_aka_auth() will report failure, if
417 * this identity is not known. */
421 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
422 identity, identity_len);
424 if (!after_reauth && data->reauth) {
425 eap_aka_state(data, REAUTH);
429 res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity,
430 identity_len, data->rand, data->autn,
431 data->ik, data->ck, data->res,
433 if (res == EAP_SIM_DB_PENDING) {
434 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
435 "not yet available - pending request");
436 sm->method_pending = METHOD_PENDING_WAIT;
441 data->counter = 0; /* reset re-auth counter since this is full auth */
444 wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA "
445 "authentication data for the peer");
446 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
447 eap_aka_state(data, NOTIFICATION);
450 if (sm->method_pending == METHOD_PENDING_WAIT) {
451 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
452 "available - abort pending wait");
453 sm->method_pending = METHOD_PENDING_NONE;
456 identity_len = sm->identity_len;
457 while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
458 wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null "
459 "character from identity");
462 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation",
463 sm->identity, identity_len);
465 eap_aka_derive_mk(sm->identity, identity_len, data->ik, data->ck,
467 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
470 eap_aka_state(data, CHALLENGE);
474 static void eap_aka_process_identity(struct eap_sm *sm,
475 struct eap_aka_data *data,
476 u8 *respData, size_t respDataLen,
477 struct eap_sim_attrs *attr)
479 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity");
481 if (attr->mac || attr->iv || attr->encr_data) {
482 wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute "
483 "received in EAP-Response/AKA-Identity");
484 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
485 eap_aka_state(data, NOTIFICATION);
489 if (attr->identity) {
491 sm->identity = malloc(attr->identity_len);
493 memcpy(sm->identity, attr->identity,
495 sm->identity_len = attr->identity_len;
499 eap_aka_determine_identity(sm, data, 0, 0);
503 static void eap_aka_process_challenge(struct eap_sm *sm,
504 struct eap_aka_data *data,
505 u8 *respData, size_t respDataLen,
506 struct eap_sim_attrs *attr)
511 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
513 if (attr->mac == NULL ||
514 eap_sim_verify_mac(data->k_aut, respData, respDataLen, attr->mac,
516 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
517 "did not include valid AT_MAC");
518 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
519 eap_aka_state(data, NOTIFICATION);
523 if (attr->res == NULL || attr->res_len != data->res_len ||
524 memcmp(attr->res, data->res, data->res_len) != 0) {
525 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
526 "include valid AT_RES");
527 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
528 eap_aka_state(data, NOTIFICATION);
532 wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the "
534 eap_aka_state(data, SUCCESS);
536 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity,
537 sm->identity_len, &identity_len);
538 if (identity == NULL) {
539 identity = sm->identity;
540 identity_len = sm->identity_len;
543 if (data->next_pseudonym) {
544 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
546 data->next_pseudonym);
547 data->next_pseudonym = NULL;
549 if (data->next_reauth_id) {
550 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
552 data->next_reauth_id, data->counter + 1,
554 data->next_reauth_id = NULL;
559 static void eap_aka_process_sync_failure(struct eap_sm *sm,
560 struct eap_aka_data *data,
561 u8 *respData, size_t respDataLen,
562 struct eap_sim_attrs *attr)
564 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure");
566 if (attr->auts == NULL) {
567 wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure "
568 "message did not include valid AT_AUTS");
569 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
570 eap_aka_state(data, NOTIFICATION);
574 /* Avoid re-reporting AUTS when processing pending EAP packet by
575 * maintaining a local flag stating whether this AUTS has already been
577 if (!data->auts_reported &&
578 eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity,
579 sm->identity_len, attr->auts,
581 wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
582 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
583 eap_aka_state(data, NOTIFICATION);
586 data->auts_reported = 1;
588 /* Try again after resynchronization */
589 eap_aka_determine_identity(sm, data, 0, 0);
593 static void eap_aka_process_reauth(struct eap_sm *sm,
594 struct eap_aka_data *data,
595 u8 *respData, size_t respDataLen,
596 struct eap_sim_attrs *attr)
598 struct eap_sim_attrs eattr;
599 u8 *decrypted = NULL;
600 const u8 *identity, *id2;
601 size_t identity_len, id2_len;
603 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
605 if (attr->mac == NULL ||
606 eap_sim_verify_mac(data->k_aut, respData, respDataLen, attr->mac,
607 data->nonce_s, EAP_SIM_NONCE_S_LEN)) {
608 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
609 "did not include valid AT_MAC");
613 if (attr->encr_data == NULL || attr->iv == NULL) {
614 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
615 "message did not include encrypted data");
619 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
620 attr->encr_data_len, attr->iv, &eattr,
622 if (decrypted == NULL) {
623 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
624 "data from reauthentication message");
628 if (eattr.counter != data->counter) {
629 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
630 "used incorrect counter %u, expected %u",
631 eattr.counter, data->counter);
637 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes "
638 "the correct AT_MAC");
640 if (eattr.counter_too_small) {
641 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
642 "included AT_COUNTER_TOO_SMALL - starting full "
644 eap_aka_determine_identity(sm, data, 0, 1);
648 eap_aka_state(data, SUCCESS);
651 identity = data->reauth->identity;
652 identity_len = data->reauth->identity_len;
654 identity = sm->identity;
655 identity_len = sm->identity_len;
658 id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity,
659 identity_len, &id2_len);
662 identity_len = id2_len;
665 if (data->next_pseudonym) {
666 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
667 identity_len, data->next_pseudonym);
668 data->next_pseudonym = NULL;
670 if (data->next_reauth_id) {
671 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
672 identity_len, data->next_reauth_id,
673 data->counter + 1, data->mk);
674 data->next_reauth_id = NULL;
676 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
683 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
684 eap_aka_state(data, NOTIFICATION);
685 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
691 static void eap_aka_process_client_error(struct eap_sm *sm,
692 struct eap_aka_data *data,
693 u8 *respData, size_t respDataLen,
694 struct eap_sim_attrs *attr)
696 wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d",
697 attr->client_error_code);
698 eap_aka_state(data, FAILURE);
702 static void eap_aka_process_authentication_reject(
703 struct eap_sm *sm, struct eap_aka_data *data,
704 u8 *respData, size_t respDataLen, struct eap_sim_attrs *attr)
706 wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication");
707 eap_aka_state(data, FAILURE);
711 static void eap_aka_process_notification(struct eap_sm *sm,
712 struct eap_aka_data *data,
713 u8 *respData, size_t respDataLen,
714 struct eap_sim_attrs *attr)
716 wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification");
717 eap_aka_state(data, FAILURE);
721 static void eap_aka_process(struct eap_sm *sm, void *priv,
722 u8 *respData, size_t respDataLen)
724 struct eap_aka_data *data = priv;
725 struct eap_hdr *resp;
728 struct eap_sim_attrs attr;
730 resp = (struct eap_hdr *) respData;
731 pos = (u8 *) (resp + 1);
734 if (eap_aka_subtype_ok(data, subtype)) {
735 wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected "
736 "EAP-AKA Subtype in EAP Response");
737 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
738 eap_aka_state(data, NOTIFICATION);
742 len = be_to_host16(resp->length);
745 if (eap_sim_parse_attr(pos, respData + len, &attr, 1, 0)) {
746 wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes");
747 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
748 eap_aka_state(data, NOTIFICATION);
752 if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) {
753 eap_aka_process_client_error(sm, data, respData, len, &attr);
757 if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) {
758 eap_aka_process_authentication_reject(sm, data, respData, len,
763 switch (data->state) {
765 eap_aka_process_identity(sm, data, respData, len, &attr);
768 if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
769 eap_aka_process_sync_failure(sm, data, respData, len,
772 eap_aka_process_challenge(sm, data, respData, len,
777 eap_aka_process_reauth(sm, data, respData, len, &attr);
780 eap_aka_process_notification(sm, data, respData, len, &attr);
783 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
784 "process", data->state);
790 static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv)
792 struct eap_aka_data *data = priv;
793 return data->state == SUCCESS || data->state == FAILURE;
797 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
799 struct eap_aka_data *data = priv;
802 if (data->state != SUCCESS)
805 key = malloc(EAP_SIM_KEYING_DATA_LEN);
808 memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
809 *len = EAP_SIM_KEYING_DATA_LEN;
814 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
816 struct eap_aka_data *data = priv;
819 if (data->state != SUCCESS)
822 key = malloc(EAP_EMSK_LEN);
825 memcpy(key, data->emsk, EAP_EMSK_LEN);
831 static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv)
833 struct eap_aka_data *data = priv;
834 return data->state == SUCCESS;
838 int eap_server_aka_register(void)
840 struct eap_method *eap;
843 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
844 EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
848 eap->init = eap_aka_init;
849 eap->reset = eap_aka_reset;
850 eap->buildReq = eap_aka_buildReq;
851 eap->check = eap_aka_check;
852 eap->process = eap_aka_process;
853 eap->isDone = eap_aka_isDone;
854 eap->getKey = eap_aka_getKey;
855 eap->isSuccess = eap_aka_isSuccess;
856 eap->get_emsk = eap_aka_get_emsk;
858 ret = eap_server_method_register(eap);
860 eap_server_method_free(eap);