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