/**
*   @file    hse_secure_boot.c
*
*   @brief   Secure Boot configuration.
*   @details Contains definitions of HSE services used for configuring (Advanced/Basic) Secure Boot.
*
*   @addtogroup [SECURE_BOOT]
*   @{
*/
/*==================================================================================================
*
*   Copyright 2020-2021 NXP.
*
*   This software is owned or controlled by NXP and may only be used strictly in accordance with
*   the applicable license terms. By expressly accepting such terms or by downloading, installing,
*   activating and/or otherwise using the software, you are agreeing that you have read, and that
*   you agree to comply with and are bound by, such license terms. If you do not agree to
*   be bound by the applicable license terms, then you may not retain, install, activate or
*   otherwise use the software.
==================================================================================================*/

#ifdef __cplusplus
extern "C"{
#endif

/*==================================================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/

#include "global_variables.h"
#include "hse_host_attrs.h"
#include "hse_host_boot.h"
#include "hse_host_format_key_catalogs.h"
#include "hse_host_import_key.h"
#include "hse_host_mac.h"
#include "hse_host_sign.h"
#include "demo_app_services.h"
#include "host_flash.h"
#include "S32K344_DCM.h"
#include <bsp.h>

/*
 * ============================================================================
 *                               GLOBAL VARIABLES
 * ============================================================================
*/
bool_t IsTagLocationErased = FALSE;
volatile hseSrvResponse_t KeyReadSrvResponse = HSE_SRV_RSP_GENERAL_ERROR;
//volatile uint32_t temp_addr_of_app_image = APP_TEMP_ADDRESS;

#define CRYPTO_START_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "Crypto_MemMap.h"

uint8_t __attribute__((aligned(4))) AuthTag[2U][BITS_TO_BYTES(4096U)] ;
uint32_t AuthTagLen[2U]  ;

hseSmrEntry_t smrEntry[8U] ;
hseCrEntry_t crEntry[2U] ;

uint8_t  __attribute__((aligned(4))) BootDataTag[16] ;

static hseAttrSmrCoreStatus_t smrCoreStatus_Get;

hseAttrConfigBootAuth_t GetIVTauthbit ;

#define CRYPTO_STOP_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "Crypto_MemMap.h"

/*
 * ============================================================================
 *                             LOCAL MACROS
 * ============================================================================
 */

#define SALT_LENGTH                             (20UL)

/*
 * ============================================================================
 *                               LOCAL VARIABLES
 * ============================================================================
*/

static uint8_t ReadAppDebugKey[ADKP_LENGTH] = {0U};
//IV example (used for AES CBC and AEAD example)
static const uint8_t gmac_iv[] =
{ 0xff, 0xbc, 0x51, 0x6a, 0x8f, 0xbe, 0x61, 0x52, 0xaa, 0x42, 0x8c, 0xdd, 0x48, 0x0c, 0x06, 0x2d };


/*
 * ============================================================================
 *                        LOCAL FUNCTION PROTOTYPES
 * ============================================================================
*/
static hseSrvResponse_t ConfigureSHESecureBoot(void);
static hseSrvResponse_t Check_DebugKey_status(void);
static hseSrvResponse_t ConfigureBasicSecureBoot(void);
static void HSE_SignImages
(
        const uint8_t headerTag,
        const uint32_t pImg,
        const uint32_t pImgTagAddr,
        const uint32_t CodeLength
);
static hseSrvResponse_t InstallSMR(uint8_t Index);
static hseSrvResponse_t VerifyKeys(uint8_t Index);
static hseSrvResponse_t ConfigureAdvancedSecureBoot( void );
static void ConfigureSMR( hseAppHeader_t *ptr_AppHeader, uint32_t AppAddress);
/* ============================================================================
 *                              GLOBAL FUNCTIONS
 * ============================================================================
*/

/******************************************************************************
 * Function:    SecureBootConfiguration
 * Description: HSE secure boot configuration - ASB/BSB
 *****************************************************************************/
hseSrvResponse_t SecureBootConfiguration( void )
{
    hseSrvResponse_t srvResponse = HSE_SRV_RSP_GENERAL_ERROR;
    if (( USE_SHE_BASED_SECURE_BOOT == gRunSecureBootType )
        && (KEY_CATALOGS_FORMATTED == (testStatus & KEY_CATALOGS_FORMATTED))
       )
    {
        /* Install SHE SMR/CR entries */
        srvResponse = ConfigureSHESecureBoot();
    }
    else if (( USE_ADVANCED_SECURE_BOOT == gRunSecureBootType)
            && (KEY_CATALOGS_FORMATTED == (testStatus & KEY_CATALOGS_FORMATTED))
            )
    {
        /* Install SMR/CR entries */
        srvResponse = ConfigureAdvancedSecureBoot();
    }
    else if ( USE_BASIC_SECURE_BOOT == gRunSecureBootType )
    {
        /* Sign the application image using a device specific key */
        srvResponse = ConfigureBasicSecureBoot();
    }
    else
    {

    }
    return srvResponse;
}

/* ============================================================================
 *                              LOCAL FUNCTIONS
 * ============================================================================
*/

/******************************************************************************
 * Function:    ConfigureAdvancedSecureBoot
 * Description: SMR/CR entries done for Advanced secure boot
 *****************************************************************************/
static hseSrvResponse_t ConfigureAdvancedSecureBoot( void )
{
    hseSrvResponse_t srvResponse = 0xff;
    /* S32K3xx has maximum 3 Cores */
    hseAppHeader_t *pAppHeader[HSE_APP_CORE3];
    hseAppCore_t app_core = HSE_APP_CORE0;
    /* Address where the code starts */
    uint32_t pAppCodeStart[HSE_APP_CORE10] = { 0U };
    uint8_t i;

    /* Steps for configuring secure boot is as followed.
     * Note:Single app is configure for ASB to demonstrate in this demo app.
     * The app is assumed to be flashed at BLOCK4 from where secure boot will
     * happen. App configured as below is only for secure boot purpose.
     */
    /* 1)copy IVT of length 256B from BLOCK0 section to data flash section */
    memcpy(
            (void *)&IVT,
            (const void *)( BLOCK0_IVT_ADDRESS + OTA_OFFSET ) ,
            0x100
          );

    /* check the ivt  valid */
    if( !(SBAF_BOOT_MARKER == IVT.IVT_header) )
    {
        return srvResponse ;
    }

    /*
     * 2)copy start address of app from IVT in local variable.
     *   In case of SHE secure boot, SMR#0 shall be configured so app address
     *   is copied in local variable.
     */

    pAppHeader[HSE_APP_CORE0] = (hseAppHeader_t *)(IVT.AppBL + OTA_OFFSET);
    pAppCodeStart[HSE_APP_CORE0] = pAppHeader[HSE_APP_CORE0]->pAppStartEntry  ;

    ConfigureSMR(pAppHeader[HSE_APP_CORE0], pAppCodeStart[HSE_APP_CORE0]);

    /* Configure CR entry */
    crEntry[app_core].coreId = app_core;                                /* Define the behavior for core 0 - M33_0, core 1 - M33_1 */
    for(i = 0; i < SMR_CONFIGURED; i++)
    {
#if 0
    	crEntry[app_core].preBootSmrMap |= authentication_type[i] << i; /* Tie it to the verification of SMR defined above (index 0) */
#else
    	crEntry[app_core].postBootSmrMap |= authentication_type[i] << i;
#endif
    }
    crEntry[app_core].pPassReset = pAppHeader[HSE_APP_CORE0]->pAppStartEntry;     /* Entry point - address of the first instruction */
    crEntry[app_core].crSanction = HSE_CR_SANCTION_DIS_ALL_KEYS;           /* Sanction in case SMR verification fails - keep core in reset */
    crEntry[app_core].altPreBootSmrMap = 0x0UL;                         /* Not used here - configuration in case boot fails */
    crEntry[app_core].pAltReset = pAppHeader[HSE_APP_CORE0]->pAppStartEntry;      /* Alternate Reset should not be NULL or 0xFFFFFFFF */
    crEntry[app_core].startOption = HSE_CR_AUTO_START;

    /*
     * 5) Generate and verify the tag so as to confirm
     * that application is verified for secure boot
     */
    for(i = 0; i < SMR_CONFIGURED; i++)
    {
    	if(TRUE == authentication_type[i])
    	{
			/* generate TAG for all verification scheme. */
			srvResponse = VerifyKeys(i);
			ASSERT(HSE_SRV_RSP_OK == srvResponse);

			/* Install SMR Entry */
			srvResponse = InstallSMR(i);
			ASSERT(HSE_SRV_RSP_OK == srvResponse);
    	}
    }

    /* erase tag on flash */
#if 0
    ASSERT(FLS_JOB_OK == HostFlash_EraseSector( CMAC_TAG_CODE_FLASH_ADDRESS, 1U));
#endif

    /* Install CR Entry */
    srvResponse = HSE_InstallCoreResetEntry( app_core,&(crEntry[app_core]) );
    ASSERT(HSE_SRV_RSP_OK == srvResponse);

    /* verify if secure boot is success */

    srvResponse = GetAttr(
            HSE_SMR_CORE_BOOT_STATUS_ATTR_ID,
            sizeof(hseAttrSmrCoreStatus_t),
            (void *)(&smrCoreStatus_Get)
            );
    ASSERT(HSE_SRV_RSP_OK == srvResponse);

    /*
     * 7) Now application is configured for secure boot,
     * final step is to enable secure boot by setting BOOT_SEQ = 1 in IVT
     */
    return srvResponse;
}

/******************************************************************************
 * Function:    ConfigureSHESecureBoot
 * Description: SMR/CR entries done for SHE secure boot
 *****************************************************************************/
static hseSrvResponse_t ConfigureSHESecureBoot(void)
{
    uint8_t smr;                        /* Will use SMR#1 */
    hseSrvResponse_t srvResponse = HSE_SRV_RSP_GENERAL_ERROR;
    hseAppHeader_t *pAppHeader[HSE_APP_CORE10];
    hseAppCore_t app_core = HSE_APP_CORE0;

    /* Steps for configuring secure boot is as followed.
     * Note:Single app is configure for ASB to demonstrate in this demo app.
     * The app is assumed to be flashed at BLOCK4 from where secure boot will
     * happen. App configured as below is only for secure boot purpose.
     */
    /* 1)copy IVT of length 256B from BLOCK0 section to data flash section */
    memcpy((void *)&IVT, (const void *)( BLOCK0_IVT_ADDRESS + OTA_OFFSET ), 0x100);

    /*
     * 2)copy start address of app from IVT in local variable.
     *   In case of SHE secure boot, SMR#0 shall be configured so app address
     *   is copied in local variable.
     */
    smr = 0U;
    pAppHeader[HSE_APP_CORE0] = (hseAppHeader_t *)IVT.AppBL;

    smrEntry[smr].configFlags = HSE_SMR_CFG_FLAG_INSTALL_AUTH;				/* Indicate that verification should be done on provided signature */
    smrEntry[smr].pSmrDest = 0U;                                      		/* destination address shall be NULL for flashed based devices */
    smrEntry[smr].checkPeriod = 0U;
	smrEntry[smr].pSmrSrc = pAppHeader[smr]->pAppStartEntry;           		/* Start of APP code */
    smrEntry[smr].smrSize = pAppHeader[smr]->codeLength;                                        /* Length of APP code */
	smrEntry[smr].authKeyHandle = NVM_SHE_AES128_BOOT_KEY;
	smrEntry[smr].authScheme.macScheme.macAlgo = HSE_MAC_ALGO_CMAC;
	smrEntry[smr].authScheme.macScheme.sch.cmac.cipherAlgo = HSE_CIPHER_ALGO_AES;
	smrEntry[smr].pInstAuthTag[0] = (uint32_t)NULL;     					/* NR for SHE */
	smrEntry[smr].pInstAuthTag[1] = (uint32_t)NULL;                   		/* NR for SHE */

    /* Configure CR entry */
    crEntry[app_core].coreId = app_core;                                /* Define the behavior for core 0 - M33_0, core 1 - M33_1 */
    crEntry[app_core].preBootSmrMap = HSE_KF_SMR_0;                     /* Tie it to the verification of SMR defined above (index 0) */
    crEntry[app_core].pPassReset = pAppHeader[smr]->pAppStartEntry;     /* Entry point - address of the first instruction */
    crEntry[app_core].crSanction = HSE_CR_SANCTION_DIS_ALL_KEYS;  		/* Sanction in case SMR verification fails - keep core in reset */
    crEntry[app_core].altPreBootSmrMap = 0x0UL;                         /* Not used here - configuration in case boot fails */
    crEntry[app_core].pAltReset = pAppHeader[smr]->pAppStartEntry;
    crEntry[app_core].startOption = HSE_CR_AUTO_START;

    /* import keys and Install SMR Entry */
    srvResponse = HSE_InstallSmrEntry(
                    smr,
                    (const hseSmrEntry_t *)&smrEntry[smr],
                    (const uint8_t *)smrEntry[smr].pSmrSrc,
                    smrEntry[smr].smrSize,
                    (const uint8_t *)NULL,
                    (const uint8_t *)NULL,
                    0U,
                    0U );
    ASSERT(HSE_SRV_RSP_OK == srvResponse);

    /* Install CR Entry */
    srvResponse = HSE_InstallCoreResetEntry( smr,&(crEntry[app_core]) );
    ASSERT(HSE_SRV_RSP_OK == srvResponse);

    /* verify if secure boot is success */

    /*
     * in non-caccheable
        hseAttrSmrCoreStatus_t smrCoreStatus_Get;
    */

    srvResponse = GetAttr(
            HSE_SMR_CORE_BOOT_STATUS_ATTR_ID,
            sizeof(hseAttrSmrCoreStatus_t),
            (void *)(&smrCoreStatus_Get)
            );
    ASSERT(HSE_SRV_RSP_OK == srvResponse);

    /*
     * 7) Now application is configured for secure boot,
     * final step is to enable secure boot by setting BOOT_SEQ = 1 in IVT
     */
    return srvResponse;
}

/******************************************************************************
* Function:     VerifyKeys
* Description:  Verify imported keys for Advanced secure boot for all SMR's
******************************************************************************/
static hseSrvResponse_t VerifyKeys(uint8_t Index)
{
    hseSrvResponse_t srvResponse = HSE_SRV_RSP_GENERAL_ERROR;

    Fls_CheckStatusType write_status = FLS_JOB_FAILED;
    /* Erasing Tag Locations so new Tags can be programmed here. */
    if(TRUE != IsTagLocationErased)
    {
        IsTagLocationErased = TRUE;
        write_status =  HostFlash_EraseByLen( AUTH_TAG_MARKER_ADDRESS + OTA_OFFSET , FLS_SECTOR_MIN_ERASE_SIZE ) ;
        ASSERT(FLS_JOB_OK == write_status);

        uint32_t __attribute__((aligned(4))) markerVal[2] = { 0 };
        markerVal[1] = *((uint32*) (AUTH_TAG_MARKER_ADDRESS + OTA_OFFSET + sizeof(markerVal[0])));
        if( 0xffffffff == markerVal[1] )
        {
            markerVal[1] = 0 ;
        }
        else
        {
            markerVal[1] += 1;
        }

        if( (DCM->DCMSTAT) & DCM_DCMSTAT_DCMOTAR_MASK )
        {
            /* high address */
            markerVal[0] = AUTH_TAG_MARKER_HIGH_ADDRESS_VAL ;
        }
        else
        {
            /* low address */
            markerVal[0] = AUTH_TAG_MARKER_LOW_ADDRESS_VAL ;
        }

        write_status = HostFlash_Program((uint32_t) ( AUTH_TAG_MARKER_ADDRESS + OTA_OFFSET), (uint8_t*) (markerVal), (uint32_t) (8u));
        ASSERT(FLS_JOB_OK == write_status);
    }

    switch (Index)
    {
        case (0U):
        {
            /* AES-CMAC */
            /* Generate CMAC tag */
            AuthTagLen[0] = sizeof(AuthTag[0]);

            srvResponse = AesCmacGenerate(NVM_AES128_PROVISION_KEY, smrEntry[Index].smrSize, (const uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ), &AuthTagLen[0], AuthTag[0], 0U);
            ASSERT(HSE_SRV_RSP_OK == srvResponse);

            write_status = HostFlash_Program(  (uint32_t)( CMAC_TAG_CODE_FLASH_ADDRESS + OTA_OFFSET ) , (uint8_t*) AuthTag[0], AuthTagLen[0] );
            ASSERT(FLS_JOB_OK == write_status);

            /* verify tag */
            srvResponse = AesCmacVerify(NVM_AES128_BOOT_KEY, smrEntry[Index].smrSize, (const uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ), &AuthTagLen[0],
                    (const uint8*)( CMAC_TAG_CODE_FLASH_ADDRESS + OTA_OFFSET ), 0U);
            ASSERT(HSE_SRV_RSP_OK == srvResponse);
            break;
        }
        case (1U):
        {
            /* AES-GMAC */
            AuthTagLen[0] = sizeof(AuthTag[0]);

            srvResponse = AesGmacGenerate(NVM_AES128_PROVISION_KEY, sizeof(gmac_iv), gmac_iv, smrEntry[Index].smrSize, (const uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
                    &AuthTagLen[0], AuthTag[0]);
            ASSERT(HSE_SRV_RSP_OK == srvResponse);

            write_status = HostFlash_Program( (uint32_t)( GMAC_TAG_CODE_FLASH_ADDRESS + OTA_OFFSET ), (uint8_t*) AuthTag[0], AuthTagLen[0] );
            ASSERT(FLS_JOB_OK == write_status);


            /* verify tag */
            srvResponse = AesGmacVerify(NVM_AES128_BOOT_KEY, sizeof(gmac_iv), gmac_iv, smrEntry[Index].smrSize, (const uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
                    &AuthTagLen[0], (const uint8*)( GMAC_TAG_CODE_FLASH_ADDRESS + OTA_OFFSET ));

            ASSERT(HSE_SRV_RSP_OK == srvResponse);
            break;
        }
        case (2U):
        {
            /* HMAC */
            AuthTagLen[0] = sizeof(AuthTag[0]);

            srvResponse = HmacGenerate(NVM_HMAC_KEY0, HSE_HASH_ALGO_SHA2_256,
                    smrEntry[Index].smrSize, (const uint8_t*)( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
                    &AuthTagLen[0], AuthTag[0]);
            ASSERT(HSE_SRV_RSP_OK == srvResponse);

            write_status = HostFlash_Program( (uint32_t)( HMAC_TAG_CODE_FLASH_ADDRESS + OTA_OFFSET ), (uint8_t*) AuthTag[0], AuthTagLen[0]);
            ASSERT(FLS_JOB_OK == write_status);


            /* verify tag */
            srvResponse = HmacVerify(NVM_HMAC_KEY1, HSE_HASH_ALGO_SHA2_256,
                    smrEntry[Index].smrSize, (const uint8_t*)( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
                    &AuthTagLen[0], (const uint8*)( HMAC_TAG_CODE_FLASH_ADDRESS + OTA_OFFSET ) );
            ASSERT(HSE_SRV_RSP_OK == srvResponse);
            break;
        }
        case (3U):
        {
            /* ECC - ECDSA */
            AuthTagLen[0] = sizeof(AuthTag[0]);
            AuthTagLen[1] = sizeof(AuthTag[1]);

            srvResponse = EcdsaSign(NVM_ECC_KEY_HANDLE,
            HSE_HASH_ALGO_SHA2_256, smrEntry[Index].smrSize, (const uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
            FALSE, 0U, &AuthTagLen[0], AuthTag[0], &AuthTagLen[1], AuthTag[1]);

            ASSERT(HSE_SRV_RSP_OK == srvResponse);

            write_status = HostFlash_Program(  (uint32_t)( ECDSA_TAG1_CODE_FLASH_ADDRESS + OTA_OFFSET ), (uint8_t*) AuthTag[0], AuthTagLen[0]);
            ASSERT(FLS_JOB_OK == write_status);

            write_status = HostFlash_Program(  (uint32_t)( ECDSA_TAG2_CODE_FLASH_ADDRESS + OTA_OFFSET ), (uint8_t*) AuthTag[1], AuthTagLen[1]);
            ASSERT(FLS_JOB_OK == write_status);

            /* Program */
            srvResponse = EcdsaVerify(
            NVM_ECC_KEY_HANDLE_PUBLIC,
            HSE_HASH_ALGO_SHA2_256,
            smrEntry[Index].smrSize, (const uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
            FALSE, 0U,
            &AuthTagLen[0], (const uint8_t*)( ECDSA_TAG1_CODE_FLASH_ADDRESS + OTA_OFFSET ),
            &AuthTagLen[1], (const uint8_t*)( ECDSA_TAG2_CODE_FLASH_ADDRESS + OTA_OFFSET ));

            ASSERT(HSE_SRV_RSP_OK == srvResponse);
            break;
        }
        case (4U):
        {
            /* RSA -PSS */
            /*
             * HSE_SysAuthorization_Example
             * */
            AuthTagLen[0] = sizeof(AuthTag[0]);
            AuthTagLen[1] = 0;
            memset(AuthTag[0],0,sizeof(AuthTag[0]));
            memset(AuthTag[1],0,sizeof(AuthTag[1]));
			
            srvResponse = RsaPssSignSrv(
            NVM_RSA2048_PAIR_CUSTAUTH_HANDLE1,
            SALT_LENGTH,
            HSE_HASH_ALGO_SHA2_256, smrEntry[Index].smrSize, (const uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
            FALSE, 0U, &AuthTagLen[0], AuthTag[0]);

            ASSERT(HSE_SRV_RSP_OK == srvResponse);

            write_status = HostFlash_Program(  (uint32_t) ( RSA_PSS_TAG_CODE_FLASH_ADDRESS + OTA_OFFSET ), (uint8_t*) AuthTag[0],
            AuthTagLen[0]);
            ASSERT(FLS_JOB_OK == write_status);

            srvResponse = RsaPssVerSrv(
            NVM_RSA2048_PUB_CUSTAUTH_HANDLE1,
            SALT_LENGTH,
            HSE_HASH_ALGO_SHA2_256, smrEntry[Index].smrSize, (const uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
            FALSE, 0U, &AuthTagLen[0], (const uint8_t*) ( RSA_PSS_TAG_CODE_FLASH_ADDRESS + OTA_OFFSET ));

            ASSERT(HSE_SRV_RSP_OK == srvResponse);
            break;
        }
        case (5U):
        {
            /* RSA - PKCS1_V15 */
            AuthTagLen[0] = sizeof(AuthTag[0]);
            TOGGLE_IO();
            srvResponse = RsaPkcs1v15SignSrv(NVM_RSA2048_PAIR_CUSTAUTH_HANDLE1,
            HSE_HASH_ALGO_SHA2_256, smrEntry[Index].smrSize, (uint8_t*)( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
            FALSE, 0U, &AuthTagLen[0], AuthTag[0]);
            TOGGLE_IO();
            ASSERT(HSE_SRV_RSP_OK == srvResponse);

            write_status = HostFlash_Program(  (uint32_t) ( RSA_PKCS1_TAG_CODE_FLASH_ADDRESS + OTA_OFFSET ), (uint8_t*) AuthTag[0],
            AuthTagLen[0]);
            TOGGLE_IO();
            ASSERT(FLS_JOB_OK == write_status);

            srvResponse = RsaPkcs1v15VerSrv(NVM_RSA2048_PUB_CUSTAUTH_HANDLE1,
            HSE_HASH_ALGO_SHA2_256, smrEntry[Index].smrSize, (uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
            FALSE, 0U, &AuthTagLen[0], (uint8_t*) ( RSA_PKCS1_TAG_CODE_FLASH_ADDRESS + OTA_OFFSET ));
            TOGGLE_IO();
            ASSERT(HSE_SRV_RSP_OK == srvResponse);

            break;
        }
        case (6U):
        {
            /* ECC - EDDSA */
			AuthTagLen[0] = sizeof(AuthTag[0]);
            AuthTagLen[1] = sizeof(AuthTag[1]);
			
            TOGGLE_IO();
            srvResponse = EddsaSign(NVM_ECC_KEY_HANDLE_PAIR_EDDSA, smrEntry[Index].authScheme.sigScheme.sch.eddsa.bHashEddsa, smrEntry[Index].smrSize,
                    (const uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
                    FALSE, smrEntry[Index].authScheme.sigScheme.sch.eddsa.contextLength,
                    (const uint8_t*) smrEntry[Index].authScheme.sigScheme.sch.eddsa.pContext, &AuthTagLen[0], AuthTag[0], &AuthTagLen[1], AuthTag[1]);
            TOGGLE_IO();
            ASSERT(HSE_SRV_RSP_OK == srvResponse);

            write_status = HostFlash_Program(  (uint32_t) ( EDDSA_TAG1_CODE_FLASH_ADDRESS + OTA_OFFSET ), (uint8_t*) AuthTag[0], AuthTagLen[0]);

            ASSERT(FLS_JOB_OK == write_status);

            write_status = HostFlash_Program(  (uint32_t) ( EDDSA_TAG2_CODE_FLASH_ADDRESS + OTA_OFFSET ), (uint8_t*) AuthTag[1], AuthTagLen[1]);

            ASSERT(FLS_JOB_OK == write_status);

            /* Program */
            TOGGLE_IO();
            srvResponse = EddsaVerify(NVM_ECC_KEY_HANDLE_PUBLIC_1, smrEntry[Index].authScheme.sigScheme.sch.eddsa.bHashEddsa, smrEntry[Index].smrSize,
                    (const uint8_t*) ( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
                    FALSE, smrEntry[Index].authScheme.sigScheme.sch.eddsa.contextLength,
                    (const uint8_t*) smrEntry[Index].authScheme.sigScheme.sch.eddsa.pContext, 
					&AuthTagLen[0], (const uint8_t*)( EDDSA_TAG1_CODE_FLASH_ADDRESS + OTA_OFFSET ),
					&AuthTagLen[1], (const uint8_t*)( EDDSA_TAG2_CODE_FLASH_ADDRESS + OTA_OFFSET ));
            TOGGLE_IO();
            ASSERT(HSE_SRV_RSP_OK == srvResponse);

            break;
        }

        default:
        {
            break;
        }
    }
    return srvResponse;
}

/******************************************************************************
* Function:     InstallSMR
* Description:  Installs SMR for Advanced secure boot and SHE secure boot
******************************************************************************/
static hseSrvResponse_t InstallSMR(uint8_t Index)
{
    hseSrvResponse_t srvResponse = HSE_SRV_RSP_GENERAL_ERROR;

    /* 6) Finally, install SMR and CR entry and verify SMR install */
    srvResponse = HSE_InstallSmrEntry( (Index),
                                        (const hseSmrEntry_t *)&smrEntry[Index],
                                        (const uint8_t *)( smrEntry[Index].pSmrSrc + OTA_OFFSET ),
                                        smrEntry[Index].smrSize,
                                        (const uint8 *)(AuthTag[0]),
                                        (const uint8 *)(AuthTag[1]),
                                        AuthTagLen[0],
                                        AuthTagLen[1]
                                        );
    ASSERT(HSE_SRV_RSP_OK == srvResponse);

#ifndef HSE_S32K3XX_OTA_ENABLE
    /* verify SMR entry - SMR verify is not allowed for SHE boot,
        only on next cycle could it be verified if BOOT_SEQ=0 */
    srvResponse = smrVerifyTest(Index);
    ASSERT(HSE_SRV_RSP_OK == srvResponse);
#endif

    return srvResponse;
}

/******************************************************************************
 * Function:    Check_DebugKey_status
 * Description: provisions device specific key for basic secure boot
 *****************************************************************************/
static hseSrvResponse_t Check_DebugKey_status(void)
{
   /*Check if ADKP is already programmed, if yes, then NOT_ALLOWED response is
    * expected from HSE else ADKP hash will be read
    */
    return HSE_ReadAdkp(&ReadAppDebugKey[0U]);
}

/******************************************************************************
* Function:     ConfigureBasicSecureBoot
* Description:  Generates APP TAG for BSB,
*               Authenticate the application using a device specific key
*****************************************************************************/
static hseSrvResponse_t ConfigureBasicSecureBoot(void)
{
    hseSrvResponse_t HseResponse;

    ivt_t *pIvt = (ivt_t*) ( BLOCK0_IVT_ADDRESS + OTA_OFFSET );

    HseResponse = Check_DebugKey_status();
    if( HSE_SRV_RSP_OK != HseResponse)
    {
        goto exit;
    }

    /* check if have SU right , the crypto example test about user auth, block it or can't perform BSB */
    if(FALSE == HSE_CheckStatus(HSE_STATUS_CUST_SUPER_USER))
    {
        goto exit;
    }

    /* Sign application using BootData Sign/Verify services */
    HSE_SignImages( HEADER_APP_TAG,
            (const uint32_t)(((hseAppHeader_t*)pIvt->AppBL)) ,
            (const uint32_t)(BootDataTag),
            (const uint32_t)((((hseAppHeader_t*)pIvt->AppBL)->codeLength) ) );

    exit :
    return HseResponse;
}

/******************************************************************************
* Function:     HSE_SignImages
* Description:  Helper for signing and verifying boot images(App in this case)
******************************************************************************/
static void HSE_SignImages
(
        const uint8_t headerTag,
        const uint32_t pImg,
        const uint32_t pImgTagAddr,
        const uint32_t CodeLength
)
{
    hseSrvResponse_t srvResponse = HSE_SRV_RSP_GENERAL_ERROR;
    /* Check if PRIMARY image is set */
    if(ADDR_NOT_NULL(pImg))
    {
        uint8_t header_tag = *(volatile uint8_t*) pImg;
        /* Header tag sanity check */
        ASSERT(headerTag == header_tag);

        /* Sign the primary image - 16 bytes MAC */
        srvResponse = HSE_SignBootImage((uint8_t*) pImg, BOOT_IMG_TAG_LEN, (uint8_t*) pImgTagAddr);
        ASSERT(HSE_SRV_RSP_OK == srvResponse);

        /* write IVT with GMAC appended at the offset 0xF0 of IVT location */
        ASSERT(HostFlash_EraseSector(  (uint32_t)( pImg + APP_HEADER_LENGTH + CodeLength + OTA_OFFSET ), 1U ) == FLS_JOB_OK);
        ASSERT(HostFlash_Program(  (uint32_t)( pImg + APP_HEADER_LENGTH + CodeLength + OTA_OFFSET), (uint8_t* )pImgTagAddr, BOOT_IMG_TAG_LEN ) == FLS_JOB_OK);

#ifndef HSE_S32K3XX_OTA_ENABLE
        /* Verify the Tag was generated and programmed correctly */
        if(HEADER_APP_TAG == headerTag)
        {
            srvResponse = HSE_VerifyBootImage((uint8_t*) pImg);
            ASSERT(HSE_SRV_RSP_OK == srvResponse);
        }
#endif
    }
}

/******************************************************************************
* Function:     UpdateIvt
* Description:  Enable Secure Boot by signing IVT and by setting BOOT_SEQ bit
******************************************************************************/
hseSrvResponse_t UpdateIvt( uint32_t UpdateAddress , uint32_t SourceAddress , ivt_type_t IvtType )
{
    hseSrvResponse_t hseResponse;

    ivt_t TempIvt ;

    (void) hseResponse;
    /* save origin ivt */
    memcpy((void *)&TempIvt, (void *)( SourceAddress ), sizeof(ivt_t) );

    if ( NON_SECURE_IVT == IvtType)
    {
        TempIvt.bootCfgWord &= ~IVT_BOOT_CFG_WORD_BOOT_SEQ;
    }
    else
    {
        hseResponse = HSE_GetIVTauthbit(&GetIVTauthbit);

        if( HSE_IVT_NO_AUTH == GetIVTauthbit )
        {
            TempIvt.bootCfgWord |= IVT_BOOT_CFG_WORD_BOOT_SEQ;
            /* 1. FXOSC enablement flag must be enabled
             * 2. PLL is configured only when BOOT_SEQ==1 */
            uint64_t* FxoscValAddr = (uint64_t*)(UTEST_BASE_ADDRESS+0x50u) ;

            if( FXOSC_ENABLE_MAGIC_NUMBER == (uint32_t)( ((uint64_t)(*FxoscValAddr)) >> 32u ) )
            {
                TempIvt.bootCfgWord |= IVT_BOOT_CFG_WORD_PLL_ENABLE;
            }
        }
        else
        {
            /* generate GMAC of IVT, write to block 0 ivt address */

        }
    }
    /* erase IVT location */
    ASSERT( HostFlash_EraseSector(  UpdateAddress , 1U ) == FLS_JOB_OK);

    ASSERT( HostFlash_Program(  UpdateAddress, (uint8_t* )&TempIvt,(uint32_t)sizeof(ivt_t) ) == FLS_JOB_OK);

    return HSE_SRV_RSP_OK;
}

static void ConfigureSMR( hseAppHeader_t *ptr_AppHeader, uint32_t AppAddress)
{
    uint8_t i;
	for(i = 0; i < SMR_CONFIGURED; i++)
	{
		if(TRUE != authentication_type[i])
		{
		    continue ;
		}

		switch(i)
		{
            case (0U):
            {
                /* AES-CMAC */
                smrEntry[i].configFlags = HSE_SMR_CFG_FLAG_INSTALL_AUTH; /* Indicate that verification should be done on provided signature */
                smrEntry[i].pSmrDest = 0U; /* destination address shall be NULL for flashed based devices */
                smrEntry[i].checkPeriod = 0U;
                smrEntry[i].pSmrSrc = AppAddress;                              /* Start of APP code */
                smrEntry[i].smrSize = ptr_AppHeader->codeLength;                                  /* Length of APP code */
                smrEntry[i].authKeyHandle = NVM_AES128_BOOT_KEY;
                smrEntry[i].authScheme.macScheme.macAlgo = HSE_MAC_ALGO_CMAC;
                smrEntry[i].authScheme.macScheme.sch.cmac.cipherAlgo = HSE_CIPHER_ALGO_AES;
                smrEntry[i].pInstAuthTag[0] = (uint32_t)CMAC_TAG_CODE_FLASH_ADDRESS;     /* signature tag address */
                smrEntry[i].pInstAuthTag[1] = (uint32_t)NULL;                  /* In this example, AES keys is used hence 2nd tag address is NULL */
                break;
            }
            case (1U):
            {
                /* AES-GMAC */
                smrEntry[i].configFlags = HSE_SMR_CFG_FLAG_INSTALL_AUTH; /* Indicate that verification should be done on provided signature */
                smrEntry[i].pSmrDest = 0U; /* destination address shall be NULL for flashed based devices */
                smrEntry[i].checkPeriod = 0U;
                smrEntry[i].pSmrSrc = AppAddress; /* Start of APP code */
                smrEntry[i].smrSize = ptr_AppHeader->codeLength; /* Length of APP code */
                smrEntry[i].authKeyHandle = NVM_AES128_BOOT_KEY;
                smrEntry[i].authScheme.macScheme.macAlgo = HSE_MAC_ALGO_GMAC;
                smrEntry[i].authScheme.macScheme.sch.gmac.pIV = (HOST_ADDR) gmac_iv;
                smrEntry[i].authScheme.macScheme.sch.gmac.ivLength = sizeof(gmac_iv);
                smrEntry[i].pInstAuthTag[0] = (uint32_t) GMAC_TAG_CODE_FLASH_ADDRESS; /* signature tag address */
                smrEntry[i].pInstAuthTag[1] = (uint32_t) NULL;                  /* In this example, AES keys is used hence 2nd tag address is NULL */
                break;
            }
            case (2U):
            {
                /* HMAC */
                smrEntry[i].configFlags = HSE_SMR_CFG_FLAG_INSTALL_AUTH; /* Indicate that verification should be done on provided signature */
                smrEntry[i].pSmrDest = 0U; /* destination address shall be NULL for flashed based devices */
                smrEntry[i].checkPeriod = 0U;
                smrEntry[i].pSmrSrc =  AppAddress;                    /* Start of APP code */
                smrEntry[i].smrSize = ptr_AppHeader->codeLength;                                  /* Length of APP code */
                smrEntry[i].authKeyHandle = NVM_HMAC_KEY1;
                smrEntry[i].authScheme.macScheme.macAlgo = HSE_MAC_ALGO_HMAC;
                smrEntry[i].authScheme.macScheme.sch.hmac.hashAlgo = HSE_HASH_ALGO_SHA2_256;
                smrEntry[i].pInstAuthTag[0] = (uint32_t)HMAC_TAG_CODE_FLASH_ADDRESS;     /* signature tag address */
                smrEntry[i].pInstAuthTag[1] = (uint32_t)NULL;                  /* In this example, AES keys is used hence 2nd tag address is NULL */
                break;
            }
            case (3U):
            {
                /* ECC - ECDSA */
                smrEntry[i].configFlags = HSE_SMR_CFG_FLAG_INSTALL_AUTH; /* Indicate that verification should be done on provided signature */
                smrEntry[i].pSmrDest = 0U; /* destination address shall be NULL for flashed based devices */
                smrEntry[i].checkPeriod = 0U;
                smrEntry[i].pSmrSrc = AppAddress;                     /* Start of APP code */
                smrEntry[i].smrSize = ptr_AppHeader->codeLength;                                  /* Length of APP code */
                smrEntry[i].authKeyHandle = NVM_ECC_KEY_HANDLE_PUBLIC;
                smrEntry[i].authScheme.sigScheme.signSch = HSE_SIGN_ECDSA;
                smrEntry[i].authScheme.sigScheme.sch.ecdsa.hashAlgo = HSE_HASH_ALGO_SHA2_256;
                smrEntry[i].pInstAuthTag[0] = (uint32_t)ECDSA_TAG1_CODE_FLASH_ADDRESS;     /* signature tag address */
                smrEntry[i].pInstAuthTag[1] = (uint32_t)ECDSA_TAG2_CODE_FLASH_ADDRESS;     /* signature tag address */
                break;
            }
            case (4U):
            {
                /* RSA - PSS */
                smrEntry[i].configFlags = HSE_SMR_CFG_FLAG_INSTALL_AUTH; /* Indicate that verification should be done on provided signature */
                smrEntry[i].pSmrDest = 0U; /* destination address shall be NULL for flashed based devices */
                smrEntry[i].checkPeriod = 0U;
                smrEntry[i].pSmrSrc = AppAddress;                     /* Start of APP code */
                smrEntry[i].smrSize = ptr_AppHeader->codeLength;                                  /* Length of APP code */
                smrEntry[i].authKeyHandle = NVM_RSA2048_PUB_CUSTAUTH_HANDLE1;
                smrEntry[i].authScheme.sigScheme.signSch = HSE_SIGN_RSASSA_PSS;
                smrEntry[i].authScheme.sigScheme.sch.rsaPss.hashAlgo = HSE_HASH_ALGO_SHA2_256;
                smrEntry[i].authScheme.sigScheme.sch.rsaPss.saltLength = SALT_LENGTH;
                smrEntry[i].pInstAuthTag[0] = (uint32_t)RSA_PSS_TAG_CODE_FLASH_ADDRESS;     /* signature tag address */
                smrEntry[i].pInstAuthTag[1] = (uint32_t)NULL;                 /* In this example, AES keys is used hence 2nd tag address is NULL */
                break;
            }
            case (5U):
            {
                /* RSA - PKCS1_V15 */
                smrEntry[i].configFlags = HSE_SMR_CFG_FLAG_INSTALL_AUTH;          /* Indicate that verification should be done on provided signature */
                smrEntry[i].pSmrDest = 0U;                                        /* destination address shall be NULL for flashed based devices */
                smrEntry[i].checkPeriod = 0U;
                smrEntry[i].pSmrSrc = AppAddress; /* Start of APP code */
                smrEntry[i].smrSize = ptr_AppHeader->codeLength;; /* Length of APP code */
                smrEntry[i].authKeyHandle = NVM_RSA2048_PUB_CUSTAUTH_HANDLE1;
                smrEntry[i].authScheme.sigScheme.signSch = HSE_SIGN_RSASSA_PKCS1_V15;
                smrEntry[i].authScheme.sigScheme.sch.rsaPkcs1v15.hashAlgo = HSE_HASH_ALGO_SHA2_256;
                smrEntry[i].pInstAuthTag[0] = RSA_PKCS1_TAG_CODE_FLASH_ADDRESS; /* signature tag address */
                smrEntry[i].pInstAuthTag[1] = (uint32_t) NULL; /* In this example, AES keys is used hence 2nd tag address is NULL */
                break;
            }
            case (6U):
            {
                /* ECC - EDDSA */
                smrEntry[i].configFlags = 0;          /* Indicate that verification should be done on provided signature */
                smrEntry[i].pSmrDest = 0U;                                        /* destination address shall be NULL for flashed based devices */
                smrEntry[i].checkPeriod = 0U;
                smrEntry[i].pSmrSrc = AppAddress; /* Start of APP code */
                smrEntry[i].smrSize = ptr_AppHeader->codeLength; /* Length of APP code */
                smrEntry[i].authKeyHandle = NVM_ECC_KEY_HANDLE_PUBLIC_1;
                smrEntry[i].authScheme.sigScheme.signSch = HSE_SIGN_EDDSA;
                smrEntry[i].authScheme.sigScheme.sch.eddsa.bHashEddsa = true;
                smrEntry[i].authScheme.sigScheme.sch.eddsa.contextLength = 0;
                smrEntry[i].authScheme.sigScheme.sch.eddsa.pContext = (HOST_ADDR) NULL;
                smrEntry[i].pInstAuthTag[0] = EDDSA_TAG1_CODE_FLASH_ADDRESS; /* signature tag address */
                smrEntry[i].pInstAuthTag[1] = EDDSA_TAG2_CODE_FLASH_ADDRESS; /* signature tag address */
                break;
            }
            default:
            {
                break;
            }
        }
    }
}
#ifdef __cplusplus
}
#endif

/** @} */
