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