00001
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019
00020 #include "common.h"
00021 #include "eap_i.h"
00022 #include "wpa_supplicant.h"
00023 #include "config_ssid.h"
00024 #include "crypto.h"
00025 #include "pcsc_funcs.h"
00026 #include "eap_sim_common.h"
00027
00028
00029 #define EAP_AKA_SUBTYPE_CHALLENGE 1
00030 #define EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT 2
00031 #define EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE 4
00032 #define EAP_AKA_SUBTYPE_IDENTITY 5
00033 #define EAP_AKA_SUBTYPE_NOTIFICATION 12
00034 #define EAP_AKA_SUBTYPE_REAUTHENTICATION 13
00035 #define EAP_AKA_SUBTYPE_CLIENT_ERROR 14
00036
00037
00038 #define EAP_AKA_UNABLE_TO_PROCESS_PACKET 0
00039
00040 #define AKA_AUTS_LEN 14
00041 #define RES_MAX_LEN 16
00042 #define IK_LEN 16
00043 #define CK_LEN 16
00044 #define EAP_AKA_MAX_FAST_REAUTHS 1000
00045
00046 struct eap_aka_data {
00047 u8 ik[IK_LEN], ck[CK_LEN], res[RES_MAX_LEN];
00048 size_t res_len;
00049 u8 nonce_s[EAP_SIM_NONCE_S_LEN];
00050 u8 mk[EAP_SIM_MK_LEN];
00051 u8 k_aut[EAP_SIM_K_AUT_LEN];
00052 u8 k_encr[EAP_SIM_K_ENCR_LEN];
00053 u8 msk[EAP_SIM_KEYING_DATA_LEN];
00054 u8 rand[AKA_RAND_LEN], autn[AKA_AUTN_LEN];
00055 u8 auts[AKA_AUTS_LEN];
00056
00057 int num_id_req, num_notification;
00058 u8 *pseudonym;
00059 size_t pseudonym_len;
00060 u8 *reauth_id;
00061 size_t reauth_id_len;
00062 int reauth;
00063 unsigned int counter, counter_too_small;
00064 u8 *last_eap_identity;
00065 size_t last_eap_identity_len;
00066 enum { CONTINUE, SUCCESS, FAILURE } state;
00067 };
00068
00069
00070 static void * eap_aka_init(struct eap_sm *sm)
00071 {
00072 struct eap_aka_data *data;
00073 data = malloc(sizeof(*data));
00074 if (data == NULL)
00075 return NULL;
00076 memset(data, 0, sizeof(*data));
00077
00078 data->state = CONTINUE;
00079
00080 return data;
00081 }
00082
00083
00084 static void eap_aka_deinit(struct eap_sm *sm, void *priv)
00085 {
00086 struct eap_aka_data *data = priv;
00087 if (data) {
00088 free(data->pseudonym);
00089 free(data->reauth_id);
00090 free(data->last_eap_identity);
00091 free(data);
00092 }
00093 }
00094
00095
00096 static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data)
00097 {
00098 wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm");
00099 #ifdef PCSC_FUNCS
00100 return scard_umts_auth(sm->scard_ctx, data->rand,
00101 data->autn, data->res, &data->res_len,
00102 data->ik, data->ck, data->auts);
00103 #else
00104
00105
00106 memset(data->res, '2', RES_MAX_LEN);
00107 data->res_len = 16;
00108 memset(data->ik, '3', IK_LEN);
00109 memset(data->ck, '4', CK_LEN);
00110 {
00111 u8 autn[AKA_AUTN_LEN];
00112 memset(autn, '1', AKA_AUTN_LEN);
00113 if (memcmp(autn, data->autn, AKA_AUTN_LEN) != 0) {
00114 wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match "
00115 "with expected value");
00116 return -1;
00117 }
00118 }
00119 return 0;
00120 #endif
00121 }
00122
00123
00124 static void eap_aka_derive_mk(struct eap_aka_data *data,
00125 const u8 *identity, size_t identity_len)
00126 {
00127 const u8 *addr[3];
00128 size_t len[3];
00129
00130 addr[0] = identity;
00131 len[0] = identity_len;
00132 addr[1] = data->ik;
00133 len[1] = IK_LEN;
00134 addr[2] = data->ck;
00135 len[2] = CK_LEN;
00136
00137
00138 sha1_vector(3, addr, len, data->mk);
00139 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", data->ik, IK_LEN);
00140 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", data->ck, CK_LEN);
00141 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", data->mk, EAP_SIM_MK_LEN);
00142 }
00143
00144
00145 #define CLEAR_PSEUDONYM 0x01
00146 #define CLEAR_REAUTH_ID 0x02
00147 #define CLEAR_EAP_ID 0x04
00148
00149 static void eap_aka_clear_identities(struct eap_aka_data *data, int id)
00150 {
00151 wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old%s%s%s",
00152 id & CLEAR_PSEUDONYM ? " pseudonym" : "",
00153 id & CLEAR_REAUTH_ID ? " reauth_id" : "",
00154 id & CLEAR_EAP_ID ? " eap_id" : "");
00155 if (id & CLEAR_PSEUDONYM) {
00156 free(data->pseudonym);
00157 data->pseudonym = NULL;
00158 data->pseudonym_len = 0;
00159 }
00160 if (id & CLEAR_REAUTH_ID) {
00161 free(data->reauth_id);
00162 data->reauth_id = NULL;
00163 data->reauth_id_len = 0;
00164 }
00165 if (id & CLEAR_EAP_ID) {
00166 free(data->last_eap_identity);
00167 data->last_eap_identity = NULL;
00168 data->last_eap_identity_len = 0;
00169 }
00170 }
00171
00172
00173 static int eap_aka_learn_ids(struct eap_aka_data *data,
00174 struct eap_sim_attrs *attr)
00175 {
00176 if (attr->next_pseudonym) {
00177 free(data->pseudonym);
00178 data->pseudonym = malloc(attr->next_pseudonym_len);
00179 if (data->pseudonym == NULL) {
00180 wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
00181 "next pseudonym");
00182 return -1;
00183 }
00184 memcpy(data->pseudonym, attr->next_pseudonym,
00185 attr->next_pseudonym_len);
00186 data->pseudonym_len = attr->next_pseudonym_len;
00187 wpa_hexdump_ascii(MSG_DEBUG,
00188 "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
00189 data->pseudonym,
00190 data->pseudonym_len);
00191 }
00192
00193 if (attr->next_reauth_id) {
00194 free(data->reauth_id);
00195 data->reauth_id = malloc(attr->next_reauth_id_len);
00196 if (data->reauth_id == NULL) {
00197 wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
00198 "next reauth_id");
00199 return -1;
00200 }
00201 memcpy(data->reauth_id, attr->next_reauth_id,
00202 attr->next_reauth_id_len);
00203 data->reauth_id_len = attr->next_reauth_id_len;
00204 wpa_hexdump_ascii(MSG_DEBUG,
00205 "EAP-AKA: (encr) AT_NEXT_REAUTH_ID",
00206 data->reauth_id,
00207 data->reauth_id_len);
00208 }
00209
00210 return 0;
00211 }
00212
00213
00214 static u8 * eap_aka_client_error(struct eap_sm *sm, struct eap_aka_data *data,
00215 const struct eap_hdr *req,
00216 size_t *respDataLen, int err)
00217 {
00218 struct eap_sim_msg *msg;
00219
00220 data->state = FAILURE;
00221 data->num_id_req = 0;
00222 data->num_notification = 0;
00223
00224 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
00225 EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CLIENT_ERROR);
00226 eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
00227 return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0);
00228 }
00229
00230
00231 static u8 * eap_aka_authentication_reject(struct eap_sm *sm,
00232 struct eap_aka_data *data,
00233 const struct eap_hdr *req,
00234 size_t *respDataLen)
00235 {
00236 struct eap_sim_msg *msg;
00237
00238 data->state = FAILURE;
00239 data->num_id_req = 0;
00240 data->num_notification = 0;
00241
00242 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject "
00243 "(id=%d)", req->identifier);
00244 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
00245 EAP_TYPE_AKA,
00246 EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT);
00247 return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0);
00248 }
00249
00250
00251 static u8 * eap_aka_synchronization_failure(struct eap_sm *sm,
00252 struct eap_aka_data *data,
00253 const struct eap_hdr *req,
00254 size_t *respDataLen)
00255 {
00256 struct eap_sim_msg *msg;
00257
00258 data->state = FAILURE;
00259 data->num_id_req = 0;
00260 data->num_notification = 0;
00261
00262 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure "
00263 "(id=%d)", req->identifier);
00264 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
00265 EAP_TYPE_AKA,
00266 EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE);
00267 wpa_printf(MSG_DEBUG, " AT_AUTS");
00268 eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, AKA_AUTS_LEN);
00269 return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0);
00270 }
00271
00272
00273 static u8 * eap_aka_response_identity(struct eap_sm *sm,
00274 struct eap_aka_data *data,
00275 const struct eap_hdr *req,
00276 size_t *respDataLen,
00277 enum eap_sim_id_req id_req)
00278 {
00279 struct wpa_ssid *config = eap_get_config(sm);
00280 u8 *identity = NULL;
00281 size_t identity_len = 0;
00282 struct eap_sim_msg *msg;
00283
00284 data->reauth = 0;
00285 if (id_req == ANY_ID && data->reauth_id) {
00286 identity = data->reauth_id;
00287 identity_len = data->reauth_id_len;
00288 data->reauth = 1;
00289 } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
00290 data->pseudonym) {
00291 identity = data->pseudonym;
00292 identity_len = data->pseudonym_len;
00293 eap_aka_clear_identities(data, CLEAR_REAUTH_ID);
00294 } else if (id_req != NO_ID_REQ && config && config->identity) {
00295 identity = config->identity;
00296 identity_len = config->identity_len;
00297 eap_aka_clear_identities(data,
00298 CLEAR_PSEUDONYM | CLEAR_REAUTH_ID);
00299 }
00300 if (id_req != NO_ID_REQ)
00301 eap_aka_clear_identities(data, CLEAR_EAP_ID);
00302
00303 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)",
00304 req->identifier);
00305 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
00306 EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY);
00307
00308 if (identity) {
00309 wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY",
00310 identity, identity_len);
00311 eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
00312 identity, identity_len);
00313 }
00314
00315 return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0);
00316 }
00317
00318
00319 static u8 * eap_aka_response_challenge(struct eap_sm *sm,
00320 struct eap_aka_data *data,
00321 const struct eap_hdr *req,
00322 size_t *respDataLen)
00323 {
00324 struct eap_sim_msg *msg;
00325
00326 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)",
00327 req->identifier);
00328 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
00329 EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE);
00330 wpa_printf(MSG_DEBUG, " AT_RES");
00331 eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len,
00332 data->res, data->res_len);
00333 wpa_printf(MSG_DEBUG, " AT_MAC");
00334 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00335 return eap_sim_msg_finish(msg, respDataLen, data->k_aut, (u8 *) "", 0);
00336 }
00337
00338
00339 static u8 * eap_aka_response_reauth(struct eap_sm *sm,
00340 struct eap_aka_data *data,
00341 const struct eap_hdr *req,
00342 size_t *respDataLen, int counter_too_small)
00343 {
00344 struct eap_sim_msg *msg;
00345 unsigned int counter;
00346
00347 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)",
00348 req->identifier);
00349 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
00350 EAP_TYPE_AKA,
00351 EAP_AKA_SUBTYPE_REAUTHENTICATION);
00352 wpa_printf(MSG_DEBUG, " AT_IV");
00353 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
00354 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
00355
00356 if (counter_too_small) {
00357 wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL");
00358 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
00359 counter = data->counter_too_small;
00360 } else
00361 counter = data->counter;
00362
00363 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter);
00364 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
00365
00366 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
00367 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
00368 "AT_ENCR_DATA");
00369 eap_sim_msg_free(msg);
00370 return NULL;
00371 }
00372 wpa_printf(MSG_DEBUG, " AT_MAC");
00373 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00374 return eap_sim_msg_finish(msg, respDataLen, data->k_aut, data->nonce_s,
00375 EAP_SIM_NONCE_S_LEN);
00376 }
00377
00378
00379 static u8 * eap_aka_response_notification(struct eap_sm *sm,
00380 struct eap_aka_data *data,
00381 const struct eap_hdr *req,
00382 size_t *respDataLen,
00383 u16 notification)
00384 {
00385 struct eap_sim_msg *msg;
00386 u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
00387
00388 wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)",
00389 req->identifier);
00390 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
00391 EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION);
00392 wpa_printf(MSG_DEBUG, " AT_NOTIFICATION");
00393 eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, notification, NULL, 0);
00394 if (k_aut && data->reauth) {
00395 wpa_printf(MSG_DEBUG, " AT_IV");
00396 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
00397 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
00398 EAP_SIM_AT_ENCR_DATA);
00399 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter);
00400 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
00401 NULL, 0);
00402 if (eap_sim_msg_add_encr_end(msg, data->k_encr,
00403 EAP_SIM_AT_PADDING)) {
00404 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
00405 "AT_ENCR_DATA");
00406 eap_sim_msg_free(msg);
00407 return NULL;
00408 }
00409 }
00410 if (k_aut) {
00411 wpa_printf(MSG_DEBUG, " AT_MAC");
00412 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00413 }
00414 return eap_sim_msg_finish(msg, respDataLen, k_aut, (u8 *) "", 0);
00415 }
00416
00417
00418 static u8 * eap_aka_process_identity(struct eap_sm *sm,
00419 struct eap_aka_data *data,
00420 const struct eap_hdr *req,
00421 size_t reqDataLen,
00422 size_t *respDataLen,
00423 struct eap_sim_attrs *attr)
00424 {
00425 int id_error;
00426
00427 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity");
00428
00429 id_error = 0;
00430 switch (attr->id_req) {
00431 case NO_ID_REQ:
00432 break;
00433 case ANY_ID:
00434 if (data->num_id_req > 0)
00435 id_error++;
00436 data->num_id_req++;
00437 break;
00438 case FULLAUTH_ID:
00439 if (data->num_id_req > 1)
00440 id_error++;
00441 data->num_id_req++;
00442 break;
00443 case PERMANENT_ID:
00444 if (data->num_id_req > 2)
00445 id_error++;
00446 data->num_id_req++;
00447 break;
00448 }
00449 if (id_error) {
00450 wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests "
00451 "used within one authentication");
00452 return eap_aka_client_error(sm, data, req, respDataLen,
00453 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00454 }
00455
00456 return eap_aka_response_identity(sm, data, req, respDataLen,
00457 attr->id_req);
00458 }
00459
00460
00461 static u8 * eap_aka_process_challenge(struct eap_sm *sm,
00462 struct eap_aka_data *data,
00463 const struct eap_hdr *req,
00464 size_t reqDataLen,
00465 size_t *respDataLen,
00466 struct eap_sim_attrs *attr)
00467 {
00468 struct wpa_ssid *config = eap_get_config(sm);
00469 u8 *identity;
00470 size_t identity_len;
00471 int res;
00472 struct eap_sim_attrs eattr;
00473
00474 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge");
00475 data->reauth = 0;
00476 if (!attr->mac || !attr->rand || !attr->autn) {
00477 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
00478 "did not include%s%s%s",
00479 !attr->mac ? " AT_MAC" : "",
00480 !attr->rand ? " AT_RAND" : "",
00481 !attr->autn ? " AT_AUTN" : "");
00482 return eap_aka_client_error(sm, data, req, respDataLen,
00483 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00484 }
00485 memcpy(data->rand, attr->rand, AKA_RAND_LEN);
00486 memcpy(data->autn, attr->autn, AKA_AUTN_LEN);
00487
00488 res = eap_aka_umts_auth(sm, data);
00489 if (res == -1) {
00490 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
00491 "failed (AUTN)");
00492 return eap_aka_authentication_reject(sm, data, req,
00493 respDataLen);
00494 } else if (res == -2) {
00495 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
00496 "failed (AUTN seq# -> AUTS)");
00497 return eap_aka_synchronization_failure(sm, data, req,
00498 respDataLen);
00499 } else if (res) {
00500 wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed");
00501 return eap_aka_client_error(sm, data, req, respDataLen,
00502 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00503 }
00504 if (data->last_eap_identity) {
00505 identity = data->last_eap_identity;
00506 identity_len = data->last_eap_identity_len;
00507 } else if (data->pseudonym) {
00508 identity = data->pseudonym;
00509 identity_len = data->pseudonym_len;
00510 } else {
00511 identity = config->identity;
00512 identity_len = config->identity_len;
00513 }
00514 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
00515 "derivation", identity, identity_len);
00516 eap_aka_derive_mk(data, identity, identity_len);
00517 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk);
00518 if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
00519 attr->mac, (u8 *) "", 0)) {
00520 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
00521 "used invalid AT_MAC");
00522 return eap_aka_client_error(sm, data, req, respDataLen,
00523 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00524 }
00525
00526
00527
00528
00529 eap_aka_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID |
00530 CLEAR_EAP_ID);
00531
00532 if (attr->encr_data) {
00533 u8 *decrypted;
00534 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
00535 attr->encr_data_len, attr->iv,
00536 &eattr, 0);
00537 if (decrypted == NULL) {
00538 return eap_aka_client_error(
00539 sm, data, req, respDataLen,
00540 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00541 }
00542 eap_aka_learn_ids(data, &eattr);
00543 free(decrypted);
00544 }
00545
00546 if (data->state != FAILURE)
00547 data->state = SUCCESS;
00548
00549 data->num_id_req = 0;
00550 data->num_notification = 0;
00551
00552
00553
00554 data->counter = 0;
00555 return eap_aka_response_challenge(sm, data, req, respDataLen);
00556 }
00557
00558
00559 static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
00560 const struct eap_hdr *req,
00561 size_t reqDataLen,
00562 struct eap_sim_attrs *attr)
00563 {
00564 struct eap_sim_attrs eattr;
00565 u8 *decrypted;
00566
00567 if (attr->encr_data == NULL || attr->iv == NULL) {
00568 wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after "
00569 "reauth did not include encrypted data");
00570 return -1;
00571 }
00572
00573 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
00574 attr->encr_data_len, attr->iv, &eattr,
00575 0);
00576 if (decrypted == NULL) {
00577 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
00578 "data from notification message");
00579 return -1;
00580 }
00581
00582 if (eattr.counter != data->counter) {
00583 wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification "
00584 "message does not match with counter in reauth "
00585 "message");
00586 free(decrypted);
00587 return -1;
00588 }
00589
00590 free(decrypted);
00591 return 0;
00592 }
00593
00594
00595 static int eap_aka_process_notification_auth(struct eap_aka_data *data,
00596 const struct eap_hdr *req,
00597 size_t reqDataLen,
00598 struct eap_sim_attrs *attr)
00599 {
00600 if (attr->mac == NULL) {
00601 wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth "
00602 "Notification message");
00603 return -1;
00604 }
00605
00606 if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
00607 attr->mac, (u8 *) "", 0)) {
00608 wpa_printf(MSG_WARNING, "EAP-AKA: Notification message "
00609 "used invalid AT_MAC");
00610 return -1;
00611 }
00612
00613 if (data->reauth &&
00614 eap_aka_process_notification_reauth(data, req, reqDataLen, attr)) {
00615 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification "
00616 "message after reauth");
00617 return -1;
00618 }
00619
00620 return 0;
00621 }
00622
00623
00624 static u8 * eap_aka_process_notification(struct eap_sm *sm,
00625 struct eap_aka_data *data,
00626 const struct eap_hdr *req,
00627 size_t reqDataLen,
00628 size_t *respDataLen,
00629 struct eap_sim_attrs *attr)
00630 {
00631 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification");
00632 if (data->num_notification > 0) {
00633 wpa_printf(MSG_INFO, "EAP-AKA: too many notification "
00634 "rounds (only one allowed)");
00635 return eap_aka_client_error(sm, data, req, respDataLen,
00636 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00637 }
00638 data->num_notification++;
00639 if (attr->notification == -1) {
00640 wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in "
00641 "Notification message");
00642 return eap_aka_client_error(sm, data, req, respDataLen,
00643 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00644 }
00645
00646 if ((attr->notification & 0x4000) == 0 &&
00647 eap_aka_process_notification_auth(data, req, reqDataLen, attr)) {
00648 return eap_aka_client_error(sm, data, req, respDataLen,
00649 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00650 }
00651
00652 eap_sim_report_notification(sm->msg_ctx, attr->notification, 1);
00653 if (attr->notification >= 0 && attr->notification < 32768) {
00654 data->state = FAILURE;
00655 }
00656 return eap_aka_response_notification(sm, data, req, respDataLen,
00657 attr->notification);
00658 }
00659
00660
00661 static u8 * eap_aka_process_reauthentication(struct eap_sm *sm,
00662 struct eap_aka_data *data,
00663 const struct eap_hdr *req,
00664 size_t reqDataLen,
00665 size_t *respDataLen,
00666 struct eap_sim_attrs *attr)
00667 {
00668 struct eap_sim_attrs eattr;
00669 u8 *decrypted;
00670
00671 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication");
00672
00673 if (data->reauth_id == NULL) {
00674 wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying "
00675 "reauthentication, but no reauth_id available");
00676 return eap_aka_client_error(sm, data, req, respDataLen,
00677 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00678 }
00679
00680 data->reauth = 1;
00681 if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
00682 attr->mac, (u8 *) "", 0)) {
00683 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
00684 "did not have valid AT_MAC");
00685 return eap_aka_client_error(sm, data, req, respDataLen,
00686 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00687 }
00688
00689 if (attr->encr_data == NULL || attr->iv == NULL) {
00690 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
00691 "message did not include encrypted data");
00692 return eap_aka_client_error(sm, data, req, respDataLen,
00693 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00694 }
00695
00696 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
00697 attr->encr_data_len, attr->iv, &eattr,
00698 0);
00699 if (decrypted == NULL) {
00700 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
00701 "data from reauthentication message");
00702 return eap_aka_client_error(sm, data, req, respDataLen,
00703 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00704 }
00705
00706 if (eattr.nonce_s == NULL || eattr.counter < 0) {
00707 wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet",
00708 !eattr.nonce_s ? " AT_NONCE_S" : "",
00709 eattr.counter < 0 ? " AT_COUNTER" : "");
00710 free(decrypted);
00711 return eap_aka_client_error(sm, data, req, respDataLen,
00712 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00713 }
00714
00715 if (eattr.counter <= data->counter) {
00716 wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter "
00717 "(%d <= %d)", eattr.counter, data->counter);
00718 data->counter_too_small = eattr.counter;
00719
00720
00721
00722
00723
00724 free(data->last_eap_identity);
00725 data->last_eap_identity = data->reauth_id;
00726 data->last_eap_identity_len = data->reauth_id_len;
00727 data->reauth_id = NULL;
00728 data->reauth_id_len = 0;
00729 free(decrypted);
00730 return eap_aka_response_reauth(sm, data, req, respDataLen, 1);
00731 }
00732 data->counter = eattr.counter;
00733
00734 memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
00735 wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S",
00736 data->nonce_s, EAP_SIM_NONCE_S_LEN);
00737
00738 eap_sim_derive_keys_reauth(data->counter,
00739 data->reauth_id, data->reauth_id_len,
00740 data->nonce_s, data->mk, data->msk);
00741 eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
00742 eap_aka_learn_ids(data, &eattr);
00743
00744 if (data->state != FAILURE)
00745 data->state = SUCCESS;
00746
00747 data->num_id_req = 0;
00748 data->num_notification = 0;
00749 if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) {
00750 wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of "
00751 "fast reauths performed - force fullauth");
00752 eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
00753 }
00754 free(decrypted);
00755 return eap_aka_response_reauth(sm, data, req, respDataLen, 0);
00756 }
00757
00758
00759 static u8 * eap_aka_process(struct eap_sm *sm, void *priv,
00760 struct eap_method_ret *ret,
00761 const u8 *reqData, size_t reqDataLen,
00762 size_t *respDataLen)
00763 {
00764 struct eap_aka_data *data = priv;
00765 struct wpa_ssid *config = eap_get_config(sm);
00766 const struct eap_hdr *req;
00767 u8 subtype, *res;
00768 const u8 *pos;
00769 struct eap_sim_attrs attr;
00770 size_t len;
00771
00772 wpa_hexdump(MSG_DEBUG, "EAP-AKA: EAP data", reqData, reqDataLen);
00773 if (config == NULL || config->identity == NULL) {
00774 wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured");
00775 eap_sm_request_identity(sm, config);
00776 ret->ignore = TRUE;
00777 return NULL;
00778 }
00779
00780 pos = eap_hdr_validate(EAP_TYPE_AKA, reqData, reqDataLen, &len);
00781 if (pos == NULL || len < 1) {
00782 ret->ignore = TRUE;
00783 return NULL;
00784 }
00785 req = (const struct eap_hdr *) reqData;
00786 len = be_to_host16(req->length);
00787
00788 ret->ignore = FALSE;
00789 ret->methodState = METHOD_MAY_CONT;
00790 ret->decision = DECISION_FAIL;
00791 ret->allowNotifications = TRUE;
00792
00793 subtype = *pos++;
00794 wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype);
00795 pos += 2;
00796
00797 if (eap_sim_parse_attr(pos, reqData + len, &attr, 1, 0)) {
00798 res = eap_aka_client_error(sm, data, req, respDataLen,
00799 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00800 goto done;
00801 }
00802
00803 switch (subtype) {
00804 case EAP_AKA_SUBTYPE_IDENTITY:
00805 res = eap_aka_process_identity(sm, data, req, len,
00806 respDataLen, &attr);
00807 break;
00808 case EAP_AKA_SUBTYPE_CHALLENGE:
00809 res = eap_aka_process_challenge(sm, data, req, len,
00810 respDataLen, &attr);
00811 break;
00812 case EAP_AKA_SUBTYPE_NOTIFICATION:
00813 res = eap_aka_process_notification(sm, data, req, len,
00814 respDataLen, &attr);
00815 break;
00816 case EAP_AKA_SUBTYPE_REAUTHENTICATION:
00817 res = eap_aka_process_reauthentication(sm, data, req, len,
00818 respDataLen, &attr);
00819 break;
00820 case EAP_AKA_SUBTYPE_CLIENT_ERROR:
00821 wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error");
00822 res = eap_aka_client_error(sm, data, req, respDataLen,
00823 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00824 break;
00825 default:
00826 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype);
00827 res = eap_aka_client_error(sm, data, req, respDataLen,
00828 EAP_AKA_UNABLE_TO_PROCESS_PACKET);
00829 break;
00830 }
00831
00832 done:
00833 if (data->state == FAILURE) {
00834 ret->decision = DECISION_FAIL;
00835 ret->methodState = METHOD_DONE;
00836 } else if (data->state == SUCCESS) {
00837 ret->decision = DECISION_COND_SUCC;
00838 ret->methodState = METHOD_DONE;
00839 }
00840
00841 if (ret->methodState == METHOD_DONE) {
00842 ret->allowNotifications = FALSE;
00843 }
00844
00845 return res;
00846 }
00847
00848
00849 static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv)
00850 {
00851 struct eap_aka_data *data = priv;
00852 return data->pseudonym || data->reauth_id;
00853 }
00854
00855
00856 static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv)
00857 {
00858 struct eap_aka_data *data = priv;
00859 eap_aka_clear_identities(data, CLEAR_EAP_ID);
00860 }
00861
00862
00863 static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv)
00864 {
00865 struct eap_aka_data *data = priv;
00866 data->num_id_req = 0;
00867 data->num_notification = 0;
00868 data->state = CONTINUE;
00869 return priv;
00870 }
00871
00872
00873 static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv,
00874 size_t *len)
00875 {
00876 struct eap_aka_data *data = priv;
00877
00878 if (data->reauth_id) {
00879 *len = data->reauth_id_len;
00880 return data->reauth_id;
00881 }
00882
00883 if (data->pseudonym) {
00884 *len = data->pseudonym_len;
00885 return data->pseudonym;
00886 }
00887
00888 return NULL;
00889 }
00890
00891
00892 static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv)
00893 {
00894 struct eap_aka_data *data = priv;
00895 return data->state == SUCCESS;
00896 }
00897
00898
00899 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
00900 {
00901 struct eap_aka_data *data = priv;
00902 u8 *key;
00903
00904 if (data->state != SUCCESS)
00905 return NULL;
00906
00907 key = malloc(EAP_SIM_KEYING_DATA_LEN);
00908 if (key == NULL)
00909 return NULL;
00910
00911 *len = EAP_SIM_KEYING_DATA_LEN;
00912 memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
00913
00914 return key;
00915 }
00916
00917
00918 const struct eap_method eap_method_aka =
00919 {
00920 .method = EAP_TYPE_AKA,
00921 .name = "AKA",
00922 .init = eap_aka_init,
00923 .deinit = eap_aka_deinit,
00924 .process = eap_aka_process,
00925 .isKeyAvailable = eap_aka_isKeyAvailable,
00926 .getKey = eap_aka_getKey,
00927 .has_reauth_data = eap_aka_has_reauth_data,
00928 .deinit_for_reauth = eap_aka_deinit_for_reauth,
00929 .init_for_reauth = eap_aka_init_for_reauth,
00930 .get_identity = eap_aka_get_identity,
00931 };
00932