xref: /freebsd/contrib/wpa/src/eap_server/eap_server_sim.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
1 /*
2  * hostapd / EAP-SIM (RFC 4186)
3  * Copyright (c) 2005-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 "utils/base64.h"
13 #include "crypto/crypto.h"
14 #include "crypto/random.h"
15 #include "eap_server/eap_i.h"
16 #include "eap_common/eap_sim_common.h"
17 #include "eap_server/eap_sim_db.h"
18 
19 
20 struct eap_sim_data {
21 	u8 mk[EAP_SIM_MK_LEN];
22 	u8 nonce_mt[EAP_SIM_NONCE_MT_LEN];
23 	u8 nonce_s[EAP_SIM_NONCE_S_LEN];
24 	u8 k_aut[EAP_SIM_K_AUT_LEN];
25 	u8 k_encr[EAP_SIM_K_ENCR_LEN];
26 	u8 msk[EAP_SIM_KEYING_DATA_LEN];
27 	u8 emsk[EAP_EMSK_LEN];
28 	u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN];
29 	u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN];
30 	u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN];
31 	u8 reauth_mac[EAP_SIM_MAC_LEN];
32 	int num_chal;
33 	enum {
34 		START, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
35 	} state;
36 	char *next_pseudonym;
37 	char *next_reauth_id;
38 	u16 counter;
39 	struct eap_sim_reauth *reauth;
40 	u16 notification;
41 	int use_result_ind;
42 	int start_round;
43 	char permanent[20]; /* Permanent username */
44 };
45 
46 
eap_sim_state_txt(int state)47 static const char * eap_sim_state_txt(int state)
48 {
49 	switch (state) {
50 	case START:
51 		return "START";
52 	case CHALLENGE:
53 		return "CHALLENGE";
54 	case REAUTH:
55 		return "REAUTH";
56 	case SUCCESS:
57 		return "SUCCESS";
58 	case FAILURE:
59 		return "FAILURE";
60 	case NOTIFICATION:
61 		return "NOTIFICATION";
62 	default:
63 		return "Unknown?!";
64 	}
65 }
66 
67 
eap_sim_state(struct eap_sim_data * data,int state)68 static void eap_sim_state(struct eap_sim_data *data, int state)
69 {
70 	wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s",
71 		   eap_sim_state_txt(data->state),
72 		   eap_sim_state_txt(state));
73 	data->state = state;
74 }
75 
76 
eap_sim_init(struct eap_sm * sm)77 static void * eap_sim_init(struct eap_sm *sm)
78 {
79 	struct eap_sim_data *data;
80 
81 	if (!sm->cfg->eap_sim_db_priv) {
82 		wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured");
83 		return NULL;
84 	}
85 
86 	data = os_zalloc(sizeof(*data));
87 	if (data == NULL)
88 		return NULL;
89 	data->state = START;
90 
91 	return data;
92 }
93 
94 
eap_sim_reset(struct eap_sm * sm,void * priv)95 static void eap_sim_reset(struct eap_sm *sm, void *priv)
96 {
97 	struct eap_sim_data *data = priv;
98 	os_free(data->next_pseudonym);
99 	os_free(data->next_reauth_id);
100 	bin_clear_free(data, sizeof(*data));
101 }
102 
103 
eap_sim_build_start(struct eap_sm * sm,struct eap_sim_data * data,u8 id)104 static struct wpabuf * eap_sim_build_start(struct eap_sm *sm,
105 					   struct eap_sim_data *data, u8 id)
106 {
107 	struct eap_sim_msg *msg;
108 	u8 ver[2];
109 	bool id_req = true;
110 
111 	wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start");
112 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
113 			       EAP_SIM_SUBTYPE_START);
114 	data->start_round++;
115 
116 	if (data->start_round == 1 && (sm->cfg->eap_sim_id & 0x04)) {
117 		char *username;
118 
119 		username = sim_get_username(sm->identity, sm->identity_len);
120 		if (username && username[0] == EAP_SIM_REAUTH_ID_PREFIX &&
121 		    eap_sim_db_get_reauth_entry(sm->cfg->eap_sim_db_priv,
122 						username))
123 			id_req = false;
124 
125 		os_free(username);
126 	}
127 
128 	if (!id_req) {
129 		wpa_printf(MSG_DEBUG, "   No identity request");
130 	} else if (data->start_round == 1) {
131 		/*
132 		 * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is
133 		 * ignored and the SIM/Start is used to request the identity.
134 		 */
135 		wpa_printf(MSG_DEBUG, "   AT_ANY_ID_REQ");
136 		eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
137 	} else if (data->start_round > 3) {
138 		/* Cannot use more than three rounds of Start messages */
139 		eap_sim_msg_free(msg);
140 		return NULL;
141 	} else if (data->start_round == 0) {
142 		/*
143 		 * This is a special case that is used to recover from
144 		 * AT_COUNTER_TOO_SMALL during re-authentication. Since we
145 		 * already know the identity of the peer, there is no need to
146 		 * request any identity in this case.
147 		 */
148 	} else if (sm->identity && sm->identity_len > 0 &&
149 		   sm->identity[0] == EAP_SIM_REAUTH_ID_PREFIX) {
150 		/* Reauth id may have expired - try fullauth */
151 		wpa_printf(MSG_DEBUG, "   AT_FULLAUTH_ID_REQ");
152 		eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0);
153 	} else {
154 		wpa_printf(MSG_DEBUG, "   AT_PERMANENT_ID_REQ");
155 		eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
156 	}
157 	wpa_printf(MSG_DEBUG, "   AT_VERSION_LIST");
158 	ver[0] = 0;
159 	ver[1] = EAP_SIM_VERSION;
160 	eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver),
161 			ver, sizeof(ver));
162 	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0);
163 }
164 
165 
eap_sim_build_encr(struct eap_sm * sm,struct eap_sim_data * data,struct eap_sim_msg * msg,u16 counter,const u8 * nonce_s)166 static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data,
167 			      struct eap_sim_msg *msg, u16 counter,
168 			      const u8 *nonce_s)
169 {
170 	os_free(data->next_pseudonym);
171 	if (!(sm->cfg->eap_sim_id & 0x01)) {
172 		/* Use of pseudonyms disabled in configuration */
173 		data->next_pseudonym = NULL;
174 	} else if (!nonce_s) {
175 		data->next_pseudonym =
176 			eap_sim_db_get_next_pseudonym(sm->cfg->eap_sim_db_priv,
177 						      EAP_SIM_DB_SIM);
178 	} else {
179 		/* Do not update pseudonym during re-authentication */
180 		data->next_pseudonym = NULL;
181 	}
182 	os_free(data->next_reauth_id);
183 	if (!(sm->cfg->eap_sim_id & 0x02)) {
184 		/* Use of fast reauth disabled in configuration */
185 		data->next_reauth_id = NULL;
186 	} else if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) {
187 		data->next_reauth_id =
188 			eap_sim_db_get_next_reauth_id(sm->cfg->eap_sim_db_priv,
189 						      EAP_SIM_DB_SIM);
190 	} else {
191 		wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication "
192 			   "count exceeded - force full authentication");
193 		data->next_reauth_id = NULL;
194 	}
195 
196 	if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
197 	    counter == 0 && nonce_s == NULL)
198 		return 0;
199 
200 	wpa_printf(MSG_DEBUG, "   AT_IV");
201 	wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
202 	eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
203 
204 	if (counter > 0) {
205 		wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)", counter);
206 		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
207 	}
208 
209 	if (nonce_s) {
210 		wpa_printf(MSG_DEBUG, "   *AT_NONCE_S");
211 		eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
212 				EAP_SIM_NONCE_S_LEN);
213 	}
214 
215 	if (data->next_pseudonym) {
216 		wpa_printf(MSG_DEBUG, "   *AT_NEXT_PSEUDONYM (%s)",
217 			   data->next_pseudonym);
218 		eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
219 				os_strlen(data->next_pseudonym),
220 				(u8 *) data->next_pseudonym,
221 				os_strlen(data->next_pseudonym));
222 	}
223 
224 	if (data->next_reauth_id) {
225 		wpa_printf(MSG_DEBUG, "   *AT_NEXT_REAUTH_ID (%s)",
226 			   data->next_reauth_id);
227 		eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
228 				os_strlen(data->next_reauth_id),
229 				(u8 *) data->next_reauth_id,
230 				os_strlen(data->next_reauth_id));
231 	}
232 
233 	if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
234 		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
235 			   "AT_ENCR_DATA");
236 		return -1;
237 	}
238 
239 	return 0;
240 }
241 
242 
eap_sim_build_challenge(struct eap_sm * sm,struct eap_sim_data * data,u8 id)243 static struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm,
244 					       struct eap_sim_data *data,
245 					       u8 id)
246 {
247 	struct eap_sim_msg *msg;
248 
249 	wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge");
250 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
251 			       EAP_SIM_SUBTYPE_CHALLENGE);
252 	wpa_printf(MSG_DEBUG, "   AT_RAND");
253 	eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand,
254 			data->num_chal * GSM_RAND_LEN);
255 
256 	if (eap_sim_build_encr(sm, data, msg, 0, NULL)) {
257 		eap_sim_msg_free(msg);
258 		return NULL;
259 	}
260 
261 	if (sm->cfg->eap_sim_aka_result_ind) {
262 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
263 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
264 	}
265 
266 	wpa_printf(MSG_DEBUG, "   AT_MAC");
267 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
268 	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut,
269 				  data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
270 }
271 
272 
eap_sim_build_reauth(struct eap_sm * sm,struct eap_sim_data * data,u8 id)273 static struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm,
274 					    struct eap_sim_data *data, u8 id)
275 {
276 	struct eap_sim_msg *msg;
277 	struct wpabuf *buf;
278 
279 	wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication");
280 
281 	if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN))
282 		return NULL;
283 	wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S",
284 			data->nonce_s, EAP_SIM_NONCE_S_LEN);
285 
286 	eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
287 			    data->emsk);
288 	eap_sim_derive_keys_reauth(data->counter, sm->identity,
289 				   sm->identity_len, data->nonce_s, data->mk,
290 				   data->msk, data->emsk);
291 
292 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
293 			       EAP_SIM_SUBTYPE_REAUTHENTICATION);
294 
295 	if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
296 		eap_sim_msg_free(msg);
297 		return NULL;
298 	}
299 
300 	if (sm->cfg->eap_sim_aka_result_ind) {
301 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
302 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
303 	}
304 
305 	wpa_printf(MSG_DEBUG, "   AT_MAC");
306 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
307 	buf = eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, NULL, 0);
308 
309 	/* Remember this MAC before sending it to the peer. This MAC is used for
310 	 * Session-Id calculation after receiving response from the peer and
311 	 * after all other checks pass. */
312 	os_memcpy(data->reauth_mac,
313 		  wpabuf_head_u8(buf) + wpabuf_len(buf) - EAP_SIM_MAC_LEN,
314 		  EAP_SIM_MAC_LEN);
315 
316 	return buf;
317 }
318 
319 
eap_sim_build_notification(struct eap_sm * sm,struct eap_sim_data * data,u8 id)320 static struct wpabuf * eap_sim_build_notification(struct eap_sm *sm,
321 						  struct eap_sim_data *data,
322 						  u8 id)
323 {
324 	struct eap_sim_msg *msg;
325 
326 	wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification");
327 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
328 			       EAP_SIM_SUBTYPE_NOTIFICATION);
329 	wpa_printf(MSG_DEBUG, "   AT_NOTIFICATION (%d)", data->notification);
330 	eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
331 			NULL, 0);
332 	if (data->use_result_ind) {
333 		if (data->reauth) {
334 			wpa_printf(MSG_DEBUG, "   AT_IV");
335 			wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
336 			eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
337 						   EAP_SIM_AT_ENCR_DATA);
338 			wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)",
339 				   data->counter);
340 			eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
341 					NULL, 0);
342 
343 			if (eap_sim_msg_add_encr_end(msg, data->k_encr,
344 						     EAP_SIM_AT_PADDING)) {
345 				wpa_printf(MSG_WARNING, "EAP-SIM: Failed to "
346 					   "encrypt AT_ENCR_DATA");
347 				eap_sim_msg_free(msg);
348 				return NULL;
349 			}
350 		}
351 
352 		wpa_printf(MSG_DEBUG, "   AT_MAC");
353 		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
354 	}
355 	return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, NULL, 0);
356 }
357 
358 
eap_sim_buildReq(struct eap_sm * sm,void * priv,u8 id)359 static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id)
360 {
361 	struct eap_sim_data *data = priv;
362 
363 	switch (data->state) {
364 	case START:
365 		return eap_sim_build_start(sm, data, id);
366 	case CHALLENGE:
367 		return eap_sim_build_challenge(sm, data, id);
368 	case REAUTH:
369 		return eap_sim_build_reauth(sm, data, id);
370 	case NOTIFICATION:
371 		return eap_sim_build_notification(sm, data, id);
372 	default:
373 		wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in "
374 			   "buildReq", data->state);
375 		break;
376 	}
377 	return NULL;
378 }
379 
380 
eap_sim_check(struct eap_sm * sm,void * priv,struct wpabuf * respData)381 static bool eap_sim_check(struct eap_sm *sm, void *priv,
382 			  struct wpabuf *respData)
383 {
384 	const u8 *pos;
385 	size_t len;
386 
387 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len);
388 	if (pos == NULL || len < 3) {
389 		wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame");
390 		return true;
391 	}
392 
393 	return false;
394 }
395 
396 
eap_sim_unexpected_subtype(struct eap_sim_data * data,u8 subtype)397 static bool eap_sim_unexpected_subtype(struct eap_sim_data *data,
398 				       u8 subtype)
399 {
400 	if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR)
401 		return false;
402 
403 	switch (data->state) {
404 	case START:
405 		if (subtype != EAP_SIM_SUBTYPE_START) {
406 			wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
407 				   "subtype %d", subtype);
408 			return true;
409 		}
410 		break;
411 	case CHALLENGE:
412 		if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) {
413 			wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
414 				   "subtype %d", subtype);
415 			return true;
416 		}
417 		break;
418 	case REAUTH:
419 		if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) {
420 			wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
421 				   "subtype %d", subtype);
422 			return true;
423 		}
424 		break;
425 	case NOTIFICATION:
426 		if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) {
427 			wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
428 				   "subtype %d", subtype);
429 			return true;
430 		}
431 		break;
432 	default:
433 		wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for "
434 			   "processing a response", data->state);
435 		return true;
436 	}
437 
438 	return false;
439 }
440 
441 
eap_sim_supported_ver(struct eap_sim_data * data,int version)442 static int eap_sim_supported_ver(struct eap_sim_data *data, int version)
443 {
444 	return version == EAP_SIM_VERSION;
445 }
446 
447 
eap_sim_process_start(struct eap_sm * sm,struct eap_sim_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)448 static void eap_sim_process_start(struct eap_sm *sm,
449 				  struct eap_sim_data *data,
450 				  struct wpabuf *respData,
451 				  struct eap_sim_attrs *attr)
452 {
453 	const u8 *identity;
454 	size_t identity_len;
455 	u8 ver_list[2];
456 	u8 *new_identity;
457 	char *username;
458 
459 	wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response");
460 
461 	if (data->start_round == 0) {
462 		/*
463 		 * Special case for AT_COUNTER_TOO_SMALL recovery - no identity
464 		 * was requested since we already know it.
465 		 */
466 		goto skip_id_update;
467 	}
468 
469 	if ((sm->cfg->eap_sim_id & 0x04) &&
470 	    (!attr->identity || attr->identity_len == 0))
471 		goto skip_id_attr;
472 
473 	/*
474 	 * Unless explicitly configured otherwise, we always request identity
475 	 * in SIM/Start, so the peer is required to have replied with one.
476 	 */
477 	if (!attr->identity || attr->identity_len == 0) {
478 		wpa_printf(MSG_DEBUG, "EAP-SIM: Peer did not provide any "
479 			   "identity");
480 		goto failed;
481 	}
482 
483 	new_identity = os_malloc(attr->identity_len);
484 	if (new_identity == NULL)
485 		goto failed;
486 	os_free(sm->identity);
487 	sm->identity = new_identity;
488 	os_memcpy(sm->identity, attr->identity, attr->identity_len);
489 	sm->identity_len = attr->identity_len;
490 
491 skip_id_attr:
492 	if (sm->sim_aka_permanent[0]) {
493 		identity = (const u8 *) sm->sim_aka_permanent;
494 		identity_len = os_strlen(sm->sim_aka_permanent);
495 	} else {
496 		identity = sm->identity;
497 		identity_len = sm->identity_len;
498 	}
499 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
500 			  identity, identity_len);
501 	username = sim_get_username(identity, identity_len);
502 	if (username == NULL)
503 		goto failed;
504 
505 	if (username[0] == EAP_SIM_REAUTH_ID_PREFIX) {
506 		wpa_printf(MSG_DEBUG, "EAP-SIM: Reauth username '%s'",
507 			   username);
508 		data->reauth = eap_sim_db_get_reauth_entry(
509 			sm->cfg->eap_sim_db_priv, username);
510 		os_free(username);
511 		if (data->reauth == NULL) {
512 			wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown reauth "
513 				   "identity - request full auth identity");
514 			/* Remain in START state for another round */
515 			return;
516 		}
517 
518 		if (data->reauth->counter >
519 		    sm->cfg->eap_sim_aka_fast_reauth_limit &&
520 		    (sm->cfg->eap_sim_id & 0x04)) {
521 			wpa_printf(MSG_DEBUG,
522 				   "EAP-SIM: Too many fast re-authentication attemps - fall back to full authentication");
523 			wpa_printf(MSG_DEBUG,
524 				   "EAP-SIM: Permanent identity recognized - skip new Identity query");
525 			os_strlcpy(data->permanent,
526 				   data->reauth->permanent,
527 				   sizeof(data->permanent));
528 			os_strlcpy(sm->sim_aka_permanent,
529 				   data->reauth->permanent,
530 				   sizeof(sm->sim_aka_permanent));
531 			eap_sim_db_remove_reauth(
532 				sm->cfg->eap_sim_db_priv,
533 				data->reauth);
534 			data->reauth = NULL;
535 			goto skip_id_update;
536 		}
537 
538 		wpa_printf(MSG_DEBUG,
539 			   "EAP-SIM: Using fast re-authentication (counter=%d)",
540 			   data->reauth->counter);
541 		os_strlcpy(data->permanent, data->reauth->permanent,
542 			   sizeof(data->permanent));
543 		data->counter = data->reauth->counter;
544 		os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN);
545 		eap_sim_state(data, REAUTH);
546 		return;
547 	}
548 
549 	if (username[0] == EAP_SIM_PSEUDONYM_PREFIX) {
550 		const char *permanent;
551 		wpa_printf(MSG_DEBUG, "EAP-SIM: Pseudonym username '%s'",
552 			   username);
553 		permanent = eap_sim_db_get_permanent(
554 			sm->cfg->eap_sim_db_priv, username);
555 		os_free(username);
556 		if (permanent == NULL) {
557 			wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown pseudonym "
558 				   "identity - request permanent identity");
559 			/* Remain in START state for another round */
560 			return;
561 		}
562 		os_strlcpy(data->permanent, permanent,
563 			   sizeof(data->permanent));
564 	} else if (username[0] == EAP_SIM_PERMANENT_PREFIX) {
565 		wpa_printf(MSG_DEBUG, "EAP-SIM: Permanent username '%s'",
566 			   username);
567 		os_strlcpy(data->permanent, username, sizeof(data->permanent));
568 		os_free(username);
569 #ifdef CRYPTO_RSA_OAEP_SHA256
570 	} else if (sm->identity_len > 1 && sm->identity[0] == '\0') {
571 		char *enc_id, *pos, *end;
572 		size_t enc_id_len;
573 		u8 *decoded_id;
574 		size_t decoded_id_len;
575 		struct wpabuf *enc, *dec;
576 		u8 *new_id;
577 
578 		os_free(username);
579 		if (!sm->cfg->imsi_privacy_key) {
580 			wpa_printf(MSG_DEBUG,
581 				   "EAP-SIM: Received encrypted identity, but no IMSI privacy key configured to decrypt it");
582 			goto failed;
583 		}
584 
585 		enc_id = (char *) &sm->identity[1];
586 		end = (char *) &sm->identity[sm->identity_len];
587 		for (pos = enc_id; pos < end; pos++) {
588 			if (*pos == ',')
589 				break;
590 		}
591 		enc_id_len = pos - enc_id;
592 
593 		wpa_hexdump_ascii(MSG_DEBUG,
594 				  "EAP-SIM: Encrypted permanent identity",
595 				  enc_id, enc_id_len);
596 		decoded_id = base64_decode(enc_id, enc_id_len, &decoded_id_len);
597 		if (!decoded_id) {
598 			wpa_printf(MSG_DEBUG,
599 				   "EAP-SIM: Could not base64 decode encrypted identity");
600 			goto failed;
601 		}
602 		wpa_hexdump(MSG_DEBUG,
603 			    "EAP-SIM: Decoded encrypted permanent identity",
604 			    decoded_id, decoded_id_len);
605 		enc = wpabuf_alloc_copy(decoded_id, decoded_id_len);
606 		os_free(decoded_id);
607 		if (!enc)
608 			goto failed;
609 		dec = crypto_rsa_oaep_sha256_decrypt(sm->cfg->imsi_privacy_key,
610 						     enc);
611 		wpabuf_free(enc);
612 		if (!dec) {
613 			wpa_printf(MSG_DEBUG,
614 				   "EAP-SIM: Failed to decrypt encrypted identity");
615 			goto failed;
616 		}
617 		wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Decrypted permanent identity",
618 				  wpabuf_head(dec), wpabuf_len(dec));
619 		username = sim_get_username(wpabuf_head(dec), wpabuf_len(dec));
620 		if (!username) {
621 			wpabuf_free(dec);
622 			goto failed;
623 		}
624 		new_id = os_memdup(wpabuf_head(dec), wpabuf_len(dec));
625 		if (!new_id) {
626 			wpabuf_free(dec);
627 			goto failed;
628 		}
629 		os_free(sm->identity);
630 		sm->identity = new_id;
631 		sm->identity_len = wpabuf_len(dec);
632 		wpabuf_free(dec);
633 		os_strlcpy(data->permanent, username, sizeof(data->permanent));
634 		os_free(username);
635 #endif /* CRYPTO_RSA_OAEP_SHA256 */
636 	} else {
637 		wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized username '%s'",
638 			   username);
639 		os_free(username);
640 		goto failed;
641 	}
642 
643 skip_id_update:
644 	/* Full authentication */
645 
646 	if (attr->nonce_mt == NULL || attr->selected_version < 0) {
647 		wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing "
648 			   "required attributes");
649 		goto failed;
650 	}
651 
652 	if (!eap_sim_supported_ver(data, attr->selected_version)) {
653 		wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported "
654 			   "version %d", attr->selected_version);
655 		goto failed;
656 	}
657 
658 	data->counter = 0; /* reset re-auth counter since this is full auth */
659 	data->reauth = NULL;
660 
661 	data->num_chal = eap_sim_db_get_gsm_triplets(
662 		sm->cfg->eap_sim_db_priv, data->permanent, EAP_SIM_MAX_CHAL,
663 		(u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm);
664 	if (data->num_chal == EAP_SIM_DB_PENDING) {
665 		wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets "
666 			   "not yet available - pending request");
667 		sm->method_pending = METHOD_PENDING_WAIT;
668 		return;
669 	}
670 	if (data->num_chal < 2) {
671 		wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM "
672 			   "authentication triplets for the peer");
673 		goto failed;
674 	}
675 
676 	if (data->permanent[0] == EAP_SIM_PERMANENT_PREFIX)
677 		os_strlcpy(sm->imsi, &data->permanent[1], sizeof(sm->imsi));
678 
679 	identity_len = sm->identity_len;
680 	while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
681 		wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null "
682 			   "character from identity");
683 		identity_len--;
684 	}
685 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation",
686 			  sm->identity, identity_len);
687 
688 	os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN);
689 	WPA_PUT_BE16(ver_list, EAP_SIM_VERSION);
690 	eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt,
691 			  attr->selected_version, ver_list, sizeof(ver_list),
692 			  data->num_chal, (const u8 *) data->kc, data->mk);
693 	eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
694 			    data->emsk);
695 
696 	eap_sim_state(data, CHALLENGE);
697 	return;
698 
699 failed:
700 	data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
701 	eap_sim_state(data, NOTIFICATION);
702 }
703 
704 
eap_sim_process_challenge(struct eap_sm * sm,struct eap_sim_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)705 static void eap_sim_process_challenge(struct eap_sm *sm,
706 				      struct eap_sim_data *data,
707 				      struct wpabuf *respData,
708 				      struct eap_sim_attrs *attr)
709 {
710 	if (attr->mac == NULL ||
711 	    eap_sim_verify_mac(data->k_aut, respData, attr->mac,
712 			       (u8 *) data->sres,
713 			       data->num_chal * EAP_SIM_SRES_LEN)) {
714 		wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
715 			   "did not include valid AT_MAC");
716 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
717 		eap_sim_state(data, NOTIFICATION);
718 		return;
719 	}
720 
721 	wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the "
722 		   "correct AT_MAC");
723 	if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) {
724 		data->use_result_ind = 1;
725 		data->notification = EAP_SIM_SUCCESS;
726 		eap_sim_state(data, NOTIFICATION);
727 	} else
728 		eap_sim_state(data, SUCCESS);
729 
730 	if (data->next_pseudonym) {
731 		eap_sim_db_add_pseudonym(sm->cfg->eap_sim_db_priv,
732 					 data->permanent,
733 					 data->next_pseudonym);
734 		data->next_pseudonym = NULL;
735 	}
736 	if (data->next_reauth_id) {
737 		eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv, data->permanent,
738 				      data->next_reauth_id, data->counter + 1,
739 				      data->mk);
740 		data->next_reauth_id = NULL;
741 	}
742 }
743 
744 
eap_sim_process_reauth(struct eap_sm * sm,struct eap_sim_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)745 static void eap_sim_process_reauth(struct eap_sm *sm,
746 				   struct eap_sim_data *data,
747 				   struct wpabuf *respData,
748 				   struct eap_sim_attrs *attr)
749 {
750 	struct eap_sim_attrs eattr;
751 	u8 *decrypted = NULL;
752 
753 	if (attr->mac == NULL ||
754 	    eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s,
755 			       EAP_SIM_NONCE_S_LEN)) {
756 		wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message "
757 			   "did not include valid AT_MAC");
758 		goto fail;
759 	}
760 
761 	if (attr->encr_data == NULL || attr->iv == NULL) {
762 		wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
763 			   "message did not include encrypted data");
764 		goto fail;
765 	}
766 
767 	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
768 				       attr->encr_data_len, attr->iv, &eattr,
769 				       0);
770 	if (decrypted == NULL) {
771 		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
772 			   "data from reauthentication message");
773 		goto fail;
774 	}
775 
776 	if (eattr.counter != data->counter) {
777 		wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message "
778 			   "used incorrect counter %u, expected %u",
779 			   eattr.counter, data->counter);
780 		goto fail;
781 	}
782 	os_free(decrypted);
783 	decrypted = NULL;
784 
785 	wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes "
786 		   "the correct AT_MAC");
787 
788 	if (eattr.counter_too_small) {
789 		wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
790 			   "included AT_COUNTER_TOO_SMALL - starting full "
791 			   "authentication");
792 		data->start_round = -1;
793 		eap_sim_state(data, START);
794 		return;
795 	}
796 
797 	if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) {
798 		data->use_result_ind = 1;
799 		data->notification = EAP_SIM_SUCCESS;
800 		eap_sim_state(data, NOTIFICATION);
801 	} else
802 		eap_sim_state(data, SUCCESS);
803 
804 	if (data->next_reauth_id) {
805 		eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv, data->permanent,
806 				      data->next_reauth_id,
807 				      data->counter + 1, data->mk);
808 		data->next_reauth_id = NULL;
809 	} else {
810 		eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv,
811 					 data->reauth);
812 		data->reauth = NULL;
813 	}
814 
815 	return;
816 
817 fail:
818 	data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
819 	eap_sim_state(data, NOTIFICATION);
820 	eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv, data->reauth);
821 	data->reauth = NULL;
822 	os_free(decrypted);
823 }
824 
825 
eap_sim_process_client_error(struct eap_sm * sm,struct eap_sim_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)826 static void eap_sim_process_client_error(struct eap_sm *sm,
827 					 struct eap_sim_data *data,
828 					 struct wpabuf *respData,
829 					 struct eap_sim_attrs *attr)
830 {
831 	wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d",
832 		   attr->client_error_code);
833 	if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
834 		eap_sim_state(data, SUCCESS);
835 	else
836 		eap_sim_state(data, FAILURE);
837 }
838 
839 
eap_sim_process_notification(struct eap_sm * sm,struct eap_sim_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)840 static void eap_sim_process_notification(struct eap_sm *sm,
841 					 struct eap_sim_data *data,
842 					 struct wpabuf *respData,
843 					 struct eap_sim_attrs *attr)
844 {
845 	wpa_printf(MSG_DEBUG, "EAP-SIM: Client replied to notification");
846 	if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
847 		eap_sim_state(data, SUCCESS);
848 	else
849 		eap_sim_state(data, FAILURE);
850 }
851 
852 
eap_sim_process(struct eap_sm * sm,void * priv,struct wpabuf * respData)853 static void eap_sim_process(struct eap_sm *sm, void *priv,
854 			    struct wpabuf *respData)
855 {
856 	struct eap_sim_data *data = priv;
857 	const u8 *pos, *end;
858 	u8 subtype;
859 	size_t len;
860 	struct eap_sim_attrs attr;
861 
862 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len);
863 	if (pos == NULL || len < 3)
864 		return;
865 
866 	end = pos + len;
867 	subtype = *pos;
868 	pos += 3;
869 
870 	if (eap_sim_unexpected_subtype(data, subtype)) {
871 		wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized or unexpected "
872 			   "EAP-SIM Subtype in EAP Response");
873 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
874 		eap_sim_state(data, NOTIFICATION);
875 		return;
876 	}
877 
878 	if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) {
879 		wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes");
880 		if (subtype != EAP_SIM_SUBTYPE_CLIENT_ERROR &&
881 		    (data->state == START || data->state == CHALLENGE ||
882 		     data->state == REAUTH)) {
883 			data->notification =
884 				EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
885 			eap_sim_state(data, NOTIFICATION);
886 			return;
887 		}
888 		eap_sim_state(data, FAILURE);
889 		return;
890 	}
891 
892 	if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) {
893 		eap_sim_process_client_error(sm, data, respData, &attr);
894 		return;
895 	}
896 
897 	switch (data->state) {
898 	case START:
899 		eap_sim_process_start(sm, data, respData, &attr);
900 		break;
901 	case CHALLENGE:
902 		eap_sim_process_challenge(sm, data, respData, &attr);
903 		break;
904 	case REAUTH:
905 		eap_sim_process_reauth(sm, data, respData, &attr);
906 		break;
907 	case NOTIFICATION:
908 		eap_sim_process_notification(sm, data, respData, &attr);
909 		break;
910 	default:
911 		wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in "
912 			   "process", data->state);
913 		break;
914 	}
915 }
916 
917 
eap_sim_isDone(struct eap_sm * sm,void * priv)918 static bool eap_sim_isDone(struct eap_sm *sm, void *priv)
919 {
920 	struct eap_sim_data *data = priv;
921 	return data->state == SUCCESS || data->state == FAILURE;
922 }
923 
924 
eap_sim_getKey(struct eap_sm * sm,void * priv,size_t * len)925 static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len)
926 {
927 	struct eap_sim_data *data = priv;
928 	u8 *key;
929 
930 	if (data->state != SUCCESS)
931 		return NULL;
932 
933 	key = os_memdup(data->msk, EAP_SIM_KEYING_DATA_LEN);
934 	if (key == NULL)
935 		return NULL;
936 	*len = EAP_SIM_KEYING_DATA_LEN;
937 	return key;
938 }
939 
940 
eap_sim_get_emsk(struct eap_sm * sm,void * priv,size_t * len)941 static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
942 {
943 	struct eap_sim_data *data = priv;
944 	u8 *key;
945 
946 	if (data->state != SUCCESS)
947 		return NULL;
948 
949 	key = os_memdup(data->emsk, EAP_EMSK_LEN);
950 	if (key == NULL)
951 		return NULL;
952 	*len = EAP_EMSK_LEN;
953 	return key;
954 }
955 
956 
eap_sim_isSuccess(struct eap_sm * sm,void * priv)957 static bool eap_sim_isSuccess(struct eap_sm *sm, void *priv)
958 {
959 	struct eap_sim_data *data = priv;
960 	return data->state == SUCCESS;
961 }
962 
963 
eap_sim_get_session_id(struct eap_sm * sm,void * priv,size_t * len)964 static u8 * eap_sim_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
965 {
966 	struct eap_sim_data *data = priv;
967 	u8 *id;
968 
969 	if (data->state != SUCCESS)
970 		return NULL;
971 
972 	if (!data->reauth)
973 		*len = 1 + data->num_chal * GSM_RAND_LEN + EAP_SIM_NONCE_MT_LEN;
974 	else
975 		*len = 1 + EAP_SIM_NONCE_S_LEN + EAP_SIM_MAC_LEN;
976 	id = os_malloc(*len);
977 	if (id == NULL)
978 		return NULL;
979 
980 	id[0] = EAP_TYPE_SIM;
981 	if (!data->reauth) {
982 		os_memcpy(id + 1, data->rand, data->num_chal * GSM_RAND_LEN);
983 		os_memcpy(id + 1 + data->num_chal * GSM_RAND_LEN,
984 			  data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
985 	} else {
986 		os_memcpy(id + 1, data->nonce_s, EAP_SIM_NONCE_S_LEN);
987 		os_memcpy(id + 1 + EAP_SIM_NONCE_S_LEN, data->reauth_mac,
988 			  EAP_SIM_MAC_LEN);
989 
990 	}
991 	wpa_hexdump(MSG_DEBUG, "EAP-SIM: Derived Session-Id", id, *len);
992 
993 	return id;
994 }
995 
996 
eap_server_sim_register(void)997 int eap_server_sim_register(void)
998 {
999 	struct eap_method *eap;
1000 
1001 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1002 				      EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
1003 	if (eap == NULL)
1004 		return -1;
1005 
1006 	eap->init = eap_sim_init;
1007 	eap->reset = eap_sim_reset;
1008 	eap->buildReq = eap_sim_buildReq;
1009 	eap->check = eap_sim_check;
1010 	eap->process = eap_sim_process;
1011 	eap->isDone = eap_sim_isDone;
1012 	eap->getKey = eap_sim_getKey;
1013 	eap->isSuccess = eap_sim_isSuccess;
1014 	eap->get_emsk = eap_sim_get_emsk;
1015 	eap->getSessionId = eap_sim_get_session_id;
1016 
1017 	return eap_server_method_register(eap);
1018 }
1019