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