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