static struct wpabuf * eap_mschapv2_challenge_reply( struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id, u8 mschapv2_id, const u8 *auth_challenge) { struct wpabuf *resp; struct eap_mschapv2_hdr *ms; u8 *peer_challenge; int ms_len; struct ms_response *r; size_t identity_len, password_len; const u8 *identity, *password; int pwhash; wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generate Challenge Response\n"); identity = eap_get_config_identity(sm, &identity_len); password = eap_get_config_password2(sm, &password_len, &pwhash); if (identity == NULL || password == NULL) return NULL; ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len; resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, EAP_CODE_RESPONSE, id); if (resp == NULL) return NULL; ms = wpabuf_put(resp, sizeof(*ms)); ms->op_code = MSCHAPV2_OP_RESPONSE; ms->mschapv2_id = mschapv2_id; if (data->prev_error) ms->mschapv2_id++; WPA_PUT_BE16(ms->ms_length, ms_len); wpabuf_put_u8(resp, sizeof(*r)); /* Response */ r = wpabuf_put(resp, sizeof(*r)); peer_challenge = r->peer_challenge; if (data->peer_challenge) { peer_challenge = data->peer_challenge; os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN); } else if (random_get_bytes(peer_challenge, MSCHAPV2_CHAL_LEN)) { wpabuf_free(resp); return NULL; } os_memset(r->reserved, 0, 8); if (data->auth_challenge) auth_challenge = data->auth_challenge; if (mschapv2_derive_response(identity, identity_len, password, password_len, pwhash, auth_challenge, peer_challenge, r->nt_response, data->auth_response, data->master_key)) { wpabuf_free(resp); return NULL; } data->auth_response_valid = 1; data->master_key_valid = 1; r->flags = 0; wpabuf_put_data(resp, identity, identity_len); return resp; }
static struct wpabuf * eap_mschapv2_challenge_reply( struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id, u8 mschapv2_id, const u8 *auth_challenge) { struct wpabuf *resp; struct eap_mschapv2_hdr *ms; u8 *peer_challenge; int ms_len; struct ms_response *r; size_t identity_len, password_len; const u8 *identity, *password; int pwhash; wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response"); identity = eap_get_config_identity(sm, &identity_len); password = eap_get_config_password2(sm, &password_len, &pwhash); if (identity == NULL || password == NULL) return NULL; ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len; resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, EAP_CODE_RESPONSE, id); if (resp == NULL) return NULL; ms = wpabuf_put(resp, sizeof(*ms)); ms->op_code = MSCHAPV2_OP_RESPONSE; ms->mschapv2_id = mschapv2_id; if (data->prev_error) { /* * TODO: this does not seem to be enough when processing two * or more failure messages. IAS did not increment mschapv2_id * in its own packets, but it seemed to expect the peer to * increment this for all packets(?). */ ms->mschapv2_id++; } WPA_PUT_BE16(ms->ms_length, ms_len); wpabuf_put_u8(resp, sizeof(*r)); /* Value-Size */ /* Response */ r = wpabuf_put(resp, sizeof(*r)); peer_challenge = r->peer_challenge; if (data->peer_challenge) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated " "in Phase 1"); peer_challenge = data->peer_challenge; os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN); } else if (random_get_bytes(peer_challenge, MSCHAPV2_CHAL_LEN)) { wpabuf_free(resp); return NULL; } os_memset(r->reserved, 0, 8); if (data->auth_challenge) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated " "in Phase 1"); auth_challenge = data->auth_challenge; } if (mschapv2_derive_response(identity, identity_len, password, password_len, pwhash, auth_challenge, peer_challenge, r->nt_response, data->auth_response, data->master_key)) { wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to derive " "response"); wpabuf_free(resp); return NULL; } data->auth_response_valid = 1; data->master_key_valid = 1; r->flags = 0; /* reserved, must be zero */ wpabuf_put_data(resp, identity, identity_len); wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " "(response)", id, ms->mschapv2_id); return resp; }