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