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