u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data, size_t encr_data_len, const u8 *iv, struct eap_sim_attrs *attr, int aka) { u8 *decrypted; if (!iv) { wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV"); return NULL; } decrypted = os_malloc(encr_data_len); if (decrypted == NULL) return NULL; os_memcpy(decrypted, encr_data, encr_data_len); if (aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len)) { os_free(decrypted); return NULL; } wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA", decrypted, encr_data_len); if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr, aka, 1)) { wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse " "decrypted AT_ENCR_DATA"); os_free(decrypted); return NULL; } return decrypted; }
static void eap_sim_process(struct eap_sm *sm, void *priv, struct wpabuf *respData) { struct eap_sim_data *data = priv; const u8 *pos, *end; u8 subtype; size_t len; struct eap_sim_attrs attr; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); if (pos == NULL || len < 3) return; end = pos + len; subtype = *pos; pos += 3; if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) { wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes"); eap_sim_state(data, FAILURE); return; } if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) { eap_sim_process_client_error(sm, data, respData, &attr); return; } switch (data->state) { case START: eap_sim_process_start(sm, data, respData, &attr); break; case CHALLENGE: eap_sim_process_challenge(sm, data, respData, &attr); break; case REAUTH: eap_sim_process_reauth(sm, data, respData, &attr); break; case NOTIFICATION: eap_sim_process_notification(sm, data, respData, &attr); break; default: wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " "process", data->state); break; } }
static void eap_sim_process(struct eap_sm *sm, void *priv, u8 *respData, size_t respDataLen) { struct eap_sim_data *data = priv; struct eap_hdr *resp; u8 *pos, subtype; size_t len; struct eap_sim_attrs attr; resp = (struct eap_hdr *) respData; pos = (u8 *) (resp + 1); subtype = pos[1]; len = ntohs(resp->length); pos += 4; if (eap_sim_parse_attr(pos, respData + len, &attr, 0, 0)) { wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes"); eap_sim_state(data, FAILURE); return; } if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) { eap_sim_process_client_error(sm, data, respData, len, &attr); return; } switch (data->state) { case START: eap_sim_process_start(sm, data, respData, len, &attr); break; case CHALLENGE: eap_sim_process_challenge(sm, data, respData, len, &attr); break; case REAUTH: eap_sim_process_reauth(sm, data, respData, len, &attr); break; default: wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " "process", data->state); break; } }
static u8 * eap_sim_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, u8 *reqData, size_t reqDataLen, size_t *respDataLen) { struct eap_sim_data *data = priv; struct wpa_ssid *config = eap_get_config(sm); struct eap_hdr *req; u8 *pos, subtype, *res; struct eap_sim_attrs attr; size_t len; wpa_hexdump(MSG_DEBUG, "EAP-SIM: EAP data", reqData, reqDataLen); if (config == NULL || config->identity == NULL) { wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured"); eap_sm_request_identity(sm, config); ret->ignore = TRUE; return NULL; } req = (struct eap_hdr *) reqData; pos = (u8 *) (req + 1); if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_SIM || (len = be_to_host16(req->length)) > reqDataLen) { wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); ret->ignore = TRUE; return NULL; } ret->ignore = FALSE; ret->methodState = METHOD_CONT; ret->decision = DECISION_FAIL; ret->allowNotifications = TRUE; pos++; subtype = *pos++; wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype); pos += 2; /* Reserved */ if (eap_sim_parse_attr(pos, reqData + len, &attr, 0, 0)) { res = eap_sim_client_error(sm, data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); goto done; } switch (subtype) { case EAP_SIM_SUBTYPE_START: res = eap_sim_process_start(sm, data, req, len, respDataLen, &attr); break; case EAP_SIM_SUBTYPE_CHALLENGE: res = eap_sim_process_challenge(sm, data, req, len, respDataLen, &attr); break; case EAP_SIM_SUBTYPE_NOTIFICATION: res = eap_sim_process_notification(sm, data, req, len, respDataLen, &attr); break; case EAP_SIM_SUBTYPE_REAUTHENTICATION: res = eap_sim_process_reauthentication(sm, data, req, len, respDataLen, &attr); break; case EAP_SIM_SUBTYPE_CLIENT_ERROR: wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error"); res = eap_sim_client_error(sm, data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); break; default: wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype); res = eap_sim_client_error(sm, data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); break; } done: if (data->state == FAILURE) { ret->decision = DECISION_FAIL; ret->methodState = METHOD_DONE; } else if (data->state == SUCCESS) { ret->decision = DECISION_UNCOND_SUCC; ret->methodState = METHOD_DONE; } if (ret->methodState == METHOD_DONE) { ret->allowNotifications = FALSE; } return res; }
static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData) { struct eap_aka_data *data = priv; const struct eap_hdr *req; u8 subtype, id; struct wpabuf *res; const u8 *pos; struct eap_sim_attrs attr; size_t len; wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData); if (eap_get_config_identity(sm, &len) == NULL) { wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); eap_sm_request_identity(sm); ret->ignore = TRUE; return NULL; } pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData, &len); if (pos == NULL || len < 1) { ret->ignore = TRUE; return NULL; } req = wpabuf_head(reqData); id = req->identifier; len = be_to_host16(req->length); ret->ignore = FALSE; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; ret->allowNotifications = TRUE; subtype = *pos++; wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); pos += 2; /* Reserved */ if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, 0)) { res = eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); goto done; } switch (subtype) { case EAP_AKA_SUBTYPE_IDENTITY: res = eap_aka_process_identity(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_CHALLENGE: res = eap_aka_process_challenge(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_NOTIFICATION: res = eap_aka_process_notification(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_REAUTHENTICATION: res = eap_aka_process_reauthentication(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_CLIENT_ERROR: wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error"); res = eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); break; default: wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype); res = eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); break; } done: if (data->state == FAILURE) { ret->decision = DECISION_FAIL; ret->methodState = METHOD_DONE; } else if (data->state == SUCCESS) { ret->decision = data->use_result_ind ? DECISION_UNCOND_SUCC : DECISION_COND_SUCC; /* * It is possible for the server to reply with AKA * Notification, so we must allow the method to continue and * not only accept EAP-Success at this point. */ ret->methodState = data->use_result_ind ? METHOD_DONE : METHOD_MAY_CONT; } else if (data->state == RESULT_FAILURE) ret->methodState = METHOD_CONT; else if (data->state == RESULT_SUCCESS) ret->methodState = METHOD_CONT; if (ret->methodState == METHOD_DONE) { ret->allowNotifications = FALSE; } return res; }
static void eap_aka_process(struct eap_sm *sm, void *priv, struct wpabuf *respData) { struct eap_aka_data *data = priv; const u8 *pos, *end; u8 subtype; size_t len; struct eap_sim_attrs attr; pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, &len); if (pos == NULL || len < 3) return; end = pos + len; subtype = *pos; pos += 3; if (eap_aka_subtype_ok(data, subtype)) { wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected " "EAP-AKA Subtype in EAP Response"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } if (eap_sim_parse_attr(pos, end, &attr, data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, 0)) { wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) { eap_aka_process_client_error(sm, data, respData, &attr); return; } if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) { eap_aka_process_authentication_reject(sm, data, respData, &attr); return; } switch (data->state) { case IDENTITY: eap_aka_process_identity(sm, data, respData, &attr); break; case CHALLENGE: if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { eap_aka_process_sync_failure(sm, data, respData, &attr); } else { eap_aka_process_challenge(sm, data, respData, &attr); } break; case REAUTH: eap_aka_process_reauth(sm, data, respData, &attr); break; case NOTIFICATION: eap_aka_process_notification(sm, data, respData, &attr); break; default: wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " "process", data->state); break; } }