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