1 /*
2  * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448)
3  * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "pcsc_funcs.h"
13 #include "crypto/crypto.h"
14 #include "crypto/sha1.h"
15 #include "crypto/sha256.h"
16 #include "crypto/milenage.h"
17 #include "eap_common/eap_sim_common.h"
18 #include "eap_config.h"
19 #include "eap_i.h"
20 
21 
22 struct eap_aka_data {
23 	u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN];
24 	size_t res_len;
25 	u8 nonce_s[EAP_SIM_NONCE_S_LEN];
26 	u8 mk[EAP_SIM_MK_LEN];
27 	u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
28 	u8 k_encr[EAP_SIM_K_ENCR_LEN];
29 	u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */
30 	u8 msk[EAP_SIM_KEYING_DATA_LEN];
31 	u8 emsk[EAP_EMSK_LEN];
32 	u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN];
33 	u8 auts[EAP_AKA_AUTS_LEN];
34 
35 	int num_id_req, num_notification;
36 	u8 *pseudonym;
37 	size_t pseudonym_len;
38 	u8 *reauth_id;
39 	size_t reauth_id_len;
40 	int reauth;
41 	unsigned int counter, counter_too_small;
42 	u8 *last_eap_identity;
43 	size_t last_eap_identity_len;
44 	enum {
45 		CONTINUE, RESULT_SUCCESS, SUCCESS, FAILURE
46 	} state;
47 
48 	struct wpabuf *id_msgs;
49 	int prev_id;
50 	int result_ind, use_result_ind;
51 	int use_pseudonym;
52 	u8 eap_method;
53 	u8 *network_name;
54 	size_t network_name_len;
55 	u16 kdf;
56 	int kdf_negotiation;
57 };
58 
59 
60 #ifndef CONFIG_NO_STDOUT_DEBUG
eap_aka_state_txt(int state)61 static const char * eap_aka_state_txt(int state)
62 {
63 	switch (state) {
64 	case CONTINUE:
65 		return "CONTINUE";
66 	case RESULT_SUCCESS:
67 		return "RESULT_SUCCESS";
68 	case SUCCESS:
69 		return "SUCCESS";
70 	case FAILURE:
71 		return "FAILURE";
72 	default:
73 		return "?";
74 	}
75 }
76 #endif /* CONFIG_NO_STDOUT_DEBUG */
77 
78 
eap_aka_state(struct eap_aka_data * data,int state)79 static void eap_aka_state(struct eap_aka_data *data, int state)
80 {
81 	wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
82 		   eap_aka_state_txt(data->state),
83 		   eap_aka_state_txt(state));
84 	data->state = state;
85 }
86 
87 
eap_aka_init(struct eap_sm * sm)88 static void * eap_aka_init(struct eap_sm *sm)
89 {
90 	struct eap_aka_data *data;
91 	const char *phase1 = eap_get_config_phase1(sm);
92 	struct eap_peer_config *config = eap_get_config(sm);
93 
94 	data = os_zalloc(sizeof(*data));
95 	if (data == NULL)
96 		return NULL;
97 
98 	data->eap_method = EAP_TYPE_AKA;
99 
100 	eap_aka_state(data, CONTINUE);
101 	data->prev_id = -1;
102 
103 	data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL;
104 
105 	data->use_pseudonym = !sm->init_phase2;
106 	if (config && config->anonymous_identity && data->use_pseudonym) {
107 		data->pseudonym = os_malloc(config->anonymous_identity_len);
108 		if (data->pseudonym) {
109 			os_memcpy(data->pseudonym, config->anonymous_identity,
110 				  config->anonymous_identity_len);
111 			data->pseudonym_len = config->anonymous_identity_len;
112 		}
113 	}
114 
115 	return data;
116 }
117 
118 
119 #ifdef EAP_AKA_PRIME
eap_aka_prime_init(struct eap_sm * sm)120 static void * eap_aka_prime_init(struct eap_sm *sm)
121 {
122 	struct eap_aka_data *data = eap_aka_init(sm);
123 	if (data == NULL)
124 		return NULL;
125 	data->eap_method = EAP_TYPE_AKA_PRIME;
126 	return data;
127 }
128 #endif /* EAP_AKA_PRIME */
129 
130 
eap_aka_clear_keys(struct eap_aka_data * data,int reauth)131 static void eap_aka_clear_keys(struct eap_aka_data *data, int reauth)
132 {
133 	if (!reauth) {
134 		os_memset(data->mk, 0, EAP_SIM_MK_LEN);
135 		os_memset(data->k_aut, 0, EAP_AKA_PRIME_K_AUT_LEN);
136 		os_memset(data->k_encr, 0, EAP_SIM_K_ENCR_LEN);
137 		os_memset(data->k_re, 0, EAP_AKA_PRIME_K_RE_LEN);
138 	}
139 	os_memset(data->msk, 0, EAP_SIM_KEYING_DATA_LEN);
140 	os_memset(data->emsk, 0, EAP_EMSK_LEN);
141 	os_memset(data->autn, 0, EAP_AKA_AUTN_LEN);
142 	os_memset(data->auts, 0, EAP_AKA_AUTS_LEN);
143 }
144 
145 
eap_aka_deinit(struct eap_sm * sm,void * priv)146 static void eap_aka_deinit(struct eap_sm *sm, void *priv)
147 {
148 	struct eap_aka_data *data = priv;
149 	if (data) {
150 		os_free(data->pseudonym);
151 		os_free(data->reauth_id);
152 		os_free(data->last_eap_identity);
153 		wpabuf_free(data->id_msgs);
154 		os_free(data->network_name);
155 		eap_aka_clear_keys(data, 0);
156 		os_free(data);
157 	}
158 }
159 
160 
eap_aka_ext_sim_req(struct eap_sm * sm,struct eap_aka_data * data)161 static int eap_aka_ext_sim_req(struct eap_sm *sm, struct eap_aka_data *data)
162 {
163 	char req[200], *pos, *end;
164 
165 	wpa_printf(MSG_DEBUG, "EAP-AKA: Use external USIM processing");
166 	pos = req;
167 	end = pos + sizeof(req);
168 	pos += os_snprintf(pos, end - pos, "UMTS-AUTH");
169 	pos += os_snprintf(pos, end - pos, ":");
170 	pos += wpa_snprintf_hex(pos, end - pos, data->rand, EAP_AKA_RAND_LEN);
171 	pos += os_snprintf(pos, end - pos, ":");
172 	wpa_snprintf_hex(pos, end - pos, data->autn, EAP_AKA_AUTN_LEN);
173 
174 	eap_sm_request_sim(sm, req);
175 	return 1;
176 }
177 
178 
eap_aka_ext_sim_result(struct eap_sm * sm,struct eap_aka_data * data,struct eap_peer_config * conf)179 static int eap_aka_ext_sim_result(struct eap_sm *sm, struct eap_aka_data *data,
180 				  struct eap_peer_config *conf)
181 {
182 	char *resp, *pos;
183 
184 	wpa_printf(MSG_DEBUG,
185 		   "EAP-AKA: Use result from external USIM processing");
186 
187 	resp = conf->external_sim_resp;
188 	conf->external_sim_resp = NULL;
189 
190 	if (os_strncmp(resp, "UMTS-AUTS:", 10) == 0) {
191 		pos = resp + 10;
192 		if (hexstr2bin(pos, data->auts, EAP_AKA_AUTS_LEN) < 0)
193 			goto invalid;
194 		wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: AUTS", data->auts,
195 				EAP_AKA_AUTS_LEN);
196 		os_free(resp);
197 		return -2;
198 	}
199 
200 	if (os_strncmp(resp, "UMTS-AUTH:", 10) != 0) {
201 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized external USIM processing response");
202 		os_free(resp);
203 		return -1;
204 	}
205 
206 	pos = resp + 10;
207 	wpa_hexdump(MSG_DEBUG, "EAP-AKA: RAND", data->rand, EAP_AKA_RAND_LEN);
208 
209 	if (hexstr2bin(pos, data->ik, EAP_AKA_IK_LEN) < 0)
210 		goto invalid;
211 	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", data->ik, EAP_AKA_IK_LEN);
212 	pos += EAP_AKA_IK_LEN * 2;
213 	if (*pos != ':')
214 		goto invalid;
215 	pos++;
216 
217 	if (hexstr2bin(pos, data->ck, EAP_AKA_CK_LEN) < 0)
218 		goto invalid;
219 	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", data->ck, EAP_AKA_CK_LEN);
220 	pos += EAP_AKA_CK_LEN * 2;
221 	if (*pos != ':')
222 		goto invalid;
223 	pos++;
224 
225 	data->res_len = os_strlen(pos) / 2;
226 	if (data->res_len > EAP_AKA_RES_MAX_LEN) {
227 		data->res_len = 0;
228 		goto invalid;
229 	}
230 	if (hexstr2bin(pos, data->res, data->res_len) < 0)
231 		goto invalid;
232 	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: RES", data->res, data->res_len);
233 
234 	os_free(resp);
235 	return 0;
236 
237 invalid:
238 	wpa_printf(MSG_DEBUG, "EAP-AKA: Invalid external USIM processing UMTS-AUTH response");
239 	os_free(resp);
240 	return -1;
241 }
242 
243 
eap_aka_umts_auth(struct eap_sm * sm,struct eap_aka_data * data)244 static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data)
245 {
246 	struct eap_peer_config *conf;
247 
248 	wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm");
249 
250 	conf = eap_get_config(sm);
251 	if (conf == NULL)
252 		return -1;
253 
254 	if (sm->external_sim) {
255 		if (conf->external_sim_resp)
256 			return eap_aka_ext_sim_result(sm, data, conf);
257 		else
258 			return eap_aka_ext_sim_req(sm, data);
259 	}
260 
261 	if (conf->pcsc) {
262 		return scard_umts_auth(sm->scard_ctx, data->rand,
263 				       data->autn, data->res, &data->res_len,
264 				       data->ik, data->ck, data->auts);
265 	}
266 
267 #ifdef CONFIG_USIM_SIMULATOR
268 	if (conf->password) {
269 		u8 opc[16], k[16], sqn[6];
270 		const char *pos;
271 		wpa_printf(MSG_DEBUG, "EAP-AKA: Use internal Milenage "
272 			   "implementation for UMTS authentication");
273 		if (conf->password_len < 78) {
274 			wpa_printf(MSG_DEBUG, "EAP-AKA: invalid Milenage "
275 				   "password");
276 			return -1;
277 		}
278 		pos = (const char *) conf->password;
279 		if (hexstr2bin(pos, k, 16))
280 			return -1;
281 		pos += 32;
282 		if (*pos != ':')
283 			return -1;
284 		pos++;
285 
286 		if (hexstr2bin(pos, opc, 16))
287 			return -1;
288 		pos += 32;
289 		if (*pos != ':')
290 			return -1;
291 		pos++;
292 
293 		if (hexstr2bin(pos, sqn, 6))
294 			return -1;
295 
296 		return milenage_check(opc, k, sqn, data->rand, data->autn,
297 				      data->ik, data->ck,
298 				      data->res, &data->res_len, data->auts);
299 	}
300 #endif /* CONFIG_USIM_SIMULATOR */
301 
302 #ifdef CONFIG_USIM_HARDCODED
303 	wpa_printf(MSG_DEBUG, "EAP-AKA: Use hardcoded Kc and SRES values for "
304 		   "testing");
305 
306 	/* These hardcoded Kc and SRES values are used for testing.
307 	 * Could consider making them configurable. */
308 	os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN);
309 	data->res_len = EAP_AKA_RES_MAX_LEN;
310 	os_memset(data->ik, '3', EAP_AKA_IK_LEN);
311 	os_memset(data->ck, '4', EAP_AKA_CK_LEN);
312 	{
313 		u8 autn[EAP_AKA_AUTN_LEN];
314 		os_memset(autn, '1', EAP_AKA_AUTN_LEN);
315 		if (os_memcmp_const(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) {
316 			wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match "
317 				   "with expected value");
318 			return -1;
319 		}
320 	}
321 #if 0
322 	{
323 		static int test_resync = 1;
324 		if (test_resync) {
325 			/* Test Resynchronization */
326 			test_resync = 0;
327 			return -2;
328 		}
329 	}
330 #endif
331 	return 0;
332 
333 #else /* CONFIG_USIM_HARDCODED */
334 
335 	wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorithm "
336 		   "enabled");
337 	return -1;
338 
339 #endif /* CONFIG_USIM_HARDCODED */
340 }
341 
342 
343 #define CLEAR_PSEUDONYM	0x01
344 #define CLEAR_REAUTH_ID	0x02
345 #define CLEAR_EAP_ID	0x04
346 
eap_aka_clear_identities(struct eap_sm * sm,struct eap_aka_data * data,int id)347 static void eap_aka_clear_identities(struct eap_sm *sm,
348 				     struct eap_aka_data *data, int id)
349 {
350 	if ((id & CLEAR_PSEUDONYM) && data->pseudonym) {
351 		wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old pseudonym");
352 		os_free(data->pseudonym);
353 		data->pseudonym = NULL;
354 		data->pseudonym_len = 0;
355 		if (data->use_pseudonym)
356 			eap_set_anon_id(sm, NULL, 0);
357 	}
358 	if ((id & CLEAR_REAUTH_ID) && data->reauth_id) {
359 		wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old reauth_id");
360 		os_free(data->reauth_id);
361 		data->reauth_id = NULL;
362 		data->reauth_id_len = 0;
363 	}
364 	if ((id & CLEAR_EAP_ID) && data->last_eap_identity) {
365 		wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old eap_id");
366 		os_free(data->last_eap_identity);
367 		data->last_eap_identity = NULL;
368 		data->last_eap_identity_len = 0;
369 	}
370 }
371 
372 
eap_aka_learn_ids(struct eap_sm * sm,struct eap_aka_data * data,struct eap_sim_attrs * attr)373 static int eap_aka_learn_ids(struct eap_sm *sm, struct eap_aka_data *data,
374 			     struct eap_sim_attrs *attr)
375 {
376 	if (attr->next_pseudonym) {
377 		const u8 *identity = NULL;
378 		size_t identity_len = 0;
379 		const u8 *realm = NULL;
380 		size_t realm_len = 0;
381 
382 		wpa_hexdump_ascii(MSG_DEBUG,
383 				  "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
384 				  attr->next_pseudonym,
385 				  attr->next_pseudonym_len);
386 		os_free(data->pseudonym);
387 		/* Look for the realm of the permanent identity */
388 		identity = eap_get_config_identity(sm, &identity_len);
389 		if (identity) {
390 			for (realm = identity, realm_len = identity_len;
391 			     realm_len > 0; realm_len--, realm++) {
392 				if (*realm == '@')
393 					break;
394 			}
395 		}
396 		data->pseudonym = os_malloc(attr->next_pseudonym_len +
397 					    realm_len);
398 		if (data->pseudonym == NULL) {
399 			wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
400 				   "next pseudonym");
401 			data->pseudonym_len = 0;
402 			return -1;
403 		}
404 		os_memcpy(data->pseudonym, attr->next_pseudonym,
405 			  attr->next_pseudonym_len);
406 		if (realm_len) {
407 			os_memcpy(data->pseudonym + attr->next_pseudonym_len,
408 				  realm, realm_len);
409 		}
410 		data->pseudonym_len = attr->next_pseudonym_len + realm_len;
411 		if (data->use_pseudonym)
412 			eap_set_anon_id(sm, data->pseudonym,
413 					data->pseudonym_len);
414 	}
415 
416 	if (attr->next_reauth_id) {
417 		os_free(data->reauth_id);
418 		data->reauth_id = os_malloc(attr->next_reauth_id_len);
419 		if (data->reauth_id == NULL) {
420 			wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
421 				   "next reauth_id");
422 			data->reauth_id_len = 0;
423 			return -1;
424 		}
425 		os_memcpy(data->reauth_id, attr->next_reauth_id,
426 			  attr->next_reauth_id_len);
427 		data->reauth_id_len = attr->next_reauth_id_len;
428 		wpa_hexdump_ascii(MSG_DEBUG,
429 				  "EAP-AKA: (encr) AT_NEXT_REAUTH_ID",
430 				  data->reauth_id,
431 				  data->reauth_id_len);
432 	}
433 
434 	return 0;
435 }
436 
437 
eap_aka_add_id_msg(struct eap_aka_data * data,const struct wpabuf * msg)438 static int eap_aka_add_id_msg(struct eap_aka_data *data,
439 			      const struct wpabuf *msg)
440 {
441 	if (msg == NULL)
442 		return -1;
443 
444 	if (data->id_msgs == NULL) {
445 		data->id_msgs = wpabuf_dup(msg);
446 		return data->id_msgs == NULL ? -1 : 0;
447 	}
448 
449 	if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
450 		return -1;
451 	wpabuf_put_buf(data->id_msgs, msg);
452 
453 	return 0;
454 }
455 
456 
eap_aka_add_checkcode(struct eap_aka_data * data,struct eap_sim_msg * msg)457 static void eap_aka_add_checkcode(struct eap_aka_data *data,
458 				  struct eap_sim_msg *msg)
459 {
460 	const u8 *addr;
461 	size_t len;
462 	u8 hash[SHA256_MAC_LEN];
463 
464 	wpa_printf(MSG_DEBUG, "   AT_CHECKCODE");
465 
466 	if (data->id_msgs == NULL) {
467 		/*
468 		 * No EAP-AKA/Identity packets were exchanged - send empty
469 		 * checkcode.
470 		 */
471 		eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
472 		return;
473 	}
474 
475 	/* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */
476 	addr = wpabuf_head(data->id_msgs);
477 	len = wpabuf_len(data->id_msgs);
478 	wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
479 #ifdef EAP_AKA_PRIME
480 	if (data->eap_method == EAP_TYPE_AKA_PRIME)
481 		sha256_vector(1, &addr, &len, hash);
482 	else
483 #endif /* EAP_AKA_PRIME */
484 		sha1_vector(1, &addr, &len, hash);
485 
486 	eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
487 			data->eap_method == EAP_TYPE_AKA_PRIME ?
488 			EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
489 }
490 
491 
eap_aka_verify_checkcode(struct eap_aka_data * data,const u8 * checkcode,size_t checkcode_len)492 static int eap_aka_verify_checkcode(struct eap_aka_data *data,
493 				    const u8 *checkcode, size_t checkcode_len)
494 {
495 	const u8 *addr;
496 	size_t len;
497 	u8 hash[SHA256_MAC_LEN];
498 	size_t hash_len;
499 
500 	if (checkcode == NULL)
501 		return -1;
502 
503 	if (data->id_msgs == NULL) {
504 		if (checkcode_len != 0) {
505 			wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server "
506 				   "indicates that AKA/Identity messages were "
507 				   "used, but they were not");
508 			return -1;
509 		}
510 		return 0;
511 	}
512 
513 	hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ?
514 		EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN;
515 
516 	if (checkcode_len != hash_len) {
517 		wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server "
518 			   "indicates that AKA/Identity message were not "
519 			   "used, but they were");
520 		return -1;
521 	}
522 
523 	/* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */
524 	addr = wpabuf_head(data->id_msgs);
525 	len = wpabuf_len(data->id_msgs);
526 #ifdef EAP_AKA_PRIME
527 	if (data->eap_method == EAP_TYPE_AKA_PRIME)
528 		sha256_vector(1, &addr, &len, hash);
529 	else
530 #endif /* EAP_AKA_PRIME */
531 		sha1_vector(1, &addr, &len, hash);
532 
533 	if (os_memcmp_const(hash, checkcode, hash_len) != 0) {
534 		wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
535 		return -1;
536 	}
537 
538 	return 0;
539 }
540 
541 
eap_aka_client_error(struct eap_aka_data * data,u8 id,int err)542 static struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id,
543 					    int err)
544 {
545 	struct eap_sim_msg *msg;
546 
547 	eap_aka_state(data, FAILURE);
548 	data->num_id_req = 0;
549 	data->num_notification = 0;
550 
551 	wpa_printf(MSG_DEBUG, "EAP-AKA: Send Client-Error (error code %d)",
552 		   err);
553 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
554 			       EAP_AKA_SUBTYPE_CLIENT_ERROR);
555 	eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
556 	return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
557 }
558 
559 
eap_aka_authentication_reject(struct eap_aka_data * data,u8 id)560 static struct wpabuf * eap_aka_authentication_reject(struct eap_aka_data *data,
561 						     u8 id)
562 {
563 	struct eap_sim_msg *msg;
564 
565 	eap_aka_state(data, FAILURE);
566 	data->num_id_req = 0;
567 	data->num_notification = 0;
568 
569 	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject "
570 		   "(id=%d)", id);
571 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
572 			       EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT);
573 	return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
574 }
575 
576 
eap_aka_synchronization_failure(struct eap_aka_data * data,u8 id)577 static struct wpabuf * eap_aka_synchronization_failure(
578 	struct eap_aka_data *data, u8 id)
579 {
580 	struct eap_sim_msg *msg;
581 
582 	data->num_id_req = 0;
583 	data->num_notification = 0;
584 
585 	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure "
586 		   "(id=%d)", id);
587 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
588 			       EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE);
589 	wpa_printf(MSG_DEBUG, "   AT_AUTS");
590 	eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts,
591 			     EAP_AKA_AUTS_LEN);
592 	return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
593 }
594 
595 
eap_aka_response_identity(struct eap_sm * sm,struct eap_aka_data * data,u8 id,enum eap_sim_id_req id_req)596 static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm,
597 						 struct eap_aka_data *data,
598 						 u8 id,
599 						 enum eap_sim_id_req id_req)
600 {
601 	const u8 *identity = NULL;
602 	size_t identity_len = 0;
603 	struct eap_sim_msg *msg;
604 
605 	data->reauth = 0;
606 	if (id_req == ANY_ID && data->reauth_id) {
607 		identity = data->reauth_id;
608 		identity_len = data->reauth_id_len;
609 		data->reauth = 1;
610 	} else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
611 		   data->pseudonym) {
612 		identity = data->pseudonym;
613 		identity_len = data->pseudonym_len;
614 		eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID);
615 	} else if (id_req != NO_ID_REQ) {
616 		identity = eap_get_config_identity(sm, &identity_len);
617 		if (identity) {
618 			eap_aka_clear_identities(sm, data, CLEAR_PSEUDONYM |
619 						 CLEAR_REAUTH_ID);
620 		}
621 	}
622 	if (id_req != NO_ID_REQ)
623 		eap_aka_clear_identities(sm, data, CLEAR_EAP_ID);
624 
625 	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id);
626 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
627 			       EAP_AKA_SUBTYPE_IDENTITY);
628 
629 	if (identity) {
630 		wpa_hexdump_ascii(MSG_DEBUG, "   AT_IDENTITY",
631 				  identity, identity_len);
632 		eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
633 				identity, identity_len);
634 	}
635 
636 	return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
637 }
638 
639 
eap_aka_response_challenge(struct eap_aka_data * data,u8 id)640 static struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data,
641 						  u8 id)
642 {
643 	struct eap_sim_msg *msg;
644 
645 	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id);
646 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
647 			       EAP_AKA_SUBTYPE_CHALLENGE);
648 	wpa_printf(MSG_DEBUG, "   AT_RES");
649 	eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8,
650 			data->res, data->res_len);
651 	eap_aka_add_checkcode(data, msg);
652 	if (data->use_result_ind) {
653 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
654 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
655 	}
656 	wpa_printf(MSG_DEBUG, "   AT_MAC");
657 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
658 	return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, (u8 *) "",
659 				  0);
660 }
661 
662 
eap_aka_response_reauth(struct eap_aka_data * data,u8 id,int counter_too_small,const u8 * nonce_s)663 static struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data,
664 					       u8 id, int counter_too_small,
665 					       const u8 *nonce_s)
666 {
667 	struct eap_sim_msg *msg;
668 	unsigned int counter;
669 
670 	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)",
671 		   id);
672 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
673 			       EAP_AKA_SUBTYPE_REAUTHENTICATION);
674 	wpa_printf(MSG_DEBUG, "   AT_IV");
675 	wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
676 	eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
677 
678 	if (counter_too_small) {
679 		wpa_printf(MSG_DEBUG, "   *AT_COUNTER_TOO_SMALL");
680 		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
681 		counter = data->counter_too_small;
682 	} else
683 		counter = data->counter;
684 
685 	wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", counter);
686 	eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
687 
688 	if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
689 		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
690 			   "AT_ENCR_DATA");
691 		eap_sim_msg_free(msg);
692 		return NULL;
693 	}
694 	eap_aka_add_checkcode(data, msg);
695 	if (data->use_result_ind) {
696 		wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
697 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
698 	}
699 	wpa_printf(MSG_DEBUG, "   AT_MAC");
700 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
701 	return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, nonce_s,
702 				  EAP_SIM_NONCE_S_LEN);
703 }
704 
705 
eap_aka_response_notification(struct eap_aka_data * data,u8 id,u16 notification)706 static struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data,
707 						     u8 id, u16 notification)
708 {
709 	struct eap_sim_msg *msg;
710 	u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
711 
712 	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id);
713 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
714 			       EAP_AKA_SUBTYPE_NOTIFICATION);
715 	if (k_aut && data->reauth) {
716 		wpa_printf(MSG_DEBUG, "   AT_IV");
717 		wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
718 		eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
719 					   EAP_SIM_AT_ENCR_DATA);
720 		wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", data->counter);
721 		eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
722 				NULL, 0);
723 		if (eap_sim_msg_add_encr_end(msg, data->k_encr,
724 					     EAP_SIM_AT_PADDING)) {
725 			wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
726 				   "AT_ENCR_DATA");
727 			eap_sim_msg_free(msg);
728 			return NULL;
729 		}
730 	}
731 	if (k_aut) {
732 		wpa_printf(MSG_DEBUG, "   AT_MAC");
733 		eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
734 	}
735 	return eap_sim_msg_finish(msg, data->eap_method, k_aut, (u8 *) "", 0);
736 }
737 
738 
eap_aka_process_identity(struct eap_sm * sm,struct eap_aka_data * data,u8 id,const struct wpabuf * reqData,struct eap_sim_attrs * attr)739 static struct wpabuf * eap_aka_process_identity(struct eap_sm *sm,
740 						struct eap_aka_data *data,
741 						u8 id,
742 						const struct wpabuf *reqData,
743 						struct eap_sim_attrs *attr)
744 {
745 	int id_error;
746 	struct wpabuf *buf;
747 
748 	wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity");
749 
750 	id_error = 0;
751 	switch (attr->id_req) {
752 	case NO_ID_REQ:
753 		break;
754 	case ANY_ID:
755 		if (data->num_id_req > 0)
756 			id_error++;
757 		data->num_id_req++;
758 		break;
759 	case FULLAUTH_ID:
760 		if (data->num_id_req > 1)
761 			id_error++;
762 		data->num_id_req++;
763 		break;
764 	case PERMANENT_ID:
765 		if (data->num_id_req > 2)
766 			id_error++;
767 		data->num_id_req++;
768 		break;
769 	}
770 	if (id_error) {
771 		wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests "
772 			   "used within one authentication");
773 		return eap_aka_client_error(data, id,
774 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
775 	}
776 
777 	buf = eap_aka_response_identity(sm, data, id, attr->id_req);
778 
779 	if (data->prev_id != id) {
780 		eap_aka_add_id_msg(data, reqData);
781 		eap_aka_add_id_msg(data, buf);
782 		data->prev_id = id;
783 	}
784 
785 	return buf;
786 }
787 
788 
eap_aka_verify_mac(struct eap_aka_data * data,const struct wpabuf * req,const u8 * mac,const u8 * extra,size_t extra_len)789 static int eap_aka_verify_mac(struct eap_aka_data *data,
790 			      const struct wpabuf *req,
791 			      const u8 *mac, const u8 *extra,
792 			      size_t extra_len)
793 {
794 	if (data->eap_method == EAP_TYPE_AKA_PRIME)
795 		return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
796 						 extra_len);
797 	return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
798 }
799 
800 
801 #ifdef EAP_AKA_PRIME
eap_aka_prime_kdf_select(struct eap_aka_data * data,u8 id,u16 kdf)802 static struct wpabuf * eap_aka_prime_kdf_select(struct eap_aka_data *data,
803 						u8 id, u16 kdf)
804 {
805 	struct eap_sim_msg *msg;
806 
807 	data->kdf_negotiation = 1;
808 	data->kdf = kdf;
809 	wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d) (KDF "
810 		   "select)", id);
811 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
812 			       EAP_AKA_SUBTYPE_CHALLENGE);
813 	wpa_printf(MSG_DEBUG, "   AT_KDF");
814 	eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0);
815 	return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
816 }
817 
818 
eap_aka_prime_kdf_neg(struct eap_aka_data * data,u8 id,struct eap_sim_attrs * attr)819 static struct wpabuf * eap_aka_prime_kdf_neg(struct eap_aka_data *data,
820 					     u8 id, struct eap_sim_attrs *attr)
821 {
822 	size_t i;
823 
824 	for (i = 0; i < attr->kdf_count; i++) {
825 		if (attr->kdf[i] == EAP_AKA_PRIME_KDF)
826 			return eap_aka_prime_kdf_select(data, id,
827 							EAP_AKA_PRIME_KDF);
828 	}
829 
830 	/* No matching KDF found - fail authentication as if AUTN had been
831 	 * incorrect */
832 	return eap_aka_authentication_reject(data, id);
833 }
834 
835 
eap_aka_prime_kdf_valid(struct eap_aka_data * data,struct eap_sim_attrs * attr)836 static int eap_aka_prime_kdf_valid(struct eap_aka_data *data,
837 				   struct eap_sim_attrs *attr)
838 {
839 	size_t i, j;
840 
841 	if (attr->kdf_count == 0)
842 		return 0;
843 
844 	/* The only allowed (and required) duplication of a KDF is the addition
845 	 * of the selected KDF into the beginning of the list. */
846 
847 	if (data->kdf_negotiation) {
848 		if (attr->kdf[0] != data->kdf) {
849 			wpa_printf(MSG_WARNING, "EAP-AKA': The server did not "
850 				   "accept the selected KDF");
851 			return 0;
852 		}
853 
854 		for (i = 1; i < attr->kdf_count; i++) {
855 			if (attr->kdf[i] == data->kdf)
856 				break;
857 		}
858 		if (i == attr->kdf_count &&
859 		    attr->kdf_count < EAP_AKA_PRIME_KDF_MAX) {
860 			wpa_printf(MSG_WARNING, "EAP-AKA': The server did not "
861 				   "duplicate the selected KDF");
862 			return 0;
863 		}
864 
865 		/* TODO: should check that the list is identical to the one
866 		 * used in the previous Challenge message apart from the added
867 		 * entry in the beginning. */
868 	}
869 
870 	for (i = data->kdf ? 1 : 0; i < attr->kdf_count; i++) {
871 		for (j = i + 1; j < attr->kdf_count; j++) {
872 			if (attr->kdf[i] == attr->kdf[j]) {
873 				wpa_printf(MSG_WARNING, "EAP-AKA': The server "
874 					   "included a duplicated KDF");
875 				return 0;
876 			}
877 		}
878 	}
879 
880 	return 1;
881 }
882 #endif /* EAP_AKA_PRIME */
883 
884 
eap_aka_process_challenge(struct eap_sm * sm,struct eap_aka_data * data,u8 id,const struct wpabuf * reqData,struct eap_sim_attrs * attr)885 static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm,
886 						 struct eap_aka_data *data,
887 						 u8 id,
888 						 const struct wpabuf *reqData,
889 						 struct eap_sim_attrs *attr)
890 {
891 	const u8 *identity;
892 	size_t identity_len;
893 	int res;
894 	struct eap_sim_attrs eattr;
895 
896 	wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge");
897 
898 	if (attr->checkcode &&
899 	    eap_aka_verify_checkcode(data, attr->checkcode,
900 				     attr->checkcode_len)) {
901 		wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
902 			   "message");
903 		return eap_aka_client_error(data, id,
904 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
905 	}
906 
907 #ifdef EAP_AKA_PRIME
908 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
909 		if (!attr->kdf_input || attr->kdf_input_len == 0) {
910 			wpa_printf(MSG_WARNING, "EAP-AKA': Challenge message "
911 				   "did not include non-empty AT_KDF_INPUT");
912 			/* Fail authentication as if AUTN had been incorrect */
913 			return eap_aka_authentication_reject(data, id);
914 		}
915 		os_free(data->network_name);
916 		data->network_name = os_malloc(attr->kdf_input_len);
917 		if (data->network_name == NULL) {
918 			wpa_printf(MSG_WARNING, "EAP-AKA': No memory for "
919 				   "storing Network Name");
920 			return eap_aka_authentication_reject(data, id);
921 		}
922 		os_memcpy(data->network_name, attr->kdf_input,
923 			  attr->kdf_input_len);
924 		data->network_name_len = attr->kdf_input_len;
925 		wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': Network Name "
926 				  "(AT_KDF_INPUT)",
927 				  data->network_name, data->network_name_len);
928 		/* TODO: check Network Name per 3GPP.33.402 */
929 
930 		if (!eap_aka_prime_kdf_valid(data, attr))
931 			return eap_aka_authentication_reject(data, id);
932 
933 		if (attr->kdf[0] != EAP_AKA_PRIME_KDF)
934 			return eap_aka_prime_kdf_neg(data, id, attr);
935 
936 		data->kdf = EAP_AKA_PRIME_KDF;
937 		wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
938 	}
939 
940 	if (data->eap_method == EAP_TYPE_AKA && attr->bidding) {
941 		u16 flags = WPA_GET_BE16(attr->bidding);
942 		if ((flags & EAP_AKA_BIDDING_FLAG_D) &&
943 		    eap_allowed_method(sm, EAP_VENDOR_IETF,
944 				       EAP_TYPE_AKA_PRIME)) {
945 			wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from "
946 				   "AKA' to AKA detected");
947 			/* Fail authentication as if AUTN had been incorrect */
948 			return eap_aka_authentication_reject(data, id);
949 		}
950 	}
951 #endif /* EAP_AKA_PRIME */
952 
953 	data->reauth = 0;
954 	if (!attr->mac || !attr->rand || !attr->autn) {
955 		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
956 			   "did not include%s%s%s",
957 			   !attr->mac ? " AT_MAC" : "",
958 			   !attr->rand ? " AT_RAND" : "",
959 			   !attr->autn ? " AT_AUTN" : "");
960 		return eap_aka_client_error(data, id,
961 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
962 	}
963 	os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN);
964 	os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN);
965 
966 	res = eap_aka_umts_auth(sm, data);
967 	if (res == -1) {
968 		wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
969 			   "failed (AUTN)");
970 		return eap_aka_authentication_reject(data, id);
971 	} else if (res == -2) {
972 		wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
973 			   "failed (AUTN seq# -> AUTS)");
974 		return eap_aka_synchronization_failure(data, id);
975 	} else if (res > 0) {
976 		wpa_printf(MSG_DEBUG, "EAP-AKA: Wait for external USIM processing");
977 		return NULL;
978 	} else if (res) {
979 		wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed");
980 		return eap_aka_client_error(data, id,
981 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
982 	}
983 #ifdef EAP_AKA_PRIME
984 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
985 		/* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
986 		 * needed 6-octet SQN ^ AK for CK',IK' derivation */
987 		u16 amf = WPA_GET_BE16(data->autn + 6);
988 		if (!(amf & 0x8000)) {
989 			wpa_printf(MSG_WARNING, "EAP-AKA': AMF separation bit "
990 				   "not set (AMF=0x%4x)", amf);
991 			return eap_aka_authentication_reject(data, id);
992 		}
993 		eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
994 						 data->autn,
995 						 data->network_name,
996 						 data->network_name_len);
997 	}
998 #endif /* EAP_AKA_PRIME */
999 	if (data->last_eap_identity) {
1000 		identity = data->last_eap_identity;
1001 		identity_len = data->last_eap_identity_len;
1002 	} else if (data->pseudonym) {
1003 		identity = data->pseudonym;
1004 		identity_len = data->pseudonym_len;
1005 	} else
1006 		identity = eap_get_config_identity(sm, &identity_len);
1007 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
1008 			  "derivation", identity, identity_len);
1009 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1010 		eap_aka_prime_derive_keys(identity, identity_len, data->ik,
1011 					  data->ck, data->k_encr, data->k_aut,
1012 					  data->k_re, data->msk, data->emsk);
1013 	} else {
1014 		eap_aka_derive_mk(identity, identity_len, data->ik, data->ck,
1015 				  data->mk);
1016 		eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
1017 				    data->msk, data->emsk);
1018 	}
1019 	if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
1020 		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
1021 			   "used invalid AT_MAC");
1022 		return eap_aka_client_error(data, id,
1023 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1024 	}
1025 
1026 	/* Old reauthentication identity must not be used anymore. In
1027 	 * other words, if no new identities are received, full
1028 	 * authentication will be used on next reauthentication (using
1029 	 * pseudonym identity or permanent identity). */
1030 	eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1031 
1032 	if (attr->encr_data) {
1033 		u8 *decrypted;
1034 		decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1035 					       attr->encr_data_len, attr->iv,
1036 					       &eattr, 0);
1037 		if (decrypted == NULL) {
1038 			return eap_aka_client_error(
1039 				data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1040 		}
1041 		eap_aka_learn_ids(sm, data, &eattr);
1042 		os_free(decrypted);
1043 	}
1044 
1045 	if (data->result_ind && attr->result_ind)
1046 		data->use_result_ind = 1;
1047 
1048 	if (data->state != FAILURE) {
1049 		eap_aka_state(data, data->use_result_ind ?
1050 			      RESULT_SUCCESS : SUCCESS);
1051 	}
1052 
1053 	data->num_id_req = 0;
1054 	data->num_notification = 0;
1055 	/* RFC 4187 specifies that counter is initialized to one after
1056 	 * fullauth, but initializing it to zero makes it easier to implement
1057 	 * reauth verification. */
1058 	data->counter = 0;
1059 	return eap_aka_response_challenge(data, id);
1060 }
1061 
1062 
eap_aka_process_notification_reauth(struct eap_aka_data * data,struct eap_sim_attrs * attr)1063 static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
1064 					       struct eap_sim_attrs *attr)
1065 {
1066 	struct eap_sim_attrs eattr;
1067 	u8 *decrypted;
1068 
1069 	if (attr->encr_data == NULL || attr->iv == NULL) {
1070 		wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after "
1071 			   "reauth did not include encrypted data");
1072 		return -1;
1073 	}
1074 
1075 	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1076 				       attr->encr_data_len, attr->iv, &eattr,
1077 				       0);
1078 	if (decrypted == NULL) {
1079 		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
1080 			   "data from notification message");
1081 		return -1;
1082 	}
1083 
1084 	if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
1085 		wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification "
1086 			   "message does not match with counter in reauth "
1087 			   "message");
1088 		os_free(decrypted);
1089 		return -1;
1090 	}
1091 
1092 	os_free(decrypted);
1093 	return 0;
1094 }
1095 
1096 
eap_aka_process_notification_auth(struct eap_aka_data * data,const struct wpabuf * reqData,struct eap_sim_attrs * attr)1097 static int eap_aka_process_notification_auth(struct eap_aka_data *data,
1098 					     const struct wpabuf *reqData,
1099 					     struct eap_sim_attrs *attr)
1100 {
1101 	if (attr->mac == NULL) {
1102 		wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth "
1103 			   "Notification message");
1104 		return -1;
1105 	}
1106 
1107 	if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
1108 		wpa_printf(MSG_WARNING, "EAP-AKA: Notification message "
1109 			   "used invalid AT_MAC");
1110 		return -1;
1111 	}
1112 
1113 	if (data->reauth &&
1114 	    eap_aka_process_notification_reauth(data, attr)) {
1115 		wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification "
1116 			   "message after reauth");
1117 		return -1;
1118 	}
1119 
1120 	return 0;
1121 }
1122 
1123 
eap_aka_process_notification(struct eap_sm * sm,struct eap_aka_data * data,u8 id,const struct wpabuf * reqData,struct eap_sim_attrs * attr)1124 static struct wpabuf * eap_aka_process_notification(
1125 	struct eap_sm *sm, struct eap_aka_data *data, u8 id,
1126 	const struct wpabuf *reqData, struct eap_sim_attrs *attr)
1127 {
1128 	wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification");
1129 	if (data->num_notification > 0) {
1130 		wpa_printf(MSG_INFO, "EAP-AKA: too many notification "
1131 			   "rounds (only one allowed)");
1132 		return eap_aka_client_error(data, id,
1133 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1134 	}
1135 	data->num_notification++;
1136 	if (attr->notification == -1) {
1137 		wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in "
1138 			   "Notification message");
1139 		return eap_aka_client_error(data, id,
1140 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1141 	}
1142 
1143 	if ((attr->notification & 0x4000) == 0 &&
1144 	    eap_aka_process_notification_auth(data, reqData, attr)) {
1145 		return eap_aka_client_error(data, id,
1146 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1147 	}
1148 
1149 	eap_sim_report_notification(sm->msg_ctx, attr->notification, 1);
1150 	if (attr->notification >= 0 && attr->notification < 32768) {
1151 		eap_aka_state(data, FAILURE);
1152 	} else if (attr->notification == EAP_SIM_SUCCESS &&
1153 		   data->state == RESULT_SUCCESS)
1154 		eap_aka_state(data, SUCCESS);
1155 	return eap_aka_response_notification(data, id, attr->notification);
1156 }
1157 
1158 
eap_aka_process_reauthentication(struct eap_sm * sm,struct eap_aka_data * data,u8 id,const struct wpabuf * reqData,struct eap_sim_attrs * attr)1159 static struct wpabuf * eap_aka_process_reauthentication(
1160 	struct eap_sm *sm, struct eap_aka_data *data, u8 id,
1161 	const struct wpabuf *reqData, struct eap_sim_attrs *attr)
1162 {
1163 	struct eap_sim_attrs eattr;
1164 	u8 *decrypted;
1165 
1166 	wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication");
1167 
1168 	if (attr->checkcode &&
1169 	    eap_aka_verify_checkcode(data, attr->checkcode,
1170 				     attr->checkcode_len)) {
1171 		wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
1172 			   "message");
1173 		return eap_aka_client_error(data, id,
1174 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1175 	}
1176 
1177 	if (data->reauth_id == NULL) {
1178 		wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying "
1179 			   "reauthentication, but no reauth_id available");
1180 		return eap_aka_client_error(data, id,
1181 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1182 	}
1183 
1184 	data->reauth = 1;
1185 	if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
1186 		wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
1187 			   "did not have valid AT_MAC");
1188 		return eap_aka_client_error(data, id,
1189 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1190 	}
1191 
1192 	if (attr->encr_data == NULL || attr->iv == NULL) {
1193 		wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
1194 			   "message did not include encrypted data");
1195 		return eap_aka_client_error(data, id,
1196 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1197 	}
1198 
1199 	decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1200 				       attr->encr_data_len, attr->iv, &eattr,
1201 				       0);
1202 	if (decrypted == NULL) {
1203 		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
1204 			   "data from reauthentication message");
1205 		return eap_aka_client_error(data, id,
1206 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1207 	}
1208 
1209 	if (eattr.nonce_s == NULL || eattr.counter < 0) {
1210 		wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet",
1211 			   !eattr.nonce_s ? " AT_NONCE_S" : "",
1212 			   eattr.counter < 0 ? " AT_COUNTER" : "");
1213 		os_free(decrypted);
1214 		return eap_aka_client_error(data, id,
1215 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1216 	}
1217 
1218 	if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
1219 		struct wpabuf *res;
1220 		wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter "
1221 			   "(%d <= %d)", eattr.counter, data->counter);
1222 		data->counter_too_small = eattr.counter;
1223 
1224 		/* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
1225 		 * reauth_id must not be used to start a new reauthentication.
1226 		 * However, since it was used in the last EAP-Response-Identity
1227 		 * packet, it has to saved for the following fullauth to be
1228 		 * used in MK derivation. */
1229 		os_free(data->last_eap_identity);
1230 		data->last_eap_identity = data->reauth_id;
1231 		data->last_eap_identity_len = data->reauth_id_len;
1232 		data->reauth_id = NULL;
1233 		data->reauth_id_len = 0;
1234 
1235 		res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s);
1236 		os_free(decrypted);
1237 
1238 		return res;
1239 	}
1240 	data->counter = eattr.counter;
1241 
1242 	os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
1243 	wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S",
1244 		    data->nonce_s, EAP_SIM_NONCE_S_LEN);
1245 
1246 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1247 		eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
1248 						 data->reauth_id,
1249 						 data->reauth_id_len,
1250 						 data->nonce_s,
1251 						 data->msk, data->emsk);
1252 	} else {
1253 		eap_sim_derive_keys_reauth(data->counter, data->reauth_id,
1254 					   data->reauth_id_len,
1255 					   data->nonce_s, data->mk,
1256 					   data->msk, data->emsk);
1257 	}
1258 	eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1259 	eap_aka_learn_ids(sm, data, &eattr);
1260 
1261 	if (data->result_ind && attr->result_ind)
1262 		data->use_result_ind = 1;
1263 
1264 	if (data->state != FAILURE) {
1265 		eap_aka_state(data, data->use_result_ind ?
1266 			      RESULT_SUCCESS : SUCCESS);
1267 	}
1268 
1269 	data->num_id_req = 0;
1270 	data->num_notification = 0;
1271 	if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) {
1272 		wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of "
1273 			   "fast reauths performed - force fullauth");
1274 		eap_aka_clear_identities(sm, data,
1275 					 CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1276 	}
1277 	os_free(decrypted);
1278 	return eap_aka_response_reauth(data, id, 0, data->nonce_s);
1279 }
1280 
1281 
eap_aka_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)1282 static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv,
1283 				       struct eap_method_ret *ret,
1284 				       const struct wpabuf *reqData)
1285 {
1286 	struct eap_aka_data *data = priv;
1287 	const struct eap_hdr *req;
1288 	u8 subtype, id;
1289 	struct wpabuf *res;
1290 	const u8 *pos;
1291 	struct eap_sim_attrs attr;
1292 	size_t len;
1293 
1294 	wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData);
1295 	if (eap_get_config_identity(sm, &len) == NULL) {
1296 		wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured");
1297 		eap_sm_request_identity(sm);
1298 		ret->ignore = TRUE;
1299 		return NULL;
1300 	}
1301 
1302 	pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData,
1303 			       &len);
1304 	if (pos == NULL || len < 3) {
1305 		ret->ignore = TRUE;
1306 		return NULL;
1307 	}
1308 	req = wpabuf_head(reqData);
1309 	id = req->identifier;
1310 	len = be_to_host16(req->length);
1311 
1312 	ret->ignore = FALSE;
1313 	ret->methodState = METHOD_MAY_CONT;
1314 	ret->decision = DECISION_FAIL;
1315 	ret->allowNotifications = TRUE;
1316 
1317 	subtype = *pos++;
1318 	wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype);
1319 	pos += 2; /* Reserved */
1320 
1321 	if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr,
1322 			       data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
1323 			       0)) {
1324 		res = eap_aka_client_error(data, id,
1325 					   EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1326 		goto done;
1327 	}
1328 
1329 	switch (subtype) {
1330 	case EAP_AKA_SUBTYPE_IDENTITY:
1331 		res = eap_aka_process_identity(sm, data, id, reqData, &attr);
1332 		break;
1333 	case EAP_AKA_SUBTYPE_CHALLENGE:
1334 		res = eap_aka_process_challenge(sm, data, id, reqData, &attr);
1335 		break;
1336 	case EAP_AKA_SUBTYPE_NOTIFICATION:
1337 		res = eap_aka_process_notification(sm, data, id, reqData,
1338 						   &attr);
1339 		break;
1340 	case EAP_AKA_SUBTYPE_REAUTHENTICATION:
1341 		res = eap_aka_process_reauthentication(sm, data, id, reqData,
1342 						       &attr);
1343 		break;
1344 	case EAP_AKA_SUBTYPE_CLIENT_ERROR:
1345 		wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error");
1346 		res = eap_aka_client_error(data, id,
1347 					   EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1348 		break;
1349 	default:
1350 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype);
1351 		res = eap_aka_client_error(data, id,
1352 					   EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1353 		break;
1354 	}
1355 
1356 done:
1357 	if (data->state == FAILURE) {
1358 		ret->decision = DECISION_FAIL;
1359 		ret->methodState = METHOD_DONE;
1360 	} else if (data->state == SUCCESS) {
1361 		ret->decision = data->use_result_ind ?
1362 			DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
1363 		/*
1364 		 * It is possible for the server to reply with AKA
1365 		 * Notification, so we must allow the method to continue and
1366 		 * not only accept EAP-Success at this point.
1367 		 */
1368 		ret->methodState = data->use_result_ind ?
1369 			METHOD_DONE : METHOD_MAY_CONT;
1370 	} else if (data->state == RESULT_SUCCESS)
1371 		ret->methodState = METHOD_CONT;
1372 
1373 	if (ret->methodState == METHOD_DONE) {
1374 		ret->allowNotifications = FALSE;
1375 	}
1376 
1377 	return res;
1378 }
1379 
1380 
eap_aka_has_reauth_data(struct eap_sm * sm,void * priv)1381 static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv)
1382 {
1383 	struct eap_aka_data *data = priv;
1384 	return data->pseudonym || data->reauth_id;
1385 }
1386 
1387 
eap_aka_deinit_for_reauth(struct eap_sm * sm,void * priv)1388 static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv)
1389 {
1390 	struct eap_aka_data *data = priv;
1391 	eap_aka_clear_identities(sm, data, CLEAR_EAP_ID);
1392 	data->prev_id = -1;
1393 	wpabuf_free(data->id_msgs);
1394 	data->id_msgs = NULL;
1395 	data->use_result_ind = 0;
1396 	data->kdf_negotiation = 0;
1397 	eap_aka_clear_keys(data, 1);
1398 }
1399 
1400 
eap_aka_init_for_reauth(struct eap_sm * sm,void * priv)1401 static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv)
1402 {
1403 	struct eap_aka_data *data = priv;
1404 	data->num_id_req = 0;
1405 	data->num_notification = 0;
1406 	eap_aka_state(data, CONTINUE);
1407 	return priv;
1408 }
1409 
1410 
eap_aka_get_identity(struct eap_sm * sm,void * priv,size_t * len)1411 static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv,
1412 				       size_t *len)
1413 {
1414 	struct eap_aka_data *data = priv;
1415 
1416 	if (data->reauth_id) {
1417 		*len = data->reauth_id_len;
1418 		return data->reauth_id;
1419 	}
1420 
1421 	if (data->pseudonym) {
1422 		*len = data->pseudonym_len;
1423 		return data->pseudonym;
1424 	}
1425 
1426 	return NULL;
1427 }
1428 
1429 
eap_aka_isKeyAvailable(struct eap_sm * sm,void * priv)1430 static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv)
1431 {
1432 	struct eap_aka_data *data = priv;
1433 	return data->state == SUCCESS;
1434 }
1435 
1436 
eap_aka_getKey(struct eap_sm * sm,void * priv,size_t * len)1437 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
1438 {
1439 	struct eap_aka_data *data = priv;
1440 	u8 *key;
1441 
1442 	if (data->state != SUCCESS)
1443 		return NULL;
1444 
1445 	key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
1446 	if (key == NULL)
1447 		return NULL;
1448 
1449 	*len = EAP_SIM_KEYING_DATA_LEN;
1450 	os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
1451 
1452 	return key;
1453 }
1454 
1455 
eap_aka_get_session_id(struct eap_sm * sm,void * priv,size_t * len)1456 static u8 * eap_aka_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1457 {
1458 	struct eap_aka_data *data = priv;
1459 	u8 *id;
1460 
1461 	if (data->state != SUCCESS)
1462 		return NULL;
1463 
1464 	*len = 1 + EAP_AKA_RAND_LEN + EAP_AKA_AUTN_LEN;
1465 	id = os_malloc(*len);
1466 	if (id == NULL)
1467 		return NULL;
1468 
1469 	id[0] = data->eap_method;
1470 	os_memcpy(id + 1, data->rand, EAP_AKA_RAND_LEN);
1471 	os_memcpy(id + 1 + EAP_AKA_RAND_LEN, data->autn, EAP_AKA_AUTN_LEN);
1472 	wpa_hexdump(MSG_DEBUG, "EAP-AKA: Derived Session-Id", id, *len);
1473 
1474 	return id;
1475 }
1476 
1477 
eap_aka_get_emsk(struct eap_sm * sm,void * priv,size_t * len)1478 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1479 {
1480 	struct eap_aka_data *data = priv;
1481 	u8 *key;
1482 
1483 	if (data->state != SUCCESS)
1484 		return NULL;
1485 
1486 	key = os_malloc(EAP_EMSK_LEN);
1487 	if (key == NULL)
1488 		return NULL;
1489 
1490 	*len = EAP_EMSK_LEN;
1491 	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
1492 
1493 	return key;
1494 }
1495 
1496 
eap_peer_aka_register(void)1497 int eap_peer_aka_register(void)
1498 {
1499 	struct eap_method *eap;
1500 
1501 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1502 				    EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
1503 	if (eap == NULL)
1504 		return -1;
1505 
1506 	eap->init = eap_aka_init;
1507 	eap->deinit = eap_aka_deinit;
1508 	eap->process = eap_aka_process;
1509 	eap->isKeyAvailable = eap_aka_isKeyAvailable;
1510 	eap->getKey = eap_aka_getKey;
1511 	eap->getSessionId = eap_aka_get_session_id;
1512 	eap->has_reauth_data = eap_aka_has_reauth_data;
1513 	eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
1514 	eap->init_for_reauth = eap_aka_init_for_reauth;
1515 	eap->get_identity = eap_aka_get_identity;
1516 	eap->get_emsk = eap_aka_get_emsk;
1517 
1518 	return eap_peer_method_register(eap);
1519 }
1520 
1521 
1522 #ifdef EAP_AKA_PRIME
eap_peer_aka_prime_register(void)1523 int eap_peer_aka_prime_register(void)
1524 {
1525 	struct eap_method *eap;
1526 
1527 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1528 				    EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
1529 				    "AKA'");
1530 	if (eap == NULL)
1531 		return -1;
1532 
1533 	eap->init = eap_aka_prime_init;
1534 	eap->deinit = eap_aka_deinit;
1535 	eap->process = eap_aka_process;
1536 	eap->isKeyAvailable = eap_aka_isKeyAvailable;
1537 	eap->getKey = eap_aka_getKey;
1538 	eap->getSessionId = eap_aka_get_session_id;
1539 	eap->has_reauth_data = eap_aka_has_reauth_data;
1540 	eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
1541 	eap->init_for_reauth = eap_aka_init_for_reauth;
1542 	eap->get_identity = eap_aka_get_identity;
1543 	eap->get_emsk = eap_aka_get_emsk;
1544 
1545 	return eap_peer_method_register(eap);
1546 }
1547 #endif /* EAP_AKA_PRIME */
1548