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 struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data, u8 id, u16 notification) { struct eap_sim_msg *msg; u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, EAP_AKA_SUBTYPE_NOTIFICATION); if (k_aut && data->reauth) { wpa_printf(MSG_DEBUG, " AT_IV"); wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, NULL, 0); if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " "AT_ENCR_DATA"); eap_sim_msg_free(msg); return NULL; } } if (k_aut) { wpa_printf(MSG_DEBUG, " AT_MAC"); eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); } return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0); }
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 struct wpabuf * eap_sim_build_start(struct eap_sm *sm, struct eap_sim_data *data, u8 id) { struct eap_sim_msg *msg; u8 ver[2]; wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, sm->identity_len)) { wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); } else { /* * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is * ignored and the SIM/Start is used to request the identity. */ wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); } wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); ver[0] = 0; ver[1] = EAP_SIM_VERSION; eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), ver, sizeof(ver)); return eap_sim_msg_finish(msg, NULL, NULL, 0); }
static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm, struct eap_aka_data *data, u8 id) { struct eap_sim_msg *msg; struct wpabuf *buf; wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, EAP_AKA_SUBTYPE_IDENTITY); if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, sm->identity_len)) { wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); } else { /* * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is * ignored and the AKA/Identity is used to request the * identity. */ wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); } buf = eap_sim_msg_finish(msg, NULL, NULL, 0); if (eap_aka_add_id_msg(data, buf) < 0) { wpabuf_free(buf); return NULL; } data->pending_id = id; return buf; }
static struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm, struct eap_sim_data *data, u8 id) { struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE); wpa_printf(MSG_DEBUG, " AT_RAND"); eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, data->num_chal * GSM_RAND_LEN); if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { 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, data->nonce_mt, EAP_SIM_NONCE_MT_LEN); }
static u8 * eap_sim_response_start(struct eap_sm *sm, struct eap_sim_data *data, const struct eap_hdr *req, size_t *respDataLen, enum eap_sim_id_req id_req) { const u8 *identity = NULL; size_t identity_len = 0; struct eap_sim_msg *msg; data->reauth = 0; if (id_req == ANY_ID && data->reauth_id) { identity = data->reauth_id; identity_len = data->reauth_id_len; data->reauth = 1; } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && data->pseudonym) { identity = data->pseudonym; identity_len = data->pseudonym_len; eap_sim_clear_identities(data, CLEAR_REAUTH_ID); } else if (id_req != NO_ID_REQ) { identity = eap_get_config_identity(sm, &identity_len); if (identity) { eap_sim_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID); } } if (id_req != NO_ID_REQ) eap_sim_clear_identities(data, CLEAR_EAP_ID); wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", req->identifier); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); if (!data->reauth) { wpa_hexdump(MSG_DEBUG, " AT_NONCE_MT", data->nonce_mt, EAP_SIM_NONCE_MT_LEN); eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0, data->nonce_mt, EAP_SIM_NONCE_MT_LEN); wpa_printf(MSG_DEBUG, " AT_SELECTED_VERSION %d", data->selected_version); eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION, data->selected_version, NULL, 0); } if (identity) { wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", identity, identity_len); eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, identity, identity_len); } return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); }
static struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id, int err) { struct eap_sim_msg *msg; eap_aka_state(data, FAILURE); data->num_id_req = 0; data->num_notification = 0; msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, EAP_AKA_SUBTYPE_CLIENT_ERROR); eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); return eap_sim_msg_finish(msg, NULL, NULL, 0); }
static struct wpabuf * eap_aka_authentication_reject(struct eap_aka_data *data, u8 id) { struct eap_sim_msg *msg; eap_aka_state(data, FAILURE); data->num_id_req = 0; data->num_notification = 0; wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject " "(id=%d)", id); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT); return eap_sim_msg_finish(msg, NULL, NULL, 0); }
static struct wpabuf * eap_aka_prime_kdf_select(struct eap_aka_data *data, u8 id, u16 kdf) { struct eap_sim_msg *msg; data->kdf_negotiation = 1; data->kdf = kdf; wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d) (KDF " "select)", id); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, EAP_AKA_SUBTYPE_CHALLENGE); wpa_printf(MSG_DEBUG, " AT_KDF"); eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0); return eap_sim_msg_finish(msg, NULL, NULL, 0); }
static u8 * eap_sim_client_error(struct eap_sm *sm, struct eap_sim_data *data, struct eap_hdr *req, size_t *respDataLen, int err) { struct eap_sim_msg *msg; data->state = FAILURE; data->num_id_req = 0; data->num_notification = 0; msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CLIENT_ERROR); eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); }
static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id, int err) { struct eap_sim_msg *msg; eap_sim_state(data, FAILURE); data->num_id_req = 0; data->num_notification = 0; wpa_printf(MSG_DEBUG, "EAP-SIM: Send Client-Error (error code %d)", err); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CLIENT_ERROR); eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0); }
static u8 * eap_sim_response_challenge(struct eap_sim_data *data, const struct eap_hdr *req, size_t *respDataLen) { struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", req->identifier); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE); wpa_printf(MSG_DEBUG, " AT_MAC"); eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); return eap_sim_msg_finish(msg, respDataLen, data->k_aut, (u8 *) data->sres, data->num_chal * EAP_SIM_SRES_LEN); }
static struct wpabuf * eap_aka_synchronization_failure( struct eap_aka_data *data, u8 id) { struct eap_sim_msg *msg; data->num_id_req = 0; data->num_notification = 0; wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure " "(id=%d)", id); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE); wpa_printf(MSG_DEBUG, " AT_AUTS"); eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, EAP_AKA_AUTS_LEN); return eap_sim_msg_finish(msg, NULL, NULL, 0); }
static u8 * eap_aka_response_challenge(struct eap_aka_data *data, const struct eap_hdr *req, size_t *respDataLen) { struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", req->identifier); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE); wpa_printf(MSG_DEBUG, " AT_RES"); eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8, data->res, data->res_len); wpa_printf(MSG_DEBUG, " AT_MAC"); eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); return eap_sim_msg_finish(msg, respDataLen, data->k_aut, (u8 *) "", 0); }
static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data, u8 id) { struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", id); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE); if (data->use_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, (u8 *) data->sres, data->num_chal * EAP_SIM_SRES_LEN); }
static u8 * eap_aka_authentication_reject(struct eap_aka_data *data, const struct eap_hdr *req, size_t *respDataLen) { struct eap_sim_msg *msg; data->state = FAILURE; data->num_id_req = 0; data->num_notification = 0; wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject " "(id=%d)", req->identifier); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, EAP_TYPE_AKA, EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT); return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); }
static u8 * eap_aka_response_identity(struct eap_sm *sm, struct eap_aka_data *data, const struct eap_hdr *req, size_t *respDataLen, enum eap_sim_id_req id_req) { const u8 *identity = NULL; size_t identity_len = 0; struct eap_sim_msg *msg; data->reauth = 0; if (id_req == ANY_ID && data->reauth_id) { identity = data->reauth_id; identity_len = data->reauth_id_len; data->reauth = 1; } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && data->pseudonym) { identity = data->pseudonym; identity_len = data->pseudonym_len; eap_aka_clear_identities(data, CLEAR_REAUTH_ID); } else if (id_req != NO_ID_REQ) { identity = eap_get_config_identity(sm, &identity_len); if (identity) { eap_aka_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID); } } if (id_req != NO_ID_REQ) eap_aka_clear_identities(data, CLEAR_EAP_ID); wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", req->identifier); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY); if (identity) { wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", identity, identity_len); eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, identity, identity_len); } return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); }
static struct wpabuf * eap_sim_build_start(struct eap_sm *sm, struct eap_sim_data *data, u8 id) { struct eap_sim_msg *msg; u8 ver[2]; wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); data->start_round++; if (data->start_round == 1) { /* * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is * ignored and the SIM/Start is used to request the identity. */ wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); } else if (data->start_round > 3) { /* Cannot use more than three rounds of Start messages */ eap_sim_msg_free(msg); return NULL; } else if (data->start_round == 0) { /* * This is a special case that is used to recover from * AT_COUNTER_TOO_SMALL during re-authentication. Since we * already know the identity of the peer, there is no need to * request any identity in this case. */ } else if (sm->identity && sm->identity_len > 0 && sm->identity[0] == EAP_SIM_REAUTH_ID_PREFIX) { /* Reauth id may have expired - try fullauth */ wpa_printf(MSG_DEBUG, " AT_FULLAUTH_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0); } else { wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); } wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); ver[0] = 0; ver[1] = EAP_SIM_VERSION; eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), ver, sizeof(ver)); return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0); }
static u8 * eap_aka_synchronization_failure(struct eap_aka_data *data, const struct eap_hdr *req, size_t *respDataLen) { struct eap_sim_msg *msg; data->num_id_req = 0; data->num_notification = 0; wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure " "(id=%d)", req->identifier); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, EAP_TYPE_AKA, EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE); wpa_printf(MSG_DEBUG, " AT_AUTS"); eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, EAP_AKA_AUTS_LEN); return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); }
static struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data, u8 id) { struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, EAP_AKA_SUBTYPE_CHALLENGE); wpa_printf(MSG_DEBUG, " AT_RES"); eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8, data->res, data->res_len); eap_aka_add_checkcode(data, msg); if (data->use_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, (u8 *) "", 0); }
static struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data, u8 id, int counter_too_small, const u8 *nonce_s) { struct eap_sim_msg *msg; unsigned int counter; wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)", id); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, EAP_AKA_SUBTYPE_REAUTHENTICATION); wpa_printf(MSG_DEBUG, " AT_IV"); wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); if (counter_too_small) { wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); counter = data->counter_too_small; } else counter = data->counter; wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " "AT_ENCR_DATA"); eap_sim_msg_free(msg); return NULL; } eap_aka_add_checkcode(data, msg); if (data->use_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, nonce_s, EAP_SIM_NONCE_S_LEN); }
static u8 * eap_sim_build_start(struct eap_sm *sm, struct eap_sim_data *data, int id, size_t *reqDataLen) { struct eap_sim_msg *msg; u8 ver[2]; wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, sm->identity_len)) { wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); } wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); ver[0] = 0; ver[1] = EAP_SIM_VERSION; eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), ver, sizeof(ver)); return eap_sim_msg_finish(msg, reqDataLen, NULL, NULL, 0); }
static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm, struct eap_aka_data *data, u8 id) { struct eap_sim_msg *msg; struct wpabuf *buf; wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, EAP_AKA_SUBTYPE_IDENTITY); data->identity_round++; if (data->identity_round == 1) { /* * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is * ignored and the AKA/Identity is used to request the * identity. */ wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); } else if (data->identity_round > 3) { /* Cannot use more than three rounds of Identity messages */ eap_sim_msg_free(msg); return NULL; } else if (sm->identity && sm->identity_len > 0 && (sm->identity[0] == EAP_AKA_REAUTH_ID_PREFIX || sm->identity[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX)) { /* Reauth id may have expired - try fullauth */ wpa_printf(MSG_DEBUG, " AT_FULLAUTH_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0); } else { wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); } buf = eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0); if (eap_aka_add_id_msg(data, buf) < 0) { wpabuf_free(buf); return NULL; } data->pending_id = id; return buf; }
static u8 * eap_sim_response_reauth(struct eap_sm *sm, struct eap_sim_data *data, struct eap_hdr *req, size_t *respDataLen, int counter_too_small) { struct eap_sim_msg *msg; unsigned int counter; wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)", req->identifier); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_REAUTHENTICATION); wpa_printf(MSG_DEBUG, " AT_IV"); wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); if (counter_too_small) { wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); counter = data->counter_too_small; } else counter = data->counter; wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " "AT_ENCR_DATA"); 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, respDataLen, data->k_aut, data->nonce_s, EAP_SIM_NONCE_S_LEN); }
static u8 * eap_sim_build_challenge(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 Challenge"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE); wpa_printf(MSG_DEBUG, " AT_RAND"); eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, data->num_chal * GSM_RAND_LEN); if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { 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, data->nonce_mt, EAP_SIM_NONCE_MT_LEN); }
static u8 * eap_sim_response_notification(struct eap_sm *sm, struct eap_sim_data *data, struct eap_hdr *req, size_t *respDataLen, u16 notification) { struct eap_sim_msg *msg; u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", req->identifier); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION); wpa_printf(MSG_DEBUG, " AT_NOTIFICATION"); eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, notification, NULL, 0); if (k_aut && data->reauth) { wpa_printf(MSG_DEBUG, " AT_IV"); wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, NULL, 0); if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " "AT_ENCR_DATA"); eap_sim_msg_free(msg); return NULL; } } if (k_aut) { wpa_printf(MSG_DEBUG, " AT_MAC"); eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); } return eap_sim_msg_finish(msg, respDataLen, k_aut, (u8 *) "", 0); }
static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm, struct eap_aka_data *data, u8 id) { struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, EAP_AKA_SUBTYPE_NOTIFICATION); wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, NULL, 0); if (data->use_result_ind) { if (data->reauth) { wpa_printf(MSG_DEBUG, " AT_IV"); wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", data->counter); eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, NULL, 0); if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { wpa_printf(MSG_WARNING, "EAP-AKA: Failed to " "encrypt AT_ENCR_DATA"); 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, data->k_aut, NULL, 0); }
static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm, struct eap_aka_data *data, u8 id) { struct eap_sim_msg *msg; wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge"); msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, EAP_AKA_SUBTYPE_CHALLENGE); wpa_printf(MSG_DEBUG, " AT_RAND"); eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN); wpa_printf(MSG_DEBUG, " AT_AUTN"); eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN); if (data->eap_method == EAP_TYPE_AKA_PRIME) { if (data->kdf) { /* Add the selected KDF into the beginning */ wpa_printf(MSG_DEBUG, " AT_KDF"); eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf, NULL, 0); } wpa_printf(MSG_DEBUG, " AT_KDF"); eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF, NULL, 0); wpa_printf(MSG_DEBUG, " AT_KDF_INPUT"); eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT, data->network_name_len, data->network_name, data->network_name_len); } if (eap_aka_build_encr(sm, data, msg, 0, NULL)) { eap_sim_msg_free(msg); return NULL; } eap_aka_add_checkcode(data, msg); 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); } #ifdef EAP_SERVER_AKA_PRIME if (data->eap_method == EAP_TYPE_AKA) { u16 flags = 0; int i; int aka_prime_preferred = 0; i = 0; while (sm->user && i < EAP_MAX_METHODS && (sm->user->methods[i].vendor != EAP_VENDOR_IETF || sm->user->methods[i].method != EAP_TYPE_NONE)) { if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) { if (sm->user->methods[i].method == EAP_TYPE_AKA) break; if (sm->user->methods[i].method == EAP_TYPE_AKA_PRIME) { aka_prime_preferred = 1; break; } } i++; } if (aka_prime_preferred) flags |= EAP_AKA_BIDDING_FLAG_D; eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0); } #endif /* EAP_SERVER_AKA_PRIME */ 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); }