static void eap_aka_process_sync_failure(struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr) { wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure"); if (attr->auts == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure " "message did not include valid AT_AUTS"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } /* Avoid re-reporting AUTS when processing pending EAP packet by * maintaining a local flag stating whether this AUTS has already been * reported. */ if (!data->auts_reported && eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity, sm->identity_len, attr->auts, data->rand)) { wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } data->auts_reported = 1; /* Try again after resynchronization */ eap_aka_determine_identity(sm, data, 0, 0); }
static void eap_aka_process_identity(struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr) { wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity"); if (attr->mac || attr->iv || attr->encr_data) { wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute " "received in EAP-Response/AKA-Identity"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } if (attr->identity) { os_free(sm->identity); sm->identity = os_malloc(attr->identity_len); if (sm->identity) { os_memcpy(sm->identity, attr->identity, attr->identity_len); sm->identity_len = attr->identity_len; } } eap_aka_determine_identity(sm, data, 0, 0); if (eap_get_id(respData) == data->pending_id) { data->pending_id = -1; eap_aka_add_id_msg(data, respData); } }
static void * eap_aka_prime_init(struct eap_sm *sm) { struct eap_aka_data *data; /* TODO: make ANID configurable; see 3GPP TS 24.302 */ char *network_name = "WLAN"; if (sm->eap_sim_db_priv == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); return NULL; } data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->eap_method = EAP_TYPE_AKA_PRIME; data->network_name = os_malloc(os_strlen(network_name)); if (data->network_name == NULL) { os_free(data); return NULL; } data->network_name_len = os_strlen(network_name); os_memcpy(data->network_name, network_name, data->network_name_len); data->state = IDENTITY; eap_aka_determine_identity(sm, data, 1, 0); data->pending_id = -1; return data; }
static void eap_aka_process_identity(struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr) { u8 *new_identity; wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity"); if (attr->mac || attr->iv || attr->encr_data) { wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute " "received in EAP-Response/AKA-Identity"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } /* * We always request identity with AKA/Identity, so the peer is * required to have replied with one. */ if (!attr->identity || attr->identity_len == 0) { wpa_printf(MSG_DEBUG, "EAP-AKA: Peer did not provide any " "identity"); data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } new_identity = os_malloc(attr->identity_len); if (new_identity == NULL) { data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); return; } os_free(sm->identity); sm->identity = new_identity; os_memcpy(sm->identity, attr->identity, attr->identity_len); sm->identity_len = attr->identity_len; eap_aka_determine_identity(sm, data); if (eap_get_id(respData) == data->pending_id) { data->pending_id = -1; eap_aka_add_id_msg(data, respData); } }
static void * eap_aka_init(struct eap_sm *sm) { struct eap_aka_data *data; if (sm->eap_sim_db_priv == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); return NULL; } data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->eap_method = EAP_TYPE_AKA; data->state = IDENTITY; eap_aka_determine_identity(sm, data, 1, 0); data->pending_id = -1; return data; }
static void eap_aka_process_reauth(struct eap_sm *sm, struct eap_aka_data *data, struct wpabuf *respData, struct eap_sim_attrs *attr) { struct eap_sim_attrs eattr; u8 *decrypted = NULL; const u8 *identity, *id2; size_t identity_len, id2_len; wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication"); if (attr->mac == NULL || eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s, EAP_SIM_NONCE_S_LEN)) { wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " "did not include valid AT_MAC"); goto fail; } if (attr->encr_data == NULL || attr->iv == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " "message did not include encrypted data"); goto fail; } decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, attr->encr_data_len, attr->iv, &eattr, 0); if (decrypted == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " "data from reauthentication message"); goto fail; } if (eattr.counter != data->counter) { wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " "used incorrect counter %u, expected %u", eattr.counter, data->counter); goto fail; } os_free(decrypted); decrypted = NULL; wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes " "the correct AT_MAC"); if (eattr.counter_too_small) { wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response " "included AT_COUNTER_TOO_SMALL - starting full " "authentication"); eap_aka_determine_identity(sm, data, 0, 1); return; } if (sm->eap_sim_aka_result_ind && attr->result_ind) { data->use_result_ind = 1; data->notification = EAP_SIM_SUCCESS; eap_aka_state(data, NOTIFICATION); } else eap_aka_state(data, SUCCESS); if (data->reauth) { identity = data->reauth->identity; identity_len = data->reauth->identity_len; } else { identity = sm->identity; identity_len = sm->identity_len; } id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, identity_len, &id2_len); if (id2) { identity = id2; identity_len = id2_len; } if (data->next_pseudonym) { eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, identity_len, data->next_pseudonym); data->next_pseudonym = NULL; } if (data->next_reauth_id) { if (data->eap_method == EAP_TYPE_AKA_PRIME) { #ifdef EAP_SERVER_AKA_PRIME eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, identity, identity_len, data->next_reauth_id, data->counter + 1, data->k_encr, data->k_aut, data->k_re); #endif /* EAP_SERVER_AKA_PRIME */ } else { eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, identity_len, data->next_reauth_id, data->counter + 1, data->mk); } data->next_reauth_id = NULL; } else { eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); data->reauth = NULL; } return; fail: data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; eap_aka_state(data, NOTIFICATION); eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); data->reauth = NULL; os_free(decrypted); }