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