Home | History | Annotate | Download | only in eap_server
      1 /*
      2  * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf)
      3  * Copyright (c) 2005-2008, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "crypto/sha256.h"
     13 #include "crypto/crypto.h"
     14 #include "crypto/random.h"
     15 #include "eap_common/eap_sim_common.h"
     16 #include "eap_server/eap_i.h"
     17 #include "eap_server/eap_sim_db.h"
     18 
     19 
     20 struct eap_aka_data {
     21 	u8 mk[EAP_SIM_MK_LEN];
     22 	u8 nonce_s[EAP_SIM_NONCE_S_LEN];
     23 	u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
     24 	u8 k_encr[EAP_SIM_K_ENCR_LEN];
     25 	u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */
     26 	u8 msk[EAP_SIM_KEYING_DATA_LEN];
     27 	u8 emsk[EAP_EMSK_LEN];
     28 	u8 rand[EAP_AKA_RAND_LEN];
     29 	u8 autn[EAP_AKA_AUTN_LEN];
     30 	u8 ck[EAP_AKA_CK_LEN];
     31 	u8 ik[EAP_AKA_IK_LEN];
     32 	u8 res[EAP_AKA_RES_MAX_LEN];
     33 	size_t res_len;
     34 	enum {
     35 		IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
     36 	} state;
     37 	char *next_pseudonym;
     38 	char *next_reauth_id;
     39 	u16 counter;
     40 	struct eap_sim_reauth *reauth;
     41 	int auts_reported; /* whether the current AUTS has been reported to the
     42 			    * eap_sim_db */
     43 	u16 notification;
     44 	int use_result_ind;
     45 
     46 	struct wpabuf *id_msgs;
     47 	int pending_id;
     48 	u8 eap_method;
     49 	u8 *network_name;
     50 	size_t network_name_len;
     51 	u16 kdf;
     52 };
     53 
     54 
     55 static void eap_aka_determine_identity(struct eap_sm *sm,
     56 				       struct eap_aka_data *data,
     57 				       int before_identity, int after_reauth);
     58 
     59 
     60 static const char * eap_aka_state_txt(int state)
     61 {
     62 	switch (state) {
     63 	case IDENTITY:
     64 		return "IDENTITY";
     65 	case CHALLENGE:
     66 		return "CHALLENGE";
     67 	case REAUTH:
     68 		return "REAUTH";
     69 	case SUCCESS:
     70 		return "SUCCESS";
     71 	case FAILURE:
     72 		return "FAILURE";
     73 	case NOTIFICATION:
     74 		return "NOTIFICATION";
     75 	default:
     76 		return "Unknown?!";
     77 	}
     78 }
     79 
     80 
     81 static void eap_aka_state(struct eap_aka_data *data, int state)
     82 {
     83 	wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
     84 		   eap_aka_state_txt(data->state),
     85 		   eap_aka_state_txt(state));
     86 	data->state = state;
     87 }
     88 
     89 
     90 static void * eap_aka_init(struct eap_sm *sm)
     91 {
     92 	struct eap_aka_data *data;
     93 
     94 	if (sm->eap_sim_db_priv == NULL) {
     95 		wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
     96 		return NULL;
     97 	}
     98 
     99 	data = os_zalloc(sizeof(*data));
    100 	if (data == NULL)
    101 		return NULL;
    102 
    103 	data->eap_method = EAP_TYPE_AKA;
    104 
    105 	data->state = IDENTITY;
    106 	eap_aka_determine_identity(sm, data, 1, 0);
    107 	data->pending_id = -1;
    108 
    109 	return data;
    110 }
    111 
    112 
    113 #ifdef EAP_SERVER_AKA_PRIME
    114 static void * eap_aka_prime_init(struct eap_sm *sm)
    115 {
    116 	struct eap_aka_data *data;
    117 	/* TODO: make ANID configurable; see 3GPP TS 24.302 */
    118 	char *network_name = "WLAN";
    119 
    120 	if (sm->eap_sim_db_priv == NULL) {
    121 		wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
    122 		return NULL;
    123 	}
    124 
    125 	data = os_zalloc(sizeof(*data));
    126 	if (data == NULL)
    127 		return NULL;
    128 
    129 	data->eap_method = EAP_TYPE_AKA_PRIME;
    130 	data->network_name = (u8 *) os_strdup(network_name);
    131 	if (data->network_name == NULL) {
    132 		os_free(data);
    133 		return NULL;
    134 	}
    135 
    136 	data->network_name_len = os_strlen(network_name);
    137 
    138 	data->state = IDENTITY;
    139 	eap_aka_determine_identity(sm, data, 1, 0);
    140 	data->pending_id = -1;
    141 
    142 	return data;
    143 }
    144 #endif /* EAP_SERVER_AKA_PRIME */
    145 
    146 
    147 static void eap_aka_reset(struct eap_sm *sm, void *priv)
    148 {
    149 	struct eap_aka_data *data = priv;
    150 	os_free(data->next_pseudonym);
    151 	os_free(data->next_reauth_id);
    152 	wpabuf_free(data->id_msgs);
    153 	os_free(data->network_name);
    154 	os_free(data);
    155 }
    156 
    157 
    158 static int eap_aka_add_id_msg(struct eap_aka_data *data,
    159 			      const struct wpabuf *msg)
    160 {
    161 	if (msg == NULL)
    162 		return -1;
    163 
    164 	if (data->id_msgs == NULL) {
    165 		data->id_msgs = wpabuf_dup(msg);
    166 		return data->id_msgs == NULL ? -1 : 0;
    167 	}
    168 
    169 	if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
    170 		return -1;
    171 	wpabuf_put_buf(data->id_msgs, msg);
    172 
    173 	return 0;
    174 }
    175 
    176 
    177 static void eap_aka_add_checkcode(struct eap_aka_data *data,
    178 				  struct eap_sim_msg *msg)
    179 {
    180 	const u8 *addr;
    181 	size_t len;
    182 	u8 hash[SHA256_MAC_LEN];
    183 
    184 	wpa_printf(MSG_DEBUG, "   AT_CHECKCODE");
    185 
    186 	if (data->id_msgs == NULL) {
    187 		/*
    188 		 * No EAP-AKA/Identity packets were exchanged - send empty
    189 		 * checkcode.
    190 		 */
    191 		eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
    192 		return;
    193 	}
    194 
    195 	/* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
    196 	addr = wpabuf_head(data->id_msgs);
    197 	len = wpabuf_len(data->id_msgs);
    198 	wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
    199 	if (data->eap_method == EAP_TYPE_AKA_PRIME)
    200 		sha256_vector(1, &addr, &len, hash);
    201 	else
    202 		sha1_vector(1, &addr, &len, hash);
    203 
    204 	eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
    205 			data->eap_method == EAP_TYPE_AKA_PRIME ?
    206 			EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
    207 }
    208 
    209 
    210 static int eap_aka_verify_checkcode(struct eap_aka_data *data,
    211 				    const u8 *checkcode, size_t checkcode_len)
    212 {
    213 	const u8 *addr;
    214 	size_t len;
    215 	u8 hash[SHA256_MAC_LEN];
    216 	size_t hash_len;
    217 
    218 	if (checkcode == NULL)
    219 		return -1;
    220 
    221 	if (data->id_msgs == NULL) {
    222 		if (checkcode_len != 0) {
    223 			wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer "
    224 				   "indicates that AKA/Identity messages were "
    225 				   "used, but they were not");
    226 			return -1;
    227 		}
    228 		return 0;
    229 	}
    230 
    231 	hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ?
    232 		EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN;
    233 
    234 	if (checkcode_len != hash_len) {
    235 		wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates "
    236 			   "that AKA/Identity message were not used, but they "
    237 			   "were");
    238 		return -1;
    239 	}
    240 
    241 	/* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
    242 	addr = wpabuf_head(data->id_msgs);
    243 	len = wpabuf_len(data->id_msgs);
    244 	if (data->eap_method == EAP_TYPE_AKA_PRIME)
    245 		sha256_vector(1, &addr, &len, hash);
    246 	else
    247 		sha1_vector(1, &addr, &len, hash);
    248 
    249 	if (os_memcmp(hash, checkcode, hash_len) != 0) {
    250 		wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
    251 		return -1;
    252 	}
    253 
    254 	return 0;
    255 }
    256 
    257 
    258 static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm,
    259 					      struct eap_aka_data *data, u8 id)
    260 {
    261 	struct eap_sim_msg *msg;
    262 	struct wpabuf *buf;
    263 
    264 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity");
    265 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
    266 			       EAP_AKA_SUBTYPE_IDENTITY);
    267 	if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
    268 				      sm->identity_len)) {
    269 		wpa_printf(MSG_DEBUG, "   AT_PERMANENT_ID_REQ");
    270 		eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
    271 	} else {
    272 		/*
    273 		 * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is
    274 		 * ignored and the AKA/Identity is used to request the
    275 		 * identity.
    276 		 */
    277 		wpa_printf(MSG_DEBUG, "   AT_ANY_ID_REQ");
    278 		eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
    279 	}
    280 	buf = eap_sim_msg_finish(msg, NULL, NULL, 0);
    281 	if (eap_aka_add_id_msg(data, buf) < 0) {
    282 		wpabuf_free(buf);
    283 		return NULL;
    284 	}
    285 	data->pending_id = id;
    286 	return buf;
    287 }
    288 
    289 
    290 static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
    291 			      struct eap_sim_msg *msg, u16 counter,
    292 			      const u8 *nonce_s)
    293 {
    294 	os_free(data->next_pseudonym);
    295 	data->next_pseudonym =
    296 		eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1);
    297 	os_free(data->next_reauth_id);
    298 	if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
    299 		data->next_reauth_id =
    300 			eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 1);
    301 	} else {
    302 		wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication "
    303 			   "count exceeded - force full authentication");
    304 		data->next_reauth_id = NULL;
    305 	}
    306 
    307 	if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
    308 	    counter == 0 && nonce_s == NULL)
    309 		return 0;
    310 
    311 	wpa_printf(MSG_DEBUG, "   AT_IV");
    312 	wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
    313 	eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
    314 
    315 	if (counter > 0) {
    316 		wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)", counter);
    317 		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
    318 	}
    319 
    320 	if (nonce_s) {
    321 		wpa_printf(MSG_DEBUG, "   *AT_NONCE_S");
    322 		eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
    323 				EAP_SIM_NONCE_S_LEN);
    324 	}
    325 
    326 	if (data->next_pseudonym) {
    327 		wpa_printf(MSG_DEBUG, "   *AT_NEXT_PSEUDONYM (%s)",
    328 			   data->next_pseudonym);
    329 		eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
    330 				os_strlen(data->next_pseudonym),
    331 				(u8 *) data->next_pseudonym,
    332 				os_strlen(data->next_pseudonym));
    333 	}
    334 
    335 	if (data->next_reauth_id) {
    336 		wpa_printf(MSG_DEBUG, "   *AT_NEXT_REAUTH_ID (%s)",
    337 			   data->next_reauth_id);
    338 		eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
    339 				os_strlen(data->next_reauth_id),
    340 				(u8 *) data->next_reauth_id,
    341 				os_strlen(data->next_reauth_id));
    342 	}
    343 
    344 	if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
    345 		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
    346 			   "AT_ENCR_DATA");
    347 		return -1;
    348 	}
    349 
    350 	return 0;
    351 }
    352 
    353 
    354 static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
    355 					       struct eap_aka_data *data,
    356 					       u8 id)
    357 {
    358 	struct eap_sim_msg *msg;
    359 
    360 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge");
    361 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
    362 			       EAP_AKA_SUBTYPE_CHALLENGE);
    363 	wpa_printf(MSG_DEBUG, "   AT_RAND");
    364 	eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN);
    365 	wpa_printf(MSG_DEBUG, "   AT_AUTN");
    366 	eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN);
    367 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    368 		if (data->kdf) {
    369 			/* Add the selected KDF into the beginning */
    370 			wpa_printf(MSG_DEBUG, "   AT_KDF");
    371 			eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf,
    372 					NULL, 0);
    373 		}
    374 		wpa_printf(MSG_DEBUG, "   AT_KDF");
    375 		eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF,
    376 				NULL, 0);
    377 		wpa_printf(MSG_DEBUG, "   AT_KDF_INPUT");
    378 		eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT,
    379 				data->network_name_len,
    380 				data->network_name, data->network_name_len);
    381 	}
    382 
    383 	if (eap_aka_build_encr(sm, data, msg, 0, NULL)) {
    384 		eap_sim_msg_free(msg);
    385 		return NULL;
    386 	}
    387 
    388 	eap_aka_add_checkcode(data, msg);
    389 
    390 	if (sm->eap_sim_aka_result_ind) {
    391 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
    392 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
    393 	}
    394 
    395 #ifdef EAP_SERVER_AKA_PRIME
    396 	if (data->eap_method == EAP_TYPE_AKA) {
    397 		u16 flags = 0;
    398 		int i;
    399 		int aka_prime_preferred = 0;
    400 
    401 		i = 0;
    402 		while (sm->user && i < EAP_MAX_METHODS &&
    403 		       (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
    404 			sm->user->methods[i].method != EAP_TYPE_NONE)) {
    405 			if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) {
    406 				if (sm->user->methods[i].method ==
    407 				    EAP_TYPE_AKA)
    408 					break;
    409 				if (sm->user->methods[i].method ==
    410 				    EAP_TYPE_AKA_PRIME) {
    411 					aka_prime_preferred = 1;
    412 					break;
    413 				}
    414 			}
    415 			i++;
    416 		}
    417 
    418 		if (aka_prime_preferred)
    419 			flags |= EAP_AKA_BIDDING_FLAG_D;
    420 		eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0);
    421 	}
    422 #endif /* EAP_SERVER_AKA_PRIME */
    423 
    424 	wpa_printf(MSG_DEBUG, "   AT_MAC");
    425 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
    426 	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
    427 }
    428 
    429 
    430 static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm,
    431 					    struct eap_aka_data *data, u8 id)
    432 {
    433 	struct eap_sim_msg *msg;
    434 
    435 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication");
    436 
    437 	if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN))
    438 		return NULL;
    439 	wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
    440 			data->nonce_s, EAP_SIM_NONCE_S_LEN);
    441 
    442 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    443 		eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
    444 						 sm->identity,
    445 						 sm->identity_len,
    446 						 data->nonce_s,
    447 						 data->msk, data->emsk);
    448 	} else {
    449 		eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
    450 				    data->msk, data->emsk);
    451 		eap_sim_derive_keys_reauth(data->counter, sm->identity,
    452 					   sm->identity_len, data->nonce_s,
    453 					   data->mk, data->msk, data->emsk);
    454 	}
    455 
    456 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
    457 			       EAP_AKA_SUBTYPE_REAUTHENTICATION);
    458 
    459 	if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
    460 		eap_sim_msg_free(msg);
    461 		return NULL;
    462 	}
    463 
    464 	eap_aka_add_checkcode(data, msg);
    465 
    466 	if (sm->eap_sim_aka_result_ind) {
    467 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
    468 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
    469 	}
    470 
    471 	wpa_printf(MSG_DEBUG, "   AT_MAC");
    472 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
    473 	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
    474 }
    475 
    476 
    477 static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm,
    478 						  struct eap_aka_data *data,
    479 						  u8 id)
    480 {
    481 	struct eap_sim_msg *msg;
    482 
    483 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification");
    484 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
    485 			       EAP_AKA_SUBTYPE_NOTIFICATION);
    486 	wpa_printf(MSG_DEBUG, "   AT_NOTIFICATION (%d)", data->notification);
    487 	eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
    488 			NULL, 0);
    489 	if (data->use_result_ind) {
    490 		if (data->reauth) {
    491 			wpa_printf(MSG_DEBUG, "   AT_IV");
    492 			wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
    493 			eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
    494 						   EAP_SIM_AT_ENCR_DATA);
    495 			wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)",
    496 				   data->counter);
    497 			eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
    498 					NULL, 0);
    499 
    500 			if (eap_sim_msg_add_encr_end(msg, data->k_encr,
    501 						     EAP_SIM_AT_PADDING)) {
    502 				wpa_printf(MSG_WARNING, "EAP-AKA: Failed to "
    503 					   "encrypt AT_ENCR_DATA");
    504 				eap_sim_msg_free(msg);
    505 				return NULL;
    506 			}
    507 		}
    508 
    509 		wpa_printf(MSG_DEBUG, "   AT_MAC");
    510 		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
    511 	}
    512 	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
    513 }
    514 
    515 
    516 static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id)
    517 {
    518 	struct eap_aka_data *data = priv;
    519 
    520 	data->auts_reported = 0;
    521 	switch (data->state) {
    522 	case IDENTITY:
    523 		return eap_aka_build_identity(sm, data, id);
    524 	case CHALLENGE:
    525 		return eap_aka_build_challenge(sm, data, id);
    526 	case REAUTH:
    527 		return eap_aka_build_reauth(sm, data, id);
    528 	case NOTIFICATION:
    529 		return eap_aka_build_notification(sm, data, id);
    530 	default:
    531 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
    532 			   "buildReq", data->state);
    533 		break;
    534 	}
    535 	return NULL;
    536 }
    537 
    538 
    539 static Boolean eap_aka_check(struct eap_sm *sm, void *priv,
    540 			     struct wpabuf *respData)
    541 {
    542 	struct eap_aka_data *data = priv;
    543 	const u8 *pos;
    544 	size_t len;
    545 
    546 	pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
    547 			       &len);
    548 	if (pos == NULL || len < 3) {
    549 		wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
    550 		return TRUE;
    551 	}
    552 
    553 	return FALSE;
    554 }
    555 
    556 
    557 static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
    558 {
    559 	if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR ||
    560 	    subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT)
    561 		return FALSE;
    562 
    563 	switch (data->state) {
    564 	case IDENTITY:
    565 		if (subtype != EAP_AKA_SUBTYPE_IDENTITY) {
    566 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
    567 				   "subtype %d", subtype);
    568 			return TRUE;
    569 		}
    570 		break;
    571 	case CHALLENGE:
    572 		if (subtype != EAP_AKA_SUBTYPE_CHALLENGE &&
    573 		    subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
    574 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
    575 				   "subtype %d", subtype);
    576 			return TRUE;
    577 		}
    578 		break;
    579 	case REAUTH:
    580 		if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) {
    581 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
    582 				   "subtype %d", subtype);
    583 			return TRUE;
    584 		}
    585 		break;
    586 	case NOTIFICATION:
    587 		if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) {
    588 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
    589 				   "subtype %d", subtype);
    590 			return TRUE;
    591 		}
    592 		break;
    593 	default:
    594 		wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for "
    595 			   "processing a response", data->state);
    596 		return TRUE;
    597 	}
    598 
    599 	return FALSE;
    600 }
    601 
    602 
    603 static void eap_aka_determine_identity(struct eap_sm *sm,
    604 				       struct eap_aka_data *data,
    605 				       int before_identity, int after_reauth)
    606 {
    607 	const u8 *identity;
    608 	size_t identity_len;
    609 	int res;
    610 
    611 	identity = NULL;
    612 	identity_len = 0;
    613 
    614 	if (after_reauth && data->reauth) {
    615 		identity = data->reauth->identity;
    616 		identity_len = data->reauth->identity_len;
    617 	} else if (sm->identity && sm->identity_len > 0 &&
    618 		   sm->identity[0] == EAP_AKA_PERMANENT_PREFIX) {
    619 		identity = sm->identity;
    620 		identity_len = sm->identity_len;
    621 	} else {
    622 		identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv,
    623 						    sm->identity,
    624 						    sm->identity_len,
    625 						    &identity_len);
    626 		if (identity == NULL) {
    627 			data->reauth = eap_sim_db_get_reauth_entry(
    628 				sm->eap_sim_db_priv, sm->identity,
    629 				sm->identity_len);
    630 			if (data->reauth &&
    631 			    data->reauth->aka_prime !=
    632 			    (data->eap_method == EAP_TYPE_AKA_PRIME)) {
    633 				wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data "
    634 					   "was for different AKA version");
    635 				data->reauth = NULL;
    636 			}
    637 			if (data->reauth) {
    638 				wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast "
    639 					   "re-authentication");
    640 				identity = data->reauth->identity;
    641 				identity_len = data->reauth->identity_len;
    642 				data->counter = data->reauth->counter;
    643 				if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    644 					os_memcpy(data->k_encr,
    645 						  data->reauth->k_encr,
    646 						  EAP_SIM_K_ENCR_LEN);
    647 					os_memcpy(data->k_aut,
    648 						  data->reauth->k_aut,
    649 						  EAP_AKA_PRIME_K_AUT_LEN);
    650 					os_memcpy(data->k_re,
    651 						  data->reauth->k_re,
    652 						  EAP_AKA_PRIME_K_RE_LEN);
    653 				} else {
    654 					os_memcpy(data->mk, data->reauth->mk,
    655 						  EAP_SIM_MK_LEN);
    656 				}
    657 			}
    658 		}
    659 	}
    660 
    661 	if (identity == NULL ||
    662 	    eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
    663 				      sm->identity_len) < 0) {
    664 		if (before_identity) {
    665 			wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name "
    666 				   "not known - send AKA-Identity request");
    667 			eap_aka_state(data, IDENTITY);
    668 			return;
    669 		} else {
    670 			wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the "
    671 				   "permanent user name is known; try to use "
    672 				   "it");
    673 			/* eap_sim_db_get_aka_auth() will report failure, if
    674 			 * this identity is not known. */
    675 		}
    676 	}
    677 
    678 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
    679 			  identity, identity_len);
    680 
    681 	if (!after_reauth && data->reauth) {
    682 		eap_aka_state(data, REAUTH);
    683 		return;
    684 	}
    685 
    686 	res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity,
    687 				      identity_len, data->rand, data->autn,
    688 				      data->ik, data->ck, data->res,
    689 				      &data->res_len, sm);
    690 	if (res == EAP_SIM_DB_PENDING) {
    691 		wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
    692 			   "not yet available - pending request");
    693 		sm->method_pending = METHOD_PENDING_WAIT;
    694 		return;
    695 	}
    696 
    697 #ifdef EAP_SERVER_AKA_PRIME
    698 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    699 		/* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
    700 		 * needed 6-octet SQN ^AK for CK',IK' derivation */
    701 		eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
    702 						 data->autn,
    703 						 data->network_name,
    704 						 data->network_name_len);
    705 	}
    706 #endif /* EAP_SERVER_AKA_PRIME */
    707 
    708 	data->reauth = NULL;
    709 	data->counter = 0; /* reset re-auth counter since this is full auth */
    710 
    711 	if (res != 0) {
    712 		wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA "
    713 			   "authentication data for the peer");
    714 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    715 		eap_aka_state(data, NOTIFICATION);
    716 		return;
    717 	}
    718 	if (sm->method_pending == METHOD_PENDING_WAIT) {
    719 		wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
    720 			   "available - abort pending wait");
    721 		sm->method_pending = METHOD_PENDING_NONE;
    722 	}
    723 
    724 	identity_len = sm->identity_len;
    725 	while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
    726 		wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null "
    727 			   "character from identity");
    728 		identity_len--;
    729 	}
    730 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation",
    731 			  sm->identity, identity_len);
    732 
    733 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    734 		eap_aka_prime_derive_keys(identity, identity_len, data->ik,
    735 					  data->ck, data->k_encr, data->k_aut,
    736 					  data->k_re, data->msk, data->emsk);
    737 	} else {
    738 		eap_aka_derive_mk(sm->identity, identity_len, data->ik,
    739 				  data->ck, data->mk);
    740 		eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
    741 				    data->msk, data->emsk);
    742 	}
    743 
    744 	eap_aka_state(data, CHALLENGE);
    745 }
    746 
    747 
    748 static void eap_aka_process_identity(struct eap_sm *sm,
    749 				     struct eap_aka_data *data,
    750 				     struct wpabuf *respData,
    751 				     struct eap_sim_attrs *attr)
    752 {
    753 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity");
    754 
    755 	if (attr->mac || attr->iv || attr->encr_data) {
    756 		wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute "
    757 			   "received in EAP-Response/AKA-Identity");
    758 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    759 		eap_aka_state(data, NOTIFICATION);
    760 		return;
    761 	}
    762 
    763 	if (attr->identity) {
    764 		os_free(sm->identity);
    765 		sm->identity = os_malloc(attr->identity_len);
    766 		if (sm->identity) {
    767 			os_memcpy(sm->identity, attr->identity,
    768 				  attr->identity_len);
    769 			sm->identity_len = attr->identity_len;
    770 		}
    771 	}
    772 
    773 	eap_aka_determine_identity(sm, data, 0, 0);
    774 	if (eap_get_id(respData) == data->pending_id) {
    775 		data->pending_id = -1;
    776 		eap_aka_add_id_msg(data, respData);
    777 	}
    778 }
    779 
    780 
    781 static int eap_aka_verify_mac(struct eap_aka_data *data,
    782 			      const struct wpabuf *req,
    783 			      const u8 *mac, const u8 *extra,
    784 			      size_t extra_len)
    785 {
    786 	if (data->eap_method == EAP_TYPE_AKA_PRIME)
    787 		return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
    788 						 extra_len);
    789 	return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
    790 }
    791 
    792 
    793 static void eap_aka_process_challenge(struct eap_sm *sm,
    794 				      struct eap_aka_data *data,
    795 				      struct wpabuf *respData,
    796 				      struct eap_sim_attrs *attr)
    797 {
    798 	const u8 *identity;
    799 	size_t identity_len;
    800 
    801 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
    802 
    803 #ifdef EAP_SERVER_AKA_PRIME
    804 #if 0
    805 	/* KDF negotiation; to be enabled only after more than one KDF is
    806 	 * supported */
    807 	if (data->eap_method == EAP_TYPE_AKA_PRIME &&
    808 	    attr->kdf_count == 1 && attr->mac == NULL) {
    809 		if (attr->kdf[0] != EAP_AKA_PRIME_KDF) {
    810 			wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected "
    811 				   "unknown KDF");
    812 			data->notification =
    813 				EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    814 			eap_aka_state(data, NOTIFICATION);
    815 			return;
    816 		}
    817 
    818 		data->kdf = attr->kdf[0];
    819 
    820 		/* Allow negotiation to continue with the selected KDF by
    821 		 * sending another Challenge message */
    822 		wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
    823 		return;
    824 	}
    825 #endif
    826 #endif /* EAP_SERVER_AKA_PRIME */
    827 
    828 	if (attr->checkcode &&
    829 	    eap_aka_verify_checkcode(data, attr->checkcode,
    830 				     attr->checkcode_len)) {
    831 		wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
    832 			   "message");
    833 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    834 		eap_aka_state(data, NOTIFICATION);
    835 		return;
    836 	}
    837 	if (attr->mac == NULL ||
    838 	    eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) {
    839 		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
    840 			   "did not include valid AT_MAC");
    841 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    842 		eap_aka_state(data, NOTIFICATION);
    843 		return;
    844 	}
    845 
    846 	/*
    847 	 * AT_RES is padded, so verify that there is enough room for RES and
    848 	 * that the RES length in bits matches with the expected RES.
    849 	 */
    850 	if (attr->res == NULL || attr->res_len < data->res_len ||
    851 	    attr->res_len_bits != data->res_len * 8 ||
    852 	    os_memcmp(attr->res, data->res, data->res_len) != 0) {
    853 		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
    854 			   "include valid AT_RES (attr len=%lu, res len=%lu "
    855 			   "bits, expected %lu bits)",
    856 			   (unsigned long) attr->res_len,
    857 			   (unsigned long) attr->res_len_bits,
    858 			   (unsigned long) data->res_len * 8);
    859 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    860 		eap_aka_state(data, NOTIFICATION);
    861 		return;
    862 	}
    863 
    864 	wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the "
    865 		   "correct AT_MAC");
    866 	if (sm->eap_sim_aka_result_ind && attr->result_ind) {
    867 		data->use_result_ind = 1;
    868 		data->notification = EAP_SIM_SUCCESS;
    869 		eap_aka_state(data, NOTIFICATION);
    870 	} else
    871 		eap_aka_state(data, SUCCESS);
    872 
    873 	identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity,
    874 					    sm->identity_len, &identity_len);
    875 	if (identity == NULL) {
    876 		identity = sm->identity;
    877 		identity_len = sm->identity_len;
    878 	}
    879 
    880 	if (data->next_pseudonym) {
    881 		eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
    882 					 identity_len,
    883 					 data->next_pseudonym);
    884 		data->next_pseudonym = NULL;
    885 	}
    886 	if (data->next_reauth_id) {
    887 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    888 #ifdef EAP_SERVER_AKA_PRIME
    889 			eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
    890 						    identity,
    891 						    identity_len,
    892 						    data->next_reauth_id,
    893 						    data->counter + 1,
    894 						    data->k_encr, data->k_aut,
    895 						    data->k_re);
    896 #endif /* EAP_SERVER_AKA_PRIME */
    897 		} else {
    898 			eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
    899 					      identity_len,
    900 					      data->next_reauth_id,
    901 					      data->counter + 1,
    902 					      data->mk);
    903 		}
    904 		data->next_reauth_id = NULL;
    905 	}
    906 }
    907 
    908 
    909 static void eap_aka_process_sync_failure(struct eap_sm *sm,
    910 					 struct eap_aka_data *data,
    911 					 struct wpabuf *respData,
    912 					 struct eap_sim_attrs *attr)
    913 {
    914 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure");
    915 
    916 	if (attr->auts == NULL) {
    917 		wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure "
    918 			   "message did not include valid AT_AUTS");
    919 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    920 		eap_aka_state(data, NOTIFICATION);
    921 		return;
    922 	}
    923 
    924 	/* Avoid re-reporting AUTS when processing pending EAP packet by
    925 	 * maintaining a local flag stating whether this AUTS has already been
    926 	 * reported. */
    927 	if (!data->auts_reported &&
    928 	    eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity,
    929 				     sm->identity_len, attr->auts,
    930 				     data->rand)) {
    931 		wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
    932 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    933 		eap_aka_state(data, NOTIFICATION);
    934 		return;
    935 	}
    936 	data->auts_reported = 1;
    937 
    938 	/* Try again after resynchronization */
    939 	eap_aka_determine_identity(sm, data, 0, 0);
    940 }
    941 
    942 
    943 static void eap_aka_process_reauth(struct eap_sm *sm,
    944 				   struct eap_aka_data *data,
    945 				   struct wpabuf *respData,
    946 				   struct eap_sim_attrs *attr)
    947 {
    948 	struct eap_sim_attrs eattr;
    949 	u8 *decrypted = NULL;
    950 	const u8 *identity, *id2;
    951 	size_t identity_len, id2_len;
    952 
    953 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
    954 
    955 	if (attr->mac == NULL ||
    956 	    eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s,
    957 			       EAP_SIM_NONCE_S_LEN)) {
    958 		wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
    959 			   "did not include valid AT_MAC");
    960 		goto fail;
    961 	}
    962 
    963 	if (attr->encr_data == NULL || attr->iv == NULL) {
    964 		wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
    965 			   "message did not include encrypted data");
    966 		goto fail;
    967 	}
    968 
    969 	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
    970 				       attr->encr_data_len, attr->iv, &eattr,
    971 				       0);
    972 	if (decrypted == NULL) {
    973 		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
    974 			   "data from reauthentication message");
    975 		goto fail;
    976 	}
    977 
    978 	if (eattr.counter != data->counter) {
    979 		wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
    980 			   "used incorrect counter %u, expected %u",
    981 			   eattr.counter, data->counter);
    982 		goto fail;
    983 	}
    984 	os_free(decrypted);
    985 	decrypted = NULL;
    986 
    987 	wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes "
    988 		   "the correct AT_MAC");
    989 
    990 	if (eattr.counter_too_small) {
    991 		wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
    992 			   "included AT_COUNTER_TOO_SMALL - starting full "
    993 			   "authentication");
    994 		eap_aka_determine_identity(sm, data, 0, 1);
    995 		return;
    996 	}
    997 
    998 	if (sm->eap_sim_aka_result_ind && attr->result_ind) {
    999 		data->use_result_ind = 1;
   1000 		data->notification = EAP_SIM_SUCCESS;
   1001 		eap_aka_state(data, NOTIFICATION);
   1002 	} else
   1003 		eap_aka_state(data, SUCCESS);
   1004 
   1005 	if (data->reauth) {
   1006 		identity = data->reauth->identity;
   1007 		identity_len = data->reauth->identity_len;
   1008 	} else {
   1009 		identity = sm->identity;
   1010 		identity_len = sm->identity_len;
   1011 	}
   1012 
   1013 	id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity,
   1014 				       identity_len, &id2_len);
   1015 	if (id2) {
   1016 		identity = id2;
   1017 		identity_len = id2_len;
   1018 	}
   1019 
   1020 	if (data->next_pseudonym) {
   1021 		eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
   1022 					 identity_len, data->next_pseudonym);
   1023 		data->next_pseudonym = NULL;
   1024 	}
   1025 	if (data->next_reauth_id) {
   1026 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
   1027 #ifdef EAP_SERVER_AKA_PRIME
   1028 			eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
   1029 						    identity,
   1030 						    identity_len,
   1031 						    data->next_reauth_id,
   1032 						    data->counter + 1,
   1033 						    data->k_encr, data->k_aut,
   1034 						    data->k_re);
   1035 #endif /* EAP_SERVER_AKA_PRIME */
   1036 		} else {
   1037 			eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
   1038 					      identity_len,
   1039 					      data->next_reauth_id,
   1040 					      data->counter + 1,
   1041 					      data->mk);
   1042 		}
   1043 		data->next_reauth_id = NULL;
   1044 	} else {
   1045 		eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
   1046 		data->reauth = NULL;
   1047 	}
   1048 
   1049 	return;
   1050 
   1051 fail:
   1052 	data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
   1053 	eap_aka_state(data, NOTIFICATION);
   1054 	eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
   1055 	data->reauth = NULL;
   1056 	os_free(decrypted);
   1057 }
   1058 
   1059 
   1060 static void eap_aka_process_client_error(struct eap_sm *sm,
   1061 					 struct eap_aka_data *data,
   1062 					 struct wpabuf *respData,
   1063 					 struct eap_sim_attrs *attr)
   1064 {
   1065 	wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d",
   1066 		   attr->client_error_code);
   1067 	if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
   1068 		eap_aka_state(data, SUCCESS);
   1069 	else
   1070 		eap_aka_state(data, FAILURE);
   1071 }
   1072 
   1073 
   1074 static void eap_aka_process_authentication_reject(
   1075 	struct eap_sm *sm, struct eap_aka_data *data,
   1076 	struct wpabuf *respData, struct eap_sim_attrs *attr)
   1077 {
   1078 	wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication");
   1079 	eap_aka_state(data, FAILURE);
   1080 }
   1081 
   1082 
   1083 static void eap_aka_process_notification(struct eap_sm *sm,
   1084 					 struct eap_aka_data *data,
   1085 					 struct wpabuf *respData,
   1086 					 struct eap_sim_attrs *attr)
   1087 {
   1088 	wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification");
   1089 	if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
   1090 		eap_aka_state(data, SUCCESS);
   1091 	else
   1092 		eap_aka_state(data, FAILURE);
   1093 }
   1094 
   1095 
   1096 static void eap_aka_process(struct eap_sm *sm, void *priv,
   1097 			    struct wpabuf *respData)
   1098 {
   1099 	struct eap_aka_data *data = priv;
   1100 	const u8 *pos, *end;
   1101 	u8 subtype;
   1102 	size_t len;
   1103 	struct eap_sim_attrs attr;
   1104 
   1105 	pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
   1106 			       &len);
   1107 	if (pos == NULL || len < 3)
   1108 		return;
   1109 
   1110 	end = pos + len;
   1111 	subtype = *pos;
   1112 	pos += 3;
   1113 
   1114 	if (eap_aka_subtype_ok(data, subtype)) {
   1115 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected "
   1116 			   "EAP-AKA Subtype in EAP Response");
   1117 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
   1118 		eap_aka_state(data, NOTIFICATION);
   1119 		return;
   1120 	}
   1121 
   1122 	if (eap_sim_parse_attr(pos, end, &attr,
   1123 			       data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
   1124 			       0)) {
   1125 		wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes");
   1126 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
   1127 		eap_aka_state(data, NOTIFICATION);
   1128 		return;
   1129 	}
   1130 
   1131 	if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) {
   1132 		eap_aka_process_client_error(sm, data, respData, &attr);
   1133 		return;
   1134 	}
   1135 
   1136 	if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) {
   1137 		eap_aka_process_authentication_reject(sm, data, respData,
   1138 						      &attr);
   1139 		return;
   1140 	}
   1141 
   1142 	switch (data->state) {
   1143 	case IDENTITY:
   1144 		eap_aka_process_identity(sm, data, respData, &attr);
   1145 		break;
   1146 	case CHALLENGE:
   1147 		if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
   1148 			eap_aka_process_sync_failure(sm, data, respData,
   1149 						     &attr);
   1150 		} else {
   1151 			eap_aka_process_challenge(sm, data, respData, &attr);
   1152 		}
   1153 		break;
   1154 	case REAUTH:
   1155 		eap_aka_process_reauth(sm, data, respData, &attr);
   1156 		break;
   1157 	case NOTIFICATION:
   1158 		eap_aka_process_notification(sm, data, respData, &attr);
   1159 		break;
   1160 	default:
   1161 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
   1162 			   "process", data->state);
   1163 		break;
   1164 	}
   1165 }
   1166 
   1167 
   1168 static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv)
   1169 {
   1170 	struct eap_aka_data *data = priv;
   1171 	return data->state == SUCCESS || data->state == FAILURE;
   1172 }
   1173 
   1174 
   1175 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
   1176 {
   1177 	struct eap_aka_data *data = priv;
   1178 	u8 *key;
   1179 
   1180 	if (data->state != SUCCESS)
   1181 		return NULL;
   1182 
   1183 	key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
   1184 	if (key == NULL)
   1185 		return NULL;
   1186 	os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
   1187 	*len = EAP_SIM_KEYING_DATA_LEN;
   1188 	return key;
   1189 }
   1190 
   1191 
   1192 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
   1193 {
   1194 	struct eap_aka_data *data = priv;
   1195 	u8 *key;
   1196 
   1197 	if (data->state != SUCCESS)
   1198 		return NULL;
   1199 
   1200 	key = os_malloc(EAP_EMSK_LEN);
   1201 	if (key == NULL)
   1202 		return NULL;
   1203 	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
   1204 	*len = EAP_EMSK_LEN;
   1205 	return key;
   1206 }
   1207 
   1208 
   1209 static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv)
   1210 {
   1211 	struct eap_aka_data *data = priv;
   1212 	return data->state == SUCCESS;
   1213 }
   1214 
   1215 
   1216 int eap_server_aka_register(void)
   1217 {
   1218 	struct eap_method *eap;
   1219 	int ret;
   1220 
   1221 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
   1222 				      EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
   1223 	if (eap == NULL)
   1224 		return -1;
   1225 
   1226 	eap->init = eap_aka_init;
   1227 	eap->reset = eap_aka_reset;
   1228 	eap->buildReq = eap_aka_buildReq;
   1229 	eap->check = eap_aka_check;
   1230 	eap->process = eap_aka_process;
   1231 	eap->isDone = eap_aka_isDone;
   1232 	eap->getKey = eap_aka_getKey;
   1233 	eap->isSuccess = eap_aka_isSuccess;
   1234 	eap->get_emsk = eap_aka_get_emsk;
   1235 
   1236 	ret = eap_server_method_register(eap);
   1237 	if (ret)
   1238 		eap_server_method_free(eap);
   1239 	return ret;
   1240 }
   1241 
   1242 
   1243 #ifdef EAP_SERVER_AKA_PRIME
   1244 int eap_server_aka_prime_register(void)
   1245 {
   1246 	struct eap_method *eap;
   1247 	int ret;
   1248 
   1249 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
   1250 				      EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
   1251 				      "AKA'");
   1252 	if (eap == NULL)
   1253 		return -1;
   1254 
   1255 	eap->init = eap_aka_prime_init;
   1256 	eap->reset = eap_aka_reset;
   1257 	eap->buildReq = eap_aka_buildReq;
   1258 	eap->check = eap_aka_check;
   1259 	eap->process = eap_aka_process;
   1260 	eap->isDone = eap_aka_isDone;
   1261 	eap->getKey = eap_aka_getKey;
   1262 	eap->isSuccess = eap_aka_isSuccess;
   1263 	eap->get_emsk = eap_aka_get_emsk;
   1264 
   1265 	ret = eap_server_method_register(eap);
   1266 	if (ret)
   1267 		eap_server_method_free(eap);
   1268 
   1269 	return ret;
   1270 }
   1271 #endif /* EAP_SERVER_AKA_PRIME */
   1272