/*--------------------------------------------------------------------------*/
/* Copyright 2021 NXP                                                       */
/*                                                                          */
/* NXP Confidential. This software is owned or controlled by NXP and may    */
/* only be used strictly in accordance with the applicable license terms.   */
/* By expressly accepting such terms or by downloading, installing,         */
/* activating and/or otherwise using the software, you are agreeing that    */
/* you have read, and that you agree to comply with and are bound by, such  */
/* license terms. If you do not agree to be bound by the applicable license */
/* terms, then you may not retain, install, activate or otherwise use the   */
/* software.                                                                */
/*--------------------------------------------------------------------------*/

/** @file  data_invariant_memory_copy.c
 *  @brief Example constant-time memory copy (CLNS component mcuxCsslMemory) */

#include <stdbool.h>
#include <stdint.h>
#include <mcuxCsslMemory.h>
#include <mcuxCsslExamples.h>
#include <mcuxCsslFlowProtection.h>
#include <mcuxCsslParamIntegrity.h>

#define EXIT_CODE_ERROR 0x00U ///< example return code in case an error occurred
#define EXIT_CODE_OK    0x01U ///< example return code in case of successful operation


/* Declaration of data_invariant_memory_copy */
MCUX_CSSL_FP_FUNCTION_DECL(data_invariant_memory_copy)
MCUX_CSSL_FP_PROTECTED_TYPE(uint32_t) data_invariant_memory_copy(void);


/* Definition of data_invariant_memory_copy */
MCUX_CSSL_FP_FUNCTION_DEF(data_invariant_memory_copy)
MCUX_CSSL_FP_PROTECTED_TYPE(uint32_t) data_invariant_memory_copy(void) ///< function prototype of flow protected function
{
     /* FUNCTION_ENTRY initializes the flow protection for this function. */
    MCUX_CSSL_FP_FUNCTION_ENTRY(data_invariant_memory_copy);
    
    /* Define data arrays */
    uint8_t arr1[] = {0xe4u, 0xf9u, 0x26u, 0x4cu, 0x65u, 0xe2u, 0x13u, 0xa3u,
                      0x9au, 0x40u, 0xd7u, 0x87u, 0xccu, 0x0bu, 0x31u, 0x18u,
                      0xacu, 0x55u, 0xb5u, 0x7du, 0x06u, 0x7fu, 0xceu, 0xe4u,
                      0xb2u, 0x7eu, 0xd5u, 0xaau, 0x90u, 0x9au, 0x42u, 0x56u,
                      0x76u};
    uint8_t arr2[sizeof(arr1)] = {0u};

    /* Provoke buffer overflow => should return invalid parameter error */
    MCUX_CSSL_FP_FUNCTION_CALL(copyResult, mcuxCsslMemory_Copy(
                                /*  mcuxCsslParamIntegrity_Checksum_t chk,*/ mcuxCsslParamIntegrity_Protect(4u, arr1, arr2, sizeof(arr1), sizeof(arr1) + 1u),
                                /*  void const * src,           */ arr1,
                                /*  void * dst,                 */ arr2,
                                /*  size_t dst_size,                     */ sizeof(arr1),
                                /*  size_t cnt                           */ sizeof(arr1) + 1u)); /* Copy the values */

    /* Check the return code of mcuxCsslMemory_Copy */
    if(MCUXCSSLMEMORY_COPY_INVALID_PARAMETER != copyResult)
    {
        /* If the return code != MCUXCSSLMEMORY_COPY_INVALID_PARAMETER, exit with EXIT_CODE_ERROR */
        MCUX_CSSL_FP_FUNCTION_EXIT(data_invariant_memory_copy, EXIT_CODE_ERROR); 
    }
    
    /* Try to copy nothing (cnt = 0 bytes) => should return invalid parameter error */
    MCUX_CSSL_FP_FUNCTION_CALL(copyResult1, mcuxCsslMemory_Copy(
                                /*  mcuxCsslParamIntegrity_Checksum_t chk,*/ mcuxCsslParamIntegrity_Protect(4u, arr1, arr2, sizeof(arr1), 0u),
                                /*  void const * src,           */ arr1,
                                /*  void * dst,                 */ arr2,
                                /*  size_t dst_size,                     */ sizeof(arr1),
                                /*  size_t cnt                           */ 0u));   /* Copy the values */

    /* Check the return code of mcuxCsslMemory_Copy */
    if(MCUXCSSLMEMORY_COPY_INVALID_PARAMETER != copyResult)
    {
        /* If the return code != MCUXCSSLMEMORY_COPY_INVALID_PARAMETER, exit with EXIT_CODE_ERROR */
        MCUX_CSSL_FP_FUNCTION_EXIT(data_invariant_memory_copy, EXIT_CODE_ERROR); 
    }                           
    
    /* Copy arr1 to arr2 => should return success */
    MCUX_CSSL_FP_FUNCTION_CALL(copyResult2, mcuxCsslMemory_Copy(
                                /*  mcuxCsslParamIntegrity_Checksum_t chk,*/ mcuxCsslParamIntegrity_Protect(4u, arr1, arr2, sizeof(arr1), sizeof(arr1)),
                                /*  void const * src,           */ arr1,
                                /*  void * dst,                 */ arr2,
                                /*  size_t dst_size,                     */ sizeof(arr1),
                                /*  size_t cnt                           */ sizeof(arr1))); /* Copy the values */

    /* Check the return code of mcuxCsslMemory_Copy */
    if(MCUXCSSLMEMORY_COPY_SUCCESS != copyResult2)
    {
        /* If the return code != MCUXCSSLMEMORY_COPY_SUCCESS, exit with EXIT_CODE_ERROR */
        MCUX_CSSL_FP_FUNCTION_EXIT(data_invariant_memory_copy, EXIT_CODE_ERROR); 
    }    

    /* No error occurred during execution, exit with EXIT_CODE_OK */
    MCUX_CSSL_FP_FUNCTION_EXIT(data_invariant_memory_compare, EXIT_CODE_OK,
                      MCUX_CSSL_FP_FUNCTION_CALLED(mcuxCsslMemory_Copy),
                      MCUX_CSSL_FP_FUNCTION_CALLED(mcuxCsslMemory_Copy),
                      MCUX_CSSL_FP_FUNCTION_CALLED(mcuxCsslMemory_Copy));
}
