eap_aka.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
1/*
2 * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf)
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16
17#include "common.h"
18#include "pcsc_funcs.h"
19#include "crypto/crypto.h"
20#include "crypto/sha1.h"
21#include "crypto/sha256.h"
22#include "crypto/milenage.h"
23#include "eap_common/eap_sim_common.h"
24#include "eap_config.h"
25#include "eap_i.h"
26
27
28struct eap_aka_data {
29	u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN];
30	size_t res_len;
31	u8 nonce_s[EAP_SIM_NONCE_S_LEN];
32	u8 mk[EAP_SIM_MK_LEN];
33	u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
34	u8 k_encr[EAP_SIM_K_ENCR_LEN];
35	u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */
36	u8 msk[EAP_SIM_KEYING_DATA_LEN];
37	u8 emsk[EAP_EMSK_LEN];
38	u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN];
39	u8 auts[EAP_AKA_AUTS_LEN];
40
41	int num_id_req, num_notification;
42	u8 *pseudonym;
43	size_t pseudonym_len;
44	u8 *reauth_id;
45	size_t reauth_id_len;
46	int reauth;
47	unsigned int counter, counter_too_small;
48	u8 *last_eap_identity;
49	size_t last_eap_identity_len;
50	enum {
51		CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE
52	} state;
53
54	struct wpabuf *id_msgs;
55	int prev_id;
56	int result_ind, use_result_ind;
57	u8 eap_method;
58	u8 *network_name;
59	size_t network_name_len;
60	u16 kdf;
61	int kdf_negotiation;
62};
63
64
65#ifndef CONFIG_NO_STDOUT_DEBUG
66static const char * eap_aka_state_txt(int state)
67{
68	switch (state) {
69	case CONTINUE:
70		return "CONTINUE";
71	case RESULT_SUCCESS:
72		return "RESULT_SUCCESS";
73	case RESULT_FAILURE:
74		return "RESULT_FAILURE";
75	case SUCCESS:
76		return "SUCCESS";
77	case FAILURE:
78		return "FAILURE";
79	default:
80		return "?";
81	}
82}
83#endif /* CONFIG_NO_STDOUT_DEBUG */
84
85
86static void eap_aka_state(struct eap_aka_data *data, int state)
87{
88	wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
89		   eap_aka_state_txt(data->state),
90		   eap_aka_state_txt(state));
91	data->state = state;
92}
93
94
95static void * eap_aka_init(struct eap_sm *sm)
96{
97	struct eap_aka_data *data;
98	const char *phase1 = eap_get_config_phase1(sm);
99
100	data = os_zalloc(sizeof(*data));
101	if (data == NULL)
102		return NULL;
103
104	data->eap_method = EAP_TYPE_AKA;
105
106	eap_aka_state(data, CONTINUE);
107	data->prev_id = -1;
108
109	data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL;
110
111	return data;
112}
113
114
115#ifdef EAP_AKA_PRIME
116static void * eap_aka_prime_init(struct eap_sm *sm)
117{
118	struct eap_aka_data *data = eap_aka_init(sm);
119	if (data == NULL)
120		return NULL;
121	data->eap_method = EAP_TYPE_AKA_PRIME;
122	return data;
123}
124#endif /* EAP_AKA_PRIME */
125
126
127static void eap_aka_deinit(struct eap_sm *sm, void *priv)
128{
129	struct eap_aka_data *data = priv;
130	if (data) {
131		os_free(data->pseudonym);
132		os_free(data->reauth_id);
133		os_free(data->last_eap_identity);
134		wpabuf_free(data->id_msgs);
135		os_free(data->network_name);
136		os_free(data);
137	}
138}
139
140
141static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data)
142{
143	struct eap_peer_config *conf;
144
145	wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm");
146
147	conf = eap_get_config(sm);
148	if (conf == NULL)
149		return -1;
150	if (conf->pcsc) {
151		return scard_umts_auth(sm->scard_ctx, data->rand,
152				       data->autn, data->res, &data->res_len,
153				       data->ik, data->ck, data->auts);
154	}
155
156#ifdef CONFIG_USIM_SIMULATOR
157	if (conf->password) {
158		u8 opc[16], k[16], sqn[6];
159		const char *pos;
160		wpa_printf(MSG_DEBUG, "EAP-AKA: Use internal Milenage "
161			   "implementation for UMTS authentication");
162		if (conf->password_len < 78) {
163			wpa_printf(MSG_DEBUG, "EAP-AKA: invalid Milenage "
164				   "password");
165			return -1;
166		}
167		pos = (const char *) conf->password;
168		if (hexstr2bin(pos, k, 16))
169			return -1;
170		pos += 32;
171		if (*pos != ':')
172			return -1;
173		pos++;
174
175		if (hexstr2bin(pos, opc, 16))
176			return -1;
177		pos += 32;
178		if (*pos != ':')
179			return -1;
180		pos++;
181
182		if (hexstr2bin(pos, sqn, 6))
183			return -1;
184
185		return milenage_check(opc, k, sqn, data->rand, data->autn,
186				      data->ik, data->ck,
187				      data->res, &data->res_len, data->auts);
188	}
189#endif /* CONFIG_USIM_SIMULATOR */
190
191#ifdef CONFIG_USIM_HARDCODED
192	wpa_printf(MSG_DEBUG, "EAP-AKA: Use hardcoded Kc and SRES values for "
193		   "testing");
194
195	/* These hardcoded Kc and SRES values are used for testing.
196	 * Could consider making them configurable. */
197	os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN);
198	data->res_len = EAP_AKA_RES_MAX_LEN;
199	os_memset(data->ik, '3', EAP_AKA_IK_LEN);
200	os_memset(data->ck, '4', EAP_AKA_CK_LEN);
201	{
202		u8 autn[EAP_AKA_AUTN_LEN];
203		os_memset(autn, '1', EAP_AKA_AUTN_LEN);
204		if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) {
205			wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match "
206				   "with expected value");
207			return -1;
208		}
209	}
210#if 0
211	{
212		static int test_resync = 1;
213		if (test_resync) {
214			/* Test Resynchronization */
215			test_resync = 0;
216			return -2;
217		}
218	}
219#endif
220	return 0;
221
222#else /* CONFIG_USIM_HARDCODED */
223
224	wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorith "
225		   "enabled");
226	return -1;
227
228#endif /* CONFIG_USIM_HARDCODED */
229}
230
231
232#define CLEAR_PSEUDONYM	0x01
233#define CLEAR_REAUTH_ID	0x02
234#define CLEAR_EAP_ID	0x04
235
236static void eap_aka_clear_identities(struct eap_aka_data *data, int id)
237{
238	if (id & CLEAR_PSEUDONYM) {
239		wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old pseudonym");
240		os_free(data->pseudonym);
241		data->pseudonym = NULL;
242		data->pseudonym_len = 0;
243	}
244	if (id & CLEAR_REAUTH_ID) {
245		wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old reauth_id");
246		os_free(data->reauth_id);
247		data->reauth_id = NULL;
248		data->reauth_id_len = 0;
249	}
250	if (id & CLEAR_EAP_ID) {
251		wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old eap_id");
252		os_free(data->last_eap_identity);
253		data->last_eap_identity = NULL;
254		data->last_eap_identity_len = 0;
255	}
256}
257
258
259static int eap_aka_learn_ids(struct eap_aka_data *data,
260			     struct eap_sim_attrs *attr)
261{
262	if (attr->next_pseudonym) {
263		os_free(data->pseudonym);
264		data->pseudonym = os_malloc(attr->next_pseudonym_len);
265		if (data->pseudonym == NULL) {
266			wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
267				   "next pseudonym");
268			return -1;
269		}
270		os_memcpy(data->pseudonym, attr->next_pseudonym,
271			  attr->next_pseudonym_len);
272		data->pseudonym_len = attr->next_pseudonym_len;
273		wpa_hexdump_ascii(MSG_DEBUG,
274				  "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
275				  data->pseudonym,
276				  data->pseudonym_len);
277	}
278
279	if (attr->next_reauth_id) {
280		os_free(data->reauth_id);
281		data->reauth_id = os_malloc(attr->next_reauth_id_len);
282		if (data->reauth_id == NULL) {
283			wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
284				   "next reauth_id");
285			return -1;
286		}
287		os_memcpy(data->reauth_id, attr->next_reauth_id,
288			  attr->next_reauth_id_len);
289		data->reauth_id_len = attr->next_reauth_id_len;
290		wpa_hexdump_ascii(MSG_DEBUG,
291				  "EAP-AKA: (encr) AT_NEXT_REAUTH_ID",
292				  data->reauth_id,
293				  data->reauth_id_len);
294	}
295
296	return 0;
297}
298
299
300static int eap_aka_add_id_msg(struct eap_aka_data *data,
301			      const struct wpabuf *msg)
302{
303	if (msg == NULL)
304		return -1;
305
306	if (data->id_msgs == NULL) {
307		data->id_msgs = wpabuf_dup(msg);
308		return data->id_msgs == NULL ? -1 : 0;
309	}
310
311	if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
312		return -1;
313	wpabuf_put_buf(data->id_msgs, msg);
314
315	return 0;
316}
317
318
319static void eap_aka_add_checkcode(struct eap_aka_data *data,
320				  struct eap_sim_msg *msg)
321{
322	const u8 *addr;
323	size_t len;
324	u8 hash[SHA256_MAC_LEN];
325
326	wpa_printf(MSG_DEBUG, "   AT_CHECKCODE");
327
328	if (data->id_msgs == NULL) {
329		/*
330		 * No EAP-AKA/Identity packets were exchanged - send empty
331		 * checkcode.
332		 */
333		eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
334		return;
335	}
336
337	/* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */
338	addr = wpabuf_head(data->id_msgs);
339	len = wpabuf_len(data->id_msgs);
340	wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
341#ifdef EAP_AKA_PRIME
342	if (data->eap_method == EAP_TYPE_AKA_PRIME)
343		sha256_vector(1, &addr, &len, hash);
344	else
345#endif /* EAP_AKA_PRIME */
346		sha1_vector(1, &addr, &len, hash);
347
348	eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
349			data->eap_method == EAP_TYPE_AKA_PRIME ?
350			EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
351}
352
353
354static int eap_aka_verify_checkcode(struct eap_aka_data *data,
355				    const u8 *checkcode, size_t checkcode_len)
356{
357	const u8 *addr;
358	size_t len;
359	u8 hash[SHA256_MAC_LEN];
360	size_t hash_len;
361
362	if (checkcode == NULL)
363		return -1;
364
365	if (data->id_msgs == NULL) {
366		if (checkcode_len != 0) {
367			wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server "
368				   "indicates that AKA/Identity messages were "
369				   "used, but they were not");
370			return -1;
371		}
372		return 0;
373	}
374
375	hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ?
376		EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN;
377
378	if (checkcode_len != hash_len) {
379		wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server "
380			   "indicates that AKA/Identity message were not "
381			   "used, but they were");
382		return -1;
383	}
384
385	/* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */
386	addr = wpabuf_head(data->id_msgs);
387	len = wpabuf_len(data->id_msgs);
388#ifdef EAP_AKA_PRIME
389	if (data->eap_method == EAP_TYPE_AKA_PRIME)
390		sha256_vector(1, &addr, &len, hash);
391	else
392#endif /* EAP_AKA_PRIME */
393		sha1_vector(1, &addr, &len, hash);
394
395	if (os_memcmp(hash, checkcode, hash_len) != 0) {
396		wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
397		return -1;
398	}
399
400	return 0;
401}
402
403
404static struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id,
405					    int err)
406{
407	struct eap_sim_msg *msg;
408
409	eap_aka_state(data, FAILURE);
410	data->num_id_req = 0;
411	data->num_notification = 0;
412
413	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
414			       EAP_AKA_SUBTYPE_CLIENT_ERROR);
415	eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
416	return eap_sim_msg_finish(msg, NULL, NULL, 0);
417}
418
419
420static struct wpabuf * eap_aka_authentication_reject(struct eap_aka_data *data,
421						     u8 id)
422{
423	struct eap_sim_msg *msg;
424
425	eap_aka_state(data, FAILURE);
426	data->num_id_req = 0;
427	data->num_notification = 0;
428
429	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject "
430		   "(id=%d)", id);
431	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
432			       EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT);
433	return eap_sim_msg_finish(msg, NULL, NULL, 0);
434}
435
436
437static struct wpabuf * eap_aka_synchronization_failure(
438	struct eap_aka_data *data, u8 id)
439{
440	struct eap_sim_msg *msg;
441
442	data->num_id_req = 0;
443	data->num_notification = 0;
444
445	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure "
446		   "(id=%d)", id);
447	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
448			       EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE);
449	wpa_printf(MSG_DEBUG, "   AT_AUTS");
450	eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts,
451			     EAP_AKA_AUTS_LEN);
452	return eap_sim_msg_finish(msg, NULL, NULL, 0);
453}
454
455
456static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm,
457						 struct eap_aka_data *data,
458						 u8 id,
459						 enum eap_sim_id_req id_req)
460{
461	const u8 *identity = NULL;
462	size_t identity_len = 0;
463	struct eap_sim_msg *msg;
464
465	data->reauth = 0;
466	if (id_req == ANY_ID && data->reauth_id) {
467		identity = data->reauth_id;
468		identity_len = data->reauth_id_len;
469		data->reauth = 1;
470	} else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
471		   data->pseudonym) {
472		identity = data->pseudonym;
473		identity_len = data->pseudonym_len;
474		eap_aka_clear_identities(data, CLEAR_REAUTH_ID);
475	} else if (id_req != NO_ID_REQ) {
476		identity = eap_get_config_identity(sm, &identity_len);
477		if (identity) {
478			eap_aka_clear_identities(data, CLEAR_PSEUDONYM |
479						 CLEAR_REAUTH_ID);
480		}
481	}
482	if (id_req != NO_ID_REQ)
483		eap_aka_clear_identities(data, CLEAR_EAP_ID);
484
485	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id);
486	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
487			       EAP_AKA_SUBTYPE_IDENTITY);
488
489	if (identity) {
490		wpa_hexdump_ascii(MSG_DEBUG, "   AT_IDENTITY",
491				  identity, identity_len);
492		eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
493				identity, identity_len);
494	}
495
496	return eap_sim_msg_finish(msg, NULL, NULL, 0);
497}
498
499
500static struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data,
501						  u8 id)
502{
503	struct eap_sim_msg *msg;
504
505	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id);
506	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
507			       EAP_AKA_SUBTYPE_CHALLENGE);
508	wpa_printf(MSG_DEBUG, "   AT_RES");
509	eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8,
510			data->res, data->res_len);
511	eap_aka_add_checkcode(data, msg);
512	if (data->use_result_ind) {
513		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
514		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
515	}
516	wpa_printf(MSG_DEBUG, "   AT_MAC");
517	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
518	return eap_sim_msg_finish(msg, data->k_aut, (u8 *) "", 0);
519}
520
521
522static struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data,
523					       u8 id, int counter_too_small,
524					       const u8 *nonce_s)
525{
526	struct eap_sim_msg *msg;
527	unsigned int counter;
528
529	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)",
530		   id);
531	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
532			       EAP_AKA_SUBTYPE_REAUTHENTICATION);
533	wpa_printf(MSG_DEBUG, "   AT_IV");
534	wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
535	eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
536
537	if (counter_too_small) {
538		wpa_printf(MSG_DEBUG, "   *AT_COUNTER_TOO_SMALL");
539		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
540		counter = data->counter_too_small;
541	} else
542		counter = data->counter;
543
544	wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", counter);
545	eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
546
547	if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
548		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
549			   "AT_ENCR_DATA");
550		eap_sim_msg_free(msg);
551		return NULL;
552	}
553	eap_aka_add_checkcode(data, msg);
554	if (data->use_result_ind) {
555		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
556		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
557	}
558	wpa_printf(MSG_DEBUG, "   AT_MAC");
559	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
560	return eap_sim_msg_finish(msg, data->k_aut, nonce_s,
561				  EAP_SIM_NONCE_S_LEN);
562}
563
564
565static struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data,
566						     u8 id, u16 notification)
567{
568	struct eap_sim_msg *msg;
569	u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
570
571	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id);
572	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
573			       EAP_AKA_SUBTYPE_NOTIFICATION);
574	if (k_aut && data->reauth) {
575		wpa_printf(MSG_DEBUG, "   AT_IV");
576		wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
577		eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
578					   EAP_SIM_AT_ENCR_DATA);
579		wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", data->counter);
580		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
581				NULL, 0);
582		if (eap_sim_msg_add_encr_end(msg, data->k_encr,
583					     EAP_SIM_AT_PADDING)) {
584			wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
585				   "AT_ENCR_DATA");
586			eap_sim_msg_free(msg);
587			return NULL;
588		}
589	}
590	if (k_aut) {
591		wpa_printf(MSG_DEBUG, "   AT_MAC");
592		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
593	}
594	return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0);
595}
596
597
598static struct wpabuf * eap_aka_process_identity(struct eap_sm *sm,
599						struct eap_aka_data *data,
600						u8 id,
601						const struct wpabuf *reqData,
602						struct eap_sim_attrs *attr)
603{
604	int id_error;
605	struct wpabuf *buf;
606
607	wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity");
608
609	id_error = 0;
610	switch (attr->id_req) {
611	case NO_ID_REQ:
612		break;
613	case ANY_ID:
614		if (data->num_id_req > 0)
615			id_error++;
616		data->num_id_req++;
617		break;
618	case FULLAUTH_ID:
619		if (data->num_id_req > 1)
620			id_error++;
621		data->num_id_req++;
622		break;
623	case PERMANENT_ID:
624		if (data->num_id_req > 2)
625			id_error++;
626		data->num_id_req++;
627		break;
628	}
629	if (id_error) {
630		wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests "
631			   "used within one authentication");
632		return eap_aka_client_error(data, id,
633					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
634	}
635
636	buf = eap_aka_response_identity(sm, data, id, attr->id_req);
637
638	if (data->prev_id != id) {
639		eap_aka_add_id_msg(data, reqData);
640		eap_aka_add_id_msg(data, buf);
641		data->prev_id = id;
642	}
643
644	return buf;
645}
646
647
648static int eap_aka_verify_mac(struct eap_aka_data *data,
649			      const struct wpabuf *req,
650			      const u8 *mac, const u8 *extra,
651			      size_t extra_len)
652{
653	if (data->eap_method == EAP_TYPE_AKA_PRIME)
654		return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
655						 extra_len);
656	return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
657}
658
659
660#ifdef EAP_AKA_PRIME
661static struct wpabuf * eap_aka_prime_kdf_select(struct eap_aka_data *data,
662						u8 id, u16 kdf)
663{
664	struct eap_sim_msg *msg;
665
666	data->kdf_negotiation = 1;
667	data->kdf = kdf;
668	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d) (KDF "
669		   "select)", id);
670	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
671			       EAP_AKA_SUBTYPE_CHALLENGE);
672	wpa_printf(MSG_DEBUG, "   AT_KDF");
673	eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0);
674	return eap_sim_msg_finish(msg, NULL, NULL, 0);
675}
676
677
678static struct wpabuf * eap_aka_prime_kdf_neg(struct eap_aka_data *data,
679					     u8 id, struct eap_sim_attrs *attr)
680{
681	size_t i;
682
683	for (i = 0; i < attr->kdf_count; i++) {
684		if (attr->kdf[i] == EAP_AKA_PRIME_KDF)
685			return eap_aka_prime_kdf_select(data, id,
686							EAP_AKA_PRIME_KDF);
687	}
688
689	/* No matching KDF found - fail authentication as if AUTN had been
690	 * incorrect */
691	return eap_aka_authentication_reject(data, id);
692}
693
694
695static int eap_aka_prime_kdf_valid(struct eap_aka_data *data,
696				   struct eap_sim_attrs *attr)
697{
698	size_t i, j;
699
700	if (attr->kdf_count == 0)
701		return 0;
702
703	/* The only allowed (and required) duplication of a KDF is the addition
704	 * of the selected KDF into the beginning of the list. */
705
706	if (data->kdf_negotiation) {
707		if (attr->kdf[0] != data->kdf) {
708			wpa_printf(MSG_WARNING, "EAP-AKA': The server did not "
709				   "accept the selected KDF");
710			return 0;
711		}
712
713		for (i = 1; i < attr->kdf_count; i++) {
714			if (attr->kdf[i] == data->kdf)
715				break;
716		}
717		if (i == attr->kdf_count &&
718		    attr->kdf_count < EAP_AKA_PRIME_KDF_MAX) {
719			wpa_printf(MSG_WARNING, "EAP-AKA': The server did not "
720				   "duplicate the selected KDF");
721			return 0;
722		}
723
724		/* TODO: should check that the list is identical to the one
725		 * used in the previous Challenge message apart from the added
726		 * entry in the beginning. */
727	}
728
729	for (i = data->kdf ? 1 : 0; i < attr->kdf_count; i++) {
730		for (j = i + 1; j < attr->kdf_count; j++) {
731			if (attr->kdf[i] == attr->kdf[j]) {
732				wpa_printf(MSG_WARNING, "EAP-AKA': The server "
733					   "included a duplicated KDF");
734				return 0;
735			}
736		}
737	}
738
739	return 1;
740}
741#endif /* EAP_AKA_PRIME */
742
743
744static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm,
745						 struct eap_aka_data *data,
746						 u8 id,
747						 const struct wpabuf *reqData,
748						 struct eap_sim_attrs *attr)
749{
750	const u8 *identity;
751	size_t identity_len;
752	int res;
753	struct eap_sim_attrs eattr;
754
755	wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge");
756
757	if (attr->checkcode &&
758	    eap_aka_verify_checkcode(data, attr->checkcode,
759				     attr->checkcode_len)) {
760		wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
761			   "message");
762		return eap_aka_client_error(data, id,
763					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
764	}
765
766#ifdef EAP_AKA_PRIME
767	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
768		if (!attr->kdf_input || attr->kdf_input_len == 0) {
769			wpa_printf(MSG_WARNING, "EAP-AKA': Challenge message "
770				   "did not include non-empty AT_KDF_INPUT");
771			/* Fail authentication as if AUTN had been incorrect */
772			return eap_aka_authentication_reject(data, id);
773		}
774		os_free(data->network_name);
775		data->network_name = os_malloc(attr->kdf_input_len);
776		if (data->network_name == NULL) {
777			wpa_printf(MSG_WARNING, "EAP-AKA': No memory for "
778				   "storing Network Name");
779			return eap_aka_authentication_reject(data, id);
780		}
781		os_memcpy(data->network_name, attr->kdf_input,
782			  attr->kdf_input_len);
783		data->network_name_len = attr->kdf_input_len;
784		wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': Network Name "
785				  "(AT_KDF_INPUT)",
786				  data->network_name, data->network_name_len);
787		/* TODO: check Network Name per 3GPP.33.402 */
788
789		if (!eap_aka_prime_kdf_valid(data, attr))
790			return eap_aka_authentication_reject(data, id);
791
792		if (attr->kdf[0] != EAP_AKA_PRIME_KDF)
793			return eap_aka_prime_kdf_neg(data, id, attr);
794
795		data->kdf = EAP_AKA_PRIME_KDF;
796		wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
797	}
798
799	if (data->eap_method == EAP_TYPE_AKA && attr->bidding) {
800		u16 flags = WPA_GET_BE16(attr->bidding);
801		if ((flags & EAP_AKA_BIDDING_FLAG_D) &&
802		    eap_allowed_method(sm, EAP_VENDOR_IETF,
803				       EAP_TYPE_AKA_PRIME)) {
804			wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from "
805				   "AKA' to AKA detected");
806			/* Fail authentication as if AUTN had been incorrect */
807			return eap_aka_authentication_reject(data, id);
808		}
809	}
810#endif /* EAP_AKA_PRIME */
811
812	data->reauth = 0;
813	if (!attr->mac || !attr->rand || !attr->autn) {
814		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
815			   "did not include%s%s%s",
816			   !attr->mac ? " AT_MAC" : "",
817			   !attr->rand ? " AT_RAND" : "",
818			   !attr->autn ? " AT_AUTN" : "");
819		return eap_aka_client_error(data, id,
820					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
821	}
822	os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN);
823	os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN);
824
825	res = eap_aka_umts_auth(sm, data);
826	if (res == -1) {
827		wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
828			   "failed (AUTN)");
829		return eap_aka_authentication_reject(data, id);
830	} else if (res == -2) {
831		wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
832			   "failed (AUTN seq# -> AUTS)");
833		return eap_aka_synchronization_failure(data, id);
834	} else if (res) {
835		wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed");
836		return eap_aka_client_error(data, id,
837					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
838	}
839#ifdef EAP_AKA_PRIME
840	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
841		/* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
842		 * needed 6-octet SQN ^ AK for CK',IK' derivation */
843		u16 amf = WPA_GET_BE16(data->autn + 6);
844		if (!(amf & 0x8000)) {
845			wpa_printf(MSG_WARNING, "EAP-AKA': AMF separation bit "
846				   "not set (AMF=0x%4x)", amf);
847			return eap_aka_authentication_reject(data, id);
848		}
849		eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
850						 data->autn,
851						 data->network_name,
852						 data->network_name_len);
853	}
854#endif /* EAP_AKA_PRIME */
855	if (data->last_eap_identity) {
856		identity = data->last_eap_identity;
857		identity_len = data->last_eap_identity_len;
858	} else if (data->pseudonym) {
859		identity = data->pseudonym;
860		identity_len = data->pseudonym_len;
861	} else
862		identity = eap_get_config_identity(sm, &identity_len);
863	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
864			  "derivation", identity, identity_len);
865	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
866		eap_aka_prime_derive_keys(identity, identity_len, data->ik,
867					  data->ck, data->k_encr, data->k_aut,
868					  data->k_re, data->msk, data->emsk);
869	} else {
870		eap_aka_derive_mk(identity, identity_len, data->ik, data->ck,
871				  data->mk);
872		eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
873				    data->msk, data->emsk);
874	}
875	if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
876		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
877			   "used invalid AT_MAC");
878		return eap_aka_client_error(data, id,
879					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
880	}
881
882	/* Old reauthentication identity must not be used anymore. In
883	 * other words, if no new identities are received, full
884	 * authentication will be used on next reauthentication (using
885	 * pseudonym identity or permanent identity). */
886	eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
887
888	if (attr->encr_data) {
889		u8 *decrypted;
890		decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
891					       attr->encr_data_len, attr->iv,
892					       &eattr, 0);
893		if (decrypted == NULL) {
894			return eap_aka_client_error(
895				data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET);
896		}
897		eap_aka_learn_ids(data, &eattr);
898		os_free(decrypted);
899	}
900
901	if (data->result_ind && attr->result_ind)
902		data->use_result_ind = 1;
903
904	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
905		eap_aka_state(data, data->use_result_ind ?
906			      RESULT_SUCCESS : SUCCESS);
907	}
908
909	data->num_id_req = 0;
910	data->num_notification = 0;
911	/* RFC 4187 specifies that counter is initialized to one after
912	 * fullauth, but initializing it to zero makes it easier to implement
913	 * reauth verification. */
914	data->counter = 0;
915	return eap_aka_response_challenge(data, id);
916}
917
918
919static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
920					       struct eap_sim_attrs *attr)
921{
922	struct eap_sim_attrs eattr;
923	u8 *decrypted;
924
925	if (attr->encr_data == NULL || attr->iv == NULL) {
926		wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after "
927			   "reauth did not include encrypted data");
928		return -1;
929	}
930
931	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
932				       attr->encr_data_len, attr->iv, &eattr,
933				       0);
934	if (decrypted == NULL) {
935		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
936			   "data from notification message");
937		return -1;
938	}
939
940	if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
941		wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification "
942			   "message does not match with counter in reauth "
943			   "message");
944		os_free(decrypted);
945		return -1;
946	}
947
948	os_free(decrypted);
949	return 0;
950}
951
952
953static int eap_aka_process_notification_auth(struct eap_aka_data *data,
954					     const struct wpabuf *reqData,
955					     struct eap_sim_attrs *attr)
956{
957	if (attr->mac == NULL) {
958		wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth "
959			   "Notification message");
960		return -1;
961	}
962
963	if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
964		wpa_printf(MSG_WARNING, "EAP-AKA: Notification message "
965			   "used invalid AT_MAC");
966		return -1;
967	}
968
969	if (data->reauth &&
970	    eap_aka_process_notification_reauth(data, attr)) {
971		wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification "
972			   "message after reauth");
973		return -1;
974	}
975
976	return 0;
977}
978
979
980static struct wpabuf * eap_aka_process_notification(
981	struct eap_sm *sm, struct eap_aka_data *data, u8 id,
982	const struct wpabuf *reqData, struct eap_sim_attrs *attr)
983{
984	wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification");
985	if (data->num_notification > 0) {
986		wpa_printf(MSG_INFO, "EAP-AKA: too many notification "
987			   "rounds (only one allowed)");
988		return eap_aka_client_error(data, id,
989					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
990	}
991	data->num_notification++;
992	if (attr->notification == -1) {
993		wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in "
994			   "Notification message");
995		return eap_aka_client_error(data, id,
996					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
997	}
998
999	if ((attr->notification & 0x4000) == 0 &&
1000	    eap_aka_process_notification_auth(data, reqData, attr)) {
1001		return eap_aka_client_error(data, id,
1002					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1003	}
1004
1005	eap_sim_report_notification(sm->msg_ctx, attr->notification, 1);
1006	if (attr->notification >= 0 && attr->notification < 32768) {
1007		eap_aka_state(data, FAILURE);
1008	} else if (attr->notification == EAP_SIM_SUCCESS &&
1009		   data->state == RESULT_SUCCESS)
1010		eap_aka_state(data, SUCCESS);
1011	return eap_aka_response_notification(data, id, attr->notification);
1012}
1013
1014
1015static struct wpabuf * eap_aka_process_reauthentication(
1016	struct eap_sm *sm, struct eap_aka_data *data, u8 id,
1017	const struct wpabuf *reqData, struct eap_sim_attrs *attr)
1018{
1019	struct eap_sim_attrs eattr;
1020	u8 *decrypted;
1021
1022	wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication");
1023
1024	if (attr->checkcode &&
1025	    eap_aka_verify_checkcode(data, attr->checkcode,
1026				     attr->checkcode_len)) {
1027		wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
1028			   "message");
1029		return eap_aka_client_error(data, id,
1030					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1031	}
1032
1033	if (data->reauth_id == NULL) {
1034		wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying "
1035			   "reauthentication, but no reauth_id available");
1036		return eap_aka_client_error(data, id,
1037					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1038	}
1039
1040	data->reauth = 1;
1041	if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
1042		wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
1043			   "did not have valid AT_MAC");
1044		return eap_aka_client_error(data, id,
1045					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1046	}
1047
1048	if (attr->encr_data == NULL || attr->iv == NULL) {
1049		wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
1050			   "message did not include encrypted data");
1051		return eap_aka_client_error(data, id,
1052					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1053	}
1054
1055	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1056				       attr->encr_data_len, attr->iv, &eattr,
1057				       0);
1058	if (decrypted == NULL) {
1059		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
1060			   "data from reauthentication message");
1061		return eap_aka_client_error(data, id,
1062					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1063	}
1064
1065	if (eattr.nonce_s == NULL || eattr.counter < 0) {
1066		wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet",
1067			   !eattr.nonce_s ? " AT_NONCE_S" : "",
1068			   eattr.counter < 0 ? " AT_COUNTER" : "");
1069		os_free(decrypted);
1070		return eap_aka_client_error(data, id,
1071					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1072	}
1073
1074	if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
1075		struct wpabuf *res;
1076		wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter "
1077			   "(%d <= %d)", eattr.counter, data->counter);
1078		data->counter_too_small = eattr.counter;
1079
1080		/* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
1081		 * reauth_id must not be used to start a new reauthentication.
1082		 * However, since it was used in the last EAP-Response-Identity
1083		 * packet, it has to saved for the following fullauth to be
1084		 * used in MK derivation. */
1085		os_free(data->last_eap_identity);
1086		data->last_eap_identity = data->reauth_id;
1087		data->last_eap_identity_len = data->reauth_id_len;
1088		data->reauth_id = NULL;
1089		data->reauth_id_len = 0;
1090
1091		res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s);
1092		os_free(decrypted);
1093
1094		return res;
1095	}
1096	data->counter = eattr.counter;
1097
1098	os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
1099	wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S",
1100		    data->nonce_s, EAP_SIM_NONCE_S_LEN);
1101
1102	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1103		eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
1104						 data->reauth_id,
1105						 data->reauth_id_len,
1106						 data->nonce_s,
1107						 data->msk, data->emsk);
1108	} else {
1109		eap_sim_derive_keys_reauth(data->counter, data->reauth_id,
1110					   data->reauth_id_len,
1111					   data->nonce_s, data->mk,
1112					   data->msk, data->emsk);
1113	}
1114	eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1115	eap_aka_learn_ids(data, &eattr);
1116
1117	if (data->result_ind && attr->result_ind)
1118		data->use_result_ind = 1;
1119
1120	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
1121		eap_aka_state(data, data->use_result_ind ?
1122			      RESULT_SUCCESS : SUCCESS);
1123	}
1124
1125	data->num_id_req = 0;
1126	data->num_notification = 0;
1127	if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) {
1128		wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of "
1129			   "fast reauths performed - force fullauth");
1130		eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1131	}
1132	os_free(decrypted);
1133	return eap_aka_response_reauth(data, id, 0, data->nonce_s);
1134}
1135
1136
1137static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv,
1138				       struct eap_method_ret *ret,
1139				       const struct wpabuf *reqData)
1140{
1141	struct eap_aka_data *data = priv;
1142	const struct eap_hdr *req;
1143	u8 subtype, id;
1144	struct wpabuf *res;
1145	const u8 *pos;
1146	struct eap_sim_attrs attr;
1147	size_t len;
1148
1149	wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData);
1150	if (eap_get_config_identity(sm, &len) == NULL) {
1151		wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured");
1152		eap_sm_request_identity(sm);
1153		ret->ignore = TRUE;
1154		return NULL;
1155	}
1156
1157	pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData,
1158			       &len);
1159	if (pos == NULL || len < 1) {
1160		ret->ignore = TRUE;
1161		return NULL;
1162	}
1163	req = wpabuf_head(reqData);
1164	id = req->identifier;
1165	len = be_to_host16(req->length);
1166
1167	ret->ignore = FALSE;
1168	ret->methodState = METHOD_MAY_CONT;
1169	ret->decision = DECISION_FAIL;
1170	ret->allowNotifications = TRUE;
1171
1172	subtype = *pos++;
1173	wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype);
1174	pos += 2; /* Reserved */
1175
1176	if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr,
1177			       data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
1178			       0)) {
1179		res = eap_aka_client_error(data, id,
1180					   EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1181		goto done;
1182	}
1183
1184	switch (subtype) {
1185	case EAP_AKA_SUBTYPE_IDENTITY:
1186		res = eap_aka_process_identity(sm, data, id, reqData, &attr);
1187		break;
1188	case EAP_AKA_SUBTYPE_CHALLENGE:
1189		res = eap_aka_process_challenge(sm, data, id, reqData, &attr);
1190		break;
1191	case EAP_AKA_SUBTYPE_NOTIFICATION:
1192		res = eap_aka_process_notification(sm, data, id, reqData,
1193						   &attr);
1194		break;
1195	case EAP_AKA_SUBTYPE_REAUTHENTICATION:
1196		res = eap_aka_process_reauthentication(sm, data, id, reqData,
1197						       &attr);
1198		break;
1199	case EAP_AKA_SUBTYPE_CLIENT_ERROR:
1200		wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error");
1201		res = eap_aka_client_error(data, id,
1202					   EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1203		break;
1204	default:
1205		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype);
1206		res = eap_aka_client_error(data, id,
1207					   EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1208		break;
1209	}
1210
1211done:
1212	if (data->state == FAILURE) {
1213		ret->decision = DECISION_FAIL;
1214		ret->methodState = METHOD_DONE;
1215	} else if (data->state == SUCCESS) {
1216		ret->decision = data->use_result_ind ?
1217			DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
1218		/*
1219		 * It is possible for the server to reply with AKA
1220		 * Notification, so we must allow the method to continue and
1221		 * not only accept EAP-Success at this point.
1222		 */
1223		ret->methodState = data->use_result_ind ?
1224			METHOD_DONE : METHOD_MAY_CONT;
1225	} else if (data->state == RESULT_FAILURE)
1226		ret->methodState = METHOD_CONT;
1227	else if (data->state == RESULT_SUCCESS)
1228		ret->methodState = METHOD_CONT;
1229
1230	if (ret->methodState == METHOD_DONE) {
1231		ret->allowNotifications = FALSE;
1232	}
1233
1234	return res;
1235}
1236
1237
1238static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv)
1239{
1240	struct eap_aka_data *data = priv;
1241	return data->pseudonym || data->reauth_id;
1242}
1243
1244
1245static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv)
1246{
1247	struct eap_aka_data *data = priv;
1248	eap_aka_clear_identities(data, CLEAR_EAP_ID);
1249	data->prev_id = -1;
1250	wpabuf_free(data->id_msgs);
1251	data->id_msgs = NULL;
1252	data->use_result_ind = 0;
1253	data->kdf_negotiation = 0;
1254}
1255
1256
1257static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv)
1258{
1259	struct eap_aka_data *data = priv;
1260	data->num_id_req = 0;
1261	data->num_notification = 0;
1262	eap_aka_state(data, CONTINUE);
1263	return priv;
1264}
1265
1266
1267static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv,
1268				       size_t *len)
1269{
1270	struct eap_aka_data *data = priv;
1271
1272	if (data->reauth_id) {
1273		*len = data->reauth_id_len;
1274		return data->reauth_id;
1275	}
1276
1277	if (data->pseudonym) {
1278		*len = data->pseudonym_len;
1279		return data->pseudonym;
1280	}
1281
1282	return NULL;
1283}
1284
1285
1286static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv)
1287{
1288	struct eap_aka_data *data = priv;
1289	return data->state == SUCCESS;
1290}
1291
1292
1293static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
1294{
1295	struct eap_aka_data *data = priv;
1296	u8 *key;
1297
1298	if (data->state != SUCCESS)
1299		return NULL;
1300
1301	key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
1302	if (key == NULL)
1303		return NULL;
1304
1305	*len = EAP_SIM_KEYING_DATA_LEN;
1306	os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
1307
1308	return key;
1309}
1310
1311
1312static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1313{
1314	struct eap_aka_data *data = priv;
1315	u8 *key;
1316
1317	if (data->state != SUCCESS)
1318		return NULL;
1319
1320	key = os_malloc(EAP_EMSK_LEN);
1321	if (key == NULL)
1322		return NULL;
1323
1324	*len = EAP_EMSK_LEN;
1325	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
1326
1327	return key;
1328}
1329
1330
1331int eap_peer_aka_register(void)
1332{
1333	struct eap_method *eap;
1334	int ret;
1335
1336	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1337				    EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
1338	if (eap == NULL)
1339		return -1;
1340
1341	eap->init = eap_aka_init;
1342	eap->deinit = eap_aka_deinit;
1343	eap->process = eap_aka_process;
1344	eap->isKeyAvailable = eap_aka_isKeyAvailable;
1345	eap->getKey = eap_aka_getKey;
1346	eap->has_reauth_data = eap_aka_has_reauth_data;
1347	eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
1348	eap->init_for_reauth = eap_aka_init_for_reauth;
1349	eap->get_identity = eap_aka_get_identity;
1350	eap->get_emsk = eap_aka_get_emsk;
1351
1352	ret = eap_peer_method_register(eap);
1353	if (ret)
1354		eap_peer_method_free(eap);
1355	return ret;
1356}
1357
1358
1359#ifdef EAP_AKA_PRIME
1360int eap_peer_aka_prime_register(void)
1361{
1362	struct eap_method *eap;
1363	int ret;
1364
1365	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1366				    EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
1367				    "AKA'");
1368	if (eap == NULL)
1369		return -1;
1370
1371	eap->init = eap_aka_prime_init;
1372	eap->deinit = eap_aka_deinit;
1373	eap->process = eap_aka_process;
1374	eap->isKeyAvailable = eap_aka_isKeyAvailable;
1375	eap->getKey = eap_aka_getKey;
1376	eap->has_reauth_data = eap_aka_has_reauth_data;
1377	eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
1378	eap->init_for_reauth = eap_aka_init_for_reauth;
1379	eap->get_identity = eap_aka_get_identity;
1380	eap->get_emsk = eap_aka_get_emsk;
1381
1382	ret = eap_peer_method_register(eap);
1383	if (ret)
1384		eap_peer_method_free(eap);
1385
1386	return ret;
1387}
1388#endif /* EAP_AKA_PRIME */
1389