static struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm, struct eap_sim_data *data, u8 id) { struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); if (os_get_random(data->nonce_s, EAP_SIM_NONCE_S_LEN)) return NULL; wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", data->nonce_s, EAP_SIM_NONCE_S_LEN); eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, data->emsk); eap_sim_derive_keys_reauth(data->counter, sm->identity, sm->identity_len, data->nonce_s, data->mk, data->msk, data->emsk); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_REAUTHENTICATION); if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { eap_sim_msg_free(msg); return NULL; } if (sm->eap_sim_aka_result_ind) { wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); } wpa_printf(MSG_DEBUG, " AT_MAC"); eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); }
static u8 * eap_sim_build_reauth(struct eap_sm *sm, struct eap_sim_data *data, int id, size_t *reqDataLen) { struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); if (hostapd_get_rand(data->nonce_s, EAP_SIM_NONCE_S_LEN)) return NULL; wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", data->nonce_s, EAP_SIM_NONCE_S_LEN); eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, data->emsk); eap_sim_derive_keys_reauth(data->counter, sm->identity, sm->identity_len, data->nonce_s, data->mk, data->msk, data->emsk); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_REAUTHENTICATION); if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { eap_sim_msg_free(msg); return NULL; } wpa_printf(MSG_DEBUG, " AT_MAC"); eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); return eap_sim_msg_finish(msg, reqDataLen, data->k_aut, NULL, 0); }
static u8 * eap_sim_process_reauthentication(struct eap_sm *sm, struct eap_sim_data *data, struct eap_hdr *req, size_t reqDataLen, size_t *respDataLen, struct eap_sim_attrs *attr) { struct eap_sim_attrs eattr; wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication"); if (data->reauth_id == NULL) { wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying " "reauthentication, but no reauth_id available"); return eap_sim_client_error(sm, data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } data->reauth = 1; if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac, (u8 *) "", 0)) { wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " "did not have valid AT_MAC"); return eap_sim_client_error(sm, data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } if (attr->encr_data == NULL || attr->iv == NULL) { wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " "message did not include encrypted data"); return eap_sim_client_error(sm, data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } if (eap_sim_parse_encr(data->k_encr, attr->encr_data, attr->encr_data_len, attr->iv, &eattr, 0)) { wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " "data from reauthentication message"); return eap_sim_client_error(sm, data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } if (eattr.nonce_s == NULL || eattr.counter < 0) { wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet", !eattr.nonce_s ? " AT_NONCE_S" : "", eattr.counter < 0 ? " AT_COUNTER" : ""); return eap_sim_client_error(sm, data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } if (eattr.counter <= data->counter) { wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter " "(%d <= %d)", eattr.counter, data->counter); data->counter_too_small = eattr.counter; /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current * reauth_id must not be used to start a new reauthentication. * However, since it was used in the last EAP-Response-Identity * packet, it has to saved for the following fullauth to be * used in MK derivation. */ free(data->last_eap_identity); data->last_eap_identity = data->reauth_id; data->last_eap_identity_len = data->reauth_id_len; data->reauth_id = NULL; data->reauth_id_len = 0; return eap_sim_response_reauth(sm, data, req, respDataLen, 1); } data->counter = eattr.counter; memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S", data->nonce_s, EAP_SIM_NONCE_S_LEN); eap_sim_derive_keys_reauth(data->counter, data->reauth_id, data->reauth_id_len, data->nonce_s, data->mk, data->msk); eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); eap_sim_learn_ids(data, &eattr); if (data->state != FAILURE) data->state = SUCCESS; data->num_id_req = 0; data->num_notification = 0; if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) { wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of " "fast reauths performed - force fullauth"); eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); } return eap_sim_response_reauth(sm, data, req, respDataLen, 0); }
static struct wpabuf * eap_aka_process_reauthentication( struct eap_sm *sm, struct eap_aka_data *data, u8 id, const struct wpabuf *reqData, struct eap_sim_attrs *attr) { struct eap_sim_attrs eattr; u8 *decrypted; wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication"); if (attr->checkcode && eap_aka_verify_checkcode(data, attr->checkcode, attr->checkcode_len)) { wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " "message"); return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } if (data->reauth_id == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying " "reauthentication, but no reauth_id available"); return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } data->reauth = 1; if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " "did not have valid AT_MAC"); return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } if (attr->encr_data == NULL || attr->iv == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " "message did not include encrypted data"); return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } 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"); return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } if (eattr.nonce_s == NULL || eattr.counter < 0) { wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet", !eattr.nonce_s ? " AT_NONCE_S" : "", eattr.counter < 0 ? " AT_COUNTER" : ""); os_free(decrypted); return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { struct wpabuf *res; wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter " "(%d <= %d)", eattr.counter, data->counter); data->counter_too_small = eattr.counter; /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current * reauth_id must not be used to start a new reauthentication. * However, since it was used in the last EAP-Response-Identity * packet, it has to saved for the following fullauth to be * used in MK derivation. */ os_free(data->last_eap_identity); data->last_eap_identity = data->reauth_id; data->last_eap_identity_len = data->reauth_id_len; data->reauth_id = NULL; data->reauth_id_len = 0; res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s); os_free(decrypted); return res; } data->counter = eattr.counter; os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S", data->nonce_s, EAP_SIM_NONCE_S_LEN); if (data->eap_method == EAP_TYPE_AKA_PRIME) { eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, data->reauth_id, data->reauth_id_len, data->nonce_s, data->msk, data->emsk); } else { eap_sim_derive_keys_reauth(data->counter, data->reauth_id, data->reauth_id_len, data->nonce_s, data->mk, data->msk, data->emsk); } eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); eap_aka_learn_ids(sm, data, &eattr); if (data->result_ind && attr->result_ind) data->use_result_ind = 1; if (data->state != FAILURE && data->state != RESULT_FAILURE) { eap_aka_state(data, data->use_result_ind ? RESULT_SUCCESS : SUCCESS); } data->num_id_req = 0; data->num_notification = 0; if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) { wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of " "fast reauths performed - force fullauth"); eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); } os_free(decrypted); return eap_aka_response_reauth(data, id, 0, data->nonce_s); }