/*
 * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

/**
 * DOC: wlan_hdd_fips.c
 *
 * WLAN Host Device Driver FIPS Certification Feature
 */

#include "wlan_hdd_main.h"
#include "wlan_hdd_fips.h"
#include "wlan_hdd_request_manager.h"
#include "qdf_mem.h"
#include "sme_api.h"


#define WLAN_WAIT_TIME_FIPS 5000


/**
 * hdd_fips_context - hdd fips context
 * @status: status of response. 0: no error, -ENOMEM: unable to allocate
 *   memory for the response payload
 * @request: fips request
 * @response: fips response
 */
struct hdd_fips_context {
	int status;
	struct fips_params request;
	struct wmi_host_fips_event_param response;
};

/**
 * hdd_fips_event_dup () - duplicate a fips event
 * @dest: destination event
 * @src: source event
 *
 * Make a "deep" duplicate of a FIPS event
 *
 * Return: 0 if the event was duplicated, otherwise an error
 */
static int hdd_fips_event_dup(struct wmi_host_fips_event_param *dest,
			      const struct wmi_host_fips_event_param *src)
{
	*dest = *src;
	if  (dest->data_len) {
		dest->data = qdf_mem_malloc(dest->data_len);
		if (!dest->data) {
			hdd_err("memory allocation failed");
			return -ENOMEM;
		}
		qdf_mem_copy(dest->data, src->data, src->data_len);
	} else {
		/* make sure we don't have a rogue pointer */
		dest->data = NULL;
	}

	return 0;
}

/**
 * hdd_fips_cb () - fips response message handler
 * @cookie: hdd request cookie
 * @response: fips response parameters
 *
 * Return: none
 */
static void hdd_fips_cb(void *cookie,
			struct wmi_host_fips_event_param *response)
{
	struct hdd_request *request;
	struct hdd_fips_context *context;

	hdd_enter();

	if (!response) {
		hdd_err("response is NULL");
		return;
	}

	request = hdd_request_get(cookie);
	if (!request) {
		hdd_debug("Obsolete request");
		return;
	}

	hdd_debug("pdev_id %u, status %u, data_len %u",
		  response->pdev_id,
		  response->error_status,
		  response->data_len);
	qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
			   response->data, response->data_len);

	context = hdd_request_priv(request);
	if (response->error_status) {
		context->status = -ETIMEDOUT;
	} else {
		context->status = hdd_fips_event_dup(&context->response,
						     response);
	}

	hdd_request_complete(request);
	hdd_request_put(request);
	hdd_exit();
}

static void hdd_fips_context_dealloc(void *priv)
{
	struct hdd_fips_context *context = priv;

	qdf_mem_free(context->response.data);
}


static int hdd_fips_validate_request(struct iw_fips_test_request *user_request,
				     uint32_t request_len)
{
	uint32_t expected_data_len;

	if (request_len < sizeof(*user_request)) {
		hdd_debug("Request len %u is too small", request_len);
		return -EINVAL;
	}

	if ((user_request->key_len != FIPS_KEY_LENGTH_128) &&
	    (user_request->key_len != FIPS_KEY_LENGTH_256)) {
		hdd_debug("Invalid key len %u", user_request->key_len);
		return -EINVAL;
	}

	expected_data_len = request_len - sizeof(*user_request);
	if (expected_data_len != user_request->data_len) {
		hdd_debug("Unexpected data_len %u for request_len %u",
			  user_request->data_len, request_len);
		return -EINVAL;
	}

	if ((user_request->mode != FIPS_ENGINE_AES_CTR) &&
	    (user_request->mode != FIPS_ENGINE_AES_MIC)) {
		hdd_debug("Invalid mode %u", user_request->mode);
		return -EINVAL;
	}

	if ((user_request->operation != FIPS_ENCRYPT_CMD) &&
	    (user_request->operation != FIPS_DECRYPT_CMD)) {
		hdd_debug("Invalid operation %u", user_request->operation);
		return -EINVAL;
	}

	return 0;
}

static int __hdd_fips_test(struct net_device *dev,
			  struct iw_request_info *info,
			  union iwreq_data *wrqu, char *extra)
{
	struct hdd_adapter *adapter;
	struct hdd_context *hdd_ctx;
	struct iw_fips_test_request *user_request;
	struct iw_fips_test_response *user_response;
	uint32_t request_len;
	int ret;
	QDF_STATUS qdf_status;
	void *cookie;
	struct hdd_request *request;
	struct hdd_fips_context *context;
	struct fips_params *fips_request;
	struct wmi_host_fips_event_param *fips_response;
	static const struct hdd_request_params params = {
		.priv_size = sizeof(*context),
		.timeout_ms = WLAN_WAIT_TIME_FIPS,
		.dealloc = hdd_fips_context_dealloc,
	};

	hdd_enter_dev(dev);

	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
	ret = wlan_hdd_validate_context(hdd_ctx);
	if (ret)
		return ret;

	user_request = (struct iw_fips_test_request *)extra;
	request_len = wrqu->data.length;
	ret = hdd_fips_validate_request(user_request, request_len);
	if (ret)
		return ret;

	request = hdd_request_alloc(&params);
	if (!request) {
		hdd_err("Request allocation failure");
		return -ENOMEM;
	}
	context = hdd_request_priv(request);
	fips_request = &context->request;
	fips_request->key = &user_request->key[0];
	fips_request->key_len = user_request->key_len;
	fips_request->data = &user_request->data[0];
	fips_request->data_len = user_request->data_len;
	fips_request->mode = user_request->mode;
	fips_request->op = user_request->operation;
	fips_request->pdev_id = WMI_PDEV_ID_1ST;

	cookie = hdd_request_cookie(request);
	qdf_status = sme_fips_request(hdd_ctx->hHal, &context->request,
				      hdd_fips_cb, cookie);

	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
		hdd_err("Unable to post fips message");
		ret = -EINVAL;
		goto cleanup;
	}

	ret = hdd_request_wait_for_response(request);
	if (ret) {
		hdd_err("Target response timed out");
		goto cleanup;
	}

	ret = context->status;
	if (ret) {
		hdd_err("Target response processing failed");
		goto cleanup;
	}

	fips_response = &context->response;
	if (fips_response->data_len != fips_request->data_len) {
		hdd_err("Data length mismatch, got %u, expected %u",
			fips_response->data_len, fips_request->data_len);
		ret = -EINVAL;
		goto cleanup;
	}
	user_response = (struct iw_fips_test_response *)extra;
	user_response->status = context->status;
	if (user_response->status) {
		user_response->data_len = 0;
	} else {
		user_response->data_len = fips_response->data_len;
		qdf_mem_copy(user_response->data, fips_response->data,
			     fips_response->data_len);
	}

	/*
	 * By default wireless extensions private ioctls have either
	 * SET semantics (even numbered ioctls) or GET semantics (odd
	 * numbered ioctls). This is an even numbered ioctl so the SET
	 * semantics apply. This means the core kernel ioctl code took
	 * care of copying the request parameters from userspace to
	 * kernel space. However this ioctl also needs to return the
	 * response. Since the core kernel ioctl code doesn't support
	 * SET ioctls returning anything other than status, we have to
	 * explicitly copy the result to userspace.
	 */
	wrqu->data.length = sizeof(*user_response) + user_response->data_len;
	if (copy_to_user(wrqu->data.pointer, user_response, wrqu->data.length))
		ret = -EFAULT;

cleanup:
	hdd_request_put(request);

	hdd_exit();
	return ret;
}

int hdd_fips_test(struct net_device *dev,
		  struct iw_request_info *info,
		  union iwreq_data *wrqu, char *extra)
{
	int ret;

	cds_ssr_protect(__func__);
	ret = __hdd_fips_test(dev, info, wrqu, extra);
	cds_ssr_unprotect(__func__);

	return ret;
}
