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 const u8 *nonce_s) 443 { 444 struct eap_sim_msg *msg; 445 unsigned int counter; 446 447 wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)", 448 id); 449 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, 450 EAP_SIM_SUBTYPE_REAUTHENTICATION); 451 wpa_printf(MSG_DEBUG, " AT_IV"); 452 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 453 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 454 455 if (counter_too_small) { 456 wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); 457 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); 458 counter = data->counter_too_small; 459 } else 460 counter = data->counter; 461 462 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); 463 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 464 465 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 466 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " 467 "AT_ENCR_DATA"); 468 eap_sim_msg_free(msg); 469 return NULL; 470 } 471 if (data->use_result_ind) { 472 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 473 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 474 } 475 wpa_printf(MSG_DEBUG, " AT_MAC"); 476 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 477 return eap_sim_msg_finish(msg, data->k_aut, nonce_s, 478 EAP_SIM_NONCE_S_LEN); 479 } 480 481 482 static struct wpabuf * eap_sim_response_notification(struct eap_sim_data *data, 483 u8 id, u16 notification) 484 { 485 struct eap_sim_msg *msg; 486 u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; 487 488 wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", id); 489 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, 490 EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION); 491 if (k_aut && data->reauth) { 492 wpa_printf(MSG_DEBUG, " AT_IV"); 493 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 494 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 495 EAP_SIM_AT_ENCR_DATA); 496 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); 497 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 498 NULL, 0); 499 if (eap_sim_msg_add_encr_end(msg, data->k_encr, 500 EAP_SIM_AT_PADDING)) { 501 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " 502 "AT_ENCR_DATA"); 503 eap_sim_msg_free(msg); 504 return NULL; 505 } 506 } 507 if (k_aut) { 508 wpa_printf(MSG_DEBUG, " AT_MAC"); 509 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 510 } 511 return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0); 512 } 513 514 515 static struct wpabuf * eap_sim_process_start(struct eap_sm *sm, 516 struct eap_sim_data *data, u8 id, 517 struct eap_sim_attrs *attr) 518 { 519 int selected_version = -1, id_error; 520 size_t i; 521 u8 *pos; 522 523 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start"); 524 if (attr->version_list == NULL) { 525 wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in " 526 "SIM/Start"); 527 return eap_sim_client_error(data, id, 528 EAP_SIM_UNSUPPORTED_VERSION); 529 } 530 531 os_free(data->ver_list); 532 data->ver_list = os_malloc(attr->version_list_len); 533 if (data->ver_list == NULL) { 534 wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate " 535 "memory for version list"); 536 return eap_sim_client_error(data, id, 537 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 538 } 539 os_memcpy(data->ver_list, attr->version_list, attr->version_list_len); 540 data->ver_list_len = attr->version_list_len; 541 pos = data->ver_list; 542 for (i = 0; i < data->ver_list_len / 2; i++) { 543 int ver = pos[0] * 256 + pos[1]; 544 pos += 2; 545 if (eap_sim_supported_ver(ver)) { 546 selected_version = ver; 547 break; 548 } 549 } 550 if (selected_version < 0) { 551 wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported " 552 "version"); 553 return eap_sim_client_error(data, id, 554 EAP_SIM_UNSUPPORTED_VERSION); 555 } 556 wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d", 557 selected_version); 558 data->selected_version = selected_version; 559 560 id_error = 0; 561 switch (attr->id_req) { 562 case NO_ID_REQ: 563 break; 564 case ANY_ID: 565 if (data->num_id_req > 0) 566 id_error++; 567 data->num_id_req++; 568 break; 569 case FULLAUTH_ID: 570 if (data->num_id_req > 1) 571 id_error++; 572 data->num_id_req++; 573 break; 574 case PERMANENT_ID: 575 if (data->num_id_req > 2) 576 id_error++; 577 data->num_id_req++; 578 break; 579 } 580 if (id_error) { 581 wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests " 582 "used within one authentication"); 583 return eap_sim_client_error(data, id, 584 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 585 } 586 587 return eap_sim_response_start(sm, data, id, attr->id_req); 588 } 589 590 591 static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm, 592 struct eap_sim_data *data, 593 u8 id, 594 const struct wpabuf *reqData, 595 struct eap_sim_attrs *attr) 596 { 597 const u8 *identity; 598 size_t identity_len; 599 struct eap_sim_attrs eattr; 600 601 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge"); 602 data->reauth = 0; 603 if (!attr->mac || !attr->rand) { 604 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " 605 "did not include%s%s", 606 !attr->mac ? " AT_MAC" : "", 607 !attr->rand ? " AT_RAND" : ""); 608 return eap_sim_client_error(data, id, 609 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 610 } 611 612 wpa_printf(MSG_DEBUG, "EAP-SIM: %lu challenges", 613 (unsigned long) attr->num_chal); 614 if (attr->num_chal < data->min_num_chal) { 615 wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of " 616 "challenges (%lu)", (unsigned long) attr->num_chal); 617 return eap_sim_client_error(data, id, 618 EAP_SIM_INSUFFICIENT_NUM_OF_CHAL); 619 } 620 if (attr->num_chal > 3) { 621 wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges " 622 "(%lu)", (unsigned long) attr->num_chal); 623 return eap_sim_client_error(data, id, 624 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 625 } 626 627 /* Verify that RANDs are different */ 628 if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN, 629 GSM_RAND_LEN) == 0 || 630 (attr->num_chal > 2 && 631 (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN, 632 GSM_RAND_LEN) == 0 || 633 os_memcmp(attr->rand + GSM_RAND_LEN, 634 attr->rand + 2 * GSM_RAND_LEN, 635 GSM_RAND_LEN) == 0))) { 636 wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times"); 637 return eap_sim_client_error(data, id, 638 EAP_SIM_RAND_NOT_FRESH); 639 } 640 641 os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN); 642 data->num_chal = attr->num_chal; 643 644 if (eap_sim_gsm_auth(sm, data)) { 645 wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed"); 646 return eap_sim_client_error(data, id, 647 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 648 } 649 if (data->last_eap_identity) { 650 identity = data->last_eap_identity; 651 identity_len = data->last_eap_identity_len; 652 } else if (data->pseudonym) { 653 identity = data->pseudonym; 654 identity_len = data->pseudonym_len; 655 } else 656 identity = eap_get_config_identity(sm, &identity_len); 657 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK " 658 "derivation", identity, identity_len); 659 eap_sim_derive_mk(identity, identity_len, data->nonce_mt, 660 data->selected_version, data->ver_list, 661 data->ver_list_len, data->num_chal, 662 (const u8 *) data->kc, data->mk); 663 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 664 data->emsk); 665 if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, data->nonce_mt, 666 EAP_SIM_NONCE_MT_LEN)) { 667 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " 668 "used invalid AT_MAC"); 669 return eap_sim_client_error(data, id, 670 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 671 } 672 673 /* Old reauthentication identity must not be used anymore. In 674 * other words, if no new reauth identity is received, full 675 * authentication will be used on next reauthentication (using 676 * pseudonym identity or permanent identity). */ 677 eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 678 679 if (attr->encr_data) { 680 u8 *decrypted; 681 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 682 attr->encr_data_len, attr->iv, 683 &eattr, 0); 684 if (decrypted == NULL) { 685 return eap_sim_client_error( 686 data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET); 687 } 688 eap_sim_learn_ids(sm, data, &eattr); 689 os_free(decrypted); 690 } 691 692 if (data->result_ind && attr->result_ind) 693 data->use_result_ind = 1; 694 695 if (data->state != FAILURE && data->state != RESULT_FAILURE) { 696 eap_sim_state(data, data->use_result_ind ? 697 RESULT_SUCCESS : SUCCESS); 698 } 699 700 data->num_id_req = 0; 701 data->num_notification = 0; 702 /* RFC 4186 specifies that counter is initialized to one after 703 * fullauth, but initializing it to zero makes it easier to implement 704 * reauth verification. */ 705 data->counter = 0; 706 return eap_sim_response_challenge(data, id); 707 } 708 709 710 static int eap_sim_process_notification_reauth(struct eap_sim_data *data, 711 struct eap_sim_attrs *attr) 712 { 713 struct eap_sim_attrs eattr; 714 u8 *decrypted; 715 716 if (attr->encr_data == NULL || attr->iv == NULL) { 717 wpa_printf(MSG_WARNING, "EAP-SIM: Notification message after " 718 "reauth did not include encrypted data"); 719 return -1; 720 } 721 722 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 723 attr->encr_data_len, attr->iv, &eattr, 724 0); 725 if (decrypted == NULL) { 726 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " 727 "data from notification message"); 728 return -1; 729 } 730 731 if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) { 732 wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification " 733 "message does not match with counter in reauth " 734 "message"); 735 os_free(decrypted); 736 return -1; 737 } 738 739 os_free(decrypted); 740 return 0; 741 } 742 743 744 static int eap_sim_process_notification_auth(struct eap_sim_data *data, 745 const struct wpabuf *reqData, 746 struct eap_sim_attrs *attr) 747 { 748 if (attr->mac == NULL) { 749 wpa_printf(MSG_INFO, "EAP-SIM: no AT_MAC in after_auth " 750 "Notification message"); 751 return -1; 752 } 753 754 if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0)) 755 { 756 wpa_printf(MSG_WARNING, "EAP-SIM: Notification message " 757 "used invalid AT_MAC"); 758 return -1; 759 } 760 761 if (data->reauth && 762 eap_sim_process_notification_reauth(data, attr)) { 763 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification " 764 "message after reauth"); 765 return -1; 766 } 767 768 return 0; 769 } 770 771 772 static struct wpabuf * eap_sim_process_notification( 773 struct eap_sm *sm, struct eap_sim_data *data, u8 id, 774 const struct wpabuf *reqData, struct eap_sim_attrs *attr) 775 { 776 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Notification"); 777 if (data->num_notification > 0) { 778 wpa_printf(MSG_INFO, "EAP-SIM: too many notification " 779 "rounds (only one allowed)"); 780 return eap_sim_client_error(data, id, 781 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 782 } 783 data->num_notification++; 784 if (attr->notification == -1) { 785 wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in " 786 "Notification message"); 787 return eap_sim_client_error(data, id, 788 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 789 } 790 791 if ((attr->notification & 0x4000) == 0 && 792 eap_sim_process_notification_auth(data, reqData, attr)) { 793 return eap_sim_client_error(data, id, 794 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 795 } 796 797 eap_sim_report_notification(sm->msg_ctx, attr->notification, 0); 798 if (attr->notification >= 0 && attr->notification < 32768) { 799 eap_sim_state(data, FAILURE); 800 } else if (attr->notification == EAP_SIM_SUCCESS && 801 data->state == RESULT_SUCCESS) 802 eap_sim_state(data, SUCCESS); 803 return eap_sim_response_notification(data, id, attr->notification); 804 } 805 806 807 static struct wpabuf * eap_sim_process_reauthentication( 808 struct eap_sm *sm, struct eap_sim_data *data, u8 id, 809 const struct wpabuf *reqData, struct eap_sim_attrs *attr) 810 { 811 struct eap_sim_attrs eattr; 812 u8 *decrypted; 813 814 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication"); 815 816 if (data->reauth_id == NULL) { 817 wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying " 818 "reauthentication, but no reauth_id available"); 819 return eap_sim_client_error(data, id, 820 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 821 } 822 823 data->reauth = 1; 824 if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0)) 825 { 826 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " 827 "did not have valid AT_MAC"); 828 return eap_sim_client_error(data, id, 829 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 830 } 831 832 if (attr->encr_data == NULL || attr->iv == NULL) { 833 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " 834 "message did not include encrypted data"); 835 return eap_sim_client_error(data, id, 836 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 837 } 838 839 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 840 attr->encr_data_len, attr->iv, &eattr, 841 0); 842 if (decrypted == NULL) { 843 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " 844 "data from reauthentication message"); 845 return eap_sim_client_error(data, id, 846 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 847 } 848 849 if (eattr.nonce_s == NULL || eattr.counter < 0) { 850 wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet", 851 !eattr.nonce_s ? " AT_NONCE_S" : "", 852 eattr.counter < 0 ? " AT_COUNTER" : ""); 853 os_free(decrypted); 854 return eap_sim_client_error(data, id, 855 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 856 } 857 858 if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { 859 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter " 860 "(%d <= %d)", eattr.counter, data->counter); 861 data->counter_too_small = eattr.counter; 862 /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current 863 * reauth_id must not be used to start a new reauthentication. 864 * However, since it was used in the last EAP-Response-Identity 865 * packet, it has to saved for the following fullauth to be 866 * used in MK derivation. */ 867 os_free(data->last_eap_identity); 868 data->last_eap_identity = data->reauth_id; 869 data->last_eap_identity_len = data->reauth_id_len; 870 data->reauth_id = NULL; 871 data->reauth_id_len = 0; 872 os_free(decrypted); 873 return eap_sim_response_reauth(data, id, 1, eattr.nonce_s); 874 } 875 data->counter = eattr.counter; 876 877 os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); 878 wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S", 879 data->nonce_s, EAP_SIM_NONCE_S_LEN); 880 881 eap_sim_derive_keys_reauth(data->counter, 882 data->reauth_id, data->reauth_id_len, 883 data->nonce_s, data->mk, data->msk, 884 data->emsk); 885 eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 886 eap_sim_learn_ids(sm, data, &eattr); 887 888 if (data->result_ind && attr->result_ind) 889 data->use_result_ind = 1; 890 891 if (data->state != FAILURE && data->state != RESULT_FAILURE) { 892 eap_sim_state(data, data->use_result_ind ? 893 RESULT_SUCCESS : SUCCESS); 894 } 895 896 data->num_id_req = 0; 897 data->num_notification = 0; 898 if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) { 899 wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of " 900 "fast reauths performed - force fullauth"); 901 eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 902 } 903 os_free(decrypted); 904 return eap_sim_response_reauth(data, id, 0, data->nonce_s); 905 } 906 907 908 static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv, 909 struct eap_method_ret *ret, 910 const struct wpabuf *reqData) 911 { 912 struct eap_sim_data *data = priv; 913 const struct eap_hdr *req; 914 u8 subtype, id; 915 struct wpabuf *res; 916 const u8 *pos; 917 struct eap_sim_attrs attr; 918 size_t len; 919 920 wpa_hexdump_buf(MSG_DEBUG, "EAP-SIM: EAP data", reqData); 921 if (eap_get_config_identity(sm, &len) == NULL) { 922 wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured"); 923 eap_sm_request_identity(sm); 924 ret->ignore = TRUE; 925 return NULL; 926 } 927 928 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len); 929 if (pos == NULL || len < 1) { 930 ret->ignore = TRUE; 931 return NULL; 932 } 933 req = wpabuf_head(reqData); 934 id = req->identifier; 935 len = be_to_host16(req->length); 936 937 ret->ignore = FALSE; 938 ret->methodState = METHOD_MAY_CONT; 939 ret->decision = DECISION_FAIL; 940 ret->allowNotifications = TRUE; 941 942 subtype = *pos++; 943 wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype); 944 pos += 2; /* Reserved */ 945 946 if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 0, 947 0)) { 948 res = eap_sim_client_error(data, id, 949 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 950 goto done; 951 } 952 953 switch (subtype) { 954 case EAP_SIM_SUBTYPE_START: 955 res = eap_sim_process_start(sm, data, id, &attr); 956 break; 957 case EAP_SIM_SUBTYPE_CHALLENGE: 958 res = eap_sim_process_challenge(sm, data, id, reqData, &attr); 959 break; 960 case EAP_SIM_SUBTYPE_NOTIFICATION: 961 res = eap_sim_process_notification(sm, data, id, reqData, 962 &attr); 963 break; 964 case EAP_SIM_SUBTYPE_REAUTHENTICATION: 965 res = eap_sim_process_reauthentication(sm, data, id, reqData, 966 &attr); 967 break; 968 case EAP_SIM_SUBTYPE_CLIENT_ERROR: 969 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error"); 970 res = eap_sim_client_error(data, id, 971 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 972 break; 973 default: 974 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype); 975 res = eap_sim_client_error(data, id, 976 EAP_SIM_UNABLE_TO_PROCESS_PACKET); 977 break; 978 } 979 980 done: 981 if (data->state == FAILURE) { 982 ret->decision = DECISION_FAIL; 983 ret->methodState = METHOD_DONE; 984 } else if (data->state == SUCCESS) { 985 ret->decision = data->use_result_ind ? 986 DECISION_UNCOND_SUCC : DECISION_COND_SUCC; 987 ret->methodState = data->use_result_ind ? 988 METHOD_DONE : METHOD_MAY_CONT; 989 } else if (data->state == RESULT_FAILURE) 990 ret->methodState = METHOD_CONT; 991 else if (data->state == RESULT_SUCCESS) 992 ret->methodState = METHOD_CONT; 993 994 if (ret->methodState == METHOD_DONE) { 995 ret->allowNotifications = FALSE; 996 } 997 998 return res; 999 } 1000 1001 1002 static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv) 1003 { 1004 struct eap_sim_data *data = priv; 1005 return data->pseudonym || data->reauth_id; 1006 } 1007 1008 1009 static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv) 1010 { 1011 struct eap_sim_data *data = priv; 1012 eap_sim_clear_identities(data, CLEAR_EAP_ID); 1013 data->use_result_ind = 0; 1014 } 1015 1016 1017 static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv) 1018 { 1019 struct eap_sim_data *data = priv; 1020 if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { 1021 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " 1022 "for NONCE_MT"); 1023 os_free(data); 1024 return NULL; 1025 } 1026 data->num_id_req = 0; 1027 data->num_notification = 0; 1028 eap_sim_state(data, CONTINUE); 1029 return priv; 1030 } 1031 1032 1033 static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv, 1034 size_t *len) 1035 { 1036 struct eap_sim_data *data = priv; 1037 1038 if (data->reauth_id) { 1039 *len = data->reauth_id_len; 1040 return data->reauth_id; 1041 } 1042 1043 if (data->pseudonym) { 1044 *len = data->pseudonym_len; 1045 return data->pseudonym; 1046 } 1047 1048 return NULL; 1049 } 1050 1051 1052 static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv) 1053 { 1054 struct eap_sim_data *data = priv; 1055 return data->state == SUCCESS; 1056 } 1057 1058 1059 static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) 1060 { 1061 struct eap_sim_data *data = priv; 1062 u8 *key; 1063 1064 if (data->state != SUCCESS) 1065 return NULL; 1066 1067 key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 1068 if (key == NULL) 1069 return NULL; 1070 1071 *len = EAP_SIM_KEYING_DATA_LEN; 1072 os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 1073 1074 return key; 1075 } 1076 1077 1078 static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 1079 { 1080 struct eap_sim_data *data = priv; 1081 u8 *key; 1082 1083 if (data->state != SUCCESS) 1084 return NULL; 1085 1086 key = os_malloc(EAP_EMSK_LEN); 1087 if (key == NULL) 1088 return NULL; 1089 1090 *len = EAP_EMSK_LEN; 1091 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 1092 1093 return key; 1094 } 1095 1096 1097 int eap_peer_sim_register(void) 1098 { 1099 struct eap_method *eap; 1100 int ret; 1101 1102 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 1103 EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); 1104 if (eap == NULL) 1105 return -1; 1106 1107 eap->init = eap_sim_init; 1108 eap->deinit = eap_sim_deinit; 1109 eap->process = eap_sim_process; 1110 eap->isKeyAvailable = eap_sim_isKeyAvailable; 1111 eap->getKey = eap_sim_getKey; 1112 eap->has_reauth_data = eap_sim_has_reauth_data; 1113 eap->deinit_for_reauth = eap_sim_deinit_for_reauth; 1114 eap->init_for_reauth = eap_sim_init_for_reauth; 1115 eap->get_identity = eap_sim_get_identity; 1116 eap->get_emsk = eap_sim_get_emsk; 1117 1118 ret = eap_peer_method_register(eap); 1119 if (ret) 1120 eap_peer_method_free(eap); 1121 return ret; 1122 } 1123