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