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