/*
 * Copyright (c) 2017 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;

	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);
	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,
	};

	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);

	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;
}
