2 * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf)
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.
18 #include "eap_server/eap_i.h"
19 #include "eap_common/eap_sim_common.h"
20 #include "eap_server/eap_sim_db.h"
27 u8 mk[EAP_SIM_MK_LEN];
28 u8 nonce_s[EAP_SIM_NONCE_S_LEN];
29 u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
30 u8 k_encr[EAP_SIM_K_ENCR_LEN];
31 u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */
32 u8 msk[EAP_SIM_KEYING_DATA_LEN];
33 u8 emsk[EAP_EMSK_LEN];
34 u8 rand[EAP_AKA_RAND_LEN];
35 u8 autn[EAP_AKA_AUTN_LEN];
36 u8 ck[EAP_AKA_CK_LEN];
37 u8 ik[EAP_AKA_IK_LEN];
38 u8 res[EAP_AKA_RES_MAX_LEN];
41 IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
46 struct eap_sim_reauth *reauth;
47 int auts_reported; /* whether the current AUTS has been reported to the
52 struct wpabuf *id_msgs;
56 size_t network_name_len;
61 static void eap_aka_determine_identity(struct eap_sm *sm,
62 struct eap_aka_data *data,
63 int before_identity, int after_reauth);
66 static const char * eap_aka_state_txt(int state)
80 return "NOTIFICATION";
87 static void eap_aka_state(struct eap_aka_data *data, int state)
89 wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
90 eap_aka_state_txt(data->state),
91 eap_aka_state_txt(state));
96 static void * eap_aka_init(struct eap_sm *sm)
98 struct eap_aka_data *data;
100 if (sm->eap_sim_db_priv == NULL) {
101 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
105 data = os_zalloc(sizeof(*data));
109 data->eap_method = EAP_TYPE_AKA;
111 data->state = IDENTITY;
112 eap_aka_determine_identity(sm, data, 1, 0);
113 data->pending_id = -1;
120 static void * eap_aka_prime_init(struct eap_sm *sm)
122 struct eap_aka_data *data;
123 /* TODO: make ANID configurable; see 3GPP TS 24.302 */
124 char *network_name = "WLAN";
126 if (sm->eap_sim_db_priv == NULL) {
127 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
131 data = os_zalloc(sizeof(*data));
135 data->eap_method = EAP_TYPE_AKA_PRIME;
136 data->network_name = os_malloc(os_strlen(network_name));
137 if (data->network_name == NULL) {
142 data->network_name_len = os_strlen(network_name);
143 os_memcpy(data->network_name, network_name, data->network_name_len);
145 data->state = IDENTITY;
146 eap_aka_determine_identity(sm, data, 1, 0);
147 data->pending_id = -1;
151 #endif /* EAP_AKA_PRIME */
154 static void eap_aka_reset(struct eap_sm *sm, void *priv)
156 struct eap_aka_data *data = priv;
157 os_free(data->next_pseudonym);
158 os_free(data->next_reauth_id);
159 wpabuf_free(data->id_msgs);
160 os_free(data->network_name);
165 static int eap_aka_add_id_msg(struct eap_aka_data *data,
166 const struct wpabuf *msg)
171 if (data->id_msgs == NULL) {
172 data->id_msgs = wpabuf_dup(msg);
173 return data->id_msgs == NULL ? -1 : 0;
176 if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
178 wpabuf_put_buf(data->id_msgs, msg);
184 static void eap_aka_add_checkcode(struct eap_aka_data *data,
185 struct eap_sim_msg *msg)
189 u8 hash[SHA256_MAC_LEN];
191 wpa_printf(MSG_DEBUG, " AT_CHECKCODE");
193 if (data->id_msgs == NULL) {
195 * No EAP-AKA/Identity packets were exchanged - send empty
198 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
202 /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
203 addr = wpabuf_head(data->id_msgs);
204 len = wpabuf_len(data->id_msgs);
205 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
206 if (data->eap_method == EAP_TYPE_AKA_PRIME)
207 sha256_vector(1, &addr, &len, hash);
209 sha1_vector(1, &addr, &len, hash);
211 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
212 data->eap_method == EAP_TYPE_AKA_PRIME ?
213 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
217 static int eap_aka_verify_checkcode(struct eap_aka_data *data,
218 const u8 *checkcode, size_t checkcode_len)
222 u8 hash[SHA256_MAC_LEN];
225 if (checkcode == NULL)
228 if (data->id_msgs == NULL) {
229 if (checkcode_len != 0) {
230 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer "
231 "indicates that AKA/Identity messages were "
232 "used, but they were not");
238 hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ?
239 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN;
241 if (checkcode_len != hash_len) {
242 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates "
243 "that AKA/Identity message were not used, but they "
248 /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
249 addr = wpabuf_head(data->id_msgs);
250 len = wpabuf_len(data->id_msgs);
251 if (data->eap_method == EAP_TYPE_AKA_PRIME)
252 sha256_vector(1, &addr, &len, hash);
254 sha1_vector(1, &addr, &len, hash);
256 if (os_memcmp(hash, checkcode, hash_len) != 0) {
257 wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
265 static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm,
266 struct eap_aka_data *data, u8 id)
268 struct eap_sim_msg *msg;
271 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity");
272 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
273 EAP_AKA_SUBTYPE_IDENTITY);
274 if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
276 wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ");
277 eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
280 * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is
281 * ignored and the AKA/Identity is used to request the
284 wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ");
285 eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
287 buf = eap_sim_msg_finish(msg, NULL, NULL, 0);
288 if (eap_aka_add_id_msg(data, buf) < 0) {
292 data->pending_id = id;
297 static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
298 struct eap_sim_msg *msg, u16 counter,
301 os_free(data->next_pseudonym);
302 data->next_pseudonym =
303 eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1);
304 os_free(data->next_reauth_id);
305 if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
306 data->next_reauth_id =
307 eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 1);
309 wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication "
310 "count exceeded - force full authentication");
311 data->next_reauth_id = NULL;
314 if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
315 counter == 0 && nonce_s == NULL)
318 wpa_printf(MSG_DEBUG, " AT_IV");
319 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
320 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
323 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter);
324 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
328 wpa_printf(MSG_DEBUG, " *AT_NONCE_S");
329 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
330 EAP_SIM_NONCE_S_LEN);
333 if (data->next_pseudonym) {
334 wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)",
335 data->next_pseudonym);
336 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
337 os_strlen(data->next_pseudonym),
338 (u8 *) data->next_pseudonym,
339 os_strlen(data->next_pseudonym));
342 if (data->next_reauth_id) {
343 wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)",
344 data->next_reauth_id);
345 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
346 os_strlen(data->next_reauth_id),
347 (u8 *) data->next_reauth_id,
348 os_strlen(data->next_reauth_id));
351 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
352 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
361 static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
362 struct eap_aka_data *data,
365 struct eap_sim_msg *msg;
367 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge");
368 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
369 EAP_AKA_SUBTYPE_CHALLENGE);
370 wpa_printf(MSG_DEBUG, " AT_RAND");
371 eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN);
372 eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN);
373 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
375 /* Add the selected KDF into the beginning */
376 eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf,
379 eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF,
381 eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT,
382 data->network_name_len,
383 data->network_name, data->network_name_len);
386 if (eap_aka_build_encr(sm, data, msg, 0, NULL)) {
387 eap_sim_msg_free(msg);
391 eap_aka_add_checkcode(data, msg);
393 if (sm->eap_sim_aka_result_ind) {
394 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
395 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
399 if (data->eap_method == EAP_TYPE_AKA) {
402 int aka_prime_preferred = 0;
405 while (sm->user && i < EAP_MAX_METHODS &&
406 (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
407 sm->user->methods[i].method != EAP_TYPE_NONE)) {
408 if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) {
409 if (sm->user->methods[i].method ==
412 if (sm->user->methods[i].method ==
413 EAP_TYPE_AKA_PRIME) {
414 aka_prime_preferred = 1;
421 if (aka_prime_preferred)
422 flags |= EAP_AKA_BIDDING_FLAG_D;
423 eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0);
425 #endif /* EAP_AKA_PRIME */
427 wpa_printf(MSG_DEBUG, " AT_MAC");
428 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
429 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
433 static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm,
434 struct eap_aka_data *data, u8 id)
436 struct eap_sim_msg *msg;
438 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication");
440 if (os_get_random(data->nonce_s, EAP_SIM_NONCE_S_LEN))
442 wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
443 data->nonce_s, EAP_SIM_NONCE_S_LEN);
445 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
446 eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
450 data->msk, data->emsk);
452 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
453 data->msk, data->emsk);
454 eap_sim_derive_keys_reauth(data->counter, sm->identity,
455 sm->identity_len, data->nonce_s,
456 data->mk, data->msk, data->emsk);
459 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
460 EAP_AKA_SUBTYPE_REAUTHENTICATION);
462 if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
463 eap_sim_msg_free(msg);
467 eap_aka_add_checkcode(data, msg);
469 if (sm->eap_sim_aka_result_ind) {
470 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
471 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
474 wpa_printf(MSG_DEBUG, " AT_MAC");
475 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
476 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
480 static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm,
481 struct eap_aka_data *data,
484 struct eap_sim_msg *msg;
486 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification");
487 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
488 EAP_AKA_SUBTYPE_NOTIFICATION);
489 wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification);
490 eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
492 if (data->use_result_ind) {
494 wpa_printf(MSG_DEBUG, " AT_IV");
495 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
496 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
497 EAP_SIM_AT_ENCR_DATA);
498 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)",
500 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
503 if (eap_sim_msg_add_encr_end(msg, data->k_encr,
504 EAP_SIM_AT_PADDING)) {
505 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to "
506 "encrypt AT_ENCR_DATA");
507 eap_sim_msg_free(msg);
512 wpa_printf(MSG_DEBUG, " AT_MAC");
513 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
515 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
519 static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id)
521 struct eap_aka_data *data = priv;
523 data->auts_reported = 0;
524 switch (data->state) {
526 return eap_aka_build_identity(sm, data, id);
528 return eap_aka_build_challenge(sm, data, id);
530 return eap_aka_build_reauth(sm, data, id);
532 return eap_aka_build_notification(sm, data, id);
534 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
535 "buildReq", data->state);
542 static Boolean eap_aka_check(struct eap_sm *sm, void *priv,
543 struct wpabuf *respData)
545 struct eap_aka_data *data = priv;
549 pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
551 if (pos == NULL || len < 3) {
552 wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
560 static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
562 if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR ||
563 subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT)
566 switch (data->state) {
568 if (subtype != EAP_AKA_SUBTYPE_IDENTITY) {
569 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
570 "subtype %d", subtype);
575 if (subtype != EAP_AKA_SUBTYPE_CHALLENGE &&
576 subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
577 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
578 "subtype %d", subtype);
583 if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) {
584 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
585 "subtype %d", subtype);
590 if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) {
591 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
592 "subtype %d", subtype);
597 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for "
598 "processing a response", data->state);
606 static void eap_aka_determine_identity(struct eap_sm *sm,
607 struct eap_aka_data *data,
608 int before_identity, int after_reauth)
617 if (after_reauth && data->reauth) {
618 identity = data->reauth->identity;
619 identity_len = data->reauth->identity_len;
620 } else if (sm->identity && sm->identity_len > 0 &&
621 sm->identity[0] == EAP_AKA_PERMANENT_PREFIX) {
622 identity = sm->identity;
623 identity_len = sm->identity_len;
625 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv,
629 if (identity == NULL) {
630 data->reauth = eap_sim_db_get_reauth_entry(
631 sm->eap_sim_db_priv, sm->identity,
634 data->reauth->aka_prime !=
635 (data->eap_method == EAP_TYPE_AKA_PRIME)) {
636 wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data "
637 "was for different AKA version");
641 wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast "
642 "re-authentication");
643 identity = data->reauth->identity;
644 identity_len = data->reauth->identity_len;
645 data->counter = data->reauth->counter;
646 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
647 os_memcpy(data->k_encr,
648 data->reauth->k_encr,
650 os_memcpy(data->k_aut,
652 EAP_AKA_PRIME_K_AUT_LEN);
653 os_memcpy(data->k_re,
655 EAP_AKA_PRIME_K_RE_LEN);
657 os_memcpy(data->mk, data->reauth->mk,
664 if (identity == NULL ||
665 eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
666 sm->identity_len) < 0) {
667 if (before_identity) {
668 wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name "
669 "not known - send AKA-Identity request");
670 eap_aka_state(data, IDENTITY);
673 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the "
674 "permanent user name is known; try to use "
676 /* eap_sim_db_get_aka_auth() will report failure, if
677 * this identity is not known. */
681 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
682 identity, identity_len);
684 if (!after_reauth && data->reauth) {
685 eap_aka_state(data, REAUTH);
689 res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity,
690 identity_len, data->rand, data->autn,
691 data->ik, data->ck, data->res,
693 if (res == EAP_SIM_DB_PENDING) {
694 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
695 "not yet available - pending request");
696 sm->method_pending = METHOD_PENDING_WAIT;
701 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
702 /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
703 * needed 6-octet SQN ^AK for CK',IK' derivation */
704 eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
707 data->network_name_len);
709 #endif /* EAP_AKA_PRIME */
712 data->counter = 0; /* reset re-auth counter since this is full auth */
715 wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA "
716 "authentication data for the peer");
717 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
718 eap_aka_state(data, NOTIFICATION);
721 if (sm->method_pending == METHOD_PENDING_WAIT) {
722 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
723 "available - abort pending wait");
724 sm->method_pending = METHOD_PENDING_NONE;
727 identity_len = sm->identity_len;
728 while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
729 wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null "
730 "character from identity");
733 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation",
734 sm->identity, identity_len);
736 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
737 eap_aka_prime_derive_keys(identity, identity_len, data->ik,
738 data->ck, data->k_encr, data->k_aut,
739 data->k_re, data->msk, data->emsk);
741 eap_aka_derive_mk(sm->identity, identity_len, data->ik,
743 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
744 data->msk, data->emsk);
747 eap_aka_state(data, CHALLENGE);
751 static void eap_aka_process_identity(struct eap_sm *sm,
752 struct eap_aka_data *data,
753 struct wpabuf *respData,
754 struct eap_sim_attrs *attr)
756 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity");
758 if (attr->mac || attr->iv || attr->encr_data) {
759 wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute "
760 "received in EAP-Response/AKA-Identity");
761 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
762 eap_aka_state(data, NOTIFICATION);
766 if (attr->identity) {
767 os_free(sm->identity);
768 sm->identity = os_malloc(attr->identity_len);
770 os_memcpy(sm->identity, attr->identity,
772 sm->identity_len = attr->identity_len;
776 eap_aka_determine_identity(sm, data, 0, 0);
777 if (eap_get_id(respData) == data->pending_id) {
778 data->pending_id = -1;
779 eap_aka_add_id_msg(data, respData);
784 static int eap_aka_verify_mac(struct eap_aka_data *data,
785 const struct wpabuf *req,
786 const u8 *mac, const u8 *extra,
789 if (data->eap_method == EAP_TYPE_AKA_PRIME)
790 return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
792 return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
796 static void eap_aka_process_challenge(struct eap_sm *sm,
797 struct eap_aka_data *data,
798 struct wpabuf *respData,
799 struct eap_sim_attrs *attr)
804 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
808 /* KDF negotiation; to be enabled only after more than one KDF is
810 if (data->eap_method == EAP_TYPE_AKA_PRIME &&
811 attr->kdf_count == 1 && attr->mac == NULL) {
812 if (attr->kdf[0] != EAP_AKA_PRIME_KDF) {
813 wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected "
816 EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
817 eap_aka_state(data, NOTIFICATION);
821 data->kdf = attr->kdf[0];
823 /* Allow negotiation to continue with the selected KDF by
824 * sending another Challenge message */
825 wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
829 #endif /* EAP_AKA_PRIME */
831 if (attr->checkcode &&
832 eap_aka_verify_checkcode(data, attr->checkcode,
833 attr->checkcode_len)) {
834 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
836 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
837 eap_aka_state(data, NOTIFICATION);
840 if (attr->mac == NULL ||
841 eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) {
842 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
843 "did not include valid AT_MAC");
844 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
845 eap_aka_state(data, NOTIFICATION);
850 * AT_RES is padded, so verify that there is enough room for RES and
851 * that the RES length in bits matches with the expected RES.
853 if (attr->res == NULL || attr->res_len < data->res_len ||
854 attr->res_len_bits != data->res_len * 8 ||
855 os_memcmp(attr->res, data->res, data->res_len) != 0) {
856 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
857 "include valid AT_RES (attr len=%lu, res len=%lu "
858 "bits, expected %lu bits)",
859 (unsigned long) attr->res_len,
860 (unsigned long) attr->res_len_bits,
861 (unsigned long) data->res_len * 8);
862 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
863 eap_aka_state(data, NOTIFICATION);
867 wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the "
869 if (sm->eap_sim_aka_result_ind && attr->result_ind) {
870 data->use_result_ind = 1;
871 data->notification = EAP_SIM_SUCCESS;
872 eap_aka_state(data, NOTIFICATION);
874 eap_aka_state(data, SUCCESS);
876 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity,
877 sm->identity_len, &identity_len);
878 if (identity == NULL) {
879 identity = sm->identity;
880 identity_len = sm->identity_len;
883 if (data->next_pseudonym) {
884 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
886 data->next_pseudonym);
887 data->next_pseudonym = NULL;
889 if (data->next_reauth_id) {
890 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
891 eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
894 data->next_reauth_id,
896 data->k_encr, data->k_aut,
899 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
901 data->next_reauth_id,
905 data->next_reauth_id = NULL;
910 static void eap_aka_process_sync_failure(struct eap_sm *sm,
911 struct eap_aka_data *data,
912 struct wpabuf *respData,
913 struct eap_sim_attrs *attr)
915 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure");
917 if (attr->auts == NULL) {
918 wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure "
919 "message did not include valid AT_AUTS");
920 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
921 eap_aka_state(data, NOTIFICATION);
925 /* Avoid re-reporting AUTS when processing pending EAP packet by
926 * maintaining a local flag stating whether this AUTS has already been
928 if (!data->auts_reported &&
929 eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity,
930 sm->identity_len, attr->auts,
932 wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
933 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
934 eap_aka_state(data, NOTIFICATION);
937 data->auts_reported = 1;
939 /* Try again after resynchronization */
940 eap_aka_determine_identity(sm, data, 0, 0);
944 static void eap_aka_process_reauth(struct eap_sm *sm,
945 struct eap_aka_data *data,
946 struct wpabuf *respData,
947 struct eap_sim_attrs *attr)
949 struct eap_sim_attrs eattr;
950 u8 *decrypted = NULL;
951 const u8 *identity, *id2;
952 size_t identity_len, id2_len;
954 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
956 if (attr->mac == NULL ||
957 eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s,
958 EAP_SIM_NONCE_S_LEN)) {
959 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
960 "did not include valid AT_MAC");
964 if (attr->encr_data == NULL || attr->iv == NULL) {
965 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
966 "message did not include encrypted data");
970 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
971 attr->encr_data_len, attr->iv, &eattr,
973 if (decrypted == NULL) {
974 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
975 "data from reauthentication message");
979 if (eattr.counter != data->counter) {
980 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
981 "used incorrect counter %u, expected %u",
982 eattr.counter, data->counter);
988 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes "
989 "the correct AT_MAC");
991 if (eattr.counter_too_small) {
992 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
993 "included AT_COUNTER_TOO_SMALL - starting full "
995 eap_aka_determine_identity(sm, data, 0, 1);
999 if (sm->eap_sim_aka_result_ind && attr->result_ind) {
1000 data->use_result_ind = 1;
1001 data->notification = EAP_SIM_SUCCESS;
1002 eap_aka_state(data, NOTIFICATION);
1004 eap_aka_state(data, SUCCESS);
1007 identity = data->reauth->identity;
1008 identity_len = data->reauth->identity_len;
1010 identity = sm->identity;
1011 identity_len = sm->identity_len;
1014 id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity,
1015 identity_len, &id2_len);
1018 identity_len = id2_len;
1021 if (data->next_pseudonym) {
1022 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
1023 identity_len, data->next_pseudonym);
1024 data->next_pseudonym = NULL;
1026 if (data->next_reauth_id) {
1027 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1028 eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
1031 data->next_reauth_id,
1033 data->k_encr, data->k_aut,
1036 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
1038 data->next_reauth_id,
1042 data->next_reauth_id = NULL;
1044 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
1045 data->reauth = NULL;
1051 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1052 eap_aka_state(data, NOTIFICATION);
1053 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
1054 data->reauth = NULL;
1059 static void eap_aka_process_client_error(struct eap_sm *sm,
1060 struct eap_aka_data *data,
1061 struct wpabuf *respData,
1062 struct eap_sim_attrs *attr)
1064 wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d",
1065 attr->client_error_code);
1066 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
1067 eap_aka_state(data, SUCCESS);
1069 eap_aka_state(data, FAILURE);
1073 static void eap_aka_process_authentication_reject(
1074 struct eap_sm *sm, struct eap_aka_data *data,
1075 struct wpabuf *respData, struct eap_sim_attrs *attr)
1077 wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication");
1078 eap_aka_state(data, FAILURE);
1082 static void eap_aka_process_notification(struct eap_sm *sm,
1083 struct eap_aka_data *data,
1084 struct wpabuf *respData,
1085 struct eap_sim_attrs *attr)
1087 wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification");
1088 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
1089 eap_aka_state(data, SUCCESS);
1091 eap_aka_state(data, FAILURE);
1095 static void eap_aka_process(struct eap_sm *sm, void *priv,
1096 struct wpabuf *respData)
1098 struct eap_aka_data *data = priv;
1099 const u8 *pos, *end;
1102 struct eap_sim_attrs attr;
1104 pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
1106 if (pos == NULL || len < 3)
1113 if (eap_aka_subtype_ok(data, subtype)) {
1114 wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected "
1115 "EAP-AKA Subtype in EAP Response");
1116 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1117 eap_aka_state(data, NOTIFICATION);
1121 if (eap_sim_parse_attr(pos, end, &attr,
1122 data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
1124 wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes");
1125 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1126 eap_aka_state(data, NOTIFICATION);
1130 if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) {
1131 eap_aka_process_client_error(sm, data, respData, &attr);
1135 if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) {
1136 eap_aka_process_authentication_reject(sm, data, respData,
1141 switch (data->state) {
1143 eap_aka_process_identity(sm, data, respData, &attr);
1146 if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
1147 eap_aka_process_sync_failure(sm, data, respData,
1150 eap_aka_process_challenge(sm, data, respData, &attr);
1154 eap_aka_process_reauth(sm, data, respData, &attr);
1157 eap_aka_process_notification(sm, data, respData, &attr);
1160 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
1161 "process", data->state);
1167 static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv)
1169 struct eap_aka_data *data = priv;
1170 return data->state == SUCCESS || data->state == FAILURE;
1174 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
1176 struct eap_aka_data *data = priv;
1179 if (data->state != SUCCESS)
1182 key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
1185 os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
1186 *len = EAP_SIM_KEYING_DATA_LEN;
1191 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1193 struct eap_aka_data *data = priv;
1196 if (data->state != SUCCESS)
1199 key = os_malloc(EAP_EMSK_LEN);
1202 os_memcpy(key, data->emsk, EAP_EMSK_LEN);
1203 *len = EAP_EMSK_LEN;
1208 static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv)
1210 struct eap_aka_data *data = priv;
1211 return data->state == SUCCESS;
1215 int eap_server_aka_register(void)
1217 struct eap_method *eap;
1220 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1221 EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
1225 eap->init = eap_aka_init;
1226 eap->reset = eap_aka_reset;
1227 eap->buildReq = eap_aka_buildReq;
1228 eap->check = eap_aka_check;
1229 eap->process = eap_aka_process;
1230 eap->isDone = eap_aka_isDone;
1231 eap->getKey = eap_aka_getKey;
1232 eap->isSuccess = eap_aka_isSuccess;
1233 eap->get_emsk = eap_aka_get_emsk;
1235 ret = eap_server_method_register(eap);
1237 eap_server_method_free(eap);
1242 #ifdef EAP_AKA_PRIME
1243 int eap_server_aka_prime_register(void)
1245 struct eap_method *eap;
1248 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1249 EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
1254 eap->init = eap_aka_prime_init;
1255 eap->reset = eap_aka_reset;
1256 eap->buildReq = eap_aka_buildReq;
1257 eap->check = eap_aka_check;
1258 eap->process = eap_aka_process;
1259 eap->isDone = eap_aka_isDone;
1260 eap->getKey = eap_aka_getKey;
1261 eap->isSuccess = eap_aka_isSuccess;
1262 eap->get_emsk = eap_aka_get_emsk;
1264 ret = eap_server_method_register(eap);
1266 eap_server_method_free(eap);
1270 #endif /* EAP_AKA_PRIME */