eap_sim.c revision 351611
1/*
2 * EAP peer method: EAP-SIM (RFC 4186)
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/milenage.h"
14#include "crypto/random.h"
15#include "eap_peer/eap_i.h"
16#include "eap_config.h"
17#include "eap_common/eap_sim_common.h"
18
19
20struct eap_sim_data {
21	u8 *ver_list;
22	size_t ver_list_len;
23	int selected_version;
24	size_t min_num_chal, num_chal;
25
26	u8 kc[3][EAP_SIM_KC_LEN];
27	u8 sres[3][EAP_SIM_SRES_LEN];
28	u8 nonce_mt[EAP_SIM_NONCE_MT_LEN], nonce_s[EAP_SIM_NONCE_S_LEN];
29	u8 mk[EAP_SIM_MK_LEN];
30	u8 k_aut[EAP_SIM_K_AUT_LEN];
31	u8 k_encr[EAP_SIM_K_ENCR_LEN];
32	u8 msk[EAP_SIM_KEYING_DATA_LEN];
33	u8 emsk[EAP_EMSK_LEN];
34	u8 rand[3][GSM_RAND_LEN];
35	u8 reauth_mac[EAP_SIM_MAC_LEN];
36
37	int num_id_req, num_notification;
38	u8 *pseudonym;
39	size_t pseudonym_len;
40	u8 *reauth_id;
41	size_t reauth_id_len;
42	int reauth;
43	unsigned int counter, counter_too_small;
44	u8 *last_eap_identity;
45	size_t last_eap_identity_len;
46	enum {
47		CONTINUE, RESULT_SUCCESS, SUCCESS, FAILURE
48	} state;
49	int result_ind, use_result_ind;
50	int use_pseudonym;
51	int error_code;
52};
53
54
55#ifndef CONFIG_NO_STDOUT_DEBUG
56static const char * eap_sim_state_txt(int state)
57{
58	switch (state) {
59	case CONTINUE:
60		return "CONTINUE";
61	case RESULT_SUCCESS:
62		return "RESULT_SUCCESS";
63	case SUCCESS:
64		return "SUCCESS";
65	case FAILURE:
66		return "FAILURE";
67	default:
68		return "?";
69	}
70}
71#endif /* CONFIG_NO_STDOUT_DEBUG */
72
73
74static void eap_sim_state(struct eap_sim_data *data, int state)
75{
76	wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s",
77		   eap_sim_state_txt(data->state),
78		   eap_sim_state_txt(state));
79	data->state = state;
80}
81
82
83static void * eap_sim_init(struct eap_sm *sm)
84{
85	struct eap_sim_data *data;
86	struct eap_peer_config *config = eap_get_config(sm);
87
88	data = os_zalloc(sizeof(*data));
89	if (data == NULL)
90		return NULL;
91
92	if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
93		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
94			   "for NONCE_MT");
95		os_free(data);
96		return NULL;
97	}
98
99	/* Zero is a valid error code, so we need to initialize */
100	data->error_code = NO_EAP_METHOD_ERROR;
101
102	data->min_num_chal = 2;
103	if (config && config->phase1) {
104		char *pos = os_strstr(config->phase1, "sim_min_num_chal=");
105		if (pos) {
106			data->min_num_chal = atoi(pos + 17);
107			if (data->min_num_chal < 2 || data->min_num_chal > 3) {
108				wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
109					   "sim_min_num_chal configuration "
110					   "(%lu, expected 2 or 3)",
111					   (unsigned long) data->min_num_chal);
112				os_free(data);
113				return NULL;
114			}
115			wpa_printf(MSG_DEBUG, "EAP-SIM: Set minimum number of "
116				   "challenges to %lu",
117				   (unsigned long) data->min_num_chal);
118		}
119
120		data->result_ind = os_strstr(config->phase1, "result_ind=1") !=
121			NULL;
122	}
123
124	data->use_pseudonym = !sm->init_phase2;
125	if (config && config->anonymous_identity && data->use_pseudonym) {
126		data->pseudonym = os_malloc(config->anonymous_identity_len);
127		if (data->pseudonym) {
128			os_memcpy(data->pseudonym, config->anonymous_identity,
129				  config->anonymous_identity_len);
130			data->pseudonym_len = config->anonymous_identity_len;
131		}
132	}
133
134	eap_sim_state(data, CONTINUE);
135
136	return data;
137}
138
139
140static void eap_sim_clear_keys(struct eap_sim_data *data, int reauth)
141{
142	if (!reauth) {
143		os_memset(data->mk, 0, EAP_SIM_MK_LEN);
144		os_memset(data->k_aut, 0, EAP_SIM_K_AUT_LEN);
145		os_memset(data->k_encr, 0, EAP_SIM_K_ENCR_LEN);
146	}
147	os_memset(data->kc, 0, 3 * EAP_SIM_KC_LEN);
148	os_memset(data->sres, 0, 3 * EAP_SIM_SRES_LEN);
149	os_memset(data->msk, 0, EAP_SIM_KEYING_DATA_LEN);
150	os_memset(data->emsk, 0, EAP_EMSK_LEN);
151}
152
153
154static void eap_sim_deinit(struct eap_sm *sm, void *priv)
155{
156	struct eap_sim_data *data = priv;
157	if (data) {
158		os_free(data->ver_list);
159		os_free(data->pseudonym);
160		os_free(data->reauth_id);
161		os_free(data->last_eap_identity);
162		eap_sim_clear_keys(data, 0);
163		os_free(data);
164	}
165}
166
167
168static int eap_sim_ext_sim_req(struct eap_sm *sm, struct eap_sim_data *data)
169{
170	char req[200], *pos, *end;
171	size_t i;
172
173	wpa_printf(MSG_DEBUG, "EAP-SIM: Use external SIM processing");
174	pos = req;
175	end = pos + sizeof(req);
176	pos += os_snprintf(pos, end - pos, "GSM-AUTH");
177	for (i = 0; i < data->num_chal; i++) {
178		pos += os_snprintf(pos, end - pos, ":");
179		pos += wpa_snprintf_hex(pos, end - pos, data->rand[i],
180					GSM_RAND_LEN);
181	}
182
183	eap_sm_request_sim(sm, req);
184	return 1;
185}
186
187
188static int eap_sim_ext_sim_result(struct eap_sm *sm, struct eap_sim_data *data,
189				  struct eap_peer_config *conf)
190{
191	char *resp, *pos;
192	size_t i;
193
194	wpa_printf(MSG_DEBUG,
195		   "EAP-SIM: Use result from external SIM processing");
196
197	resp = conf->external_sim_resp;
198	conf->external_sim_resp = NULL;
199
200	if (os_strncmp(resp, "GSM-AUTH:", 9) != 0) {
201		wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized external SIM processing response");
202		os_free(resp);
203		return -1;
204	}
205
206	pos = resp + 9;
207	for (i = 0; i < data->num_chal; i++) {
208		wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND",
209			    data->rand[i], GSM_RAND_LEN);
210
211		if (hexstr2bin(pos, data->kc[i], EAP_SIM_KC_LEN) < 0)
212			goto invalid;
213		wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc",
214				data->kc[i], EAP_SIM_KC_LEN);
215		pos += EAP_SIM_KC_LEN * 2;
216		if (*pos != ':')
217			goto invalid;
218		pos++;
219
220		if (hexstr2bin(pos, data->sres[i], EAP_SIM_SRES_LEN) < 0)
221			goto invalid;
222		wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES",
223				data->sres[i], EAP_SIM_SRES_LEN);
224		pos += EAP_SIM_SRES_LEN * 2;
225		if (i + 1 < data->num_chal) {
226			if (*pos != ':')
227				goto invalid;
228			pos++;
229		}
230	}
231
232	os_free(resp);
233	return 0;
234
235invalid:
236	wpa_printf(MSG_DEBUG, "EAP-SIM: Invalid external SIM processing GSM-AUTH response");
237	os_free(resp);
238	return -1;
239}
240
241
242static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data)
243{
244	struct eap_peer_config *conf;
245
246	wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm");
247
248	conf = eap_get_config(sm);
249	if (conf == NULL)
250		return -1;
251
252	if (sm->external_sim) {
253		if (conf->external_sim_resp)
254			return eap_sim_ext_sim_result(sm, data, conf);
255		else
256			return eap_sim_ext_sim_req(sm, data);
257	}
258
259#ifdef PCSC_FUNCS
260	if (conf->pcsc) {
261		if (scard_gsm_auth(sm->scard_ctx, data->rand[0],
262				   data->sres[0], data->kc[0]) ||
263		    scard_gsm_auth(sm->scard_ctx, data->rand[1],
264				   data->sres[1], data->kc[1]) ||
265		    (data->num_chal > 2 &&
266		     scard_gsm_auth(sm->scard_ctx, data->rand[2],
267				    data->sres[2], data->kc[2]))) {
268			wpa_printf(MSG_DEBUG, "EAP-SIM: GSM SIM "
269				   "authentication could not be completed");
270			return -1;
271		}
272		return 0;
273	}
274#endif /* PCSC_FUNCS */
275
276#ifdef CONFIG_SIM_SIMULATOR
277	if (conf->password) {
278		u8 opc[16], k[16];
279		const char *pos;
280		size_t i;
281		wpa_printf(MSG_DEBUG, "EAP-SIM: Use internal GSM-Milenage "
282			   "implementation for authentication");
283		if (conf->password_len < 65) {
284			wpa_printf(MSG_DEBUG, "EAP-SIM: invalid GSM-Milenage "
285				   "password");
286			return -1;
287		}
288		pos = (const char *) conf->password;
289		if (hexstr2bin(pos, k, 16))
290			return -1;
291		pos += 32;
292		if (*pos != ':')
293			return -1;
294		pos++;
295
296		if (hexstr2bin(pos, opc, 16))
297			return -1;
298
299		for (i = 0; i < data->num_chal; i++) {
300			if (gsm_milenage(opc, k, data->rand[i],
301					 data->sres[i], data->kc[i])) {
302				wpa_printf(MSG_DEBUG, "EAP-SIM: "
303					   "GSM-Milenage authentication "
304					   "could not be completed");
305				return -1;
306			}
307			wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND",
308				    data->rand[i], GSM_RAND_LEN);
309			wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES",
310					data->sres[i], EAP_SIM_SRES_LEN);
311			wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc",
312					data->kc[i], EAP_SIM_KC_LEN);
313		}
314		return 0;
315	}
316#endif /* CONFIG_SIM_SIMULATOR */
317
318#ifdef CONFIG_SIM_HARDCODED
319	/* These hardcoded Kc and SRES values are used for testing. RAND to
320	 * KC/SREC mapping is very bogus as far as real authentication is
321	 * concerned, but it is quite useful for cases where the AS is rotating
322	 * the order of pre-configured values. */
323	{
324		size_t i;
325
326		wpa_printf(MSG_DEBUG, "EAP-SIM: Use hardcoded Kc and SRES "
327			   "values for testing");
328
329		for (i = 0; i < data->num_chal; i++) {
330			if (data->rand[i][0] == 0xaa) {
331				os_memcpy(data->kc[i],
332					  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7",
333					  EAP_SIM_KC_LEN);
334				os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4",
335					  EAP_SIM_SRES_LEN);
336			} else if (data->rand[i][0] == 0xbb) {
337				os_memcpy(data->kc[i],
338					  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7",
339					  EAP_SIM_KC_LEN);
340				os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4",
341					  EAP_SIM_SRES_LEN);
342			} else {
343				os_memcpy(data->kc[i],
344					  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
345					  EAP_SIM_KC_LEN);
346				os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4",
347					  EAP_SIM_SRES_LEN);
348			}
349		}
350	}
351
352	return 0;
353
354#else /* CONFIG_SIM_HARDCODED */
355
356	wpa_printf(MSG_DEBUG, "EAP-SIM: No GSM authentication algorithm "
357		   "enabled");
358	return -1;
359
360#endif /* CONFIG_SIM_HARDCODED */
361}
362
363
364static int eap_sim_supported_ver(int version)
365{
366	return version == EAP_SIM_VERSION;
367}
368
369
370#define CLEAR_PSEUDONYM	0x01
371#define CLEAR_REAUTH_ID	0x02
372#define CLEAR_EAP_ID	0x04
373
374static void eap_sim_clear_identities(struct eap_sm *sm,
375				     struct eap_sim_data *data, int id)
376{
377	if ((id & CLEAR_PSEUDONYM) && data->pseudonym) {
378		wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old pseudonym");
379		os_free(data->pseudonym);
380		data->pseudonym = NULL;
381		data->pseudonym_len = 0;
382		if (data->use_pseudonym)
383			eap_set_anon_id(sm, NULL, 0);
384	}
385	if ((id & CLEAR_REAUTH_ID) && data->reauth_id) {
386		wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old reauth_id");
387		os_free(data->reauth_id);
388		data->reauth_id = NULL;
389		data->reauth_id_len = 0;
390	}
391	if ((id & CLEAR_EAP_ID) && data->last_eap_identity) {
392		wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old eap_id");
393		os_free(data->last_eap_identity);
394		data->last_eap_identity = NULL;
395		data->last_eap_identity_len = 0;
396	}
397}
398
399
400static int eap_sim_learn_ids(struct eap_sm *sm, struct eap_sim_data *data,
401			     struct eap_sim_attrs *attr)
402{
403	if (attr->next_pseudonym) {
404		const u8 *identity = NULL;
405		size_t identity_len = 0;
406		const u8 *realm = NULL;
407		size_t realm_len = 0;
408
409		wpa_hexdump_ascii(MSG_DEBUG,
410				  "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
411				  attr->next_pseudonym,
412				  attr->next_pseudonym_len);
413		os_free(data->pseudonym);
414		/* Look for the realm of the permanent identity */
415		identity = eap_get_config_identity(sm, &identity_len);
416		if (identity) {
417			for (realm = identity, realm_len = identity_len;
418			     realm_len > 0; realm_len--, realm++) {
419				if (*realm == '@')
420					break;
421			}
422		}
423		data->pseudonym = os_malloc(attr->next_pseudonym_len +
424					    realm_len);
425		if (data->pseudonym == NULL) {
426			wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
427				   "next pseudonym");
428			data->pseudonym_len = 0;
429			return -1;
430		}
431		os_memcpy(data->pseudonym, attr->next_pseudonym,
432			  attr->next_pseudonym_len);
433		if (realm_len) {
434			os_memcpy(data->pseudonym + attr->next_pseudonym_len,
435				  realm, realm_len);
436		}
437		data->pseudonym_len = attr->next_pseudonym_len + realm_len;
438		if (data->use_pseudonym)
439			eap_set_anon_id(sm, data->pseudonym,
440					data->pseudonym_len);
441	}
442
443	if (attr->next_reauth_id) {
444		os_free(data->reauth_id);
445		data->reauth_id = os_memdup(attr->next_reauth_id,
446					    attr->next_reauth_id_len);
447		if (data->reauth_id == NULL) {
448			wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
449				   "next reauth_id");
450			data->reauth_id_len = 0;
451			return -1;
452		}
453		data->reauth_id_len = attr->next_reauth_id_len;
454		wpa_hexdump_ascii(MSG_DEBUG,
455				  "EAP-SIM: (encr) AT_NEXT_REAUTH_ID",
456				  data->reauth_id,
457				  data->reauth_id_len);
458	}
459
460	return 0;
461}
462
463
464static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id,
465					    int err)
466{
467	struct eap_sim_msg *msg;
468
469	eap_sim_state(data, FAILURE);
470	data->num_id_req = 0;
471	data->num_notification = 0;
472
473	wpa_printf(MSG_DEBUG, "EAP-SIM: Send Client-Error (error code %d)",
474		   err);
475	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
476			       EAP_SIM_SUBTYPE_CLIENT_ERROR);
477	eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
478	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0);
479}
480
481
482static struct wpabuf * eap_sim_response_start(struct eap_sm *sm,
483					      struct eap_sim_data *data, u8 id,
484					      enum eap_sim_id_req id_req)
485{
486	const u8 *identity = NULL;
487	size_t identity_len = 0;
488	struct eap_sim_msg *msg;
489
490	data->reauth = 0;
491	if (id_req == ANY_ID && data->reauth_id) {
492		identity = data->reauth_id;
493		identity_len = data->reauth_id_len;
494		data->reauth = 1;
495	} else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
496		   data->pseudonym &&
497		   !eap_sim_anonymous_username(data->pseudonym,
498					       data->pseudonym_len)) {
499		identity = data->pseudonym;
500		identity_len = data->pseudonym_len;
501		eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID);
502	} else if (id_req != NO_ID_REQ) {
503		identity = eap_get_config_identity(sm, &identity_len);
504		if (identity) {
505			int ids = CLEAR_PSEUDONYM | CLEAR_REAUTH_ID;
506
507			if (data->pseudonym &&
508			    eap_sim_anonymous_username(data->pseudonym,
509						       data->pseudonym_len))
510				ids &= ~CLEAR_PSEUDONYM;
511			eap_sim_clear_identities(sm, data, ids);
512		}
513	}
514	if (id_req != NO_ID_REQ)
515		eap_sim_clear_identities(sm, data, CLEAR_EAP_ID);
516
517	wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id);
518	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
519			       EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START);
520	if (!data->reauth) {
521		wpa_hexdump(MSG_DEBUG, "   AT_NONCE_MT",
522			    data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
523		eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0,
524				data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
525		wpa_printf(MSG_DEBUG, "   AT_SELECTED_VERSION %d",
526			   data->selected_version);
527		eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION,
528				data->selected_version, NULL, 0);
529	}
530
531	if (identity) {
532		wpa_hexdump_ascii(MSG_DEBUG, "   AT_IDENTITY",
533				  identity, identity_len);
534		eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
535				identity, identity_len);
536	}
537
538	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0);
539}
540
541
542static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data,
543						  u8 id)
544{
545	struct eap_sim_msg *msg;
546
547	wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", id);
548	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
549			       EAP_SIM_SUBTYPE_CHALLENGE);
550	if (data->use_result_ind) {
551		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
552		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
553	}
554	wpa_printf(MSG_DEBUG, "   AT_MAC");
555	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
556	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut,
557				  (u8 *) data->sres,
558				  data->num_chal * EAP_SIM_SRES_LEN);
559}
560
561
562static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data,
563					       u8 id, int counter_too_small,
564					       const u8 *nonce_s)
565{
566	struct eap_sim_msg *msg;
567	unsigned int counter;
568
569	wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)",
570		   id);
571	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
572			       EAP_SIM_SUBTYPE_REAUTHENTICATION);
573	wpa_printf(MSG_DEBUG, "   AT_IV");
574	wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
575	eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
576
577	if (counter_too_small) {
578		wpa_printf(MSG_DEBUG, "   *AT_COUNTER_TOO_SMALL");
579		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
580		counter = data->counter_too_small;
581	} else
582		counter = data->counter;
583
584	wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", counter);
585	eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
586
587	if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
588		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
589			   "AT_ENCR_DATA");
590		eap_sim_msg_free(msg);
591		return NULL;
592	}
593	if (data->use_result_ind) {
594		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
595		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
596	}
597	wpa_printf(MSG_DEBUG, "   AT_MAC");
598	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
599	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, nonce_s,
600				  EAP_SIM_NONCE_S_LEN);
601}
602
603
604static struct wpabuf * eap_sim_response_notification(struct eap_sim_data *data,
605						     u8 id, u16 notification)
606{
607	struct eap_sim_msg *msg;
608	u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
609
610	wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", id);
611	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
612			       EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION);
613	if (k_aut && data->reauth) {
614		wpa_printf(MSG_DEBUG, "   AT_IV");
615		wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
616		eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
617					   EAP_SIM_AT_ENCR_DATA);
618		wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", data->counter);
619		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
620				NULL, 0);
621		if (eap_sim_msg_add_encr_end(msg, data->k_encr,
622					     EAP_SIM_AT_PADDING)) {
623			wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
624				   "AT_ENCR_DATA");
625			eap_sim_msg_free(msg);
626			return NULL;
627		}
628	}
629	if (k_aut) {
630		wpa_printf(MSG_DEBUG, "   AT_MAC");
631		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
632	}
633	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, k_aut, (u8 *) "", 0);
634}
635
636
637static struct wpabuf * eap_sim_process_start(struct eap_sm *sm,
638					     struct eap_sim_data *data, u8 id,
639					     struct eap_sim_attrs *attr)
640{
641	int selected_version = -1, id_error;
642	size_t i;
643	u8 *pos;
644
645	wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start");
646	if (attr->version_list == NULL) {
647		wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in "
648			   "SIM/Start");
649		return eap_sim_client_error(data, id,
650					    EAP_SIM_UNSUPPORTED_VERSION);
651	}
652
653	os_free(data->ver_list);
654	data->ver_list = os_memdup(attr->version_list, attr->version_list_len);
655	if (data->ver_list == NULL) {
656		wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate "
657			   "memory for version list");
658		return eap_sim_client_error(data, id,
659					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
660	}
661	data->ver_list_len = attr->version_list_len;
662	pos = data->ver_list;
663	for (i = 0; i < data->ver_list_len / 2; i++) {
664		int ver = pos[0] * 256 + pos[1];
665		pos += 2;
666		if (eap_sim_supported_ver(ver)) {
667			selected_version = ver;
668			break;
669		}
670	}
671	if (selected_version < 0) {
672		wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported "
673			   "version");
674		return eap_sim_client_error(data, id,
675					    EAP_SIM_UNSUPPORTED_VERSION);
676	}
677	wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d",
678		   selected_version);
679	data->selected_version = selected_version;
680
681	id_error = 0;
682	switch (attr->id_req) {
683	case NO_ID_REQ:
684		break;
685	case ANY_ID:
686		if (data->num_id_req > 0)
687			id_error++;
688		data->num_id_req++;
689		break;
690	case FULLAUTH_ID:
691		if (data->num_id_req > 1)
692			id_error++;
693		data->num_id_req++;
694		break;
695	case PERMANENT_ID:
696		if (data->num_id_req > 2)
697			id_error++;
698		data->num_id_req++;
699		break;
700	}
701	if (id_error) {
702		wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests "
703			   "used within one authentication");
704		return eap_sim_client_error(data, id,
705					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
706	}
707
708	return eap_sim_response_start(sm, data, id, attr->id_req);
709}
710
711
712static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm,
713						 struct eap_sim_data *data,
714						 u8 id,
715						 const struct wpabuf *reqData,
716						 struct eap_sim_attrs *attr)
717{
718	const u8 *identity;
719	size_t identity_len;
720	struct eap_sim_attrs eattr;
721	int res;
722
723	wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge");
724	data->reauth = 0;
725	if (!attr->mac || !attr->rand) {
726		wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
727			   "did not include%s%s",
728			   !attr->mac ? " AT_MAC" : "",
729			   !attr->rand ? " AT_RAND" : "");
730		return eap_sim_client_error(data, id,
731					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
732	}
733
734	wpa_printf(MSG_DEBUG, "EAP-SIM: %lu challenges",
735		   (unsigned long) attr->num_chal);
736	if (attr->num_chal < data->min_num_chal) {
737		wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of "
738			   "challenges (%lu)", (unsigned long) attr->num_chal);
739		return eap_sim_client_error(data, id,
740					    EAP_SIM_INSUFFICIENT_NUM_OF_CHAL);
741	}
742	if (attr->num_chal > 3) {
743		wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges "
744			   "(%lu)", (unsigned long) attr->num_chal);
745		return eap_sim_client_error(data, id,
746					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
747	}
748
749	/* Verify that RANDs are different */
750	if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN,
751		   GSM_RAND_LEN) == 0 ||
752	    (attr->num_chal > 2 &&
753	     (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN,
754			GSM_RAND_LEN) == 0 ||
755	      os_memcmp(attr->rand + GSM_RAND_LEN,
756			attr->rand + 2 * GSM_RAND_LEN,
757			GSM_RAND_LEN) == 0))) {
758		wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times");
759		return eap_sim_client_error(data, id,
760					    EAP_SIM_RAND_NOT_FRESH);
761	}
762
763	os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN);
764	data->num_chal = attr->num_chal;
765
766	res = eap_sim_gsm_auth(sm, data);
767	if (res > 0) {
768		wpa_printf(MSG_DEBUG, "EAP-SIM: Wait for external SIM processing");
769		return NULL;
770	}
771	if (res) {
772		wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed");
773		return eap_sim_client_error(data, id,
774					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
775	}
776	if (data->last_eap_identity) {
777		identity = data->last_eap_identity;
778		identity_len = data->last_eap_identity_len;
779	} else if (data->pseudonym &&
780		   !eap_sim_anonymous_username(data->pseudonym,
781					       data->pseudonym_len)) {
782		identity = data->pseudonym;
783		identity_len = data->pseudonym_len;
784	} else {
785		struct eap_peer_config *config;
786
787		config = eap_get_config(sm);
788		if (config && config->imsi_identity) {
789			identity = config->imsi_identity;
790			identity_len = config->imsi_identity_len;
791		} else {
792			identity = eap_get_config_identity(sm, &identity_len);
793		}
794	}
795	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK "
796			  "derivation", identity, identity_len);
797	eap_sim_derive_mk(identity, identity_len, data->nonce_mt,
798			  data->selected_version, data->ver_list,
799			  data->ver_list_len, data->num_chal,
800			  (const u8 *) data->kc, data->mk);
801	eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
802			    data->emsk);
803	if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, data->nonce_mt,
804			       EAP_SIM_NONCE_MT_LEN)) {
805		wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
806			   "used invalid AT_MAC");
807#ifdef TEST_FUZZ
808		wpa_printf(MSG_INFO,
809			   "TEST: Ignore AT_MAC mismatch for fuzz testing");
810#else /* TEST_FUZZ */
811		return eap_sim_client_error(data, id,
812					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
813#endif /* TEST_FUZZ */
814	}
815
816	/* Old reauthentication identity must not be used anymore. In
817	 * other words, if no new reauth identity is received, full
818	 * authentication will be used on next reauthentication (using
819	 * pseudonym identity or permanent identity). */
820	eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
821
822	if (attr->encr_data) {
823		u8 *decrypted;
824		decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
825					       attr->encr_data_len, attr->iv,
826					       &eattr, 0);
827		if (decrypted == NULL) {
828			return eap_sim_client_error(
829				data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET);
830		}
831		eap_sim_learn_ids(sm, data, &eattr);
832		os_free(decrypted);
833	}
834
835	if (data->result_ind && attr->result_ind)
836		data->use_result_ind = 1;
837
838	if (data->state != FAILURE) {
839		eap_sim_state(data, data->use_result_ind ?
840			      RESULT_SUCCESS : SUCCESS);
841	}
842
843	data->num_id_req = 0;
844	data->num_notification = 0;
845	/* RFC 4186 specifies that counter is initialized to one after
846	 * fullauth, but initializing it to zero makes it easier to implement
847	 * reauth verification. */
848	data->counter = 0;
849	return eap_sim_response_challenge(data, id);
850}
851
852
853static int eap_sim_process_notification_reauth(struct eap_sim_data *data,
854					       struct eap_sim_attrs *attr)
855{
856	struct eap_sim_attrs eattr;
857	u8 *decrypted;
858
859	if (attr->encr_data == NULL || attr->iv == NULL) {
860		wpa_printf(MSG_WARNING, "EAP-SIM: Notification message after "
861			   "reauth did not include encrypted data");
862		return -1;
863	}
864
865	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
866				       attr->encr_data_len, attr->iv, &eattr,
867				       0);
868	if (decrypted == NULL) {
869		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
870			   "data from notification message");
871		return -1;
872	}
873
874	if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
875		wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification "
876			   "message does not match with counter in reauth "
877			   "message");
878		os_free(decrypted);
879		return -1;
880	}
881
882	os_free(decrypted);
883	return 0;
884}
885
886
887static int eap_sim_process_notification_auth(struct eap_sim_data *data,
888					     const struct wpabuf *reqData,
889					     struct eap_sim_attrs *attr)
890{
891	if (attr->mac == NULL) {
892		wpa_printf(MSG_INFO, "EAP-SIM: no AT_MAC in after_auth "
893			   "Notification message");
894		return -1;
895	}
896
897	if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
898	{
899		wpa_printf(MSG_WARNING, "EAP-SIM: Notification message "
900			   "used invalid AT_MAC");
901		return -1;
902	}
903
904	if (data->reauth &&
905	    eap_sim_process_notification_reauth(data, attr)) {
906		wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification "
907			   "message after reauth");
908		return -1;
909	}
910
911	return 0;
912}
913
914
915static struct wpabuf * eap_sim_process_notification(
916	struct eap_sm *sm, struct eap_sim_data *data, u8 id,
917	const struct wpabuf *reqData, struct eap_sim_attrs *attr)
918{
919	wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Notification");
920	if (data->num_notification > 0) {
921		wpa_printf(MSG_INFO, "EAP-SIM: too many notification "
922			   "rounds (only one allowed)");
923		return eap_sim_client_error(data, id,
924					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
925	}
926	data->num_notification++;
927	if (attr->notification == -1) {
928		wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in "
929			   "Notification message");
930		return eap_sim_client_error(data, id,
931					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
932	}
933
934	if ((attr->notification & 0x4000) == 0 &&
935	    eap_sim_process_notification_auth(data, reqData, attr)) {
936		return eap_sim_client_error(data, id,
937					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
938	}
939
940	eap_sim_report_notification(sm->msg_ctx, attr->notification, 0);
941	if (attr->notification >= 0 && attr->notification < 32768) {
942		data->error_code = attr->notification;
943		eap_sim_state(data, FAILURE);
944	} else if (attr->notification == EAP_SIM_SUCCESS &&
945		   data->state == RESULT_SUCCESS)
946		eap_sim_state(data, SUCCESS);
947	return eap_sim_response_notification(data, id, attr->notification);
948}
949
950
951static struct wpabuf * eap_sim_process_reauthentication(
952	struct eap_sm *sm, struct eap_sim_data *data, u8 id,
953	const struct wpabuf *reqData, struct eap_sim_attrs *attr)
954{
955	struct eap_sim_attrs eattr;
956	u8 *decrypted;
957
958	wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication");
959
960	if (data->reauth_id == NULL) {
961		wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying "
962			   "reauthentication, but no reauth_id available");
963		return eap_sim_client_error(data, id,
964					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
965	}
966
967	data->reauth = 1;
968	if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
969	{
970		wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
971			   "did not have valid AT_MAC");
972#ifdef TEST_FUZZ
973		wpa_printf(MSG_INFO,
974			   "TEST: Ignore AT_MAC mismatch for fuzz testing");
975#else /* TEST_FUZZ */
976		return eap_sim_client_error(data, id,
977					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
978#endif /* TEST_FUZZ */
979	}
980
981	/* At this stage the received MAC has been verified. Use this MAC for
982	 * reauth Session-Id calculation if all other checks pass.
983	 * The peer does not use the local MAC but the received MAC in deriving
984	 * Session-Id. */
985#ifdef TEST_FUZZ
986	if (attr->mac)
987		os_memcpy(data->reauth_mac, attr->mac, EAP_SIM_MAC_LEN);
988	else
989		os_memset(data->reauth_mac, 0x12, EAP_SIM_MAC_LEN);
990#else /* TEST_FUZZ */
991	os_memcpy(data->reauth_mac, attr->mac, EAP_SIM_MAC_LEN);
992#endif /* TEST_FUZZ */
993	wpa_hexdump(MSG_DEBUG, "EAP-SIM: Server MAC",
994		    data->reauth_mac, EAP_SIM_MAC_LEN);
995
996	if (attr->encr_data == NULL || attr->iv == NULL) {
997		wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
998			   "message did not include encrypted data");
999		return eap_sim_client_error(data, id,
1000					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
1001	}
1002
1003	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1004				       attr->encr_data_len, attr->iv, &eattr,
1005				       0);
1006	if (decrypted == NULL) {
1007		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
1008			   "data from reauthentication message");
1009		return eap_sim_client_error(data, id,
1010					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
1011	}
1012
1013	if (eattr.nonce_s == NULL || eattr.counter < 0) {
1014		wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet",
1015			   !eattr.nonce_s ? " AT_NONCE_S" : "",
1016			   eattr.counter < 0 ? " AT_COUNTER" : "");
1017		os_free(decrypted);
1018		return eap_sim_client_error(data, id,
1019					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
1020	}
1021
1022	if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
1023		struct wpabuf *res;
1024		wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter "
1025			   "(%d <= %d)", eattr.counter, data->counter);
1026		data->counter_too_small = eattr.counter;
1027
1028		/* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
1029		 * reauth_id must not be used to start a new reauthentication.
1030		 * However, since it was used in the last EAP-Response-Identity
1031		 * packet, it has to saved for the following fullauth to be
1032		 * used in MK derivation. */
1033		os_free(data->last_eap_identity);
1034		data->last_eap_identity = data->reauth_id;
1035		data->last_eap_identity_len = data->reauth_id_len;
1036		data->reauth_id = NULL;
1037		data->reauth_id_len = 0;
1038
1039		res = eap_sim_response_reauth(data, id, 1, eattr.nonce_s);
1040		os_free(decrypted);
1041
1042		return res;
1043	}
1044	data->counter = eattr.counter;
1045
1046	os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
1047	wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S",
1048		    data->nonce_s, EAP_SIM_NONCE_S_LEN);
1049
1050	eap_sim_derive_keys_reauth(data->counter,
1051				   data->reauth_id, data->reauth_id_len,
1052				   data->nonce_s, data->mk, data->msk,
1053				   data->emsk);
1054	eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1055	eap_sim_learn_ids(sm, data, &eattr);
1056
1057	if (data->result_ind && attr->result_ind)
1058		data->use_result_ind = 1;
1059
1060	if (data->state != FAILURE) {
1061		eap_sim_state(data, data->use_result_ind ?
1062			      RESULT_SUCCESS : SUCCESS);
1063	}
1064
1065	data->num_id_req = 0;
1066	data->num_notification = 0;
1067	if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) {
1068		wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of "
1069			   "fast reauths performed - force fullauth");
1070		eap_sim_clear_identities(sm, data,
1071					 CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1072	}
1073	os_free(decrypted);
1074	return eap_sim_response_reauth(data, id, 0, data->nonce_s);
1075}
1076
1077
1078static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv,
1079				       struct eap_method_ret *ret,
1080				       const struct wpabuf *reqData)
1081{
1082	struct eap_sim_data *data = priv;
1083	const struct eap_hdr *req;
1084	u8 subtype, id;
1085	struct wpabuf *res;
1086	const u8 *pos;
1087	struct eap_sim_attrs attr;
1088	size_t len;
1089
1090	wpa_hexdump_buf(MSG_DEBUG, "EAP-SIM: EAP data", reqData);
1091	if (eap_get_config_identity(sm, &len) == NULL) {
1092		wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured");
1093		eap_sm_request_identity(sm);
1094		ret->ignore = TRUE;
1095		return NULL;
1096	}
1097
1098	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len);
1099	if (pos == NULL || len < 3) {
1100		ret->ignore = TRUE;
1101		return NULL;
1102	}
1103	req = wpabuf_head(reqData);
1104	id = req->identifier;
1105	len = be_to_host16(req->length);
1106
1107	ret->ignore = FALSE;
1108	ret->methodState = METHOD_MAY_CONT;
1109	ret->decision = DECISION_FAIL;
1110	ret->allowNotifications = TRUE;
1111
1112	subtype = *pos++;
1113	wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype);
1114	pos += 2; /* Reserved */
1115
1116	if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 0,
1117			       0)) {
1118		res = eap_sim_client_error(data, id,
1119					   EAP_SIM_UNABLE_TO_PROCESS_PACKET);
1120		goto done;
1121	}
1122
1123	switch (subtype) {
1124	case EAP_SIM_SUBTYPE_START:
1125		res = eap_sim_process_start(sm, data, id, &attr);
1126		break;
1127	case EAP_SIM_SUBTYPE_CHALLENGE:
1128		res = eap_sim_process_challenge(sm, data, id, reqData, &attr);
1129		break;
1130	case EAP_SIM_SUBTYPE_NOTIFICATION:
1131		res = eap_sim_process_notification(sm, data, id, reqData,
1132						   &attr);
1133		break;
1134	case EAP_SIM_SUBTYPE_REAUTHENTICATION:
1135		res = eap_sim_process_reauthentication(sm, data, id, reqData,
1136						       &attr);
1137		break;
1138	case EAP_SIM_SUBTYPE_CLIENT_ERROR:
1139		wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error");
1140		res = eap_sim_client_error(data, id,
1141					   EAP_SIM_UNABLE_TO_PROCESS_PACKET);
1142		break;
1143	default:
1144		wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype);
1145		res = eap_sim_client_error(data, id,
1146					   EAP_SIM_UNABLE_TO_PROCESS_PACKET);
1147		break;
1148	}
1149
1150done:
1151	if (data->state == FAILURE) {
1152		ret->decision = DECISION_FAIL;
1153		ret->methodState = METHOD_DONE;
1154	} else if (data->state == SUCCESS) {
1155		ret->decision = data->use_result_ind ?
1156			DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
1157		ret->methodState = data->use_result_ind ?
1158			METHOD_DONE : METHOD_MAY_CONT;
1159	} else if (data->state == RESULT_SUCCESS)
1160		ret->methodState = METHOD_CONT;
1161
1162	if (ret->methodState == METHOD_DONE) {
1163		ret->allowNotifications = FALSE;
1164	}
1165
1166	return res;
1167}
1168
1169
1170static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv)
1171{
1172	struct eap_sim_data *data = priv;
1173	return data->pseudonym || data->reauth_id;
1174}
1175
1176
1177static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv)
1178{
1179	struct eap_sim_data *data = priv;
1180	eap_sim_clear_identities(sm, data, CLEAR_EAP_ID);
1181	data->use_result_ind = 0;
1182	eap_sim_clear_keys(data, 1);
1183}
1184
1185
1186static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv)
1187{
1188	struct eap_sim_data *data = priv;
1189	if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
1190		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
1191			   "for NONCE_MT");
1192		eap_sim_deinit(sm, data);
1193		return NULL;
1194	}
1195	data->num_id_req = 0;
1196	data->num_notification = 0;
1197	eap_sim_state(data, CONTINUE);
1198	return priv;
1199}
1200
1201
1202static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv,
1203				       size_t *len)
1204{
1205	struct eap_sim_data *data = priv;
1206
1207	if (data->reauth_id) {
1208		*len = data->reauth_id_len;
1209		return data->reauth_id;
1210	}
1211
1212	if (data->pseudonym) {
1213		*len = data->pseudonym_len;
1214		return data->pseudonym;
1215	}
1216
1217	return NULL;
1218}
1219
1220
1221static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv)
1222{
1223	struct eap_sim_data *data = priv;
1224	return data->state == SUCCESS;
1225}
1226
1227
1228static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len)
1229{
1230	struct eap_sim_data *data = priv;
1231	u8 *key;
1232
1233	if (data->state != SUCCESS)
1234		return NULL;
1235
1236	key = os_memdup(data->msk, EAP_SIM_KEYING_DATA_LEN);
1237	if (key == NULL)
1238		return NULL;
1239
1240	*len = EAP_SIM_KEYING_DATA_LEN;
1241
1242	return key;
1243}
1244
1245
1246static u8 * eap_sim_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1247{
1248	struct eap_sim_data *data = priv;
1249	u8 *id;
1250
1251	if (data->state != SUCCESS)
1252		return NULL;
1253
1254	if (!data->reauth)
1255		*len = 1 + data->num_chal * GSM_RAND_LEN + EAP_SIM_NONCE_MT_LEN;
1256	else
1257		*len = 1 + EAP_SIM_NONCE_S_LEN + EAP_SIM_MAC_LEN;
1258	id = os_malloc(*len);
1259	if (id == NULL)
1260		return NULL;
1261
1262	id[0] = EAP_TYPE_SIM;
1263	if (!data->reauth) {
1264		os_memcpy(id + 1, data->rand, data->num_chal * GSM_RAND_LEN);
1265		os_memcpy(id + 1 + data->num_chal * GSM_RAND_LEN,
1266			  data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
1267	} else {
1268		os_memcpy(id + 1, data->nonce_s, EAP_SIM_NONCE_S_LEN);
1269		os_memcpy(id + 1 + EAP_SIM_NONCE_S_LEN, data->reauth_mac,
1270			  EAP_SIM_MAC_LEN);
1271	}
1272	wpa_hexdump(MSG_DEBUG, "EAP-SIM: Derived Session-Id", id, *len);
1273
1274	return id;
1275}
1276
1277
1278static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1279{
1280	struct eap_sim_data *data = priv;
1281	u8 *key;
1282
1283	if (data->state != SUCCESS)
1284		return NULL;
1285
1286	key = os_memdup(data->emsk, EAP_EMSK_LEN);
1287	if (key == NULL)
1288		return NULL;
1289
1290	*len = EAP_EMSK_LEN;
1291
1292	return key;
1293}
1294
1295
1296static int eap_sim_get_error_code(void *priv)
1297{
1298	struct eap_sim_data *data = priv;
1299	int current_data_error;
1300
1301	if (!data)
1302		return NO_EAP_METHOD_ERROR;
1303
1304	current_data_error = data->error_code;
1305
1306	/* Now reset for next transaction */
1307	data->error_code = NO_EAP_METHOD_ERROR;
1308
1309	return current_data_error;
1310}
1311
1312
1313int eap_peer_sim_register(void)
1314{
1315	struct eap_method *eap;
1316
1317	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1318				    EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
1319	if (eap == NULL)
1320		return -1;
1321
1322	eap->init = eap_sim_init;
1323	eap->deinit = eap_sim_deinit;
1324	eap->process = eap_sim_process;
1325	eap->isKeyAvailable = eap_sim_isKeyAvailable;
1326	eap->getKey = eap_sim_getKey;
1327	eap->getSessionId = eap_sim_get_session_id;
1328	eap->has_reauth_data = eap_sim_has_reauth_data;
1329	eap->deinit_for_reauth = eap_sim_deinit_for_reauth;
1330	eap->init_for_reauth = eap_sim_init_for_reauth;
1331	eap->get_identity = eap_sim_get_identity;
1332	eap->get_emsk = eap_sim_get_emsk;
1333	eap->get_error_code = eap_sim_get_error_code;
1334
1335	return eap_peer_method_register(eap);
1336}
1337