#include "em_common.h"

int em_context_make_request(uint8_t *req_buf, em_context *ctx)
{
	int ret, i = 0;

	em_req_payload *req = (em_req_payload *)req_buf;
	EM_CHECK_NULL(__func__, EM_ERR_EM_CONTEXT_MAKE_REQUEST, req, ctx);

	ret = em_check_provision();
	if (ret != EM_SUCCESS) {
		if (ret != EM_ERR_EM_CHECK_PROVISION_NOT_PROVISION) {
			LOGE("Rpmb can't be used(0x%08x)\n", ret);
			goto out;
		}
		LOGI("RPMB isn't provisioned\n");
	} else {
		ctx->is_provision = 1;
	}

	if (req->version != EM_PAYLOAD_VERSION) {
		LOGE("payload version isn't matched(%u/%u)\n", req->version, EM_PAYLOAD_VERSION);
		ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_VERSION;
		goto out;
	}

	memcpy(ctx, &req->primary, sizeof(em_req_payload_primary));

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_TOKEN) {
		memcpy(ctx->token, req->secondary.token, EM_LEN_TOKEN);
	}

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_MESSAGE) {
		ctx->len_message = req->secondary.len_message;
		if (ctx->len_message > EM_LEN_MESSAGE || ctx->len_message <= 0) {
			LOGE("please check message length(%u)\n", ctx->len_message);
			ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_LEN_MESSAGE;
			goto out;
		}
		memcpy(ctx->message, req->secondary.message, ctx->len_message);
	}

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_RECOVERY_MESSAGE) {
		ctx->len_message = req->secondary.len_message;
		if (ctx->len_message > EM_LEN_RECOVERY_DATA || ctx->len_message <= 0) {
			LOGE("please check recovery message length(%u)\n", ctx->len_message);
			ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_LEN_RECOVERY_MESSAGE;
			goto out;
		}
		memcpy(ctx->recovery_data, req->secondary.message, ctx->len_message);
	}

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_CERT) {
		ctx->len_cert = req->secondary.len_cert;
		if (ctx->len_cert > EM_LEN_CERTIFICATE || ctx->len_cert <= 0) {
			LOGE("please check certificate length(%u)\n", ctx->len_cert);
			ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_LEN_CERT;
			goto out;
		}
		memcpy(ctx->cert, req->secondary.cert, ctx->len_cert);
	}

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_ESS_PREFIXBODY) {
		ctx->len_ess_prefixbody = req->secondary.len_ess_prefixbody;
		if (ctx->len_ess_prefixbody > EM_LEN_ESS_PREFIX_BODY || ctx->len_ess_prefixbody <= 0) {
			LOGE("please check ess prefixbody length(%u)\n", ctx->len_ess_prefixbody);
			ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_LEN_ESS_PREFIXBODY;
			goto out;
		}
		memcpy(ctx->ess_prefixbody, req->secondary.ess_prefixbody, ctx->len_ess_prefixbody);
	}

	if (req->primary.flags[0] & EM_FLAGS_0_EXIST_KEEPING_ITEM)
		memcpy(&ctx->keep, &req->primary.keep, sizeof(em_keeping_item));

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_ESI)
		memcpy(ctx->esi, req->secondary.esi, EM_LEN_ESI);

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_ESS_IV_B64)
		memcpy(ctx->ess_iv_b64, req->secondary.ess_iv_b64, EM_LEN_ESS_IV_B64);

#ifdef EMBS
	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_CORE_V20)
		memcpy(ctx->core, req->secondary.core, EM_LEN_CORE_V20);
#endif

	for (i = 0; i < EM_LEN_PAYLOAD_FLAGS; i++)
		ctx->flags[i] = (ctx->flags[i] | req->primary.flags[i]) | req->secondary.flags[i];

	ret = EM_SUCCESS;
out:
	return ret;
}

int em_context_make_response(uint8_t *rsp_buf, em_context *ctx, uint32_t result)
{
	int ret;

	em_rsp_payload *rsp = (em_rsp_payload *)rsp_buf;
	EM_CHECK_NULL(__func__, EM_ERR_EM_CONTEXT_MAKE_RESPONSE, rsp, ctx);

	LOGE("TEST - 0x%08x", result);
	rsp->ret = result;
	rsp->version = EM_PAYLOAD_VERSION;

	if (ctx->cmd == EM_CMD_GET_TUC)
		rsp->ret = ctx->ret_temp;

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_TOKEN) {
		rsp->secondary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_TOKEN;
		memcpy(rsp->secondary.token, ctx->token, EM_LEN_TOKEN);
	}

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_MESSAGE) {
		rsp->secondary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_MESSAGE;
		rsp->secondary.len_message = ctx->len_message;
		if (rsp->secondary.len_message > EM_LEN_MESSAGE || rsp->secondary.len_message <= 0) {
			LOGE("%s : please check message length(%u)\n", __func__, ctx->len_message);
			ret = EM_ERR_EM_CONTEXT_MAKE_RESPONSE_LEN_MESSAGE;
			goto out;
		}
		memcpy(rsp->secondary.message, ctx->message, ctx->len_message);
	}

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_ESI) {
		rsp->secondary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_ESI;
		memcpy(rsp->secondary.esi, ctx->esi, EM_LEN_ESI);
	}

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_KEEPING_ITEM) {
		rsp->primary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_KEEPING_ITEM;
		memcpy(&rsp->primary.keep, &ctx->keep, sizeof(em_keeping_item));
	}

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_MODES_BIT) {
		rsp->primary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_MODES_BIT;
		memcpy(rsp->primary.mode_bits, ctx->mode_bits, EM_LEN_GET_MODES_BIT_BUFFER*sizeof(uint64_t));
	}

	ret = EM_SUCCESS;
out:
	return ret;
}
