/**
*   @file       Crypto.c
*   @implements Crypto.c_Artifact
*   @version    1.0.0
*   @brief      AUTOSAR Crypto - Cryptographic Services Engine (CRYPTO) functions
*   @details    Contains functions for accessing CRYPTO from the CRYPTO driver perspective
*
*   @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_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_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 Crypto_c_REF_3
* Violates MISRA 2012 Advisory Rule 8.7, Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
* These functions represent the API of the driver. External linkage is needed to "export" the API.
*
* @section Crypto_c_REF_4
* Violates MISRA 2012 Advisory Rule 8.9, An object should be defined at block scope if its identifier only appears in a single function.
* The object is actually used also in other functions for other configurations.
*
* @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.h"
#include "Crypto_Types.h"
#include "CryIf_Cbk.h"
#include "Det.h"
#include "Crypto_Ipw.h"
#include "Crypto_Private.h"
#include "Crypto_Util.h"

/*==================================================================================================
*                                       SOURCE FILE VERSION INFORMATION
==================================================================================================*/
#define CRYPTO_VENDOR_ID_C                     43
#define CRYPTO_AR_RELEASE_MAJOR_VERSION_C      4
#define CRYPTO_AR_RELEASE_MINOR_VERSION_C      3
#define CRYPTO_AR_RELEASE_REVISION_VERSION_C   1
#define CRYPTO_SW_MAJOR_VERSION_C              1
#define CRYPTO_SW_MINOR_VERSION_C              0
#define CRYPTO_SW_PATCH_VERSION_C              0

/*==================================================================================================
*                                      FILE VERSION CHECKS
==================================================================================================*/
/* Check if Crypto source file and Crypto header file are of the same vendor */
#if (CRYPTO_VENDOR_ID_C != CRYPTO_VENDOR_ID)
    #error "Crypto.c and Crypto.h have different vendor ids"
#endif

/* Check if Crypto source file and Crypto header file are of the same Autosar version */
#if ((CRYPTO_AR_RELEASE_MAJOR_VERSION_C    != CRYPTO_AR_RELEASE_MAJOR_VERSION) || \
     (CRYPTO_AR_RELEASE_MINOR_VERSION_C    != CRYPTO_AR_RELEASE_MINOR_VERSION) || \
     (CRYPTO_AR_RELEASE_REVISION_VERSION_C != CRYPTO_AR_RELEASE_REVISION_VERSION) \
    )
    #error "AutoSar Version Numbers of Crypto.c and Crypto.h are different"
#endif

/* Check if Crypto source file and Crypto header file are of the same Software version */
#if ((CRYPTO_SW_MAJOR_VERSION_C != CRYPTO_SW_MAJOR_VERSION) || \
     (CRYPTO_SW_MINOR_VERSION_C != CRYPTO_SW_MINOR_VERSION) || \
     (CRYPTO_SW_PATCH_VERSION_C != CRYPTO_SW_PATCH_VERSION)    \
    )
    #error "Software Version Numbers of Crypto.c and Crypto.h are different"
#endif

/* Check if Crypto source file and Crypto types header file are of the same vendor */
#if (CRYPTO_VENDOR_ID_C != CRYPTO_VENDOR_ID_TYPES)
    #error "Crypto.c and Crypto_Types.h have different vendor ids"
#endif

/* Check if Crypto source file and Crypto types header file are of the same Autosar version */
#if ((CRYPTO_AR_RELEASE_MAJOR_VERSION_C    != CRYPTO_AR_RELEASE_MAJOR_VERSION_TYPES) || \
     (CRYPTO_AR_RELEASE_MINOR_VERSION_C    != CRYPTO_AR_RELEASE_MINOR_VERSION_TYPES) || \
     (CRYPTO_AR_RELEASE_REVISION_VERSION_C != CRYPTO_AR_RELEASE_REVISION_VERSION_TYPES) \
    )
    #error "AutoSar Version Numbers of Crypto.c and Crypto_Types.h are different"
#endif

/* Check if Crypto source file and Crypto types header file are of the same Software version */
#if ((CRYPTO_SW_MAJOR_VERSION_C != CRYPTO_SW_MAJOR_VERSION_TYPES) || \
     (CRYPTO_SW_MINOR_VERSION_C != CRYPTO_SW_MINOR_VERSION_TYPES) || \
     (CRYPTO_SW_PATCH_VERSION_C != CRYPTO_SW_PATCH_VERSION_TYPES)    \
    )
    #error "Software Version Numbers of Crypto.c and Crypto_Types.h are different"
#endif

/* Check if Crypto source file and Crypto Ipw header file are of the same vendor */
#if (CRYPTO_VENDOR_ID_C != CRYPTO_VENDOR_ID_IPW_H)
    #error "Crypto.c and Crypto_Ipw.h have different vendor ids"
#endif

/* Check if Crypto source file and Crypto Ipw header file are of the same Autosar version */
#if ((CRYPTO_AR_RELEASE_MAJOR_VERSION_C    != CRYPTO_AR_RELEASE_MAJOR_VERSION_IPW_H) || \
     (CRYPTO_AR_RELEASE_MINOR_VERSION_C    != CRYPTO_AR_RELEASE_MINOR_VERSION_IPW_H) || \
     (CRYPTO_AR_RELEASE_REVISION_VERSION_C != CRYPTO_AR_RELEASE_REVISION_VERSION_IPW_H) \
    )
    #error "AutoSar Version Numbers of Crypto.c and Crypto_Ipw.h are different"
#endif

/* Check if Crypto source file and Crypto Ipw header file are of the same Software version */
#if ((CRYPTO_SW_MAJOR_VERSION_C != CRYPTO_SW_MAJOR_VERSION_IPW_H) || \
     (CRYPTO_SW_MINOR_VERSION_C != CRYPTO_SW_MINOR_VERSION_IPW_H) || \
     (CRYPTO_SW_PATCH_VERSION_C != CRYPTO_SW_PATCH_VERSION_IPW_H)    \
    )
    #error "Software Version Numbers of Crypto.c and Crypto_Ipw.h are different"
#endif

/* Check if Crypto source file and Crypto private header file are of the same vendor */
#if (CRYPTO_VENDOR_ID_C != CRYPTO_VENDOR_ID_PRIVATE)
    #error "Crypto.c and Crypto_Private.h have different vendor ids"
#endif

/* Check if Crypto source file and Crypto private header file are of the same Autosar version */
#if ((CRYPTO_AR_RELEASE_MAJOR_VERSION_C    != CRYPTO_AR_RELEASE_MAJOR_VERSION_PRIVATE) || \
     (CRYPTO_AR_RELEASE_MINOR_VERSION_C    != CRYPTO_AR_RELEASE_MINOR_VERSION_PRIVATE) || \
     (CRYPTO_AR_RELEASE_REVISION_VERSION_C != CRYPTO_AR_RELEASE_REVISION_VERSION_PRIVATE) \
    )
    #error "AutoSar Version Numbers of Crypto.c and Crypto_Private.h are different"
#endif

/* Check if Crypto source file and Crypto private header file are of the same Software version */
#if ((CRYPTO_SW_MAJOR_VERSION_C != CRYPTO_SW_MAJOR_VERSION_PRIVATE) || \
     (CRYPTO_SW_MINOR_VERSION_C != CRYPTO_SW_MINOR_VERSION_PRIVATE) || \
     (CRYPTO_SW_PATCH_VERSION_C != CRYPTO_SW_PATCH_VERSION_PRIVATE)    \
    )
    #error "Software Version Numbers of Crypto.c and Crypto_Private.h are different"
#endif

/* Check if Crypto source file and Crypto_Util header file are of the same vendor */
#if (CRYPTO_VENDOR_ID_C != CRYPTO_UTIL_VENDOR_ID)
    #error "Crypto.c and Crypto_Util.h have different vendor ids"
#endif

/* Check if Crypto source file and Crypto_Util header file are of the same Autosar version */
#if ((CRYPTO_AR_RELEASE_MAJOR_VERSION_C    != CRYPTO_UTIL_AR_RELEASE_MAJOR_VERSION) || \
     (CRYPTO_AR_RELEASE_MINOR_VERSION_C    != CRYPTO_UTIL_AR_RELEASE_MINOR_VERSION) || \
     (CRYPTO_AR_RELEASE_REVISION_VERSION_C != CRYPTO_UTIL_AR_RELEASE_REVISION_VERSION) \
    )
    #error "AutoSar Version Numbers of Crypto.c and Crypto_Util.h are different"
#endif

/* Check if Crypto source file and Crypto_Util header file are of the same Software version */
#if ((CRYPTO_SW_MAJOR_VERSION_C != CRYPTO_UTIL_SW_MAJOR_VERSION) || \
     (CRYPTO_SW_MINOR_VERSION_C != CRYPTO_UTIL_SW_MINOR_VERSION) || \
     (CRYPTO_SW_PATCH_VERSION_C != CRYPTO_UTIL_SW_PATCH_VERSION)    \
    )
    #error "Software Version Numbers of Crypto.c and Crypto_Util.h are different"
#endif

#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
    /* Check if Crypto.c file and Det header file are of the same AutoSar version */
    #if ((CRYPTO_AR_RELEASE_MAJOR_VERSION_C != DET_AR_RELEASE_MAJOR_VERSION) || \
         (CRYPTO_AR_RELEASE_MINOR_VERSION_C != DET_AR_RELEASE_MINOR_VERSION)    \
        )
        #error "AutoSar Version Numbers of Crypto.c and Det.h are different"
    #endif 

    /* Check if Crypto.c file and CryIf_Cbk header file are of the same AutoSar version */
    #if ((CRYPTO_AR_RELEASE_MAJOR_VERSION_C != CRYIF_CBK_AR_RELEASE_MAJOR_VERSION) || \
         (CRYPTO_AR_RELEASE_MINOR_VERSION_C != CRYIF_CBK_AR_RELEASE_MINOR_VERSION)    \
        )
        #error "AutoSar Version Numbers of Crypto.c and CryIf_Cbk.h are different"
    #endif 
#endif

/*==================================================================================================
*                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/
/**
* @brief Enum containing the possible return values for function Crypto_VerifyServiceParameters
*/
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
typedef enum
{
    CRYPTO_NULL_PTR     = 0x00U,
    CRYPTO_INVALID_LEN  = 0x01U,
    CRYPTO_NO_ERROR     = 0x02U,
    CRYPTO_NOT_OK       = 0x03U
} Crypto_ErrorType;
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */

/*==================================================================================================
*                                       LOCAL MACROS
==================================================================================================*/
/* Reserved value associated with invalid Crypto Driver Object Id */
#define CRYPTO_INVALID_CDO_IDX_U32           ((uint32)0xFFFFFFFFU)

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

/*==================================================================================================
*                                      LOCAL VARIABLES
==================================================================================================*/
#define CRYPTO_START_SEC_VAR_INIT_UNSPECIFIED
/**
* @violates @ref Crypto_c_REF_1 #include directives should only be preceded by preprocessor
* directives or comments.
*
* @violates @ref Crypto_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          This variable holds the state of the driver.
* @details        This variable holds the state of the driver. After reset is UNINIT. The output of Crypto_Init() function
*                 should set this variable into IDLE state.
*                  CRYPTO_DRIVER_UNINIT = The CRYPTO controller is not initialized. All registers belonging to the CRYPTO module are in reset state.
*
*/
/**
* @violates @ref Crypto_c_REF_4 An object should be defined at block scope if its identifier only appears in a single function.
*
*/
VAR(Crypto_DriverStateType, CRYPTO_VAR) Crypto_eDriverState = CRYPTO_DRIVER_UNINIT;

#define CRYPTO_STOP_SEC_VAR_INIT_UNSPECIFIED
/**
* @violates @ref Crypto_c_REF_1 #include directives should only be preceded by preprocessor
* directives or comments.
*
* @violates @ref Crypto_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"

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

/*==================================================================================================
*                                      GLOBAL VARIABLES
==================================================================================================*/
#define CRYPTO_START_SEC_VAR_NO_INIT_UNSPECIFIED
/**
* @violates @ref Crypto_c_REF_1 #include directives should only be preceded by preprocessor
* directives or comments.
*
* @violates @ref Crypto_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"

P2FUNC(void, CRYPTO_CODE, Callback) (const Crypto_JobType* pJob, Std_ReturnType Result);

#define CRYPTO_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
/**
* @violates @ref Crypto_c_REF_1 #include directives should only be preceded by preprocessor
* directives or comments.
*
* @violates @ref Crypto_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"

/*==================================================================================================
*                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/
#define CRYPTO_START_SEC_CODE
/**
* @violates @ref Crypto_c_REF_1 #include directives should only be preceded by preprocessor
* directives or comments.
*
* @violates @ref Crypto_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           Verify if an object ID is valid
* @details         Verify if an object ID is valid (found inside the array of all Crypto Object IDs supported by the Crypto driver)
*
* @param[in]       u32ObjectId - objectId to be verified
*
* @return         CRYPTO_INVALID_CDO_IDX_U32: Request failed, object Id not found
*                 All other values:           Request successful, object Id found
* @api
*
* @pre
*
*/
LOCAL_INLINE FUNC(uint32, CRYPTO_CODE) Crypto_GetObjectIdIdx
(
    VAR (uint32, AUTOMATIC) u32ObjectId
);

#if (STD_ON == CRYPTO_KEYS_EXIST)
/**
* @brief           Verify if a key ID is valid 
* @details         Verify if a key ID is valid  (found inside the array of all key IDs supported by the Crypto driver)
*
* @param[in]       pJob - structure containing the key ID
*
* @return         E_OK:     Request successful, key ID found
*                 E_NOT_OK: Request failed, key ID not found
* @api
*
* @pre
*
*/
LOCAL_INLINE FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_VerifyKeyValidity
(
    P2CONST(Crypto_JobType, AUTOMATIC, CRYPTO_APPL_CONST) pJob
);

#endif

#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
/**
* @brief           Verify if certain parameters of one job are incorrect (null ptr, invalid length)
* @details         Verify if certain parameters of one job are incorrect (null ptr, invalid length)
*
* @param[in]       pJob - Pointer to the configuration of the job. Contains structures with job and primitive relevant information but also pointer to result buffers.
*
* @return          CRYPTO_NOT_OK:       Request failed, only singlecall mode supported
*                  CRYPTO_NULL_PTR:     NULL PTR found
*                  CRYPTO_INVALID_LEN : Invalid length found
*                  CRYPTO_NO_ERROR :    Request successful
* @api
*
* @pre
*
*/
LOCAL_INLINE FUNC(Crypto_ErrorType, CRYPTO_CODE) Crypto_VerifyServiceParameters
(
    P2CONST(Crypto_JobType, AUTOMATIC, CRYPTO_APPL_CONST) pJob
);

/**
* @brief           Verify if a certain primitive is supported by a crypto driver object
* @details         Verify if a certain primitive is supported by a crypto driver object specified by u32objectIndex
*
* @param[in]       u32ObjectId - Holds the identifier of the Crypto Driver Object.
* @param[in]       pJob - Pointer to the configuration of the job. Contains structures with job and primitive relevant information but also pointer to result buffers.
*
* @return         E_OK: Request successful, primitive found
*                 E_NOT_OK: Request failed, primitive not found
* @api
*
* @pre
*
*/
LOCAL_INLINE FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_VerifyPrimitive
(
    VAR    (uint32,         AUTOMATIC                   ) u32ObjectId,
    P2CONST(Crypto_JobType, AUTOMATIC, CRYPTO_APPL_CONST) pJob
);
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */

/*==================================================================================================
*                                      LOCAL FUNCTIONS
==================================================================================================*/
/**
* @brief           Verify if an object ID is valid
* @details         Verify if an object ID is valid (found inside the array of all crypto object IDs supported by the Crypto driver)
*
* @param[in]       u32ObjectId - objectId to be verified
*
* @return         CRYPTO_INVALID_CDO_IDX_U32: Request failed, object Id not found
*                 All other values:           Request successful, object Id found
* @api
*
* @pre
*
*/
LOCAL_INLINE FUNC(uint32, CRYPTO_CODE) Crypto_GetObjectIdIdx
(
    VAR (uint32, AUTOMATIC) u32ObjectId
)
{
    VAR(uint32, AUTOMATIC) u32RetVal = CRYPTO_INVALID_CDO_IDX_U32;
    VAR(uint32, AUTOMATIC) u32Counter;
    
    for ( u32Counter = 0U; u32Counter < CRYPTO_NUMBER_OF_DRIVER_OBJECTS_U32; u32Counter++)
    {
        if (u32ObjectId == Crypto_aObjectList[u32Counter]->u32CryptoDriverObjectId)
        {
            u32RetVal = u32Counter;
            break;
        }
    }
    return u32RetVal;
}

#if (STD_ON == CRYPTO_KEYS_EXIST)
/**
* @brief           Verify if a key ID is valid 
* @details         Verify if a key ID is valid  (found inside the array of all key IDs supported by the Crypto driver)
*
* @param[in]       pJob - structure containing the key ID
*
* @return          E_OK: Request successful, key ID found
*                  E_NOT_OK: Request failed, key ID not found
* @api
*
* @pre
*
*/
LOCAL_INLINE FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_VerifyKeyValidity
(
    P2CONST(Crypto_JobType, AUTOMATIC, CRYPTO_APPL_CONST) pJob
)
{
    VAR(Crypto_ServiceInfoType, AUTOMATIC) eJobService       = pJob->jobPrimitiveInfo->primitiveInfo->service;
    VAR(uint32,                 AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(pJob->cryptoKeyId);
    VAR(Std_ReturnType,         AUTOMATIC) RetVal            = (Std_ReturnType)E_OK;
    
    /* All crypto services listed in Crypto_ServiceInfoType except for:
        - CRYPTO_RANDOMGENERATE
        - CRYPTO_HASH
        - CRYPTO_SECCOUNTERINCREMENT
        - CRYPTO_SECCOUNTERREAD
    require a key represented as a key identifier. */
    if ((CRYPTO_RANDOMGENERATE      != eJobService) &&
        (CRYPTO_HASH                != eJobService) &&
        (CRYPTO_SECCOUNTERINCREMENT != eJobService) &&
        (CRYPTO_SECCOUNTERREAD      != eJobService)
       )
    {
        if (u32CryptoKeyIdIdx < CRYPTO_NUMBER_OF_KEYS_U32)
        {
            if ((boolean)FALSE == Crypto_aKeyList[u32CryptoKeyIdIdx]->bCryptoKeyValid)
            {
                RetVal = (Std_ReturnType)CRYPTO_E_KEY_NOT_VALID;
            }
        }
        else
        {
            RetVal = (Std_ReturnType)E_NOT_OK;
        }
    }
    return RetVal;
}
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
/**
* @brief           Verify if certain parameters of one job are incorrect (null ptr, invalid length)
* @details         Verify if certain parameters of one job are incorrect (null ptr, invalid length)
*
* @param[in]       pJob - Pointer to the configuration of the job. Contains structures with job and primitive relevant information but also pointer to result buffers.
*
* @return          CRYPTO_NOT_OK:       Request failed, only singlecall mode supported
*                  CRYPTO_NULL_PTR:     NULL PTR found
*                  CRYPTO_INVALID_LEN:  Invalid length found
*                  CRYPTO_NO_ERROR :    Request successful
* @api
*
* @pre
*
*/
LOCAL_INLINE FUNC(Crypto_ErrorType, CRYPTO_CODE) Crypto_VerifyServiceParameters
(
    P2CONST(Crypto_JobType, AUTOMATIC, CRYPTO_APPL_CONST) pJob
)
{
    VAR(Crypto_ErrorType,         AUTOMATIC) eRetVal = CRYPTO_NO_ERROR;
    VAR(Crypto_OperationModeType, AUTOMATIC) jobMode = pJob->jobPrimitiveInputOutput.mode;
    
        switch (pJob->jobPrimitiveInfo->primitiveInfo->service)
        {
            case HASH:
            case MAC_GENERATE:
            case SIGNATURE_GENERATE:
                if (
                    (CRYPTO_OPERATIONMODE_SINGLECALL  == jobMode) || \
                    (CRYPTO_OPERATIONMODE_UPDATE      == jobMode) || \
                    (CRYPTO_OPERATIONMODE_STREAMSTART == jobMode)
                   )
                {
                    if (NULL_PTR == pJob->jobPrimitiveInputOutput.inputPtr)
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if (0U == pJob->jobPrimitiveInputOutput.inputLength)
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }
                }
                if ((CRYPTO_NO_ERROR == eRetVal) && \
                    ((CRYPTO_OPERATIONMODE_SINGLECALL  == jobMode) || \
                     (CRYPTO_OPERATIONMODE_FINISH      == jobMode) || \
                     (CRYPTO_OPERATIONMODE_STREAMSTART == jobMode)
                    )
                   )
                {
                    if ((NULL_PTR == pJob->jobPrimitiveInputOutput.outputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputLengthPtr))
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if (0U == *pJob->jobPrimitiveInputOutput.outputLengthPtr) 
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }
                }
                break;
                
            case MAC_VERIFY:
            case SIGNATURE_VERIFY:
                if (
                    (CRYPTO_OPERATIONMODE_SINGLECALL  == jobMode) || \
                    (CRYPTO_OPERATIONMODE_UPDATE      == jobMode) || \
                    (CRYPTO_OPERATIONMODE_STREAMSTART == jobMode)
                   )
                {
                    if (NULL_PTR == pJob->jobPrimitiveInputOutput.inputPtr) 
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if (0U == pJob->jobPrimitiveInputOutput.inputLength)
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }
                }
                if ((CRYPTO_NO_ERROR == eRetVal) && \
                    ((CRYPTO_OPERATIONMODE_SINGLECALL  == jobMode) || \
                     (CRYPTO_OPERATIONMODE_FINISH      == jobMode) || \
                     (CRYPTO_OPERATIONMODE_STREAMSTART == jobMode)
                    )
                   )
                {
                    if ((NULL_PTR == pJob->jobPrimitiveInputOutput.secondaryInputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.verifyPtr))
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if (0U == pJob->jobPrimitiveInputOutput.secondaryInputLength)
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }
                }
                break;
                
            case ENCRYPT:
            case DECRYPT:
                if (
                    (CRYPTO_OPERATIONMODE_SINGLECALL  == jobMode) || \
                    (CRYPTO_OPERATIONMODE_UPDATE      == jobMode) || \
                    (CRYPTO_OPERATIONMODE_STREAMSTART == jobMode)
                   )
                {
                    if ((NULL_PTR == pJob->jobPrimitiveInputOutput.inputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputLengthPtr))
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if ((0U == pJob->jobPrimitiveInputOutput.inputLength) || (0U == *pJob->jobPrimitiveInputOutput.outputLengthPtr))
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }
                }
                if ((CRYPTO_NO_ERROR == eRetVal) && \
                    ((CRYPTO_OPERATIONMODE_SINGLECALL  == jobMode) || \
                     (CRYPTO_OPERATIONMODE_FINISH      == jobMode) || \
                     (CRYPTO_OPERATIONMODE_STREAMSTART == jobMode)
                    )
                   )
                {
                    if ((NULL_PTR == pJob->jobPrimitiveInputOutput.outputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputLengthPtr))
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if (0U == *pJob->jobPrimitiveInputOutput.outputLengthPtr)
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }  
                }
                break;
                
            case AEAD_ENCRYPT:
                if (
                    (CRYPTO_OPERATIONMODE_SINGLECALL  == jobMode) || \
                    (CRYPTO_OPERATIONMODE_UPDATE      == jobMode) || \
                    (CRYPTO_OPERATIONMODE_STREAMSTART == jobMode)
                   )
                {
                    if ((NULL_PTR == pJob->jobPrimitiveInputOutput.inputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputLengthPtr))
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if ((0U == pJob->jobPrimitiveInputOutput.inputLength) || (0U == *pJob->jobPrimitiveInputOutput.outputLengthPtr))
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }
                }
                if ((CRYPTO_NO_ERROR == eRetVal) && \
                    ((CRYPTO_OPERATIONMODE_SINGLECALL  == jobMode) || \
                     (CRYPTO_OPERATIONMODE_FINISH      == jobMode) || \
                     (CRYPTO_OPERATIONMODE_STREAMSTART == jobMode)
                    )
                   )
                {
                    if (
                         (NULL_PTR == pJob->jobPrimitiveInputOutput.secondaryInputPtr)  || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputPtr)       || \
                         (NULL_PTR == pJob->jobPrimitiveInputOutput.secondaryOutputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputLengthPtr) || \
                         (NULL_PTR == pJob->jobPrimitiveInputOutput.secondaryOutputLengthPtr)
                        )
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if (
                             (0U ==  pJob->jobPrimitiveInputOutput.secondaryInputLength)     || 
                             (0U == *pJob->jobPrimitiveInputOutput.secondaryOutputLengthPtr) || \
                             (0U == *pJob->jobPrimitiveInputOutput.secondaryOutputLengthPtr)
                            )
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }
                }
                break;
                
            case AEAD_DECRYPT:
                if (
                    (CRYPTO_OPERATIONMODE_SINGLECALL  == jobMode) || \
                    (CRYPTO_OPERATIONMODE_UPDATE      == jobMode) || \
                    (CRYPTO_OPERATIONMODE_STREAMSTART == jobMode)
                   )
                {
                    if ((NULL_PTR == pJob->jobPrimitiveInputOutput.inputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputLengthPtr))
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if ((0U == pJob->jobPrimitiveInputOutput.inputLength) || (0U == *pJob->jobPrimitiveInputOutput.outputLengthPtr))
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }
                }
                if ((CRYPTO_NO_ERROR == eRetVal) && \
                    ((CRYPTO_OPERATIONMODE_SINGLECALL  == jobMode) || \
                     (CRYPTO_OPERATIONMODE_FINISH      == jobMode) || \
                     (CRYPTO_OPERATIONMODE_STREAMSTART == jobMode)
                    )
                   )
                {
                    if (
                         (NULL_PTR == pJob->jobPrimitiveInputOutput.secondaryInputPtr)  || (NULL_PTR == pJob->jobPrimitiveInputOutput.tertiaryInputPtr) || \
                         (NULL_PTR == pJob->jobPrimitiveInputOutput.outputPtr)          || (NULL_PTR == pJob->jobPrimitiveInputOutput.verifyPtr)        || \
                         (NULL_PTR == pJob->jobPrimitiveInputOutput.outputLengthPtr)
                        )
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if (
                             (0U ==  pJob->jobPrimitiveInputOutput.secondaryInputLength) || \
                             (0U ==  pJob->jobPrimitiveInputOutput.tertiaryInputLength)  || \
                             (0U == *pJob->jobPrimitiveInputOutput.outputLengthPtr)
                            )
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }
                }
                break;
                
            case SECCOUNTERINCREMENT:
                /* Nothing to be verified; Only single call is available for seccounterincrement (start, update, finish not possible) */ 
                if (CRYPTO_OPERATIONMODE_SINGLECALL != jobMode) 
                {
                    eRetVal = CRYPTO_NOT_OK;
                }
                break;
                
            case SECCOUNTERREAD:
                if (CRYPTO_OPERATIONMODE_SINGLECALL == jobMode) 
                {
                    if (NULL_PTR == pJob->jobPrimitiveInputOutput.output64Ptr)
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                }
                else
                {
                    /* Only single call is available for seccounteread (start, update, finish not possible)*/
                    eRetVal = CRYPTO_NOT_OK;
                }
                break;
                
            case RANDOM:
                /* Only single call is available for random function (start, update, finish not possible)*/
                if (CRYPTO_OPERATIONMODE_SINGLECALL == jobMode) 
                {
                    if  ((NULL_PTR == pJob->jobPrimitiveInputOutput.outputPtr) || (NULL_PTR == pJob->jobPrimitiveInputOutput.outputLengthPtr))
                    {
                        eRetVal = CRYPTO_NULL_PTR;
                    }
                    else if (0U == *pJob->jobPrimitiveInputOutput.outputLengthPtr)
                    {
                        eRetVal = CRYPTO_INVALID_LEN;
                    }
                    else
                    {
                        /* Do nothing */
                    }
                }
                else
                {
                    /* Only single call is available for random function (start, update, finish not possible) - return an error in this case */
                    eRetVal = CRYPTO_NOT_OK;
                }
                break;
            default:
                /* Should never get here */
                eRetVal = CRYPTO_NOT_OK;
                break;
        }
        
    return eRetVal;
}

/**
* @brief           Verify if a certain primitive is supported by a crypto driver object
* @details         Verify if a certain primitive is supported by a crypto driver object specified by u32objectIndex
*
* @param[in]       u32ObjectId - Holds the identifier of the Crypto Driver Object.
* @param[in]       pJob - Pointer to the configuration of the job. Contains structures with job and primitive relevant information but also pointer to result buffers.
*
* @return          E_OK:     Request successful, primitive found
*                  E_NOT_OK: Request failed, primitive not found
* @api
*
* @pre
*
*/
LOCAL_INLINE FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_VerifyPrimitive
(
    VAR    (uint32,         AUTOMATIC                   ) u32ObjectId,
    P2CONST(Crypto_JobType, AUTOMATIC, CRYPTO_APPL_CONST) pJob
)
{
    VAR    (Std_ReturnType,           AUTOMATIC                   ) RetVal            = (Std_ReturnType)E_NOT_OK;
    P2CONST(Crypto_PrimitiveInfoType, AUTOMATIC, CRYPTO_APPL_CONST) pJobPrimitiveInfo = pJob->jobPrimitiveInfo->primitiveInfo;
    VAR    (uint32,                   AUTOMATIC                   ) u32Counter;
    P2CONST(Crypto_PrimitiveType,     AUTOMATIC, CRYPTO_APPL_CONST) pCryptoKeyPrimitive;
    
    for (u32Counter = 0U; u32Counter < Crypto_aObjectList[u32ObjectId]->u32NoCryptoPrimitives; u32Counter++)
    {
        pCryptoKeyPrimitive = &Crypto_aObjectList[u32ObjectId]->pCryptoKeyPrimitives[u32Counter];
        if (
            (pJobPrimitiveInfo->service          == pCryptoKeyPrimitive->eService) && \
            (pJobPrimitiveInfo->algorithm.family == pCryptoKeyPrimitive->eFamily)  && \
            (pJobPrimitiveInfo->algorithm.mode   == pCryptoKeyPrimitive->eMode)
           )
        {
            RetVal = (Std_ReturnType)E_OK;
            break;
        }
    }
    
    return RetVal;
}
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */

/*==================================================================================================
*                                       GLOBAL FUNCTIONS
==================================================================================================*/
/**
* @brief            Initializes the Crypto Driver.
* @details          Initializes the internal variables of the driver, initializes the MU communication layer.
*
* @param[in]        none
*
* @return           void
*
* @api
*
* @pre
*
* @implements       Crypto_Init_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(void, CRYPTO_CODE) Crypto_Init (void)
{
    VAR (Std_ReturnType, AUTOMATIC) HwInitRetVal;
    /* Initialize the driver only if the driver was not already initialized */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        HwInitRetVal = Crypto_Ipw_Init();
        if((Std_ReturnType)E_OK == HwInitRetVal)
        {
            /* Initialize queues used by the driver's CDOs */
            Crypto_Util_InitJobQueues();
            /* Initialize the callback with the CryIf one */
            Callback = CryIf_CallbackNotification;
            /* After initialization, the Crypto driver is in initialized state */
            Crypto_eDriverState = CRYPTO_DRIVER_INITIALIZED;
        }
#if(STD_ON == CRYPTO_DEV_ERROR_DETECT)
        else
        {
            (void) Det_ReportError( (uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_INIT_ID, (uint8)CRYPTO_E_INIT_FAILED );
        }
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    }
}

#if (STD_ON == CRYPTO_VERSION_INFO_API)
/**
* @brief            Returns the version information of this module.
* @details          Writes the version information attributes of this module in the location pointed by versioninfo parameter.
*
* @param[inout]     versioninfo     Pointer where to store the version information of this module
*
* @return           void
*
* @api
*
* @pre
*
* @implements       Crypto_GetVersionInfo_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(void, CRYPTO_CODE) Crypto_GetVersionInfo (P2VAR(Std_VersionInfoType, AUTOMATIC, CRYPTO_APPL_DATA) versioninfo)
{
#if(STD_ON == CRYPTO_DEV_ERROR_DETECT)
    if (NULL_PTR == versioninfo)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_GETVERSIONINFO_ID, (uint8)CRYPTO_E_PARAM_POINTER);
    }
    else
#endif /* STD_ON == CRYPTO_DEV_ERROR_DETECT */
    {
        versioninfo->moduleID           = (uint16)CRYPTO_MODULE_ID;
        versioninfo->vendorID           = (uint16)CRYPTO_VENDOR_ID;
        versioninfo->sw_major_version   = (uint8)CRYPTO_SW_MAJOR_VERSION;
        versioninfo->sw_minor_version   = (uint8)CRYPTO_SW_MINOR_VERSION;
        versioninfo->sw_patch_version   = (uint8)CRYPTO_SW_PATCH_VERSION;
    }
}
#endif /* (STD_ON == CRYPTO_VERSION_INFO_API) */

/**
* @brief            Performs the crypto primitive that is configured in the job parameter.
* @details          Performs the crypto primitive, that is configured in the job parameter.
*
* @param[in]        objectId    Holds the identifier of the Crypto Driver Object
* @param[inout]     job         Pointer to the configuration of the job. Contains structures with job and primitive relevant information but also pointer to result buffers.
*
* @return           Result of the operation
* @retval           E_OK                        Request successful
* @retval           E_NOT_OK                    Request failed
* @retval           CRYPTO_E_BUSY               Request failed, Crypro Driver Object is Busy
* @retval           CRYPTO_E_KEY_NOT_VALID      Request failed, the key is not valid
* @retval           CRYPTO_E_KEY_SIZE_MISMATCH  Request failed, a key element has the wrong size
* @retval           CRYPTO_E_QUEUE_FULL         Request failed, the queue is full
* @retval           CRYPTO_E_ENTROPY_EXHAUSTION Request failed, the entropy is exhausted
* @retval           CRYPTO_E_SMALL_BUFFER       The provided buffer is too small to store the result
* @retval           CRYPTO_E_COUNTER_OVERFLOW   The counter is overflowed
* @retval           CRYPTO_E_JOB_CANCELED       The service request failed because the synchronous Job has been canceled
*
* @api
*
* @pre
*
* @implements     Crypto_ProcessJob_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_ProcessJob
(
    VAR  (uint32,         AUTOMATIC                  ) objectId,
    P2VAR(Crypto_JobType, AUTOMATIC, CRYPTO_APPL_DATA) job
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal         = (Std_ReturnType)E_NOT_OK;
    VAR(uint32,         AUTOMATIC) u32ObjectIdIdx = Crypto_GetObjectIdIdx(objectId);
    
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    VAR(Crypto_ErrorType, AUTOMATIC) eCryptoError;
    

    /* Check whether the Crypto driver is in CRYPTO_DRIVER_UNINIT state */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_PROCESSJOB_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If the parameter objectId is out of range and if development error detection for the Crypto Driver is enabled, 
       the function Crypto_ProcessJob shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if (CRYPTO_INVALID_CDO_IDX_U32 == u32ObjectIdIdx)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_PROCESSJOB_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    /* If the parameter job is a null pointer and if development error detection for the Crypto Driver is enabled, 
       the function Crypto_ProcessJob shall report CRYPTO_E_PARAM_POINTER to the DET and return E_NOT_OK. */
    else if (NULL_PTR == job)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_PROCESSJOB_ID, (uint8)CRYPTO_E_PARAM_POINTER);
    }
    /* If the parameter job->jobPrimitiveInfo->primitiveInfo->service is not supported by the Crypto Driver Object and
      if development error detection for the Crypto Driver is enabled, the function Crypto_ProcessJob shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK */
    else if ((Std_ReturnType)E_NOT_OK == Crypto_VerifyPrimitive(u32ObjectIdIdx, job))
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_PROCESSJOB_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    /* If a pointer is required as an argument, but it is a null pointer, the Crypto_ProcessJob() function shall report CRYPTO_E_PARAM_POINTER. */
    else
    {
        eCryptoError = Crypto_VerifyServiceParameters(job);
        if (CRYPTO_NULL_PTR == eCryptoError)
        {
            (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_PROCESSJOB_ID, (uint8)CRYPTO_E_PARAM_POINTER);
        }
        /* If the value, which is pointed by a length pointer, is zero, and if development error detection for the Crypto Driver is enabled, the Crypto_ProcessJob() function report CRYPTO_E_PARAM_VALUE to the DET and return E_NOT_OK.
        If a length pointer is required as an argument, but the value, which is pointed by the length pointer is zero, and if development error detection for the Crypto Driver is enabled, the Crypto_ProcessJob() function     report CRYPTO_E_PARAM_VALUE to the DET and return E_NOT_OK.    */
        else if (CRYPTO_INVALID_LEN == eCryptoError)
        {
            (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_PROCESSJOB_ID, (uint8)CRYPTO_E_PARAM_VALUE);
        }
        else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
        {
            RetVal = (Std_ReturnType)E_OK;
#if (STD_ON == CRYPTO_KEYS_EXIST)
            /* All crypto services listed in Crypto_ServiceInfoType except of CRYPTO_HASH, CRYPTO_SECCOUNTERINCREMENT, CRYPTO_SECCOUNTERREAD and CRYPTO_RANDOMGENERATE require a key represented as a key identifier. */
            RetVal = Crypto_VerifyKeyValidity(job);
#endif
            if ((Std_ReturnType)E_OK == RetVal)
            {
                RetVal = Crypto_Ipw_ProcessJob(u32ObjectIdIdx, job);
            }
        }
        /* If the buffer job->jobPrimitiveInput.outputPtr or job->jobPrimitiveInput.secondaryOutputPtr is too small to store the result of the request, 
        CRYPTO_E_SMALL_BUFFER shall be returned and the function shall additionally report the runtime error CRYPTO_E_RE_SMALL_BUFFER */
        if ((Std_ReturnType)CRYPTO_E_SMALL_BUFFER == RetVal)
        {
            (void)Det_ReportRuntimeError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_PROCESSJOB_ID, (uint8)CRYPTO_E_RE_SMALL_BUFFER);
        }
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    }
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */

    return RetVal;
}

/**
* @brief           This interface removes the provided job from the queue and cancels the processing of the job if possible.
* @details         This interface removes the provided job from the queue and cancels the processing of the job if possible.
*
* @param[in]       objectId     Holds the identifier of the Crypto Driver Object.
* @param[inout]    job          Pointer to the configuration of the job. Contains structures with job and primitive relevant information.

* @return           Result of the operation
* @retval           E_OK        Request successful, job has been removed
* @retval           E_NOT_OK    Request failed, job couldn't be removed 
*
* @api
*
* @pre
*
* @implements     Crypto_CancelJob_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_CancelJob 
(
    VAR  (uint32,             AUTOMATIC                  ) objectId,
    P2VAR(Crypto_JobInfoType, AUTOMATIC, CRYPTO_APPL_DATA) job
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal         = (Std_ReturnType)E_NOT_OK;
    VAR(uint32,         AUTOMATIC) u32ObjectIdIdx = Crypto_GetObjectIdIdx(objectId);

#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* Check whether the Crypto driver is in CRYPTO_DRIVER_UNINIT state */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        /* If development error detection for the Crypto Driver is enabled: The function Crypto_CancelJob shall raise the error CRYPTO_E_UNINIT and return E_NOT_OK if the module is not yet initialized. */
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_CANCELJOB_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If development error detection for the Crypto Driver is enabled: The function Crypto_CancelJob shall raise the error CRYPTO_E_PARAM_HANDLE and return E_NOT_OK if the parameter objectId is out or range. */
    else if (CRYPTO_INVALID_CDO_IDX_U32 == u32ObjectIdIdx)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_CANCELJOB_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    /* If development error detection for the Crypto Driver is enabled: The function Crypto_CancelJob shall raise the error CRYPTO_E_PARAM_POINTER and return E_NOT_OK if the parameter job is a null pointer. */
    else if (NULL_PTR == job)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_CANCELJOB_ID, (uint8)CRYPTO_E_PARAM_POINTER);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    {
        RetVal = Crypto_Ipw_CancelJob(u32ObjectIdIdx, job);
    }

    return RetVal;
}

/**
* @brief            Sets the given key element bytes to the key identified by cryptoKeyId.
* @details          Sets the given key element bytes to the key identified by cryptoKeyId.
*
* @param[in]        cryptoKeyId      Holds the identifier of the key whose key element shall be set
* @param[in]        keyElementId     Holds the identifier of the key element which shall be set
* @param[in]        keyPtr           Holds the pointer to the key data which shall be set as key element
* @param[in]        keyLength        Contains the length of the key element in bytes
*
* @return           Result of the operation
* @retval           E_OK                        Request successful
* @retval           E_NOT_OK                    Request failed
* @retval           CRYPTO_E_BUSY               Request failed, Crypto Driver Object is busy
* @retval           CRYPTO_E_KEY_WRITE_FAIL     Request failed because write access was denied
* @retval           CRYPTO_E_KEY_NOT_AVAILABLE  Request failed because the key is not available
* @retval           CRYPTO_E_KEY_SIZE_MISMATCH  Request failed, key element size does not match size of provided data
*
* @api
*
* @pre
*
* @implements     Crypto_KeyElementSet_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_KeyElementSet 
(
    VAR    (uint32, AUTOMATIC                   ) cryptoKeyId,
    VAR    (uint32, AUTOMATIC                   ) keyElementId,
    P2CONST(uint8,  AUTOMATIC, CRYPTO_APPL_CONST) keyPtr,
    VAR    (uint32, AUTOMATIC                   ) keyLength
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;
    
#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR    (uint32,                         AUTOMATIC                   ) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);
    VAR    (Crypto_VerifyKeyElementIdType,  AUTOMATIC                   ) VerifyKeyElementId;
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the Crypto Driver is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementSet shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTSET_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementSet shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if (CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTSET_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    /* If the parameter keyPtr is a null pointer and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementSet shall report CRYPTO_E_PARAM_POINTER to the DET and return E_NOT_OK. */
    else if (NULL_PTR == keyPtr)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTSET_ID, (uint8)CRYPTO_E_PARAM_POINTER);
    }
    /* If keyLength is zero and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementSet shall report CRYPTO_E_PARAM_VALUE to the DET and return E_NOT_OK. */
    else if (0U == keyLength)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTSET_ID, (uint8)CRYPTO_E_PARAM_VALUE);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    { 
        /* If parameter keyElementId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementSet shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
        VerifyKeyElementId    = Crypto_Util_VerifyKeyElementId (u32CryptoKeyIdIdx, keyElementId);
        if ((Std_ReturnType)E_OK == VerifyKeyElementId.RetVal)
        {
            /* If keylength parameter of the function is smaller than the size of the key element and the key element is not configured to allow partial access 
               or if is greater than the key length return CRYPTO_E_KEY_SIZE_MISMATCH */
            if (((0U == Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->bCryptoKeyElementAllowPartialAccess) && (keyLength < Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementMaxSize)) ||
                (keyLength > Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementMaxSize)
               )
            {
                RetVal = (Std_ReturnType)CRYPTO_E_KEY_SIZE_MISMATCH;
            }
            /* If the key does not allow write access - request failed because write access was denied */
            else if (CRYPTO_WA_DENIED == Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->eCryptoKeyElementWriteAccess)
            {
                RetVal = (Std_ReturnType)CRYPTO_E_KEY_WRITE_FAIL;
            }
            else
            {   
                /* When the KeyElementSet is called, the key state is set to invalid */
                Crypto_aKeyList[u32CryptoKeyIdIdx]->bCryptoKeyValid = (boolean)FALSE;
                
                /* If the key element is key material, send it to be stored */
                if (CRYPTO_KEY_MATERIAL_U32 == keyElementId)
                {
                    RetVal = Crypto_Ipw_LoadKey (keyPtr,
                                                 keyLength,
                                                 u32CryptoKeyIdIdx);
                }
                /* If the key element is different from key material (IV, seed) - store it */
                else
                {
                    Crypto_Util_Memcpy(keyPtr, Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->pCryptoElementArray, keyLength);
                    RetVal = (Std_ReturnType)E_OK;
                }
                /* Store the actual size of the key element */
                if ((Std_ReturnType)E_OK == RetVal)
                {
                    Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize = keyLength;
                }
            }
        }
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
        else
        {
            (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTSET_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
        }
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    }
#else
    (void) cryptoKeyId;
    (void) keyElementId;
    (void) keyPtr; 
    (void) keyLength;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST)*/

    return RetVal;
}

/**
* @brief            Sets the key state of the key identified by cryptoKeyId to valid.
* @details          Sets the key state of the key identified by cryptoKeyId to valid.
*
* @param[in]        cryptoKeyId  Holds the identifier of the key which shall be set to valid
*
* @return           Result of the operation
* @retval           E_OK            Request successful
* @retval           E_NOT_OK        Request failed
* @retval           CRYPTO_E_BUSY   Request failed, Crypto Driver Object is busy
*
* @api
*
* @pre
*
* @implements     Crypto_KeySetValid_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_KeySetValid
(
    VAR(uint32, AUTOMATIC) cryptoKeyId
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;
    
#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(uint32, AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);

#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the module is not yet initialized and development error detection for the Crypto Driver is enabled, the function Crypto_KeySetValid shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYSETVALID_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If parameter cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeySetValid shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if (CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYSETVALID_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    {
        /* Set the key to be valid */
        Crypto_aKeyList[u32CryptoKeyIdIdx]->bCryptoKeyValid = (boolean)TRUE;
        RetVal = (Std_ReturnType)E_OK;
    }
#else
    /* Avoid compiler warnings */
    (void) cryptoKeyId;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}

/**
* @brief            This interface shall be used to get a key element of the key identified by the cryptoKeyId and store the key element in the memory location pointed by the result pointer.
* @details          This interface shall be used to get a key element of the key identified by the cryptoKeyId and store the key element in the memory location pointed by the result pointer. 
*                   Note: If the actual key element is directly mapped to flash memory, there could be a bigger delay when calling this function (synchronous operation).
*
* @param[in]        cryptoKeyId      Holds the identifier of the key whose key element shall be returned
* @param[in]        keyElementId     Holds the identifier of the key element which shall be returned
* @param[out]       resultPtr        Holds the pointer of the buffer for the returned key element
* @param[inout]     resultLengthPtr  Holds a pointer to a memory location in which the length information is stored. On calling this function this parameter shall contain the size of the buffer provided by resultPtr. 
*                                    If the key element is configured to allow partial access, this parameter contains the amount of data which should be read from the key element. 
*                                    The size may not be equal to the size of the provided buffer anymore. When the request has finished, the amount of data that has been stored shall be stored.
*
* @return           Result of the operation
* @retval           E_OK                        Request successful
* @retval           E_NOT_OK                    Request failed
* @retval           CRYPTO_E_BUSY               Request failed, Crypto Driver Object is busy
* @retval           CRYPTO_E_KEY_NOT_AVAILABLE  Request failed, the requested key element is not available
* @retval           CRYPTO_E_KEY_READ_FAIL      Request failed because read access was denied
* @retval           CRYPTO_E_SMALL_BUFFER       The provided buffer is too small to store the result
*
* @api
*
* @pre
*
* @implements     Crypto_KeyElementGet_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_KeyElementGet
(
    VAR  (uint32, AUTOMATIC                  ) cryptoKeyId,
    VAR  (uint32, AUTOMATIC                  ) keyElementId,
    P2VAR(uint8,  AUTOMATIC, CRYPTO_APPL_DATA) resultPtr,
    P2VAR(uint32, AUTOMATIC, CRYPTO_APPL_DATA) resultLengthPtr
)
{
    VAR(Std_ReturnType,                AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;
#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(uint32,                        AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);
    VAR(Crypto_VerifyKeyElementIdType, AUTOMATIC) VerifyKeyElementId;
    
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the module is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementGet shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTGET_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If parameter cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeySetValid shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if (CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTGET_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    /* If the parameter resultPtr is a null pointer and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementGet shall report CRYPTO_E_PARAM_POINTER the DET and return E_NOT_OK. */
    /* If the parameter resultLengthPtr is a null pointer and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementGet shall report CRYPTO_E_PARAM_POINTER to the DET and return E_NOT_OK. */
    else if ((NULL_PTR == resultPtr) || (NULL_PTR == resultLengthPtr))
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTGET_ID, (uint8)CRYPTO_E_PARAM_POINTER);
    }
    /* If the value, which is pointed by resultLengthPtr is zero and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementGet shall report CRYPTO_E_PARAM_VALUE to the DET and return E_NOT_OK. */
    else if (0U == *resultLengthPtr)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTGET_ID, (uint8)CRYPTO_E_PARAM_VALUE);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    { 
        /* If the parameter keyElementId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementGet shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
        VerifyKeyElementId = Crypto_Util_VerifyKeyElementId (u32CryptoKeyIdIdx, keyElementId);
        if ((Std_ReturnType)E_OK == VerifyKeyElementId.RetVal) 
        {
            /* Request failed because read acces was denied */
            if (CRYPTO_RA_DENIED == Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->eCryptoKeyElementReadAccess)
            {
                RetVal = (Std_ReturnType)CRYPTO_E_KEY_READ_FAIL;
            }
            /* If the buffer resultPtr is too small to store the result of the request, CRYPTO_E_SMALL_BUFFER shall be returned and if development error detection is enabled, CRYPTO_E_SMALL_BUFFER shall be reported to the DET. */
            else if (*resultLengthPtr < Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize)
            {
                RetVal = (Std_ReturnType)CRYPTO_E_SMALL_BUFFER;
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
                (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTGET_ID, (uint8)CRYPTO_E_SMALL_BUFFER);
#endif          
            }
            else
            {  
                /* If the key element is key material, retrieve the key */
                if (CRYPTO_KEY_MATERIAL_U32 == keyElementId)
                {
                    /* Export the key */
                    RetVal = Crypto_Ipw_ExportKey(VerifyKeyElementId.u32Counter, 
                                                  resultPtr, 
                                                  resultLengthPtr);
                }
                /* If the key element is different from key material (IV, seed) */
                else
                {
                    Crypto_Util_Memcpy(Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->pCryptoElementArray, resultPtr, Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize);
                    /* When the request has finished, the amount of data that has been stored shall be stored. */
                    *resultLengthPtr = Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize;
                    RetVal = (Std_ReturnType)E_OK;
                }
            }
        }
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
        else
        {
            (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTGET_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
        }
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    }
    
    /* If the function Crypto_KeyElementGet returns CRYPTO_E_KEY_NOT_AVAILABLE, the function shall additionally report the runtime error CRYPTO_E_RE_KEY_NOT_AVAILABLE */
    if ((Std_ReturnType)CRYPTO_E_KEY_NOT_AVAILABLE == RetVal)
    {
        (void)Det_ReportRuntimeError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTGET_ID, (uint8)CRYPTO_E_RE_KEY_NOT_AVAILABLE);
    }
    /* If the function Crypto_KeyElementGet returns CRYPTO_E_KEY_READ_FAIL, the function shall additionally report the runtime error CRYPTO_E_RE_KEY_READ_FAIL. */
    else if ((Std_ReturnType)CRYPTO_E_KEY_READ_FAIL == RetVal)
    {
        (void)Det_ReportRuntimeError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTGET_ID, (uint8)CRYPTO_E_RE_KEY_READ_FAIL);
    }
    else
    {
        /* do nothing */
    }
    
#else
    /* Avoid compiler warnings */
    (void) cryptoKeyId;
    (void) keyElementId;
    (void) resultPtr;
    (void) resultLengthPtr;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}

/**
* @brief            Copies a key element to another key element in the same Crypto driver.
* @details          Copies a key element to another key element in the same Crypto driver. 
*                   Note: If the actual key element is directly mapped to flash memory, there could be a bigger delay when calling this function (synchronous operation)
*
* @param[in]        cryptoKeyId          Holds the identifier of the key whose key element shall be the source element
* @param[in]        keyElementId         Holds the identifier of the key element which shall be the source for the copy operation
* @param[in]        targetCryptoKeyId    Holds the identifier of the key whose key element shall be the destination element
* @param[in]        targetKeyElementId   Holds the identifier of the key element which shall be the destination for the copy operation
*
* @return           Result of the operation
* @retval           E_OK                        Request successful
* @retval           E_NOT_OK                    Request failed
* @retval           CRYPTO_E_BUSY               Request failed, Crypto Driver Object is busy
* @retval           CRYPTO_E_KEY_NOT_AVAILABLE  Request failed, the requested key element is not available
* @retval           CRYPTO_E_KEY_READ_FAIL      Request failed, not allowed to extract key element
* @retval           CRYPTO_E_KEY_WRITE_FAIL     Request failed, not allowed to write key element
* @retval           CRYPTO_E_KEY_SIZE_MISMATCH  Request failed, key element sizes are not compatible
*
* @api
*
* @pre
*
* @implements     Crypto_KeyElementCopy_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_KeyElementCopy
(
    VAR(uint32, AUTOMATIC) cryptoKeyId,
    VAR(uint32, AUTOMATIC) keyElementId,
    VAR(uint32, AUTOMATIC) targetCryptoKeyId,
    VAR(uint32, AUTOMATIC) targetKeyElementId
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;
#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(uint32,                         AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);
    VAR(uint32,                         AUTOMATIC) u32TargetKeyIdIdx = Crypto_Util_GetKeyIdIdx(targetCryptoKeyId);
    VAR (Crypto_VerifyKeyElementIdType, AUTOMATIC) VerifyKeyElementId;
    VAR (Crypto_VerifyKeyElementIdType, AUTOMATIC) VerifyTargetKeyElementId;
    

    
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the Crypto Driver is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementCopy shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTCOPY_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If parameter cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeySetValid shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    /* If parameter targetCryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeySetValid shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if ((CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx) || (CRYPTO_INVALID_KEY_IDX_U32 == u32TargetKeyIdIdx))
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTCOPY_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    { 
        /* If parameter keyElementId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementCopy shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
        /* If parameter targetKeyElementId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementCopy shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
        VerifyKeyElementId       = Crypto_Util_VerifyKeyElementId(u32CryptoKeyIdIdx,       keyElementId);
        VerifyTargetKeyElementId = Crypto_Util_VerifyKeyElementId(u32TargetKeyIdIdx, targetKeyElementId);

        if (((Std_ReturnType)E_OK == VerifyKeyElementId.RetVal) && ((Std_ReturnType)E_OK == VerifyTargetKeyElementId.RetVal))
        {
            /* Request failed, not allowed to extract key element */
            if (CRYPTO_RA_DENIED == Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->eCryptoKeyElementReadAccess)
            {
                RetVal = (Std_ReturnType)CRYPTO_E_KEY_READ_FAIL;
            }
            /* Request failed, not allowed to write key element */
            else if (CRYPTO_WA_DENIED == Crypto_aKeyElementList[VerifyTargetKeyElementId.u32Counter]->eCryptoKeyElementWriteAccess)
            {
                RetVal = (Std_ReturnType)CRYPTO_E_KEY_WRITE_FAIL;
            }
            /* Incompatible sizes between key elements */
            else if (
                      (Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize > Crypto_aKeyElementList[VerifyTargetKeyElementId.u32Counter]->u32CryptoKeyElementMaxSize) || \
                      (
                        (Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize != Crypto_aKeyElementList[VerifyTargetKeyElementId.u32Counter]->u32CryptoKeyElementMaxSize) && \
                        ((boolean)FALSE == Crypto_aKeyElementList[VerifyTargetKeyElementId.u32Counter]->bCryptoKeyElementAllowPartialAccess)
                      )
                     )
            {
                RetVal = (Std_ReturnType)CRYPTO_E_KEY_SIZE_MISMATCH;
            }
            else
            {
                /* If the key element is key material, send it to be stored */
                if (CRYPTO_KEY_MATERIAL_U32 == targetKeyElementId) 
                {
                                    RetVal = Crypto_Ipw_LoadKey (Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->pCryptoElementArray, 
                                                 Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize,
                                                 u32TargetKeyIdIdx);
                }
                /* If the key element is different from key material (IV, seed) - store it */
                else
                {
                    Crypto_Util_Memcpy(Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->pCryptoElementArray, Crypto_aKeyElementList[VerifyTargetKeyElementId.u32Counter]->pCryptoElementArray , Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize);
                    RetVal = (Std_ReturnType)E_OK;
                }
                /* If everything went fine, store the actual size of the element */
                if ((Std_ReturnType)E_OK == RetVal)
                {
                    Crypto_aKeyElementList[VerifyTargetKeyElementId.u32Counter]->u32CryptoKeyElementActualSize = Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize;
                }
            }
        }
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
        else
        {
            (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTCOPY_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
        }
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    }
#else
    /* Avoid compiler warnings */
    (void) cryptoKeyId;
    (void) keyElementId;
    (void) targetCryptoKeyId;
    (void) targetKeyElementId;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}

/**
* @brief            Copies a key with all its elements to another key in the same crypto driver.
* @details          Copies a key with all its elements to another key in the same crypto driver.
*                   Note: If the actual key element is directly mapped to flash memory, there could be a bigger delay when calling this function (synchronous operation)
*
* @param[in]        cryptoKeyId          Holds the identifier of the key whose key element shall be the source element
* @param[in]        targetCryptoKeyId    Holds the identifier of the key whose key element shall be the destination element
*
* @return           Result of the operation
* @retval           E_OK                        Request successful
* @retval           E_NOT_OK                    Request failed
* @retval           CRYPTO_E_BUSY               Request failed, Crypto Driver Object is busy
* @retval           CRYPTO_E_KEY_NOT_AVAILABLE  Request failed, the requested key element is not available
* @retval           CRYPTO_E_KEY_READ_FAIL      Request failed, not allowed to extract key element
* @retval           CRYPTO_E_KEY_WRITE_FAIL     Request failed, not allowed to write key element
* @retval           CRYPTO_E_KEY_SIZE_MISMATCH  Request failed, key element sizes are not compatible
*
* @api
*
* @pre
*
* @implements     Crypto_KeyCopy_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_KeyCopy
(
    VAR(uint32, AUTOMATIC) cryptoKeyId,
    VAR(uint32, AUTOMATIC) targetCryptoKeyId
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;
#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(boolean, AUTOMATIC) bKeyMaterialExists         = (boolean)FALSE;
    VAR(uint32,  AUTOMATIC) u32CryptoKeyIdIdx          = Crypto_Util_GetKeyIdIdx(cryptoKeyId);
    VAR(uint32,  AUTOMATIC) u32TargetKeyIdIdx          = Crypto_Util_GetKeyIdIdx(targetCryptoKeyId);
    VAR(uint32,  AUTOMATIC) u32KeyMaterialElementIndex = 0U;
    VAR(uint32,  AUTOMATIC) u32Counter1;
    VAR(uint32,  AUTOMATIC) u32Counter2;
    VAR(boolean, AUTOMATIC) bFound;
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)    

    /* If the Crypto Driver is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyCopy shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */ 
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYCOPY_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyCopy shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    /* If targetCryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyCopy shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if ((CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx) || (CRYPTO_INVALID_KEY_IDX_U32 == u32TargetKeyIdIdx))
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYCOPY_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    else
#endif
    { 
        /* Verify if number of Crypto Key Elements is larger on the source than on target. Report E_NOT_OK if this happens */
        if (Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32NoCryptoKeyElements > Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32NoCryptoKeyElements)
        {
            RetVal = (Std_ReturnType)E_NOT_OK;
        }
        else
        {
            RetVal = (Std_ReturnType)E_OK;
            for (u32Counter1 = 0U; ((u32Counter1 < Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32NoCryptoKeyElements) && ((Std_ReturnType)E_OK == RetVal)); u32Counter1++)
            {
                bFound = (boolean)FALSE;
                for (u32Counter2 = 0U; ((u32Counter2 < Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32NoCryptoKeyElements) && ((boolean)FALSE == bFound)); u32Counter2++)
                {
                    if (Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1]]->u32CryptoKeyElementId ==  \
                        Crypto_aKeyElementList[Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter2]]->u32CryptoKeyElementId
                        )
                    {
                        bFound = (boolean)TRUE;
                        if (CRYPTO_RA_DENIED == Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1]]->eCryptoKeyElementReadAccess)
                        {
                            RetVal = (Std_ReturnType)CRYPTO_E_KEY_READ_FAIL;
                        }
                        else if (CRYPTO_WA_DENIED == Crypto_aKeyElementList[Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter2]]->eCryptoKeyElementWriteAccess)
                        {
                            RetVal = (Std_ReturnType)CRYPTO_E_KEY_WRITE_FAIL;
                        }
                        else if (
                                 (Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1]]->u32CryptoKeyElementActualSize > Crypto_aKeyElementList[Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter2]]->u32CryptoKeyElementMaxSize) || \
                                  (
                                   (Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1]]->u32CryptoKeyElementActualSize != Crypto_aKeyElementList[Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter2]]->u32CryptoKeyElementMaxSize) && \
                                   ((boolean)FALSE == Crypto_aKeyElementList[Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter2]]->bCryptoKeyElementAllowPartialAccess)
                                  )
                                 )
                        {
                            RetVal = (Std_ReturnType)CRYPTO_E_KEY_SIZE_MISMATCH;
                        }
                        else
                        {
                            /* Do nothing*/
                        }
                        /* If any errors occured, get out */
                        if ((Std_ReturnType)E_OK != RetVal)
                        {
                            break;
                        }
                        /* if the key element is key material itself, store the position in the list of key elements, it is needed for later */
                        if (CRYPTO_KEY_MATERIAL_U32 == Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1]]->u32CryptoKeyElementId)
                        {
                            u32KeyMaterialElementIndex = Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1];
                            bKeyMaterialExists = (boolean)TRUE;
                        }
                    }
                }
                /* If no compatible key element was found, return */
                if (((boolean)FALSE == bFound) || ((Std_ReturnType)E_OK != RetVal))
                {
                    RetVal = (Std_ReturnType)E_NOT_OK;
                    break;
                }
            }
        }
        /* If verification for all key elements was successful, start copying the elements; start with key material because in case there is an error the other elements should not be copied */
        if (((boolean)TRUE == bKeyMaterialExists) && ((Std_ReturnType)E_OK == RetVal))
        {
            RetVal = Crypto_Ipw_LoadKey (Crypto_aKeyElementList[u32KeyMaterialElementIndex]->pCryptoElementArray,
                                         Crypto_aKeyElementList[u32KeyMaterialElementIndex]->u32CryptoKeyElementActualSize,
                                         u32CryptoKeyIdIdx);
        }
        /* Copy the rest of the elements (different from key material) */
        if ((Std_ReturnType)E_OK == RetVal)
        {
            bFound = (boolean)FALSE;
            for (u32Counter1 = 0U; u32Counter1 < Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32NoCryptoKeyElements; u32Counter1++)
            {
                bFound = (boolean)FALSE;
                for (u32Counter2 = 0U; ((u32Counter2 < Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32NoCryptoKeyElements) && ((boolean)FALSE == bFound)); u32Counter2++)
                {
                    if ((Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1]]->u32CryptoKeyElementId ==  \
                         Crypto_aKeyElementList[Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter2]]->u32CryptoKeyElementId) &&
                         (1U != Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1]]->u32CryptoKeyElementId) 
                        )
                         
                    {
                        bFound = (boolean)TRUE;
                        Crypto_Util_Memcpy(Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1]]->pCryptoElementArray, Crypto_aKeyElementList[Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter2]]->pCryptoElementArray , Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1]]->u32CryptoKeyElementActualSize);
                        Crypto_aKeyElementList[Crypto_aKeyList[u32TargetKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter2]]->u32CryptoKeyElementActualSize = Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Counter1]]->u32CryptoKeyElementActualSize;
                    }
                }
            }
        }
    }
#else
    /* Avoid compiler warnings */
    (void) cryptoKeyId;
    (void) targetCryptoKeyId;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */
  
    return RetVal;
}


/**
* @brief            Used to retrieve information which key elements are available in a given key.
* @details          Used to retrieve information which key elements are available in a given key.
*
* @param[in]        cryptoKeyId               Holds the identifier of the key whose available element ids shall be exported
* @param[out]       keyElementIdsPtr          Contains the pointer to the array where the ids of the key elements shall be stored
* @param[inout]     keyElementIdsLengthPtr    Holds a pointer to the memory location in which the number of key elements in the given key is stored.
*                                             On calling this function, this parameter shall contain the size of the buffer provided by keyElementIdsPtr.
*                                             When the request has finished, the actual number of key elements shall be stored.
*
* @return           Result of the operation
* @retval           E_OK                    Request successful
* @retval           E_NOT_OK                Request failed
* @retval           CRYPTO_E_BUSY           Request failed, Crypto Driver Object is busy
* @retval           CRYPTO_E_SMALL_BUFFER   The provided buffer is too small to store the result
*
* @api
*
* @pre
*
* @implements     Crypto_KeyElementIdsGet_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_KeyElementIdsGet
(
    VAR  (uint32, AUTOMATIC                  ) cryptoKeyId,
    P2VAR(uint32, AUTOMATIC, CRYPTO_APPL_DATA) keyElementIdsPtr,
    P2VAR(uint32, AUTOMATIC, CRYPTO_APPL_DATA) keyElementIdsLengthPtr
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;
#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(uint32,  AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);
    VAR(uint32,  AUTOMATIC) u32Index;
    
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the Crypto Driver is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementIdsGet shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTIDSGET_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyElementIdsGet shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if (CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx)
    {  
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTIDSGET_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    /* If the buffer keyElementIdsPtr is too small to store the result of the request, 
    CRYPTO_E_SMALL_BUFFER shall be returned and if development error detection is enabled, CRYPTO_E_SMALL_BUFFER shall be reported to the DET. */
    else if (Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32NoCryptoKeyElements > *keyElementIdsLengthPtr)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYELEMENTIDSGET_ID, (uint8)CRYPTO_E_SMALL_BUFFER);
        RetVal = (Std_ReturnType)CRYPTO_E_SMALL_BUFFER;
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    {
        if ((NULL_PTR != keyElementIdsPtr) && (NULL_PTR != keyElementIdsLengthPtr))
        {
            *keyElementIdsLengthPtr = Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32NoCryptoKeyElements;
            for (u32Index = 0U; u32Index < Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32NoCryptoKeyElements; u32Index++)
            {
                *keyElementIdsPtr = Crypto_aKeyElementList[Crypto_aKeyList[u32CryptoKeyIdIdx]->pCryptoKeyElementList->u32CryptoKeyElements[u32Index]]->u32CryptoKeyElementId;
                keyElementIdsPtr++;
            }
            RetVal = (Std_ReturnType)E_OK;
        }
    }
#else
    /* Avoid compiler warnings */
    (void) cryptoKeyId;
    (void) keyElementIdsPtr;
    (void) keyElementIdsLengthPtr;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}

/**
* @brief            This function generates the internal seed state using the provided entropy source. Furthermore, this function can be used to update the seed state with new entropy.
* @details          This function generates the internal seed state using the provided entropy source. Furthermore, this function can be used to update the seed state with new entropy.
*
* @param[in]        cryptoKeyId               Holds the identifier of the key for which a new seed shall be generated
* @param[in]        seedPtr                   Holds a pointer to the memory location which contains the data to feed the entropy
* @param[in]        seedLength                Contains the length of the entropy in bytes
*
* @return           Result of the operation
* @retval           E_OK        Request successful
* @retval           E_NOT_OK    Request failed
*
* @api
*
* @pre
*
* @implements     Crypto_RandomSeed_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_RandomSeed
(
    VAR    (uint32, AUTOMATIC                   ) cryptoKeyId,
    P2CONST(uint8,  AUTOMATIC, CRYPTO_APPL_CONST) seedPtr,
    VAR    (uint32, AUTOMATIC                   ) seedLength
)
{
    VAR(Std_ReturnType,                AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;
#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(Crypto_VerifyKeyElementIdType, AUTOMATIC) VerifyKeyElementId;
    VAR(uint32,                        AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);

#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the module is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_RandomSeed shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_RANDOMSEED_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_RandomSeed shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if (CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx)
    {  
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_RANDOMSEED_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    /* If the parameter seedPtr is a null pointer and if development error detection for the Crypto Driver is enabled, the function Crypto_RandomSeed shall report CRYPTO_E_PARAM_POINTER to the DET and return E_NOT_OK. */
    else if (NULL_PTR == seedPtr)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_RANDOMSEED_ID, (uint8)CRYPTO_E_PARAM_POINTER);
    }
    /* If seedLength is zero and if development error detection for the Crypto Driver is enabled, the function Crypto_RandomSeed shall report CRYPTO_E_PARAM_VALUE to the DET and return E_NOT_OK. */
    else if  (0U == seedLength)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_RANDOMSEED_ID, (uint8)CRYPTO_E_PARAM_VALUE);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    {
        VerifyKeyElementId = Crypto_Util_VerifyKeyElementId (u32CryptoKeyIdIdx, CRYPTO_KE_RANDOM_SEED_STATE);
        if((Std_ReturnType)E_OK == VerifyKeyElementId.RetVal)
        {
            RetVal = Crypto_Ipw_GenerateSeed(seedPtr, seedLength, Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->pCryptoElementArray);
        }
    }
#else
    /* Avoid compiler warnings */
    (void) cryptoKeyId;
    (void) seedPtr;
    (void) seedLength;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}


/**
* @brief            Generates new key material and stores it in the key identified by cryptoKeyId.
* @details          Generates new key material and stores it in the key identified by cryptoKeyId.
*
* @param[in]        cryptoKeyId     Holds the identifier of the key which is to be updated with the generated value
*
* @return           Result of the operation
* @retval           E_OK            Request successful
* @retval           E_NOT_OK        Request failed
* @retval           CRYPTO_E_BUSY   Request failed, Crypto Driver Object is busy
*
* @api
*
* @pre
*
* @implements     Crypto_KeyGenerate_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_KeyGenerate
(
    VAR(uint32, AUTOMATIC) cryptoKeyId
)
{
    VAR(Std_ReturnType,                AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;
#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(uint32,                        AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);
    VAR(Crypto_VerifyKeyElementIdType, AUTOMATIC) VerifyKeyElementId;
    VAR(Crypto_VerifyKeyElementIdType, AUTOMATIC) VerifyKeyBaseExchange; 

#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the module is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyGenerate shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYGENERATE_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If the parameter cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyGenerate shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if (CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYGENERATE_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    {
        VerifyKeyElementId = Crypto_Util_VerifyKeyElementId (u32CryptoKeyIdIdx, CRYPTO_KEY_MATERIAL_U32);
        
        /* CRYPTO_KE_KEYEXCHANGE_BASE key element will be used as Curve Id for ECC and public Exponent for RSA*/
        VerifyKeyBaseExchange = Crypto_Util_VerifyKeyElementId(u32CryptoKeyIdIdx, CRYPTO_KE_KEYEXCHANGE_BASE);
        
        if(((Std_ReturnType)E_OK == VerifyKeyElementId.RetVal) && ((Std_ReturnType)E_OK == VerifyKeyBaseExchange.RetVal) )
        {
            RetVal = Crypto_Ipw_GenerateKey(VerifyKeyElementId.u32Counter,VerifyKeyBaseExchange.u32Counter);
        }
    }
#else
    /* Avoid compiler warnings */
    (void)cryptoKeyId;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}


/**
* @brief            Derives a new key by using the key elements in the given key identified by the cryptoKeyId.
* @details          Derives a new key by using the key elements in the given key identified by the cryptoKeyId. The given key contains the key elements for the password, salt. 
*                   The derived key is stored in the key element with the id 1 of the key identified by targetCryptoKeyId. The number of iterations is given in the key element CRYPTO_KE_KEYDERIVATION_ITERATIONS.
*
* @param[in]        cryptoKeyId          Holds the identifier of the key which is used for key derivation
* @param[in]        targetCryptoKeyId    Holds the identifier of the key which is used to store the derived key
*
* @return           Result of the operation
* @retval           E_OK            Request successful
* @retval           E_NOT_OK        Request failed
* @retval           CRYPTO_E_BUSY   Request failed, Crypto Driver Object is busy
*
* @api
*
* @pre
*
* @implements     Crypto_KeyDerive_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_KeyDerive
(
    VAR(uint32, AUTOMATIC) cryptoKeyId, 
    VAR(uint32, AUTOMATIC) targetCryptoKeyId
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;
#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(uint32,  AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);
    VAR(uint32,  AUTOMATIC) u32TargetKeyIdIdx = Crypto_Util_GetKeyIdIdx(targetCryptoKeyId);

#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the module is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyDerive shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYDERIVE_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If the parameter cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyDerive shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    /* If the parameter targetCryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyDerive shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK.*/
    else if ((CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx) || (CRYPTO_INVALID_KEY_IDX_U32 == u32TargetKeyIdIdx))
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYDERIVE_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    { 
        RetVal = Crypto_Ipw_KeyDerive(u32CryptoKeyIdIdx, u32TargetKeyIdIdx);
    }
#else
    /* Avoid compiler warnings */
    (void)cryptoKeyId;
    (void)targetCryptoKeyId;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}

/**
* @brief            Calculates the public value for the key exchange and stores the public key in the memory location pointed by the public value pointer.
* @details          Calculates the public value for the key exchange and stores the public key in the memory location pointed by the public value pointer. 
*
* @param[in]        cryptoKeyId               Holds the identifier of the key which shall be used for the key exchange protocol
* @param[out]       publicValuePtr            Contains the pointer to the data where the public value shall be stored
* @param[inout]     publicValueLengthPtr      Holds a pointer to the memory location in which the public value length information is stored. 
*                                             On calling this function, this parameter shall contain the size of the buffer provided by publicValuePtr.
*                                             When the request has finished, the actual length of the returned value shall be stored.
*
* @return           Result of the operation
* @retval           E_OK                    Request successful
* @retval           E_NOT_OK                Request failed
* @retval           CRYPTO_E_BUSY           Request failed, Crypto Driver Object is busy
* @retval           CRYPTO_E_SMALL_BUFFER   The provided buffer is too small to store the result
*
* @api
*
* @pre
*
* @implements     Crypto_KeyExchangeCalcPubVal_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_KeyExchangeCalcPubVal
(
    VAR  (uint32, AUTOMATIC                  ) cryptoKeyId, 
    P2VAR(uint8,  AUTOMATIC, CRYPTO_APPL_DATA) publicValuePtr,
    P2VAR(uint32, AUTOMATIC, CRYPTO_APPL_DATA) publicValueLengthPtr
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;

#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(uint32,                         AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);
    VAR (Crypto_VerifyKeyElementIdType, AUTOMATIC) VerifyKeyElementId;
    
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the module is not yet initialized and if development error detection for the Crypto Driver is enabled: The function Crypto_KeyExchangeCalcPubVal shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCPUBVAL_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If the parameter cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyExchangeCalcPubVal shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if (CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCPUBVAL_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    /* If the parameter publicValuePtr is a null pointer and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyExchangeCalcPubVal shall report CRYPTO_E_PARAM_POINTER to the DET and return E_NOT_OK. */
    else if (NULL_PTR == publicValuePtr)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCPUBVAL_ID, (uint8)CRYPTO_E_PARAM_POINTER);
    }
    /* If the parameter pubValueLengthPtr is a null pointer and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyExchangeCalcPubVal shall report CRYPTO_E_PARAM_POINTER to the DET and return E_NOT_OK. */
    else if (NULL_PTR == publicValueLengthPtr)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCPUBVAL_ID, (uint8)CRYPTO_E_PARAM_POINTER);
    }
    /* If the value, which is pointed by pubValueLengthPtr is zero and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyExchangeCalcPubVal shall report CRYPTO_E_PARAM_VALUE to the DET and return E_NOT_OK. */
    else if (0U == *publicValueLengthPtr)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCPUBVAL_ID, (uint8)CRYPTO_E_PARAM_VALUE);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    {
        VerifyKeyElementId = Crypto_Util_VerifyKeyElementId (u32CryptoKeyIdIdx, CRYPTO_KE_KEYEXCHANGE_OWNPUBKEY);
        if((Std_ReturnType)E_OK == VerifyKeyElementId.RetVal)
        {
            /* If the buffer publicValuePtr is too small to store the result of the request, CRYPTO_E_SMALL_BUFFER shall be returned and the function shall additionally report the runtime error CRYPTO_E_RE_SMALL_BUFFER. */
            if (*publicValueLengthPtr < Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize)
            {
                (void)Det_ReportRuntimeError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCPUBVAL_ID, (uint8)CRYPTO_E_RE_SMALL_BUFFER);
                RetVal = (Std_ReturnType)CRYPTO_E_SMALL_BUFFER; 
            }
            else
            {
                Crypto_Util_Memcpy(Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->pCryptoElementArray , publicValuePtr , Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize);
                *publicValueLengthPtr = Crypto_aKeyElementList[VerifyKeyElementId.u32Counter]->u32CryptoKeyElementActualSize;
                RetVal = (Std_ReturnType)E_OK;
            }
        }
#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
        else
        {     
            (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCPUBVAL_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
        }
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    }
#else
    /* Avoid compiler warnings */
    (void)cryptoKeyId;
    (void)publicValuePtr;
    (void)publicValueLengthPtr;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}


/**
* @brief            Calculates the shared secret key.
* @details          Calculates the shared secret key for the key exchange with the key material of the key identified by the 
*                   cryptoKeyId and the partner public key. The shared secret key is stored as a key element in the same key. 
*
* @param[in]        cryptoKeyId                   Holds the identifier of the key which shall be used for the key exchange protocol
* @param[in]        partnerPublicValuePtr         Holds the pointer to the memory location which contains the partner's public value
* @param[in]        partnerPublicValueLength      Contains the length of the partner's public value in bytes.
*                                                 On calling this function, this parameter shall contain the size of the buffer provided by publicValuePtr.
*                                                 When the request has finished, the actual length of the returned value shall be stored.
*
* @return           Result of the operation
* @retval           E_OK                    Request successful
* @retval           E_NOT_OK                Request failed
* @retval           CRYPTO_E_BUSY           Request failed, Crypto Driver Object is busy
* @retval           CRYPTO_E_SMALL_BUFFER   The provided buffer is too small to store the result
*
* @api
*
* @pre
*
* @implements     Crypto_KeyExchangeCalcSecret_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_KeyExchangeCalcSecret
(
    VAR    (uint32, AUTOMATIC                   ) cryptoKeyId, 
    P2CONST(uint8,  AUTOMATIC, CRYPTO_APPL_CONST) partnerPublicValuePtr,
    VAR    (uint32, AUTOMATIC                   ) partnerPublicValueLength
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;

#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(uint32,                        AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);
    VAR(Crypto_VerifyKeyElementIdType, AUTOMATIC) VerifyKeyElementPriv;
    VAR(Crypto_VerifyKeyElementIdType, AUTOMATIC) VerifyKeyElementPub; 
    VAR(Crypto_VerifyKeyElementIdType, AUTOMATIC) VerifyKeyElementShared;

#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the module is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyExchangeCalcSecret shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCSECRET_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If the parameter cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyExchangeCalcSecret shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if (CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCSECRET_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    /* If the parameter partnerPublicValuePtr is a null pointer and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyExchangeCalcSecret shall report CRYPTO_E_PARAM_POINTER to the DET and return E_NOT_OK. */
    else if (NULL_PTR == partnerPublicValuePtr)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCSECRET_ID, (uint8)CRYPTO_E_PARAM_POINTER);
    }
    /* If partnerPublicValueLength is zero and if development error detection for the Crypto Driver is enabled, the function Crypto_KeyExchangeCalcSecret shall report CRYPTO_E_PARAM_VALUE to the DET and return E_NOT_OK. */
    else if (0U == partnerPublicValueLength)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_KEYEXCHANGECALCSECRET_ID, (uint8)CRYPTO_E_PARAM_VALUE);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    {
        /* Search for the Private Key  */
        VerifyKeyElementPriv   = Crypto_Util_VerifyKeyElementId(u32CryptoKeyIdIdx, CRYPTO_KE_KEYEXCHANGE_PRIVKEY);
        VerifyKeyElementPub    = Crypto_Util_VerifyKeyElementId(u32CryptoKeyIdIdx, CRYPTO_KE_KEYEXCHANGE_OWNPUBKEY);
        VerifyKeyElementShared = Crypto_Util_VerifyKeyElementId(u32CryptoKeyIdIdx, CRYPTO_KE_KEYEXCHANGE_SHAREDVALUE);
        /* The key used for exchange must have Public and Private Keys as key elements in order to trigger request */
        if( ((Std_ReturnType)E_OK == VerifyKeyElementPriv.RetVal) && ((Std_ReturnType)E_OK == VerifyKeyElementPub.RetVal) && (((Std_ReturnType)E_OK == VerifyKeyElementShared.RetVal)))
        {
            RetVal = Crypto_Ipw_CalcSecret(partnerPublicValuePtr, partnerPublicValueLength,
                                           Crypto_aKeyElementList[VerifyKeyElementPriv.u32Counter]->u32CryptoKeyHandle,
                                           Crypto_aKeyElementList[VerifyKeyElementPub.u32Counter]->u32CryptoKeyHandle,
                                           Crypto_aKeyElementList[VerifyKeyElementShared.u32Counter]->u32CryptoKeyHandle);
        }
    }
#else
    /* Avoid compiler warnings */
    (void)cryptoKeyId;
    (void)partnerPublicValuePtr;
    (void)partnerPublicValueLength;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}

/**
* @brief            Parses the certificate data stored in the key element CRYPTO_KE_CERT_DATA and fills the key elements CRYPTO_KE_CERT_SIGNEDDATA, CRYPTO_KE_CERT_PARSEDPUBLICKEY and CRYPTO_KE_CERT_SIGNATURE.
* @details          Parses the certificate data stored in the key element CRYPTO_KE_CERT_DATA and fills the key elements CRYPTO_KE_CERT_SIGNEDDATA, CRYPTO_KE_CERT_PARSEDPUBLICKEY and CRYPTO_KE_CERT_SIGNATURE.
*
* @param[in]        cryptoKeyId     Holds the identifier of the key which shall be parsed
*
* @return           Result of the operation
* @retval           E_OK            Request successful
* @retval           E_NOT_OK        Request failed
* @retval           CRYPTO_E_BUSY   Request failed, Crypto Driver Object is busy
*
* @api
*
* @pre
*
* @implements  Crypto_CertificateParse_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_CertificateParse
(
    VAR(uint32, AUTOMATIC) cryptoKeyId
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;

#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(uint32, AUTOMATIC) u32CryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(cryptoKeyId);

#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the module is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_CertificateParse shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_CERTIFICATEPARSE_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If the parameter cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_CertificateParse shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if (CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_CERTIFICATEPARSE_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    {
        RetVal = Crypto_Ipw_CertificateParse(u32CryptoKeyIdIdx);
    }
#else
    /* Avoid compiler warnings */
    (void)cryptoKeyId;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}

/**
* @brief            Verifies the certificate stored in the key referenced by cryptoValidateKeyId with the certificate stored in the key referenced by cryptoKeyId.
* @details          Verifies the certificate stored in the key referenced by cryptoValidateKeyId with the certificate stored in the key referenced by cryptoKeyId.
*
* @param[in]        cryptoKeyId         Holds the identifier of the key which shall be used to validate the certificate
* @param[in]        verifyCryptoKeyId   Holds the identifier of the key contain
* @param[out]       verifyPtr           Holds a pointer to the memory location which will contain the result of the certificate verification
*
* @return           Result of the operation
* @retval           E_OK            Request successful
* @retval           E_NOT_OK        Request failed
* @retval           CRYPTO_E_BUSY   Request failed, Crypto Driver Object is busy
*
* @api
*
* @pre
*
* @implements  Crypto_CertificateVerify_Activity   
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(Std_ReturnType, CRYPTO_CODE) Crypto_CertificateVerify
(
    VAR  (uint32,                  AUTOMATIC                  ) cryptoKeyId,
    VAR  (uint32,                  AUTOMATIC                  ) verifyCryptoKeyId,
    P2VAR(Crypto_VerifyResultType, AUTOMATIC, CRYPTO_APPL_DATA) verifyPtr
)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = (Std_ReturnType)E_NOT_OK;

#if (STD_ON == CRYPTO_KEYS_EXIST)
    VAR(uint32, AUTOMATIC) u32CryptoKeyIdIdx       = Crypto_Util_GetKeyIdIdx(cryptoKeyId);
    VAR(uint32, AUTOMATIC) u32VerifyCryptoKeyIdIdx = Crypto_Util_GetKeyIdIdx(verifyCryptoKeyId);

#if (STD_ON == CRYPTO_DEV_ERROR_DETECT)
    /* If the module is not yet initialized and if development error detection for the Crypto Driver is enabled, the function Crypto_CertificateVerify shall report CRYPTO_E_UNINIT to the DET and return E_NOT_OK. */
    if (CRYPTO_DRIVER_UNINIT == Crypto_eDriverState)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_CERTIFICATEVERIFY_ID, (uint8)CRYPTO_E_UNINIT);
    }
    /* If cryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_CertificateVerify shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    /* If verifyCryptoKeyId is out of range and if development error detection for the Crypto Driver is enabled, the function Crypto_CertificateVerify shall report CRYPTO_E_PARAM_HANDLE to the DET and return E_NOT_OK. */
    else if ((CRYPTO_INVALID_KEY_IDX_U32 == u32CryptoKeyIdIdx) || (CRYPTO_INVALID_KEY_IDX_U32 == u32VerifyCryptoKeyIdIdx))
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_CERTIFICATEVERIFY_ID, (uint8)CRYPTO_E_PARAM_HANDLE);
    }
    /* If the parameter verifyPtr is a null pointer and if development error detection for the Crypto Driver is enabled, the function Crypto_CertificateVerify shall report CRYPTO_E_PARAM_POINTER to the DET and return E_NOT_OK. */
    else if (NULL_PTR == verifyPtr)
    {
        (void)Det_ReportError((uint16)CRYPTO_MODULE_ID, (uint8)CRYPTO_INSTANCE_ID, (uint8)CRYPTO_CERTIFICATEVERIFY_ID, (uint8)CRYPTO_E_PARAM_POINTER);
    }
    else
#endif /* (STD_ON == CRYPTO_DEV_ERROR_DETECT) */
    {
        RetVal = Crypto_Ipw_CertificateVerify(u32CryptoKeyIdIdx, u32VerifyCryptoKeyIdIdx, verifyPtr);
    }
#else
    /* Avoid compiler warnings */
    (void)cryptoKeyId;
    (void)verifyCryptoKeyId;
    (void)verifyPtr;
#endif /* (STD_ON == CRYPTO_KEYS_EXIST) */

    return RetVal;
}

/**
* @brief            If asynchronous job processing is configured and there are job queues, the function is called cyclically to process queued jobs.
* @details          If asynchronous job processing is configured and there are job queues, the function is called cyclically to process queued jobs.
*
* @param[in]        none
*
* @return           void
*
* @api
*
* @pre
*
* @implements  Crypto_MainFunction_Activity
*
*/
/**
* @violates @ref Crypto_c_REF_3 Functions and objects should not be defined with external linkage if
* they are referenced in only one translation unit.
*/
FUNC(void, CRYPTO_CODE) Crypto_MainFunction (void)
{
    Crypto_Ipw_MainFunction();
}


#define CRYPTO_STOP_SEC_CODE
/**
* @violates @ref Crypto_c_REF_1 #include directives should only be preceded by preprocessor
* directives or comments.
*
* @violates @ref Crypto_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

/** @} */
