/*!
 * \file    init_tl.c
 * \brief   process_init implementation
 * \author  Shyam Prasad
 * \date    11/15/2013
 *
 * <hr>
 * \section LICENSE
 * Copyright Samsung Electronics, Co. Ltd. B2B TIMA team. 2013 04
 * <hr>
 */

#include "TZ_Vendor_tl.h"
#include "spay_init_tl.h"

#ifdef ESE_SPI
#include "sec_EseStatus.h"
#include "sec_apdu.h"
#endif

#ifdef USE_BF
#include "tee_internal_api.h"
#endif

#ifdef ICCC_ENABLED
#if !defined(USE_QSEE)
#include "icccOperations.h"
#else
#include "tz_iccc_comdef.h"
#endif
#endif

#define TIMA_SIGN_LEN 256
#define RSAEXPONENT	3
#define RSA_NUMBYTES  256
#define RSANUMWORDS (RSA_NUMBYTES/sizeof(uint32_t))
#define TIMA_MAGIC "TIMA3.0"
#define TIMA_MAGIC_LEN strlen(TIMA_MAGIC)
#define TIMA_MAGIC_MAX_LEN 16

#ifdef USE_QSEE // Trusted boot changes for the MSM8939
#if defined(MSM8x26)
#define KNOX_LICENSE_SIZE 4
#else
#define KNOX_LICENSE_SIZE 2
#endif
#else
#define KNOX_LICENSE_SIZE 4
#endif

#define QSEE_HASH_IDX_SHA1 2
#define QSEE_HASH_IDX_SHA256 3

#if defined(USE_QSEE) && !defined(SDM845) && !defined(SDM660) && !defined(SDM450) && !defined(SDM710) && !defined(SM8150) && !defined(SM6150) && !defined(SM7150) && !defined(SM8250) && !defined(SM7250) && !defined(SM8350) && !defined(SM7225) && !defined(SM7325) && !defined(SM7125) && !defined(SM8450)// need to check
uint32_t golden_msr_addr = TIMA_GOLDEN_MEASUREMENT_ADDR;
#endif

#include "ta_log.h"

/* For TIMA secure address */
uint32_t tima_sec_mem_addr;

//samsung_modulus name is changed due to conflict with ICCC module.
uint32_t spay_samsung_modulus[RSANUMWORDS] = {
	1891720543U, 2898899684U, 2253445094U, 1936295747U, 4196704067U,
	3864872433U, 1472239824U, 3164687093U, 338896034U,  904012785U,
	2451936152U, 827648720U,  365656865U,  637536106U,  1388833157U,
	2732715088U, 1940841272U, 1539208106U, 1863720856U, 2896482916U,
	3409408324U, 4045575973U, 3038854981U, 2023178681U, 712543360U,
	57729334U,   2201215102U, 2563951780U, 3027128989U, 2774880565U,
	436072510U,  4203237951U, 176406685U,  2260374784U, 2948096985U,
	2744760779U, 3277277305U, 818397983U,  3771428155U, 2861543228U,
	2799946394U, 1811432048U, 2474392044U, 3149618135U, 2995766846U,
	4184031422U, 81011589U,   3844396389U, 727248317U,  2603428677U,
	4223592821U, 692124161U,  17089674U,   3445043668U, 79863921U,
	3175980450U, 3248655378U, 3631812347U, 3034309458U, 2462841710U,
	405598924U,  185102806U,  860543909U,  3072136338U
};

#ifdef NOCHECK_TRUSTED_BOOT
uint32_t process_spay_init(
	tz_spay_init_msg_cmd_t * sendmsg,
	tz_spay_init_msg_resp_t * respmsg
)
{
	uint32_t ret;

    ret = TZ_SPAY_INIT_OK;
    TTY_LOG("TZ_SPAY_INIT: process_spay_init will be skipped.");
#ifdef ESE_SPI
	if (spiOpenFlag) {	
		spiRet = spiClose();
		if (0 != spiRet) {
			STORE_TA_ERROR("TZ_SPAY_INIT: spiClose failed: spiRet = 0x%x = %d", spiRet, spiRet);
		} else {
			TTY_LOG("TZ_SPAY_INIT: spiClose succeeded");
		}
	}
#endif

    return ret;
}

uint32_t verify_trusted_boot()
{
    TTY_LOG("TZ_SPAY_INIT: verify_trusted_boot will be skipped.");
    return TZ_SPAY_INIT_OK;
}

#else

#if !defined(ICCC_ENABLED)
static uint32_t switch_endianness(
	uint32_t val
)
{
	uint32_t result;

	result = ((val & 0xff) << 24) |
	    (((val >> 8) & 0xff) << 16) |
	    (((val >> 16) & 0xff) << 8) | ((val >> 24) & 0xff);
	return result;
}

static  uint32_t tima_verify_signature(
	uint8_t * msg,
	uint32_t len,
	uint8_t * sig_ptr,
	uint32_t type
)
{
	uint32_t final_modulus[RSANUMWORDS];
	uint32_t i, j;
	uint8_t exponent = RSAEXPONENT;
	bool isValidSig = false;
	uint32_t ret = TZ_SPAY_INIT_ERROR;

	/* Prepare the modulus - provided modulus is little endian
	 * Needs to change according to mobicore expectations
	 */
	for (i = 0, j = (RSANUMWORDS - 1); i < RSANUMWORDS; i++, j--)
		final_modulus[i] = switch_endianness(spay_samsung_modulus[j]);

	if (type == 0xEA) {
#if defined(USE_QSEE) || defined(USE_BF)
		ret = TZ_verify_CKM_SHA256_RSA_PKCS(((uint8_t *) & final_modulus[0]), RSA_NUMBYTES,
									   ((uint8_t *) & exponent), sizeof(uint8_t),
									   msg, len, sig_ptr, RSA_NUMBYTES, &isValidSig);
#else
		ret = TZ_verify_CKM_SHA256_RSA_PKCS_NO_ASN1(((uint8_t *) & final_modulus[0]), RSA_NUMBYTES,
									   ((uint8_t *) & exponent), sizeof(uint8_t),
									   msg, len, sig_ptr, RSA_NUMBYTES, &isValidSig);
#endif
	} else {
		ret = TZ_verify_CKM_SHA1_RSA_PKCS(((uint8_t *) & final_modulus[0]), RSA_NUMBYTES,
									   ((uint8_t *) & exponent), sizeof(uint8_t),
									   msg, len, sig_ptr, RSA_NUMBYTES, &isValidSig);
	}

	if (ret != TZ_SPAY_INIT_OK){
		ret = TZ_SPAY_INIT_ERROR;
		STORE_TA_ERROR("%s: Error verifying signature on time_measurement_info", __FUNCTION__);
		goto exit;
	}

#if defined(USE_QSEE)
	if (!isValidSig) {
		TTY_LOG("%s: Signature verification failed partially - verifying special padding", __FUNCTION__);
		ret = TZ_verify_special_qsee_padding((uint8_t *) &spay_samsung_modulus[0],
				RSA_NUMBYTES, &exponent,
				sizeof(uint8_t), msg, len,
				sig_ptr, RSA_NUMBYTES,
				&isValidSig, (type == 0xEA) ? QSEE_HASH_IDX_SHA256 : QSEE_HASH_IDX_SHA1);

		if (ret != TZ_API_OK || !isValidSig){
			ret = TZ_API_ERROR;
			STORE_TA_ERROR("%s: Error verifying signature on tima_measurement_info", __FUNCTION__);
		}
	}
#endif

exit:
	return ret;
}

#if defined(USE_QSEE)
uint32_t read_golden_measurement(
	uint8_t * msr,
	uint16_t * msr_size
)
{
	uint32_t ret;
	uint16_t golden_msr_size = 0;
	uint8_t tima_magic_golden_msr[TZ_SPAY_TIMA_MSR_MAX_SIZE] = { 0 };

	TTY_LOG("TZ_SPAY_INIT: Reading golden measurement");
#if defined(SDM845) || defined(SDM660) || defined(SDM450) || defined(SDM710) || defined(SM8150) || defined(SM6150) || defined(SM7150) || defined(SM8250) || defined(SM7250) || defined(SM8350) || defined(SM7225) || defined(SM7125) || defined(SM7325) || defined(SM8450)
	TTY_LOG("TZ_SPAY_INIT: TZ_oem_read");
	ret = TZ_oem_read(TIMA_GOLDEN_MEASUREMENT_OFFSET, (void *)tima_magic_golden_msr, TIMA_MSR_MAX_SIZE);
	if(ret) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - Failed to read golden msr, ret : %d", __FUNCTION__, ret);
		goto exit;
	}
#else
	ret = TZ_phys_read((void *)golden_msr_addr, TZ_SPAY_TIMA_MSR_MAX_SIZE, tima_magic_golden_msr);
	if (ret != TZ_API_OK) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - p-address -> v-address mapping error!", __FUNCTION__);
		goto exit;
	}
#endif
	if ((ret =
	     memcmp(tima_magic_golden_msr, TIMA_MAGIC, TIMA_MAGIC_LEN)) != 0) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - Secure memory is not initialized", __FUNCTION__);
		ret = 3;
		goto exit;
	}
	
	//read the measurement size from the secure memory which follows the TIMA_MAGIC
#if defined(MSM8x26)	
	memcpy(&golden_msr_size, (tima_magic_golden_msr + TIMA_MAGIC_MAX_LEN + KNOX_LICENSE_SIZE), sizeof(golden_msr_size));
#else
	memcpy(&golden_msr_size, (tima_magic_golden_msr + TIMA_MAGIC_LEN + KNOX_LICENSE_SIZE),
	       sizeof(golden_msr_size));
#endif
	TTY_LOG("TZ_SPAY_INIT: Measurement size is : %d", golden_msr_size);
	
	//Check if the measurement size is corrupt
	if (golden_msr_size > (TZ_SPAY_TIMA_MSR_MAX_SIZE - TIMA_MAGIC_LEN - KNOX_LICENSE_SIZE - sizeof(golden_msr_size))) {
		STORE_TA_ERROR
		    ("TZ_SPAY_INIT: %s - Secure memory is not initialized, wrong measurement size", __FUNCTION__);
		ret = 3;
		goto exit;
	}
	
	//copy the measurement size to the output parameter
	*msr_size = golden_msr_size;
	
	// Then copy the measurements to the output buffer
#if defined(MSM8x26)
	memcpy(msr,
	       (tima_magic_golden_msr + TIMA_MAGIC_MAX_LEN + KNOX_LICENSE_SIZE +
		sizeof(golden_msr_size)), golden_msr_size);
#else
	memcpy(msr,
	       (tima_magic_golden_msr + TIMA_MAGIC_LEN + KNOX_LICENSE_SIZE +
		sizeof(golden_msr_size)), golden_msr_size);
#endif

exit:
	return ret;
}

uint32_t init_golden_measurement(
	uint8_t * msr,
	uint16_t msr_size
)
{
	uint32_t ret;
	uint8_t tima_magic_golden_msr[TZ_SPAY_TIMA_MSR_MAX_SIZE] = { 0 };
	
	TTY_LOG("TZ_SPAY_INIT: init golden measurement msr_len = %d", msr_size);
	if(sizeof(tima_magic_golden_msr) < TIMA_MAGIC_LEN + KNOX_LICENSE_SIZE + sizeof(msr_size) + msr_size) {
		STORE_TA_ERROR("TZ_SPAY_INIT: - %s - buffer overflow (%d,%d)",
				__FUNCTION__,
				TIMA_MAGIC_LEN + KNOX_LICENSE_SIZE + sizeof(msr_size) + msr_size, msr_size);
		return TZ_SPAY_INIT_ERROR;
	}

	// write TIMA_MAGIC at the beginning of the measurement area
	memcpy(tima_magic_golden_msr, TIMA_MAGIC, TIMA_MAGIC_LEN);

	// write the size of the measurements following TIMA_MAGIC
	memcpy((tima_magic_golden_msr + TIMA_MAGIC_LEN + KNOX_LICENSE_SIZE), &msr_size,
	       sizeof(msr_size));

	// finally, write the measurements to the secure mem
	memcpy((tima_magic_golden_msr + TIMA_MAGIC_LEN + KNOX_LICENSE_SIZE + sizeof(msr_size)), msr,
	       msr_size);
		   
	TTY_LOG("TZ_SPAY_INIT: Writing golden_msr to memory..");
#if defined(SDM845) || defined(SDM660) || defined(SDM450) || defined(SDM710) || defined(SM8150) || defined(SM6150) || defined(SM7150) || defined(SM8250) || defined(SM7250) || defined(SM8350) || defined(SM7225) || defined(SM7125) || defined(SM7325) || defined(SM8450)
	TTY_LOG("TZ_SPAY_INIT: TZ_oem_write");
	ret = TZ_oem_write(TIMA_GOLDEN_MEASUREMENT_OFFSET, tima_magic_golden_msr, TIMA_MSR_MAX_SIZE);
	if(ret) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - Failed to init golden msr, ret : %d", __FUNCTION__, ret);
	} else {
		TTY_LOG("TZ_SPAY_INIT:: successfully written to secure memory");
	}
#else
	ret = TZ_phys_write((void *)golden_msr_addr, sizeof(tima_magic_golden_msr), tima_magic_golden_msr);
	if (ret != TZ_API_OK) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - Failed to write golden_msr to memory!", __FUNCTION__);
	} else {
		TTY_LOG("TZ_SPAY_INIT:: successfully written to secure memory");
	}
#endif
	return ret;
}

#else // #if defined USE_QSEE
static uint32_t read_golden_measurement(
	uint8_t * msr,
	uint16_t * msr_size
)
{
	uint32_t ret;
	uint16_t golden_msr_size = 0;
	uint8_t tima_magic_golden_msr[TZ_SPAY_TIMA_MSR_MAX_SIZE / 2] = { 0 };

	do {
		uint32_t golden_msr_addr = 0;
		ret = TZ_get_trusted_boot_address(&golden_msr_addr, TIMA_GOLDEN_MSR);

		if( ret != TZ_API_OK || golden_msr_addr == 0) {
			ret = TZ_SPAY_INIT_ERROR;
			break;
		}

		DBG_LOG("TZ_SPAY_INIT: Reading golden measurement");
		ret = TZ_phys_read((void *)golden_msr_addr, TZ_SPAY_TIMA_MSR_MAX_SIZE / 2, tima_magic_golden_msr);
		if (ret != TZ_API_OK) {
			STORE_TA_ERROR("TZ_SPAY_INIT: %s - read_golden_measurement:  p-address -> v-address mapping error!", __FUNCTION__);
			break;
		}

		if ((ret =
		     memcmp(tima_magic_golden_msr, TIMA_MAGIC, TIMA_MAGIC_LEN)) != 0) {
			STORE_TA_ERROR("TZ_SPAY_INIT: %s - read_golden_measurement:  Secure memory is not initialized", __FUNCTION__);
			ret = 3;
			break;
		}

		//read the measurement size from the secure memory which follows the TIMA_MAGIC
		memcpy(&golden_msr_size, (tima_magic_golden_msr + TIMA_MAGIC_MAX_LEN + KNOX_LICENSE_SIZE), sizeof(golden_msr_size));
		DBG_LOG("TZ_SPAY_INIT: read_golden_measurement:  Measurement size at offset %d is : %d", TIMA_MAGIC_LEN, golden_msr_size);

		//Check if the measurement size is corrupt
		if (golden_msr_size == 0 || golden_msr_size > ((TZ_SPAY_TIMA_MSR_MAX_SIZE/2) - TIMA_MAGIC_MAX_LEN - KNOX_LICENSE_SIZE - sizeof(golden_msr_size))) {
			STORE_TA_ERROR
			    ("TZ_SPAY_INIT: %s - read_golden_measurement:  Secure memory is not initialized, wrong measurement size: %d", __FUNCTION__, golden_msr_size);
			ret = 3;
			break;
		}

		if (golden_msr_size > *msr_size) {
			STORE_TA_ERROR("TZ_SPAY_INIT: %s - insufficient buffer to write golden measurements-(%d,%d)", __FUNCTION__, *msr_size, golden_msr_size);
			ret = TZ_SPAY_INIT_ERROR;
			break;
		}
		//copy the measurement size to the output parameter
		*msr_size = golden_msr_size;
		// Then copy the measurements to the output buffer
		memcpy(msr, (tima_magic_golden_msr + TIMA_MAGIC_MAX_LEN + KNOX_LICENSE_SIZE + sizeof(golden_msr_size)), golden_msr_size);

	} while (false);

	return ret;
}

static uint32_t init_golden_measurement(
	uint8_t * msr,
	uint16_t msr_size
)
{
	uint32_t ret;
	uint8_t tima_magic_golden_msr[TZ_SPAY_TIMA_MSR_MAX_SIZE/2] = { 0 };
	uint32_t golden_msr_addr;

	DBG_LOG("TZ_SPAY_INIT: init_golden_measurement:  init golden measurement msr_len = %d", msr_size);
	if(sizeof(tima_magic_golden_msr) < TIMA_MAGIC_MAX_LEN + KNOX_LICENSE_SIZE + sizeof(msr_size) + msr_size) {
		STORE_TA_ERROR("TZ_SPAY_INIT: - %s - buffer overflow (%d,%d)",
				__FUNCTION__,
				TIMA_MAGIC_MAX_LEN + KNOX_LICENSE_SIZE + sizeof(msr_size) + msr_size, msr_size);
		return TZ_SPAY_INIT_ERROR;
	}
	// write TIMA_MAGIC at the beginning of the measurement area
	memcpy(tima_magic_golden_msr, TIMA_MAGIC, TIMA_MAGIC_LEN);

	// write the size of the measurements following TIMA_MAGIC
	memcpy((tima_magic_golden_msr + TIMA_MAGIC_MAX_LEN + KNOX_LICENSE_SIZE), &msr_size,
	       sizeof(msr_size));

	// finally, write the measurements to the secure mem
	memcpy((tima_magic_golden_msr + TIMA_MAGIC_MAX_LEN + KNOX_LICENSE_SIZE + sizeof(msr_size)), msr,
	       msr_size);

	ret = TZ_get_trusted_boot_address(&golden_msr_addr, TIMA_GOLDEN_MSR);
	if( ret != TZ_API_OK || golden_msr_addr == 0) {
		return TZ_SPAY_INIT_ERROR;
	}

	DBG_LOG("TZ_SPAY_INIT: init_golden_measurement:  golden_msr_addr : %x", golden_msr_addr);
	ret = TZ_phys_write((void *)golden_msr_addr, sizeof(tima_magic_golden_msr), tima_magic_golden_msr);
	if (ret != TZ_API_OK) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - init_golden_measurement:  p-address -> v-address mapping error!", __FUNCTION__);
	}

	DBG_LOG("TZ_SPAY_INIT: init_golden_measurement:  successfully written to secure memory");
	return ret;
}
#endif  // #if defined USE_QSEE

static uint32_t read_measurement(
	void *msg,
	uint32_t size,
	uint8_t * msr,
	uint16_t * msr_size
)
{
	uint32_t ret;
	unsigned char type = 0;
	uint8_t *signature = NULL;
	uint16_t out_size = 0;
	uint8_t msg_buf[TZ_SPAY_TIMA_MSR_MAX_SIZE + TIMA_SIGN_LEN + 1] = {0};
	uint32_t msg_size = size;

	if (msg_size <= TIMA_SIGN_LEN
	    || msg_size > TZ_SPAY_TIMA_MSR_MAX_SIZE + TIMA_SIGN_LEN + 1) {
		STORE_TA_ERROR
		    ("TZ_SPAY_INIT: %s - read_measurement: tima_measurement_info has the wrong size (%d)!",
		    __FUNCTION__,
		     msg_size);
		return TZ_SPAY_INIT_ERROR;
	}
	memcpy(msg_buf, msg, msg_size);

	/*check for knox build option */
	memcpy(&type, msg_buf, 1);
	if (type != 0xE9 && type != 0xEA) {
		TTY_LOG("TZ_SPAY_INIT: %s - read_measurement: tima only works with knox images!", __FUNCTION__);
		//return TZ_SPAY_INIT_ERROR;
	}

	signature = (uint8_t *) msg_buf + msg_size - TIMA_SIGN_LEN;
	ret = tima_verify_signature(msg_buf, msg_size - TIMA_SIGN_LEN, signature, type);
	if (ret != TZ_SPAY_INIT_OK) {
		STORE_TA_ERROR
		    ("TZ_SPAY_INIT: %s read_measurement: tima_measurement_info has the wrong signature!", __FUNCTION__);
		return TZ_SPAY_INIT_ERROR;
	}

	out_size = msg_size - TIMA_SIGN_LEN - 1;
	if (out_size > *msr_size) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s buffer overflow (%d,%d)", __FUNCTION__, out_size, *msr_size);
		return TZ_SPAY_INIT_ERROR;
	}

	*msr_size = out_size;
	memcpy(msr, ((uint8_t *) msg_buf) + 1,
			((*msr_size < TZ_SPAY_TIMA_MSR_MAX_SIZE) ?
			*msr_size : (TZ_SPAY_TIMA_MSR_MAX_SIZE - 1)));

	return TZ_SPAY_INIT_OK;
}

static uint32_t boot_measurement(
	uint8_t * msr,
	uint16_t msr_size
)
{
 	uint32_t ret;

#if defined(SDM845) || defined(SDM660) || defined(SDM450) || defined(SDM710) || defined(SM8150) || defined(SM6150) || defined(SM7150) || defined(SM8250) || defined(SM7250) || defined(SM8350) || defined(SM7225) || defined(SM7125) || defined(SM7325) || defined(SM8450)
	TTY_LOG("TZ_SPAY_INIT: TZ_oem_read");
	ret = TZ_oem_read(TIMA_BOOT_MEASUREMENT_OFFSET, msr, msr_size);
	if(ret) {
		TTY_LOG("TZ_SPAY_INIT: %s Failed to read boot msr, ret : %d, msr_size : %d", __FUNCTION__, ret, msr_size);
	}
#else
	uint32_t boot_msr_addr = 0;

	ret = TZ_get_trusted_boot_address(&boot_msr_addr, TIMA_BOOT_MSR);
	if(ret != TZ_API_OK || boot_msr_addr == 0) {
		return TZ_SPAY_INIT_ERROR;
	}

	ret = TZ_phys_read((void *)boot_msr_addr, msr_size, msr);
	if (ret != TZ_API_OK) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - boot_measurement: p-address -> v-address mapping error!", __FUNCTION__);
	}
#endif
	return ret;
}
#endif

uint32_t process_spay_init(
	tz_spay_init_msg_cmd_t * sendmsg,
	tz_spay_init_msg_resp_t * respmsg
)
{
	uint32_t ret = TZ_SPAY_INIT_ERROR;

#if defined(BUILD_CHANGELIST) && defined(USE_QSEE)
    TTY_LOG("TZ_SPAY_INIT(%s) %s", TRUSTED_APP_NAME, BUILD_CHANGELIST);
#elif defined(BUILD_CHANGELIST) && defined(USE_BF)
    TTY_LOG("TZ_SPAY_INIT(%s) %s", TA_NAME, BUILD_CHANGELIST);
#endif

#ifdef ESE_SPI
	int spiRet = 0;
	int spiOpenFlag = 0;

	spiRet = spiOpen();
	if (0 != spiRet) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - spiOpen failed: spiRet = 0x%x = %d", __FUNCTION__, spiRet, spiRet);
		ret = spiRet;
		goto exit;
	} else {
		TTY_LOG("TZ_SPAY_INIT: %s - spiOpen succeeded", __FUNCTION__);
		spiOpenFlag = 1;
	}
#endif

#ifdef ICCC_ENABLED
	//Device integrity check using ICCC

//  uint32_t iccc_flag;
    uint8_t resp_msg_buf[4096];
    uint32_t resp_msg_len;
    uint32_t result_code;
    uint32_t type;
    int value;

    type = ICCC_STATUS_COMP_TYPE_SOFT_INTEGRITY;

    value = Iccc_DeviceStatus_TA(type, resp_msg_buf, 4096, &resp_msg_len, &result_code);

    if(ICCC_SUCCESS != value) {
        TTY_LOG("TZ_SPAY_INIT : iccc_operation is failed.");
        ret = TZ_SPAY_INIT_ICCC_OPERATION_FAILED;
        goto exit;
    } else {
        if(0 != result_code) {
            TTY_LOG("TZ_SPAY_INIT : integrity check is failed. - (%x)", result_code);
            ret = TZ_SPAY_INIT_INTEGRITY_CHECK_FAILED;
            goto exit;
        }

    }
    TTY_LOG("TZ_SPAY_INIT : integrity check is succeed.");

#else
	uint8_t boot_msrs[TZ_SPAY_TIMA_MSR_MAX_SIZE];
	uint8_t golden_msrs[TZ_SPAY_TIMA_MSR_MAX_SIZE];
	uint16_t msr_size;
    msr_size = sizeof(golden_msrs);
	bool secure_boot_enable;

	if (TZ_is_tamper_fuse_bit_set()) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - Initialize failed - tamper fuse set", __FUNCTION__);
		ret = TZ_SPAY_INIT_ERROR_TAMPER_FUSE_FAIL;
		goto exit;
	}


	TTY_LOG("TZ_SPAY_INIT: tamper_fuse_good - process_init, msr_size: %d", sendmsg->measurement.len);

	if (0 == sendmsg->measurement.len) {
		if (read_golden_measurement(golden_msrs, &msr_size)) {
			STORE_TA_ERROR("TZ_SPAY_INIT: %s - Uninitialized secure memory", __FUNCTION__);
			ret = TZ_SPAY_INIT_UNINITIALIZED_SECURE_MEM;
			goto exit;
		}
	} else {
		if (read_measurement((void *)sendmsg->measurement.blob,
				     sendmsg->measurement.len, golden_msrs,
				     &msr_size)) {
			STORE_TA_ERROR
			    ("TZ_SPAY_INIT: %s - Initialize failed - Read measurements failed", __FUNCTION__);
			ret = TZ_SPAY_INIT_MSR_MODIFIED;
			goto exit;
		}

		/* after verifying the golden measurements, initialize the
		   measurements in the secure memory */

		if (init_golden_measurement(golden_msrs, msr_size)) {
			STORE_TA_ERROR
			    ("TZ_SPAY_INIT: %s - Failed to initialize golden measurements", __FUNCTION__);
			ret = TZ_SPAY_INIT_ERROR;
			goto exit;
		}
	}

	DBG_LOG("TZ_SPAY_INIT: Read boot time measurement");

	if(msr_size > sizeof(boot_msrs) || msr_size > sizeof(golden_msrs)) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - Buffer overflow - %d", __FUNCTION__, msr_size);
		ret = TZ_SPAY_INIT_ERROR;
		goto exit;
	}
	if (boot_measurement(boot_msrs, msr_size)) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - Failed to read the boot-time measurements", __FUNCTION__);
		ret = TZ_SPAY_INIT_ERROR;
		goto exit;
	}

	DBG_LOG("TZ_SPAY_INIT: compare measurements from boot and golden_msrs");

	/* For the skip of measurement check when secure boot has not been enabled yet */
	secure_boot_enable = TZ_is_secure_boot_enable();
	if (secure_boot_enable == false) {
		TTY_LOG("TZ_SPAY_INIT: secure boot has not been enabled yet, skip measurement check!!!");
	} else {
		if (memcmp(boot_msrs, golden_msrs, msr_size)) {
			STORE_TA_ERROR
			    ("TZ_SPAY_INIT: %s - Initialize failed - Boot-time measurements mismatch", __FUNCTION__);

#ifndef ENABLE_DEMO
			DBG_LOG("TZ_SPAY_INIT: Golden msrs from secure memory: ");
			DBG_DUMP(golden_msrs, msr_size);

			DBG_LOG("TZ_SPAY_INIT: Boot msrs from secure memory: ");
			DBG_DUMP(boot_msrs, msr_size);
#endif
			ret = TZ_SPAY_INIT_MSR_MISMATCH;
			goto exit;
		}
	}
	TTY_LOG("TZ_SPAY_INIT: Measurements match - Initialization complete");
#endif

    ret = TZ_SPAY_INIT_OK;

exit:

#ifdef ESE_SPI
	if (spiOpenFlag) {	
		spiRet = spiClose();
		if (0 != spiRet) {
			STORE_TA_ERROR("TZ_SPAY_INIT: spiClose failed: spiRet = 0x%x = %d", spiRet, spiRet);
		} else {
			TTY_LOG("TZ_SPAY_INIT: spiClose succeeded");
		}
	}
#endif

	respmsg->return_code = ret;
	return ret;
}

uint32_t verify_trusted_boot()
{

#if ICCC_ENABLED
	//Device integrity check using ICCC

//  uint32_t iccc_flag;
    uint8_t resp_msg_buf[4096];
    uint32_t resp_msg_len;
    uint32_t result_code;
    uint32_t type = ICCC_STATUS_COMP_TYPE_SOFT_INTEGRITY;

    int value = Iccc_DeviceStatus_TA(type, resp_msg_buf, 4096, &resp_msg_len, &result_code);

    
    if(ICCC_SUCCESS != value) {
        TTY_LOG("TZ_SPAY_INIT :: iccc_operation is failed.");
        return TZ_SPAY_INIT_ICCC_OPERATION_FAILED;
    } else {
        if(0 != result_code) {
            TTY_LOG("TZ_SPAY_INIT :: integrity check is failed. -- (%x)", result_code);
            return TZ_SPAY_INIT_INTEGRITY_CHECK_FAILED;
        }

    }
    TTY_LOG("TZ_SPAY_INIT :: integrity check is succeed.");
    
#else
	int ret;
	uint8_t boot_msr[TZ_SPAY_TIMA_MSR_MAX_SIZE];
	uint8_t golden_msrs[TZ_SPAY_TIMA_MSR_MAX_SIZE];
	uint16_t msr_size = sizeof(golden_msrs);
	bool secure_boot_enable;

	/*check if tamper fuse bit is already set */
	if (TZ_is_tamper_fuse_bit_set()) {
		STORE_TA_ERROR
		    ("TZ_SPAY_INIT: %s - verify_trusted_boot: in wrap key Initialize failed - tamper fuse set", __FUNCTION__);
		return TZ_SPAY_INIT_ERROR_TAMPER_FUSE_FAIL;
	}

	ret = read_golden_measurement(golden_msrs, &msr_size);
	if (ret != TZ_SPAY_INIT_OK) {
		STORE_TA_ERROR("TZ_SPAY_INIT: %s - Uninitialized secure memory", __FUNCTION__);
		return TZ_SPAY_INIT_ERROR;
	}
	TTY_LOG
	    ("TZ_SPAY_INIT: verify_trusted_boot: after read_golden_measurement");

	/* read boot msr and check if it matches good msr */
	ret = boot_measurement(boot_msr, msr_size);
	if (ret != TZ_SPAY_INIT_OK) {
		return TZ_SPAY_INIT_ERROR;
	}
	TTY_LOG
	    ("TZ_SPAY_INIT: verify_trusted_boot: after boot_measurement");

	/* For the skip of measurement check when secure boot has not been enabled yet */
	secure_boot_enable = TZ_is_secure_boot_enable();
	if (secure_boot_enable == false) {
		TTY_LOG("TZ_SPAY_INIT: secure boot has not been enabled yet, skip measurement check!!!");
	} else {
		ret = memcmp(golden_msrs, boot_msr, msr_size);
		if (ret != 0) {
			STORE_TA_ERROR("TZ_SPAY_INIT: %s - verify_trusted_boot failed", __FUNCTION__);
			return TZ_SPAY_INIT_MSR_MISMATCH;
		}
		TTY_LOG("TZ_SPAY_INIT: verify_trusted_boot done");
	}
#endif	
	return TZ_SPAY_INIT_OK;

}

#endif
