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 u8 reauth_mac[EAP_SIM_MAC_LEN];
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 {
46 CONTINUE, RESULT_SUCCESS, SUCCESS, FAILURE
47 } state;
48
49 struct wpabuf *id_msgs;
50 int prev_id;
51 int result_ind, use_result_ind;
52 int use_pseudonym;
53 u8 eap_method;
54 u8 *network_name;
55 size_t network_name_len;
56 u16 kdf;
57 int kdf_negotiation;
58 u16 last_kdf_attrs[EAP_AKA_PRIME_KDF_MAX];
59 size_t last_kdf_count;
60 int error_code;
61 };
62
63
64 #ifndef CONFIG_NO_STDOUT_DEBUG
eap_aka_state_txt(int state)65 static 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";
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
eap_aka_state(struct eap_aka_data * data,int state)83 static 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
eap_aka_init(struct eap_sm * sm)92 static void * eap_aka_init(struct eap_sm *sm)
93 {
94 struct eap_aka_data *data;
95 const char *phase1 = eap_get_config_phase1(sm);
96 struct eap_peer_config *config = eap_get_config(sm);
97
98 data = os_zalloc(sizeof(*data));
99 if (data == NULL)
100 return NULL;
101
102 data->eap_method = EAP_TYPE_AKA;
103
104 /* Zero is a valid error code, so we need to initialize */
105 data->error_code = NO_EAP_METHOD_ERROR;
106
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
112 data->use_pseudonym = !sm->init_phase2;
113 if (config && config->anonymous_identity && data->use_pseudonym) {
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
122 return data;
123 }
124
125
126 #ifdef EAP_AKA_PRIME
eap_aka_prime_init(struct eap_sm * sm)127 static 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
eap_aka_clear_keys(struct eap_aka_data * data,int reauth)138 static 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
eap_aka_deinit(struct eap_sm * sm,void * priv)153 static 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);
161 os_free(data->network_name);
162 eap_aka_clear_keys(data, 0);
163 os_free(data);
164 }
165 }
166
167
eap_aka_ext_sim_req(struct eap_sm * sm,struct eap_aka_data * data)168 static 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, ":");
179 wpa_snprintf_hex(pos, end - pos, data->autn, EAP_AKA_AUTN_LEN);
180
181 eap_sm_request_sim(sm, req);
182 return 1;
183 }
184
185
eap_aka_ext_sim_result(struct eap_sm * sm,struct eap_aka_data * data,struct eap_peer_config * conf)186 static 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
244 invalid:
245 wpa_printf(MSG_DEBUG, "EAP-AKA: Invalid external USIM processing UMTS-AUTH response");
246 os_free(resp);
247 return -1;
248 }
249
250
eap_aka_umts_auth(struct eap_sm * sm,struct eap_aka_data * data)251 static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data)
252 {
253 struct eap_peer_config *conf;
254
255 wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm");
256
257 conf = eap_get_config(sm);
258 if (conf == NULL)
259 return -1;
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
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
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);
322 if (os_memcmp_const(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) {
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;
339
340 #else /* CONFIG_USIM_HARDCODED */
341
342 wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorithm "
343 "enabled");
344 return -1;
345
346 #endif /* CONFIG_USIM_HARDCODED */
347 }
348
349
350 #define CLEAR_PSEUDONYM 0x01
351 #define CLEAR_REAUTH_ID 0x02
352 #define CLEAR_EAP_ID 0x04
353
eap_aka_clear_identities(struct eap_sm * sm,struct eap_aka_data * data,int id)354 static void eap_aka_clear_identities(struct eap_sm *sm,
355 struct eap_aka_data *data, int id)
356 {
357 if ((id & CLEAR_PSEUDONYM) && data->pseudonym) {
358 wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old pseudonym");
359 os_free(data->pseudonym);
360 data->pseudonym = NULL;
361 data->pseudonym_len = 0;
362 if (data->use_pseudonym)
363 eap_set_anon_id(sm, NULL, 0);
364 }
365 if ((id & CLEAR_REAUTH_ID) && data->reauth_id) {
366 wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old reauth_id");
367 os_free(data->reauth_id);
368 data->reauth_id = NULL;
369 data->reauth_id_len = 0;
370 }
371 if ((id & CLEAR_EAP_ID) && data->last_eap_identity) {
372 wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old eap_id");
373 os_free(data->last_eap_identity);
374 data->last_eap_identity = NULL;
375 data->last_eap_identity_len = 0;
376 }
377 }
378
379
eap_aka_learn_ids(struct eap_sm * sm,struct eap_aka_data * data,struct eap_sim_attrs * attr)380 static int eap_aka_learn_ids(struct eap_sm *sm, struct eap_aka_data *data,
381 struct eap_sim_attrs *attr)
382 {
383 if (attr->next_pseudonym) {
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);
393 os_free(data->pseudonym);
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);
405 if (data->pseudonym == NULL) {
406 wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
407 "next pseudonym");
408 data->pseudonym_len = 0;
409 return -1;
410 }
411 os_memcpy(data->pseudonym, attr->next_pseudonym,
412 attr->next_pseudonym_len);
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;
418 if (data->use_pseudonym)
419 eap_set_anon_id(sm, data->pseudonym,
420 data->pseudonym_len);
421 }
422
423 if (attr->next_reauth_id) {
424 os_free(data->reauth_id);
425 data->reauth_id = os_memdup(attr->next_reauth_id,
426 attr->next_reauth_id_len);
427 if (data->reauth_id == NULL) {
428 wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
429 "next reauth_id");
430 data->reauth_id_len = 0;
431 return -1;
432 }
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
eap_aka_add_id_msg(struct eap_aka_data * data,const struct wpabuf * msg)444 static 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
eap_aka_add_checkcode(struct eap_aka_data * data,struct eap_sim_msg * msg)463 static 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;
468 u8 hash[SHA256_MAC_LEN];
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
481 /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */
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);
485 #ifdef EAP_AKA_PRIME
486 if (data->eap_method == EAP_TYPE_AKA_PRIME)
487 sha256_vector(1, &addr, &len, hash);
488 else
489 #endif /* EAP_AKA_PRIME */
490 sha1_vector(1, &addr, &len, hash);
491
492 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
493 data->eap_method == EAP_TYPE_AKA_PRIME ?
494 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
495 }
496
497
eap_aka_verify_checkcode(struct eap_aka_data * data,const u8 * checkcode,size_t checkcode_len)498 static 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;
503 u8 hash[SHA256_MAC_LEN];
504 size_t hash_len;
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
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) {
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
529 /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */
530 addr = wpabuf_head(data->id_msgs);
531 len = wpabuf_len(data->id_msgs);
532 #ifdef EAP_AKA_PRIME
533 if (data->eap_method == EAP_TYPE_AKA_PRIME)
534 sha256_vector(1, &addr, &len, hash);
535 else
536 #endif /* EAP_AKA_PRIME */
537 sha1_vector(1, &addr, &len, hash);
538
539 if (os_memcmp_const(hash, checkcode, hash_len) != 0) {
540 wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
541 return -1;
542 }
543
544 return 0;
545 }
546
547
eap_aka_client_error(struct eap_aka_data * data,u8 id,int err)548 static 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
557 wpa_printf(MSG_DEBUG, "EAP-AKA: Send Client-Error (error code %d)",
558 err);
559 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
560 EAP_AKA_SUBTYPE_CLIENT_ERROR);
561 eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
562 return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
563 }
564
565
eap_aka_authentication_reject(struct eap_aka_data * data,u8 id)566 static 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);
577 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
578 EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT);
579 return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
580 }
581
582
eap_aka_synchronization_failure(struct eap_aka_data * data,u8 id,struct eap_sim_attrs * attr)583 static struct wpabuf * eap_aka_synchronization_failure(
584 struct eap_aka_data *data, u8 id, struct eap_sim_attrs *attr)
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);
593 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
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);
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 }
607 return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
608 }
609
610
eap_aka_response_identity(struct eap_sm * sm,struct eap_aka_data * data,u8 id,enum eap_sim_id_req id_req)611 static 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) &&
626 data->pseudonym &&
627 !eap_sim_anonymous_username(data->pseudonym,
628 data->pseudonym_len)) {
629 identity = data->pseudonym;
630 identity_len = data->pseudonym_len;
631 eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID);
632 } else if (id_req != NO_ID_REQ) {
633 identity = eap_get_config_identity(sm, &identity_len);
634 if (identity) {
635 int ids = CLEAR_PSEUDONYM | CLEAR_REAUTH_ID;
636
637 if (data->pseudonym &&
638 eap_sim_anonymous_username(data->pseudonym,
639 data->pseudonym_len))
640 ids &= ~CLEAR_PSEUDONYM;
641 eap_aka_clear_identities(sm, data, ids);
642 }
643 }
644 if (id_req != NO_ID_REQ)
645 eap_aka_clear_identities(sm, data, CLEAR_EAP_ID);
646
647 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id);
648 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
649 EAP_AKA_SUBTYPE_IDENTITY);
650
651 if (identity) {
652 wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY",
653 identity, identity_len);
654 eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
655 identity, identity_len);
656 }
657
658 return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
659 }
660
661
eap_aka_response_challenge(struct eap_aka_data * data,u8 id)662 static struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data,
663 u8 id)
664 {
665 struct eap_sim_msg *msg;
666
667 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id);
668 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
669 EAP_AKA_SUBTYPE_CHALLENGE);
670 wpa_printf(MSG_DEBUG, " AT_RES");
671 eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8,
672 data->res, data->res_len);
673 eap_aka_add_checkcode(data, msg);
674 if (data->use_result_ind) {
675 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
676 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
677 }
678 wpa_printf(MSG_DEBUG, " AT_MAC");
679 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
680 return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, (u8 *) "",
681 0);
682 }
683
684
eap_aka_response_reauth(struct eap_aka_data * data,u8 id,int counter_too_small,const u8 * nonce_s)685 static struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data,
686 u8 id, int counter_too_small,
687 const u8 *nonce_s)
688 {
689 struct eap_sim_msg *msg;
690 unsigned int counter;
691
692 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)",
693 id);
694 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
695 EAP_AKA_SUBTYPE_REAUTHENTICATION);
696 wpa_printf(MSG_DEBUG, " AT_IV");
697 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
698 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
699
700 if (counter_too_small) {
701 wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL");
702 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
703 counter = data->counter_too_small;
704 } else
705 counter = data->counter;
706
707 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter);
708 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
709
710 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
711 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
712 "AT_ENCR_DATA");
713 eap_sim_msg_free(msg);
714 return NULL;
715 }
716 eap_aka_add_checkcode(data, msg);
717 if (data->use_result_ind) {
718 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
719 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
720 }
721 wpa_printf(MSG_DEBUG, " AT_MAC");
722 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
723 return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, nonce_s,
724 EAP_SIM_NONCE_S_LEN);
725 }
726
727
eap_aka_response_notification(struct eap_aka_data * data,u8 id,u16 notification)728 static struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data,
729 u8 id, u16 notification)
730 {
731 struct eap_sim_msg *msg;
732 u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
733
734 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id);
735 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
736 EAP_AKA_SUBTYPE_NOTIFICATION);
737 if (k_aut && data->reauth) {
738 wpa_printf(MSG_DEBUG, " AT_IV");
739 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
740 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
741 EAP_SIM_AT_ENCR_DATA);
742 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter);
743 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
744 NULL, 0);
745 if (eap_sim_msg_add_encr_end(msg, data->k_encr,
746 EAP_SIM_AT_PADDING)) {
747 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
748 "AT_ENCR_DATA");
749 eap_sim_msg_free(msg);
750 return NULL;
751 }
752 }
753 if (k_aut) {
754 wpa_printf(MSG_DEBUG, " AT_MAC");
755 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
756 }
757 return eap_sim_msg_finish(msg, data->eap_method, k_aut, (u8 *) "", 0);
758 }
759
760
eap_aka_process_identity(struct eap_sm * sm,struct eap_aka_data * data,u8 id,const struct wpabuf * reqData,struct eap_sim_attrs * attr)761 static struct wpabuf * eap_aka_process_identity(struct eap_sm *sm,
762 struct eap_aka_data *data,
763 u8 id,
764 const struct wpabuf *reqData,
765 struct eap_sim_attrs *attr)
766 {
767 int id_error;
768 struct wpabuf *buf;
769
770 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity");
771
772 id_error = 0;
773 switch (attr->id_req) {
774 case NO_ID_REQ:
775 break;
776 case ANY_ID:
777 if (data->num_id_req > 0)
778 id_error++;
779 data->num_id_req++;
780 break;
781 case FULLAUTH_ID:
782 if (data->num_id_req > 1)
783 id_error++;
784 data->num_id_req++;
785 break;
786 case PERMANENT_ID:
787 if (data->num_id_req > 2)
788 id_error++;
789 data->num_id_req++;
790 break;
791 }
792 if (id_error) {
793 wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests "
794 "used within one authentication");
795 return eap_aka_client_error(data, id,
796 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
797 }
798
799 buf = eap_aka_response_identity(sm, data, id, attr->id_req);
800
801 if (data->prev_id != id) {
802 eap_aka_add_id_msg(data, reqData);
803 eap_aka_add_id_msg(data, buf);
804 data->prev_id = id;
805 }
806
807 return buf;
808 }
809
810
eap_aka_verify_mac(struct eap_aka_data * data,const struct wpabuf * req,const u8 * mac,const u8 * extra,size_t extra_len)811 static int eap_aka_verify_mac(struct eap_aka_data *data,
812 const struct wpabuf *req,
813 const u8 *mac, const u8 *extra,
814 size_t extra_len)
815 {
816 if (data->eap_method == EAP_TYPE_AKA_PRIME)
817 return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
818 extra_len);
819 return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
820 }
821
822
823 #ifdef EAP_AKA_PRIME
eap_aka_prime_kdf_select(struct eap_aka_data * data,u8 id,u16 kdf)824 static struct wpabuf * eap_aka_prime_kdf_select(struct eap_aka_data *data,
825 u8 id, u16 kdf)
826 {
827 struct eap_sim_msg *msg;
828
829 data->kdf_negotiation = 1;
830 data->kdf = kdf;
831 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d) (KDF "
832 "select)", id);
833 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
834 EAP_AKA_SUBTYPE_CHALLENGE);
835 wpa_printf(MSG_DEBUG, " AT_KDF");
836 eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0);
837 return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
838 }
839
840
eap_aka_prime_kdf_neg(struct eap_aka_data * data,u8 id,struct eap_sim_attrs * attr)841 static struct wpabuf * eap_aka_prime_kdf_neg(struct eap_aka_data *data,
842 u8 id, struct eap_sim_attrs *attr)
843 {
844 size_t i;
845
846 for (i = 0; i < attr->kdf_count; i++) {
847 if (attr->kdf[i] == EAP_AKA_PRIME_KDF) {
848 os_memcpy(data->last_kdf_attrs, attr->kdf,
849 sizeof(u16) * attr->kdf_count);
850 data->last_kdf_count = attr->kdf_count;
851 return eap_aka_prime_kdf_select(data, id,
852 EAP_AKA_PRIME_KDF);
853 }
854 }
855
856 /* No matching KDF found - fail authentication as if AUTN had been
857 * incorrect */
858 return eap_aka_authentication_reject(data, id);
859 }
860
861
eap_aka_prime_kdf_valid(struct eap_aka_data * data,struct eap_sim_attrs * attr)862 static int eap_aka_prime_kdf_valid(struct eap_aka_data *data,
863 struct eap_sim_attrs *attr)
864 {
865 size_t i, j;
866
867 if (attr->kdf_count == 0)
868 return 0;
869
870 /* The only allowed (and required) duplication of a KDF is the addition
871 * of the selected KDF into the beginning of the list. */
872
873 if (data->kdf_negotiation) {
874 /* When the peer receives the new EAP-Request/AKA'-Challenge
875 * message, must check only requested change occurred in the
876 * list of AT_KDF attributes. If there are any other changes,
877 * the peer must behave like the case that AT_MAC had been
878 * incorrect and authentication is failed. These are defined in
879 * EAP-AKA' specification RFC 5448, Section 3.2. */
880 if (attr->kdf[0] != data->kdf) {
881 wpa_printf(MSG_WARNING, "EAP-AKA': The server did not "
882 "accept the selected KDF");
883 return -1;
884 }
885
886 if (attr->kdf_count > EAP_AKA_PRIME_KDF_MAX ||
887 attr->kdf_count != data->last_kdf_count + 1) {
888 wpa_printf(MSG_WARNING,
889 "EAP-AKA': The length of KDF attributes is wrong");
890 return -1;
891 }
892
893 for (i = 1; i < attr->kdf_count; i++) {
894 if (attr->kdf[i] != data->last_kdf_attrs[i - 1]) {
895 wpa_printf(MSG_WARNING,
896 "EAP-AKA': The KDF attributes except selected KDF are not same as original one");
897 return -1;
898 }
899 }
900 }
901
902 for (i = data->kdf ? 1 : 0; i < attr->kdf_count; i++) {
903 for (j = i + 1; j < attr->kdf_count; j++) {
904 if (attr->kdf[i] == attr->kdf[j]) {
905 wpa_printf(MSG_WARNING, "EAP-AKA': The server "
906 "included a duplicated KDF");
907 return 0;
908 }
909 }
910 }
911
912 return 1;
913 }
914 #endif /* EAP_AKA_PRIME */
915
916
eap_aka_process_challenge(struct eap_sm * sm,struct eap_aka_data * data,u8 id,const struct wpabuf * reqData,struct eap_sim_attrs * attr)917 static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm,
918 struct eap_aka_data *data,
919 u8 id,
920 const struct wpabuf *reqData,
921 struct eap_sim_attrs *attr)
922 {
923 const u8 *identity;
924 size_t identity_len;
925 int res;
926 struct eap_sim_attrs eattr;
927
928 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge");
929
930 if (attr->checkcode &&
931 eap_aka_verify_checkcode(data, attr->checkcode,
932 attr->checkcode_len)) {
933 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
934 "message");
935 #ifdef TEST_FUZZ
936 wpa_printf(MSG_INFO,
937 "TEST: Ignore AT_CHECKCODE mismatch for fuzz testing");
938 #else /* TEST_FUZZ */
939 return eap_aka_client_error(data, id,
940 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
941 #endif /* TEST_FUZZ */
942 }
943
944 #ifdef EAP_AKA_PRIME
945 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
946 if (!attr->kdf_input || attr->kdf_input_len == 0) {
947 wpa_printf(MSG_WARNING, "EAP-AKA': Challenge message "
948 "did not include non-empty AT_KDF_INPUT");
949 /* Fail authentication as if AUTN had been incorrect */
950 return eap_aka_authentication_reject(data, id);
951 }
952 os_free(data->network_name);
953 data->network_name = os_memdup(attr->kdf_input,
954 attr->kdf_input_len);
955 if (data->network_name == NULL) {
956 wpa_printf(MSG_WARNING, "EAP-AKA': No memory for "
957 "storing Network Name");
958 return eap_aka_authentication_reject(data, id);
959 }
960 data->network_name_len = attr->kdf_input_len;
961 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': Network Name "
962 "(AT_KDF_INPUT)",
963 data->network_name, data->network_name_len);
964 /* TODO: check Network Name per 3GPP.33.402 */
965
966 res = eap_aka_prime_kdf_valid(data, attr);
967 if (res == 0)
968 return eap_aka_authentication_reject(data, id);
969 else if (res == -1)
970 return eap_aka_client_error(
971 data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET);
972
973 if (attr->kdf[0] != EAP_AKA_PRIME_KDF)
974 return eap_aka_prime_kdf_neg(data, id, attr);
975
976 data->kdf = EAP_AKA_PRIME_KDF;
977 wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
978 }
979
980 if (data->eap_method == EAP_TYPE_AKA && attr->bidding) {
981 u16 flags = WPA_GET_BE16(attr->bidding);
982 if ((flags & EAP_AKA_BIDDING_FLAG_D) &&
983 eap_allowed_method(sm, EAP_VENDOR_IETF,
984 EAP_TYPE_AKA_PRIME)) {
985 wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from "
986 "AKA' to AKA detected");
987 /* Fail authentication as if AUTN had been incorrect */
988 return eap_aka_authentication_reject(data, id);
989 }
990 }
991 #endif /* EAP_AKA_PRIME */
992
993 data->reauth = 0;
994 if (!attr->mac || !attr->rand || !attr->autn) {
995 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
996 "did not include%s%s%s",
997 !attr->mac ? " AT_MAC" : "",
998 !attr->rand ? " AT_RAND" : "",
999 !attr->autn ? " AT_AUTN" : "");
1000 return eap_aka_client_error(data, id,
1001 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1002 }
1003 os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN);
1004 os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN);
1005
1006 res = eap_aka_umts_auth(sm, data);
1007 if (res == -1) {
1008 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
1009 "failed (AUTN)");
1010 return eap_aka_authentication_reject(data, id);
1011 } else if (res == -2) {
1012 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
1013 "failed (AUTN seq# -> AUTS)");
1014 return eap_aka_synchronization_failure(data, id, attr);
1015 } else if (res > 0) {
1016 wpa_printf(MSG_DEBUG, "EAP-AKA: Wait for external USIM processing");
1017 return NULL;
1018 } else if (res) {
1019 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed");
1020 return eap_aka_client_error(data, id,
1021 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1022 }
1023 #ifdef EAP_AKA_PRIME
1024 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1025 /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
1026 * needed 6-octet SQN ^ AK for CK',IK' derivation */
1027 u16 amf = WPA_GET_BE16(data->autn + 6);
1028 if (!(amf & 0x8000)) {
1029 wpa_printf(MSG_WARNING, "EAP-AKA': AMF separation bit "
1030 "not set (AMF=0x%4x)", amf);
1031 return eap_aka_authentication_reject(data, id);
1032 }
1033 eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
1034 data->autn,
1035 data->network_name,
1036 data->network_name_len);
1037 }
1038 #endif /* EAP_AKA_PRIME */
1039 if (data->last_eap_identity) {
1040 identity = data->last_eap_identity;
1041 identity_len = data->last_eap_identity_len;
1042 } else if (data->pseudonym &&
1043 !eap_sim_anonymous_username(data->pseudonym,
1044 data->pseudonym_len)) {
1045 identity = data->pseudonym;
1046 identity_len = data->pseudonym_len;
1047 } else {
1048 struct eap_peer_config *config;
1049
1050 config = eap_get_config(sm);
1051 if (config && config->imsi_identity) {
1052 identity = config->imsi_identity;
1053 identity_len = config->imsi_identity_len;
1054 } else {
1055 identity = eap_get_config_identity(sm, &identity_len);
1056 }
1057 }
1058 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
1059 "derivation", identity, identity_len);
1060 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1061 eap_aka_prime_derive_keys(identity, identity_len, data->ik,
1062 data->ck, data->k_encr, data->k_aut,
1063 data->k_re, data->msk, data->emsk);
1064 } else {
1065 eap_aka_derive_mk(identity, identity_len, data->ik, data->ck,
1066 data->mk);
1067 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
1068 data->msk, data->emsk);
1069 }
1070 if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
1071 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
1072 "used invalid AT_MAC");
1073 #ifdef TEST_FUZZ
1074 wpa_printf(MSG_INFO,
1075 "TEST: Ignore AT_MAC mismatch for fuzz testing");
1076 #else /* TEST_FUZZ */
1077 return eap_aka_client_error(data, id,
1078 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1079 #endif /* TEST_FUZZ */
1080 }
1081
1082 /* Old reauthentication identity must not be used anymore. In
1083 * other words, if no new identities are received, full
1084 * authentication will be used on next reauthentication (using
1085 * pseudonym identity or permanent identity). */
1086 eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1087
1088 if (attr->encr_data) {
1089 u8 *decrypted;
1090 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1091 attr->encr_data_len, attr->iv,
1092 &eattr, 0);
1093 if (decrypted == NULL) {
1094 return eap_aka_client_error(
1095 data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1096 }
1097 eap_aka_learn_ids(sm, data, &eattr);
1098 os_free(decrypted);
1099 }
1100
1101 if (data->result_ind && attr->result_ind)
1102 data->use_result_ind = 1;
1103
1104 if (data->state != FAILURE) {
1105 eap_aka_state(data, data->use_result_ind ?
1106 RESULT_SUCCESS : SUCCESS);
1107 }
1108
1109 data->num_id_req = 0;
1110 data->num_notification = 0;
1111 /* RFC 4187 specifies that counter is initialized to one after
1112 * fullauth, but initializing it to zero makes it easier to implement
1113 * reauth verification. */
1114 data->counter = 0;
1115 return eap_aka_response_challenge(data, id);
1116 }
1117
1118
eap_aka_process_notification_reauth(struct eap_aka_data * data,struct eap_sim_attrs * attr)1119 static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
1120 struct eap_sim_attrs *attr)
1121 {
1122 struct eap_sim_attrs eattr;
1123 u8 *decrypted;
1124
1125 if (attr->encr_data == NULL || attr->iv == NULL) {
1126 wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after "
1127 "reauth did not include encrypted data");
1128 return -1;
1129 }
1130
1131 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1132 attr->encr_data_len, attr->iv, &eattr,
1133 0);
1134 if (decrypted == NULL) {
1135 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
1136 "data from notification message");
1137 return -1;
1138 }
1139
1140 if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
1141 wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification "
1142 "message does not match with counter in reauth "
1143 "message");
1144 os_free(decrypted);
1145 return -1;
1146 }
1147
1148 os_free(decrypted);
1149 return 0;
1150 }
1151
1152
eap_aka_process_notification_auth(struct eap_aka_data * data,const struct wpabuf * reqData,struct eap_sim_attrs * attr)1153 static int eap_aka_process_notification_auth(struct eap_aka_data *data,
1154 const struct wpabuf *reqData,
1155 struct eap_sim_attrs *attr)
1156 {
1157 if (attr->mac == NULL) {
1158 wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth "
1159 "Notification message");
1160 return -1;
1161 }
1162
1163 if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
1164 wpa_printf(MSG_WARNING, "EAP-AKA: Notification message "
1165 "used invalid AT_MAC");
1166 return -1;
1167 }
1168
1169 if (data->reauth &&
1170 eap_aka_process_notification_reauth(data, attr)) {
1171 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification "
1172 "message after reauth");
1173 return -1;
1174 }
1175
1176 return 0;
1177 }
1178
1179
eap_aka_process_notification(struct eap_sm * sm,struct eap_aka_data * data,u8 id,const struct wpabuf * reqData,struct eap_sim_attrs * attr)1180 static struct wpabuf * eap_aka_process_notification(
1181 struct eap_sm *sm, struct eap_aka_data *data, u8 id,
1182 const struct wpabuf *reqData, struct eap_sim_attrs *attr)
1183 {
1184 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification");
1185 if (data->num_notification > 0) {
1186 wpa_printf(MSG_INFO, "EAP-AKA: too many notification "
1187 "rounds (only one allowed)");
1188 return eap_aka_client_error(data, id,
1189 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1190 }
1191 data->num_notification++;
1192 if (attr->notification == -1) {
1193 wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in "
1194 "Notification message");
1195 return eap_aka_client_error(data, id,
1196 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1197 }
1198
1199 if ((attr->notification & 0x4000) == 0 &&
1200 eap_aka_process_notification_auth(data, reqData, attr)) {
1201 return eap_aka_client_error(data, id,
1202 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1203 }
1204
1205 eap_sim_report_notification(sm->msg_ctx, attr->notification, 1);
1206 if (attr->notification >= 0 && attr->notification < 32768) {
1207 data->error_code = attr->notification;
1208 eap_aka_state(data, FAILURE);
1209 } else if (attr->notification == EAP_SIM_SUCCESS &&
1210 data->state == RESULT_SUCCESS)
1211 eap_aka_state(data, SUCCESS);
1212 return eap_aka_response_notification(data, id, attr->notification);
1213 }
1214
1215
eap_aka_process_reauthentication(struct eap_sm * sm,struct eap_aka_data * data,u8 id,const struct wpabuf * reqData,struct eap_sim_attrs * attr)1216 static struct wpabuf * eap_aka_process_reauthentication(
1217 struct eap_sm *sm, struct eap_aka_data *data, u8 id,
1218 const struct wpabuf *reqData, struct eap_sim_attrs *attr)
1219 {
1220 struct eap_sim_attrs eattr;
1221 u8 *decrypted;
1222
1223 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication");
1224
1225 if (attr->checkcode &&
1226 eap_aka_verify_checkcode(data, attr->checkcode,
1227 attr->checkcode_len)) {
1228 #ifdef TEST_FUZZ
1229 wpa_printf(MSG_INFO,
1230 "TEST: Ignore AT_CHECKCODE mismatch for fuzz testing");
1231 #else /* TEST_FUZZ */
1232 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
1233 "message");
1234 #endif /* TEST_FUZZ */
1235 return eap_aka_client_error(data, id,
1236 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1237 }
1238
1239 if (data->reauth_id == NULL) {
1240 wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying "
1241 "reauthentication, but no reauth_id available");
1242 return eap_aka_client_error(data, id,
1243 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1244 }
1245
1246 data->reauth = 1;
1247 if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
1248 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
1249 "did not have valid AT_MAC");
1250 return eap_aka_client_error(data, id,
1251 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1252 }
1253
1254 /* At this stage the received MAC has been verified. Use this MAC for
1255 * reauth Session-Id calculation if all other checks pass.
1256 * The peer does not use the local MAC but the received MAC in deriving
1257 * Session-Id. */
1258 os_memcpy(data->reauth_mac, attr->mac, EAP_SIM_MAC_LEN);
1259 wpa_hexdump(MSG_DEBUG, "EAP-AKA: Server MAC",
1260 data->reauth_mac, EAP_SIM_MAC_LEN);
1261
1262 if (attr->encr_data == NULL || attr->iv == NULL) {
1263 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
1264 "message did not include encrypted data");
1265 return eap_aka_client_error(data, id,
1266 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1267 }
1268
1269 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
1270 attr->encr_data_len, attr->iv, &eattr,
1271 0);
1272 if (decrypted == NULL) {
1273 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
1274 "data from reauthentication message");
1275 return eap_aka_client_error(data, id,
1276 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1277 }
1278
1279 if (eattr.nonce_s == NULL || eattr.counter < 0) {
1280 wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet",
1281 !eattr.nonce_s ? " AT_NONCE_S" : "",
1282 eattr.counter < 0 ? " AT_COUNTER" : "");
1283 os_free(decrypted);
1284 return eap_aka_client_error(data, id,
1285 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1286 }
1287
1288 if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
1289 struct wpabuf *res;
1290 wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter "
1291 "(%d <= %d)", eattr.counter, data->counter);
1292 data->counter_too_small = eattr.counter;
1293
1294 /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
1295 * reauth_id must not be used to start a new reauthentication.
1296 * However, since it was used in the last EAP-Response-Identity
1297 * packet, it has to saved for the following fullauth to be
1298 * used in MK derivation. */
1299 os_free(data->last_eap_identity);
1300 data->last_eap_identity = data->reauth_id;
1301 data->last_eap_identity_len = data->reauth_id_len;
1302 data->reauth_id = NULL;
1303 data->reauth_id_len = 0;
1304
1305 res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s);
1306 os_free(decrypted);
1307
1308 return res;
1309 }
1310 data->counter = eattr.counter;
1311
1312 os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
1313 wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S",
1314 data->nonce_s, EAP_SIM_NONCE_S_LEN);
1315
1316 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
1317 eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
1318 data->reauth_id,
1319 data->reauth_id_len,
1320 data->nonce_s,
1321 data->msk, data->emsk);
1322 } else {
1323 eap_sim_derive_keys_reauth(data->counter, data->reauth_id,
1324 data->reauth_id_len,
1325 data->nonce_s, data->mk,
1326 data->msk, data->emsk);
1327 }
1328 eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1329 eap_aka_learn_ids(sm, data, &eattr);
1330
1331 if (data->result_ind && attr->result_ind)
1332 data->use_result_ind = 1;
1333
1334 if (data->state != FAILURE) {
1335 eap_aka_state(data, data->use_result_ind ?
1336 RESULT_SUCCESS : SUCCESS);
1337 }
1338
1339 data->num_id_req = 0;
1340 data->num_notification = 0;
1341 if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) {
1342 wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of "
1343 "fast reauths performed - force fullauth");
1344 eap_aka_clear_identities(sm, data,
1345 CLEAR_REAUTH_ID | CLEAR_EAP_ID);
1346 }
1347 os_free(decrypted);
1348 return eap_aka_response_reauth(data, id, 0, data->nonce_s);
1349 }
1350
1351
eap_aka_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)1352 static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv,
1353 struct eap_method_ret *ret,
1354 const struct wpabuf *reqData)
1355 {
1356 struct eap_aka_data *data = priv;
1357 const struct eap_hdr *req;
1358 u8 subtype, id;
1359 struct wpabuf *res;
1360 const u8 *pos;
1361 struct eap_sim_attrs attr;
1362 size_t len;
1363
1364 wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData);
1365 if (eap_get_config_identity(sm, &len) == NULL) {
1366 wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured");
1367 eap_sm_request_identity(sm);
1368 ret->ignore = TRUE;
1369 return NULL;
1370 }
1371
1372 pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData,
1373 &len);
1374 if (pos == NULL || len < 3) {
1375 ret->ignore = TRUE;
1376 return NULL;
1377 }
1378 req = wpabuf_head(reqData);
1379 id = req->identifier;
1380 len = be_to_host16(req->length);
1381
1382 ret->ignore = FALSE;
1383 ret->methodState = METHOD_MAY_CONT;
1384 ret->decision = DECISION_FAIL;
1385 ret->allowNotifications = TRUE;
1386
1387 subtype = *pos++;
1388 wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype);
1389 pos += 2; /* Reserved */
1390
1391 if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr,
1392 data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
1393 0)) {
1394 res = eap_aka_client_error(data, id,
1395 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1396 goto done;
1397 }
1398
1399 switch (subtype) {
1400 case EAP_AKA_SUBTYPE_IDENTITY:
1401 res = eap_aka_process_identity(sm, data, id, reqData, &attr);
1402 break;
1403 case EAP_AKA_SUBTYPE_CHALLENGE:
1404 res = eap_aka_process_challenge(sm, data, id, reqData, &attr);
1405 break;
1406 case EAP_AKA_SUBTYPE_NOTIFICATION:
1407 res = eap_aka_process_notification(sm, data, id, reqData,
1408 &attr);
1409 break;
1410 case EAP_AKA_SUBTYPE_REAUTHENTICATION:
1411 res = eap_aka_process_reauthentication(sm, data, id, reqData,
1412 &attr);
1413 break;
1414 case EAP_AKA_SUBTYPE_CLIENT_ERROR:
1415 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error");
1416 res = eap_aka_client_error(data, id,
1417 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1418 break;
1419 default:
1420 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype);
1421 res = eap_aka_client_error(data, id,
1422 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
1423 break;
1424 }
1425
1426 done:
1427 if (data->state == FAILURE) {
1428 ret->decision = DECISION_FAIL;
1429 ret->methodState = METHOD_DONE;
1430 } else if (data->state == SUCCESS) {
1431 ret->decision = data->use_result_ind ?
1432 DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
1433 /*
1434 * It is possible for the server to reply with AKA
1435 * Notification, so we must allow the method to continue and
1436 * not only accept EAP-Success at this point.
1437 */
1438 ret->methodState = data->use_result_ind ?
1439 METHOD_DONE : METHOD_MAY_CONT;
1440 } else if (data->state == RESULT_SUCCESS)
1441 ret->methodState = METHOD_CONT;
1442
1443 if (ret->methodState == METHOD_DONE) {
1444 ret->allowNotifications = FALSE;
1445 }
1446
1447 return res;
1448 }
1449
1450
eap_aka_has_reauth_data(struct eap_sm * sm,void * priv)1451 static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv)
1452 {
1453 struct eap_aka_data *data = priv;
1454 return data->pseudonym || data->reauth_id;
1455 }
1456
1457
eap_aka_deinit_for_reauth(struct eap_sm * sm,void * priv)1458 static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv)
1459 {
1460 struct eap_aka_data *data = priv;
1461 eap_aka_clear_identities(sm, data, CLEAR_EAP_ID);
1462 data->prev_id = -1;
1463 wpabuf_free(data->id_msgs);
1464 data->id_msgs = NULL;
1465 data->use_result_ind = 0;
1466 data->kdf_negotiation = 0;
1467 eap_aka_clear_keys(data, 1);
1468 }
1469
1470
eap_aka_init_for_reauth(struct eap_sm * sm,void * priv)1471 static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv)
1472 {
1473 struct eap_aka_data *data = priv;
1474 data->num_id_req = 0;
1475 data->num_notification = 0;
1476 eap_aka_state(data, CONTINUE);
1477 return priv;
1478 }
1479
1480
eap_aka_get_identity(struct eap_sm * sm,void * priv,size_t * len)1481 static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv,
1482 size_t *len)
1483 {
1484 struct eap_aka_data *data = priv;
1485
1486 if (data->reauth_id) {
1487 *len = data->reauth_id_len;
1488 return data->reauth_id;
1489 }
1490
1491 if (data->pseudonym) {
1492 *len = data->pseudonym_len;
1493 return data->pseudonym;
1494 }
1495
1496 return NULL;
1497 }
1498
1499
eap_aka_isKeyAvailable(struct eap_sm * sm,void * priv)1500 static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv)
1501 {
1502 struct eap_aka_data *data = priv;
1503 return data->state == SUCCESS;
1504 }
1505
1506
eap_aka_getKey(struct eap_sm * sm,void * priv,size_t * len)1507 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
1508 {
1509 struct eap_aka_data *data = priv;
1510 u8 *key;
1511
1512 if (data->state != SUCCESS)
1513 return NULL;
1514
1515 key = os_memdup(data->msk, EAP_SIM_KEYING_DATA_LEN);
1516 if (key == NULL)
1517 return NULL;
1518
1519 *len = EAP_SIM_KEYING_DATA_LEN;
1520
1521 return key;
1522 }
1523
1524
eap_aka_get_session_id(struct eap_sm * sm,void * priv,size_t * len)1525 static u8 * eap_aka_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1526 {
1527 struct eap_aka_data *data = priv;
1528 u8 *id;
1529
1530 if (data->state != SUCCESS)
1531 return NULL;
1532
1533 if (!data->reauth)
1534 *len = 1 + EAP_AKA_RAND_LEN + EAP_AKA_AUTN_LEN;
1535 else
1536 *len = 1 + EAP_SIM_NONCE_S_LEN + EAP_SIM_MAC_LEN;
1537 id = os_malloc(*len);
1538 if (id == NULL)
1539 return NULL;
1540
1541 id[0] = data->eap_method;
1542 if (!data->reauth) {
1543 os_memcpy(id + 1, data->rand, EAP_AKA_RAND_LEN);
1544 os_memcpy(id + 1 + EAP_AKA_RAND_LEN, data->autn,
1545 EAP_AKA_AUTN_LEN);
1546 } else {
1547 os_memcpy(id + 1, data->nonce_s, EAP_SIM_NONCE_S_LEN);
1548 os_memcpy(id + 1 + EAP_SIM_NONCE_S_LEN, data->reauth_mac,
1549 EAP_SIM_MAC_LEN);
1550 }
1551 wpa_hexdump(MSG_DEBUG, "EAP-AKA: Derived Session-Id", id, *len);
1552
1553 return id;
1554 }
1555
1556
eap_aka_get_emsk(struct eap_sm * sm,void * priv,size_t * len)1557 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1558 {
1559 struct eap_aka_data *data = priv;
1560 u8 *key;
1561
1562 if (data->state != SUCCESS)
1563 return NULL;
1564
1565 key = os_memdup(data->emsk, EAP_EMSK_LEN);
1566 if (key == NULL)
1567 return NULL;
1568
1569 *len = EAP_EMSK_LEN;
1570
1571 return key;
1572 }
1573
1574
eap_aka_get_error_code(void * priv)1575 static int eap_aka_get_error_code(void *priv)
1576 {
1577 struct eap_aka_data *data = priv;
1578 int current_data_error;
1579
1580 if (!data)
1581 return NO_EAP_METHOD_ERROR;
1582
1583 current_data_error = data->error_code;
1584
1585 /* Now reset for next transaction */
1586 data->error_code = NO_EAP_METHOD_ERROR;
1587
1588 return current_data_error;
1589 }
1590
1591
eap_peer_aka_register(void)1592 int eap_peer_aka_register(void)
1593 {
1594 struct eap_method *eap;
1595
1596 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1597 EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
1598 if (eap == NULL)
1599 return -1;
1600
1601 eap->init = eap_aka_init;
1602 eap->deinit = eap_aka_deinit;
1603 eap->process = eap_aka_process;
1604 eap->isKeyAvailable = eap_aka_isKeyAvailable;
1605 eap->getKey = eap_aka_getKey;
1606 eap->getSessionId = eap_aka_get_session_id;
1607 eap->has_reauth_data = eap_aka_has_reauth_data;
1608 eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
1609 eap->init_for_reauth = eap_aka_init_for_reauth;
1610 eap->get_identity = eap_aka_get_identity;
1611 eap->get_emsk = eap_aka_get_emsk;
1612 eap->get_error_code = eap_aka_get_error_code;
1613
1614 return eap_peer_method_register(eap);
1615 }
1616
1617
1618 #ifdef EAP_AKA_PRIME
eap_peer_aka_prime_register(void)1619 int eap_peer_aka_prime_register(void)
1620 {
1621 struct eap_method *eap;
1622
1623 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1624 EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
1625 "AKA'");
1626 if (eap == NULL)
1627 return -1;
1628
1629 eap->init = eap_aka_prime_init;
1630 eap->deinit = eap_aka_deinit;
1631 eap->process = eap_aka_process;
1632 eap->isKeyAvailable = eap_aka_isKeyAvailable;
1633 eap->getKey = eap_aka_getKey;
1634 eap->getSessionId = eap_aka_get_session_id;
1635 eap->has_reauth_data = eap_aka_has_reauth_data;
1636 eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
1637 eap->init_for_reauth = eap_aka_init_for_reauth;
1638 eap->get_identity = eap_aka_get_identity;
1639 eap->get_emsk = eap_aka_get_emsk;
1640 eap->get_error_code = eap_aka_get_error_code;
1641
1642 return eap_peer_method_register(eap);
1643 }
1644 #endif /* EAP_AKA_PRIME */
1645