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