1 /* 2 * hostapd / EAP-SIM (RFC 4186) 3 * Copyright (c) 2005-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 "utils/base64.h" 13 #include "crypto/crypto.h" 14 #include "crypto/random.h" 15 #include "eap_server/eap_i.h" 16 #include "eap_common/eap_sim_common.h" 17 #include "eap_server/eap_sim_db.h" 18 19 20 struct eap_sim_data { 21 u8 mk[EAP_SIM_MK_LEN]; 22 u8 nonce_mt[EAP_SIM_NONCE_MT_LEN]; 23 u8 nonce_s[EAP_SIM_NONCE_S_LEN]; 24 u8 k_aut[EAP_SIM_K_AUT_LEN]; 25 u8 k_encr[EAP_SIM_K_ENCR_LEN]; 26 u8 msk[EAP_SIM_KEYING_DATA_LEN]; 27 u8 emsk[EAP_EMSK_LEN]; 28 u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN]; 29 u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN]; 30 u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN]; 31 u8 reauth_mac[EAP_SIM_MAC_LEN]; 32 int num_chal; 33 enum { 34 START, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE 35 } state; 36 char *next_pseudonym; 37 char *next_reauth_id; 38 u16 counter; 39 struct eap_sim_reauth *reauth; 40 u16 notification; 41 int use_result_ind; 42 int start_round; 43 char permanent[20]; /* Permanent username */ 44 }; 45 46 47 static const char * eap_sim_state_txt(int state) 48 { 49 switch (state) { 50 case START: 51 return "START"; 52 case CHALLENGE: 53 return "CHALLENGE"; 54 case REAUTH: 55 return "REAUTH"; 56 case SUCCESS: 57 return "SUCCESS"; 58 case FAILURE: 59 return "FAILURE"; 60 case NOTIFICATION: 61 return "NOTIFICATION"; 62 default: 63 return "Unknown?!"; 64 } 65 } 66 67 68 static void eap_sim_state(struct eap_sim_data *data, int state) 69 { 70 wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s", 71 eap_sim_state_txt(data->state), 72 eap_sim_state_txt(state)); 73 data->state = state; 74 } 75 76 77 static void * eap_sim_init(struct eap_sm *sm) 78 { 79 struct eap_sim_data *data; 80 81 if (!sm->cfg->eap_sim_db_priv) { 82 wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured"); 83 return NULL; 84 } 85 86 data = os_zalloc(sizeof(*data)); 87 if (data == NULL) 88 return NULL; 89 data->state = START; 90 91 return data; 92 } 93 94 95 static void eap_sim_reset(struct eap_sm *sm, void *priv) 96 { 97 struct eap_sim_data *data = priv; 98 os_free(data->next_pseudonym); 99 os_free(data->next_reauth_id); 100 bin_clear_free(data, sizeof(*data)); 101 } 102 103 104 static struct wpabuf * eap_sim_build_start(struct eap_sm *sm, 105 struct eap_sim_data *data, u8 id) 106 { 107 struct eap_sim_msg *msg; 108 u8 ver[2]; 109 bool id_req = true; 110 111 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start"); 112 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 113 EAP_SIM_SUBTYPE_START); 114 data->start_round++; 115 116 if (data->start_round == 1 && (sm->cfg->eap_sim_id & 0x04)) { 117 char *username; 118 119 username = sim_get_username(sm->identity, sm->identity_len); 120 if (username && username[0] == EAP_SIM_REAUTH_ID_PREFIX && 121 eap_sim_db_get_reauth_entry(sm->cfg->eap_sim_db_priv, 122 username)) 123 id_req = false; 124 125 os_free(username); 126 } 127 128 if (!id_req) { 129 wpa_printf(MSG_DEBUG, " No identity request"); 130 } else if (data->start_round == 1) { 131 /* 132 * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is 133 * ignored and the SIM/Start is used to request the identity. 134 */ 135 wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); 136 eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); 137 } else if (data->start_round > 3) { 138 /* Cannot use more than three rounds of Start messages */ 139 eap_sim_msg_free(msg); 140 return NULL; 141 } else if (data->start_round == 0) { 142 /* 143 * This is a special case that is used to recover from 144 * AT_COUNTER_TOO_SMALL during re-authentication. Since we 145 * already know the identity of the peer, there is no need to 146 * request any identity in this case. 147 */ 148 } else if (sm->identity && sm->identity_len > 0 && 149 sm->identity[0] == EAP_SIM_REAUTH_ID_PREFIX) { 150 /* Reauth id may have expired - try fullauth */ 151 wpa_printf(MSG_DEBUG, " AT_FULLAUTH_ID_REQ"); 152 eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0); 153 } else { 154 wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); 155 eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); 156 } 157 wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); 158 ver[0] = 0; 159 ver[1] = EAP_SIM_VERSION; 160 eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), 161 ver, sizeof(ver)); 162 return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0); 163 } 164 165 166 static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data, 167 struct eap_sim_msg *msg, u16 counter, 168 const u8 *nonce_s) 169 { 170 os_free(data->next_pseudonym); 171 if (!(sm->cfg->eap_sim_id & 0x01)) { 172 /* Use of pseudonyms disabled in configuration */ 173 data->next_pseudonym = NULL; 174 } else if (!nonce_s) { 175 data->next_pseudonym = 176 eap_sim_db_get_next_pseudonym(sm->cfg->eap_sim_db_priv, 177 EAP_SIM_DB_SIM); 178 } else { 179 /* Do not update pseudonym during re-authentication */ 180 data->next_pseudonym = NULL; 181 } 182 os_free(data->next_reauth_id); 183 if (!(sm->cfg->eap_sim_id & 0x02)) { 184 /* Use of fast reauth disabled in configuration */ 185 data->next_reauth_id = NULL; 186 } else if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) { 187 data->next_reauth_id = 188 eap_sim_db_get_next_reauth_id(sm->cfg->eap_sim_db_priv, 189 EAP_SIM_DB_SIM); 190 } else { 191 wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication " 192 "count exceeded - force full authentication"); 193 data->next_reauth_id = NULL; 194 } 195 196 if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && 197 counter == 0 && nonce_s == NULL) 198 return 0; 199 200 wpa_printf(MSG_DEBUG, " AT_IV"); 201 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 202 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 203 204 if (counter > 0) { 205 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); 206 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 207 } 208 209 if (nonce_s) { 210 wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); 211 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, 212 EAP_SIM_NONCE_S_LEN); 213 } 214 215 if (data->next_pseudonym) { 216 wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", 217 data->next_pseudonym); 218 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, 219 os_strlen(data->next_pseudonym), 220 (u8 *) data->next_pseudonym, 221 os_strlen(data->next_pseudonym)); 222 } 223 224 if (data->next_reauth_id) { 225 wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", 226 data->next_reauth_id); 227 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, 228 os_strlen(data->next_reauth_id), 229 (u8 *) data->next_reauth_id, 230 os_strlen(data->next_reauth_id)); 231 } 232 233 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 234 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " 235 "AT_ENCR_DATA"); 236 return -1; 237 } 238 239 return 0; 240 } 241 242 243 static struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm, 244 struct eap_sim_data *data, 245 u8 id) 246 { 247 struct eap_sim_msg *msg; 248 249 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge"); 250 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 251 EAP_SIM_SUBTYPE_CHALLENGE); 252 wpa_printf(MSG_DEBUG, " AT_RAND"); 253 eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, 254 data->num_chal * GSM_RAND_LEN); 255 256 if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { 257 eap_sim_msg_free(msg); 258 return NULL; 259 } 260 261 if (sm->cfg->eap_sim_aka_result_ind) { 262 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 263 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 264 } 265 266 wpa_printf(MSG_DEBUG, " AT_MAC"); 267 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 268 return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, 269 data->nonce_mt, EAP_SIM_NONCE_MT_LEN); 270 } 271 272 273 static struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm, 274 struct eap_sim_data *data, u8 id) 275 { 276 struct eap_sim_msg *msg; 277 struct wpabuf *buf; 278 279 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); 280 281 if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) 282 return NULL; 283 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", 284 data->nonce_s, EAP_SIM_NONCE_S_LEN); 285 286 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 287 data->emsk); 288 eap_sim_derive_keys_reauth(data->counter, sm->identity, 289 sm->identity_len, data->nonce_s, data->mk, 290 data->msk, data->emsk); 291 292 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 293 EAP_SIM_SUBTYPE_REAUTHENTICATION); 294 295 if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { 296 eap_sim_msg_free(msg); 297 return NULL; 298 } 299 300 if (sm->cfg->eap_sim_aka_result_ind) { 301 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 302 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 303 } 304 305 wpa_printf(MSG_DEBUG, " AT_MAC"); 306 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 307 buf = eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, NULL, 0); 308 309 /* Remember this MAC before sending it to the peer. This MAC is used for 310 * Session-Id calculation after receiving response from the peer and 311 * after all other checks pass. */ 312 os_memcpy(data->reauth_mac, 313 wpabuf_head_u8(buf) + wpabuf_len(buf) - EAP_SIM_MAC_LEN, 314 EAP_SIM_MAC_LEN); 315 316 return buf; 317 } 318 319 320 static struct wpabuf * eap_sim_build_notification(struct eap_sm *sm, 321 struct eap_sim_data *data, 322 u8 id) 323 { 324 struct eap_sim_msg *msg; 325 326 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification"); 327 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 328 EAP_SIM_SUBTYPE_NOTIFICATION); 329 wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); 330 eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, 331 NULL, 0); 332 if (data->use_result_ind) { 333 if (data->reauth) { 334 wpa_printf(MSG_DEBUG, " AT_IV"); 335 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 336 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 337 EAP_SIM_AT_ENCR_DATA); 338 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", 339 data->counter); 340 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 341 NULL, 0); 342 343 if (eap_sim_msg_add_encr_end(msg, data->k_encr, 344 EAP_SIM_AT_PADDING)) { 345 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to " 346 "encrypt AT_ENCR_DATA"); 347 eap_sim_msg_free(msg); 348 return NULL; 349 } 350 } 351 352 wpa_printf(MSG_DEBUG, " AT_MAC"); 353 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 354 } 355 return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, NULL, 0); 356 } 357 358 359 static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id) 360 { 361 struct eap_sim_data *data = priv; 362 363 switch (data->state) { 364 case START: 365 return eap_sim_build_start(sm, data, id); 366 case CHALLENGE: 367 return eap_sim_build_challenge(sm, data, id); 368 case REAUTH: 369 return eap_sim_build_reauth(sm, data, id); 370 case NOTIFICATION: 371 return eap_sim_build_notification(sm, data, id); 372 default: 373 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 374 "buildReq", data->state); 375 break; 376 } 377 return NULL; 378 } 379 380 381 static bool eap_sim_check(struct eap_sm *sm, void *priv, 382 struct wpabuf *respData) 383 { 384 const u8 *pos; 385 size_t len; 386 387 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 388 if (pos == NULL || len < 3) { 389 wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); 390 return true; 391 } 392 393 return false; 394 } 395 396 397 static bool eap_sim_unexpected_subtype(struct eap_sim_data *data, 398 u8 subtype) 399 { 400 if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) 401 return false; 402 403 switch (data->state) { 404 case START: 405 if (subtype != EAP_SIM_SUBTYPE_START) { 406 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 407 "subtype %d", subtype); 408 return true; 409 } 410 break; 411 case CHALLENGE: 412 if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { 413 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 414 "subtype %d", subtype); 415 return true; 416 } 417 break; 418 case REAUTH: 419 if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { 420 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 421 "subtype %d", subtype); 422 return true; 423 } 424 break; 425 case NOTIFICATION: 426 if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { 427 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 428 "subtype %d", subtype); 429 return true; 430 } 431 break; 432 default: 433 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " 434 "processing a response", data->state); 435 return true; 436 } 437 438 return false; 439 } 440 441 442 static int eap_sim_supported_ver(struct eap_sim_data *data, int version) 443 { 444 return version == EAP_SIM_VERSION; 445 } 446 447 448 static void eap_sim_process_start(struct eap_sm *sm, 449 struct eap_sim_data *data, 450 struct wpabuf *respData, 451 struct eap_sim_attrs *attr) 452 { 453 const u8 *identity; 454 size_t identity_len; 455 u8 ver_list[2]; 456 u8 *new_identity; 457 char *username; 458 459 wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response"); 460 461 if (data->start_round == 0) { 462 /* 463 * Special case for AT_COUNTER_TOO_SMALL recovery - no identity 464 * was requested since we already know it. 465 */ 466 goto skip_id_update; 467 } 468 469 if ((sm->cfg->eap_sim_id & 0x04) && 470 (!attr->identity || attr->identity_len == 0)) 471 goto skip_id_attr; 472 473 /* 474 * Unless explicitly configured otherwise, we always request identity 475 * in SIM/Start, so the peer is required to have replied with one. 476 */ 477 if (!attr->identity || attr->identity_len == 0) { 478 wpa_printf(MSG_DEBUG, "EAP-SIM: Peer did not provide any " 479 "identity"); 480 goto failed; 481 } 482 483 new_identity = os_malloc(attr->identity_len); 484 if (new_identity == NULL) 485 goto failed; 486 os_free(sm->identity); 487 sm->identity = new_identity; 488 os_memcpy(sm->identity, attr->identity, attr->identity_len); 489 sm->identity_len = attr->identity_len; 490 491 skip_id_attr: 492 if (sm->sim_aka_permanent[0]) { 493 identity = (const u8 *) sm->sim_aka_permanent; 494 identity_len = os_strlen(sm->sim_aka_permanent); 495 } else { 496 identity = sm->identity; 497 identity_len = sm->identity_len; 498 } 499 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", 500 identity, identity_len); 501 username = sim_get_username(identity, identity_len); 502 if (username == NULL) 503 goto failed; 504 505 if (username[0] == EAP_SIM_REAUTH_ID_PREFIX) { 506 wpa_printf(MSG_DEBUG, "EAP-SIM: Reauth username '%s'", 507 username); 508 data->reauth = eap_sim_db_get_reauth_entry( 509 sm->cfg->eap_sim_db_priv, username); 510 os_free(username); 511 if (data->reauth == NULL) { 512 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown reauth " 513 "identity - request full auth identity"); 514 /* Remain in START state for another round */ 515 return; 516 } 517 518 if (data->reauth->counter > 519 sm->cfg->eap_sim_aka_fast_reauth_limit && 520 (sm->cfg->eap_sim_id & 0x04)) { 521 wpa_printf(MSG_DEBUG, 522 "EAP-SIM: Too many fast re-authentication attemps - fall back to full authentication"); 523 wpa_printf(MSG_DEBUG, 524 "EAP-SIM: Permanent identity recognized - skip new Identity query"); 525 os_strlcpy(data->permanent, 526 data->reauth->permanent, 527 sizeof(data->permanent)); 528 os_strlcpy(sm->sim_aka_permanent, 529 data->reauth->permanent, 530 sizeof(sm->sim_aka_permanent)); 531 eap_sim_db_remove_reauth( 532 sm->cfg->eap_sim_db_priv, 533 data->reauth); 534 data->reauth = NULL; 535 goto skip_id_update; 536 } 537 538 wpa_printf(MSG_DEBUG, 539 "EAP-SIM: Using fast re-authentication (counter=%d)", 540 data->reauth->counter); 541 os_strlcpy(data->permanent, data->reauth->permanent, 542 sizeof(data->permanent)); 543 data->counter = data->reauth->counter; 544 os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN); 545 eap_sim_state(data, REAUTH); 546 return; 547 } 548 549 if (username[0] == EAP_SIM_PSEUDONYM_PREFIX) { 550 const char *permanent; 551 wpa_printf(MSG_DEBUG, "EAP-SIM: Pseudonym username '%s'", 552 username); 553 permanent = eap_sim_db_get_permanent( 554 sm->cfg->eap_sim_db_priv, username); 555 os_free(username); 556 if (permanent == NULL) { 557 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown pseudonym " 558 "identity - request permanent identity"); 559 /* Remain in START state for another round */ 560 return; 561 } 562 os_strlcpy(data->permanent, permanent, 563 sizeof(data->permanent)); 564 } else if (username[0] == EAP_SIM_PERMANENT_PREFIX) { 565 wpa_printf(MSG_DEBUG, "EAP-SIM: Permanent username '%s'", 566 username); 567 os_strlcpy(data->permanent, username, sizeof(data->permanent)); 568 os_free(username); 569 #ifdef CRYPTO_RSA_OAEP_SHA256 570 } else if (sm->identity_len > 1 && sm->identity[0] == '\0') { 571 char *enc_id, *pos, *end; 572 size_t enc_id_len; 573 u8 *decoded_id; 574 size_t decoded_id_len; 575 struct wpabuf *enc, *dec; 576 u8 *new_id; 577 578 os_free(username); 579 if (!sm->cfg->imsi_privacy_key) { 580 wpa_printf(MSG_DEBUG, 581 "EAP-SIM: Received encrypted identity, but no IMSI privacy key configured to decrypt it"); 582 goto failed; 583 } 584 585 enc_id = (char *) &sm->identity[1]; 586 end = (char *) &sm->identity[sm->identity_len]; 587 for (pos = enc_id; pos < end; pos++) { 588 if (*pos == ',') 589 break; 590 } 591 enc_id_len = pos - enc_id; 592 593 wpa_hexdump_ascii(MSG_DEBUG, 594 "EAP-SIM: Encrypted permanent identity", 595 enc_id, enc_id_len); 596 decoded_id = base64_decode(enc_id, enc_id_len, &decoded_id_len); 597 if (!decoded_id) { 598 wpa_printf(MSG_DEBUG, 599 "EAP-SIM: Could not base64 decode encrypted identity"); 600 goto failed; 601 } 602 wpa_hexdump(MSG_DEBUG, 603 "EAP-SIM: Decoded encrypted permanent identity", 604 decoded_id, decoded_id_len); 605 enc = wpabuf_alloc_copy(decoded_id, decoded_id_len); 606 os_free(decoded_id); 607 if (!enc) 608 goto failed; 609 dec = crypto_rsa_oaep_sha256_decrypt(sm->cfg->imsi_privacy_key, 610 enc); 611 wpabuf_free(enc); 612 if (!dec) { 613 wpa_printf(MSG_DEBUG, 614 "EAP-SIM: Failed to decrypt encrypted identity"); 615 goto failed; 616 } 617 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Decrypted permanent identity", 618 wpabuf_head(dec), wpabuf_len(dec)); 619 username = sim_get_username(wpabuf_head(dec), wpabuf_len(dec)); 620 if (!username) { 621 wpabuf_free(dec); 622 goto failed; 623 } 624 new_id = os_memdup(wpabuf_head(dec), wpabuf_len(dec)); 625 if (!new_id) { 626 wpabuf_free(dec); 627 goto failed; 628 } 629 os_free(sm->identity); 630 sm->identity = new_id; 631 sm->identity_len = wpabuf_len(dec); 632 wpabuf_free(dec); 633 os_strlcpy(data->permanent, username, sizeof(data->permanent)); 634 os_free(username); 635 #endif /* CRYPTO_RSA_OAEP_SHA256 */ 636 } else { 637 wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized username '%s'", 638 username); 639 os_free(username); 640 goto failed; 641 } 642 643 skip_id_update: 644 /* Full authentication */ 645 646 if (attr->nonce_mt == NULL || attr->selected_version < 0) { 647 wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing " 648 "required attributes"); 649 goto failed; 650 } 651 652 if (!eap_sim_supported_ver(data, attr->selected_version)) { 653 wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported " 654 "version %d", attr->selected_version); 655 goto failed; 656 } 657 658 data->counter = 0; /* reset re-auth counter since this is full auth */ 659 data->reauth = NULL; 660 661 data->num_chal = eap_sim_db_get_gsm_triplets( 662 sm->cfg->eap_sim_db_priv, data->permanent, EAP_SIM_MAX_CHAL, 663 (u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm); 664 if (data->num_chal == EAP_SIM_DB_PENDING) { 665 wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets " 666 "not yet available - pending request"); 667 sm->method_pending = METHOD_PENDING_WAIT; 668 return; 669 } 670 if (data->num_chal < 2) { 671 wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM " 672 "authentication triplets for the peer"); 673 goto failed; 674 } 675 676 if (data->permanent[0] == EAP_SIM_PERMANENT_PREFIX) 677 os_strlcpy(sm->imsi, &data->permanent[1], sizeof(sm->imsi)); 678 679 identity_len = sm->identity_len; 680 while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { 681 wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null " 682 "character from identity"); 683 identity_len--; 684 } 685 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation", 686 sm->identity, identity_len); 687 688 os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN); 689 WPA_PUT_BE16(ver_list, EAP_SIM_VERSION); 690 eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt, 691 attr->selected_version, ver_list, sizeof(ver_list), 692 data->num_chal, (const u8 *) data->kc, data->mk); 693 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 694 data->emsk); 695 696 eap_sim_state(data, CHALLENGE); 697 return; 698 699 failed: 700 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 701 eap_sim_state(data, NOTIFICATION); 702 } 703 704 705 static void eap_sim_process_challenge(struct eap_sm *sm, 706 struct eap_sim_data *data, 707 struct wpabuf *respData, 708 struct eap_sim_attrs *attr) 709 { 710 if (attr->mac == NULL || 711 eap_sim_verify_mac(data->k_aut, respData, attr->mac, 712 (u8 *) data->sres, 713 data->num_chal * EAP_SIM_SRES_LEN)) { 714 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " 715 "did not include valid AT_MAC"); 716 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 717 eap_sim_state(data, NOTIFICATION); 718 return; 719 } 720 721 wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the " 722 "correct AT_MAC"); 723 if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) { 724 data->use_result_ind = 1; 725 data->notification = EAP_SIM_SUCCESS; 726 eap_sim_state(data, NOTIFICATION); 727 } else 728 eap_sim_state(data, SUCCESS); 729 730 if (data->next_pseudonym) { 731 eap_sim_db_add_pseudonym(sm->cfg->eap_sim_db_priv, 732 data->permanent, 733 data->next_pseudonym); 734 data->next_pseudonym = NULL; 735 } 736 if (data->next_reauth_id) { 737 eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv, data->permanent, 738 data->next_reauth_id, data->counter + 1, 739 data->mk); 740 data->next_reauth_id = NULL; 741 } 742 } 743 744 745 static void eap_sim_process_reauth(struct eap_sm *sm, 746 struct eap_sim_data *data, 747 struct wpabuf *respData, 748 struct eap_sim_attrs *attr) 749 { 750 struct eap_sim_attrs eattr; 751 u8 *decrypted = NULL; 752 753 if (attr->mac == NULL || 754 eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s, 755 EAP_SIM_NONCE_S_LEN)) { 756 wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 757 "did not include valid AT_MAC"); 758 goto fail; 759 } 760 761 if (attr->encr_data == NULL || attr->iv == NULL) { 762 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " 763 "message did not include encrypted data"); 764 goto fail; 765 } 766 767 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 768 attr->encr_data_len, attr->iv, &eattr, 769 0); 770 if (decrypted == NULL) { 771 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " 772 "data from reauthentication message"); 773 goto fail; 774 } 775 776 if (eattr.counter != data->counter) { 777 wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 778 "used incorrect counter %u, expected %u", 779 eattr.counter, data->counter); 780 goto fail; 781 } 782 os_free(decrypted); 783 decrypted = NULL; 784 785 wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes " 786 "the correct AT_MAC"); 787 788 if (eattr.counter_too_small) { 789 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response " 790 "included AT_COUNTER_TOO_SMALL - starting full " 791 "authentication"); 792 data->start_round = -1; 793 eap_sim_state(data, START); 794 return; 795 } 796 797 if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) { 798 data->use_result_ind = 1; 799 data->notification = EAP_SIM_SUCCESS; 800 eap_sim_state(data, NOTIFICATION); 801 } else 802 eap_sim_state(data, SUCCESS); 803 804 if (data->next_reauth_id) { 805 eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv, data->permanent, 806 data->next_reauth_id, 807 data->counter + 1, data->mk); 808 data->next_reauth_id = NULL; 809 } else { 810 eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv, 811 data->reauth); 812 data->reauth = NULL; 813 } 814 815 return; 816 817 fail: 818 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 819 eap_sim_state(data, NOTIFICATION); 820 eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv, data->reauth); 821 data->reauth = NULL; 822 os_free(decrypted); 823 } 824 825 826 static void eap_sim_process_client_error(struct eap_sm *sm, 827 struct eap_sim_data *data, 828 struct wpabuf *respData, 829 struct eap_sim_attrs *attr) 830 { 831 wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d", 832 attr->client_error_code); 833 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 834 eap_sim_state(data, SUCCESS); 835 else 836 eap_sim_state(data, FAILURE); 837 } 838 839 840 static void eap_sim_process_notification(struct eap_sm *sm, 841 struct eap_sim_data *data, 842 struct wpabuf *respData, 843 struct eap_sim_attrs *attr) 844 { 845 wpa_printf(MSG_DEBUG, "EAP-SIM: Client replied to notification"); 846 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 847 eap_sim_state(data, SUCCESS); 848 else 849 eap_sim_state(data, FAILURE); 850 } 851 852 853 static void eap_sim_process(struct eap_sm *sm, void *priv, 854 struct wpabuf *respData) 855 { 856 struct eap_sim_data *data = priv; 857 const u8 *pos, *end; 858 u8 subtype; 859 size_t len; 860 struct eap_sim_attrs attr; 861 862 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 863 if (pos == NULL || len < 3) 864 return; 865 866 end = pos + len; 867 subtype = *pos; 868 pos += 3; 869 870 if (eap_sim_unexpected_subtype(data, subtype)) { 871 wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized or unexpected " 872 "EAP-SIM Subtype in EAP Response"); 873 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 874 eap_sim_state(data, NOTIFICATION); 875 return; 876 } 877 878 if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) { 879 wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes"); 880 if (subtype != EAP_SIM_SUBTYPE_CLIENT_ERROR && 881 (data->state == START || data->state == CHALLENGE || 882 data->state == REAUTH)) { 883 data->notification = 884 EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 885 eap_sim_state(data, NOTIFICATION); 886 return; 887 } 888 eap_sim_state(data, FAILURE); 889 return; 890 } 891 892 if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) { 893 eap_sim_process_client_error(sm, data, respData, &attr); 894 return; 895 } 896 897 switch (data->state) { 898 case START: 899 eap_sim_process_start(sm, data, respData, &attr); 900 break; 901 case CHALLENGE: 902 eap_sim_process_challenge(sm, data, respData, &attr); 903 break; 904 case REAUTH: 905 eap_sim_process_reauth(sm, data, respData, &attr); 906 break; 907 case NOTIFICATION: 908 eap_sim_process_notification(sm, data, respData, &attr); 909 break; 910 default: 911 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 912 "process", data->state); 913 break; 914 } 915 } 916 917 918 static bool eap_sim_isDone(struct eap_sm *sm, void *priv) 919 { 920 struct eap_sim_data *data = priv; 921 return data->state == SUCCESS || data->state == FAILURE; 922 } 923 924 925 static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) 926 { 927 struct eap_sim_data *data = priv; 928 u8 *key; 929 930 if (data->state != SUCCESS) 931 return NULL; 932 933 key = os_memdup(data->msk, EAP_SIM_KEYING_DATA_LEN); 934 if (key == NULL) 935 return NULL; 936 *len = EAP_SIM_KEYING_DATA_LEN; 937 return key; 938 } 939 940 941 static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 942 { 943 struct eap_sim_data *data = priv; 944 u8 *key; 945 946 if (data->state != SUCCESS) 947 return NULL; 948 949 key = os_memdup(data->emsk, EAP_EMSK_LEN); 950 if (key == NULL) 951 return NULL; 952 *len = EAP_EMSK_LEN; 953 return key; 954 } 955 956 957 static bool eap_sim_isSuccess(struct eap_sm *sm, void *priv) 958 { 959 struct eap_sim_data *data = priv; 960 return data->state == SUCCESS; 961 } 962 963 964 static u8 * eap_sim_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 965 { 966 struct eap_sim_data *data = priv; 967 u8 *id; 968 969 if (data->state != SUCCESS) 970 return NULL; 971 972 if (!data->reauth) 973 *len = 1 + data->num_chal * GSM_RAND_LEN + EAP_SIM_NONCE_MT_LEN; 974 else 975 *len = 1 + EAP_SIM_NONCE_S_LEN + EAP_SIM_MAC_LEN; 976 id = os_malloc(*len); 977 if (id == NULL) 978 return NULL; 979 980 id[0] = EAP_TYPE_SIM; 981 if (!data->reauth) { 982 os_memcpy(id + 1, data->rand, data->num_chal * GSM_RAND_LEN); 983 os_memcpy(id + 1 + data->num_chal * GSM_RAND_LEN, 984 data->nonce_mt, EAP_SIM_NONCE_MT_LEN); 985 } else { 986 os_memcpy(id + 1, data->nonce_s, EAP_SIM_NONCE_S_LEN); 987 os_memcpy(id + 1 + EAP_SIM_NONCE_S_LEN, data->reauth_mac, 988 EAP_SIM_MAC_LEN); 989 990 } 991 wpa_hexdump(MSG_DEBUG, "EAP-SIM: Derived Session-Id", id, *len); 992 993 return id; 994 } 995 996 997 int eap_server_sim_register(void) 998 { 999 struct eap_method *eap; 1000 1001 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 1002 EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); 1003 if (eap == NULL) 1004 return -1; 1005 1006 eap->init = eap_sim_init; 1007 eap->reset = eap_sim_reset; 1008 eap->buildReq = eap_sim_buildReq; 1009 eap->check = eap_sim_check; 1010 eap->process = eap_sim_process; 1011 eap->isDone = eap_sim_isDone; 1012 eap->getKey = eap_sim_getKey; 1013 eap->isSuccess = eap_sim_isSuccess; 1014 eap->get_emsk = eap_sim_get_emsk; 1015 eap->getSessionId = eap_sim_get_session_id; 1016 1017 return eap_server_method_register(eap); 1018 } 1019