/*!
 * \file    spay_msk_tl.c
 * \brief   Process service key moves implementation
 * \author  Balakrishna Venkataraman
 * \date    09/15/2015
 *
 * <hr>
 * \section LICENSE
 * Copyright Samsung Research America 2015
 * <hr>
 */

#include "TZ_Vendor_tl.h"
#include "spay_msk_tl.h"
#include "TZ_platform_defs.h"
#include "ta_log.h"

uint32_t process_spay_msk(
	tz_spay_msk_msg_cmd_t * sendmsg,
	tz_spay_msk_msg_resp_t * respmsg
)
{
	uint32_t ret = TZ_SPAY_MSK_UNKNOWN_ERROR;
	uint32_t tl_ret = TZ_API_ERROR;
	uint8_t decap_blob[TZ_SPAY_MAX_SK_LEN] = {0};
	uint32_t decap_blob_len = sizeof(decap_blob);
	char appname[32] = {0};
	uint8_t encap_blob[TZ_SPAY_MAX_SK_LEN] = {0};
	uint32_t encap_blob_len;
	uint8_t so_source[128] = { 0 };
	uint32_t so_source_len = sizeof(so_source);

	encap_blob_len = sendmsg->skmm_encap_msg.len;

	if (0 == encap_blob_len || encap_blob_len > TZ_SPAY_MAX_SK_LEN) {
		TTY_LOG("TZ_SPAY_MSK: Invalid input from normal world");
		ret = TZ_SPAY_MSK_PARAM_ERROR;
		STORE_TA_ERROR("%s - %s", __func__, TZ_SPAY_MSK_PARAM_ERROR_STR);
		goto exit;
	}

	memcpy(encap_blob, sendmsg->skmm_encap_msg.blob, encap_blob_len);

	tl_ret = TZ_unwrap_session_data((uint8_t *) appname, sizeof(appname),
					encap_blob, encap_blob_len,
					decap_blob, &decap_blob_len);

	if (tl_ret != TZ_API_OK) {
		TTY_LOG("TZ_SPAY_MSK: Decap failed");
		ret = TZ_SPAY_MSK_DECAP_ERROR;
		STORE_TA_ERROR("%s - %s", __func__, TZ_SPAY_MSK_DECAP_ERROR_STR);
		goto exit;
	}

	tl_ret = TZ_get_so_source(encap_blob, encap_blob_len, so_source, &so_source_len);
	if (tl_ret != TZ_API_OK) {
		TTY_LOG("TZ_SPAY_MSK: TZ_get_so_source failed");
		tl_ret = TZ_SPAY_MSK_DECAP_ERROR;
		STORE_TA_ERROR("%s - %s", __func__, TZ_SPAY_MSK_DECAP_ERROR_STR);
		goto exit;
	}

	if (memcmp(so_source, AUTH_SO_SRC_CNCC_UUID, AUTH_SO_SRC_UUID_LEN(AUTH_SO_SRC_CNCC_UUID)) &&
            memcmp(so_source, AUTH_SO_SRC_SKM_UUID, AUTH_SO_SRC_UUID_LEN(AUTH_SO_SRC_SKM_UUID))
#ifdef CONFIG_KNOX_GEARPAY		
            && memcmp(so_source, AUTH_SO_SRC_PIN_MANAGER_UUID, AUTH_SO_SRC_UUID_LEN(AUTH_SO_SRC_PIN_MANAGER_UUID))
            && memcmp(so_source, AUTH_SO_SRC_WSM_UUID, AUTH_SO_SRC_UUID_LEN(AUTH_SO_SRC_WSM_UUID))
#endif
	) {
		TTY_LOG("TZ_SPAY_MSK: Unexpected SO source(%d): %s", so_source_len, so_source);
		tl_ret = TZ_SPAY_MSK_DECAP_ERROR;
		STORE_TA_ERROR("%s - %s", __func__, TZ_SPAY_MSK_DECAP_ERROR_STR);
		goto exit;
	}

	/* Re-using encap_blob buffer here */
	tl_ret = TZ_wrap_data(decap_blob, decap_blob_len,
					encap_blob, &encap_blob_len);

	if (tl_ret != TZ_API_OK) {
		TTY_LOG("TZ_SPAY_MSK: Decap failed");
		ret = TZ_SPAY_MSK_WRAP_ERROR;
		STORE_TA_ERROR("%s - %s", __func__, TZ_SPAY_MSK_WRAP_ERROR_STR);
		goto exit;
	}

	if (encap_blob_len > sizeof(respmsg->wrapped_msg.blob)) {
		TTY_LOG("TZ_SPAY_MSK: Insufficient respmsg buffer");
		ret = TZ_SPAY_MSK_PARAM_ERROR;
		STORE_TA_ERROR("%s - %s", __func__, TZ_SPAY_MSK_WRAP_ERROR_STR);
		goto exit;
	}

	memcpy(respmsg->wrapped_msg.blob, encap_blob, encap_blob_len);
	respmsg->wrapped_msg.len = encap_blob_len;
	ret = TZ_SPAY_MSK_NO_ERROR;

	TTY_LOG("TZ_SPAY_MSK: Everything succeeded");
exit:
	respmsg->return_code = ret;
	return ret;
}

