/*******************************************************************************
* @file             main.c
*
* @version          1.0.0
*
* @brief            Integration Framework -  main function
*
* Copyright (C) 2026 Geehy Semiconductor
*
* You may not use this file except in compliance with the GEEHY COPYRIGHT NOTICE
* (Geehy Semiconductor Software License Agreement).
*
* The program is only for reference, which is distributed in the hope that it
* will be useful and instructional for customers to develop their software.
* Unless required by applicable law or agreed to in writing, the program is
* distributed on an "AS IS" BASIS, WITHOUT ANY WARRANTY OR CONDITIONS OF ANY
* KIND, either express or implied. See the Geehy Semiconductor Software License Agreement for
* the governing permissions and limitations under the License.
*
*******************************************************************************/

#ifdef __cplusplus
extern "C"{
#endif


#include "CDD_Usart.h"
#include "Mcu.h"
#include "Port.h"
#include "Crypto.h"
#include "Crypto_App.h"


/***************************************************************************
                        GLOBAL VARIABLES                                    
***************************************************************************/ 
/* AES-128, the key must be 128 bits (16 bytes) */
CONST(uint8, AUTOMATIC) AES128Key[16] = {0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36,
                          0x37, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x38};

VAR(uint8, AUTOMATIC) AES192key[24] = {0x9A, 0xBC, 0xDE, 0xF0, 0x9A, 0xBC, 0xDE, 0xF0,
                         0x9A, 0xBC, 0xDE, 0xF0, 0x9A, 0xBC, 0xDE, 0xF0,
                         0x9A, 0xBC, 0xDE, 0xF0, 0x9A, 0xBC, 0xDE, 0xF0
                        };

VAR(uint8, AUTOMATIC) AES256key[32] = {0x9A, 0xBC, 0xDE, 0xF0, 0x9A, 0xBC, 0xDE, 0xF0,
                         0x9A, 0xBC, 0xDE, 0xF0, 0x9A, 0xBC, 0xDE, 0xF0,
                         0x9A, 0xBC, 0xDE, 0xF0, 0x9A, 0xBC, 0xDE, 0xF0,
                         0x9A, 0xBC, 0xDE, 0xF0, 0x9A, 0xBC, 0xDE, 0xF0
                        };

VAR(uint8, AUTOMATIC) AES256key_Initial[32] = {0x00};
/* initialization vector for CBC mode */
VAR(uint8, AUTOMATIC) IV_1[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
                   };
/* initialization vector for CMAC mode */
static CONST(uint8, AUTOMATIC) CmacIvAllZeros[16] = {0};

/* user data */
VAR(uint8, AUTOMATIC) unencryptedData[16] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a};
/* encrypted data */
VAR(uint8, AUTOMATIC) encryptedData[16] = {0xDB, 0x30, 0x2D, 0xD6, 0x80, 0x36, 0xC0, 0x50,
                                 0xAC, 0x76, 0xA1, 0xE8, 0x39, 0x75, 0x75, 0x85};
VAR(uint8, AUTOMATIC) encryptedData_192[16] = {0xB1, 0x24, 0x25, 0x08, 0x5F, 0xDF, 0x2B, 0xEF,
                                 0x63, 0x5C, 0x67, 0x31, 0x11, 0x9F, 0x02, 0xC8};

/*******************************************************************************
                            LOCAL DEFINES AND MACROS
*******************************************************************************/

#define  AES_BLOCKSIZE   16

#define  TEST_AES_CTR
#define  TEST_AES_CMAC
#define  TEST_AES_CBC
#define  TEST_AES_ECB
#define  TEST_AES_MPC
#define  TEST_RNG
#define  TEST_HASH


/**************************************************************************
                    GLOBAL FUNCTION
**************************************************************************/

FUNC(void, CRYPTO_CODE) delay(uint32 value)
{
    while(value--);
}
/*!
 * @brief       configure encryption tasks
 *
 * @param       Job:             the job ptr
 *              TestJob:         job task
 *              CryptoKeyId:     Crypto Key Id
 *              InputPtr:        Input value Ptr
 *              InputLength:     Input value Length
 *              OutputPtr:       Output value Ptr
 *              OutputLengthPtr: Output value Length Ptr
 *              ProcessingType:  processing type
 *
 * @retval      None
 *
 * @note        Note
 */

void PrepareJob(Crypto_JobType* Job,
                CryptoTestJobType TestJob,
                uint32 CryptoKeyId,
                uint32 KeyElementId,
                const uint8* InputPtr,
                uint32 InputLength,
                uint8* OutputPtr,
                uint32* OutputLengthPtr,
                Crypto_ProcessingType ProcessingType)
{
    Job->cryptoKeyId = CryptoKeyId;
    Job->KeyElementId = KeyElementId;
    Job->jobPrimitiveInputOutput.inputPtr = InputPtr;
    Job->jobPrimitiveInputOutput.inputLength = InputLength;
    Job->jobPrimitiveInputOutput.outputPtr = OutputPtr;
    Job->jobPrimitiveInputOutput.outputLengthPtr = OutputLengthPtr;

    Crypto_PrimitiveInfoType* primInfo = NULL_PTR;
    switch (TestJob)
    {
    case TEST_ENCRYPT_AES_ECB:
        primInfo = &g_primAesEcbEncrypt;
        break;
    case TEST_DECRYPT_AES_ECB:
        primInfo = &g_primAesEcbDecrypt;
        break;
    case TEST_ENCRYPT_AES_CBC:
        primInfo = &g_primAesCbcEncrypt;
        break;
    case TEST_DECRYPT_AES_CBC:
        primInfo = &g_primAesCbcDecrypt;
        break;
    case TEST_ENCRYPT_AES_CTR:
        primInfo = &g_primAesCtrEncrypt;
        break;
    case TEST_DECRYPT_AES_CTR:
        primInfo = &g_primAesCtrDecrypt;
                break;  
    case TEST_RANDOM_GENERATE:
        primInfo = &g_primRandom;
        break;
    case TEST_CMAC_GENERATE:
        primInfo = &g_primGenerateCmac;
        break;
    case TEST_CMAC_VERIFY:
        primInfo = &g_primVerifyCmac;
        break;
    case TEST_HASH_GENERATE:
        primInfo = &g_primHash;
    break;
    case TEST_MPC_GENERATE:
        primInfo = &g_primMpc;
        break;
    default:
        printf("Error: Not supported test job %d\r\n", TestJob);
        break;
    }

    if (ProcessingType == CRYPTO_PROCESSING_SYNC)
    {
        g_jobPrimSync.primitiveInfo = primInfo;
        Job->jobPrimitiveInfo = &g_jobPrimSync;
    }
    else
    {
        g_jobPrimAsync.primitiveInfo = primInfo;
        Job->jobPrimitiveInfo = &g_jobPrimAsync;
    }
}

/*!
 * @brief       Test prepare job
 *
 * @param       TestJob:         job task
 *              CryptoKeyId:     Crypto Key Id
 *              InputPtr:        Input value Ptr
 *              InputLength:     Input value Length
 *              OutputPtr:       Output value Ptr
 *              OutputLengthPtr: Output value Length Ptr
 *              ProcessingType:  processing type
 *
 * @retval      None
 *
 * @note        Note
 */
Crypto_JobType* PrepareTestJob(CryptoTestJobType TestJob,
                               uint32 CryptoKeyId,
                               uint32 KeyElementId,
                               const uint8* InputPtr,
                               uint32 InputLength,
                               uint8* OutputPtr,
                               uint32* OutputLengthPtr,
                               Crypto_ProcessingType ProcessingType)
{
    PrepareJob(&g_cryptoJob1, TestJob, CryptoKeyId, KeyElementId,InputPtr, InputLength,
               OutputPtr, OutputLengthPtr, ProcessingType);
    return &g_cryptoJob1;
}

int main()
{ 

#if defined(TEST_AES_CTR) || defined(TEST_AES_ECB) || defined(TEST_AES_CBC) || defined(TEST_AES_CMAC) || defined(TEST_AES_MPC) || defined(TEST_RNG) || defined(TEST_HASH)
    VAR(uint8, AUTOMATIC)  flag = 0;
    VAR(uint8, AUTOMATIC) i = 0;
    P2VAR(Crypto_JobType, AUTOMATIC, CRYPTO_APPL_DATA) job = NULL_PTR;
#endif
    
    Mcu_Init(&g_mcuConfig);
    Mcu_InitClock(McuClockSettingConfig_0);
    Port_Init(&g_portConfig);
    Usart_Init(g_usartConfg);
    
    NVIC_EnableIRQ(USART2_IRQn);
    NVIC_EnableIRQ(USART1_IRQn);
    NVIC_EnableIRQ(SHA256_IRQn);
    NVIC_EnableIRQ(AES256_IRQn);
    NVIC_EnableIRQ(TRNG_IRQn);

    Usart_Init(g_usartConfg);
    printf("\r\n");
    printf("G32A1085 Crypto demo start!\r\n");
    
    Crypto_Init(NULL_PTR);

#ifdef TEST_AES_CTR
    printf("\r\n");
    printf("********************* AES mode CTR  *************************\r\n");
    #define CTR_TEST_LENGTH   16
    #define CTR_TEST_BLKNUM   (CTR_TEST_LENGTH + AES_BLOCKSIZE - 1)/ AES_BLOCKSIZE
    static VAR(uint8, AUTOMATIC) aes256CtrInputTestData[CTR_TEST_LENGTH];
    for(i = 0; i < sizeof(aes256CtrInputTestData); i++)
    {
        aes256CtrInputTestData[i] = i;
    }
    VAR(uint8, AUTOMATIC) outputCtrEncryptedtext[CTR_TEST_BLKNUM * 16] = {0};
    VAR(uint32, AUTOMATIC) outputCtrEncryptedLength = sizeof(outputCtrEncryptedtext);
    VAR(uint8, AUTOMATIC) outputCtrDecryptedtext[CTR_TEST_LENGTH] = {0};
    VAR(uint32, AUTOMATIC) outputCtrDecryptedLength = sizeof(outputCtrDecryptedtext);
    
   /* set aeskey as the key */
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_256,
                         AES256key,
                         sizeof(AES256key));
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_192,
                         AES192key,
                         sizeof(AES192key));
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_128,
                         AES128Key,
                         sizeof(AES128Key));
    /* set iv as the key */
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYELEMENT_IV,
                         IV_1,
                         sizeof(IV_1));
    
    /* set the key to be valid */
    Crypto_KeySetValid(CRYPTO_KEY_1);
    for(int testNum = 1; testNum < 4; testNum++)
    {
        /* according to the set parameters,configure encryption tasks */
        job = PrepareTestJob(TEST_ENCRYPT_AES_CTR,
                             CRYPTO_KEY_1,
                             testNum,
                             aes256CtrInputTestData,
                             sizeof(aes256CtrInputTestData),
                             outputCtrEncryptedtext,
                             &outputCtrEncryptedLength,
                             CRYPTO_PROCESSING_SYNC);
        
        /* perform encryption tasks */
        Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);
        printf("\r\n");
        /* check if the generated encrypted data is correct */
        printf("The encrypted data:");
        for (int tempSize = 0; tempSize < outputCtrEncryptedLength; tempSize++)
        {
            printf(" %02X", outputCtrEncryptedtext[tempSize]);
        }
        printf("\r\n");

        /* configure decryption task */
        job = PrepareTestJob(TEST_DECRYPT_AES_CTR,
                             CRYPTO_KEY_1,
                             testNum,
                             outputCtrEncryptedtext,
                             CTR_TEST_LENGTH,
                             outputCtrDecryptedtext,
                             &outputCtrDecryptedLength,
                             CRYPTO_PROCESSING_SYNC);
        
        /* perform decryption tasks */
        Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);
        
        /* check if the generated decrypted data is correct */
                             
        printf("The decrypted data:");
        for (int tempSize = 0; tempSize < CTR_TEST_LENGTH; tempSize++)
        {
            if (outputCtrDecryptedtext[tempSize] != aes256CtrInputTestData[tempSize])
            {
                flag = 1; 
            }
            printf(" %02X", outputCtrDecryptedtext[tempSize]);
        }
        printf("\r\n");
        
        /* encryption and decryption are error-free */
        if (flag == 0)
        {
            printf("demo ok!");
        }
        else
        {
            printf("demo error!");
        }
    }
    printf("\r\n------------------ IntegrationAppCrypto_AES_CTR End------------------\r\n");
#endif

#ifdef TEST_AES_ECB
    printf("\r\n");
    printf("********************* AES mode ECB  *************************\r\n");
    #define ECB_TEST_LENGTH   (AES_BLOCKSIZE * 1)
    static VAR(uint8, AUTOMATIC) aes256EcbInputTestData[ECB_TEST_LENGTH];
    for(i = 0; i<sizeof(aes256EcbInputTestData); i++)
    {
        aes256EcbInputTestData[i] = i;
    }
    VAR(uint8, AUTOMATIC) outputEcbEncryptedtext[ECB_TEST_LENGTH] = {0};
    VAR(uint32, AUTOMATIC) outputEcbEncryptedLength = sizeof(outputEcbEncryptedtext);
    VAR(uint8, AUTOMATIC) outputEcbDecryptedtext[ECB_TEST_LENGTH] = {0};
    VAR(uint32, AUTOMATIC) outputEcbDecryptedLength = sizeof(outputEcbDecryptedtext);

   /* set aeskey as the key */
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_256,
                         AES256key,
                         sizeof(AES256key));
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_192,
                         AES192key,
                         sizeof(AES192key));
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_128,
                         AES128Key,
                         sizeof(AES128Key));
    
    /* set the key to be valid */
    Crypto_KeySetValid(CRYPTO_KEY_1);
    for(int testNum = 1; testNum < 4; testNum++)
    {
        flag = 0;
        /* according to the set parameters,configure encryption tasks */
        job = PrepareTestJob(TEST_ENCRYPT_AES_ECB,
                             CRYPTO_KEY_1,
                             testNum,
                             aes256EcbInputTestData,
                             sizeof(aes256EcbInputTestData),
                             outputEcbEncryptedtext,
                             &outputEcbEncryptedLength,
                             CRYPTO_PROCESSING_SYNC);
        
        /* perform encryption tasks */
        Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);
        printf("\r\n");
        /* check if the generated encrypted data is correct */
        printf("The encrypted data:");
        for (int tempSize = 0; tempSize < ECB_TEST_LENGTH; tempSize++)
        {
            printf(" %02X", outputEcbEncryptedtext[tempSize]);
        }
        printf("\r\n");
        
        /* configure decryption task */
        job = PrepareTestJob(TEST_DECRYPT_AES_ECB,
                             CRYPTO_KEY_1,
                             testNum,
                             outputEcbEncryptedtext,
                             sizeof(outputEcbEncryptedtext),
                             outputEcbDecryptedtext,
                             &outputEcbDecryptedLength,
                             CRYPTO_PROCESSING_SYNC);
        
        /* perform decryption tasks */
        Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);
        
        /* check if the generated decrypted data is correct */
                             
        printf("The decrypted data:");
        for (int tempSize = 0; tempSize < ECB_TEST_LENGTH; tempSize++)
        {
            if (outputEcbDecryptedtext[tempSize] != aes256EcbInputTestData[tempSize])
            {
                flag = 1; 
            }
            printf(" %02X", outputEcbDecryptedtext[tempSize]);
        }
        printf("\r\n");
        
        /* encryption and decryption are error-free */
        if (flag == 0)
        {
            printf("demo ok!");
        }
        else
        {
            printf("demo error!");

        }
    }
    printf("\r\n------------------ IntegrationAppCrypto_AES_ECB End------------------\r\n");
#endif

#ifdef TEST_AES_CBC
    printf("\r\n");
    printf("********************* AES mode CBC  *************************\r\n");
    #define CBC_TEST_LENGTH   (AES_BLOCKSIZE * 1)
    static VAR(uint8, AUTOMATIC) aes256CbcInputTestData[CBC_TEST_LENGTH];
    for(i = 0; i<sizeof(aes256CbcInputTestData); i++)
    {
        aes256CbcInputTestData[i] = i;
    }
    VAR(uint8, AUTOMATIC) outputCbcEncryptedtext[CBC_TEST_LENGTH] = {0};
    VAR(uint32, AUTOMATIC) outputCbcEncryptedLength = sizeof(outputCbcEncryptedtext);
    VAR(uint8, AUTOMATIC) outputCbcDecryptedtext[CBC_TEST_LENGTH] = {0};
    VAR(uint32, AUTOMATIC) outputCbcDecryptedLength = sizeof(outputCbcDecryptedtext);

    /* set aeskey as the key */
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_256,
                         AES256key,
                         sizeof(AES256key));
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_192,
                         AES192key,
                         sizeof(AES192key));
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_128,
                         AES128Key,
                         sizeof(AES128Key));
    /* set iv as the key */
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYELEMENT_IV,
                         IV_1,
                         sizeof(IV_1));
    
    /* set the key to be valid */
    Crypto_KeySetValid(CRYPTO_KEY_1);
    for(int testNum = 1; testNum < 4; testNum++)
    {
        /* according to the set parameters,configure encryption tasks */
        job = PrepareTestJob(TEST_ENCRYPT_AES_CBC,
                             CRYPTO_KEY_1,
                             testNum,
                             aes256CbcInputTestData,
                             sizeof(aes256CbcInputTestData),
                             outputCbcEncryptedtext,
                             &outputCbcEncryptedLength,
                             CRYPTO_PROCESSING_SYNC);
        
        /* perform encryption tasks */
        Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);
        printf("\r\n");
        /* check if the generated encrypted data is correct */
        printf("The encrypted data:");
        for (int tempSize = 0; tempSize < outputCbcEncryptedLength; tempSize++)
        {
            printf(" %02X", outputCbcEncryptedtext[tempSize]);
        }
        printf("\r\n");
        
        /* configure decryption task */
        job = PrepareTestJob(TEST_DECRYPT_AES_CBC,
                             CRYPTO_KEY_1,
                             testNum,
                             outputCbcEncryptedtext,
                             sizeof(outputCbcEncryptedtext),
                             outputCbcDecryptedtext,
                             &outputCbcDecryptedLength,
                             CRYPTO_PROCESSING_SYNC);
        
        /* perform decryption tasks */
        Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);
        
        /* check if the generated decrypted data is correct */
                             
        printf("The decrypted data:");
        for (int tempSize = 0; tempSize < CBC_TEST_LENGTH; tempSize++)
        {
            if (outputCbcDecryptedtext[tempSize] != aes256CbcInputTestData[tempSize])
            {
                flag = 1; 
            }
            printf(" %02X", outputCbcDecryptedtext[tempSize]);
        }
        printf("\r\n");
        
        /* encryption and decryption are error-free */
        if (flag == 0)
        {
            printf("demo ok!");
        }
        else
        {
            printf("demo error!");
        }
    }

     printf("\r\n------------------ IntegrationAppCrypto_AES_CBC End------------------\r\n");
#endif

#ifdef TEST_AES_CMAC
    printf("\r\n");
    printf("********************* AES mode CMAC  *************************\r\n");
    #define CMAC_TEST_LENGTH   36
    static VAR(uint8, AUTOMATIC) aes256CmacInputTestData[CMAC_TEST_LENGTH]= "0123456789abcdefghijklmnopqrstuvwxyz";

    Crypto_VerifyResultType verifySts = CRYPTO_E_VER_OK;
    P2CONST(char, AUTOMATIC, CRYPTO_APPL_CONST) Crypto_VerifyResultTypeStr[] = {"CRYPTO_E_VER_OK", "CRYPTO_E_VER_FAIL"};
    VAR(uint8, AUTOMATIC) outputCmacEncryptedtext[16] = {0};
    VAR(uint32, AUTOMATIC) outputCmacEncryptedLength = sizeof(outputCmacEncryptedtext);
    VAR(uint8, AUTOMATIC) outputCmactext[16] = {0};
    VAR(uint32, AUTOMATIC) outputCmacLength = sizeof(outputCmactext);

    /* set aeskey as the key */
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_256,
                         AES256key,
                         sizeof(AES256key));
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_192,
                         AES192key,
                         sizeof(AES192key));
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYMATERIAL_128,
                         AES128Key,
                         sizeof(AES128Key));
    /* set iv as the key */
    Crypto_KeyElementSet(CRYPTO_KEY_1,
                         CRYPTO_KEYELEMENT_IV,
                         CmacIvAllZeros,
                         sizeof(CmacIvAllZeros));

    /* set the key to be valid */
    Crypto_KeySetValid(CRYPTO_KEY_1);

    for(int testNum = 1; testNum < 4; testNum++)
    {
        /* according to the set parameters,configure mac tasks */
        job = PrepareTestJob(TEST_CMAC_GENERATE,
                             CRYPTO_KEY_1,
                             testNum,
                             aes256CmacInputTestData,
                             sizeof(aes256CmacInputTestData),
                             outputCmactext,
                             &outputCmacLength,
                             CRYPTO_PROCESSING_SYNC);
        /* perform mac tasks */
        Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);
        printf("\r\n");
        /* check if the generated mac data is correct */
        printf("The Cmac data:");
        for (int tempSize = 0; tempSize < 16; tempSize++)
        {
            printf(" %02X", outputCmactext[tempSize]);
        }
        printf("\r\n");

        /* according to the set parameters,configure mac verify tasks */
        job = PrepareTestJob(TEST_CMAC_VERIFY,
                             CRYPTO_KEY_1,
                             testNum,
                             aes256CmacInputTestData,
                             sizeof(aes256CmacInputTestData),
                             outputCmacEncryptedtext,
                             &outputCmacEncryptedLength,
                             CRYPTO_PROCESSING_SYNC);
        job->jobPrimitiveInputOutput.secondaryInputLength = outputCmacLength;
        job->jobPrimitiveInputOutput.secondaryInputPtr = outputCmactext;
        job->jobPrimitiveInputOutput.verifyPtr = &verifySts;
        /* perform mac verify tasks */
        Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);
        /* check if the generated mac data is correct */
        printf("The Cmac verify data:");
        for (int tempSize = 0; tempSize < 16; tempSize++)
        {
            printf(" %02X", outputCmacEncryptedtext[tempSize]);
        }
        printf("\r\n");
        /* check if the mac verify pass */
        printf("The Cmac verify: %s\n ",Crypto_VerifyResultTypeStr[verifySts]);

        printf("\r\n");
    }

     printf("\r\n------------------ IntegrationAppCrypto_AES_CMAC End------------------\r\n");
#endif 
   
#ifdef TEST_AES_MPC
    printf("\r\n");
    printf("********************* AES mode MPC  *************************\r\n");
    #define MPC_TEST_LENGTH   16
    static VAR(uint8, AUTOMATIC) aes256MpcInputData[MPC_TEST_LENGTH];
    for(i = 0; i<sizeof(aes256MpcInputData); i++)
    {
        aes256MpcInputData[i] = i;
    }
    VAR(uint8, AUTOMATIC) outputMpctext[16] = {0};
    VAR(uint32, AUTOMATIC) outputMpcLength = sizeof(outputMpctext);

    /* set aeskey as the key */
    Crypto_KeyElementSet(CRYPTO_KEY_2,
                         CRYPTO_KEYMATERIAL_256,
                         AES256key_Initial,
                         sizeof(AES256key_Initial));

    /* set the key to be valid */
    Crypto_KeySetValid(CRYPTO_KEY_2);

    /* according to the set parameters,configure mac tasks */
    job = PrepareTestJob(TEST_MPC_GENERATE,
                         CRYPTO_KEY_2,
                         0,
                         aes256MpcInputData,
                         sizeof(aes256MpcInputData),
                         outputMpctext,
                         &outputMpcLength,
                         CRYPTO_PROCESSING_SYNC);
    /* perform mac tasks */
    Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);
    printf("\r\n");
    /* check if the generated Mpc data */
    printf("The Mpc data:");
    for (i = 0; i < 16; i++)
    {
        printf(" %02X", outputMpctext[i]);
    }
    printf("\r\n");

     printf("\r\n------------------ IntegrationAppCrypto_AES_MPC End------------------\r\n");
#endif 

#ifdef TEST_RNG
    printf("\r\n");
    printf("********************* TRNG  *************************\r\n");
    VAR(Std_ReturnType, AUTOMATIC) rngRet = E_NOT_OK;
    VAR(uint32, AUTOMATIC) temp = 0;
    VAR(uint8, AUTOMATIC) outputBuf[16] = {0};
    VAR(uint32, AUTOMATIC) outputLength = sizeof(outputBuf);
    
    /* create a task to generate a 16-byte random number */
    job = PrepareTestJob(TEST_RANDOM_GENERATE,
                         CRYPTO_KEY_2,
                         0,
                         NULL_PTR,
                         0,
                         outputBuf,
                         &outputLength,
                         CRYPTO_PROCESSING_SYNC);
     for(temp = 0; temp < 20;temp++)
     {
        /* execute the task */
        rngRet = Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);
        
        /* print out the generated random number */
        printf("%s", "Random Number: ");
        for (i = 0; i < 4; i++)
        {
            printf(" %02X", outputBuf[i]);
        }
        printf("\r\n");
        if (rngRet == E_OK)
        {
            printf("random number ok!\r\n");
        }
        else
        {
            printf("random number error!\r\n");
        }
    }
    printf("\r\n------------------ IntegrationAppCrypto_RNG End------------------\r\n");
#endif  
    
#ifdef TEST_HASH
    printf("\r\n");
    printf("********************* SHA256  *************************\r\n");
    VAR(Std_ReturnType, AUTOMATIC) hashRet = E_NOT_OK;
    VAR(uint8, AUTOMATIC) Sha256OutData[32]={0};
    VAR(uint32, AUTOMATIC) outputSha256Length = sizeof(Sha256OutData);
    static VAR(uint8, AUTOMATIC) Sha256InputTestData[100];
    VAR(uint32, AUTOMATIC) hashNum = 0;
    for(hashNum = 0; hashNum < sizeof(Sha256InputTestData); hashNum++)
    {
        Sha256InputTestData[hashNum] = hashNum;
    }
    /* create a task to generate a 256-bit hash */
    job = PrepareTestJob(TEST_HASH_GENERATE,
                         CRYPTO_KEY_2,
                         0,
                         Sha256InputTestData,
                         sizeof(Sha256InputTestData),
                         Sha256OutData,
                         &outputSha256Length,
                         CRYPTO_PROCESSING_ASYNC);
    /* execute the task */
    hashRet = Crypto_ProcessJob(CRYPTO_DRIVEROBJECT_WITHQUEUE, job);

        /* print out the generated 256-bit hash */
    printf("%s", "HASH Number: ");
    for (i = 0; i < 32; i++)
    {
        printf(" %x", Sha256OutData[i]);
    }
    printf("\r\n");
    if (hashRet == E_OK)
    {
        printf("HASH number ok!");
    }
    else
    {
        printf("HASH number error!");
    }
    printf("\r\n------------------ IntegrationAppCrypto_SHA256 End------------------\r\n");
#endif
    
   while(1);
}

#if defined (__CC_ARM) || defined (__ICCARM__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))

/*!
* @brief       Redirect C Library function printf to serial port.
*              After Redirection, you can use printf function.
*
* @param       ch:  The characters that need to be send.
*
* @param       *f:  pointer to a FILE that can recording all information
*              needed to control a stream
*
* @retval      The characters that need to be send.
*
* @note
*/
int fputc(int ch, FILE* f)
{
    int reVal = 0;
    reVal = Usart_PutRedefinition(USART1_ID,&ch);
    
    return reVal;
}

/* If configuring the full library using versions after IAR 9.30,
   it is necessary to implement the _write function for printf redirection.*/
size_t __write(int handle,const unsigned char *buf,size_t bufSize)
{
    int32 tempCh = 0;
    for(int i=0; i<bufSize; i++)
    {
        Usart_PutRedefinition(USART1_ID,&tempCh);
    }
    return bufSize;
}

#elif defined (__GNUC__)

/* For Arm Cross GCC: Eclipse */
int _write(int fd,const unsigned char *buf,int len)
{
    int32 tempCh = 0;
    for(int i=0; i<len; i++)
    {
        int32 tempCh = (int32)buf[i];
        Usart_PutRedefinition(USART1_ID,&tempCh);
    }
    return len;
}

#endif

#ifdef __cplusplus
}
#endif
