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