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