$search
00001 /* 00002 * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf) 00003 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "pcsc_funcs.h" 00019 #include "crypto/crypto.h" 00020 #include "crypto/sha1.h" 00021 #include "crypto/sha256.h" 00022 #include "crypto/milenage.h" 00023 #include "eap_common/eap_sim_common.h" 00024 #include "eap_config.h" 00025 #include "eap_i.h" 00026 00027 00028 struct eap_aka_data { 00029 u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN]; 00030 size_t res_len; 00031 u8 nonce_s[EAP_SIM_NONCE_S_LEN]; 00032 u8 mk[EAP_SIM_MK_LEN]; 00033 u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; 00034 u8 k_encr[EAP_SIM_K_ENCR_LEN]; 00035 u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */ 00036 u8 msk[EAP_SIM_KEYING_DATA_LEN]; 00037 u8 emsk[EAP_EMSK_LEN]; 00038 u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN]; 00039 u8 auts[EAP_AKA_AUTS_LEN]; 00040 00041 int num_id_req, num_notification; 00042 u8 *pseudonym; 00043 size_t pseudonym_len; 00044 u8 *reauth_id; 00045 size_t reauth_id_len; 00046 int reauth; 00047 unsigned int counter, counter_too_small; 00048 u8 *last_eap_identity; 00049 size_t last_eap_identity_len; 00050 enum { 00051 CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE 00052 } state; 00053 00054 struct wpabuf *id_msgs; 00055 int prev_id; 00056 int result_ind, use_result_ind; 00057 u8 eap_method; 00058 u8 *network_name; 00059 size_t network_name_len; 00060 u16 kdf; 00061 int kdf_negotiation; 00062 }; 00063 00064 00065 #ifndef CONFIG_NO_STDOUT_DEBUG 00066 static const char * eap_aka_state_txt(int state) 00067 { 00068 switch (state) { 00069 case CONTINUE: 00070 return "CONTINUE"; 00071 case RESULT_SUCCESS: 00072 return "RESULT_SUCCESS"; 00073 case RESULT_FAILURE: 00074 return "RESULT_FAILURE"; 00075 case SUCCESS: 00076 return "SUCCESS"; 00077 case FAILURE: 00078 return "FAILURE"; 00079 default: 00080 return "?"; 00081 } 00082 } 00083 #endif /* CONFIG_NO_STDOUT_DEBUG */ 00084 00085 00086 static void eap_aka_state(struct eap_aka_data *data, int state) 00087 { 00088 wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s", 00089 eap_aka_state_txt(data->state), 00090 eap_aka_state_txt(state)); 00091 data->state = state; 00092 } 00093 00094 00095 static void * eap_aka_init(struct eap_sm *sm) 00096 { 00097 struct eap_aka_data *data; 00098 const char *phase1 = eap_get_config_phase1(sm); 00099 00100 data = os_zalloc(sizeof(*data)); 00101 if (data == NULL) 00102 return NULL; 00103 00104 data->eap_method = EAP_TYPE_AKA; 00105 00106 eap_aka_state(data, CONTINUE); 00107 data->prev_id = -1; 00108 00109 data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL; 00110 00111 return data; 00112 } 00113 00114 00115 #ifdef EAP_AKA_PRIME 00116 static void * eap_aka_prime_init(struct eap_sm *sm) 00117 { 00118 struct eap_aka_data *data = eap_aka_init(sm); 00119 if (data == NULL) 00120 return NULL; 00121 data->eap_method = EAP_TYPE_AKA_PRIME; 00122 return data; 00123 } 00124 #endif /* EAP_AKA_PRIME */ 00125 00126 00127 static void eap_aka_deinit(struct eap_sm *sm, void *priv) 00128 { 00129 struct eap_aka_data *data = priv; 00130 if (data) { 00131 os_free(data->pseudonym); 00132 os_free(data->reauth_id); 00133 os_free(data->last_eap_identity); 00134 wpabuf_free(data->id_msgs); 00135 os_free(data->network_name); 00136 os_free(data); 00137 } 00138 } 00139 00140 00141 static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data) 00142 { 00143 struct eap_peer_config *conf; 00144 00145 wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm"); 00146 00147 conf = eap_get_config(sm); 00148 if (conf == NULL) 00149 return -1; 00150 if (conf->pcsc) { 00151 return scard_umts_auth(sm->scard_ctx, data->rand, 00152 data->autn, data->res, &data->res_len, 00153 data->ik, data->ck, data->auts); 00154 } 00155 00156 #ifdef CONFIG_USIM_SIMULATOR 00157 if (conf->password) { 00158 u8 opc[16], k[16], sqn[6]; 00159 const char *pos; 00160 wpa_printf(MSG_DEBUG, "EAP-AKA: Use internal Milenage " 00161 "implementation for UMTS authentication"); 00162 if (conf->password_len < 78) { 00163 wpa_printf(MSG_DEBUG, "EAP-AKA: invalid Milenage " 00164 "password"); 00165 return -1; 00166 } 00167 pos = (const char *) conf->password; 00168 if (hexstr2bin(pos, k, 16)) 00169 return -1; 00170 pos += 32; 00171 if (*pos != ':') 00172 return -1; 00173 pos++; 00174 00175 if (hexstr2bin(pos, opc, 16)) 00176 return -1; 00177 pos += 32; 00178 if (*pos != ':') 00179 return -1; 00180 pos++; 00181 00182 if (hexstr2bin(pos, sqn, 6)) 00183 return -1; 00184 00185 return milenage_check(opc, k, sqn, data->rand, data->autn, 00186 data->ik, data->ck, 00187 data->res, &data->res_len, data->auts); 00188 } 00189 #endif /* CONFIG_USIM_SIMULATOR */ 00190 00191 #ifdef CONFIG_USIM_HARDCODED 00192 wpa_printf(MSG_DEBUG, "EAP-AKA: Use hardcoded Kc and SRES values for " 00193 "testing"); 00194 00195 /* These hardcoded Kc and SRES values are used for testing. 00196 * Could consider making them configurable. */ 00197 os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN); 00198 data->res_len = EAP_AKA_RES_MAX_LEN; 00199 os_memset(data->ik, '3', EAP_AKA_IK_LEN); 00200 os_memset(data->ck, '4', EAP_AKA_CK_LEN); 00201 { 00202 u8 autn[EAP_AKA_AUTN_LEN]; 00203 os_memset(autn, '1', EAP_AKA_AUTN_LEN); 00204 if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) { 00205 wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match " 00206 "with expected value"); 00207 return -1; 00208 } 00209 } 00210 #if 0 00211 { 00212 static int test_resync = 1; 00213 if (test_resync) { 00214 /* Test Resynchronization */ 00215 test_resync = 0; 00216 return -2; 00217 } 00218 } 00219 #endif 00220 return 0; 00221 00222 #else /* CONFIG_USIM_HARDCODED */ 00223 00224 wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorith " 00225 "enabled"); 00226 return -1; 00227 00228 #endif /* CONFIG_USIM_HARDCODED */ 00229 } 00230 00231 00232 #define CLEAR_PSEUDONYM 0x01 00233 #define CLEAR_REAUTH_ID 0x02 00234 #define CLEAR_EAP_ID 0x04 00235 00236 static void eap_aka_clear_identities(struct eap_aka_data *data, int id) 00237 { 00238 wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old%s%s%s", 00239 id & CLEAR_PSEUDONYM ? " pseudonym" : "", 00240 id & CLEAR_REAUTH_ID ? " reauth_id" : "", 00241 id & CLEAR_EAP_ID ? " eap_id" : ""); 00242 if (id & CLEAR_PSEUDONYM) { 00243 os_free(data->pseudonym); 00244 data->pseudonym = NULL; 00245 data->pseudonym_len = 0; 00246 } 00247 if (id & CLEAR_REAUTH_ID) { 00248 os_free(data->reauth_id); 00249 data->reauth_id = NULL; 00250 data->reauth_id_len = 0; 00251 } 00252 if (id & CLEAR_EAP_ID) { 00253 os_free(data->last_eap_identity); 00254 data->last_eap_identity = NULL; 00255 data->last_eap_identity_len = 0; 00256 } 00257 } 00258 00259 00260 static int eap_aka_learn_ids(struct eap_aka_data *data, 00261 struct eap_sim_attrs *attr) 00262 { 00263 if (attr->next_pseudonym) { 00264 os_free(data->pseudonym); 00265 data->pseudonym = os_malloc(attr->next_pseudonym_len); 00266 if (data->pseudonym == NULL) { 00267 wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " 00268 "next pseudonym"); 00269 return -1; 00270 } 00271 os_memcpy(data->pseudonym, attr->next_pseudonym, 00272 attr->next_pseudonym_len); 00273 data->pseudonym_len = attr->next_pseudonym_len; 00274 wpa_hexdump_ascii(MSG_DEBUG, 00275 "EAP-AKA: (encr) AT_NEXT_PSEUDONYM", 00276 data->pseudonym, 00277 data->pseudonym_len); 00278 } 00279 00280 if (attr->next_reauth_id) { 00281 os_free(data->reauth_id); 00282 data->reauth_id = os_malloc(attr->next_reauth_id_len); 00283 if (data->reauth_id == NULL) { 00284 wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " 00285 "next reauth_id"); 00286 return -1; 00287 } 00288 os_memcpy(data->reauth_id, attr->next_reauth_id, 00289 attr->next_reauth_id_len); 00290 data->reauth_id_len = attr->next_reauth_id_len; 00291 wpa_hexdump_ascii(MSG_DEBUG, 00292 "EAP-AKA: (encr) AT_NEXT_REAUTH_ID", 00293 data->reauth_id, 00294 data->reauth_id_len); 00295 } 00296 00297 return 0; 00298 } 00299 00300 00301 static int eap_aka_add_id_msg(struct eap_aka_data *data, 00302 const struct wpabuf *msg) 00303 { 00304 if (msg == NULL) 00305 return -1; 00306 00307 if (data->id_msgs == NULL) { 00308 data->id_msgs = wpabuf_dup(msg); 00309 return data->id_msgs == NULL ? -1 : 0; 00310 } 00311 00312 if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) 00313 return -1; 00314 wpabuf_put_buf(data->id_msgs, msg); 00315 00316 return 0; 00317 } 00318 00319 00320 static void eap_aka_add_checkcode(struct eap_aka_data *data, 00321 struct eap_sim_msg *msg) 00322 { 00323 const u8 *addr; 00324 size_t len; 00325 u8 hash[SHA256_MAC_LEN]; 00326 00327 wpa_printf(MSG_DEBUG, " AT_CHECKCODE"); 00328 00329 if (data->id_msgs == NULL) { 00330 /* 00331 * No EAP-AKA/Identity packets were exchanged - send empty 00332 * checkcode. 00333 */ 00334 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0); 00335 return; 00336 } 00337 00338 /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */ 00339 addr = wpabuf_head(data->id_msgs); 00340 len = wpabuf_len(data->id_msgs); 00341 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len); 00342 #ifdef EAP_AKA_PRIME 00343 if (data->eap_method == EAP_TYPE_AKA_PRIME) 00344 sha256_vector(1, &addr, &len, hash); 00345 else 00346 #endif /* EAP_AKA_PRIME */ 00347 sha1_vector(1, &addr, &len, hash); 00348 00349 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash, 00350 data->eap_method == EAP_TYPE_AKA_PRIME ? 00351 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN); 00352 } 00353 00354 00355 static int eap_aka_verify_checkcode(struct eap_aka_data *data, 00356 const u8 *checkcode, size_t checkcode_len) 00357 { 00358 const u8 *addr; 00359 size_t len; 00360 u8 hash[SHA256_MAC_LEN]; 00361 size_t hash_len; 00362 00363 if (checkcode == NULL) 00364 return -1; 00365 00366 if (data->id_msgs == NULL) { 00367 if (checkcode_len != 0) { 00368 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server " 00369 "indicates that AKA/Identity messages were " 00370 "used, but they were not"); 00371 return -1; 00372 } 00373 return 0; 00374 } 00375 00376 hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ? 00377 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN; 00378 00379 if (checkcode_len != hash_len) { 00380 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server " 00381 "indicates that AKA/Identity message were not " 00382 "used, but they were"); 00383 return -1; 00384 } 00385 00386 /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */ 00387 addr = wpabuf_head(data->id_msgs); 00388 len = wpabuf_len(data->id_msgs); 00389 #ifdef EAP_AKA_PRIME 00390 if (data->eap_method == EAP_TYPE_AKA_PRIME) 00391 sha256_vector(1, &addr, &len, hash); 00392 else 00393 #endif /* EAP_AKA_PRIME */ 00394 sha1_vector(1, &addr, &len, hash); 00395 00396 if (os_memcmp(hash, checkcode, hash_len) != 0) { 00397 wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE"); 00398 return -1; 00399 } 00400 00401 return 0; 00402 } 00403 00404 00405 static struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id, 00406 int err) 00407 { 00408 struct eap_sim_msg *msg; 00409 00410 eap_aka_state(data, FAILURE); 00411 data->num_id_req = 0; 00412 data->num_notification = 0; 00413 00414 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 00415 EAP_AKA_SUBTYPE_CLIENT_ERROR); 00416 eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); 00417 return eap_sim_msg_finish(msg, NULL, NULL, 0); 00418 } 00419 00420 00421 static struct wpabuf * eap_aka_authentication_reject(struct eap_aka_data *data, 00422 u8 id) 00423 { 00424 struct eap_sim_msg *msg; 00425 00426 eap_aka_state(data, FAILURE); 00427 data->num_id_req = 0; 00428 data->num_notification = 0; 00429 00430 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject " 00431 "(id=%d)", id); 00432 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 00433 EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT); 00434 return eap_sim_msg_finish(msg, NULL, NULL, 0); 00435 } 00436 00437 00438 static struct wpabuf * eap_aka_synchronization_failure( 00439 struct eap_aka_data *data, u8 id) 00440 { 00441 struct eap_sim_msg *msg; 00442 00443 data->num_id_req = 0; 00444 data->num_notification = 0; 00445 00446 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure " 00447 "(id=%d)", id); 00448 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 00449 EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE); 00450 wpa_printf(MSG_DEBUG, " AT_AUTS"); 00451 eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, 00452 EAP_AKA_AUTS_LEN); 00453 return eap_sim_msg_finish(msg, NULL, NULL, 0); 00454 } 00455 00456 00457 static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm, 00458 struct eap_aka_data *data, 00459 u8 id, 00460 enum eap_sim_id_req id_req) 00461 { 00462 const u8 *identity = NULL; 00463 size_t identity_len = 0; 00464 struct eap_sim_msg *msg; 00465 00466 data->reauth = 0; 00467 if (id_req == ANY_ID && data->reauth_id) { 00468 identity = data->reauth_id; 00469 identity_len = data->reauth_id_len; 00470 data->reauth = 1; 00471 } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && 00472 data->pseudonym) { 00473 identity = data->pseudonym; 00474 identity_len = data->pseudonym_len; 00475 eap_aka_clear_identities(data, CLEAR_REAUTH_ID); 00476 } else if (id_req != NO_ID_REQ) { 00477 identity = eap_get_config_identity(sm, &identity_len); 00478 if (identity) { 00479 eap_aka_clear_identities(data, CLEAR_PSEUDONYM | 00480 CLEAR_REAUTH_ID); 00481 } 00482 } 00483 if (id_req != NO_ID_REQ) 00484 eap_aka_clear_identities(data, CLEAR_EAP_ID); 00485 00486 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id); 00487 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 00488 EAP_AKA_SUBTYPE_IDENTITY); 00489 00490 if (identity) { 00491 wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", 00492 identity, identity_len); 00493 eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, 00494 identity, identity_len); 00495 } 00496 00497 return eap_sim_msg_finish(msg, NULL, NULL, 0); 00498 } 00499 00500 00501 static struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data, 00502 u8 id) 00503 { 00504 struct eap_sim_msg *msg; 00505 00506 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id); 00507 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 00508 EAP_AKA_SUBTYPE_CHALLENGE); 00509 wpa_printf(MSG_DEBUG, " AT_RES"); 00510 eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8, 00511 data->res, data->res_len); 00512 eap_aka_add_checkcode(data, msg); 00513 if (data->use_result_ind) { 00514 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 00515 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 00516 } 00517 wpa_printf(MSG_DEBUG, " AT_MAC"); 00518 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 00519 return eap_sim_msg_finish(msg, data->k_aut, (u8 *) "", 0); 00520 } 00521 00522 00523 static struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data, 00524 u8 id, int counter_too_small, 00525 const u8 *nonce_s) 00526 { 00527 struct eap_sim_msg *msg; 00528 unsigned int counter; 00529 00530 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)", 00531 id); 00532 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 00533 EAP_AKA_SUBTYPE_REAUTHENTICATION); 00534 wpa_printf(MSG_DEBUG, " AT_IV"); 00535 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 00536 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 00537 00538 if (counter_too_small) { 00539 wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); 00540 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); 00541 counter = data->counter_too_small; 00542 } else 00543 counter = data->counter; 00544 00545 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); 00546 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 00547 00548 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 00549 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " 00550 "AT_ENCR_DATA"); 00551 eap_sim_msg_free(msg); 00552 return NULL; 00553 } 00554 eap_aka_add_checkcode(data, msg); 00555 if (data->use_result_ind) { 00556 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 00557 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 00558 } 00559 wpa_printf(MSG_DEBUG, " AT_MAC"); 00560 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 00561 return eap_sim_msg_finish(msg, data->k_aut, nonce_s, 00562 EAP_SIM_NONCE_S_LEN); 00563 } 00564 00565 00566 static struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data, 00567 u8 id, u16 notification) 00568 { 00569 struct eap_sim_msg *msg; 00570 u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; 00571 00572 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id); 00573 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 00574 EAP_AKA_SUBTYPE_NOTIFICATION); 00575 if (k_aut && data->reauth) { 00576 wpa_printf(MSG_DEBUG, " AT_IV"); 00577 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 00578 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 00579 EAP_SIM_AT_ENCR_DATA); 00580 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); 00581 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 00582 NULL, 0); 00583 if (eap_sim_msg_add_encr_end(msg, data->k_encr, 00584 EAP_SIM_AT_PADDING)) { 00585 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " 00586 "AT_ENCR_DATA"); 00587 eap_sim_msg_free(msg); 00588 return NULL; 00589 } 00590 } 00591 if (k_aut) { 00592 wpa_printf(MSG_DEBUG, " AT_MAC"); 00593 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 00594 } 00595 return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0); 00596 } 00597 00598 00599 static struct wpabuf * eap_aka_process_identity(struct eap_sm *sm, 00600 struct eap_aka_data *data, 00601 u8 id, 00602 const struct wpabuf *reqData, 00603 struct eap_sim_attrs *attr) 00604 { 00605 int id_error; 00606 struct wpabuf *buf; 00607 00608 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity"); 00609 00610 id_error = 0; 00611 switch (attr->id_req) { 00612 case NO_ID_REQ: 00613 break; 00614 case ANY_ID: 00615 if (data->num_id_req > 0) 00616 id_error++; 00617 data->num_id_req++; 00618 break; 00619 case FULLAUTH_ID: 00620 if (data->num_id_req > 1) 00621 id_error++; 00622 data->num_id_req++; 00623 break; 00624 case PERMANENT_ID: 00625 if (data->num_id_req > 2) 00626 id_error++; 00627 data->num_id_req++; 00628 break; 00629 } 00630 if (id_error) { 00631 wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests " 00632 "used within one authentication"); 00633 return eap_aka_client_error(data, id, 00634 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 00635 } 00636 00637 buf = eap_aka_response_identity(sm, data, id, attr->id_req); 00638 00639 if (data->prev_id != id) { 00640 eap_aka_add_id_msg(data, reqData); 00641 eap_aka_add_id_msg(data, buf); 00642 data->prev_id = id; 00643 } 00644 00645 return buf; 00646 } 00647 00648 00649 static int eap_aka_verify_mac(struct eap_aka_data *data, 00650 const struct wpabuf *req, 00651 const u8 *mac, const u8 *extra, 00652 size_t extra_len) 00653 { 00654 if (data->eap_method == EAP_TYPE_AKA_PRIME) 00655 return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra, 00656 extra_len); 00657 return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len); 00658 } 00659 00660 00661 #ifdef EAP_AKA_PRIME 00662 static struct wpabuf * eap_aka_prime_kdf_select(struct eap_aka_data *data, 00663 u8 id, u16 kdf) 00664 { 00665 struct eap_sim_msg *msg; 00666 00667 data->kdf_negotiation = 1; 00668 data->kdf = kdf; 00669 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d) (KDF " 00670 "select)", id); 00671 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 00672 EAP_AKA_SUBTYPE_CHALLENGE); 00673 wpa_printf(MSG_DEBUG, " AT_KDF"); 00674 eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0); 00675 return eap_sim_msg_finish(msg, NULL, NULL, 0); 00676 } 00677 00678 00679 static struct wpabuf * eap_aka_prime_kdf_neg(struct eap_aka_data *data, 00680 u8 id, struct eap_sim_attrs *attr) 00681 { 00682 size_t i; 00683 00684 for (i = 0; i < attr->kdf_count; i++) { 00685 if (attr->kdf[i] == EAP_AKA_PRIME_KDF) 00686 return eap_aka_prime_kdf_select(data, id, 00687 EAP_AKA_PRIME_KDF); 00688 } 00689 00690 /* No matching KDF found - fail authentication as if AUTN had been 00691 * incorrect */ 00692 return eap_aka_authentication_reject(data, id); 00693 } 00694 00695 00696 static int eap_aka_prime_kdf_valid(struct eap_aka_data *data, 00697 struct eap_sim_attrs *attr) 00698 { 00699 size_t i, j; 00700 00701 if (attr->kdf_count == 0) 00702 return 0; 00703 00704 /* The only allowed (and required) duplication of a KDF is the addition 00705 * of the selected KDF into the beginning of the list. */ 00706 00707 if (data->kdf_negotiation) { 00708 if (attr->kdf[0] != data->kdf) { 00709 wpa_printf(MSG_WARNING, "EAP-AKA': The server did not " 00710 "accept the selected KDF"); 00711 return 0; 00712 } 00713 00714 for (i = 1; i < attr->kdf_count; i++) { 00715 if (attr->kdf[i] == data->kdf) 00716 break; 00717 } 00718 if (i == attr->kdf_count && 00719 attr->kdf_count < EAP_AKA_PRIME_KDF_MAX) { 00720 wpa_printf(MSG_WARNING, "EAP-AKA': The server did not " 00721 "duplicate the selected KDF"); 00722 return 0; 00723 } 00724 00725 /* TODO: should check that the list is identical to the one 00726 * used in the previous Challenge message apart from the added 00727 * entry in the beginning. */ 00728 } 00729 00730 for (i = data->kdf ? 1 : 0; i < attr->kdf_count; i++) { 00731 for (j = i + 1; j < attr->kdf_count; j++) { 00732 if (attr->kdf[i] == attr->kdf[j]) { 00733 wpa_printf(MSG_WARNING, "EAP-AKA': The server " 00734 "included a duplicated KDF"); 00735 return 0; 00736 } 00737 } 00738 } 00739 00740 return 1; 00741 } 00742 #endif /* EAP_AKA_PRIME */ 00743 00744 00745 static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm, 00746 struct eap_aka_data *data, 00747 u8 id, 00748 const struct wpabuf *reqData, 00749 struct eap_sim_attrs *attr) 00750 { 00751 const u8 *identity; 00752 size_t identity_len; 00753 int res; 00754 struct eap_sim_attrs eattr; 00755 00756 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge"); 00757 00758 if (attr->checkcode && 00759 eap_aka_verify_checkcode(data, attr->checkcode, 00760 attr->checkcode_len)) { 00761 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " 00762 "message"); 00763 return eap_aka_client_error(data, id, 00764 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 00765 } 00766 00767 #ifdef EAP_AKA_PRIME 00768 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 00769 if (!attr->kdf_input || attr->kdf_input_len == 0) { 00770 wpa_printf(MSG_WARNING, "EAP-AKA': Challenge message " 00771 "did not include non-empty AT_KDF_INPUT"); 00772 /* Fail authentication as if AUTN had been incorrect */ 00773 return eap_aka_authentication_reject(data, id); 00774 } 00775 os_free(data->network_name); 00776 data->network_name = os_malloc(attr->kdf_input_len); 00777 if (data->network_name == NULL) { 00778 wpa_printf(MSG_WARNING, "EAP-AKA': No memory for " 00779 "storing Network Name"); 00780 return eap_aka_authentication_reject(data, id); 00781 } 00782 os_memcpy(data->network_name, attr->kdf_input, 00783 attr->kdf_input_len); 00784 data->network_name_len = attr->kdf_input_len; 00785 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': Network Name " 00786 "(AT_KDF_INPUT)", 00787 data->network_name, data->network_name_len); 00788 /* TODO: check Network Name per 3GPP.33.402 */ 00789 00790 if (!eap_aka_prime_kdf_valid(data, attr)) 00791 return eap_aka_authentication_reject(data, id); 00792 00793 if (attr->kdf[0] != EAP_AKA_PRIME_KDF) 00794 return eap_aka_prime_kdf_neg(data, id, attr); 00795 00796 data->kdf = EAP_AKA_PRIME_KDF; 00797 wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); 00798 } 00799 00800 if (data->eap_method == EAP_TYPE_AKA && attr->bidding) { 00801 u16 flags = WPA_GET_BE16(attr->bidding); 00802 if ((flags & EAP_AKA_BIDDING_FLAG_D) && 00803 eap_allowed_method(sm, EAP_VENDOR_IETF, 00804 EAP_TYPE_AKA_PRIME)) { 00805 wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from " 00806 "AKA' to AKA detected"); 00807 /* Fail authentication as if AUTN had been incorrect */ 00808 return eap_aka_authentication_reject(data, id); 00809 } 00810 } 00811 #endif /* EAP_AKA_PRIME */ 00812 00813 data->reauth = 0; 00814 if (!attr->mac || !attr->rand || !attr->autn) { 00815 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " 00816 "did not include%s%s%s", 00817 !attr->mac ? " AT_MAC" : "", 00818 !attr->rand ? " AT_RAND" : "", 00819 !attr->autn ? " AT_AUTN" : ""); 00820 return eap_aka_client_error(data, id, 00821 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 00822 } 00823 os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN); 00824 os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN); 00825 00826 res = eap_aka_umts_auth(sm, data); 00827 if (res == -1) { 00828 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " 00829 "failed (AUTN)"); 00830 return eap_aka_authentication_reject(data, id); 00831 } else if (res == -2) { 00832 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " 00833 "failed (AUTN seq# -> AUTS)"); 00834 return eap_aka_synchronization_failure(data, id); 00835 } else if (res) { 00836 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed"); 00837 return eap_aka_client_error(data, id, 00838 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 00839 } 00840 #ifdef EAP_AKA_PRIME 00841 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 00842 /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the 00843 * needed 6-octet SQN ^ AK for CK',IK' derivation */ 00844 u16 amf = WPA_GET_BE16(data->autn + 6); 00845 if (!(amf & 0x8000)) { 00846 wpa_printf(MSG_WARNING, "EAP-AKA': AMF separation bit " 00847 "not set (AMF=0x%4x)", amf); 00848 return eap_aka_authentication_reject(data, id); 00849 } 00850 eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, 00851 data->autn, 00852 data->network_name, 00853 data->network_name_len); 00854 } 00855 #endif /* EAP_AKA_PRIME */ 00856 if (data->last_eap_identity) { 00857 identity = data->last_eap_identity; 00858 identity_len = data->last_eap_identity_len; 00859 } else if (data->pseudonym) { 00860 identity = data->pseudonym; 00861 identity_len = data->pseudonym_len; 00862 } else 00863 identity = eap_get_config_identity(sm, &identity_len); 00864 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK " 00865 "derivation", identity, identity_len); 00866 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 00867 eap_aka_prime_derive_keys(identity, identity_len, data->ik, 00868 data->ck, data->k_encr, data->k_aut, 00869 data->k_re, data->msk, data->emsk); 00870 } else { 00871 eap_aka_derive_mk(identity, identity_len, data->ik, data->ck, 00872 data->mk); 00873 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, 00874 data->msk, data->emsk); 00875 } 00876 if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { 00877 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " 00878 "used invalid AT_MAC"); 00879 return eap_aka_client_error(data, id, 00880 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 00881 } 00882 00883 /* Old reauthentication and pseudonym identities must not be used 00884 * anymore. In other words, if no new identities are received, full 00885 * authentication will be used on next reauthentication. */ 00886 eap_aka_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID | 00887 CLEAR_EAP_ID); 00888 00889 if (attr->encr_data) { 00890 u8 *decrypted; 00891 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 00892 attr->encr_data_len, attr->iv, 00893 &eattr, 0); 00894 if (decrypted == NULL) { 00895 return eap_aka_client_error( 00896 data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); 00897 } 00898 eap_aka_learn_ids(data, &eattr); 00899 os_free(decrypted); 00900 } 00901 00902 if (data->result_ind && attr->result_ind) 00903 data->use_result_ind = 1; 00904 00905 if (data->state != FAILURE && data->state != RESULT_FAILURE) { 00906 eap_aka_state(data, data->use_result_ind ? 00907 RESULT_SUCCESS : SUCCESS); 00908 } 00909 00910 data->num_id_req = 0; 00911 data->num_notification = 0; 00912 /* RFC 4187 specifies that counter is initialized to one after 00913 * fullauth, but initializing it to zero makes it easier to implement 00914 * reauth verification. */ 00915 data->counter = 0; 00916 return eap_aka_response_challenge(data, id); 00917 } 00918 00919 00920 static int eap_aka_process_notification_reauth(struct eap_aka_data *data, 00921 struct eap_sim_attrs *attr) 00922 { 00923 struct eap_sim_attrs eattr; 00924 u8 *decrypted; 00925 00926 if (attr->encr_data == NULL || attr->iv == NULL) { 00927 wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after " 00928 "reauth did not include encrypted data"); 00929 return -1; 00930 } 00931 00932 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 00933 attr->encr_data_len, attr->iv, &eattr, 00934 0); 00935 if (decrypted == NULL) { 00936 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " 00937 "data from notification message"); 00938 return -1; 00939 } 00940 00941 if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) { 00942 wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification " 00943 "message does not match with counter in reauth " 00944 "message"); 00945 os_free(decrypted); 00946 return -1; 00947 } 00948 00949 os_free(decrypted); 00950 return 0; 00951 } 00952 00953 00954 static int eap_aka_process_notification_auth(struct eap_aka_data *data, 00955 const struct wpabuf *reqData, 00956 struct eap_sim_attrs *attr) 00957 { 00958 if (attr->mac == NULL) { 00959 wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth " 00960 "Notification message"); 00961 return -1; 00962 } 00963 00964 if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { 00965 wpa_printf(MSG_WARNING, "EAP-AKA: Notification message " 00966 "used invalid AT_MAC"); 00967 return -1; 00968 } 00969 00970 if (data->reauth && 00971 eap_aka_process_notification_reauth(data, attr)) { 00972 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification " 00973 "message after reauth"); 00974 return -1; 00975 } 00976 00977 return 0; 00978 } 00979 00980 00981 static struct wpabuf * eap_aka_process_notification( 00982 struct eap_sm *sm, struct eap_aka_data *data, u8 id, 00983 const struct wpabuf *reqData, struct eap_sim_attrs *attr) 00984 { 00985 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification"); 00986 if (data->num_notification > 0) { 00987 wpa_printf(MSG_INFO, "EAP-AKA: too many notification " 00988 "rounds (only one allowed)"); 00989 return eap_aka_client_error(data, id, 00990 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 00991 } 00992 data->num_notification++; 00993 if (attr->notification == -1) { 00994 wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in " 00995 "Notification message"); 00996 return eap_aka_client_error(data, id, 00997 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 00998 } 00999 01000 if ((attr->notification & 0x4000) == 0 && 01001 eap_aka_process_notification_auth(data, reqData, attr)) { 01002 return eap_aka_client_error(data, id, 01003 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 01004 } 01005 01006 eap_sim_report_notification(sm->msg_ctx, attr->notification, 1); 01007 if (attr->notification >= 0 && attr->notification < 32768) { 01008 eap_aka_state(data, FAILURE); 01009 } else if (attr->notification == EAP_SIM_SUCCESS && 01010 data->state == RESULT_SUCCESS) 01011 eap_aka_state(data, SUCCESS); 01012 return eap_aka_response_notification(data, id, attr->notification); 01013 } 01014 01015 01016 static struct wpabuf * eap_aka_process_reauthentication( 01017 struct eap_sm *sm, struct eap_aka_data *data, u8 id, 01018 const struct wpabuf *reqData, struct eap_sim_attrs *attr) 01019 { 01020 struct eap_sim_attrs eattr; 01021 u8 *decrypted; 01022 01023 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication"); 01024 01025 if (attr->checkcode && 01026 eap_aka_verify_checkcode(data, attr->checkcode, 01027 attr->checkcode_len)) { 01028 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " 01029 "message"); 01030 return eap_aka_client_error(data, id, 01031 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 01032 } 01033 01034 if (data->reauth_id == NULL) { 01035 wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying " 01036 "reauthentication, but no reauth_id available"); 01037 return eap_aka_client_error(data, id, 01038 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 01039 } 01040 01041 data->reauth = 1; 01042 if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { 01043 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " 01044 "did not have valid AT_MAC"); 01045 return eap_aka_client_error(data, id, 01046 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 01047 } 01048 01049 if (attr->encr_data == NULL || attr->iv == NULL) { 01050 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " 01051 "message did not include encrypted data"); 01052 return eap_aka_client_error(data, id, 01053 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 01054 } 01055 01056 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 01057 attr->encr_data_len, attr->iv, &eattr, 01058 0); 01059 if (decrypted == NULL) { 01060 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " 01061 "data from reauthentication message"); 01062 return eap_aka_client_error(data, id, 01063 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 01064 } 01065 01066 if (eattr.nonce_s == NULL || eattr.counter < 0) { 01067 wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet", 01068 !eattr.nonce_s ? " AT_NONCE_S" : "", 01069 eattr.counter < 0 ? " AT_COUNTER" : ""); 01070 os_free(decrypted); 01071 return eap_aka_client_error(data, id, 01072 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 01073 } 01074 01075 if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { 01076 struct wpabuf *res; 01077 wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter " 01078 "(%d <= %d)", eattr.counter, data->counter); 01079 data->counter_too_small = eattr.counter; 01080 01081 /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current 01082 * reauth_id must not be used to start a new reauthentication. 01083 * However, since it was used in the last EAP-Response-Identity 01084 * packet, it has to saved for the following fullauth to be 01085 * used in MK derivation. */ 01086 os_free(data->last_eap_identity); 01087 data->last_eap_identity = data->reauth_id; 01088 data->last_eap_identity_len = data->reauth_id_len; 01089 data->reauth_id = NULL; 01090 data->reauth_id_len = 0; 01091 01092 res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s); 01093 os_free(decrypted); 01094 01095 return res; 01096 } 01097 data->counter = eattr.counter; 01098 01099 os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); 01100 wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S", 01101 data->nonce_s, EAP_SIM_NONCE_S_LEN); 01102 01103 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 01104 eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, 01105 data->reauth_id, 01106 data->reauth_id_len, 01107 data->nonce_s, 01108 data->msk, data->emsk); 01109 } else { 01110 eap_sim_derive_keys_reauth(data->counter, data->reauth_id, 01111 data->reauth_id_len, 01112 data->nonce_s, data->mk, 01113 data->msk, data->emsk); 01114 } 01115 eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 01116 eap_aka_learn_ids(data, &eattr); 01117 01118 if (data->result_ind && attr->result_ind) 01119 data->use_result_ind = 1; 01120 01121 if (data->state != FAILURE && data->state != RESULT_FAILURE) { 01122 eap_aka_state(data, data->use_result_ind ? 01123 RESULT_SUCCESS : SUCCESS); 01124 } 01125 01126 data->num_id_req = 0; 01127 data->num_notification = 0; 01128 if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) { 01129 wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of " 01130 "fast reauths performed - force fullauth"); 01131 eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 01132 } 01133 os_free(decrypted); 01134 return eap_aka_response_reauth(data, id, 0, data->nonce_s); 01135 } 01136 01137 01138 static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, 01139 struct eap_method_ret *ret, 01140 const struct wpabuf *reqData) 01141 { 01142 struct eap_aka_data *data = priv; 01143 const struct eap_hdr *req; 01144 u8 subtype, id; 01145 struct wpabuf *res; 01146 const u8 *pos; 01147 struct eap_sim_attrs attr; 01148 size_t len; 01149 01150 wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData); 01151 if (eap_get_config_identity(sm, &len) == NULL) { 01152 wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); 01153 eap_sm_request_identity(sm); 01154 ret->ignore = TRUE; 01155 return NULL; 01156 } 01157 01158 pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData, 01159 &len); 01160 if (pos == NULL || len < 1) { 01161 ret->ignore = TRUE; 01162 return NULL; 01163 } 01164 req = wpabuf_head(reqData); 01165 id = req->identifier; 01166 len = be_to_host16(req->length); 01167 01168 ret->ignore = FALSE; 01169 ret->methodState = METHOD_MAY_CONT; 01170 ret->decision = DECISION_FAIL; 01171 ret->allowNotifications = TRUE; 01172 01173 subtype = *pos++; 01174 wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); 01175 pos += 2; /* Reserved */ 01176 01177 if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 01178 data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, 01179 0)) { 01180 res = eap_aka_client_error(data, id, 01181 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 01182 goto done; 01183 } 01184 01185 switch (subtype) { 01186 case EAP_AKA_SUBTYPE_IDENTITY: 01187 res = eap_aka_process_identity(sm, data, id, reqData, &attr); 01188 break; 01189 case EAP_AKA_SUBTYPE_CHALLENGE: 01190 res = eap_aka_process_challenge(sm, data, id, reqData, &attr); 01191 break; 01192 case EAP_AKA_SUBTYPE_NOTIFICATION: 01193 res = eap_aka_process_notification(sm, data, id, reqData, 01194 &attr); 01195 break; 01196 case EAP_AKA_SUBTYPE_REAUTHENTICATION: 01197 res = eap_aka_process_reauthentication(sm, data, id, reqData, 01198 &attr); 01199 break; 01200 case EAP_AKA_SUBTYPE_CLIENT_ERROR: 01201 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error"); 01202 res = eap_aka_client_error(data, id, 01203 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 01204 break; 01205 default: 01206 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype); 01207 res = eap_aka_client_error(data, id, 01208 EAP_AKA_UNABLE_TO_PROCESS_PACKET); 01209 break; 01210 } 01211 01212 done: 01213 if (data->state == FAILURE) { 01214 ret->decision = DECISION_FAIL; 01215 ret->methodState = METHOD_DONE; 01216 } else if (data->state == SUCCESS) { 01217 ret->decision = data->use_result_ind ? 01218 DECISION_UNCOND_SUCC : DECISION_COND_SUCC; 01219 /* 01220 * It is possible for the server to reply with AKA 01221 * Notification, so we must allow the method to continue and 01222 * not only accept EAP-Success at this point. 01223 */ 01224 ret->methodState = data->use_result_ind ? 01225 METHOD_DONE : METHOD_MAY_CONT; 01226 } else if (data->state == RESULT_FAILURE) 01227 ret->methodState = METHOD_CONT; 01228 else if (data->state == RESULT_SUCCESS) 01229 ret->methodState = METHOD_CONT; 01230 01231 if (ret->methodState == METHOD_DONE) { 01232 ret->allowNotifications = FALSE; 01233 } 01234 01235 return res; 01236 } 01237 01238 01239 static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv) 01240 { 01241 struct eap_aka_data *data = priv; 01242 return data->pseudonym || data->reauth_id; 01243 } 01244 01245 01246 static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv) 01247 { 01248 struct eap_aka_data *data = priv; 01249 eap_aka_clear_identities(data, CLEAR_EAP_ID); 01250 data->prev_id = -1; 01251 wpabuf_free(data->id_msgs); 01252 data->id_msgs = NULL; 01253 data->use_result_ind = 0; 01254 data->kdf_negotiation = 0; 01255 } 01256 01257 01258 static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv) 01259 { 01260 struct eap_aka_data *data = priv; 01261 data->num_id_req = 0; 01262 data->num_notification = 0; 01263 eap_aka_state(data, CONTINUE); 01264 return priv; 01265 } 01266 01267 01268 static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv, 01269 size_t *len) 01270 { 01271 struct eap_aka_data *data = priv; 01272 01273 if (data->reauth_id) { 01274 *len = data->reauth_id_len; 01275 return data->reauth_id; 01276 } 01277 01278 if (data->pseudonym) { 01279 *len = data->pseudonym_len; 01280 return data->pseudonym; 01281 } 01282 01283 return NULL; 01284 } 01285 01286 01287 static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv) 01288 { 01289 struct eap_aka_data *data = priv; 01290 return data->state == SUCCESS; 01291 } 01292 01293 01294 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) 01295 { 01296 struct eap_aka_data *data = priv; 01297 u8 *key; 01298 01299 if (data->state != SUCCESS) 01300 return NULL; 01301 01302 key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 01303 if (key == NULL) 01304 return NULL; 01305 01306 *len = EAP_SIM_KEYING_DATA_LEN; 01307 os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 01308 01309 return key; 01310 } 01311 01312 01313 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 01314 { 01315 struct eap_aka_data *data = priv; 01316 u8 *key; 01317 01318 if (data->state != SUCCESS) 01319 return NULL; 01320 01321 key = os_malloc(EAP_EMSK_LEN); 01322 if (key == NULL) 01323 return NULL; 01324 01325 *len = EAP_EMSK_LEN; 01326 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 01327 01328 return key; 01329 } 01330 01331 01332 int eap_peer_aka_register(void) 01333 { 01334 struct eap_method *eap; 01335 int ret; 01336 01337 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 01338 EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); 01339 if (eap == NULL) 01340 return -1; 01341 01342 eap->init = eap_aka_init; 01343 eap->deinit = eap_aka_deinit; 01344 eap->process = eap_aka_process; 01345 eap->isKeyAvailable = eap_aka_isKeyAvailable; 01346 eap->getKey = eap_aka_getKey; 01347 eap->has_reauth_data = eap_aka_has_reauth_data; 01348 eap->deinit_for_reauth = eap_aka_deinit_for_reauth; 01349 eap->init_for_reauth = eap_aka_init_for_reauth; 01350 eap->get_identity = eap_aka_get_identity; 01351 eap->get_emsk = eap_aka_get_emsk; 01352 01353 ret = eap_peer_method_register(eap); 01354 if (ret) 01355 eap_peer_method_free(eap); 01356 return ret; 01357 } 01358 01359 01360 #ifdef EAP_AKA_PRIME 01361 int eap_peer_aka_prime_register(void) 01362 { 01363 struct eap_method *eap; 01364 int ret; 01365 01366 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 01367 EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, 01368 "AKA'"); 01369 if (eap == NULL) 01370 return -1; 01371 01372 eap->init = eap_aka_prime_init; 01373 eap->deinit = eap_aka_deinit; 01374 eap->process = eap_aka_process; 01375 eap->isKeyAvailable = eap_aka_isKeyAvailable; 01376 eap->getKey = eap_aka_getKey; 01377 eap->has_reauth_data = eap_aka_has_reauth_data; 01378 eap->deinit_for_reauth = eap_aka_deinit_for_reauth; 01379 eap->init_for_reauth = eap_aka_init_for_reauth; 01380 eap->get_identity = eap_aka_get_identity; 01381 eap->get_emsk = eap_aka_get_emsk; 01382 01383 ret = eap_peer_method_register(eap); 01384 if (ret) 01385 eap_peer_method_free(eap); 01386 01387 return ret; 01388 } 01389 #endif /* EAP_AKA_PRIME */