00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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];
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
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
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
00190
00191 #ifdef CONFIG_USIM_HARDCODED
00192 wpa_printf(MSG_DEBUG, "EAP-AKA: Use hardcoded Kc and SRES values for "
00193 "testing");
00194
00195
00196
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
00215 test_resync = 0;
00216 return -2;
00217 }
00218 }
00219 #endif
00220 return 0;
00221
00222 #else
00223
00224 wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorith "
00225 "enabled");
00226 return -1;
00227
00228 #endif
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
00332
00333
00334 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
00335 return;
00336 }
00337
00338
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
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
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
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
00691
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
00705
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
00726
00727
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
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
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
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
00808 return eap_aka_authentication_reject(data, id);
00809 }
00810 }
00811 #endif
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
00843
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
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
00884
00885
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
00913
00914
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
01082
01083
01084
01085
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;
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
01221
01222
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