/**
*   @file    Crypto_Cse_Cmd.c
*   @version 1.0.0
*
*   @brief   AUTOSAR Crypto - Files used by Crypto that contain the cmd
*   @details This files implements request commands for CSE module
*
*   @addtogroup CRYPTO
*   @{
*/
/*==================================================================================================
*   Project              : AUTOSAR 4.3 MCAL
*   Platform             : PA
*   Peripheral           : Crypto
*   Dependencies         : none
*
*   Autosar Version      : 4.3.1
*   Autosar Revision     : ASR_REL_4_3_REV_0001
*   Autosar Conf.Variant :
*   SW Version           : 1.0.0
*   Build Version        : MPC5777C_MCAL_1_0_0_RTM_ASR_REL_4_3_REV_0001_20190315
*
*   (c) Copyright 2006-2016 Freescale Semiconductor, Inc. 
*       Copyright 2017-2019 NXP
*   All Rights Reserved.
==================================================================================================*/
/*==================================================================================================
==================================================================================================*/

#ifdef __cplusplus
extern "C"{
#endif

/**
* @page misra_violations MISRA-C:2012 violations
*
* @section Crypto_Cse_Cmd_c_REF_1
* Violates MISRA 2012 Advisory Rule 20.1, #include directives should only be preceded by preprocessor
* directives or comments. AUTOSAR imposes the specification of the sections in which certain parts
* of the driver must be placed.
*
* @section Crypto_Cse_Cmd_c_REF_2
* Violates MISRA 2012 Required Directive 4.10, Precautions shall be taken in order to prevent the contents
* of a header file being included more than once. This comes from the order of includes in the .c file
* and from include dependencies. As a safe approach, any file must include all its dependencies.
* Header files are already protected against double inclusions. The inclusion of Crypto_MemMap.h is as
* per AUTOSAR requirement [SWS_MemMap_00003].
*
* @section [global]
*          Violates MISRA 2012 Required Rule 5.1, External identifiers shall be distinct.
*          The used compilers use more than 31 chars for identifiers.
*
* @section [global]
*          Violates MISRA 2012 Required Rule 5.2, Identifiers declared in the same scope and name space shall be distinct.
*          The used compilers use more than 31 chars for identifiers.
*
* @section [global]
*          Violates MISRA 2012 Required Rule 5.4, Macro identifiers shall be distinct.
*          The used compilers use more than 31 chars for identifiers.
*
* @section [global]
*          Violates MISRA 2012 Required Rule 5.5, Identifiers shall be distinct from macro names.
*          The used compilers use more than 31 chars for identifiers.
*/

/*==================================================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "Crypto_Cse.h"

/*==================================================================================================
*                              SOURCE FILE VERSION INFORMATION
==================================================================================================*/
#define CRYPTO_CSE_CMD_VENDOR_ID_C                    43
#define CRYPTO_CSE_CMD_AR_RELEASE_MAJOR_VERSION_C     4
#define CRYPTO_CSE_CMD_AR_RELEASE_MINOR_VERSION_C     3
#define CRYPTO_CSE_CMD_AR_RELEASE_REVISION_VERSION_C  1
#define CRYPTO_CSE_CMD_SW_MAJOR_VERSION_C             1
#define CRYPTO_CSE_CMD_SW_MINOR_VERSION_C             0
#define CRYPTO_CSE_CMD_SW_PATCH_VERSION_C             0

/*==================================================================================================
*                                     FILE VERSION CHECKS
==================================================================================================*/
/* Check if Crypto_Cse_Irq source file and Crypto_Cse.h header file are of the same vendor */
#if (CRYPTO_CSE_CMD_VENDOR_ID_C != CRYPTO_CSE_VENDOR_ID)
    #error "Crypto_Cse_Cmd.c and Crypto_Cse.h have different vendor ids"
#endif

/* Check if Crypto_Cse_Irq source file and Crypto_Cse.h header file are of the same Autosar version */
#if ((CRYPTO_CSE_CMD_AR_RELEASE_MAJOR_VERSION_C    != CRYPTO_CSE_AR_RELEASE_MAJOR_VERSION) || \
     (CRYPTO_CSE_CMD_AR_RELEASE_MINOR_VERSION_C    != CRYPTO_CSE_AR_RELEASE_MINOR_VERSION) || \
     (CRYPTO_CSE_CMD_AR_RELEASE_REVISION_VERSION_C != CRYPTO_CSE_AR_RELEASE_REVISION_VERSION) \
    )
    #error "AutoSar Version Numbers of Crypto_Cse_Cmd.c  and Crypto_Cse.h are different"
#endif

/* Check if Crypto_Cse_Irq source file and Crypto_Cse.h header file are of the same Software version */
#if ((CRYPTO_CSE_CMD_SW_MAJOR_VERSION_C != CRYPTO_CSE_SW_MAJOR_VERSION) || \
     (CRYPTO_CSE_CMD_SW_MINOR_VERSION_C != CRYPTO_CSE_SW_MINOR_VERSION) || \
     (CRYPTO_CSE_CMD_SW_PATCH_VERSION_C != CRYPTO_CSE_SW_PATCH_VERSION)    \
    )
    #error "Software Version Numbers of Crypto_Cse_Cmd.c  and Crypto_Cse.h are different"
#endif

/*==================================================================================================
*                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/

/*==================================================================================================
*                                       LOCAL MACROS
==================================================================================================*/
/* Macro to compute a length in bits starting from a lenght given in bytes */
#define Crypto_Cse_GetBitLengthFromByteLength(len)      ((len) << 3U)

/*==================================================================================================
*                                      LOCAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                      LOCAL VARIABLES
==================================================================================================*/
#define CRYPTO_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Crypto_MemMap.h"


#if (STD_ON == CRYPTO_KEYS_EXIST)
static VAR (uint64, CRYPTO_VAR) u64MacDataBitLength;
#endif /*STD_ON == CRYPTO_KEYS_EXIST*/

static VAR (uint64, CRYPTO_VAR) u64MPLength;
static VAR (uint64, CRYPTO_VAR) u64MessLength;

#define CRYPTO_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Crypto_MemMap.h"

/*==================================================================================================
*                                      GLOBAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                      GLOBAL VARIABLES
==================================================================================================*/
#define CRYPTO_START_SEC_VAR_INIT_BOOLEAN
#include "Crypto_MemMap.h"

VAR (boolean, CRYPTO_VAR) Crypto_Cse_bCommandInProgress       = (boolean)FALSE;
VAR (boolean, CRYPTO_VAR) Crypto_Cse_bCommandInProgressIsAJob = (boolean)FALSE;

#define CRYPTO_STOP_SEC_VAR_INIT_BOOLEAN
#include "Crypto_MemMap.h"

/*==================================================================================================
*                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/

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

/*==================================================================================================
*                                       GLOBAL FUNCTIONS
==================================================================================================*/
#define CRYPTO_START_SEC_CODE
/**
* @violates @ref Crypto_Cse_Cmd_c_REF_1 #include directives should only be preceded by preprocessor
* directives or comments.
*
* @violates @ref Crypto_Cse_Cmd_c_REF_2 Precautions shall be taken in order to prevent the contents
* of a header file being included more than once.
*/
#include "Crypto_MemMap.h"


/**
* @brief        Check busy status.
* @details      Function will return TRUE if CSE is busy.
*
* @param[in]    None
*
* @return          Result of the operation.
*                   boolean - FAlSE if CSE is not busy , TRUE otherwise
*
* @pre          Driver must be initialized.
*
*/
FUNC(boolean, CRYPTO_CODE) Crypto_Cse_IsBusy(void)
{
    return Crypto_Cse_IsBitSet(REG_READ32(CRYPTO_CSE_SR_ADDR32), CRYPTO_CSE_SR_BSY_BIT_MASK_U32);
}

/**
* @brief        Sends command to CSE.
* @details      Commands are issued by first loading the appropriate parameter registers (CSE_Px) and then writing a command code to the command register (CSE_CMD).
*
* @param[in]    eCmd    Command Code
*
* @return          Result of the operation.
*                   None
*
* @pre          Driver must be initialized.
*
*/
FUNC (void, CRYPTO_CODE) Crypto_Cse_SendCommand
( 
    VAR(Cse_CmdType, AUTOMATIC) eCmd
)
{
    Crypto_Cse_bCommandInProgress = (boolean)TRUE;
    REG_WRITE32(CRYPTO_CSE_CMD_ADDR32, (uint32)(eCmd));
}

/**
* @brief        Wait command complete.
* @details      Checks if the request was processed for a period of time.
*
* @param[in]    none
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC (Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_WaitCommandComplete(void)
{   
    VAR(uint32,            AUTOMATIC) u32TimeoutCount = CRYPTO_TIMEOUT_DURATION_U32;
    VAR(Cse_ErrorCodeType, AUTOMATIC) eCseResponse;
    
    /** @violates @ref Crypto_Cse_c_REF_6 MISRA 2004 Rule 11.1, Cast from unsigned long to pointer*/ 
    /** @violates @ref Crypto_Cse_c_REF_7 MISRA 2004 Rule 11.3, Cast from unsigned long to pointer*/  
    while ( (Crypto_Cse_IsBusy() ) && ( 0U < u32TimeoutCount ) )
    {
        --u32TimeoutCount;
    }
    
    /* If the timeout did not elapse and the command has finished, return the value from ECR register */
    if ( (boolean)FALSE == Crypto_Cse_IsBusy() )
    {
        eCseResponse = (Cse_ErrorCodeType)(REG_READ32(CRYPTO_CSE_ECR_ADDR32));
    }
    else
    {
        eCseResponse = (Cse_ErrorCodeType)CSE_CMD_TIMEOUT;
    }
    
    /* No CSE command is currently processed */
    Crypto_Cse_bCommandInProgress       = (boolean)FALSE;
    /* Reset also the flag that states that the currently processed command is a job */
    Crypto_Cse_bCommandInProgressIsAJob = (boolean)FALSE;
    
    return eCseResponse;
}

#if (STD_ON == CRYPTO_KEYS_EXIST)
/**
* @brief        Performs AES-128 encryption in ECB mode.
* @details      This function performs the AES-128 encryption in ECB mode of the input plaintext buffer.
*               It operates under the assumption that the plaintext length is a multiple of 16 bytes.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes.
*
* @param[in]    eKeyId              KeyID used to perform the cryptographic operation
* @param[in]    pPlainText          Pointer to the plain text buffer to be encrypted
* @param[in]    u32PlainTextLength  Number of bytes of plain text message to be encrypted
* @param[out]   pCipherText         Pointer to the cipher text buffer. The buffer shall have the same size as the plain text buffer
* @param[in]    eJobProcessing      The processing type used
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandEcbEncrypt
(
    VAR    (Cse_KeyHandleType,     AUTOMATIC                   ) eKeyId,
    P2CONST(uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pPlainText,
    VAR    (uint32,                AUTOMATIC                   ) u32PlainTextLength,
    P2VAR  (uint8,                 AUTOMATIC, CRYPTO_APPL_DATA ) pCipherText,
    VAR    (Crypto_ProcessingType, AUTOMATIC                   ) eJobProcessing
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse = CSE_ERC_NO_ERROR;
    /* Convert buffer length in bytes to number of 128-bits blocks */
    VAR(uint16, AUTOMATIC) u16BlockToWrite = (uint16)Crypto_Cse_Get128BitBuffBlockCount(u32PlainTextLength);

    /* Select the Key Bank used based on the key id */
    Crypto_Cse_KeyBankSelect(&eKeyId);

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)eKeyId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)u16BlockToWrite);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)pPlainText);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32, (uint32)pCipherText);
    
    /* If asynchronous mode is set to INTERRUPT, enable the CSE interrupt in the configuration register */
#if (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT)
    if(CRYPTO_PROCESSING_ASYNC == eJobProcessing)
    {
        REG_BIT_SET32(CRYPTO_CSE_CR_ADDR32, CRYPTO_CSE_CR_CIE_BIT_MASK_U32);
    }
#endif /* (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT) */
    
    Crypto_Cse_SendCommand(CSE_CMD_ENC_ECB);

    if(CRYPTO_PROCESSING_SYNC == eJobProcessing)
    {
        eOutResponse = Crypto_Cse_WaitCommandComplete();
    }
    
    return eOutResponse;
}


/**
* @brief        Performs AES-128 decryption in ECB mode.
* @details      This function performs the AES-128 decryption in ECB mode of the input ciphertext buffer.
*               It operates under the assumption that the ciphertext length is a multiple of 16 bytes.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes.
*
* @param[in]    eKeyId               KeyID used to perform the cryptographic operation
* @param[in]    pCipherText          Pointer to the cipher text buffer
* @param[in]    u32CipherTextLength  Number of bytes of cipher text message to be decrypted
* @param[out]   pPlainText           Pointer to the plain text buffer. The buffer shall have the same size as the cipher text buffer.
* @param[in]    eJobProcessing      The processing type used
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandEcbDecrypt
(
    VAR    (Cse_KeyHandleType,     AUTOMATIC                   ) eKeyId, 
    P2CONST(uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pCipherText,
    VAR    (uint32,                AUTOMATIC                   ) u32CipherTextLength, 
    P2VAR  (uint8,                 AUTOMATIC, CRYPTO_APPL_DATA ) pPlainText,
    VAR    (Crypto_ProcessingType, AUTOMATIC                   ) eJobProcessing
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse = CSE_ERC_NO_ERROR;
    /* Convert buffer length in bytes to number of 128-bits blocks */
    VAR(uint16, AUTOMATIC) u16BlockToWrite = (uint16)Crypto_Cse_Get128BitBuffBlockCount(u32CipherTextLength);

    /* Select the Key Bank used based on the key id */
    Crypto_Cse_KeyBankSelect(&eKeyId);

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)eKeyId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)u16BlockToWrite);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)pCipherText);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32, (uint32)pPlainText);
    
    /* If asynchronous mode is set to INTERRUPT, enable the CSE interrupt in the configuration register */
#if (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT)
    if(CRYPTO_PROCESSING_ASYNC == eJobProcessing)
    {
        REG_BIT_SET32(CRYPTO_CSE_CR_ADDR32, CRYPTO_CSE_CR_CIE_BIT_MASK_U32);
    }
#endif /* (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT) */

    Crypto_Cse_SendCommand(CSE_CMD_DEC_ECB);

    if(CRYPTO_PROCESSING_SYNC == eJobProcessing)
    {
        eOutResponse = Crypto_Cse_WaitCommandComplete();
    }

    return eOutResponse;
}

/**
* @brief        Performs AES-128 encryption in CBC mode.
* @details      This function performs the AES-128 encryption in CBC mode of the input plaintext buffer.
*               It operates under the assumption that the plaintext length is a multiple of 16 bytes.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes.
*
* @param[in]    eKeyId              KeyID used to perform the cryptographic operation
* @param[in]    pPlainText          Pointer to the plain text buffer
* @param[in]    u32PlainTextLength  Number of bytes of plain text message to be encrypted
* @param[in]    pIV                 Pointer to the initialization vector buffer
* @param[out]   pCipherText         Pointer to the cipher text buffer. The buffer shall have the same size as the plain text buffer.
* @param[in]    eJobProcessing      The processing type used
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandCbcEncrypt
(
    VAR    (Cse_KeyHandleType,     AUTOMATIC                   ) eKeyId,
    P2CONST(uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pPlainText,
    VAR    (uint32,                AUTOMATIC                   ) u32PlainTextLength,
    P2CONST(uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pIV,
    P2VAR  (uint8,                 AUTOMATIC, CRYPTO_APPL_DATA ) pCipherText,
    VAR    (Crypto_ProcessingType, AUTOMATIC                   ) eJobProcessing
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse = CSE_ERC_NO_ERROR;
    /* Convert buffer length in bytes to number of 128-bits blocks */
    VAR(uint16, AUTOMATIC) u16BlockToWrite = (uint16)Crypto_Cse_Get128BitBuffBlockCount(u32PlainTextLength);

    /* Select the Key Bank used based on the key id */
    Crypto_Cse_KeyBankSelect(&eKeyId);

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)eKeyId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)pIV);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)u16BlockToWrite);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32, (uint32)pPlainText);
    REG_WRITE32(CRYPTO_CSE_P5_ADDR32, (uint32)pCipherText);
    
    /* If asynchronous mode is set to INTERRUPT, enable the CSE interrupt in the configuration register */
#if (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT)
    if(CRYPTO_PROCESSING_ASYNC == eJobProcessing)
    {
        REG_BIT_SET32(CRYPTO_CSE_CR_ADDR32, CRYPTO_CSE_CR_CIE_BIT_MASK_U32);
    }
#endif /* (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT) */

    Crypto_Cse_SendCommand(CSE_CMD_ENC_CBC);

    if(CRYPTO_PROCESSING_SYNC == eJobProcessing)
    {
        eOutResponse = Crypto_Cse_WaitCommandComplete();
    }

    return eOutResponse;
}

/**
* @brief        Performs AES-128 decryption in CBC mode.
* @details      This function performs the AES-128 decryption in CBC mode of the input ciphertext buffer.
*               It operates under the assumption that the ciphertext length is a multiple of 16 bytes.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes.
*
* @param[in]    eKeyId               KeyID used to perform the cryptographic operation
* @param[in]    pCipherText          Pointer to the cipher text buffer
* @param[in]    u32CipherTextLength  Number of bytes of cipher text message to be decrypted
* @param[in]    pIV                  Pointer to the initialization vector buffer
* @param[out]   pPlainText           Pointer to the plain text buffer. The buffer shall have the same size as the cipher text buffer.
* @param[in]    eJobProcessing       The processing type used
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandCbcDecrypt
(
    VAR    (Cse_KeyHandleType,     AUTOMATIC                   ) eKeyId,
    P2CONST(uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pCipherText,
    VAR    (uint32,                AUTOMATIC                   ) u32CipherTextLength,
    P2CONST(uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pIV,
    P2VAR  (uint8,                 AUTOMATIC, CRYPTO_APPL_DATA ) pPlainText,
    VAR    (Crypto_ProcessingType, AUTOMATIC                   ) eJobProcessing
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse = CSE_ERC_NO_ERROR;
    /* Convert buffer length in bytes to number of 128-bits blocks */
    VAR(uint16, AUTOMATIC) u16BlockToWrite = (uint16)Crypto_Cse_Get128BitBuffBlockCount(u32CipherTextLength);

    /* Select the Key Bank used based on the key id */
    Crypto_Cse_KeyBankSelect(&eKeyId);

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)eKeyId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)pIV);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)u16BlockToWrite);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32, (uint32)pCipherText);
    REG_WRITE32(CRYPTO_CSE_P5_ADDR32, (uint32)pPlainText);
    
    /* If asynchronous mode is set to INTERRUPT, enable the CSE interrupt in the configuration register */
#if (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT)
    if(CRYPTO_PROCESSING_ASYNC == eJobProcessing)
    {
        REG_BIT_SET32(CRYPTO_CSE_CR_ADDR32, CRYPTO_CSE_CR_CIE_BIT_MASK_U32);
    }
#endif /* (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT) */

    Crypto_Cse_SendCommand(CSE_CMD_DEC_CBC);

    if(CRYPTO_PROCESSING_SYNC == eJobProcessing)
    {
        eOutResponse = Crypto_Cse_WaitCommandComplete();
    }

    return eOutResponse;
}

/**
* @brief        Calculates the MAC of a given message using CMAC with AES-128.
* @details      This function calculates the MAC of a given message based on CMAC with the 128-bit Advanced Encryption Standard. 
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes.
*
* @param[in]    eKeyId              KeyID used to perform the cryptographic operation
* @param[in]    pData               Pointer to the message buffer
* @param[in]    u32DataLength       Pointer to the number of bits of message on which CMAC is to be computed
* @param[out]   pMac                Pointer to the 128-bit buffer containing the result of the CMAC generation
* @param[in]    eJobProcessing      The processing type used
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandMacGenerate
(
    VAR    (Cse_KeyHandleType,     AUTOMATIC                   ) eKeyId,
    P2CONST(uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pData,
    VAR    (uint32,                AUTOMATIC                   ) u32DataLength,
    P2VAR  (uint8,                 AUTOMATIC, CRYPTO_APPL_DATA ) pMac,
    VAR    (Crypto_ProcessingType, AUTOMATIC                   ) eJobProcessing
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse = CSE_ERC_NO_ERROR;

    u64MacDataBitLength = Crypto_Cse_GetBitLengthFromByteLength(u32DataLength);

    /* Select the Key Bank used based on the key id */
    Crypto_Cse_KeyBankSelect(&eKeyId);

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)eKeyId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)(&u64MacDataBitLength));
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)pData);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32, (uint32)pMac);
    
    /* If asynchronous mode is set to INTERRUPT, enable the CSE interrupt in the configuration register */
#if (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT)
    if(CRYPTO_PROCESSING_ASYNC == eJobProcessing)
    {
        REG_BIT_SET32(CRYPTO_CSE_CR_ADDR32, CRYPTO_CSE_CR_CIE_BIT_MASK_U32);
    }
#endif /* (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT) */

    Crypto_Cse_SendCommand(CSE_CMD_GENERATE_MAC);

    if(CRYPTO_PROCESSING_SYNC == eJobProcessing)
    {
        eOutResponse = Crypto_Cse_WaitCommandComplete();
    }

    return eOutResponse;
}

/**
* @brief        Calculates the MAC of a given message using CMAC with AES-128.
* @details      Calculates the MAC of a given input message concatenated with the incremented value of the selected secure counter.
*
* @param[in]    eKeyHandle          KeyID used to perform the cryptographic operation, because we have to write the value of the
                                    id on 4 bits the values that the KeyID can take are: User key 1 to 10 and CSE_RAM_KEY.
* @param[in]    eCounterId          The secure counter ID that will be used.
* @param[in]    u32MessageLength    Number of bytes of message on which CMAC is to be computed.
* @param[in]    pMessage            Pointer to the message buffer.
* @param[out]   pMac                Pointer to the 128-bit buffer containing the result of the CMAC generation.
* @param[out]   pVolatileCounter    Pointer to the the current VC.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandMacGenerateSecCounter
(
    VAR    (Cse_KeyHandleType, AUTOMATIC                   ) eKeyHandle,
    VAR    (Cse_CounterId,     AUTOMATIC                   ) eCounterId,
    VAR    (uint32,            AUTOMATIC                   ) u32MessageLength,
    P2CONST(uint8,             AUTOMATIC, CRYPTO_APPL_CONST) pMessage,
    P2VAR  (uint8,             AUTOMATIC, CRYPTO_APPL_DATA ) pMac,
    P2VAR  (uint32,            AUTOMATIC, CRYPTO_APPL_DATA ) pVolatileCounter
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse = CSE_ERC_NO_ERROR;
    VAR(uint32,            AUTOMATIC) u32Value     = 0U;

    u64MacDataBitLength = Crypto_Cse_GetBitLengthFromByteLength(u32MessageLength);

    /* Calculate Register CSE_P1: [28:31]Key ID [23:27]Counter ID */
    u32Value = u32Value | ((uint32)(eCounterId << 4)) | ((uint32)(eKeyHandle << 0));

    /* Select the Key Bank used based on the key id */
    Crypto_Cse_KeyBankSelect(&eKeyHandle);

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)u32Value);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)(&u64MacDataBitLength));
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)pMessage);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32, (uint32)pMac);

    Crypto_Cse_SendCommand(CSE_CMD_GENERATE_MAC_SC);

    eOutResponse = Crypto_Cse_WaitCommandComplete();
    
    if(CSE_ERC_NO_ERROR == eOutResponse)
    {
        *pVolatileCounter = REG_READ32(CRYPTO_CSE_P5_ADDR32);
    }
    return eOutResponse;
}

/**
* @brief        Calculates the MAC of a given message using CMAC with AES-128.
* @details      This function verifies the MAC of of a given message based on CMAC with the 128-bit Advanced Encryption Standard.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes. 
*
* @param[in]    eKeyId              KeyID used to perform the cryptographic operation
* @param[in]    pData               Pointer to the message buffer
* @param[in]    u32DataLength       Number of bits of message on which CMAC is to be computed
* @param[in]    u32MacLength        Number of bits of the CMAC to be compared. A macLength value of zero indicates that 
*                                   all 128-bits are to be compared.
* @param[in]    pMacRef             Pointer to the buffer containing the CMAC to be verified.
* @param[in]    eJobProcessing      The processing type used
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandMacVerify
(
    VAR     (Cse_KeyHandleType,     AUTOMATIC                   ) eKeyId,
    P2CONST (uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pData,
    VAR     (uint32,                AUTOMATIC                   ) u32DataLength,
    VAR     (uint32,                AUTOMATIC                   ) u32MacLength,
    P2CONST (uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pMacRef,
    VAR     (Crypto_ProcessingType, AUTOMATIC                   ) eJobProcessing
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse = CSE_ERC_NO_ERROR;

    u64MacDataBitLength = Crypto_Cse_GetBitLengthFromByteLength(u32DataLength);

    /* Select the Key Bank used based on the key id */
    Crypto_Cse_KeyBankSelect(&eKeyId);

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)eKeyId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)(&u64MacDataBitLength));
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)pData);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32, (uint32)pMacRef);
    REG_WRITE32(CRYPTO_CSE_P5_ADDR32, (uint32)u32MacLength);
    
    /* If asynchronous mode is set to INTERRUPT, enable the CSE interrupt in the configuration register */
#if (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT)
    if(CRYPTO_PROCESSING_ASYNC == eJobProcessing)
    {
        REG_BIT_SET32(CRYPTO_CSE_CR_ADDR32, CRYPTO_CSE_CR_CIE_BIT_MASK_U32);
    }
#endif /* (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT) */

    Crypto_Cse_SendCommand(CSE_CMD_VERIFY_MAC);

    if(CRYPTO_PROCESSING_SYNC == eJobProcessing)
    {
        eOutResponse = Crypto_Cse_WaitCommandComplete();
    }

    return eOutResponse;
}


/**
* @brief        Verifies the MAC of a given message using CMAC with AES-128.
* @details      Verifies the MAC of a given input message, concatenated with the implied value of the selected secure counter.
*
* @param[in]    eKeyHandle          KeyID used to perform the cryptographic operation, because we have to write the value of the
                                    id on 4 bits the values that the KeyID can take are: User key 1 to 10 and CSE_RAM_KEY.
* @param[in]    eCounterId          The secure counter ID that will be used.
* @param[in]    u8RlvPrtOffset      RP offset (RPO) value, to the current active RP value.
* @param[in]    u32MessageLength    Number of bytes of message on which CMAC is to be computed.
* @param[in]    pMessage            Pointer to the message buffer.
* @param[in]    pMac                Pointer to the buffer containing the CMAC to be verified.
* @param[in]    u32MacLength        The MAC length in bytes. A MAC length value of 0 indicates that all 128 bits are compared.
* @param[in]    u32VolatileCounter  Volatile Counter value from the incoming message.
* @param[out]   pVrfStatus          Pointer to the Verification status, if the MAC is correct status will be 0 otherwise it will be 1.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandMacVerifySecCounter
(
    VAR    (Cse_KeyHandleType, AUTOMATIC                   ) eKeyHandle,
    VAR    (Cse_CounterId,     AUTOMATIC                   ) eCounterId,
    VAR    (uint8,             AUTOMATIC                   ) u8RlvPrtOffset,
    VAR    (uint32,            AUTOMATIC                   ) u32MessageLength,
    P2CONST(uint8,             AUTOMATIC, CRYPTO_APPL_CONST) pMessage,
    P2VAR  (uint8,             AUTOMATIC, CRYPTO_APPL_DATA ) pMac,
    VAR    (uint8,             AUTOMATIC                   ) u32MacLength,
    VAR    (uint32,            AUTOMATIC                   ) u32VolatileCounter,
    P2VAR  (uint32,            AUTOMATIC, CRYPTO_APPL_DATA ) pVrfStatus
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse = CSE_ERC_NO_ERROR;
    VAR(uint32,            AUTOMATIC) u32Value     = 0U;

    /* Obtain meesage length in bits */
    u64MacDataBitLength = Crypto_Cse_GetBitLengthFromByteLength(u32MessageLength);

    /* Calculate Register CSE_P1: [28:31]Key ID [23:27]Counter ID CSE_P1[0:7]8-bit Rollover protection offse */
    u32Value = u32Value | ((uint32)(u8RlvPrtOffset << 24)) | ((uint32)(eCounterId << 4)) | ((uint32)(eKeyHandle << 0));

    /* Select the Key Bank used based on the key id */
    Crypto_Cse_KeyBankSelect(&eKeyHandle);

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)u32Value);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)(&u64MacDataBitLength));
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)pMessage);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32, (uint32)pMac);
    /* Obtain mac length in bits */
    u32Value = 0U;
    /* Calculate Register CSE_P5: CSE_P5[24:31]MAC length , CSE_P5[0:23]VC value from the incoming message */
    u32Value = u32Value | ((uint32)(u32VolatileCounter << 8)) | ((uint32)(Crypto_Cse_GetBitLengthFromByteLength(u32MacLength) << 0));
    REG_WRITE32(CRYPTO_CSE_P5_ADDR32, (uint32)u32Value);

    Crypto_Cse_SendCommand(CSE_CMD_VERIFY_MAC_SC);

    eOutResponse = Crypto_Cse_WaitCommandComplete();
    
    if(CSE_ERC_NO_ERROR == eOutResponse)
    {
        *pVrfStatus = REG_READ32(CRYPTO_CSE_P5_ADDR32);
    }

    return eOutResponse;
}

/**
* @brief        Updates the RAM key memory slot with a 128-bit plaintext.
* @details      The function updates the RAM key memory slot with a 128-bit plaintext. The key is loaded without the 
*               encryption and verification of the key, i.e. the key is handed over in plaintext.
*               A plain key can only be loaded into the RAM_KEY slot.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes.
*
* @param[in]    pKey    Pointer to the 128-bit buffer containing the key that needs to be copied in RAM_KEY slot.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandPlainKey
(
    P2CONST(uint8, AUTOMATIC, CRYPTO_APPL_CONST) pKey
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;

    /* Write pKey content to CSE_PRAM */
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)pKey);

    /* write command header to CSE_PRAM,  wait for the completion of the command, read and process error code */
    Crypto_Cse_SendCommand(CSE_CMD_LOAD_PLAIN_KEY);
    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}

/**
* @brief        Updates an internal key per the SHE specification.
* @details      The function updates an internal key per the SHE specification.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes. 
*
* @param[in]    keyId             The ID of the key to be updated.
* @param[in]    pKeyM1            Pointer to the 128-bit M1 message containing the UID, Key ID and Authentication Key ID.
* @param[in]    pKeyM2            Pointer to the 256-bit M2 message containing the new security flags, counter value and 
*                                 the key value, all encrypted using a derived key generated from the Authentication Key.
* @param[in]    pKeyM3            Pointer to the 128-bit M3 message containing a MAC generated over messages M1 and M2.
* @param[out]   pKeyM4            Pointer to the 256-bit M4 message is the concatenation of the UID, Key ID, Authorization Key ID, and the encrypted counter value.
* @param[out]   pKeyM5            Pointer to the 128-bit M5 message is the MAC calculated over message M4.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandLoadKey
(
    VAR    (Cse_KeyHandleType, AUTOMATIC                   ) eKeyId,
    P2CONST(uint8,             AUTOMATIC, CRYPTO_APPL_CONST) pKeyM1,
    P2CONST(uint8,             AUTOMATIC, CRYPTO_APPL_CONST) pKeyM2,
    P2CONST(uint8,             AUTOMATIC, CRYPTO_APPL_CONST) pKeyM3,
    P2VAR  (uint8,             AUTOMATIC, CRYPTO_APPL_DATA ) pKeyM4,
    P2VAR  (uint8,             AUTOMATIC, CRYPTO_APPL_DATA ) pKeyM5
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;

    /* Select the Key Bank used based on the key id */
    Crypto_Cse_KeyBankSelect(&eKeyId);

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)pKeyM1);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)pKeyM2);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)pKeyM3);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32, (uint32)pKeyM4);
    REG_WRITE32(CRYPTO_CSE_P5_ADDR32, (uint32)pKeyM5);
    
    Crypto_Cse_SendCommand(CSE_CMD_LOAD_KEY);
    eOutResponse = Crypto_Cse_WaitCommandComplete();
    
    return eOutResponse;
}

/**
* @brief        Exports the RAM_KEY into a format protected by SECRET_KEY.
* @details      The function exports the RAM_KEY into a format protected by SECRET_KEY. Only keys loaded with the 
*               CMD_LOAD_PLAIN_KEY command may be exported. The output messages are compatible with the messages used for LOAD_KEY.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes.
*
* @param[out]    pKey              Pointer where the RAM_KEY will be exported.
*                pKey[M1]          Pointer to a 128-bit buffer where the M1 parameter is to be exported
*                pKey[M2]          Pointer to a 256-bit buffer where the M2 parameter is to be exported
*                pKey[M3]          Pointer to a 128-bit buffer where the M3 parameter is to be exported
*                pKey[M4]          Pointer to a 256-bit buffer where the M4 parameter is to be exported
*                pKey[M5]          Pointer to a 128-bit buffer where the M5 parameter is to be exported
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandExportRamKey
(
    P2VAR(uint8, AUTOMATIC, CRYPTO_APPL_DATA) pKey
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)&pKey[CRYPTO_M1INDEX_U32]);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)&pKey[CRYPTO_M2INDEX_U32]);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)&pKey[CRYPTO_M3INDEX_U32]);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32, (uint32)&pKey[CRYPTO_M4INDEX_U32]);
    REG_WRITE32(CRYPTO_CSE_P5_ADDR32, (uint32)&pKey[CRYPTO_M5INDEX_U32]);
    
    Crypto_Cse_SendCommand(CSE_CMD_EXPORT_RAM_KEY);
    eOutResponse = Crypto_Cse_WaitCommandComplete();
    
    return eOutResponse;
}
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

/**
* @brief           Send debug authorization command.
* @details         Erases all user keys and sets the CSE_SR[IDB] flag which enables internal debugging if the 128-bit authorization input value
*                  is valid and no memory slots are write protected.
*
* @param[in]       pAuthorization    Message start address where the output challenge was stored
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @api
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandDebugAuth
(
    P2VAR(uint8, AUTOMATIC, CRYPTO_APPL_DATA) pAuthorization
)
{  
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)pAuthorization);

    Crypto_Cse_SendCommand(CSE_CMD_DBG_AUTH);

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}
/**
* @brief           Send debug challenge command
* @details         Generates a 128-bit random challenge output value that is used in conjunction with the DEBUG_AUTH command.
*
* @param[in]       pOutChallengeAdress - Message start address where the output challenge will be stored
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @api
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE)Crypto_Cse_SendCommandDebugChallenge
(
    P2VAR(uint8, AUTOMATIC, CRYPTO_APPL_DATA) pOutChallengeAdress
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;
    
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)pOutChallengeAdress);

    Crypto_Cse_SendCommand(CSE_CMD_DBG_CHAL);

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}

/**
* @brief           Send session challenge command
* @details         The SS_CHAL command outputs a 288-bit value consisting of a 128-bit random challenge value concatenated with the 120-bit UID, 4-bit Certificate ID,
*                  4-bit Challenge Mode, and 32 bits of zero padding.
*
* @param[in]       pOutChallengeAdress    Message start address where the output challenge will be stored
* @param[in]       u8CertificateId        Public key specified.
* @param[in]       u8ChallengeMode        0 - No keys are erased
*                                         1 - Erase all symmetric keys, excluding BOOT_MAC_KEY and BOOT_MAC
*                                         2 - Erase all installed public key certificates, including ROOT_PK and CRL
*                                         3 - Erase all installed public key certificates, including ROOT_PK and CRL
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @api
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE)Crypto_Cse_SendCommandSessionChallenge
(
    P2VAR(uint8, AUTOMATIC, CRYPTO_APPL_DATA) pOutChallengeAdress,
    VAR  (uint8, AUTOMATIC                  ) u8CertificateId,
    VAR  (uint8, AUTOMATIC                  ) u8ChallengeMode
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;

    /* Prepare session challenge command with user parameters */
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)u8CertificateId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)u8ChallengeMode);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)pOutChallengeAdress);
    
    Crypto_Cse_SendCommand(CSE_CMD_DBG_CHAL);

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}

/**
* @brief           Send command for MP compression.
* @details         One-way compression function used to derive a 128-bit output from a given message.
*
* @param[in]       pInputKeyAddr    Message start address.
* @param[in]       pInputKeyLen     Message length (bytes) address.
* @param[out]      pOutputKeyAddr   Output adress buffer.
* @param[in]       eJobProcessing   The processing type used.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @api
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandMPCompression
(
    P2CONST(uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pInputKeyAddr, 
    P2VAR  (uint64,                AUTOMATIC, CRYPTO_APPL_DATA ) pInputKeyLen,
    P2VAR  (uint8,                 AUTOMATIC, CRYPTO_APPL_DATA ) pOutputKeyAddr,
    VAR    (Crypto_ProcessingType, AUTOMATIC                   ) eJobProcessing
)
{  
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse = CSE_ERC_NO_ERROR;
    
    u64MPLength = (uint64)Crypto_Cse_GetBitLengthFromByteLength((*pInputKeyLen));
    /* If asynchronous mode is set to INTERRUPT, enable the CSE interrupt in the configuration register */
#if (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT)
    if(CRYPTO_PROCESSING_ASYNC == eJobProcessing)
    {
        REG_BIT_SET32(CRYPTO_CSE_CR_ADDR32, CRYPTO_CSE_CR_CIE_BIT_MASK_U32);
    }
#endif /* (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT) */
    
    /* Prepare Input registers */
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)(&u64MPLength));
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)pInputKeyAddr);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)pOutputKeyAddr);

    Crypto_Cse_SendCommand(CSE_CMD_MP_COMPRESS);

    if(CRYPTO_PROCESSING_SYNC == eJobProcessing)
    {
        eOutResponse = Crypto_Cse_WaitCommandComplete();
    }
    return eOutResponse;
}


/**
* @brief           Send command for SHA-256.
* @details         The SHA-256_HASH command generates the hash over the input message based on the RSA SSA-PKCS1-V1_5 standard.
*
* @param[in]       pInputKeyAddr    Message start address.
* @param[in]       pInputKeyLen     Message length (bits) address.
* @param[out]      pOutputKeyAddr   Output adress buffer.
* @param[in]       eJobProcessing   The processing type used.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @api
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandSHA_256
(
    P2CONST(uint8,                 AUTOMATIC, CRYPTO_APPL_CONST) pInputKeyAddr, 
    P2VAR  (uint64,                AUTOMATIC, CRYPTO_APPL_DATA ) pInputKeyLen,
    P2VAR  (uint8,                 AUTOMATIC, CRYPTO_APPL_DATA ) pOutputKeyAddr,
    VAR    (Crypto_ProcessingType, AUTOMATIC                   ) eJobProcessing
)
{  
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse = CSE_ERC_NO_ERROR;
    
    u64MPLength = Crypto_Cse_GetBitLengthFromByteLength(*pInputKeyLen);
    /* If asynchronous mode is set to INTERRUPT, enable the CSE interrupt in the configuration register */
#if (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT)
    if(CRYPTO_PROCESSING_ASYNC == eJobProcessing)
    {
        REG_BIT_SET32(CRYPTO_CSE_CR_ADDR32, CRYPTO_CSE_CR_CIE_BIT_MASK_U32);
    }
#endif /* (STD_ON == CRYPTO_ASYNC_PROCESS_INTERRUPT) */
    
    /* Prepare Input registers */
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)(&u64MPLength));
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)pInputKeyAddr);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32, (uint32)pOutputKeyAddr);

    Crypto_Cse_SendCommand(CSE_CMD_SHA_256_HASH);

    if(CRYPTO_PROCESSING_SYNC == eJobProcessing)
    {
        eOutResponse = Crypto_Cse_WaitCommandComplete();
    }
    return eOutResponse;
}

#if (STD_ON == CRYPTO_KEYS_EXIST)
/**
* @brief           Configure Secure Counter.
* @details         The CFG_SEC_CNT command initializes a secure counter and associates it with the given counter ID.
*
* @param[in]       u32CounterId      Counter ID with range[0-31].
* @param[in]       u32RolloverValue  Rollover Value with range [9-24].
* @param[out]      pStatus           Status set to 0 when a new counter is initialized and set to 1 when an existing counter is reused.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @api
*
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandCfgSecCounter
(
    VAR  (Cse_CounterId, AUTOMATIC                  ) u32CounterId,
    VAR  (uint32,        AUTOMATIC                  ) u32RolloverValue,
    P2VAR(uint32,        AUTOMATIC, CRYPTO_APPL_DATA) pStatus
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;

    /* Prepare Input */
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)u32CounterId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32, (uint32)u32RolloverValue);
    
    /* Send command */
    Crypto_Cse_SendCommand(CSE_CMD_CFG_SEC_CNT);
    
    /* Wait for the command to complete */
    eOutResponse = Crypto_Cse_WaitCommandComplete();
    
    /* Check if the command was executed successfully then read the value of the status */
    if(CSE_ERC_NO_ERROR == eOutResponse)
    {
        *pStatus = REG_READ32(CRYPTO_CSE_P3_ADDR32);
    }

    return eOutResponse;
}

/**
* @brief         Send Load plain text key command.
* @details       The LOAD_PT_KEY command loads a plaintext key into NVM.
*
* @param[in]     eKeyId         The input key ID must be in the range [0x1 – 0xD].
* @param[in]     pKeyAddr       Input key buffer address.
* @param[in]     u32KeyFlags    Security flags specific to each key slot.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre         Driver must be initialized.
*
*/
FUNC (Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandLoadPlainTextKey
(
    VAR    (Cse_KeyHandleType, AUTOMATIC                   ) eKeyId,
    P2CONST(uint8,             AUTOMATIC, CRYPTO_APPL_CONST) pKeyAddr,
    VAR    (uint32,            AUTOMATIC                   ) u32KeyFlags
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC)eOutResponse;

    /* Select the Key Bank used based on the key id */
    Crypto_Cse_KeyBankSelect(&eKeyId);

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32,  (uint32)eKeyId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32,  (uint32)pKeyAddr);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32,  (uint32)u32KeyFlags);

    Crypto_Cse_SendCommand(CSE_CMD_LOAD_PT_KEY);

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}

/**
* @brief         Send Delete plain text key command.
* @details       The DELETE_PT_KEY command clears plaintext key from RAM.
*
* @param[in]     u8KeyId    The input key ID must be in the range [0x1 – 0xD]
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre         Driver must be initialized.
*
*/
FUNC (Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandDeletePlainTextKey
(
    VAR(uint8, AUTOMATIC) u8KeyId
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC)eOutResponse;

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)u8KeyId);

    Crypto_Cse_SendCommand(CSE_CMD_DELETE_PT_KEY);

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

/**
* @brief        Initializes the seed and derives a key for the PRNG.
* @details      This function initializes the seed and derives a key for the PRNG. 
*               The function must be called before CMD_RND after every power cycle or reset.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes.
*
* @param[in]    None
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandInitRng(void)
{  
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;
    
    Crypto_Cse_SendCommand(CSE_CMD_INIT_RNG);
    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}


/**
* @brief        Extends the seed of the PRNG by compressing the former seed value and the supplied entropy into a new seed.
* @details      This function extends the seed of the PRNG by compressing the former seed value and the supplied 
*               entropy into a new seed which will be used to generate the following random numbers. The random number 
*               generator has to be initialized by Cse_InitRng() before the seed can be extended.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes.
*
* @param[in]    pEntropy    Pointer to a 128-bit buffer containing the entropy
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandExtendPrngSeed
(
    P2CONST(uint8, AUTOMATIC, CRYPTO_APPL_CONST) pEntropy
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)pEntropy);
    
    Crypto_Cse_SendCommand(CSE_CMD_EXTEND_SEED);
    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}

/**
* @brief        Generates a vector of 128 random bits.
* @details      The function returns a vector of 128 random bits. The random number generator has to be 
*               initialized by Cse_InitRng() before random numbers can be supplied.
*               This function does not work for VLRP (Very Low Power) and HSRUN (High Speed Run) modes.
*
* @param[out]   pRnd    Pointer to a 128-bit buffer where the generated random number is to be stored.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandGenerateRnd
(
    P2VAR(uint8, AUTOMATIC, CRYPTO_APPL_CONST) pRnd
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;

    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)pRnd);
    
    Crypto_Cse_SendCommand(CSE_CMD_RND); 
    eOutResponse = Crypto_Cse_WaitCommandComplete();
    
    return eOutResponse;
}

/**
* @brief        Cancel command.
* @details      Function will try to cancel the command that is processed.
*
* @param[in]    None.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandCancel(void)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;
    
    Crypto_Cse_SendCommand(CSE_CMD_CANCEL); 
    eOutResponse = Crypto_Cse_WaitCommandComplete();
    
    return eOutResponse;
}

/**
* @brief        Generates UID value.
* @details      UID value will be written in output buffer.A value of 0 is returned for the
*               MAC if the MASTER_ECU_KEY slot is empty. The UID output is a 128-bit value with
*               the 8 least significant bits set to 0.
*
* @param[in]    pUidResultAddr          Pointer to a 128-bit buffer where UID will be stored
* @param[in]    pMacAddr                Pointer to a 128-bit buffer where MAC key will be stored
* @param[in]    pSregAddr               Pointer to a 128-bit buffer where status register will be stored 
* @param[in]    pChallenge              Pointer to a 128-bit buffer where challenge is stored
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre          Driver must be initialized.
*
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandGetId
(
    P2VAR(uint8,  AUTOMATIC, CRYPTO_APPL_DATA) pUidResultAddr,
    P2VAR(uint8,  AUTOMATIC, CRYPTO_APPL_DATA) pMacAddr,
    P2VAR(uint8,  AUTOMATIC, CRYPTO_APPL_DATA) pSregAddr,
    P2VAR(uint8,  AUTOMATIC, CRYPTO_APPL_DATA) pChallenge
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC) eOutResponse;

    /* Prepare user input parameters */
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32,  (uint32)pChallenge);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32,  (uint32)pUidResultAddr);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32,  (uint32)pSregAddr);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32,  (uint32)pMacAddr);

    Crypto_Cse_SendCommand(CSE_CMD_GET_ID); 

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}

/**
* @brief         Send Verify Signature command.
* @details       The VERIFY_SIGNATURE command verifies a signed message using the RSA SSA- PKCS1-V1_5 standard.
*
* @param[in]     u8AuthCertifId    - authorization key 
* @param[in]     pMessAddr         - input message address
* @param[in]     u32MessLen        - length of input message 
* @param[in]     pSignatureAddr    - Signature address
* @param[in]     bClearBootMac     - BOOT_MAC input can be set to 1 to optionally erase the current BOOT_MAC value after a signature match
* @param[out]    pVerifStatus      - Verification status 
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre         
*
*/
FUNC (Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendVerifySignature
(
    VAR    (uint8,  AUTOMATIC                   ) u8AuthCertifId,
    P2CONST(uint8,  AUTOMATIC, CRYPTO_APPL_CONST) pMessAddr,
    VAR    (uint32, AUTOMATIC                   ) u32MessLen,
    P2CONST(uint8,  AUTOMATIC, CRYPTO_APPL_CONST) pSignatureAddr,
    VAR    (boolean,AUTOMATIC                   ) bClearBootMac,
    P2VAR  (uint32,  AUTOMATIC, CRYPTO_APPL_DATA) pVerifStatus
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC)eOutResponse  = CSE_ERC_GENERAL_ERROR;
    
    u64MessLength = Crypto_Cse_GetBitLengthFromByteLength(u32MessLen);

    /* The Clear BOOT_MAC input can be set to 1 to optionally erase the current BOOT_MAC value after a signature match.*/
    REG_WRITE32(CRYPTO_CSE_P5_ADDR32,  (uint32)bClearBootMac);
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32,  (uint32)u8AuthCertifId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32,  (uint32)pMessAddr);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32,  (uint32)(&u64MessLength));
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32,  (uint32)pSignatureAddr);
    
    Crypto_Cse_SendCommand(CSE_CMD_VERIFY_SIGNATURE);

    eOutResponse = Crypto_Cse_WaitCommandComplete();
    
    /*If the input signature matches the signature calculated over the message, the CSE_P5 register is set to 0*/
    *pVerifStatus  = REG_READ32(CRYPTO_CSE_P5_ADDR32);
    
    return eOutResponse;
}

/**
* @brief         Send Install Certificate command 
* @details       The INSTALL_CERTIFICATE command authenticates a public key certificate 
*                stored in system flash memory and enables the public key to be used 
*                for subsequent CSE operations.
*
* @param[in]     u8CertifId        Certificate ID
* @param[in]     u8AuthCertifId    Authorization ID
* @param[in]     pCertifAddr       Certificate address
* @param[in]     u8CertifType      Must be set to 0 when installing public key certificates and must be set to 1 when installing a CR
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre         
*
*/
FUNC (Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendInstallCertificate
(
    VAR    (uint8,  AUTOMATIC                   ) u8CertifId,
    VAR    (uint8,  AUTOMATIC                   ) u8AuthCertifId,
    P2CONST(uint8,  AUTOMATIC, CRYPTO_APPL_CONST) pCertifAddr,
    VAR    (uint8,  AUTOMATIC                   ) u8CertifType
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC)eOutResponse  = CSE_ERC_GENERAL_ERROR;
    
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32,  (uint32)u8CertifId);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32,  (uint32)u8AuthCertifId);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32,  (uint32)pCertifAddr);
    REG_WRITE32(CRYPTO_CSE_P4_ADDR32,  (uint32)u8CertifType);
    
    Crypto_Cse_SendCommand(CSE_CMD_INSTALL_CERTIFICATE);
    
    eOutResponse = Crypto_Cse_WaitCommandComplete();
    
    return eOutResponse;
}

/**
* @brief         Send command Backup Restore Cleanup Status.
* @details       The BRCS command provides 4 separate functions based on the mode input value.
*
* @param[in]     eBrcsMode             Mode.
* @param[inout]  pImageAddress         Backup image address.
* @param[out]    pKeySlotStatus        Slot usage status.
* @param[out]    pCounterSlotStatus    Status of counter slots.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre         
*
*/
FUNC (Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendBrcsCommand
(
    VAR  (Crypto_BrcsModeType, AUTOMATIC                  ) eBrcsMode,
    P2VAR(uint32,              AUTOMATIC, CRYPTO_APPL_DATA) pImageAddress,
    P2VAR(uint32,              AUTOMATIC, CRYPTO_APPL_DATA) pKeySlotStatus,
    P2VAR(uint32,              AUTOMATIC, CRYPTO_APPL_DATA) pCounterSlotStatus
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC)eOutResponse;
    
    /* Prepare Update firmware command with user inputs */
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32,  (uint32)eBrcsMode);
    
    /* P2 is input only in Mode = 1 (Backup)*/
    if ( (Crypto_BrcsModeType)BACKUP == eBrcsMode)
    {
        REG_WRITE32(CRYPTO_CSE_P2_ADDR32,  (uint32)pImageAddress);
    }

    Crypto_Cse_SendCommand(CSE_CMD_BRCS);

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    /* Check if the command was executed successfully then read the value of the status */
    if(CSE_ERC_NO_ERROR == eOutResponse)
    {
        /* Read output results and write them into output parameters */
        *pKeySlotStatus     = (uint32)REG_READ32(CRYPTO_CSE_P3_ADDR32);
        *pCounterSlotStatus = (uint32)REG_READ32(CRYPTO_CSE_P4_ADDR32);

        if ( (Crypto_BrcsModeType)BACKUP != eBrcsMode )
        {
            *pImageAddress = (uint32)REG_READ32(CRYPTO_CSE_P2_ADDR32);
        }
    }

    return eOutResponse;
}

/**
* @brief         Send command update firmware.
* @details       The UPDATE_FIRMWARE command provides a secure method to update CSE firmware in the field.
*
* @param[in]     pFirmwareAddr          The firmware address input must point to the new encrypted firmware image.
* @param[in]     pSignatureAddr         Signature address.
* @param[in]     u8AuthCertifId         CSE_P3 selects the public key certificate to use for signature verification of the firmware update image.
* @param[out]    pNewFirmVersion        New firmware version is returned in CSE_P4.
* @param[out]    pCurrentFirmVersion    Old firmware version is returned in CSE_P5.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre         
*
*/
FUNC (Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendUpdateFirmware
(
    P2VAR(uint32, AUTOMATIC,CRYPTO_APPL_DATA)pFirmwareAddr,
    P2VAR(uint32, AUTOMATIC,CRYPTO_APPL_DATA)pSignatureAddr,
    VAR  (uint8,  AUTOMATIC                 )u8AuthCertifId,
    P2VAR(uint32, AUTOMATIC,CRYPTO_APPL_DATA)pNewFirmVersion,
    P2VAR(uint32, AUTOMATIC,CRYPTO_APPL_DATA)pCurrentFirmVersion
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC)eOutResponse;
    
    /* Prepare Update firmware command with user inputs */
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32,  (uint32)pFirmwareAddr);
    REG_WRITE32(CRYPTO_CSE_P2_ADDR32,  (uint32)pSignatureAddr);
    REG_WRITE32(CRYPTO_CSE_P3_ADDR32,  (uint32)u8AuthCertifId);

    Crypto_Cse_SendCommand(CSE_CMD_UPDATE_FIRMWARE);

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    /* Check if the command was executed successfully then read the value of the status */
    if(CSE_ERC_NO_ERROR == eOutResponse)
    {
        /* Read output results and write them into output parameters */
        *pNewFirmVersion     = (uint32)REG_READ32(CRYPTO_CSE_P4_ADDR32);
        *pCurrentFirmVersion = (uint32)REG_READ32(CRYPTO_CSE_P5_ADDR32);
    }

    return eOutResponse;
}


/**
* @brief           Generates a vector of 128 ture random bits.
* @details         The function returns a vector of 128 ture random bits. 
*                  CSE_CR[DIV] field must be properly configured before this command is executed.
*                  There is a very small probability that this command may return a TRNG error (EC = 0x12) even when the TRNG is operating properly.
*                  This function does not work for VLRP (Very Low Power).
*
* @param[out]      pTrueRandomValue: The address where the random value will be stored.
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
* @api
*
* @pre          Driver must be initialized.
*
*/
/**
* @violates @ref Crypto_Ipw_c_REF_3 Violates MISRA 2004 Required Rule 8.10 could be made static
*/
FUNC(Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandGenerateTrueRandom
(
    P2VAR(uint8, AUTOMATIC, CRYPTO_APPL_DATA) pTrueRandomValue
)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC)eOutResponse;

    /*Prepare command for TRNG*/
    REG_WRITE32(CRYPTO_CSE_P1_ADDR32, (uint32)pTrueRandomValue);

    Crypto_Cse_SendCommand(CSE_CMD_TRNG_RND);

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}


/**
* @brief         Send BOOT OK command 
* @details       The BOOT_OK command sets the CSE_SR[BFN] flag and leaves the CSE_SR[BOK]
*                flag set to confirm successful completion of the secure boot processes.
*                This enables the
*                use of memory slots that have the BOOT_PROT flag set if they are not disabled for some
*                other reason.
*
* @param[in]     void
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*              
* @pre         
*
*/
FUNC (Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandBootOk(void)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC)eOutResponse;
    
    Crypto_Cse_SendCommand(CSE_CMD_BOOT_OK);

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}

/**
* @brief         Send Boot Failure command 
* @details       The BOOT_FAILURE command sets the CSE_SR[BFN] flag and clears the
*                CSE_SR[BOK] flag to disable use of memory slots that have the BOOT_PROT flag set.
*
* @param[in]     void
*
* @return          Result of the operation.
*                   Cse_ErrorCodeType     Error Code after command execution
*                                     The request was executed succesfully if the error code is CSE_ERC_NO_ERROR.
*
* @pre         
*
*/
FUNC (Cse_ErrorCodeType, CRYPTO_CODE) Crypto_Cse_SendCommandBootFailure(void)
{
    VAR(Cse_ErrorCodeType, AUTOMATIC)eOutResponse;
    
    Crypto_Cse_SendCommand(CSE_CMD_BOOT_FAILURE);

    eOutResponse = Crypto_Cse_WaitCommandComplete();

    return eOutResponse;
}

#define CRYPTO_STOP_SEC_CODE
/**
* @violates @ref Crypto_Cse_Cmd_c_REF_1 #include directives should only be preceded by preprocessor
* directives or comments.
*
* @violates @ref Crypto_Cse_Cmd_c_REF_2 Precautions shall be taken in order to prevent the contents
* of a header file being included more than once.
*/
#include "Crypto_MemMap.h"

#ifdef __cplusplus
}
#endif

/** @} */