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