xref: /netbsd-src/external/bsd/wpa/dist/src/eap_peer/eap_sim.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
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 
26 struct 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
59 static 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 
79 static 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 
88 static 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 
132 static 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 
145 static 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 
257 static 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 
267 static void eap_sim_clear_identities(struct eap_sim_data *data, int id)
268 {
269 	if ((id & CLEAR_PSEUDONYM) && data->pseudonym) {
270 		wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old pseudonym");
271 		os_free(data->pseudonym);
272 		data->pseudonym = NULL;
273 		data->pseudonym_len = 0;
274 	}
275 	if ((id & CLEAR_REAUTH_ID) && data->reauth_id) {
276 		wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old reauth_id");
277 		os_free(data->reauth_id);
278 		data->reauth_id = NULL;
279 		data->reauth_id_len = 0;
280 	}
281 	if ((id & CLEAR_EAP_ID) && data->last_eap_identity) {
282 		wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old eap_id");
283 		os_free(data->last_eap_identity);
284 		data->last_eap_identity = NULL;
285 		data->last_eap_identity_len = 0;
286 	}
287 }
288 
289 
290 static int eap_sim_learn_ids(struct eap_sm *sm, struct eap_sim_data *data,
291 			     struct eap_sim_attrs *attr)
292 {
293 	if (attr->next_pseudonym) {
294 		const u8 *identity = NULL;
295 		size_t identity_len = 0;
296 		const u8 *realm = NULL;
297 		size_t realm_len = 0;
298 
299 		wpa_hexdump_ascii(MSG_DEBUG,
300 				  "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
301 				  attr->next_pseudonym,
302 				  attr->next_pseudonym_len);
303 		os_free(data->pseudonym);
304 		/* Look for the realm of the permanent identity */
305 		identity = eap_get_config_identity(sm, &identity_len);
306 		if (identity) {
307 			for (realm = identity, realm_len = identity_len;
308 			     realm_len > 0; realm_len--, realm++) {
309 				if (*realm == '@')
310 					break;
311 			}
312 		}
313 		data->pseudonym = os_malloc(attr->next_pseudonym_len +
314 					    realm_len);
315 		if (data->pseudonym == NULL) {
316 			wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
317 				   "next pseudonym");
318 			data->pseudonym_len = 0;
319 			return -1;
320 		}
321 		os_memcpy(data->pseudonym, attr->next_pseudonym,
322 			  attr->next_pseudonym_len);
323 		if (realm_len) {
324 			os_memcpy(data->pseudonym + attr->next_pseudonym_len,
325 				  realm, realm_len);
326 		}
327 		data->pseudonym_len = attr->next_pseudonym_len + realm_len;
328 	}
329 
330 	if (attr->next_reauth_id) {
331 		os_free(data->reauth_id);
332 		data->reauth_id = os_malloc(attr->next_reauth_id_len);
333 		if (data->reauth_id == NULL) {
334 			wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
335 				   "next reauth_id");
336 			data->reauth_id_len = 0;
337 			return -1;
338 		}
339 		os_memcpy(data->reauth_id, attr->next_reauth_id,
340 			  attr->next_reauth_id_len);
341 		data->reauth_id_len = attr->next_reauth_id_len;
342 		wpa_hexdump_ascii(MSG_DEBUG,
343 				  "EAP-SIM: (encr) AT_NEXT_REAUTH_ID",
344 				  data->reauth_id,
345 				  data->reauth_id_len);
346 	}
347 
348 	return 0;
349 }
350 
351 
352 static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id,
353 					    int err)
354 {
355 	struct eap_sim_msg *msg;
356 
357 	eap_sim_state(data, FAILURE);
358 	data->num_id_req = 0;
359 	data->num_notification = 0;
360 
361 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
362 			       EAP_SIM_SUBTYPE_CLIENT_ERROR);
363 	eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
364 	return eap_sim_msg_finish(msg, NULL, NULL, 0);
365 }
366 
367 
368 static struct wpabuf * eap_sim_response_start(struct eap_sm *sm,
369 					      struct eap_sim_data *data, u8 id,
370 					      enum eap_sim_id_req id_req)
371 {
372 	const u8 *identity = NULL;
373 	size_t identity_len = 0;
374 	struct eap_sim_msg *msg;
375 
376 	data->reauth = 0;
377 	if (id_req == ANY_ID && data->reauth_id) {
378 		identity = data->reauth_id;
379 		identity_len = data->reauth_id_len;
380 		data->reauth = 1;
381 	} else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
382 		   data->pseudonym) {
383 		identity = data->pseudonym;
384 		identity_len = data->pseudonym_len;
385 		eap_sim_clear_identities(data, CLEAR_REAUTH_ID);
386 	} else if (id_req != NO_ID_REQ) {
387 		identity = eap_get_config_identity(sm, &identity_len);
388 		if (identity) {
389 			eap_sim_clear_identities(data, CLEAR_PSEUDONYM |
390 						 CLEAR_REAUTH_ID);
391 		}
392 	}
393 	if (id_req != NO_ID_REQ)
394 		eap_sim_clear_identities(data, CLEAR_EAP_ID);
395 
396 	wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id);
397 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
398 			       EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START);
399 	if (!data->reauth) {
400 		wpa_hexdump(MSG_DEBUG, "   AT_NONCE_MT",
401 			    data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
402 		eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0,
403 				data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
404 		wpa_printf(MSG_DEBUG, "   AT_SELECTED_VERSION %d",
405 			   data->selected_version);
406 		eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION,
407 				data->selected_version, NULL, 0);
408 	}
409 
410 	if (identity) {
411 		wpa_hexdump_ascii(MSG_DEBUG, "   AT_IDENTITY",
412 				  identity, identity_len);
413 		eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
414 				identity, identity_len);
415 	}
416 
417 	return eap_sim_msg_finish(msg, NULL, NULL, 0);
418 }
419 
420 
421 static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data,
422 						  u8 id)
423 {
424 	struct eap_sim_msg *msg;
425 
426 	wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", id);
427 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
428 			       EAP_SIM_SUBTYPE_CHALLENGE);
429 	if (data->use_result_ind) {
430 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
431 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
432 	}
433 	wpa_printf(MSG_DEBUG, "   AT_MAC");
434 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
435 	return eap_sim_msg_finish(msg, data->k_aut, (u8 *) data->sres,
436 				  data->num_chal * EAP_SIM_SRES_LEN);
437 }
438 
439 
440 static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data,
441 					       u8 id, int counter_too_small,
442 					       const u8 *nonce_s)
443 {
444 	struct eap_sim_msg *msg;
445 	unsigned int counter;
446 
447 	wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)",
448 		   id);
449 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
450 			       EAP_SIM_SUBTYPE_REAUTHENTICATION);
451 	wpa_printf(MSG_DEBUG, "   AT_IV");
452 	wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
453 	eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
454 
455 	if (counter_too_small) {
456 		wpa_printf(MSG_DEBUG, "   *AT_COUNTER_TOO_SMALL");
457 		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
458 		counter = data->counter_too_small;
459 	} else
460 		counter = data->counter;
461 
462 	wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", counter);
463 	eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
464 
465 	if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
466 		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
467 			   "AT_ENCR_DATA");
468 		eap_sim_msg_free(msg);
469 		return NULL;
470 	}
471 	if (data->use_result_ind) {
472 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
473 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
474 	}
475 	wpa_printf(MSG_DEBUG, "   AT_MAC");
476 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
477 	return eap_sim_msg_finish(msg, data->k_aut, nonce_s,
478 				  EAP_SIM_NONCE_S_LEN);
479 }
480 
481 
482 static struct wpabuf * eap_sim_response_notification(struct eap_sim_data *data,
483 						     u8 id, u16 notification)
484 {
485 	struct eap_sim_msg *msg;
486 	u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
487 
488 	wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", id);
489 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
490 			       EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION);
491 	if (k_aut && data->reauth) {
492 		wpa_printf(MSG_DEBUG, "   AT_IV");
493 		wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
494 		eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
495 					   EAP_SIM_AT_ENCR_DATA);
496 		wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", data->counter);
497 		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
498 				NULL, 0);
499 		if (eap_sim_msg_add_encr_end(msg, data->k_encr,
500 					     EAP_SIM_AT_PADDING)) {
501 			wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
502 				   "AT_ENCR_DATA");
503 			eap_sim_msg_free(msg);
504 			return NULL;
505 		}
506 	}
507 	if (k_aut) {
508 		wpa_printf(MSG_DEBUG, "   AT_MAC");
509 		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
510 	}
511 	return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0);
512 }
513 
514 
515 static struct wpabuf * eap_sim_process_start(struct eap_sm *sm,
516 					     struct eap_sim_data *data, u8 id,
517 					     struct eap_sim_attrs *attr)
518 {
519 	int selected_version = -1, id_error;
520 	size_t i;
521 	u8 *pos;
522 
523 	wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start");
524 	if (attr->version_list == NULL) {
525 		wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in "
526 			   "SIM/Start");
527 		return eap_sim_client_error(data, id,
528 					    EAP_SIM_UNSUPPORTED_VERSION);
529 	}
530 
531 	os_free(data->ver_list);
532 	data->ver_list = os_malloc(attr->version_list_len);
533 	if (data->ver_list == NULL) {
534 		wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate "
535 			   "memory for version list");
536 		return eap_sim_client_error(data, id,
537 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
538 	}
539 	os_memcpy(data->ver_list, attr->version_list, attr->version_list_len);
540 	data->ver_list_len = attr->version_list_len;
541 	pos = data->ver_list;
542 	for (i = 0; i < data->ver_list_len / 2; i++) {
543 		int ver = pos[0] * 256 + pos[1];
544 		pos += 2;
545 		if (eap_sim_supported_ver(ver)) {
546 			selected_version = ver;
547 			break;
548 		}
549 	}
550 	if (selected_version < 0) {
551 		wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported "
552 			   "version");
553 		return eap_sim_client_error(data, id,
554 					    EAP_SIM_UNSUPPORTED_VERSION);
555 	}
556 	wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d",
557 		   selected_version);
558 	data->selected_version = selected_version;
559 
560 	id_error = 0;
561 	switch (attr->id_req) {
562 	case NO_ID_REQ:
563 		break;
564 	case ANY_ID:
565 		if (data->num_id_req > 0)
566 			id_error++;
567 		data->num_id_req++;
568 		break;
569 	case FULLAUTH_ID:
570 		if (data->num_id_req > 1)
571 			id_error++;
572 		data->num_id_req++;
573 		break;
574 	case PERMANENT_ID:
575 		if (data->num_id_req > 2)
576 			id_error++;
577 		data->num_id_req++;
578 		break;
579 	}
580 	if (id_error) {
581 		wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests "
582 			   "used within one authentication");
583 		return eap_sim_client_error(data, id,
584 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
585 	}
586 
587 	return eap_sim_response_start(sm, data, id, attr->id_req);
588 }
589 
590 
591 static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm,
592 						 struct eap_sim_data *data,
593 						 u8 id,
594 						 const struct wpabuf *reqData,
595 						 struct eap_sim_attrs *attr)
596 {
597 	const u8 *identity;
598 	size_t identity_len;
599 	struct eap_sim_attrs eattr;
600 
601 	wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge");
602 	data->reauth = 0;
603 	if (!attr->mac || !attr->rand) {
604 		wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
605 			   "did not include%s%s",
606 			   !attr->mac ? " AT_MAC" : "",
607 			   !attr->rand ? " AT_RAND" : "");
608 		return eap_sim_client_error(data, id,
609 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
610 	}
611 
612 	wpa_printf(MSG_DEBUG, "EAP-SIM: %lu challenges",
613 		   (unsigned long) attr->num_chal);
614 	if (attr->num_chal < data->min_num_chal) {
615 		wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of "
616 			   "challenges (%lu)", (unsigned long) attr->num_chal);
617 		return eap_sim_client_error(data, id,
618 					    EAP_SIM_INSUFFICIENT_NUM_OF_CHAL);
619 	}
620 	if (attr->num_chal > 3) {
621 		wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges "
622 			   "(%lu)", (unsigned long) attr->num_chal);
623 		return eap_sim_client_error(data, id,
624 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
625 	}
626 
627 	/* Verify that RANDs are different */
628 	if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN,
629 		   GSM_RAND_LEN) == 0 ||
630 	    (attr->num_chal > 2 &&
631 	     (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN,
632 			GSM_RAND_LEN) == 0 ||
633 	      os_memcmp(attr->rand + GSM_RAND_LEN,
634 			attr->rand + 2 * GSM_RAND_LEN,
635 			GSM_RAND_LEN) == 0))) {
636 		wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times");
637 		return eap_sim_client_error(data, id,
638 					    EAP_SIM_RAND_NOT_FRESH);
639 	}
640 
641 	os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN);
642 	data->num_chal = attr->num_chal;
643 
644 	if (eap_sim_gsm_auth(sm, data)) {
645 		wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed");
646 		return eap_sim_client_error(data, id,
647 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
648 	}
649 	if (data->last_eap_identity) {
650 		identity = data->last_eap_identity;
651 		identity_len = data->last_eap_identity_len;
652 	} else if (data->pseudonym) {
653 		identity = data->pseudonym;
654 		identity_len = data->pseudonym_len;
655 	} else
656 		identity = eap_get_config_identity(sm, &identity_len);
657 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK "
658 			  "derivation", identity, identity_len);
659 	eap_sim_derive_mk(identity, identity_len, data->nonce_mt,
660 			  data->selected_version, data->ver_list,
661 			  data->ver_list_len, data->num_chal,
662 			  (const u8 *) data->kc, data->mk);
663 	eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
664 			    data->emsk);
665 	if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, data->nonce_mt,
666 			       EAP_SIM_NONCE_MT_LEN)) {
667 		wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
668 			   "used invalid AT_MAC");
669 		return eap_sim_client_error(data, id,
670 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
671 	}
672 
673 	/* Old reauthentication identity must not be used anymore. In
674 	 * other words, if no new reauth identity is received, full
675 	 * authentication will be used on next reauthentication (using
676 	 * pseudonym identity or permanent identity). */
677 	eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
678 
679 	if (attr->encr_data) {
680 		u8 *decrypted;
681 		decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
682 					       attr->encr_data_len, attr->iv,
683 					       &eattr, 0);
684 		if (decrypted == NULL) {
685 			return eap_sim_client_error(
686 				data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET);
687 		}
688 		eap_sim_learn_ids(sm, data, &eattr);
689 		os_free(decrypted);
690 	}
691 
692 	if (data->result_ind && attr->result_ind)
693 		data->use_result_ind = 1;
694 
695 	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
696 		eap_sim_state(data, data->use_result_ind ?
697 			      RESULT_SUCCESS : SUCCESS);
698 	}
699 
700 	data->num_id_req = 0;
701 	data->num_notification = 0;
702 	/* RFC 4186 specifies that counter is initialized to one after
703 	 * fullauth, but initializing it to zero makes it easier to implement
704 	 * reauth verification. */
705 	data->counter = 0;
706 	return eap_sim_response_challenge(data, id);
707 }
708 
709 
710 static int eap_sim_process_notification_reauth(struct eap_sim_data *data,
711 					       struct eap_sim_attrs *attr)
712 {
713 	struct eap_sim_attrs eattr;
714 	u8 *decrypted;
715 
716 	if (attr->encr_data == NULL || attr->iv == NULL) {
717 		wpa_printf(MSG_WARNING, "EAP-SIM: Notification message after "
718 			   "reauth did not include encrypted data");
719 		return -1;
720 	}
721 
722 	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
723 				       attr->encr_data_len, attr->iv, &eattr,
724 				       0);
725 	if (decrypted == NULL) {
726 		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
727 			   "data from notification message");
728 		return -1;
729 	}
730 
731 	if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
732 		wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification "
733 			   "message does not match with counter in reauth "
734 			   "message");
735 		os_free(decrypted);
736 		return -1;
737 	}
738 
739 	os_free(decrypted);
740 	return 0;
741 }
742 
743 
744 static int eap_sim_process_notification_auth(struct eap_sim_data *data,
745 					     const struct wpabuf *reqData,
746 					     struct eap_sim_attrs *attr)
747 {
748 	if (attr->mac == NULL) {
749 		wpa_printf(MSG_INFO, "EAP-SIM: no AT_MAC in after_auth "
750 			   "Notification message");
751 		return -1;
752 	}
753 
754 	if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
755 	{
756 		wpa_printf(MSG_WARNING, "EAP-SIM: Notification message "
757 			   "used invalid AT_MAC");
758 		return -1;
759 	}
760 
761 	if (data->reauth &&
762 	    eap_sim_process_notification_reauth(data, attr)) {
763 		wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification "
764 			   "message after reauth");
765 		return -1;
766 	}
767 
768 	return 0;
769 }
770 
771 
772 static struct wpabuf * eap_sim_process_notification(
773 	struct eap_sm *sm, struct eap_sim_data *data, u8 id,
774 	const struct wpabuf *reqData, struct eap_sim_attrs *attr)
775 {
776 	wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Notification");
777 	if (data->num_notification > 0) {
778 		wpa_printf(MSG_INFO, "EAP-SIM: too many notification "
779 			   "rounds (only one allowed)");
780 		return eap_sim_client_error(data, id,
781 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
782 	}
783 	data->num_notification++;
784 	if (attr->notification == -1) {
785 		wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in "
786 			   "Notification message");
787 		return eap_sim_client_error(data, id,
788 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
789 	}
790 
791 	if ((attr->notification & 0x4000) == 0 &&
792 	    eap_sim_process_notification_auth(data, reqData, attr)) {
793 		return eap_sim_client_error(data, id,
794 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
795 	}
796 
797 	eap_sim_report_notification(sm->msg_ctx, attr->notification, 0);
798 	if (attr->notification >= 0 && attr->notification < 32768) {
799 		eap_sim_state(data, FAILURE);
800 	} else if (attr->notification == EAP_SIM_SUCCESS &&
801 		   data->state == RESULT_SUCCESS)
802 		eap_sim_state(data, SUCCESS);
803 	return eap_sim_response_notification(data, id, attr->notification);
804 }
805 
806 
807 static struct wpabuf * eap_sim_process_reauthentication(
808 	struct eap_sm *sm, struct eap_sim_data *data, u8 id,
809 	const struct wpabuf *reqData, struct eap_sim_attrs *attr)
810 {
811 	struct eap_sim_attrs eattr;
812 	u8 *decrypted;
813 
814 	wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication");
815 
816 	if (data->reauth_id == NULL) {
817 		wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying "
818 			   "reauthentication, but no reauth_id available");
819 		return eap_sim_client_error(data, id,
820 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
821 	}
822 
823 	data->reauth = 1;
824 	if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
825 	{
826 		wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
827 			   "did not have valid AT_MAC");
828 		return eap_sim_client_error(data, id,
829 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
830 	}
831 
832 	if (attr->encr_data == NULL || attr->iv == NULL) {
833 		wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
834 			   "message did not include encrypted data");
835 		return eap_sim_client_error(data, id,
836 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
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 reauthentication message");
845 		return eap_sim_client_error(data, id,
846 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
847 	}
848 
849 	if (eattr.nonce_s == NULL || eattr.counter < 0) {
850 		wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet",
851 			   !eattr.nonce_s ? " AT_NONCE_S" : "",
852 			   eattr.counter < 0 ? " AT_COUNTER" : "");
853 		os_free(decrypted);
854 		return eap_sim_client_error(data, id,
855 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
856 	}
857 
858 	if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
859 		wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter "
860 			   "(%d <= %d)", eattr.counter, data->counter);
861 		data->counter_too_small = eattr.counter;
862 		/* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
863 		 * reauth_id must not be used to start a new reauthentication.
864 		 * However, since it was used in the last EAP-Response-Identity
865 		 * packet, it has to saved for the following fullauth to be
866 		 * used in MK derivation. */
867 		os_free(data->last_eap_identity);
868 		data->last_eap_identity = data->reauth_id;
869 		data->last_eap_identity_len = data->reauth_id_len;
870 		data->reauth_id = NULL;
871 		data->reauth_id_len = 0;
872 		os_free(decrypted);
873 		return eap_sim_response_reauth(data, id, 1, eattr.nonce_s);
874 	}
875 	data->counter = eattr.counter;
876 
877 	os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
878 	wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S",
879 		    data->nonce_s, EAP_SIM_NONCE_S_LEN);
880 
881 	eap_sim_derive_keys_reauth(data->counter,
882 				   data->reauth_id, data->reauth_id_len,
883 				   data->nonce_s, data->mk, data->msk,
884 				   data->emsk);
885 	eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
886 	eap_sim_learn_ids(sm, data, &eattr);
887 
888 	if (data->result_ind && attr->result_ind)
889 		data->use_result_ind = 1;
890 
891 	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
892 		eap_sim_state(data, data->use_result_ind ?
893 			      RESULT_SUCCESS : SUCCESS);
894 	}
895 
896 	data->num_id_req = 0;
897 	data->num_notification = 0;
898 	if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) {
899 		wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of "
900 			   "fast reauths performed - force fullauth");
901 		eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
902 	}
903 	os_free(decrypted);
904 	return eap_sim_response_reauth(data, id, 0, data->nonce_s);
905 }
906 
907 
908 static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv,
909 				       struct eap_method_ret *ret,
910 				       const struct wpabuf *reqData)
911 {
912 	struct eap_sim_data *data = priv;
913 	const struct eap_hdr *req;
914 	u8 subtype, id;
915 	struct wpabuf *res;
916 	const u8 *pos;
917 	struct eap_sim_attrs attr;
918 	size_t len;
919 
920 	wpa_hexdump_buf(MSG_DEBUG, "EAP-SIM: EAP data", reqData);
921 	if (eap_get_config_identity(sm, &len) == NULL) {
922 		wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured");
923 		eap_sm_request_identity(sm);
924 		ret->ignore = TRUE;
925 		return NULL;
926 	}
927 
928 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len);
929 	if (pos == NULL || len < 1) {
930 		ret->ignore = TRUE;
931 		return NULL;
932 	}
933 	req = wpabuf_head(reqData);
934 	id = req->identifier;
935 	len = be_to_host16(req->length);
936 
937 	ret->ignore = FALSE;
938 	ret->methodState = METHOD_MAY_CONT;
939 	ret->decision = DECISION_FAIL;
940 	ret->allowNotifications = TRUE;
941 
942 	subtype = *pos++;
943 	wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype);
944 	pos += 2; /* Reserved */
945 
946 	if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 0,
947 			       0)) {
948 		res = eap_sim_client_error(data, id,
949 					   EAP_SIM_UNABLE_TO_PROCESS_PACKET);
950 		goto done;
951 	}
952 
953 	switch (subtype) {
954 	case EAP_SIM_SUBTYPE_START:
955 		res = eap_sim_process_start(sm, data, id, &attr);
956 		break;
957 	case EAP_SIM_SUBTYPE_CHALLENGE:
958 		res = eap_sim_process_challenge(sm, data, id, reqData, &attr);
959 		break;
960 	case EAP_SIM_SUBTYPE_NOTIFICATION:
961 		res = eap_sim_process_notification(sm, data, id, reqData,
962 						   &attr);
963 		break;
964 	case EAP_SIM_SUBTYPE_REAUTHENTICATION:
965 		res = eap_sim_process_reauthentication(sm, data, id, reqData,
966 						       &attr);
967 		break;
968 	case EAP_SIM_SUBTYPE_CLIENT_ERROR:
969 		wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error");
970 		res = eap_sim_client_error(data, id,
971 					   EAP_SIM_UNABLE_TO_PROCESS_PACKET);
972 		break;
973 	default:
974 		wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype);
975 		res = eap_sim_client_error(data, id,
976 					   EAP_SIM_UNABLE_TO_PROCESS_PACKET);
977 		break;
978 	}
979 
980 done:
981 	if (data->state == FAILURE) {
982 		ret->decision = DECISION_FAIL;
983 		ret->methodState = METHOD_DONE;
984 	} else if (data->state == SUCCESS) {
985 		ret->decision = data->use_result_ind ?
986 			DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
987 		ret->methodState = data->use_result_ind ?
988 			METHOD_DONE : METHOD_MAY_CONT;
989 	} else if (data->state == RESULT_FAILURE)
990 		ret->methodState = METHOD_CONT;
991 	else if (data->state == RESULT_SUCCESS)
992 		ret->methodState = METHOD_CONT;
993 
994 	if (ret->methodState == METHOD_DONE) {
995 		ret->allowNotifications = FALSE;
996 	}
997 
998 	return res;
999 }
1000 
1001 
1002 static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv)
1003 {
1004 	struct eap_sim_data *data = priv;
1005 	return data->pseudonym || data->reauth_id;
1006 }
1007 
1008 
1009 static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv)
1010 {
1011 	struct eap_sim_data *data = priv;
1012 	eap_sim_clear_identities(data, CLEAR_EAP_ID);
1013 	data->use_result_ind = 0;
1014 }
1015 
1016 
1017 static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv)
1018 {
1019 	struct eap_sim_data *data = priv;
1020 	if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
1021 		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
1022 			   "for NONCE_MT");
1023 		os_free(data);
1024 		return NULL;
1025 	}
1026 	data->num_id_req = 0;
1027 	data->num_notification = 0;
1028 	eap_sim_state(data, CONTINUE);
1029 	return priv;
1030 }
1031 
1032 
1033 static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv,
1034 				       size_t *len)
1035 {
1036 	struct eap_sim_data *data = priv;
1037 
1038 	if (data->reauth_id) {
1039 		*len = data->reauth_id_len;
1040 		return data->reauth_id;
1041 	}
1042 
1043 	if (data->pseudonym) {
1044 		*len = data->pseudonym_len;
1045 		return data->pseudonym;
1046 	}
1047 
1048 	return NULL;
1049 }
1050 
1051 
1052 static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv)
1053 {
1054 	struct eap_sim_data *data = priv;
1055 	return data->state == SUCCESS;
1056 }
1057 
1058 
1059 static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len)
1060 {
1061 	struct eap_sim_data *data = priv;
1062 	u8 *key;
1063 
1064 	if (data->state != SUCCESS)
1065 		return NULL;
1066 
1067 	key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
1068 	if (key == NULL)
1069 		return NULL;
1070 
1071 	*len = EAP_SIM_KEYING_DATA_LEN;
1072 	os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
1073 
1074 	return key;
1075 }
1076 
1077 
1078 static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1079 {
1080 	struct eap_sim_data *data = priv;
1081 	u8 *key;
1082 
1083 	if (data->state != SUCCESS)
1084 		return NULL;
1085 
1086 	key = os_malloc(EAP_EMSK_LEN);
1087 	if (key == NULL)
1088 		return NULL;
1089 
1090 	*len = EAP_EMSK_LEN;
1091 	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
1092 
1093 	return key;
1094 }
1095 
1096 
1097 int eap_peer_sim_register(void)
1098 {
1099 	struct eap_method *eap;
1100 	int ret;
1101 
1102 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1103 				    EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
1104 	if (eap == NULL)
1105 		return -1;
1106 
1107 	eap->init = eap_sim_init;
1108 	eap->deinit = eap_sim_deinit;
1109 	eap->process = eap_sim_process;
1110 	eap->isKeyAvailable = eap_sim_isKeyAvailable;
1111 	eap->getKey = eap_sim_getKey;
1112 	eap->has_reauth_data = eap_sim_has_reauth_data;
1113 	eap->deinit_for_reauth = eap_sim_deinit_for_reauth;
1114 	eap->init_for_reauth = eap_sim_init_for_reauth;
1115 	eap->get_identity = eap_sim_get_identity;
1116 	eap->get_emsk = eap_sim_get_emsk;
1117 
1118 	ret = eap_peer_method_register(eap);
1119 	if (ret)
1120 		eap_peer_method_free(eap);
1121 	return ret;
1122 }
1123