xref: /freebsd/contrib/wpa/src/eap_server/eap_server_aka.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
1 /*
2  * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448)
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/sha256.h"
14 #include "crypto/crypto.h"
15 #include "crypto/random.h"
16 #include "eap_common/eap_sim_common.h"
17 #include "eap_server/eap_i.h"
18 #include "eap_server/eap_sim_db.h"
19 
20 
21 struct eap_aka_data {
22 	u8 mk[EAP_SIM_MK_LEN];
23 	u8 nonce_s[EAP_SIM_NONCE_S_LEN];
24 	u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
25 	u8 k_encr[EAP_SIM_K_ENCR_LEN];
26 	u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */
27 	u8 msk[EAP_SIM_KEYING_DATA_LEN];
28 	u8 emsk[EAP_EMSK_LEN];
29 	u8 rand[EAP_AKA_RAND_LEN];
30 	u8 autn[EAP_AKA_AUTN_LEN];
31 	u8 ck[EAP_AKA_CK_LEN];
32 	u8 ik[EAP_AKA_IK_LEN];
33 	u8 res[EAP_AKA_RES_MAX_LEN];
34 	u8 reauth_mac[EAP_SIM_MAC_LEN];
35 	size_t res_len;
36 	enum {
37 		IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
38 	} state;
39 	char *next_pseudonym;
40 	char *next_reauth_id;
41 	u16 counter;
42 	struct eap_sim_reauth *reauth;
43 	int auts_reported; /* whether the current AUTS has been reported to the
44 			    * eap_sim_db */
45 	u16 notification;
46 	int use_result_ind;
47 
48 	struct wpabuf *id_msgs;
49 	int pending_id;
50 	u8 eap_method;
51 	u8 *network_name;
52 	size_t network_name_len;
53 	u16 kdf;
54 	int identity_round;
55 	char permanent[20]; /* Permanent username */
56 };
57 
58 
59 static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data);
60 
61 
eap_aka_state_txt(int state)62 static const char * eap_aka_state_txt(int state)
63 {
64 	switch (state) {
65 	case IDENTITY:
66 		return "IDENTITY";
67 	case CHALLENGE:
68 		return "CHALLENGE";
69 	case REAUTH:
70 		return "REAUTH";
71 	case SUCCESS:
72 		return "SUCCESS";
73 	case FAILURE:
74 		return "FAILURE";
75 	case NOTIFICATION:
76 		return "NOTIFICATION";
77 	default:
78 		return "Unknown?!";
79 	}
80 }
81 
82 
eap_aka_state(struct eap_aka_data * data,int state)83 static void eap_aka_state(struct eap_aka_data *data, int state)
84 {
85 	wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
86 		   eap_aka_state_txt(data->state),
87 		   eap_aka_state_txt(state));
88 	data->state = state;
89 }
90 
91 
eap_aka_check_identity_reauth(struct eap_sm * sm,struct eap_aka_data * data,const char * username)92 static int eap_aka_check_identity_reauth(struct eap_sm *sm,
93 					 struct eap_aka_data *data,
94 					 const char *username)
95 {
96 	if (data->eap_method == EAP_TYPE_AKA_PRIME &&
97 	    username[0] != EAP_AKA_PRIME_REAUTH_ID_PREFIX)
98 		return 0;
99 	if (data->eap_method == EAP_TYPE_AKA &&
100 	    username[0] != EAP_AKA_REAUTH_ID_PREFIX)
101 		return 0;
102 
103 	wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth username '%s'", username);
104 	data->reauth = eap_sim_db_get_reauth_entry(sm->cfg->eap_sim_db_priv,
105 						   username);
106 	if (data->reauth == NULL) {
107 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown reauth identity - "
108 			   "request full auth identity");
109 		/* Remain in IDENTITY state for another round */
110 		return 0;
111 	}
112 
113 	if (data->reauth->counter > sm->cfg->eap_sim_aka_fast_reauth_limit) {
114 		wpa_printf(MSG_DEBUG,
115 			   "EAP-AKA: Too many fast re-authentication attemps - fall back to full authentication");
116 		if (sm->cfg->eap_sim_id & 0x04) {
117 			wpa_printf(MSG_DEBUG,
118 				   "EAP-AKA: Permanent identity recognized - skip AKA-Identity exchange");
119 			os_strlcpy(data->permanent, data->reauth->permanent,
120 				   sizeof(data->permanent));
121 			os_strlcpy(sm->sim_aka_permanent,
122 				   data->reauth->permanent,
123 				   sizeof(sm->sim_aka_permanent));
124 			eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv,
125 						 data->reauth);
126 			data->reauth = NULL;
127 			eap_aka_fullauth(sm, data);
128 			return 1;
129 		}
130 		return 0;
131 	}
132 
133 	wpa_printf(MSG_DEBUG,
134 		   "EAP-AKA: Using fast re-authentication (counter=%d)",
135 		   data->reauth->counter);
136 	os_strlcpy(data->permanent, data->reauth->permanent,
137 		   sizeof(data->permanent));
138 	data->counter = data->reauth->counter;
139 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
140 		os_memcpy(data->k_encr, data->reauth->k_encr,
141 			  EAP_SIM_K_ENCR_LEN);
142 		os_memcpy(data->k_aut, data->reauth->k_aut,
143 			  EAP_AKA_PRIME_K_AUT_LEN);
144 		os_memcpy(data->k_re, data->reauth->k_re,
145 			  EAP_AKA_PRIME_K_RE_LEN);
146 	} else {
147 		os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN);
148 	}
149 
150 	eap_aka_state(data, REAUTH);
151 	return 1;
152 }
153 
154 
eap_aka_check_identity(struct eap_sm * sm,struct eap_aka_data * data)155 static void eap_aka_check_identity(struct eap_sm *sm,
156 				   struct eap_aka_data *data)
157 {
158 	char *username;
159 	const u8 *identity = sm->identity;
160 	size_t identity_len = sm->identity_len;
161 
162 	if (sm->sim_aka_permanent[0]) {
163 		identity = (const u8 *) sm->sim_aka_permanent;
164 		identity_len = os_strlen(sm->sim_aka_permanent);
165 	}
166 
167 	/* Check if we already know the identity from EAP-Response/Identity */
168 
169 	username = sim_get_username(identity, identity_len);
170 	if (username == NULL)
171 		return;
172 
173 	if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
174 		os_free(username);
175 		/*
176 		 * Since re-auth username was recognized, skip AKA/Identity
177 		 * exchange.
178 		 */
179 		return;
180 	}
181 
182 	if (sm->sim_aka_permanent[0] && data->state == IDENTITY) {
183 		/* Skip AKA/Identity exchange since the permanent identity
184 		 * was recognized. */
185 		os_free(username);
186 		os_strlcpy(data->permanent, sm->sim_aka_permanent,
187 			   sizeof(data->permanent));
188 		eap_aka_fullauth(sm, data);
189 		return;
190 	}
191 
192 	if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
193 	     username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
194 	    (data->eap_method == EAP_TYPE_AKA &&
195 	     username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
196 		const char *permanent;
197 		wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
198 			   username);
199 		permanent = eap_sim_db_get_permanent(
200 			sm->cfg->eap_sim_db_priv, username);
201 		if (permanent == NULL) {
202 			os_free(username);
203 			wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
204 				   "identity - request permanent identity");
205 			/* Remain in IDENTITY state for another round */
206 			return;
207 		}
208 		os_strlcpy(data->permanent, permanent,
209 			   sizeof(data->permanent));
210 		/*
211 		 * Since pseudonym username was recognized, skip AKA/Identity
212 		 * exchange.
213 		 */
214 		eap_aka_fullauth(sm, data);
215 	}
216 
217 	os_free(username);
218 }
219 
220 
eap_aka_init(struct eap_sm * sm)221 static void * eap_aka_init(struct eap_sm *sm)
222 {
223 	struct eap_aka_data *data;
224 
225 	if (!sm->cfg->eap_sim_db_priv) {
226 		wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
227 		return NULL;
228 	}
229 
230 	data = os_zalloc(sizeof(*data));
231 	if (data == NULL)
232 		return NULL;
233 
234 	data->eap_method = EAP_TYPE_AKA;
235 
236 	data->state = IDENTITY;
237 	data->pending_id = -1;
238 	eap_aka_check_identity(sm, data);
239 
240 	return data;
241 }
242 
243 
244 #ifdef EAP_SERVER_AKA_PRIME
eap_aka_prime_init(struct eap_sm * sm)245 static void * eap_aka_prime_init(struct eap_sm *sm)
246 {
247 	struct eap_aka_data *data;
248 	/* TODO: make ANID configurable; see 3GPP TS 24.302 */
249 	char *network_name = "WLAN";
250 
251 	if (sm->cfg->eap_sim_db_priv == NULL) {
252 		wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
253 		return NULL;
254 	}
255 
256 	data = os_zalloc(sizeof(*data));
257 	if (data == NULL)
258 		return NULL;
259 
260 	data->eap_method = EAP_TYPE_AKA_PRIME;
261 	data->network_name = (u8 *) os_strdup(network_name);
262 	if (data->network_name == NULL) {
263 		os_free(data);
264 		return NULL;
265 	}
266 
267 	data->network_name_len = os_strlen(network_name);
268 
269 	data->state = IDENTITY;
270 	data->pending_id = -1;
271 	eap_aka_check_identity(sm, data);
272 
273 	return data;
274 }
275 #endif /* EAP_SERVER_AKA_PRIME */
276 
277 
eap_aka_reset(struct eap_sm * sm,void * priv)278 static void eap_aka_reset(struct eap_sm *sm, void *priv)
279 {
280 	struct eap_aka_data *data = priv;
281 	os_free(data->next_pseudonym);
282 	os_free(data->next_reauth_id);
283 	wpabuf_free(data->id_msgs);
284 	os_free(data->network_name);
285 	bin_clear_free(data, sizeof(*data));
286 }
287 
288 
eap_aka_add_id_msg(struct eap_aka_data * data,const struct wpabuf * msg)289 static int eap_aka_add_id_msg(struct eap_aka_data *data,
290 			      const struct wpabuf *msg)
291 {
292 	if (msg == NULL)
293 		return -1;
294 
295 	if (data->id_msgs == NULL) {
296 		data->id_msgs = wpabuf_dup(msg);
297 		return data->id_msgs == NULL ? -1 : 0;
298 	}
299 
300 	if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
301 		return -1;
302 	wpabuf_put_buf(data->id_msgs, msg);
303 
304 	return 0;
305 }
306 
307 
eap_aka_add_checkcode(struct eap_aka_data * data,struct eap_sim_msg * msg)308 static void eap_aka_add_checkcode(struct eap_aka_data *data,
309 				  struct eap_sim_msg *msg)
310 {
311 	const u8 *addr;
312 	size_t len;
313 	u8 hash[SHA256_MAC_LEN];
314 
315 	wpa_printf(MSG_DEBUG, "   AT_CHECKCODE");
316 
317 	if (data->id_msgs == NULL) {
318 		/*
319 		 * No EAP-AKA/Identity packets were exchanged - send empty
320 		 * checkcode.
321 		 */
322 		eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
323 		return;
324 	}
325 
326 	/* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
327 	addr = wpabuf_head(data->id_msgs);
328 	len = wpabuf_len(data->id_msgs);
329 	wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
330 	if (data->eap_method == EAP_TYPE_AKA_PRIME)
331 		sha256_vector(1, &addr, &len, hash);
332 	else
333 		sha1_vector(1, &addr, &len, hash);
334 
335 	eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
336 			data->eap_method == EAP_TYPE_AKA_PRIME ?
337 			EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
338 }
339 
340 
eap_aka_verify_checkcode(struct eap_aka_data * data,const u8 * checkcode,size_t checkcode_len)341 static int eap_aka_verify_checkcode(struct eap_aka_data *data,
342 				    const u8 *checkcode, size_t checkcode_len)
343 {
344 	const u8 *addr;
345 	size_t len;
346 	u8 hash[SHA256_MAC_LEN];
347 	size_t hash_len;
348 
349 	if (checkcode == NULL)
350 		return -1;
351 
352 	if (data->id_msgs == NULL) {
353 		if (checkcode_len != 0) {
354 			wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer "
355 				   "indicates that AKA/Identity messages were "
356 				   "used, but they were not");
357 			return -1;
358 		}
359 		return 0;
360 	}
361 
362 	hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ?
363 		EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN;
364 
365 	if (checkcode_len != hash_len) {
366 		wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates "
367 			   "that AKA/Identity message were not used, but they "
368 			   "were");
369 		return -1;
370 	}
371 
372 	/* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
373 	addr = wpabuf_head(data->id_msgs);
374 	len = wpabuf_len(data->id_msgs);
375 	if (data->eap_method == EAP_TYPE_AKA_PRIME)
376 		sha256_vector(1, &addr, &len, hash);
377 	else
378 		sha1_vector(1, &addr, &len, hash);
379 
380 	if (os_memcmp_const(hash, checkcode, hash_len) != 0) {
381 		wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
382 		return -1;
383 	}
384 
385 	return 0;
386 }
387 
388 
eap_aka_build_identity(struct eap_sm * sm,struct eap_aka_data * data,u8 id)389 static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm,
390 					      struct eap_aka_data *data, u8 id)
391 {
392 	struct eap_sim_msg *msg;
393 	struct wpabuf *buf;
394 
395 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity");
396 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
397 			       EAP_AKA_SUBTYPE_IDENTITY);
398 	data->identity_round++;
399 	if (data->identity_round == 1) {
400 		/*
401 		 * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is
402 		 * ignored and the AKA/Identity is used to request the
403 		 * identity.
404 		 */
405 		wpa_printf(MSG_DEBUG, "   AT_ANY_ID_REQ");
406 		eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
407 	} else if (data->identity_round > 3) {
408 		/* Cannot use more than three rounds of Identity messages */
409 		eap_sim_msg_free(msg);
410 		return NULL;
411 	} else if (sm->identity && sm->identity_len > 0 &&
412 		   (sm->identity[0] == EAP_AKA_REAUTH_ID_PREFIX ||
413 		    sm->identity[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX)) {
414 		/* Reauth id may have expired - try fullauth */
415 		wpa_printf(MSG_DEBUG, "   AT_FULLAUTH_ID_REQ");
416 		eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0);
417 	} else {
418 		wpa_printf(MSG_DEBUG, "   AT_PERMANENT_ID_REQ");
419 		eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
420 	}
421 	buf = eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
422 	if (eap_aka_add_id_msg(data, buf) < 0) {
423 		wpabuf_free(buf);
424 		return NULL;
425 	}
426 	data->pending_id = id;
427 	return buf;
428 }
429 
430 
eap_aka_build_encr(struct eap_sm * sm,struct eap_aka_data * data,struct eap_sim_msg * msg,u16 counter,const u8 * nonce_s)431 static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
432 			      struct eap_sim_msg *msg, u16 counter,
433 			      const u8 *nonce_s)
434 {
435 	os_free(data->next_pseudonym);
436 	if (!(sm->cfg->eap_sim_id & 0x01)) {
437 		/* Use of pseudonyms disabled in configuration */
438 		data->next_pseudonym = NULL;
439 	} else if (!nonce_s) {
440 		data->next_pseudonym =
441 			eap_sim_db_get_next_pseudonym(
442 				sm->cfg->eap_sim_db_priv,
443 				data->eap_method == EAP_TYPE_AKA_PRIME ?
444 				EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
445 	} else {
446 		/* Do not update pseudonym during re-authentication */
447 		data->next_pseudonym = NULL;
448 	}
449 	os_free(data->next_reauth_id);
450 	if (!(sm->cfg->eap_sim_id & 0x02)) {
451 		/* Use of fast reauth disabled in configuration */
452 		data->next_reauth_id = NULL;
453 	} else if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
454 		data->next_reauth_id =
455 			eap_sim_db_get_next_reauth_id(
456 				sm->cfg->eap_sim_db_priv,
457 				data->eap_method == EAP_TYPE_AKA_PRIME ?
458 				EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
459 	} else {
460 		wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication "
461 			   "count exceeded - force full authentication");
462 		data->next_reauth_id = NULL;
463 	}
464 
465 	if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
466 	    counter == 0 && nonce_s == NULL)
467 		return 0;
468 
469 	wpa_printf(MSG_DEBUG, "   AT_IV");
470 	wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
471 	eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
472 
473 	if (counter > 0) {
474 		wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)", counter);
475 		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
476 	}
477 
478 	if (nonce_s) {
479 		wpa_printf(MSG_DEBUG, "   *AT_NONCE_S");
480 		eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
481 				EAP_SIM_NONCE_S_LEN);
482 	}
483 
484 	if (data->next_pseudonym) {
485 		wpa_printf(MSG_DEBUG, "   *AT_NEXT_PSEUDONYM (%s)",
486 			   data->next_pseudonym);
487 		eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
488 				os_strlen(data->next_pseudonym),
489 				(u8 *) data->next_pseudonym,
490 				os_strlen(data->next_pseudonym));
491 	}
492 
493 	if (data->next_reauth_id) {
494 		wpa_printf(MSG_DEBUG, "   *AT_NEXT_REAUTH_ID (%s)",
495 			   data->next_reauth_id);
496 		eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
497 				os_strlen(data->next_reauth_id),
498 				(u8 *) data->next_reauth_id,
499 				os_strlen(data->next_reauth_id));
500 	}
501 
502 	if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
503 		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
504 			   "AT_ENCR_DATA");
505 		return -1;
506 	}
507 
508 	return 0;
509 }
510 
511 
eap_aka_build_challenge(struct eap_sm * sm,struct eap_aka_data * data,u8 id)512 static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
513 					       struct eap_aka_data *data,
514 					       u8 id)
515 {
516 	struct eap_sim_msg *msg;
517 
518 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge");
519 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
520 			       EAP_AKA_SUBTYPE_CHALLENGE);
521 	wpa_printf(MSG_DEBUG, "   AT_RAND");
522 	eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN);
523 	wpa_printf(MSG_DEBUG, "   AT_AUTN");
524 	eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN);
525 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
526 		if (data->kdf) {
527 			/* Add the selected KDF into the beginning */
528 			wpa_printf(MSG_DEBUG, "   AT_KDF");
529 			eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf,
530 					NULL, 0);
531 		}
532 		wpa_printf(MSG_DEBUG, "   AT_KDF");
533 		eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF,
534 				NULL, 0);
535 		wpa_printf(MSG_DEBUG, "   AT_KDF_INPUT");
536 		eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT,
537 				data->network_name_len,
538 				data->network_name, data->network_name_len);
539 	}
540 
541 	if (eap_aka_build_encr(sm, data, msg, 0, NULL)) {
542 		eap_sim_msg_free(msg);
543 		return NULL;
544 	}
545 
546 	eap_aka_add_checkcode(data, msg);
547 
548 	if (sm->cfg->eap_sim_aka_result_ind) {
549 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
550 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
551 	}
552 
553 #ifdef EAP_SERVER_AKA_PRIME
554 	if (data->eap_method == EAP_TYPE_AKA) {
555 		u16 flags = 0;
556 		int i;
557 		int aka_prime_preferred = 0;
558 
559 		i = 0;
560 		while (sm->user && i < EAP_MAX_METHODS &&
561 		       (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
562 			sm->user->methods[i].method != EAP_TYPE_NONE)) {
563 			if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) {
564 				if (sm->user->methods[i].method ==
565 				    EAP_TYPE_AKA)
566 					break;
567 				if (sm->user->methods[i].method ==
568 				    EAP_TYPE_AKA_PRIME) {
569 					aka_prime_preferred = 1;
570 					break;
571 				}
572 			}
573 			i++;
574 		}
575 
576 		if (aka_prime_preferred)
577 			flags |= EAP_AKA_BIDDING_FLAG_D;
578 		eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0);
579 	}
580 #endif /* EAP_SERVER_AKA_PRIME */
581 
582 	wpa_printf(MSG_DEBUG, "   AT_MAC");
583 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
584 	return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
585 }
586 
587 
eap_aka_build_reauth(struct eap_sm * sm,struct eap_aka_data * data,u8 id)588 static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm,
589 					    struct eap_aka_data *data, u8 id)
590 {
591 	struct eap_sim_msg *msg;
592 	struct wpabuf *buf;
593 
594 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication");
595 
596 	if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN))
597 		return NULL;
598 	wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
599 			data->nonce_s, EAP_SIM_NONCE_S_LEN);
600 
601 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
602 		eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
603 						 sm->identity,
604 						 sm->identity_len,
605 						 data->nonce_s,
606 						 data->msk, data->emsk);
607 	} else {
608 		eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
609 				    data->msk, data->emsk);
610 		eap_sim_derive_keys_reauth(data->counter, sm->identity,
611 					   sm->identity_len, data->nonce_s,
612 					   data->mk, data->msk, data->emsk);
613 	}
614 
615 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
616 			       EAP_AKA_SUBTYPE_REAUTHENTICATION);
617 
618 	if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
619 		eap_sim_msg_free(msg);
620 		return NULL;
621 	}
622 
623 	eap_aka_add_checkcode(data, msg);
624 
625 	if (sm->cfg->eap_sim_aka_result_ind) {
626 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
627 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
628 	}
629 
630 	wpa_printf(MSG_DEBUG, "   AT_MAC");
631 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
632 	buf = eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
633 
634 	/* Remember this MAC before sending it to the peer. This MAC is used for
635 	 * Session-Id calculation after receiving response from the peer and
636 	 * after all other checks pass. */
637 	os_memcpy(data->reauth_mac,
638 		  wpabuf_head_u8(buf) + wpabuf_len(buf) - EAP_SIM_MAC_LEN,
639 		  EAP_SIM_MAC_LEN);
640 
641 	return buf;
642 }
643 
644 
eap_aka_build_notification(struct eap_sm * sm,struct eap_aka_data * data,u8 id)645 static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm,
646 						  struct eap_aka_data *data,
647 						  u8 id)
648 {
649 	struct eap_sim_msg *msg;
650 
651 	wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification");
652 	msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
653 			       EAP_AKA_SUBTYPE_NOTIFICATION);
654 	wpa_printf(MSG_DEBUG, "   AT_NOTIFICATION (%d)", data->notification);
655 	eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
656 			NULL, 0);
657 	if (data->use_result_ind) {
658 		if (data->reauth) {
659 			wpa_printf(MSG_DEBUG, "   AT_IV");
660 			wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
661 			eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
662 						   EAP_SIM_AT_ENCR_DATA);
663 			wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)",
664 				   data->counter);
665 			eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
666 					NULL, 0);
667 
668 			if (eap_sim_msg_add_encr_end(msg, data->k_encr,
669 						     EAP_SIM_AT_PADDING)) {
670 				wpa_printf(MSG_WARNING, "EAP-AKA: Failed to "
671 					   "encrypt AT_ENCR_DATA");
672 				eap_sim_msg_free(msg);
673 				return NULL;
674 			}
675 		}
676 
677 		wpa_printf(MSG_DEBUG, "   AT_MAC");
678 		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
679 	}
680 	return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
681 }
682 
683 
eap_aka_buildReq(struct eap_sm * sm,void * priv,u8 id)684 static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id)
685 {
686 	struct eap_aka_data *data = priv;
687 
688 	data->auts_reported = 0;
689 	switch (data->state) {
690 	case IDENTITY:
691 		return eap_aka_build_identity(sm, data, id);
692 	case CHALLENGE:
693 		return eap_aka_build_challenge(sm, data, id);
694 	case REAUTH:
695 		return eap_aka_build_reauth(sm, data, id);
696 	case NOTIFICATION:
697 		return eap_aka_build_notification(sm, data, id);
698 	default:
699 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
700 			   "buildReq", data->state);
701 		break;
702 	}
703 	return NULL;
704 }
705 
706 
eap_aka_check(struct eap_sm * sm,void * priv,struct wpabuf * respData)707 static bool eap_aka_check(struct eap_sm *sm, void *priv,
708 			  struct wpabuf *respData)
709 {
710 	struct eap_aka_data *data = priv;
711 	const u8 *pos;
712 	size_t len;
713 
714 	pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
715 			       &len);
716 	if (pos == NULL || len < 3) {
717 		wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
718 		return true;
719 	}
720 
721 	return false;
722 }
723 
724 
eap_aka_subtype_ok(struct eap_aka_data * data,u8 subtype)725 static bool eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
726 {
727 	if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR ||
728 	    subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT)
729 		return false;
730 
731 	switch (data->state) {
732 	case IDENTITY:
733 		if (subtype != EAP_AKA_SUBTYPE_IDENTITY) {
734 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
735 				   "subtype %d", subtype);
736 			return true;
737 		}
738 		break;
739 	case CHALLENGE:
740 		if (subtype != EAP_AKA_SUBTYPE_CHALLENGE &&
741 		    subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
742 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
743 				   "subtype %d", subtype);
744 			return true;
745 		}
746 		break;
747 	case REAUTH:
748 		if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) {
749 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
750 				   "subtype %d", subtype);
751 			return true;
752 		}
753 		break;
754 	case NOTIFICATION:
755 		if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) {
756 			wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
757 				   "subtype %d", subtype);
758 			return true;
759 		}
760 		break;
761 	default:
762 		wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for "
763 			   "processing a response", data->state);
764 		return true;
765 	}
766 
767 	return false;
768 }
769 
770 
eap_aka_determine_identity(struct eap_sm * sm,struct eap_aka_data * data)771 static void eap_aka_determine_identity(struct eap_sm *sm,
772 				       struct eap_aka_data *data)
773 {
774 	char *username;
775 
776 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
777 			  sm->identity, sm->identity_len);
778 
779 	username = sim_get_username(sm->identity, sm->identity_len);
780 	if (!username)
781 		goto fail;
782 
783 	if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
784 		os_free(username);
785 		return;
786 	}
787 
788 	if (((data->eap_method == EAP_TYPE_AKA_PRIME &&
789 	      username[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX) ||
790 	     (data->eap_method == EAP_TYPE_AKA &&
791 	      username[0] == EAP_AKA_REAUTH_ID_PREFIX)) &&
792 	    data->identity_round == 1) {
793 		/* Remain in IDENTITY state for another round to request full
794 		 * auth identity since we did not recognize reauth id */
795 		os_free(username);
796 		return;
797 	}
798 
799 	if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
800 	     username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
801 	    (data->eap_method == EAP_TYPE_AKA &&
802 	     username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
803 		const char *permanent;
804 		wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
805 			   username);
806 		permanent = eap_sim_db_get_permanent(
807 			sm->cfg->eap_sim_db_priv, username);
808 		os_free(username);
809 		if (permanent == NULL) {
810 			wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
811 				   "identity - request permanent identity");
812 			/* Remain in IDENTITY state for another round */
813 			return;
814 		}
815 		os_strlcpy(data->permanent, permanent,
816 			   sizeof(data->permanent));
817 	} else if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
818 		    username[0] == EAP_AKA_PRIME_PERMANENT_PREFIX) ||
819 		   (data->eap_method == EAP_TYPE_AKA &&
820 		    username[0] == EAP_AKA_PERMANENT_PREFIX)) {
821 		wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent username '%s'",
822 			   username);
823 		os_strlcpy(data->permanent, username, sizeof(data->permanent));
824 		os_free(username);
825 #ifdef CRYPTO_RSA_OAEP_SHA256
826 	} else if (sm->identity_len > 1 && sm->identity[0] == '\0') {
827 		char *enc_id, *pos, *end;
828 		size_t enc_id_len;
829 		u8 *decoded_id;
830 		size_t decoded_id_len;
831 		struct wpabuf *enc, *dec;
832 		u8 *new_id;
833 
834 		os_free(username);
835 		if (!sm->cfg->imsi_privacy_key) {
836 			wpa_printf(MSG_DEBUG,
837 				   "EAP-AKA: Received encrypted identity, but no IMSI privacy key configured to decrypt it");
838 			goto fail;
839 		}
840 
841 		enc_id = (char *) &sm->identity[1];
842 		end = (char *) &sm->identity[sm->identity_len];
843 		for (pos = enc_id; pos < end; pos++) {
844 			if (*pos == ',')
845 				break;
846 		}
847 		enc_id_len = pos - enc_id;
848 
849 		wpa_hexdump_ascii(MSG_DEBUG,
850 				  "EAP-AKA: Encrypted permanent identity",
851 				  enc_id, enc_id_len);
852 		decoded_id = base64_decode(enc_id, enc_id_len, &decoded_id_len);
853 		if (!decoded_id) {
854 			wpa_printf(MSG_DEBUG,
855 				   "EAP-AKA: Could not base64 decode encrypted identity");
856 			goto fail;
857 		}
858 		wpa_hexdump(MSG_DEBUG,
859 			    "EAP-AKA: Decoded encrypted permanent identity",
860 			    decoded_id, decoded_id_len);
861 		enc = wpabuf_alloc_copy(decoded_id, decoded_id_len);
862 		os_free(decoded_id);
863 		if (!enc)
864 			goto fail;
865 		dec = crypto_rsa_oaep_sha256_decrypt(sm->cfg->imsi_privacy_key,
866 						     enc);
867 		wpabuf_free(enc);
868 		if (!dec) {
869 			wpa_printf(MSG_DEBUG,
870 				   "EAP-AKA: Failed to decrypt encrypted identity");
871 			goto fail;
872 		}
873 		wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Decrypted permanent identity",
874 				  wpabuf_head(dec), wpabuf_len(dec));
875 		username = sim_get_username(wpabuf_head(dec), wpabuf_len(dec));
876 		if (!username) {
877 			wpabuf_free(dec);
878 			goto fail;
879 		}
880 		new_id = os_memdup(wpabuf_head(dec), wpabuf_len(dec));
881 		if (!new_id) {
882 			wpabuf_free(dec);
883 			goto fail;
884 		}
885 		os_free(sm->identity);
886 		sm->identity = new_id;
887 		sm->identity_len = wpabuf_len(dec);
888 		wpabuf_free(dec);
889 		os_strlcpy(data->permanent, username, sizeof(data->permanent));
890 		os_free(username);
891 #endif /* CRYPTO_RSA_OAEP_SHA256 */
892 	} else {
893 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized username '%s'",
894 			   username);
895 		os_free(username);
896 		goto fail;
897 		return;
898 	}
899 
900 	eap_aka_fullauth(sm, data);
901 	return;
902 
903 fail:
904 	data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
905 	eap_aka_state(data, NOTIFICATION);
906 }
907 
908 
eap_aka_fullauth(struct eap_sm * sm,struct eap_aka_data * data)909 static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data)
910 {
911 	size_t identity_len;
912 	int res;
913 
914 	res = eap_sim_db_get_aka_auth(sm->cfg->eap_sim_db_priv, data->permanent,
915 				      data->rand, data->autn, data->ik,
916 				      data->ck, data->res, &data->res_len, sm);
917 	if (res == EAP_SIM_DB_PENDING) {
918 		wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
919 			   "not yet available - pending request");
920 		sm->method_pending = METHOD_PENDING_WAIT;
921 		return;
922 	}
923 
924 	if (data->permanent[0] == EAP_AKA_PERMANENT_PREFIX ||
925 	    data->permanent[0] == EAP_AKA_PRIME_PERMANENT_PREFIX)
926 		os_strlcpy(sm->imsi, &data->permanent[1], sizeof(sm->imsi));
927 
928 #ifdef EAP_SERVER_AKA_PRIME
929 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
930 		/* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
931 		 * needed 6-octet SQN ^AK for CK',IK' derivation */
932 		eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
933 						 data->autn,
934 						 data->network_name,
935 						 data->network_name_len);
936 	}
937 #endif /* EAP_SERVER_AKA_PRIME */
938 
939 	data->reauth = NULL;
940 	data->counter = 0; /* reset re-auth counter since this is full auth */
941 
942 	if (res != 0) {
943 		wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA "
944 			   "authentication data for the peer");
945 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
946 		eap_aka_state(data, NOTIFICATION);
947 		return;
948 	}
949 	if (sm->method_pending == METHOD_PENDING_WAIT) {
950 		wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
951 			   "available - abort pending wait");
952 		sm->method_pending = METHOD_PENDING_NONE;
953 	}
954 
955 	identity_len = sm->identity_len;
956 	while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
957 		wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null "
958 			   "character from identity");
959 		identity_len--;
960 	}
961 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation",
962 			  sm->identity, identity_len);
963 
964 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
965 		eap_aka_prime_derive_keys(sm->identity, identity_len, data->ik,
966 					  data->ck, data->k_encr, data->k_aut,
967 					  data->k_re, data->msk, data->emsk);
968 	} else {
969 		eap_aka_derive_mk(sm->identity, identity_len, data->ik,
970 				  data->ck, data->mk);
971 		eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
972 				    data->msk, data->emsk);
973 	}
974 
975 	eap_aka_state(data, CHALLENGE);
976 }
977 
978 
eap_aka_process_identity(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)979 static void eap_aka_process_identity(struct eap_sm *sm,
980 				     struct eap_aka_data *data,
981 				     struct wpabuf *respData,
982 				     struct eap_sim_attrs *attr)
983 {
984 	u8 *new_identity;
985 
986 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity");
987 
988 	if (attr->mac || attr->iv || attr->encr_data) {
989 		wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute "
990 			   "received in EAP-Response/AKA-Identity");
991 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
992 		eap_aka_state(data, NOTIFICATION);
993 		return;
994 	}
995 
996 	/*
997 	 * We always request identity with AKA/Identity, so the peer is
998 	 * required to have replied with one.
999 	 */
1000 	if (!attr->identity || attr->identity_len == 0) {
1001 		wpa_printf(MSG_DEBUG, "EAP-AKA: Peer did not provide any "
1002 			   "identity");
1003 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1004 		eap_aka_state(data, NOTIFICATION);
1005 		return;
1006 	}
1007 
1008 	new_identity = os_malloc(attr->identity_len);
1009 	if (new_identity == NULL) {
1010 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1011 		eap_aka_state(data, NOTIFICATION);
1012 		return;
1013 	}
1014 	os_free(sm->identity);
1015 	sm->identity = new_identity;
1016 	os_memcpy(sm->identity, attr->identity, attr->identity_len);
1017 	sm->identity_len = attr->identity_len;
1018 
1019 	eap_aka_determine_identity(sm, data);
1020 	if (eap_get_id(respData) == data->pending_id) {
1021 		data->pending_id = -1;
1022 		eap_aka_add_id_msg(data, respData);
1023 	}
1024 }
1025 
1026 
eap_aka_verify_mac(struct eap_aka_data * data,const struct wpabuf * req,const u8 * mac,const u8 * extra,size_t extra_len)1027 static int eap_aka_verify_mac(struct eap_aka_data *data,
1028 			      const struct wpabuf *req,
1029 			      const u8 *mac, const u8 *extra,
1030 			      size_t extra_len)
1031 {
1032 	if (data->eap_method == EAP_TYPE_AKA_PRIME)
1033 		return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
1034 						 extra_len);
1035 	return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
1036 }
1037 
1038 
eap_aka_process_challenge(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1039 static void eap_aka_process_challenge(struct eap_sm *sm,
1040 				      struct eap_aka_data *data,
1041 				      struct wpabuf *respData,
1042 				      struct eap_sim_attrs *attr)
1043 {
1044 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
1045 
1046 #ifdef EAP_SERVER_AKA_PRIME
1047 #if 0
1048 	/* KDF negotiation; to be enabled only after more than one KDF is
1049 	 * supported */
1050 	if (data->eap_method == EAP_TYPE_AKA_PRIME &&
1051 	    attr->kdf_count == 1 && attr->mac == NULL) {
1052 		if (attr->kdf[0] != EAP_AKA_PRIME_KDF) {
1053 			wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected "
1054 				   "unknown KDF");
1055 			data->notification =
1056 				EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1057 			eap_aka_state(data, NOTIFICATION);
1058 			return;
1059 		}
1060 
1061 		data->kdf = attr->kdf[0];
1062 
1063 		/* Allow negotiation to continue with the selected KDF by
1064 		 * sending another Challenge message */
1065 		wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
1066 		return;
1067 	}
1068 #endif
1069 #endif /* EAP_SERVER_AKA_PRIME */
1070 
1071 	if (attr->checkcode &&
1072 	    eap_aka_verify_checkcode(data, attr->checkcode,
1073 				     attr->checkcode_len)) {
1074 		wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
1075 			   "message");
1076 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1077 		eap_aka_state(data, NOTIFICATION);
1078 		return;
1079 	}
1080 	if (attr->mac == NULL ||
1081 	    eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) {
1082 		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
1083 			   "did not include valid AT_MAC");
1084 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1085 		eap_aka_state(data, NOTIFICATION);
1086 		return;
1087 	}
1088 
1089 	/*
1090 	 * AT_RES is padded, so verify that there is enough room for RES and
1091 	 * that the RES length in bits matches with the expected RES.
1092 	 */
1093 	if (attr->res == NULL || attr->res_len < data->res_len ||
1094 	    attr->res_len_bits != data->res_len * 8 ||
1095 	    os_memcmp_const(attr->res, data->res, data->res_len) != 0) {
1096 		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
1097 			   "include valid AT_RES (attr len=%lu, res len=%lu "
1098 			   "bits, expected %lu bits)",
1099 			   (unsigned long) attr->res_len,
1100 			   (unsigned long) attr->res_len_bits,
1101 			   (unsigned long) data->res_len * 8);
1102 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1103 		eap_aka_state(data, NOTIFICATION);
1104 		return;
1105 	}
1106 
1107 	wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the "
1108 		   "correct AT_MAC");
1109 	if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) {
1110 		data->use_result_ind = 1;
1111 		data->notification = EAP_SIM_SUCCESS;
1112 		eap_aka_state(data, NOTIFICATION);
1113 	} else
1114 		eap_aka_state(data, SUCCESS);
1115 
1116 	if (data->next_pseudonym) {
1117 		eap_sim_db_add_pseudonym(sm->cfg->eap_sim_db_priv,
1118 					 data->permanent,
1119 					 data->next_pseudonym);
1120 		data->next_pseudonym = NULL;
1121 	}
1122 	if (data->next_reauth_id) {
1123 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1124 #ifdef EAP_SERVER_AKA_PRIME
1125 			eap_sim_db_add_reauth_prime(sm->cfg->eap_sim_db_priv,
1126 						    data->permanent,
1127 						    data->next_reauth_id,
1128 						    data->counter + 1,
1129 						    data->k_encr, data->k_aut,
1130 						    data->k_re);
1131 #endif /* EAP_SERVER_AKA_PRIME */
1132 		} else {
1133 			eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv,
1134 					      data->permanent,
1135 					      data->next_reauth_id,
1136 					      data->counter + 1,
1137 					      data->mk);
1138 		}
1139 		data->next_reauth_id = NULL;
1140 	}
1141 }
1142 
1143 
eap_aka_process_sync_failure(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1144 static void eap_aka_process_sync_failure(struct eap_sm *sm,
1145 					 struct eap_aka_data *data,
1146 					 struct wpabuf *respData,
1147 					 struct eap_sim_attrs *attr)
1148 {
1149 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure");
1150 
1151 	if (attr->auts == NULL) {
1152 		wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure "
1153 			   "message did not include valid AT_AUTS");
1154 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1155 		eap_aka_state(data, NOTIFICATION);
1156 		return;
1157 	}
1158 
1159 	/* Avoid re-reporting AUTS when processing pending EAP packet by
1160 	 * maintaining a local flag stating whether this AUTS has already been
1161 	 * reported. */
1162 	if (!data->auts_reported &&
1163 	    eap_sim_db_resynchronize(sm->cfg->eap_sim_db_priv, data->permanent,
1164 				     attr->auts, data->rand)) {
1165 		wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
1166 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1167 		eap_aka_state(data, NOTIFICATION);
1168 		return;
1169 	}
1170 	data->auts_reported = 1;
1171 
1172 	/* Remain in CHALLENGE state to re-try after resynchronization */
1173 	eap_aka_fullauth(sm, data);
1174 }
1175 
1176 
eap_aka_process_reauth(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1177 static void eap_aka_process_reauth(struct eap_sm *sm,
1178 				   struct eap_aka_data *data,
1179 				   struct wpabuf *respData,
1180 				   struct eap_sim_attrs *attr)
1181 {
1182 	struct eap_sim_attrs eattr;
1183 	u8 *decrypted = NULL;
1184 
1185 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
1186 
1187 	if (attr->mac == NULL ||
1188 	    eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s,
1189 			       EAP_SIM_NONCE_S_LEN)) {
1190 		wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
1191 			   "did not include valid AT_MAC");
1192 		goto fail;
1193 	}
1194 
1195 	if (attr->encr_data == NULL || attr->iv == NULL) {
1196 		wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
1197 			   "message did not include encrypted data");
1198 		goto fail;
1199 	}
1200 
1201 	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1202 				       attr->encr_data_len, attr->iv, &eattr,
1203 				       0);
1204 	if (decrypted == NULL) {
1205 		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
1206 			   "data from reauthentication message");
1207 		goto fail;
1208 	}
1209 
1210 	if (eattr.counter != data->counter) {
1211 		wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
1212 			   "used incorrect counter %u, expected %u",
1213 			   eattr.counter, data->counter);
1214 		goto fail;
1215 	}
1216 	os_free(decrypted);
1217 	decrypted = NULL;
1218 
1219 	wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes "
1220 		   "the correct AT_MAC");
1221 
1222 	if (eattr.counter_too_small) {
1223 		wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
1224 			   "included AT_COUNTER_TOO_SMALL - starting full "
1225 			   "authentication");
1226 		eap_aka_fullauth(sm, data);
1227 		return;
1228 	}
1229 
1230 	if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) {
1231 		data->use_result_ind = 1;
1232 		data->notification = EAP_SIM_SUCCESS;
1233 		eap_aka_state(data, NOTIFICATION);
1234 	} else
1235 		eap_aka_state(data, SUCCESS);
1236 
1237 	if (data->next_reauth_id) {
1238 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1239 #ifdef EAP_SERVER_AKA_PRIME
1240 			eap_sim_db_add_reauth_prime(sm->cfg->eap_sim_db_priv,
1241 						    data->permanent,
1242 						    data->next_reauth_id,
1243 						    data->counter + 1,
1244 						    data->k_encr, data->k_aut,
1245 						    data->k_re);
1246 #endif /* EAP_SERVER_AKA_PRIME */
1247 		} else {
1248 			eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv,
1249 					      data->permanent,
1250 					      data->next_reauth_id,
1251 					      data->counter + 1,
1252 					      data->mk);
1253 		}
1254 		data->next_reauth_id = NULL;
1255 	} else {
1256 		eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv,
1257 					 data->reauth);
1258 		data->reauth = NULL;
1259 	}
1260 
1261 	return;
1262 
1263 fail:
1264 	data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1265 	eap_aka_state(data, NOTIFICATION);
1266 	eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv, data->reauth);
1267 	data->reauth = NULL;
1268 	os_free(decrypted);
1269 }
1270 
1271 
eap_aka_process_client_error(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1272 static void eap_aka_process_client_error(struct eap_sm *sm,
1273 					 struct eap_aka_data *data,
1274 					 struct wpabuf *respData,
1275 					 struct eap_sim_attrs *attr)
1276 {
1277 	wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d",
1278 		   attr->client_error_code);
1279 	if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
1280 		eap_aka_state(data, SUCCESS);
1281 	else
1282 		eap_aka_state(data, FAILURE);
1283 }
1284 
1285 
eap_aka_process_authentication_reject(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1286 static void eap_aka_process_authentication_reject(
1287 	struct eap_sm *sm, struct eap_aka_data *data,
1288 	struct wpabuf *respData, struct eap_sim_attrs *attr)
1289 {
1290 	wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication");
1291 	eap_aka_state(data, FAILURE);
1292 }
1293 
1294 
eap_aka_process_notification(struct eap_sm * sm,struct eap_aka_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)1295 static void eap_aka_process_notification(struct eap_sm *sm,
1296 					 struct eap_aka_data *data,
1297 					 struct wpabuf *respData,
1298 					 struct eap_sim_attrs *attr)
1299 {
1300 	wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification");
1301 	if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
1302 		eap_aka_state(data, SUCCESS);
1303 	else
1304 		eap_aka_state(data, FAILURE);
1305 }
1306 
1307 
eap_aka_process(struct eap_sm * sm,void * priv,struct wpabuf * respData)1308 static void eap_aka_process(struct eap_sm *sm, void *priv,
1309 			    struct wpabuf *respData)
1310 {
1311 	struct eap_aka_data *data = priv;
1312 	const u8 *pos, *end;
1313 	u8 subtype;
1314 	size_t len;
1315 	struct eap_sim_attrs attr;
1316 
1317 	pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
1318 			       &len);
1319 	if (pos == NULL || len < 3)
1320 		return;
1321 
1322 	end = pos + len;
1323 	subtype = *pos;
1324 	pos += 3;
1325 
1326 	if (eap_aka_subtype_ok(data, subtype)) {
1327 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected "
1328 			   "EAP-AKA Subtype in EAP Response");
1329 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1330 		eap_aka_state(data, NOTIFICATION);
1331 		return;
1332 	}
1333 
1334 	if (eap_sim_parse_attr(pos, end, &attr,
1335 			       data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
1336 			       0)) {
1337 		wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes");
1338 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
1339 		eap_aka_state(data, NOTIFICATION);
1340 		return;
1341 	}
1342 
1343 	if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) {
1344 		eap_aka_process_client_error(sm, data, respData, &attr);
1345 		return;
1346 	}
1347 
1348 	if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) {
1349 		eap_aka_process_authentication_reject(sm, data, respData,
1350 						      &attr);
1351 		return;
1352 	}
1353 
1354 	switch (data->state) {
1355 	case IDENTITY:
1356 		eap_aka_process_identity(sm, data, respData, &attr);
1357 		break;
1358 	case CHALLENGE:
1359 		if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
1360 			eap_aka_process_sync_failure(sm, data, respData,
1361 						     &attr);
1362 		} else {
1363 			eap_aka_process_challenge(sm, data, respData, &attr);
1364 		}
1365 		break;
1366 	case REAUTH:
1367 		eap_aka_process_reauth(sm, data, respData, &attr);
1368 		break;
1369 	case NOTIFICATION:
1370 		eap_aka_process_notification(sm, data, respData, &attr);
1371 		break;
1372 	default:
1373 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
1374 			   "process", data->state);
1375 		break;
1376 	}
1377 }
1378 
1379 
eap_aka_isDone(struct eap_sm * sm,void * priv)1380 static bool eap_aka_isDone(struct eap_sm *sm, void *priv)
1381 {
1382 	struct eap_aka_data *data = priv;
1383 	return data->state == SUCCESS || data->state == FAILURE;
1384 }
1385 
1386 
eap_aka_getKey(struct eap_sm * sm,void * priv,size_t * len)1387 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
1388 {
1389 	struct eap_aka_data *data = priv;
1390 	u8 *key;
1391 
1392 	if (data->state != SUCCESS)
1393 		return NULL;
1394 
1395 	key = os_memdup(data->msk, EAP_SIM_KEYING_DATA_LEN);
1396 	if (key == NULL)
1397 		return NULL;
1398 	*len = EAP_SIM_KEYING_DATA_LEN;
1399 	return key;
1400 }
1401 
1402 
eap_aka_get_emsk(struct eap_sm * sm,void * priv,size_t * len)1403 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1404 {
1405 	struct eap_aka_data *data = priv;
1406 	u8 *key;
1407 
1408 	if (data->state != SUCCESS)
1409 		return NULL;
1410 
1411 	key = os_memdup(data->emsk, EAP_EMSK_LEN);
1412 	if (key == NULL)
1413 		return NULL;
1414 	*len = EAP_EMSK_LEN;
1415 	return key;
1416 }
1417 
1418 
eap_aka_isSuccess(struct eap_sm * sm,void * priv)1419 static bool eap_aka_isSuccess(struct eap_sm *sm, void *priv)
1420 {
1421 	struct eap_aka_data *data = priv;
1422 	return data->state == SUCCESS;
1423 }
1424 
1425 
eap_aka_get_session_id(struct eap_sm * sm,void * priv,size_t * len)1426 static u8 * eap_aka_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1427 {
1428 	struct eap_aka_data *data = priv;
1429 	u8 *id;
1430 
1431 	if (data->state != SUCCESS)
1432 		return NULL;
1433 
1434 	if (!data->reauth)
1435 		*len = 1 + EAP_AKA_RAND_LEN + EAP_AKA_AUTN_LEN;
1436 	else
1437 		*len = 1 + EAP_SIM_NONCE_S_LEN + EAP_SIM_MAC_LEN;
1438 	id = os_malloc(*len);
1439 	if (id == NULL)
1440 		return NULL;
1441 
1442 	id[0] = data->eap_method;
1443 	if (!data->reauth) {
1444 		os_memcpy(id + 1, data->rand, EAP_AKA_RAND_LEN);
1445 		os_memcpy(id + 1 + EAP_AKA_RAND_LEN, data->autn,
1446 			  EAP_AKA_AUTN_LEN);
1447 	} else {
1448 		os_memcpy(id + 1, data->nonce_s, EAP_SIM_NONCE_S_LEN);
1449 		os_memcpy(id + 1 + EAP_SIM_NONCE_S_LEN, data->reauth_mac,
1450 			  EAP_SIM_MAC_LEN);
1451 	}
1452 	wpa_hexdump(MSG_DEBUG, "EAP-AKA: Derived Session-Id", id, *len);
1453 
1454 	return id;
1455 }
1456 
1457 
eap_server_aka_register(void)1458 int eap_server_aka_register(void)
1459 {
1460 	struct eap_method *eap;
1461 
1462 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1463 				      EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
1464 	if (eap == NULL)
1465 		return -1;
1466 
1467 	eap->init = eap_aka_init;
1468 	eap->reset = eap_aka_reset;
1469 	eap->buildReq = eap_aka_buildReq;
1470 	eap->check = eap_aka_check;
1471 	eap->process = eap_aka_process;
1472 	eap->isDone = eap_aka_isDone;
1473 	eap->getKey = eap_aka_getKey;
1474 	eap->isSuccess = eap_aka_isSuccess;
1475 	eap->get_emsk = eap_aka_get_emsk;
1476 	eap->getSessionId = eap_aka_get_session_id;
1477 
1478 	return eap_server_method_register(eap);
1479 }
1480 
1481 
1482 #ifdef EAP_SERVER_AKA_PRIME
eap_server_aka_prime_register(void)1483 int eap_server_aka_prime_register(void)
1484 {
1485 	struct eap_method *eap;
1486 
1487 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1488 				      EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
1489 				      "AKA'");
1490 	if (eap == NULL)
1491 		return -1;
1492 
1493 	eap->init = eap_aka_prime_init;
1494 	eap->reset = eap_aka_reset;
1495 	eap->buildReq = eap_aka_buildReq;
1496 	eap->check = eap_aka_check;
1497 	eap->process = eap_aka_process;
1498 	eap->isDone = eap_aka_isDone;
1499 	eap->getKey = eap_aka_getKey;
1500 	eap->isSuccess = eap_aka_isSuccess;
1501 	eap->get_emsk = eap_aka_get_emsk;
1502 	eap->getSessionId = eap_aka_get_session_id;
1503 
1504 	return eap_server_method_register(eap);
1505 }
1506 #endif /* EAP_SERVER_AKA_PRIME */
1507