1/* 2 * EAP peer method: EAP-SIM (RFC 4186) 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/milenage.h" 14#include "crypto/random.h" 15#include "eap_peer/eap_i.h" 16#include "eap_config.h" 17#include "eap_common/eap_sim_common.h" 18 19 20struct eap_sim_data { 21 u8 *ver_list; 22 size_t ver_list_len; 23 int selected_version; 24 size_t min_num_chal, num_chal; 25 26 u8 kc[3][EAP_SIM_KC_LEN]; 27 u8 sres[3][EAP_SIM_SRES_LEN]; 28 u8 nonce_mt[EAP_SIM_NONCE_MT_LEN], nonce_s[EAP_SIM_NONCE_S_LEN]; 29 u8 mk[EAP_SIM_MK_LEN]; 30 u8 k_aut[EAP_SIM_K_AUT_LEN]; 31 u8 k_encr[EAP_SIM_K_ENCR_LEN]; 32 u8 msk[EAP_SIM_KEYING_DATA_LEN]; 33 u8 emsk[EAP_EMSK_LEN]; 34 u8 rand[3][GSM_RAND_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 int result_ind, use_result_ind; 49 int use_pseudonym; 50 int error_code; 51}; 52 53 54#ifndef CONFIG_NO_STDOUT_DEBUG 55static const char * eap_sim_state_txt(int state) 56{ 57 switch (state) { 58 case CONTINUE: 59 return "CONTINUE"; 60 case RESULT_SUCCESS: 61 return "RESULT_SUCCESS"; 62 case SUCCESS: 63 return "SUCCESS"; 64 case FAILURE: 65 return "FAILURE"; 66 default: 67 return "?"; 68 } 69} 70#endif /* CONFIG_NO_STDOUT_DEBUG */ 71 72 73static void eap_sim_state(struct eap_sim_data *data, int state) 74{ 75 wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s", 76 eap_sim_state_txt(data->state), 77 eap_sim_state_txt(state)); 78 data->state = state; 79} 80 81 82static void * eap_sim_init(struct eap_sm *sm) 83{ 84 struct eap_sim_data *data; 85 struct eap_peer_config *config = eap_get_config(sm); 86 87 data = os_zalloc(sizeof(*data)); 88 if (data == NULL) 89 return NULL; 90 91 if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { 92 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " 93 "for NONCE_MT"); 94 os_free(data); 95 return NULL; 96 } 97 98 /* Zero is a valid error code, so we need to initialize */ 99 data->error_code = NO_EAP_METHOD_ERROR; 100 101 data->min_num_chal = 2; 102 if (config && config->phase1) { 103 char *pos = os_strstr(config->phase1, "sim_min_num_chal="); 104 if (pos) { 105 data->min_num_chal = atoi(pos + 17); 106 if (data->min_num_chal < 2 || data->min_num_chal > 3) { 107 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid " 108 "sim_min_num_chal configuration " 109 "(%lu, expected 2 or 3)", 110 (unsigned long) data->min_num_chal); 111 os_free(data); 112 return NULL; 113 } 114 wpa_printf(MSG_DEBUG, "EAP-SIM: Set minimum number of " 115 "challenges to %lu", 116 (unsigned long) data->min_num_chal); 117 } 118 119 data->result_ind = os_strstr(config->phase1, "result_ind=1") != 120 NULL; 121 } 122 123 data->use_pseudonym = !sm->init_phase2; 124 if (config && config->anonymous_identity && data->use_pseudonym) { 125 data->pseudonym = os_malloc(config->anonymous_identity_len); 126 if (data->pseudonym) { 127 os_memcpy(data->pseudonym, config->anonymous_identity, 128 config->anonymous_identity_len); 129 data->pseudonym_len = config->anonymous_identity_len; 130 } 131 } 132 133 eap_sim_state(data, CONTINUE); 134 135 return data; 136} 137 138 139static void eap_sim_clear_keys(struct eap_sim_data *data, int reauth) 140{ 141 if (!reauth) { 142 os_memset(data->mk, 0, EAP_SIM_MK_LEN); 143 os_memset(data->k_aut, 0, EAP_SIM_K_AUT_LEN); 144 os_memset(data->k_encr, 0, EAP_SIM_K_ENCR_LEN); 145 } 146 os_memset(data->kc, 0, 3 * EAP_SIM_KC_LEN); 147 os_memset(data->sres, 0, 3 * EAP_SIM_SRES_LEN); 148 os_memset(data->msk, 0, EAP_SIM_KEYING_DATA_LEN); 149 os_memset(data->emsk, 0, EAP_EMSK_LEN); 150} 151 152 153static void eap_sim_deinit(struct eap_sm *sm, void *priv) 154{ 155 struct eap_sim_data *data = priv; 156 if (data) { 157 os_free(data->ver_list); 158 os_free(data->pseudonym); 159 os_free(data->reauth_id); 160 os_free(data->last_eap_identity); 161 eap_sim_clear_keys(data, 0); 162 os_free(data); 163 } 164} 165 166 167static int eap_sim_ext_sim_req(struct eap_sm *sm, struct eap_sim_data *data) 168{ 169 char req[200], *pos, *end; 170 size_t i; 171 172 wpa_printf(MSG_DEBUG, "EAP-SIM: Use external SIM processing"); 173 pos = req; 174 end = pos + sizeof(req); 175 pos += os_snprintf(pos, end - pos, "GSM-AUTH"); 176 for (i = 0; i < data->num_chal; i++) { 177 pos += os_snprintf(pos, end - pos, ":"); 178 pos += wpa_snprintf_hex(pos, end - pos, data->rand[i], 179 GSM_RAND_LEN); 180 } 181 182 eap_sm_request_sim(sm, req); 183 return 1; 184} 185 186 187static int eap_sim_ext_sim_result(struct eap_sm *sm, struct eap_sim_data *data, 188 struct eap_peer_config *conf) 189{ 190 char *resp, *pos; 191 size_t i; 192 193 wpa_printf(MSG_DEBUG, 194 "EAP-SIM: Use result from external SIM processing"); 195 196 resp = conf->external_sim_resp; 197 conf->external_sim_resp = NULL; 198 199 if (os_strncmp(resp, "GSM-AUTH:", 9) != 0) { 200 wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized external SIM processing response"); 201 os_free(resp); 202 return -1; 203 } 204 205 pos = resp + 9; 206 for (i = 0; i < data->num_chal; i++) { 207 wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND", 208 data->rand[i], GSM_RAND_LEN); 209 210 if (hexstr2bin(pos, data->kc[i], EAP_SIM_KC_LEN) < 0) 211 goto invalid; 212 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc", 213 data->kc[i], EAP_SIM_KC_LEN); 214 pos += EAP_SIM_KC_LEN * 2; 215 if (*pos != ':') 216 goto invalid; 217 pos++; 218 219 if (hexstr2bin(pos, data->sres[i], EAP_SIM_SRES_LEN) < 0) 220 goto invalid; 221 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES", 222 data->sres[i], EAP_SIM_SRES_LEN); 223 pos += EAP_SIM_SRES_LEN * 2; 224 if (i + 1 < data->num_chal) { 225 if (*pos != ':') 226 goto invalid; 227 pos++; 228 } 229 } 230 231 os_free(resp); 232 return 0; 233 234invalid: 235 wpa_printf(MSG_DEBUG, "EAP-SIM: Invalid external SIM processing GSM-AUTH response"); 236 os_free(resp); 237 return -1; 238} 239 240 241static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data) 242{ 243 struct eap_peer_config *conf; 244 245 wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm"); 246 247 conf = eap_get_config(sm); 248 if (conf == NULL) 249 return -1; 250 251 if (sm->external_sim) { 252 if (conf->external_sim_resp) 253 return eap_sim_ext_sim_result(sm, data, conf); 254 else 255 return eap_sim_ext_sim_req(sm, data); 256 } 257 258#ifdef PCSC_FUNCS 259 if (conf->pcsc) { 260 if (scard_gsm_auth(sm->scard_ctx, data->rand[0], 261 data->sres[0], data->kc[0]) || 262 scard_gsm_auth(sm->scard_ctx, data->rand[1], 263 data->sres[1], data->kc[1]) || 264 (data->num_chal > 2 && 265 scard_gsm_auth(sm->scard_ctx, data->rand[2], 266 data->sres[2], data->kc[2]))) { 267 wpa_printf(MSG_DEBUG, "EAP-SIM: GSM SIM " 268 "authentication could not be completed"); 269 return -1; 270 } 271 return 0; 272 } 273#endif /* PCSC_FUNCS */ 274 275#ifdef CONFIG_SIM_SIMULATOR 276 if (conf->password) { 277 u8 opc[16], k[16]; 278 const char *pos; 279 size_t i; 280 wpa_printf(MSG_DEBUG, "EAP-SIM: Use internal GSM-Milenage " 281 "implementation for authentication"); 282 if (conf->password_len < 65) { 283 wpa_printf(MSG_DEBUG, "EAP-SIM: invalid GSM-Milenage " 284 "password"); 285 return -1; 286 } 287 pos = (const char *) conf->password; 288 if (hexstr2bin(pos, k, 16)) 289 return -1; 290 pos += 32; 291 if (*pos != ':') 292 return -1; 293 pos++; 294 295 if (hexstr2bin(pos, opc, 16)) 296 return -1; 297 298 for (i = 0; i < data->num_chal; i++) { 299 if (gsm_milenage(opc, k, data->rand[i], 300 data->sres[i], data->kc[i])) { 301 wpa_printf(MSG_DEBUG, "EAP-SIM: " 302 "GSM-Milenage authentication " 303 "could not be completed"); 304 return -1; 305 } 306 wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND", 307 data->rand[i], GSM_RAND_LEN); 308 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES", 309 data->sres[i], EAP_SIM_SRES_LEN); 310 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc", 311 data->kc[i], EAP_SIM_KC_LEN); 312 } 313 return 0; 314 } 315#endif /* CONFIG_SIM_SIMULATOR */ 316 317#ifdef CONFIG_SIM_HARDCODED 318 /* These hardcoded Kc and SRES values are used for testing. RAND to 319 * KC/SREC mapping is very bogus as far as real authentication is 320 * concerned, but it is quite useful for cases where the AS is rotating 321 * the order of pre-configured values. */ 322 { 323 size_t i; 324 325 wpa_printf(MSG_DEBUG, "EAP-SIM: Use hardcoded Kc and SRES " 326 "values for testing"); 327 328 for (i = 0; i < data->num_chal; i++) { 329 if (data->rand[i][0] == 0xaa) { 330 os_memcpy(data->kc[i], 331 "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7", 332 EAP_SIM_KC_LEN); 333 os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4", 334 EAP_SIM_SRES_LEN); 335 } else if (data->rand[i][0] == 0xbb) { 336 os_memcpy(data->kc[i], 337 "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7", 338 EAP_SIM_KC_LEN); 339 os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4", 340 EAP_SIM_SRES_LEN); 341 } else { 342 os_memcpy(data->kc[i], 343 "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7", 344 EAP_SIM_KC_LEN); 345 os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4", 346 EAP_SIM_SRES_LEN); 347 } 348 } 349 } 350 351 return 0; 352 353#else /* CONFIG_SIM_HARDCODED */ 354 355 wpa_printf(MSG_DEBUG, "EAP-SIM: No GSM authentication algorithm " 356 "enabled"); 357 return -1; 358 359#endif /* CONFIG_SIM_HARDCODED */ 360} 361 362 363static int eap_sim_supported_ver(int version) 364{ 365 return version == EAP_SIM_VERSION; 366} 367 368 369#define CLEAR_PSEUDONYM 0x01 370#define CLEAR_REAUTH_ID 0x02 371#define CLEAR_EAP_ID 0x04 372 373static void eap_sim_clear_identities(struct eap_sm *sm, 374 struct eap_sim_data *data, int id) 375{ 376 if ((id & CLEAR_PSEUDONYM) && data->pseudonym) { 377 wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old pseudonym"); 378 os_free(data->pseudonym); 379 data->pseudonym = NULL; 380 data->pseudonym_len = 0; 381 if (data->use_pseudonym) 382 eap_set_anon_id(sm, NULL, 0); 383 } 384 if ((id & CLEAR_REAUTH_ID) && data->reauth_id) { 385 wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old reauth_id"); 386 os_free(data->reauth_id); 387 data->reauth_id = NULL; 388 data->reauth_id_len = 0; 389 } 390 if ((id & CLEAR_EAP_ID) && data->last_eap_identity) { 391 wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old eap_id"); 392 os_free(data->last_eap_identity); 393 data->last_eap_identity = NULL; 394 data->last_eap_identity_len = 0; 395 } 396} 397 398 399static int eap_sim_learn_ids(struct eap_sm *sm, struct eap_sim_data *data, 400 struct eap_sim_attrs *attr) 401{ 402 if (attr->next_pseudonym) { 403 const u8 *identity = NULL; 404 size_t identity_len = 0; 405 const u8 *realm = NULL; 406 size_t realm_len = 0; 407 408 wpa_hexdump_ascii(MSG_DEBUG, 409 "EAP-SIM: (encr) AT_NEXT_PSEUDONYM", 410 attr->next_pseudonym, 411 attr->next_pseudonym_len); 412 os_free(data->pseudonym); 413 /* Look for the realm of the permanent identity */ 414 identity = eap_get_config_identity(sm, &identity_len); 415 if (identity) { 416 for (realm = identity, realm_len = identity_len; 417 realm_len > 0; realm_len--, realm++) { 418 if (*realm == '@') 419 break; 420 } 421 } 422 data->pseudonym = os_malloc(attr->next_pseudonym_len + 423 realm_len); 424 if (data->pseudonym == NULL) { 425 wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " 426 "next pseudonym"); 427 data->pseudonym_len = 0; 428 return -1; 429 } 430 os_memcpy(data->pseudonym, attr->next_pseudonym, 431 attr->next_pseudonym_len); 432 if (realm_len) { 433 os_memcpy(data->pseudonym + attr->next_pseudonym_len, 434 realm, realm_len); 435 } 436 data->pseudonym_len = attr->next_pseudonym_len + realm_len; 437 if (data->use_pseudonym) 438 eap_set_anon_id(sm, data->pseudonym, 439 data->pseudonym_len); 440 } 441 442 if (attr->next_reauth_id) { 443 os_free(data->reauth_id); 444 data->reauth_id = os_memdup(attr->next_reauth_id, 445 attr->next_reauth_id_len); 446 if (data->reauth_id == NULL) { 447 wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " 448 "next reauth_id"); 449 data->reauth_id_len = 0; 450 return -1; 451 } 452 data->reauth_id_len = attr->next_reauth_id_len; 453 wpa_hexdump_ascii(MSG_DEBUG, 454 "EAP-SIM: (encr) AT_NEXT_REAUTH_ID", 455 data->reauth_id, 456 data->reauth_id_len); 457 } 458 459 return 0; 460} 461 462 463static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id, 464 int err) 465{ 466 struct eap_sim_msg *msg; 467 468 eap_sim_state(data, FAILURE); 469 data->num_id_req = 0; 470 data->num_notification = 0; 471 472 wpa_printf(MSG_DEBUG, "EAP-SIM: Send Client-Error (error code %d)", 473 err); 474 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, 475 EAP_SIM_SUBTYPE_CLIENT_ERROR); 476 eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); 477 return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0); 478} 479 480 481static struct wpabuf * eap_sim_response_start(struct eap_sm *sm, 482 struct eap_sim_data *data, u8 id, 483 enum eap_sim_id_req id_req) 484{ 485 const u8 *identity = NULL; 486 size_t identity_len = 0; 487 struct eap_sim_msg *msg; 488 489 data->reauth = 0; 490 if (id_req == ANY_ID && data->reauth_id) { 491 identity = data->reauth_id; 492 identity_len = data->reauth_id_len; 493 data->reauth = 1; 494 } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && 495 data->pseudonym) { 496 identity = data->pseudonym; 497 identity_len = data->pseudonym_len; 498 eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID); 499 } else if (id_req != NO_ID_REQ) { 500 identity = eap_get_config_identity(sm, &identity_len); 501 if (identity) { 502 eap_sim_clear_identities(sm, data, CLEAR_PSEUDONYM | 503 CLEAR_REAUTH_ID); 504 } 505 } 506 if (id_req != NO_ID_REQ) 507 eap_sim_clear_identities(sm, data, CLEAR_EAP_ID); 508 509 wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id); 510 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, 511 EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); 512 if (!data->reauth) { 513 wpa_hexdump(MSG_DEBUG, " AT_NONCE_MT", 514 data->nonce_mt, EAP_SIM_NONCE_MT_LEN); 515 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0, 516 data->nonce_mt, EAP_SIM_NONCE_MT_LEN); 517 wpa_printf(MSG_DEBUG, " AT_SELECTED_VERSION %d", 518 data->selected_version); 519 eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION, 520 data->selected_version, NULL, 0); 521 } 522 523 if (identity) { 524 wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", 525 identity, identity_len); 526 eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, 527 identity, identity_len); 528 } 529 530 return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0); 531} 532 533 534static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data, 535 u8 id) 536{ 537 struct eap_sim_msg *msg; 538 539 wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", id); 540 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, 541 EAP_SIM_SUBTYPE_CHALLENGE); 542 if (data->use_result_ind) { 543 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 544 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 545 } 546 wpa_printf(MSG_DEBUG, " AT_MAC"); 547 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 548 return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, 549 (u8 *) data->sres, 550 data->num_chal * EAP_SIM_SRES_LEN); 551} 552 553 554static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data, 555 u8 id, int counter_too_small, 556 const u8 *nonce_s) 557{ 558 struct eap_sim_msg *msg; 559 unsigned int counter; 560 561 wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)", 562 id); 563 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, 564 EAP_SIM_SUBTYPE_REAUTHENTICATION); 565 wpa_printf(MSG_DEBUG, " AT_IV"); 566 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 567 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 568 569 if (counter_too_small) { 570 wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); 571 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); 572 counter = data->counter_too_small; 573 } else 574 counter = data->counter; 575 576 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); 577 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 578 579 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 580 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " 581 "AT_ENCR_DATA"); 582 eap_sim_msg_free(msg); 583 return NULL; 584 } 585 if (data->use_result_ind) { 586 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 587 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 588 } 589 wpa_printf(MSG_DEBUG, " AT_MAC"); 590 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 591 return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, nonce_s, 592 EAP_SIM_NONCE_S_LEN); 593} 594 595 596static struct wpabuf * eap_sim_response_notification(struct eap_sim_data *data, 597 u8 id, u16 notification) 598{ 599 struct eap_sim_msg *msg; 600 u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; 601 602 wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", id); 603 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, 604 EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION); 605 if (k_aut && data->reauth) { 606 wpa_printf(MSG_DEBUG, " AT_IV"); 607 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 608 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 609 EAP_SIM_AT_ENCR_DATA); 610 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); 611 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 612 NULL, 0); 613 if (eap_sim_msg_add_encr_end(msg, data->k_encr, 614 EAP_SIM_AT_PADDING)) { 615 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " 616 "AT_ENCR_DATA"); 617 eap_sim_msg_free(msg); 618 return NULL; 619 } 620 } 621 if (k_aut) { 622 wpa_printf(MSG_DEBUG, " AT_MAC"); 623 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 624 } 625 return eap_sim_msg_finish(msg, EAP_TYPE_SIM, k_aut, (u8 *) "", 0); 626} 627 628 629static struct wpabuf * eap_sim_process_start(struct eap_sm *sm, 630 struct eap_sim_data *data, u8 id, 631 struct eap_sim_attrs *attr) 632{ 633 int selected_version = -1, id_error; 634 size_t i; 635 u8 *pos; 636 637 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start"); 638 if (attr->version_list == NULL) { 639 wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in " 640 "SIM/Start"); 641 return eap_sim_client_error(data, id, 642 EAP_SIM_UNSUPPORTED_VERSION); 643 } 644 645 os_free(data->ver_list); 646 data->ver_list = os_memdup(attr->version_list, attr->version_list_len); 647 if (data->ver_list == NULL) { 648 wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate " 649 "memory for version list"); 650 return eap_sim_client_error(data, id, 651 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 652 } 653 data->ver_list_len = attr->version_list_len; 654 pos = data->ver_list; 655 for (i = 0; i < data->ver_list_len / 2; i++) { 656 int ver = pos[0] * 256 + pos[1]; 657 pos += 2; 658 if (eap_sim_supported_ver(ver)) { 659 selected_version = ver; 660 break; 661 } 662 } 663 if (selected_version < 0) { 664 wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported " 665 "version"); 666 return eap_sim_client_error(data, id, 667 EAP_SIM_UNSUPPORTED_VERSION); 668 } 669 wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d", 670 selected_version); 671 data->selected_version = selected_version; 672 673 id_error = 0; 674 switch (attr->id_req) { 675 case NO_ID_REQ: 676 break; 677 case ANY_ID: 678 if (data->num_id_req > 0) 679 id_error++; 680 data->num_id_req++; 681 break; 682 case FULLAUTH_ID: 683 if (data->num_id_req > 1) 684 id_error++; 685 data->num_id_req++; 686 break; 687 case PERMANENT_ID: 688 if (data->num_id_req > 2) 689 id_error++; 690 data->num_id_req++; 691 break; 692 } 693 if (id_error) { 694 wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests " 695 "used within one authentication"); 696 return eap_sim_client_error(data, id, 697 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 698 } 699 700 return eap_sim_response_start(sm, data, id, attr->id_req); 701} 702 703 704static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm, 705 struct eap_sim_data *data, 706 u8 id, 707 const struct wpabuf *reqData, 708 struct eap_sim_attrs *attr) 709{ 710 const u8 *identity; 711 size_t identity_len; 712 struct eap_sim_attrs eattr; 713 int res; 714 715 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge"); 716 data->reauth = 0; 717 if (!attr->mac || !attr->rand) { 718 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " 719 "did not include%s%s", 720 !attr->mac ? " AT_MAC" : "", 721 !attr->rand ? " AT_RAND" : ""); 722 return eap_sim_client_error(data, id, 723 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 724 } 725 726 wpa_printf(MSG_DEBUG, "EAP-SIM: %lu challenges", 727 (unsigned long) attr->num_chal); 728 if (attr->num_chal < data->min_num_chal) { 729 wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of " 730 "challenges (%lu)", (unsigned long) attr->num_chal); 731 return eap_sim_client_error(data, id, 732 EAP_SIM_INSUFFICIENT_NUM_OF_CHAL); 733 } 734 if (attr->num_chal > 3) { 735 wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges " 736 "(%lu)", (unsigned long) attr->num_chal); 737 return eap_sim_client_error(data, id, 738 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 739 } 740 741 /* Verify that RANDs are different */ 742 if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN, 743 GSM_RAND_LEN) == 0 || 744 (attr->num_chal > 2 && 745 (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN, 746 GSM_RAND_LEN) == 0 || 747 os_memcmp(attr->rand + GSM_RAND_LEN, 748 attr->rand + 2 * GSM_RAND_LEN, 749 GSM_RAND_LEN) == 0))) { 750 wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times"); 751 return eap_sim_client_error(data, id, 752 EAP_SIM_RAND_NOT_FRESH); 753 } 754 755 os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN); 756 data->num_chal = attr->num_chal; 757 758 res = eap_sim_gsm_auth(sm, data); 759 if (res > 0) { 760 wpa_printf(MSG_DEBUG, "EAP-SIM: Wait for external SIM processing"); 761 return NULL; 762 } 763 if (res) { 764 wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed"); 765 return eap_sim_client_error(data, id, 766 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 767 } 768 if (data->last_eap_identity) { 769 identity = data->last_eap_identity; 770 identity_len = data->last_eap_identity_len; 771 } else if (data->pseudonym) { 772 identity = data->pseudonym; 773 identity_len = data->pseudonym_len; 774 } else { 775 struct eap_peer_config *config; 776 777 config = eap_get_config(sm); 778 if (config && config->imsi_identity) { 779 identity = config->imsi_identity; 780 identity_len = config->imsi_identity_len; 781 } else { 782 identity = eap_get_config_identity(sm, &identity_len); 783 } 784 } 785 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK " 786 "derivation", identity, identity_len); 787 eap_sim_derive_mk(identity, identity_len, data->nonce_mt, 788 data->selected_version, data->ver_list, 789 data->ver_list_len, data->num_chal, 790 (const u8 *) data->kc, data->mk); 791 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 792 data->emsk); 793 if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, data->nonce_mt, 794 EAP_SIM_NONCE_MT_LEN)) { 795 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " 796 "used invalid AT_MAC"); 797 return eap_sim_client_error(data, id, 798 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 799 } 800 801 /* Old reauthentication identity must not be used anymore. In 802 * other words, if no new reauth identity is received, full 803 * authentication will be used on next reauthentication (using 804 * pseudonym identity or permanent identity). */ 805 eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 806 807 if (attr->encr_data) { 808 u8 *decrypted; 809 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 810 attr->encr_data_len, attr->iv, 811 &eattr, 0); 812 if (decrypted == NULL) { 813 return eap_sim_client_error( 814 data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET); 815 } 816 eap_sim_learn_ids(sm, data, &eattr); 817 os_free(decrypted); 818 } 819 820 if (data->result_ind && attr->result_ind) 821 data->use_result_ind = 1; 822 823 if (data->state != FAILURE) { 824 eap_sim_state(data, data->use_result_ind ? 825 RESULT_SUCCESS : SUCCESS); 826 } 827 828 data->num_id_req = 0; 829 data->num_notification = 0; 830 /* RFC 4186 specifies that counter is initialized to one after 831 * fullauth, but initializing it to zero makes it easier to implement 832 * reauth verification. */ 833 data->counter = 0; 834 return eap_sim_response_challenge(data, id); 835} 836 837 838static int eap_sim_process_notification_reauth(struct eap_sim_data *data, 839 struct eap_sim_attrs *attr) 840{ 841 struct eap_sim_attrs eattr; 842 u8 *decrypted; 843 844 if (attr->encr_data == NULL || attr->iv == NULL) { 845 wpa_printf(MSG_WARNING, "EAP-SIM: Notification message after " 846 "reauth did not include encrypted data"); 847 return -1; 848 } 849 850 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 851 attr->encr_data_len, attr->iv, &eattr, 852 0); 853 if (decrypted == NULL) { 854 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " 855 "data from notification message"); 856 return -1; 857 } 858 859 if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) { 860 wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification " 861 "message does not match with counter in reauth " 862 "message"); 863 os_free(decrypted); 864 return -1; 865 } 866 867 os_free(decrypted); 868 return 0; 869} 870 871 872static int eap_sim_process_notification_auth(struct eap_sim_data *data, 873 const struct wpabuf *reqData, 874 struct eap_sim_attrs *attr) 875{ 876 if (attr->mac == NULL) { 877 wpa_printf(MSG_INFO, "EAP-SIM: no AT_MAC in after_auth " 878 "Notification message"); 879 return -1; 880 } 881 882 if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0)) 883 { 884 wpa_printf(MSG_WARNING, "EAP-SIM: Notification message " 885 "used invalid AT_MAC"); 886 return -1; 887 } 888 889 if (data->reauth && 890 eap_sim_process_notification_reauth(data, attr)) { 891 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification " 892 "message after reauth"); 893 return -1; 894 } 895 896 return 0; 897} 898 899 900static struct wpabuf * eap_sim_process_notification( 901 struct eap_sm *sm, struct eap_sim_data *data, u8 id, 902 const struct wpabuf *reqData, struct eap_sim_attrs *attr) 903{ 904 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Notification"); 905 if (data->num_notification > 0) { 906 wpa_printf(MSG_INFO, "EAP-SIM: too many notification " 907 "rounds (only one allowed)"); 908 return eap_sim_client_error(data, id, 909 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 910 } 911 data->num_notification++; 912 if (attr->notification == -1) { 913 wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in " 914 "Notification message"); 915 return eap_sim_client_error(data, id, 916 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 917 } 918 919 if ((attr->notification & 0x4000) == 0 && 920 eap_sim_process_notification_auth(data, reqData, attr)) { 921 return eap_sim_client_error(data, id, 922 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 923 } 924 925 eap_sim_report_notification(sm->msg_ctx, attr->notification, 0); 926 if (attr->notification >= 0 && attr->notification < 32768) { 927 data->error_code = attr->notification; 928 eap_sim_state(data, FAILURE); 929 } else if (attr->notification == EAP_SIM_SUCCESS && 930 data->state == RESULT_SUCCESS) 931 eap_sim_state(data, SUCCESS); 932 return eap_sim_response_notification(data, id, attr->notification); 933} 934 935 936static struct wpabuf * eap_sim_process_reauthentication( 937 struct eap_sm *sm, struct eap_sim_data *data, u8 id, 938 const struct wpabuf *reqData, struct eap_sim_attrs *attr) 939{ 940 struct eap_sim_attrs eattr; 941 u8 *decrypted; 942 943 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication"); 944 945 if (data->reauth_id == NULL) { 946 wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying " 947 "reauthentication, but no reauth_id available"); 948 return eap_sim_client_error(data, id, 949 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 950 } 951 952 data->reauth = 1; 953 if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0)) 954 { 955 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " 956 "did not have valid AT_MAC"); 957 return eap_sim_client_error(data, id, 958 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 959 } 960 961 if (attr->encr_data == NULL || attr->iv == NULL) { 962 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " 963 "message did not include encrypted data"); 964 return eap_sim_client_error(data, id, 965 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 966 } 967 968 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 969 attr->encr_data_len, attr->iv, &eattr, 970 0); 971 if (decrypted == NULL) { 972 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " 973 "data from reauthentication message"); 974 return eap_sim_client_error(data, id, 975 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 976 } 977 978 if (eattr.nonce_s == NULL || eattr.counter < 0) { 979 wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet", 980 !eattr.nonce_s ? " AT_NONCE_S" : "", 981 eattr.counter < 0 ? " AT_COUNTER" : ""); 982 os_free(decrypted); 983 return eap_sim_client_error(data, id, 984 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 985 } 986 987 if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { 988 struct wpabuf *res; 989 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter " 990 "(%d <= %d)", eattr.counter, data->counter); 991 data->counter_too_small = eattr.counter; 992 993 /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current 994 * reauth_id must not be used to start a new reauthentication. 995 * However, since it was used in the last EAP-Response-Identity 996 * packet, it has to saved for the following fullauth to be 997 * used in MK derivation. */ 998 os_free(data->last_eap_identity); 999 data->last_eap_identity = data->reauth_id; 1000 data->last_eap_identity_len = data->reauth_id_len; 1001 data->reauth_id = NULL; 1002 data->reauth_id_len = 0; 1003 1004 res = eap_sim_response_reauth(data, id, 1, eattr.nonce_s); 1005 os_free(decrypted); 1006 1007 return res; 1008 } 1009 data->counter = eattr.counter; 1010 1011 os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); 1012 wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S", 1013 data->nonce_s, EAP_SIM_NONCE_S_LEN); 1014 1015 eap_sim_derive_keys_reauth(data->counter, 1016 data->reauth_id, data->reauth_id_len, 1017 data->nonce_s, data->mk, data->msk, 1018 data->emsk); 1019 eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 1020 eap_sim_learn_ids(sm, data, &eattr); 1021 1022 if (data->result_ind && attr->result_ind) 1023 data->use_result_ind = 1; 1024 1025 if (data->state != FAILURE) { 1026 eap_sim_state(data, data->use_result_ind ? 1027 RESULT_SUCCESS : SUCCESS); 1028 } 1029 1030 data->num_id_req = 0; 1031 data->num_notification = 0; 1032 if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) { 1033 wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of " 1034 "fast reauths performed - force fullauth"); 1035 eap_sim_clear_identities(sm, data, 1036 CLEAR_REAUTH_ID | CLEAR_EAP_ID); 1037 } 1038 os_free(decrypted); 1039 return eap_sim_response_reauth(data, id, 0, data->nonce_s); 1040} 1041 1042 1043static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv, 1044 struct eap_method_ret *ret, 1045 const struct wpabuf *reqData) 1046{ 1047 struct eap_sim_data *data = priv; 1048 const struct eap_hdr *req; 1049 u8 subtype, id; 1050 struct wpabuf *res; 1051 const u8 *pos; 1052 struct eap_sim_attrs attr; 1053 size_t len; 1054 1055 wpa_hexdump_buf(MSG_DEBUG, "EAP-SIM: EAP data", reqData); 1056 if (eap_get_config_identity(sm, &len) == NULL) { 1057 wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured"); 1058 eap_sm_request_identity(sm); 1059 ret->ignore = TRUE; 1060 return NULL; 1061 } 1062 1063 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len); 1064 if (pos == NULL || len < 3) { 1065 ret->ignore = TRUE; 1066 return NULL; 1067 } 1068 req = wpabuf_head(reqData); 1069 id = req->identifier; 1070 len = be_to_host16(req->length); 1071 1072 ret->ignore = FALSE; 1073 ret->methodState = METHOD_MAY_CONT; 1074 ret->decision = DECISION_FAIL; 1075 ret->allowNotifications = TRUE; 1076 1077 subtype = *pos++; 1078 wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype); 1079 pos += 2; /* Reserved */ 1080 1081 if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 0, 1082 0)) { 1083 res = eap_sim_client_error(data, id, 1084 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 1085 goto done; 1086 } 1087 1088 switch (subtype) { 1089 case EAP_SIM_SUBTYPE_START: 1090 res = eap_sim_process_start(sm, data, id, &attr); 1091 break; 1092 case EAP_SIM_SUBTYPE_CHALLENGE: 1093 res = eap_sim_process_challenge(sm, data, id, reqData, &attr); 1094 break; 1095 case EAP_SIM_SUBTYPE_NOTIFICATION: 1096 res = eap_sim_process_notification(sm, data, id, reqData, 1097 &attr); 1098 break; 1099 case EAP_SIM_SUBTYPE_REAUTHENTICATION: 1100 res = eap_sim_process_reauthentication(sm, data, id, reqData, 1101 &attr); 1102 break; 1103 case EAP_SIM_SUBTYPE_CLIENT_ERROR: 1104 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error"); 1105 res = eap_sim_client_error(data, id, 1106 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 1107 break; 1108 default: 1109 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype); 1110 res = eap_sim_client_error(data, id, 1111 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 1112 break; 1113 } 1114 1115done: 1116 if (data->state == FAILURE) { 1117 ret->decision = DECISION_FAIL; 1118 ret->methodState = METHOD_DONE; 1119 } else if (data->state == SUCCESS) { 1120 ret->decision = data->use_result_ind ? 1121 DECISION_UNCOND_SUCC : DECISION_COND_SUCC; 1122 ret->methodState = data->use_result_ind ? 1123 METHOD_DONE : METHOD_MAY_CONT; 1124 } else if (data->state == RESULT_SUCCESS) 1125 ret->methodState = METHOD_CONT; 1126 1127 if (ret->methodState == METHOD_DONE) { 1128 ret->allowNotifications = FALSE; 1129 } 1130 1131 return res; 1132} 1133 1134 1135static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv) 1136{ 1137 struct eap_sim_data *data = priv; 1138 return data->pseudonym || data->reauth_id; 1139} 1140 1141 1142static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv) 1143{ 1144 struct eap_sim_data *data = priv; 1145 eap_sim_clear_identities(sm, data, CLEAR_EAP_ID); 1146 data->use_result_ind = 0; 1147 eap_sim_clear_keys(data, 1); 1148} 1149 1150 1151static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv) 1152{ 1153 struct eap_sim_data *data = priv; 1154 if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { 1155 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " 1156 "for NONCE_MT"); 1157 eap_sim_deinit(sm, data); 1158 return NULL; 1159 } 1160 data->num_id_req = 0; 1161 data->num_notification = 0; 1162 eap_sim_state(data, CONTINUE); 1163 return priv; 1164} 1165 1166 1167static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv, 1168 size_t *len) 1169{ 1170 struct eap_sim_data *data = priv; 1171 1172 if (data->reauth_id) { 1173 *len = data->reauth_id_len; 1174 return data->reauth_id; 1175 } 1176 1177 if (data->pseudonym) { 1178 *len = data->pseudonym_len; 1179 return data->pseudonym; 1180 } 1181 1182 return NULL; 1183} 1184 1185 1186static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv) 1187{ 1188 struct eap_sim_data *data = priv; 1189 return data->state == SUCCESS; 1190} 1191 1192 1193static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) 1194{ 1195 struct eap_sim_data *data = priv; 1196 u8 *key; 1197 1198 if (data->state != SUCCESS) 1199 return NULL; 1200 1201 key = os_memdup(data->msk, EAP_SIM_KEYING_DATA_LEN); 1202 if (key == NULL) 1203 return NULL; 1204 1205 *len = EAP_SIM_KEYING_DATA_LEN; 1206 1207 return key; 1208} 1209 1210 1211static u8 * eap_sim_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 1212{ 1213 struct eap_sim_data *data = priv; 1214 u8 *id; 1215 1216 if (data->state != SUCCESS) 1217 return NULL; 1218 1219 *len = 1 + data->num_chal * GSM_RAND_LEN + EAP_SIM_NONCE_MT_LEN; 1220 id = os_malloc(*len); 1221 if (id == NULL) 1222 return NULL; 1223 1224 id[0] = EAP_TYPE_SIM; 1225 os_memcpy(id + 1, data->rand, data->num_chal * GSM_RAND_LEN); 1226 os_memcpy(id + 1 + data->num_chal * GSM_RAND_LEN, data->nonce_mt, 1227 EAP_SIM_NONCE_MT_LEN); 1228 wpa_hexdump(MSG_DEBUG, "EAP-SIM: Derived Session-Id", id, *len); 1229 1230 return id; 1231} 1232 1233 1234static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 1235{ 1236 struct eap_sim_data *data = priv; 1237 u8 *key; 1238 1239 if (data->state != SUCCESS) 1240 return NULL; 1241 1242 key = os_memdup(data->emsk, EAP_EMSK_LEN); 1243 if (key == NULL) 1244 return NULL; 1245 1246 *len = EAP_EMSK_LEN; 1247 1248 return key; 1249} 1250 1251static int eap_sim_get_error_code(void *priv) 1252{ 1253 struct eap_sim_data *data = priv; 1254 1255 if (!data) 1256 return NO_EAP_METHOD_ERROR; 1257 1258 int current_data_error = data->error_code; 1259 1260 /* Now reset for next transaction */ 1261 data->error_code = NO_EAP_METHOD_ERROR; 1262 1263 return current_data_error; 1264} 1265 1266int eap_peer_sim_register(void) 1267{ 1268 struct eap_method *eap; 1269 1270 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 1271 EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); 1272 if (eap == NULL) 1273 return -1; 1274 1275 eap->init = eap_sim_init; 1276 eap->deinit = eap_sim_deinit; 1277 eap->process = eap_sim_process; 1278 eap->isKeyAvailable = eap_sim_isKeyAvailable; 1279 eap->getKey = eap_sim_getKey; 1280 eap->getSessionId = eap_sim_get_session_id; 1281 eap->has_reauth_data = eap_sim_has_reauth_data; 1282 eap->deinit_for_reauth = eap_sim_deinit_for_reauth; 1283 eap->init_for_reauth = eap_sim_init_for_reauth; 1284 eap->get_identity = eap_sim_get_identity; 1285 eap->get_emsk = eap_sim_get_emsk; 1286 eap->get_error_code = eap_sim_get_error_code; 1287 1288 return eap_peer_method_register(eap); 1289} 1290