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 		return NULL;
    369 	} else if (sm->identity && sm->identity_len > 0 &&
    370 		   (sm->identity[0] == EAP_AKA_REAUTH_ID_PREFIX ||
    371 		    sm->identity[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX)) {
    372 		/* Reauth id may have expired - try fullauth */
    373 		wpa_printf(MSG_DEBUG, "   AT_FULLAUTH_ID_REQ");
    374 		eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0);
    375 	} else {
    376 		wpa_printf(MSG_DEBUG, "   AT_PERMANENT_ID_REQ");
    377 		eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
    378 	}
    379 	buf = eap_sim_msg_finish(msg, NULL, NULL, 0);
    380 	if (eap_aka_add_id_msg(data, buf) < 0) {
    381 		wpabuf_free(buf);
    382 		return NULL;
    383 	}
    384 	data->pending_id = id;
    385 	return buf;
    386 }
    387 
    388 
    389 static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
    390 			      struct eap_sim_msg *msg, u16 counter,
    391 			      const u8 *nonce_s)
    392 {
    393 	os_free(data->next_pseudonym);
    394 	if (nonce_s == NULL) {
    395 		data->next_pseudonym =
    396 			eap_sim_db_get_next_pseudonym(
    397 				sm->eap_sim_db_priv,
    398 				data->eap_method == EAP_TYPE_AKA_PRIME ?
    399 				EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
    400 	} else {
    401 		/* Do not update pseudonym during re-authentication */
    402 		data->next_pseudonym = NULL;
    403 	}
    404 	os_free(data->next_reauth_id);
    405 	if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
    406 		data->next_reauth_id =
    407 			eap_sim_db_get_next_reauth_id(
    408 				sm->eap_sim_db_priv,
    409 				data->eap_method == EAP_TYPE_AKA_PRIME ?
    410 				EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
    411 	} else {
    412 		wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication "
    413 			   "count exceeded - force full authentication");
    414 		data->next_reauth_id = NULL;
    415 	}
    416 
    417 	if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
    418 	    counter == 0 && nonce_s == NULL)
    419 		return 0;
    420 
    421 	wpa_printf(MSG_DEBUG, "   AT_IV");
    422 	wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
    423 	eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
    424 
    425 	if (counter > 0) {
    426 		wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)", counter);
    427 		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
    428 	}
    429 
    430 	if (nonce_s) {
    431 		wpa_printf(MSG_DEBUG, "   *AT_NONCE_S");
    432 		eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
    433 				EAP_SIM_NONCE_S_LEN);
    434 	}
    435 
    436 	if (data->next_pseudonym) {
    437 		wpa_printf(MSG_DEBUG, "   *AT_NEXT_PSEUDONYM (%s)",
    438 			   data->next_pseudonym);
    439 		eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
    440 				os_strlen(data->next_pseudonym),
    441 				(u8 *) data->next_pseudonym,
    442 				os_strlen(data->next_pseudonym));
    443 	}
    444 
    445 	if (data->next_reauth_id) {
    446 		wpa_printf(MSG_DEBUG, "   *AT_NEXT_REAUTH_ID (%s)",
    447 			   data->next_reauth_id);
    448 		eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
    449 				os_strlen(data->next_reauth_id),
    450 				(u8 *) data->next_reauth_id,
    451 				os_strlen(data->next_reauth_id));
    452 	}
    453 
    454 	if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
    455 		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
    456 			   "AT_ENCR_DATA");
    457 		return -1;
    458 	}
    459 
    460 	return 0;
    461 }
    462 
    463 
    464 static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
    465 					       struct eap_aka_data *data,
    466 					       u8 id)
    467 {
    468 	struct eap_sim_msg *msg;
    469 
    470 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge");
    471 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
    472 			       EAP_AKA_SUBTYPE_CHALLENGE);
    473 	wpa_printf(MSG_DEBUG, "   AT_RAND");
    474 	eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN);
    475 	wpa_printf(MSG_DEBUG, "   AT_AUTN");
    476 	eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN);
    477 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    478 		if (data->kdf) {
    479 			/* Add the selected KDF into the beginning */
    480 			wpa_printf(MSG_DEBUG, "   AT_KDF");
    481 			eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf,
    482 					NULL, 0);
    483 		}
    484 		wpa_printf(MSG_DEBUG, "   AT_KDF");
    485 		eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF,
    486 				NULL, 0);
    487 		wpa_printf(MSG_DEBUG, "   AT_KDF_INPUT");
    488 		eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT,
    489 				data->network_name_len,
    490 				data->network_name, data->network_name_len);
    491 	}
    492 
    493 	if (eap_aka_build_encr(sm, data, msg, 0, NULL)) {
    494 		eap_sim_msg_free(msg);
    495 		return NULL;
    496 	}
    497 
    498 	eap_aka_add_checkcode(data, msg);
    499 
    500 	if (sm->eap_sim_aka_result_ind) {
    501 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
    502 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
    503 	}
    504 
    505 #ifdef EAP_SERVER_AKA_PRIME
    506 	if (data->eap_method == EAP_TYPE_AKA) {
    507 		u16 flags = 0;
    508 		int i;
    509 		int aka_prime_preferred = 0;
    510 
    511 		i = 0;
    512 		while (sm->user && i < EAP_MAX_METHODS &&
    513 		       (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
    514 			sm->user->methods[i].method != EAP_TYPE_NONE)) {
    515 			if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) {
    516 				if (sm->user->methods[i].method ==
    517 				    EAP_TYPE_AKA)
    518 					break;
    519 				if (sm->user->methods[i].method ==
    520 				    EAP_TYPE_AKA_PRIME) {
    521 					aka_prime_preferred = 1;
    522 					break;
    523 				}
    524 			}
    525 			i++;
    526 		}
    527 
    528 		if (aka_prime_preferred)
    529 			flags |= EAP_AKA_BIDDING_FLAG_D;
    530 		eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0);
    531 	}
    532 #endif /* EAP_SERVER_AKA_PRIME */
    533 
    534 	wpa_printf(MSG_DEBUG, "   AT_MAC");
    535 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
    536 	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
    537 }
    538 
    539 
    540 static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm,
    541 					    struct eap_aka_data *data, u8 id)
    542 {
    543 	struct eap_sim_msg *msg;
    544 
    545 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication");
    546 
    547 	if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN))
    548 		return NULL;
    549 	wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
    550 			data->nonce_s, EAP_SIM_NONCE_S_LEN);
    551 
    552 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    553 		eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
    554 						 sm->identity,
    555 						 sm->identity_len,
    556 						 data->nonce_s,
    557 						 data->msk, data->emsk);
    558 	} else {
    559 		eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
    560 				    data->msk, data->emsk);
    561 		eap_sim_derive_keys_reauth(data->counter, sm->identity,
    562 					   sm->identity_len, data->nonce_s,
    563 					   data->mk, data->msk, data->emsk);
    564 	}
    565 
    566 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
    567 			       EAP_AKA_SUBTYPE_REAUTHENTICATION);
    568 
    569 	if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
    570 		eap_sim_msg_free(msg);
    571 		return NULL;
    572 	}
    573 
    574 	eap_aka_add_checkcode(data, msg);
    575 
    576 	if (sm->eap_sim_aka_result_ind) {
    577 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
    578 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
    579 	}
    580 
    581 	wpa_printf(MSG_DEBUG, "   AT_MAC");
    582 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
    583 	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
    584 }
    585 
    586 
    587 static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm,
    588 						  struct eap_aka_data *data,
    589 						  u8 id)
    590 {
    591 	struct eap_sim_msg *msg;
    592 
    593 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification");
    594 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
    595 			       EAP_AKA_SUBTYPE_NOTIFICATION);
    596 	wpa_printf(MSG_DEBUG, "   AT_NOTIFICATION (%d)", data->notification);
    597 	eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
    598 			NULL, 0);
    599 	if (data->use_result_ind) {
    600 		if (data->reauth) {
    601 			wpa_printf(MSG_DEBUG, "   AT_IV");
    602 			wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
    603 			eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
    604 						   EAP_SIM_AT_ENCR_DATA);
    605 			wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)",
    606 				   data->counter);
    607 			eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
    608 					NULL, 0);
    609 
    610 			if (eap_sim_msg_add_encr_end(msg, data->k_encr,
    611 						     EAP_SIM_AT_PADDING)) {
    612 				wpa_printf(MSG_WARNING, "EAP-AKA: Failed to "
    613 					   "encrypt AT_ENCR_DATA");
    614 				eap_sim_msg_free(msg);
    615 				return NULL;
    616 			}
    617 		}
    618 
    619 		wpa_printf(MSG_DEBUG, "   AT_MAC");
    620 		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
    621 	}
    622 	return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
    623 }
    624 
    625 
    626 static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id)
    627 {
    628 	struct eap_aka_data *data = priv;
    629 
    630 	data->auts_reported = 0;
    631 	switch (data->state) {
    632 	case IDENTITY:
    633 		return eap_aka_build_identity(sm, data, id);
    634 	case CHALLENGE:
    635 		return eap_aka_build_challenge(sm, data, id);
    636 	case REAUTH:
    637 		return eap_aka_build_reauth(sm, data, id);
    638 	case NOTIFICATION:
    639 		return eap_aka_build_notification(sm, data, id);
    640 	default:
    641 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
    642 			   "buildReq", data->state);
    643 		break;
    644 	}
    645 	return NULL;
    646 }
    647 
    648 
    649 static Boolean eap_aka_check(struct eap_sm *sm, void *priv,
    650 			     struct wpabuf *respData)
    651 {
    652 	struct eap_aka_data *data = priv;
    653 	const u8 *pos;
    654 	size_t len;
    655 
    656 	pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
    657 			       &len);
    658 	if (pos == NULL || len < 3) {
    659 		wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
    660 		return TRUE;
    661 	}
    662 
    663 	return FALSE;
    664 }
    665 
    666 
    667 static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
    668 {
    669 	if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR ||
    670 	    subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT)
    671 		return FALSE;
    672 
    673 	switch (data->state) {
    674 	case IDENTITY:
    675 		if (subtype != EAP_AKA_SUBTYPE_IDENTITY) {
    676 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
    677 				   "subtype %d", subtype);
    678 			return TRUE;
    679 		}
    680 		break;
    681 	case CHALLENGE:
    682 		if (subtype != EAP_AKA_SUBTYPE_CHALLENGE &&
    683 		    subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
    684 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
    685 				   "subtype %d", subtype);
    686 			return TRUE;
    687 		}
    688 		break;
    689 	case REAUTH:
    690 		if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) {
    691 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
    692 				   "subtype %d", subtype);
    693 			return TRUE;
    694 		}
    695 		break;
    696 	case NOTIFICATION:
    697 		if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) {
    698 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
    699 				   "subtype %d", subtype);
    700 			return TRUE;
    701 		}
    702 		break;
    703 	default:
    704 		wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for "
    705 			   "processing a response", data->state);
    706 		return TRUE;
    707 	}
    708 
    709 	return FALSE;
    710 }
    711 
    712 
    713 static void eap_aka_determine_identity(struct eap_sm *sm,
    714 				       struct eap_aka_data *data)
    715 {
    716 	char *username;
    717 
    718 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
    719 			  sm->identity, sm->identity_len);
    720 
    721 	username = sim_get_username(sm->identity, sm->identity_len);
    722 	if (username == NULL) {
    723 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    724 		eap_aka_state(data, NOTIFICATION);
    725 		return;
    726 	}
    727 
    728 	if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
    729 		os_free(username);
    730 		return;
    731 	}
    732 
    733 	if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
    734 	     username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
    735 	    (data->eap_method == EAP_TYPE_AKA &&
    736 	     username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
    737 		const char *permanent;
    738 		wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
    739 			   username);
    740 		permanent = eap_sim_db_get_permanent(
    741 			sm->eap_sim_db_priv, username);
    742 		os_free(username);
    743 		if (permanent == NULL) {
    744 			wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
    745 				   "identity - request permanent identity");
    746 			/* Remain in IDENTITY state for another round */
    747 			return;
    748 		}
    749 		os_strlcpy(data->permanent, permanent,
    750 			   sizeof(data->permanent));
    751 	} else if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
    752 		    username[0] == EAP_AKA_PRIME_PERMANENT_PREFIX) ||
    753 		   (data->eap_method == EAP_TYPE_AKA &&
    754 		    username[0] == EAP_AKA_PERMANENT_PREFIX)) {
    755 		wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent username '%s'",
    756 			   username);
    757 		os_strlcpy(data->permanent, username, sizeof(data->permanent));
    758 		os_free(username);
    759 	} else {
    760 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized username '%s'",
    761 			   username);
    762 		os_free(username);
    763 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    764 		eap_aka_state(data, NOTIFICATION);
    765 		return;
    766 	}
    767 
    768 	eap_aka_fullauth(sm, data);
    769 }
    770 
    771 
    772 static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data)
    773 {
    774 	size_t identity_len;
    775 	int res;
    776 
    777 	res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, data->permanent,
    778 				      data->rand, data->autn, data->ik,
    779 				      data->ck, data->res, &data->res_len, sm);
    780 	if (res == EAP_SIM_DB_PENDING) {
    781 		wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
    782 			   "not yet available - pending request");
    783 		sm->method_pending = METHOD_PENDING_WAIT;
    784 		return;
    785 	}
    786 
    787 #ifdef EAP_SERVER_AKA_PRIME
    788 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    789 		/* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
    790 		 * needed 6-octet SQN ^AK for CK',IK' derivation */
    791 		eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
    792 						 data->autn,
    793 						 data->network_name,
    794 						 data->network_name_len);
    795 	}
    796 #endif /* EAP_SERVER_AKA_PRIME */
    797 
    798 	data->reauth = NULL;
    799 	data->counter = 0; /* reset re-auth counter since this is full auth */
    800 
    801 	if (res != 0) {
    802 		wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA "
    803 			   "authentication data for the peer");
    804 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    805 		eap_aka_state(data, NOTIFICATION);
    806 		return;
    807 	}
    808 	if (sm->method_pending == METHOD_PENDING_WAIT) {
    809 		wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
    810 			   "available - abort pending wait");
    811 		sm->method_pending = METHOD_PENDING_NONE;
    812 	}
    813 
    814 	identity_len = sm->identity_len;
    815 	while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
    816 		wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null "
    817 			   "character from identity");
    818 		identity_len--;
    819 	}
    820 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation",
    821 			  sm->identity, identity_len);
    822 
    823 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    824 		eap_aka_prime_derive_keys(sm->identity, identity_len, data->ik,
    825 					  data->ck, data->k_encr, data->k_aut,
    826 					  data->k_re, data->msk, data->emsk);
    827 	} else {
    828 		eap_aka_derive_mk(sm->identity, identity_len, data->ik,
    829 				  data->ck, data->mk);
    830 		eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
    831 				    data->msk, data->emsk);
    832 	}
    833 
    834 	eap_aka_state(data, CHALLENGE);
    835 }
    836 
    837 
    838 static void eap_aka_process_identity(struct eap_sm *sm,
    839 				     struct eap_aka_data *data,
    840 				     struct wpabuf *respData,
    841 				     struct eap_sim_attrs *attr)
    842 {
    843 	u8 *new_identity;
    844 
    845 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity");
    846 
    847 	if (attr->mac || attr->iv || attr->encr_data) {
    848 		wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute "
    849 			   "received in EAP-Response/AKA-Identity");
    850 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    851 		eap_aka_state(data, NOTIFICATION);
    852 		return;
    853 	}
    854 
    855 	/*
    856 	 * We always request identity with AKA/Identity, so the peer is
    857 	 * required to have replied with one.
    858 	 */
    859 	if (!attr->identity || attr->identity_len == 0) {
    860 		wpa_printf(MSG_DEBUG, "EAP-AKA: Peer did not provide any "
    861 			   "identity");
    862 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    863 		eap_aka_state(data, NOTIFICATION);
    864 		return;
    865 	}
    866 
    867 	new_identity = os_malloc(attr->identity_len);
    868 	if (new_identity == NULL) {
    869 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    870 		eap_aka_state(data, NOTIFICATION);
    871 		return;
    872 	}
    873 	os_free(sm->identity);
    874 	sm->identity = new_identity;
    875 	os_memcpy(sm->identity, attr->identity, attr->identity_len);
    876 	sm->identity_len = attr->identity_len;
    877 
    878 	eap_aka_determine_identity(sm, data);
    879 	if (eap_get_id(respData) == data->pending_id) {
    880 		data->pending_id = -1;
    881 		eap_aka_add_id_msg(data, respData);
    882 	}
    883 }
    884 
    885 
    886 static int eap_aka_verify_mac(struct eap_aka_data *data,
    887 			      const struct wpabuf *req,
    888 			      const u8 *mac, const u8 *extra,
    889 			      size_t extra_len)
    890 {
    891 	if (data->eap_method == EAP_TYPE_AKA_PRIME)
    892 		return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
    893 						 extra_len);
    894 	return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
    895 }
    896 
    897 
    898 static void eap_aka_process_challenge(struct eap_sm *sm,
    899 				      struct eap_aka_data *data,
    900 				      struct wpabuf *respData,
    901 				      struct eap_sim_attrs *attr)
    902 {
    903 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
    904 
    905 #ifdef EAP_SERVER_AKA_PRIME
    906 #if 0
    907 	/* KDF negotiation; to be enabled only after more than one KDF is
    908 	 * supported */
    909 	if (data->eap_method == EAP_TYPE_AKA_PRIME &&
    910 	    attr->kdf_count == 1 && attr->mac == NULL) {
    911 		if (attr->kdf[0] != EAP_AKA_PRIME_KDF) {
    912 			wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected "
    913 				   "unknown KDF");
    914 			data->notification =
    915 				EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    916 			eap_aka_state(data, NOTIFICATION);
    917 			return;
    918 		}
    919 
    920 		data->kdf = attr->kdf[0];
    921 
    922 		/* Allow negotiation to continue with the selected KDF by
    923 		 * sending another Challenge message */
    924 		wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
    925 		return;
    926 	}
    927 #endif
    928 #endif /* EAP_SERVER_AKA_PRIME */
    929 
    930 	if (attr->checkcode &&
    931 	    eap_aka_verify_checkcode(data, attr->checkcode,
    932 				     attr->checkcode_len)) {
    933 		wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
    934 			   "message");
    935 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    936 		eap_aka_state(data, NOTIFICATION);
    937 		return;
    938 	}
    939 	if (attr->mac == NULL ||
    940 	    eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) {
    941 		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
    942 			   "did not include valid AT_MAC");
    943 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    944 		eap_aka_state(data, NOTIFICATION);
    945 		return;
    946 	}
    947 
    948 	/*
    949 	 * AT_RES is padded, so verify that there is enough room for RES and
    950 	 * that the RES length in bits matches with the expected RES.
    951 	 */
    952 	if (attr->res == NULL || attr->res_len < data->res_len ||
    953 	    attr->res_len_bits != data->res_len * 8 ||
    954 	    os_memcmp(attr->res, data->res, data->res_len) != 0) {
    955 		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
    956 			   "include valid AT_RES (attr len=%lu, res len=%lu "
    957 			   "bits, expected %lu bits)",
    958 			   (unsigned long) attr->res_len,
    959 			   (unsigned long) attr->res_len_bits,
    960 			   (unsigned long) data->res_len * 8);
    961 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    962 		eap_aka_state(data, NOTIFICATION);
    963 		return;
    964 	}
    965 
    966 	wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the "
    967 		   "correct AT_MAC");
    968 	if (sm->eap_sim_aka_result_ind && attr->result_ind) {
    969 		data->use_result_ind = 1;
    970 		data->notification = EAP_SIM_SUCCESS;
    971 		eap_aka_state(data, NOTIFICATION);
    972 	} else
    973 		eap_aka_state(data, SUCCESS);
    974 
    975 	if (data->next_pseudonym) {
    976 		eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, data->permanent,
    977 					 data->next_pseudonym);
    978 		data->next_pseudonym = NULL;
    979 	}
    980 	if (data->next_reauth_id) {
    981 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    982 #ifdef EAP_SERVER_AKA_PRIME
    983 			eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
    984 						    data->permanent,
    985 						    data->next_reauth_id,
    986 						    data->counter + 1,
    987 						    data->k_encr, data->k_aut,
    988 						    data->k_re);
    989 #endif /* EAP_SERVER_AKA_PRIME */
    990 		} else {
    991 			eap_sim_db_add_reauth(sm->eap_sim_db_priv,
    992 					      data->permanent,
    993 					      data->next_reauth_id,
    994 					      data->counter + 1,
    995 					      data->mk);
    996 		}
    997 		data->next_reauth_id = NULL;
    998 	}
    999 }
   1000 
   1001 
   1002 static void eap_aka_process_sync_failure(struct eap_sm *sm,
   1003 					 struct eap_aka_data *data,
   1004 					 struct wpabuf *respData,
   1005 					 struct eap_sim_attrs *attr)
   1006 {
   1007 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure");
   1008 
   1009 	if (attr->auts == NULL) {
   1010 		wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure "
   1011 			   "message did not include valid AT_AUTS");
   1012 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
   1013 		eap_aka_state(data, NOTIFICATION);
   1014 		return;
   1015 	}
   1016 
   1017 	/* Avoid re-reporting AUTS when processing pending EAP packet by
   1018 	 * maintaining a local flag stating whether this AUTS has already been
   1019 	 * reported. */
   1020 	if (!data->auts_reported &&
   1021 	    eap_sim_db_resynchronize(sm->eap_sim_db_priv, data->permanent,
   1022 				     attr->auts, data->rand)) {
   1023 		wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
   1024 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
   1025 		eap_aka_state(data, NOTIFICATION);
   1026 		return;
   1027 	}
   1028 	data->auts_reported = 1;
   1029 
   1030 	/* Remain in CHALLENGE state to re-try after resynchronization */
   1031 }
   1032 
   1033 
   1034 static void eap_aka_process_reauth(struct eap_sm *sm,
   1035 				   struct eap_aka_data *data,
   1036 				   struct wpabuf *respData,
   1037 				   struct eap_sim_attrs *attr)
   1038 {
   1039 	struct eap_sim_attrs eattr;
   1040 	u8 *decrypted = NULL;
   1041 
   1042 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
   1043 
   1044 	if (attr->mac == NULL ||
   1045 	    eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s,
   1046 			       EAP_SIM_NONCE_S_LEN)) {
   1047 		wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
   1048 			   "did not include valid AT_MAC");
   1049 		goto fail;
   1050 	}
   1051 
   1052 	if (attr->encr_data == NULL || attr->iv == NULL) {
   1053 		wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
   1054 			   "message did not include encrypted data");
   1055 		goto fail;
   1056 	}
   1057 
   1058 	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
   1059 				       attr->encr_data_len, attr->iv, &eattr,
   1060 				       0);
   1061 	if (decrypted == NULL) {
   1062 		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
   1063 			   "data from reauthentication message");
   1064 		goto fail;
   1065 	}
   1066 
   1067 	if (eattr.counter != data->counter) {
   1068 		wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
   1069 			   "used incorrect counter %u, expected %u",
   1070 			   eattr.counter, data->counter);
   1071 		goto fail;
   1072 	}
   1073 	os_free(decrypted);
   1074 	decrypted = NULL;
   1075 
   1076 	wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes "
   1077 		   "the correct AT_MAC");
   1078 
   1079 	if (eattr.counter_too_small) {
   1080 		wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
   1081 			   "included AT_COUNTER_TOO_SMALL - starting full "
   1082 			   "authentication");
   1083 		eap_aka_fullauth(sm, data);
   1084 		return;
   1085 	}
   1086 
   1087 	if (sm->eap_sim_aka_result_ind && attr->result_ind) {
   1088 		data->use_result_ind = 1;
   1089 		data->notification = EAP_SIM_SUCCESS;
   1090 		eap_aka_state(data, NOTIFICATION);
   1091 	} else
   1092 		eap_aka_state(data, SUCCESS);
   1093 
   1094 	if (data->next_reauth_id) {
   1095 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
   1096 #ifdef EAP_SERVER_AKA_PRIME
   1097 			eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
   1098 						    data->permanent,
   1099 						    data->next_reauth_id,
   1100 						    data->counter + 1,
   1101 						    data->k_encr, data->k_aut,
   1102 						    data->k_re);
   1103 #endif /* EAP_SERVER_AKA_PRIME */
   1104 		} else {
   1105 			eap_sim_db_add_reauth(sm->eap_sim_db_priv,
   1106 					      data->permanent,
   1107 					      data->next_reauth_id,
   1108 					      data->counter + 1,
   1109 					      data->mk);
   1110 		}
   1111 		data->next_reauth_id = NULL;
   1112 	} else {
   1113 		eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
   1114 		data->reauth = NULL;
   1115 	}
   1116 
   1117 	return;
   1118 
   1119 fail:
   1120 	data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
   1121 	eap_aka_state(data, NOTIFICATION);
   1122 	eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
   1123 	data->reauth = NULL;
   1124 	os_free(decrypted);
   1125 }
   1126 
   1127 
   1128 static void eap_aka_process_client_error(struct eap_sm *sm,
   1129 					 struct eap_aka_data *data,
   1130 					 struct wpabuf *respData,
   1131 					 struct eap_sim_attrs *attr)
   1132 {
   1133 	wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d",
   1134 		   attr->client_error_code);
   1135 	if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
   1136 		eap_aka_state(data, SUCCESS);
   1137 	else
   1138 		eap_aka_state(data, FAILURE);
   1139 }
   1140 
   1141 
   1142 static void eap_aka_process_authentication_reject(
   1143 	struct eap_sm *sm, struct eap_aka_data *data,
   1144 	struct wpabuf *respData, struct eap_sim_attrs *attr)
   1145 {
   1146 	wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication");
   1147 	eap_aka_state(data, FAILURE);
   1148 }
   1149 
   1150 
   1151 static void eap_aka_process_notification(struct eap_sm *sm,
   1152 					 struct eap_aka_data *data,
   1153 					 struct wpabuf *respData,
   1154 					 struct eap_sim_attrs *attr)
   1155 {
   1156 	wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification");
   1157 	if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
   1158 		eap_aka_state(data, SUCCESS);
   1159 	else
   1160 		eap_aka_state(data, FAILURE);
   1161 }
   1162 
   1163 
   1164 static void eap_aka_process(struct eap_sm *sm, void *priv,
   1165 			    struct wpabuf *respData)
   1166 {
   1167 	struct eap_aka_data *data = priv;
   1168 	const u8 *pos, *end;
   1169 	u8 subtype;
   1170 	size_t len;
   1171 	struct eap_sim_attrs attr;
   1172 
   1173 	pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
   1174 			       &len);
   1175 	if (pos == NULL || len < 3)
   1176 		return;
   1177 
   1178 	end = pos + len;
   1179 	subtype = *pos;
   1180 	pos += 3;
   1181 
   1182 	if (eap_aka_subtype_ok(data, subtype)) {
   1183 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected "
   1184 			   "EAP-AKA Subtype in EAP Response");
   1185 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
   1186 		eap_aka_state(data, NOTIFICATION);
   1187 		return;
   1188 	}
   1189 
   1190 	if (eap_sim_parse_attr(pos, end, &attr,
   1191 			       data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
   1192 			       0)) {
   1193 		wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes");
   1194 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
   1195 		eap_aka_state(data, NOTIFICATION);
   1196 		return;
   1197 	}
   1198 
   1199 	if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) {
   1200 		eap_aka_process_client_error(sm, data, respData, &attr);
   1201 		return;
   1202 	}
   1203 
   1204 	if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) {
   1205 		eap_aka_process_authentication_reject(sm, data, respData,
   1206 						      &attr);
   1207 		return;
   1208 	}
   1209 
   1210 	switch (data->state) {
   1211 	case IDENTITY:
   1212 		eap_aka_process_identity(sm, data, respData, &attr);
   1213 		break;
   1214 	case CHALLENGE:
   1215 		if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
   1216 			eap_aka_process_sync_failure(sm, data, respData,
   1217 						     &attr);
   1218 		} else {
   1219 			eap_aka_process_challenge(sm, data, respData, &attr);
   1220 		}
   1221 		break;
   1222 	case REAUTH:
   1223 		eap_aka_process_reauth(sm, data, respData, &attr);
   1224 		break;
   1225 	case NOTIFICATION:
   1226 		eap_aka_process_notification(sm, data, respData, &attr);
   1227 		break;
   1228 	default:
   1229 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
   1230 			   "process", data->state);
   1231 		break;
   1232 	}
   1233 }
   1234 
   1235 
   1236 static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv)
   1237 {
   1238 	struct eap_aka_data *data = priv;
   1239 	return data->state == SUCCESS || data->state == FAILURE;
   1240 }
   1241 
   1242 
   1243 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
   1244 {
   1245 	struct eap_aka_data *data = priv;
   1246 	u8 *key;
   1247 
   1248 	if (data->state != SUCCESS)
   1249 		return NULL;
   1250 
   1251 	key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
   1252 	if (key == NULL)
   1253 		return NULL;
   1254 	os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
   1255 	*len = EAP_SIM_KEYING_DATA_LEN;
   1256 	return key;
   1257 }
   1258 
   1259 
   1260 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
   1261 {
   1262 	struct eap_aka_data *data = priv;
   1263 	u8 *key;
   1264 
   1265 	if (data->state != SUCCESS)
   1266 		return NULL;
   1267 
   1268 	key = os_malloc(EAP_EMSK_LEN);
   1269 	if (key == NULL)
   1270 		return NULL;
   1271 	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
   1272 	*len = EAP_EMSK_LEN;
   1273 	return key;
   1274 }
   1275 
   1276 
   1277 static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv)
   1278 {
   1279 	struct eap_aka_data *data = priv;
   1280 	return data->state == SUCCESS;
   1281 }
   1282 
   1283 
   1284 int eap_server_aka_register(void)
   1285 {
   1286 	struct eap_method *eap;
   1287 	int ret;
   1288 
   1289 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
   1290 				      EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
   1291 	if (eap == NULL)
   1292 		return -1;
   1293 
   1294 	eap->init = eap_aka_init;
   1295 	eap->reset = eap_aka_reset;
   1296 	eap->buildReq = eap_aka_buildReq;
   1297 	eap->check = eap_aka_check;
   1298 	eap->process = eap_aka_process;
   1299 	eap->isDone = eap_aka_isDone;
   1300 	eap->getKey = eap_aka_getKey;
   1301 	eap->isSuccess = eap_aka_isSuccess;
   1302 	eap->get_emsk = eap_aka_get_emsk;
   1303 
   1304 	ret = eap_server_method_register(eap);
   1305 	if (ret)
   1306 		eap_server_method_free(eap);
   1307 	return ret;
   1308 }
   1309 
   1310 
   1311 #ifdef EAP_SERVER_AKA_PRIME
   1312 int eap_server_aka_prime_register(void)
   1313 {
   1314 	struct eap_method *eap;
   1315 	int ret;
   1316 
   1317 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
   1318 				      EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
   1319 				      "AKA'");
   1320 	if (eap == NULL)
   1321 		return -1;
   1322 
   1323 	eap->init = eap_aka_prime_init;
   1324 	eap->reset = eap_aka_reset;
   1325 	eap->buildReq = eap_aka_buildReq;
   1326 	eap->check = eap_aka_check;
   1327 	eap->process = eap_aka_process;
   1328 	eap->isDone = eap_aka_isDone;
   1329 	eap->getKey = eap_aka_getKey;
   1330 	eap->isSuccess = eap_aka_isSuccess;
   1331 	eap->get_emsk = eap_aka_get_emsk;
   1332 
   1333 	ret = eap_server_method_register(eap);
   1334 	if (ret)
   1335 		eap_server_method_free(eap);
   1336 
   1337 	return ret;
   1338 }
   1339 #endif /* EAP_SERVER_AKA_PRIME */
   1340