text: /***************************************************************************//**
  * \file cy_crypto_server.c
  * \version 2.30
  *
  * \brief
  *  This file provides the source code to the API for Crypto Server
  *  in the Crypto driver.
  *
  ********************************************************************************
  * Copyright 2016-2019 Cypress Semiconductor Corporation
  * SPDX-License-Identifier: Apache-2.0
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *    http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *******************************************************************************/
  
  
  #include "cy_device_headers.h"
  #include "cy_ipc_drv.h"
  #include "cy_sysint.h"
  #include "cy_syslib.h"
  #include "cy_crypto_common.h"
  #include "cy_crypto_server.h"
  #include "cy_crypto_core_aes.h"
  #include "cy_crypto_core_sha.h"
  #include "cy_crypto_core_hmac.h"
  #include "cy_crypto_core_cmac.h"
  #include "cy_crypto_core_prng.h"
  #include "cy_crypto_core_trng.h"
  #include "cy_crypto_core_rsa.h"
  #include "cy_crypto_core_mem.h"
  #include "cy_crypto_core_crc.h"
  #include "cy_crypto_core_des.h"
  #include "cy_crypto_core_hw.h"
  #include "cy_crypto_core_ecc.h"
  #include <stdbool.h>
  #include <string.h>
  
  #if defined(CY_IP_MXCRYPTO)
  
  /* The pointer to the CRYPTO instance. */
  #define CY_CRYPTO_BASE           ((CRYPTO_Type *)cy_device->cryptoBase)
  
  typedef struct
  {
      cy_crypto_prng_init_func_t   prngInitFunc;
      cy_crypto_prng_func_t        prngFunc;
      cy_crypto_trng_func_t        trngFunc;
      cy_crypto_aes_init_func_t    aesInitFunc;
      cy_crypto_aes_ecb_func_t     aesEcbFunc;
      cy_crypto_aes_cbc_func_t     aesCbcFunc;
      cy_crypto_aes_cfb_func_t     aesCfbFunc;
      cy_crypto_aes_ctr_func_t     aesCtrFunc;
      cy_crypto_cmac_func_t        cmacFunc;
      cy_crypto_sha_func_t         shaFunc;
      cy_crypto_hmac_func_t        hmacFunc;
      cy_crypto_memcpy_func_t      memCpyFunc;
      cy_crypto_memset_func_t      memSetFunc;
      cy_crypto_memcmp_func_t      memCmpFunc;
      cy_crypto_memxor_func_t      memXorFunc;
      cy_crypto_crc_init_func_t    crcInitFunc;
      cy_crypto_crc_func_t         crcFunc;
      cy_crypto_des_func_t         desFunc;
      cy_crypto_des_func_t         tdesFunc;
      cy_crypto_rsa_proc_func_t    rsaProcFunc;
      cy_crypto_rsa_coef_func_t    rsaCoefFunc;
      cy_crypto_rsa_ver_func_t     rsaVerifyFunc;
  } cy_stc_crypto_pfn_t;
  
  static cy_stc_crypto_pfn_t const *cy_CryptoFunctionTable = NULL;
  
  /*
   * The global variable to store a pointer to crypto processing context data.
   */
  cy_stc_crypto_context_t *processData = NULL;
  
  static cy_stc_crypto_server_context_t *cy_crypto_serverContext;
  
  /* Functions Prototypes */
  static cy_en_crypto_status_t Cy_Crypto_Core_CheckHwForErrors(cy_stc_crypto_context_t *cryptoContext);
  
  static cy_en_crypto_status_t Cy_Crypto_Server_Start_Common(cy_stc_crypto_config_t const *config,
                                               cy_stc_crypto_server_context_t *context);
  
  cy_en_crypto_status_t Cy_Crypto_Server_Start_Base(cy_stc_crypto_config_t const *config,
                                               cy_stc_crypto_server_context_t *context)
  {
      static const cy_stc_crypto_pfn_t cryptoV1BaseFuncs =
      {
          &Cy_Crypto_Core_V1_Prng_Init,
          &Cy_Crypto_Core_V1_Prng,
          &Cy_Crypto_Core_V1_Trng,
          NULL, /* Cy_Crypto_Core_V1_Aes_Init, */
          NULL, /* Cy_Crypto_Core_V1_Aes_Ecb,  */
          NULL, /* Cy_Crypto_Core_V1_Aes_Cbc,  */
          NULL, /* Cy_Crypto_Core_V1_Aes_Cfb,  */
          NULL, /* Cy_Crypto_Core_V1_Aes_Ctr,  */
          NULL, /* Cy_Crypto_Core_V1_Cmac,     */
          &Cy_Crypto_Core_V1_Sha,
          NULL, /* Cy_Crypto_Core_V1_Hmac,     */
          &Cy_Crypto_Core_V1_MemCpy,
          &Cy_Crypto_Core_V1_MemSet,
          &Cy_Crypto_Core_V1_MemCmp,
          &Cy_Crypto_Core_V1_MemXor,
          &Cy_Crypto_Core_V1_Crc_Init,
          &Cy_Crypto_Core_V1_Crc,
          &Cy_Crypto_Core_V1_Des,
          &Cy_Crypto_Core_V1_Tdes,
          NULL, /* Cy_Crypto_Core_Rsa_Proc,  */
          NULL, /* Cy_Crypto_Core_Rsa_Coef,  */
          NULL, /* Cy_Crypto_Core_RsaVerify, */
      };
  
      static const cy_stc_crypto_pfn_t cryptoV2BaseFuncs =
      {
          &Cy_Crypto_Core_V2_Prng_Init,
          &Cy_Crypto_Core_V2_Prng,
          &Cy_Crypto_Core_V2_Trng,
          NULL, /* Cy_Crypto_Core_V2_Aes_Init, */
          NULL, /* Cy_Crypto_Core_V2_Aes_Ecb,  */
          NULL, /* Cy_Crypto_Core_V2_Aes_Cbc,  */
          NULL, /* Cy_Crypto_Core_V2_Aes_Cfb,  */
          NULL, /* Cy_Crypto_Core_V2_Aes_Ctr,  */
          NULL, /* Cy_Crypto_Core_V2_Cmac,     */
          &Cy_Crypto_Core_V2_Sha,
          NULL, /* Cy_Crypto_Core_V2_Hmac,     */
          &Cy_Crypto_Core_V2_MemCpy,
          &Cy_Crypto_Core_V2_MemSet,
          &Cy_Crypto_Core_V2_MemCmp,
          &Cy_Crypto_Core_V2_MemXor,
          &Cy_Crypto_Core_V2_Crc_Init,
          &Cy_Crypto_Core_V2_Crc,
          &Cy_Crypto_Core_V2_Des,
          &Cy_Crypto_Core_V2_Tdes,
          NULL, /* Cy_Crypto_Core_Rsa_Proc,  */
          NULL, /* Cy_Crypto_Core_Rsa_Coef,  */
          NULL, /* Cy_Crypto_Core_RsaVerify, */
      };
  
      if (CY_CRYPTO_V1)
      {
          cy_CryptoFunctionTable = &cryptoV1BaseFuncs;
      }
      else
      {
          cy_CryptoFunctionTable = &cryptoV2BaseFuncs;
      }
      return Cy_Crypto_Server_Start_Common(config, context);
  }
  
  cy_en_crypto_status_t Cy_Crypto_Server_Start_Extra(cy_stc_crypto_config_t const *config,
                                               cy_stc_crypto_server_context_t *context)
  {
      static const cy_stc_crypto_pfn_t cryptoV1ExtraFuncs =
      {
          &Cy_Crypto_Core_V1_Prng_Init,
          &Cy_Crypto_Core_V1_Prng,
          &Cy_Crypto_Core_V1_Trng,
          &Cy_Crypto_Core_V1_Aes_Init,
          &Cy_Crypto_Core_V1_Aes_Ecb,
          &Cy_Crypto_Core_V1_Aes_Cbc,
          &Cy_Crypto_Core_V1_Aes_Cfb,
          &Cy_Crypto_Core_V1_Aes_Ctr,
          &Cy_Crypto_Core_V1_Cmac,
          &Cy_Crypto_Core_V1_Sha,
          &Cy_Crypto_Core_V1_Hmac,
          &Cy_Crypto_Core_V1_MemCpy,
          &Cy_Crypto_Core_V1_MemSet,
          &Cy_Crypto_Core_V1_MemCmp,
          &Cy_Crypto_Core_V1_MemXor,
          &Cy_Crypto_Core_V1_Crc_Init,
          &Cy_Crypto_Core_V1_Crc,
          &Cy_Crypto_Core_V1_Des,
          &Cy_Crypto_Core_V1_Tdes,
          NULL, /* Cy_Crypto_Core_Rsa_Proc,  */
          NULL, /* Cy_Crypto_Core_Rsa_Coef,  */
          NULL, /* Cy_Crypto_Core_RsaVerify, */
      };
  
      static const cy_stc_crypto_pfn_t cryptoV2ExtraFuncs =
      {
          &Cy_Crypto_Core_V2_Prng_Init,
          &Cy_Crypto_Core_V2_Prng,
          &Cy_Crypto_Core_V2_Trng,
          &Cy_Crypto_Core_V2_Aes_Init,
          &Cy_Crypto_Core_V2_Aes_Ecb,
          &Cy_Crypto_Core_V2_Aes_Cbc,
          &Cy_Crypto_Core_V2_Aes_Cfb,
          &Cy_Crypto_Core_V2_Aes_Ctr,
          &Cy_Crypto_Core_V2_Cmac,
          &Cy_Crypto_Core_V2_Sha,
          &Cy_Crypto_Core_V2_Hmac,
          &Cy_Crypto_Core_V2_MemCpy,
          &Cy_Crypto_Core_V2_MemSet,
          &Cy_Crypto_Core_V2_MemCmp,
          &Cy_Crypto_Core_V2_MemXor,
          &Cy_Crypto_Core_V2_Crc_Init,
          &Cy_Crypto_Core_V2_Crc,
          &Cy_Crypto_Core_V2_Des,
          &Cy_Crypto_Core_V2_Tdes,
          NULL, /* Cy_Crypto_Core_Rsa_Proc,  */
          NULL, /* Cy_Crypto_Core_Rsa_Coef,  */
          NULL, /* Cy_Crypto_Core_RsaVerify, */
      };
  
      if (CY_CRYPTO_V1)
      {
          cy_CryptoFunctionTable = &cryptoV1ExtraFuncs;
      }
      else
      {
          cy_CryptoFunctionTable = &cryptoV2ExtraFuncs;
      }
      return Cy_Crypto_Server_Start_Common(config, context);
  }
  
  cy_en_crypto_status_t Cy_Crypto_Server_Start_Full(cy_stc_crypto_config_t const *config,
                                               cy_stc_crypto_server_context_t *context)
  {
      static const cy_stc_crypto_pfn_t cryptoV1FullFuncs =
      {
          &Cy_Crypto_Core_V1_Prng_Init,
          &Cy_Crypto_Core_V1_Prng,
          &Cy_Crypto_Core_V1_Trng,
          &Cy_Crypto_Core_V1_Aes_Init,
          &Cy_Crypto_Core_V1_Aes_Ecb,
          &Cy_Crypto_Core_V1_Aes_Cbc,
          &Cy_Crypto_Core_V1_Aes_Cfb,
          &Cy_Crypto_Core_V1_Aes_Ctr,
          &Cy_Crypto_Core_V1_Cmac,
          &Cy_Crypto_Core_V1_Sha,
          &Cy_Crypto_Core_V1_Hmac,
          &Cy_Crypto_Core_V1_MemCpy,
          &Cy_Crypto_Core_V1_MemSet,
          &Cy_Crypto_Core_V1_MemCmp,
          &Cy_Crypto_Core_V1_MemXor,
          &Cy_Crypto_Core_V1_Crc_Init,
          &Cy_Crypto_Core_V1_Crc,
          &Cy_Crypto_Core_V1_Des,
          &Cy_Crypto_Core_V1_Tdes,
          &Cy_Crypto_Core_Rsa_Proc,
          &Cy_Crypto_Core_Rsa_Coef,
          &Cy_Crypto_Core_Rsa_Verify,
      };
  
      static const cy_stc_crypto_pfn_t cryptoV2FullFuncs =
      {
          &Cy_Crypto_Core_V2_Prng_Init,
          &Cy_Crypto_Core_V2_Prng,
          &Cy_Crypto_Core_V2_Trng,
          &Cy_Crypto_Core_V2_Aes_Init,
          &Cy_Crypto_Core_V2_Aes_Ecb,
          &Cy_Crypto_Core_V2_Aes_Cbc,
          &Cy_Crypto_Core_V2_Aes_Cfb,
          &Cy_Crypto_Core_V2_Aes_Ctr,
          &Cy_Crypto_Core_V2_Cmac,
          &Cy_Crypto_Core_V2_Sha,
          &Cy_Crypto_Core_V2_Hmac,
          &Cy_Crypto_Core_V2_MemCpy,
          &Cy_Crypto_Core_V2_MemSet,
          &Cy_Crypto_Core_V2_MemCmp,
          &Cy_Crypto_Core_V2_MemXor,
          &Cy_Crypto_Core_V2_Crc_Init,
          &Cy_Crypto_Core_V2_Crc,
          &Cy_Crypto_Core_V2_Des,
          &Cy_Crypto_Core_V2_Tdes,
          &Cy_Crypto_Core_Rsa_Proc,
          &Cy_Crypto_Core_Rsa_Coef,
          &Cy_Crypto_Core_Rsa_Verify,
      };
  
      if (CY_CRYPTO_V1)
      {
          cy_CryptoFunctionTable = &cryptoV1FullFuncs;
      }
      else
      {
          cy_CryptoFunctionTable = &cryptoV2FullFuncs;
      }
      return Cy_Crypto_Server_Start_Common(config, context);
  }
  
  static cy_en_crypto_status_t Cy_Crypto_Server_Start_Common(cy_stc_crypto_config_t const *config,
                                               cy_stc_crypto_server_context_t *context)
  {
      cy_israddress isrHandler;
  
      CY_ASSERT(NULL != config);
      CY_ASSERT(NULL != context);
      CY_ASSERT(NULL != cy_CryptoFunctionTable);
  
      context->ipcChannel = config->ipcChannel;
      context->acquireNotifierChannel = config->acquireNotifierChannel;
      context->getDataHandlerPtr  = config->userGetDataHandler;
      context->errorHandlerPtr    = config->userErrorHandler;
      context->isHwErrorOccured = false;
      context->acquireNotifierConfig.intrSrc = config->acquireNotifierConfig.intrSrc;
      context->cryptoErrorIntrConfig.intrSrc = config->cryptoErrorIntrConfig.intrSrc;
  
      Cy_Crypto_Core_HwInit();
  
      /* Initialize the interrupt controller for CM0+ and IPC Interrupt */
      if (config->userGetDataHandler != NULL)
      {
          isrHandler = config->userGetDataHandler;
      }
      else
      {
          isrHandler = &Cy_Crypto_Server_GetDataHandler;
      }
  
      (void)Cy_SysInt_Init(&config->acquireNotifierConfig, isrHandler);
  
      NVIC_EnableIRQ(config->acquireNotifierConfig.intrSrc);
  
      /* Do not bring up an IPC release interrupt here, only set up a notify interrupt */
      Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(config->acquireNotifierChannel),
                                                        CY_IPC_NO_NOTIFICATION, (1uL << config->ipcChannel));
  
      /* Initialize and enable an interrupt to handle possible Crypto HW errors */
      if (config->userErrorHandler != NULL)
      {
          isrHandler = config->userErrorHandler;
      }
      else
      {
          isrHandler = &Cy_Crypto_Server_ErrorHandler;
      }
  
      (void)Cy_SysInt_Init(&config->cryptoErrorIntrConfig, isrHandler);
  
      NVIC_ClearPendingIRQ(config->cryptoErrorIntrConfig.intrSrc);
      NVIC_EnableIRQ(config->cryptoErrorIntrConfig.intrSrc);
  
      Cy_Crypto_Core_SetInterruptMask(CY_CRYPTO_BASE, CY_CRYPTO_INTR_MASK_ERROR_MASK);
  
      cy_crypto_serverContext = context;
  
      return (CY_CRYPTO_SUCCESS);
  }
  
  cy_en_crypto_status_t Cy_Crypto_Server_Stop(void)
  {
      if (NULL != cy_crypto_serverContext)
      {
          uint32_t interruptMask;
  
          /* Disable the Notify interrupt from IPC */
          NVIC_DisableIRQ(cy_crypto_serverContext->acquireNotifierConfig.intrSrc);
          NVIC_ClearPendingIRQ(cy_crypto_serverContext->acquireNotifierConfig.intrSrc);
  
          /* Disable the Error interrupt from Crypto */
          NVIC_DisableIRQ(cy_crypto_serverContext->cryptoErrorIntrConfig.intrSrc);
          NVIC_ClearPendingIRQ(cy_crypto_serverContext->cryptoErrorIntrConfig.intrSrc);
          Cy_Crypto_Core_SetInterruptMask(CY_CRYPTO_BASE, 0u);
  
          /* Disable CRYPTO IPC interrupt */
          interruptMask = Cy_IPC_Drv_ExtractAcquireMask(Cy_IPC_Drv_GetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(cy_crypto_serverContext->acquireNotifierChannel)));
  
          Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(cy_crypto_serverContext->acquireNotifierChannel),
                                                            CY_IPC_NO_NOTIFICATION,
                                                            interruptMask & ~(1uL << cy_crypto_serverContext->ipcChannel));
  
          cy_crypto_serverContext->getDataHandlerPtr = NULL;
          cy_crypto_serverContext->errorHandlerPtr = NULL;
          cy_crypto_serverContext = NULL;
          cy_CryptoFunctionTable  = NULL;
      }
  
      return (CY_CRYPTO_SUCCESS);
  }
  
  void Cy_Crypto_Server_ErrorHandler(void)
  {
      uint32_t interrupts;
      interrupts = Cy_Crypto_Core_GetInterruptStatus(CY_CRYPTO_BASE) & CY_CRYPTO_INTR_ERROR_MASK;
  
      if (interrupts != 0u)
      {
          Cy_Crypto_Core_ClearInterrupt(CY_CRYPTO_BASE, interrupts);
  
          if (false == cy_crypto_serverContext->isHwErrorOccured)
          {
              /* HW error is not captured before */
              cy_crypto_serverContext->hwErrorStatus.errorStatus0 = REG_CRYPTO_ERROR_STATUS0(CY_CRYPTO_BASE);
              cy_crypto_serverContext->hwErrorStatus.errorStatus1 = REG_CRYPTO_ERROR_STATUS1(CY_CRYPTO_BASE);
  
              cy_crypto_serverContext->isHwErrorOccured = true;
          }
          else
          {
              /* HW error is already captured by Cy_Crypto_Core_CheckHwForErrors function */
              cy_crypto_serverContext->isHwErrorOccured = false;
          }
      }
  }
  
  void Cy_Crypto_Server_Process(void)
  {
      cy_stc_crypto_context_t* myData = processData;
  
      if (myData != NULL)
      {
          /* Default error */
          myData->resp = CY_CRYPTO_HW_NOT_ENABLED;
  
          if (CY_CRYPTO_INSTR_ENABLE == myData->instr)
          {
              myData->resp = Cy_Crypto_Core_Enable(CY_CRYPTO_BASE);
          }
          else
          {
              /* Check if Crypto HW is enabled */
              if (Cy_Crypto_Core_IsEnabled(CY_CRYPTO_BASE))
              {
                  myData->resp = CY_CRYPTO_NOT_SUPPORTED;
  
                  if (NULL != cy_CryptoFunctionTable)
                  {
                      switch(myData->instr)
                      {
                      case CY_CRYPTO_INSTR_DISABLE:
                           myData->resp = Cy_Crypto_Core_Disable(CY_CRYPTO_BASE);
                          break;
  
                      case CY_CRYPTO_INSTR_SRV_INFO:
                           myData->resp = Cy_Crypto_Core_GetLibInfo((cy_en_crypto_lib_info_t*)myData->xdata);
                          break;
  
                      /* MEM_BUFF memory management */
                      case CY_CRYPTO_INSTR_MEMBUF_SET:
                          {
                              cy_stc_crypto_context_str_t *cfContext = myData->xdata;
                              myData->resp = Cy_Crypto_Core_SetVuMemoryAddress(CY_CRYPTO_BASE, cfContext->src0, cfContext->dataSize);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_MEMBUF_ADDR:
                          {
                              cy_stc_crypto_context_str_t *cfContext = myData->xdata;
                              *(uint32_t *)(cfContext->dst) = (uint32_t)Cy_Crypto_Core_GetVuMemoryAddress(CY_CRYPTO_BASE);
                              myData->resp = CY_CRYPTO_SUCCESS;
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_MEMBUF_SIZE:
                          {
                              cy_stc_crypto_context_str_t *cfContext = myData->xdata;
                              *(uint32_t *)(cfContext->dst) = Cy_Crypto_Core_GetVuMemorySize(CY_CRYPTO_BASE);
                              myData->resp = CY_CRYPTO_SUCCESS;
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_PRNG_INIT:
                          if (NULL != cy_CryptoFunctionTable->prngInitFunc)
                          {
                              cy_stc_crypto_context_prng_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->prngInitFunc)(CY_CRYPTO_BASE,
                                  cfContext->lfsr32InitState, cfContext->lfsr31InitState, cfContext->lfsr29InitState);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_PRNG:
                          if (NULL != cy_CryptoFunctionTable->prngFunc)
                          {
                              cy_stc_crypto_context_prng_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->prngFunc)(CY_CRYPTO_BASE,
                                  cfContext->max, cfContext->prngNum);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_TRNG:
                          if (NULL != cy_CryptoFunctionTable->trngFunc)
                          {
                              cy_stc_crypto_context_trng_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->trngFunc)(CY_CRYPTO_BASE,
                                  cfContext->GAROPol, cfContext->FIROPol, cfContext->max, cfContext->trngNum);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_AES_INIT:
                          if (NULL != cy_CryptoFunctionTable->aesInitFunc)
                          {
                              cy_stc_crypto_context_aes_t *cfContext = (cy_stc_crypto_context_aes_t *)myData->xdata;
                              myData->resp =
                                  (cy_CryptoFunctionTable->aesInitFunc)(CY_CRYPTO_BASE,
                                      (uint8_t*)cfContext->key, cfContext->keyLength, &cfContext->aesState, (cy_stc_crypto_aes_buffers_t *)(Cy_Crypto_Core_GetVuMemoryAddress(CY_CRYPTO_BASE)));
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_AES_ECB:
                          if (NULL != cy_CryptoFunctionTable->aesEcbFunc)
                          {
                              cy_stc_crypto_context_aes_t *cfContext = (cy_stc_crypto_context_aes_t *)myData->xdata;
                              myData->resp =
                                  (cy_CryptoFunctionTable->aesEcbFunc)(CY_CRYPTO_BASE,
                                  cfContext->dirMode,
                                  (uint8_t*)cfContext->dst,
                                  (uint8_t*)cfContext->src,
                                  &cfContext->aesState);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_AES_CBC:
                          if (NULL != cy_CryptoFunctionTable->aesCbcFunc)
                          {
                              cy_stc_crypto_context_aes_t *cfContext = (cy_stc_crypto_context_aes_t *)myData->xdata;
                              myData->resp =
                                  (cy_CryptoFunctionTable->aesCbcFunc)(CY_CRYPTO_BASE,
                                      cfContext->dirMode,
                                      cfContext->srcSize,
                                      (uint8_t*)cfContext->ivPtr,
                                      (uint8_t*)cfContext->dst,
                                      (uint8_t*)cfContext->src,
                                      &cfContext->aesState);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_AES_CFB:
                          if (NULL != cy_CryptoFunctionTable->aesCfbFunc)
                          {
                              cy_stc_crypto_context_aes_t *cfContext = (cy_stc_crypto_context_aes_t *)myData->xdata;
                              myData->resp =
                                  (cy_CryptoFunctionTable->aesCfbFunc)(CY_CRYPTO_BASE,
                                      cfContext->dirMode,
                                      cfContext->srcSize,
                                      (uint8_t*)cfContext->ivPtr,
                                      (uint8_t*)cfContext->dst,
                                      (uint8_t*)cfContext->src,
                                      &cfContext->aesState);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_AES_CTR:
                          if (NULL != cy_CryptoFunctionTable->aesCtrFunc)
                          {
                              cy_stc_crypto_context_aes_t *cfContext = (cy_stc_crypto_context_aes_t *)myData->xdata;
                              myData->resp =
                                  (cy_CryptoFunctionTable->aesCtrFunc)(CY_CRYPTO_BASE,
                                      cfContext->srcSize,
                                      cfContext->srcOffset,
                                      (uint8_t*)cfContext->ivPtr,
                                      (uint8_t*)cfContext->streamBlock,
                                      (uint8_t*)cfContext->dst,
                                      (uint8_t*)cfContext->src,
                                      &cfContext->aesState);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_CMAC:
                          if (NULL != cy_CryptoFunctionTable->cmacFunc)
                          {
                              cy_stc_crypto_context_aes_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->cmacFunc)(CY_CRYPTO_BASE,
                                  (uint8_t*)cfContext->src, cfContext->srcSize, (uint8_t*)cfContext->key, cfContext->keyLength,
                                  (uint8_t*)cfContext->dst, &cfContext->aesState);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_SHA:
                          if (NULL != cy_CryptoFunctionTable->shaFunc)
                          {
                              cy_stc_crypto_context_sha_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->shaFunc)(CY_CRYPTO_BASE,
                                  (uint8_t *)cfContext->message, cfContext->messageSize,
                                  (uint8_t *)cfContext->dst, cfContext->mode);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_HMAC:
                          if (NULL != cy_CryptoFunctionTable->hmacFunc)
                          {
                              cy_stc_crypto_context_sha_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->hmacFunc)(CY_CRYPTO_BASE,
                                  (uint8_t *)cfContext->dst, (uint8_t *)cfContext->message, cfContext->messageSize,
                                  (uint8_t *)cfContext->key, cfContext->keyLength, cfContext->mode);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_MEM_CPY:
                          if (NULL != cy_CryptoFunctionTable->memCpyFunc)
                          {
                              cy_stc_crypto_context_str_t *cfContext = myData->xdata;
                              (cy_CryptoFunctionTable->memCpyFunc)(CY_CRYPTO_BASE,
                                  cfContext->dst, cfContext->src0, (uint16_t)cfContext->dataSize);
                              myData->resp = CY_CRYPTO_SUCCESS;
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_MEM_SET:
                          if (NULL != cy_CryptoFunctionTable->memSetFunc)
                          {
                              cy_stc_crypto_context_str_t *cfContext = myData->xdata;
                              (cy_CryptoFunctionTable->memSetFunc)(CY_CRYPTO_BASE,
                                  cfContext->dst, (uint8_t)cfContext->data, (uint16_t)cfContext->dataSize);
                              myData->resp = CY_CRYPTO_SUCCESS;
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_MEM_CMP:
                          if (NULL != cy_CryptoFunctionTable->memCmpFunc)
                          {
                              cy_stc_crypto_context_str_t *cfContext = myData->xdata;
                              *(uint32_t *)(cfContext->dst) =
                                  (cy_CryptoFunctionTable->memCmpFunc)(CY_CRYPTO_BASE,
                                      cfContext->src0, cfContext->src1, (uint16_t)cfContext->dataSize);
                              myData->resp = CY_CRYPTO_SUCCESS;
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_MEM_XOR:
                          if (NULL != cy_CryptoFunctionTable->memXorFunc)
                          {
                              cy_stc_crypto_context_str_t *cfContext = myData->xdata;
                              (cy_CryptoFunctionTable->memXorFunc)(CY_CRYPTO_BASE,
                                  cfContext->dst, cfContext->src0, cfContext->src1, (uint16_t)cfContext->dataSize);
                              myData->resp = CY_CRYPTO_SUCCESS;
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_CRC_INIT:
                          if (NULL != cy_CryptoFunctionTable->crcInitFunc)
                          {
                              cy_stc_crypto_context_crc_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->crcInitFunc)(CY_CRYPTO_BASE,
                                  cfContext->polynomial, cfContext->dataReverse, cfContext->dataXor, cfContext->remReverse, cfContext->remXor);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_CRC:
                          if (NULL != cy_CryptoFunctionTable->crcFunc)
                          {
                              cy_stc_crypto_context_crc_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->crcFunc)(CY_CRYPTO_BASE,
                                  cfContext->crc, cfContext->data, cfContext->dataSize, cfContext->lfsrInitState);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_DES:
                          if (NULL != cy_CryptoFunctionTable->desFunc)
                          {
                              cy_stc_crypto_context_des_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->desFunc)(CY_CRYPTO_BASE,
                                  cfContext->dirMode, (uint8_t const *)cfContext->key, (uint8_t *)cfContext->dst, (uint8_t const *)cfContext->src);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_3DES:
                          if (NULL != cy_CryptoFunctionTable->tdesFunc)
                          {
                              cy_stc_crypto_context_des_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->tdesFunc)(CY_CRYPTO_BASE,
                                  cfContext->dirMode, (uint8_t const *)cfContext->key, (uint8_t *)cfContext->dst, (uint8_t  const *)cfContext->src);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_RSA_PROC:
                          if (NULL != cy_CryptoFunctionTable->rsaProcFunc)
                          {
                              cy_stc_crypto_context_rsa_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->rsaProcFunc)(CY_CRYPTO_BASE,
                                  cfContext->key, (uint8_t const *)cfContext->message, cfContext->messageSize, (uint8_t *)cfContext->result);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_RSA_COEF:
                          if (NULL != cy_CryptoFunctionTable->rsaCoefFunc)
                          {
                              cy_stc_crypto_context_rsa_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->rsaCoefFunc)(CY_CRYPTO_BASE, cfContext->key);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_RSA_VER:
                          if (NULL != cy_CryptoFunctionTable->rsaVerifyFunc)
                          {
                              cy_stc_crypto_context_rsa_ver_t *cfContext = myData->xdata;
                              myData->resp = (cy_CryptoFunctionTable->rsaVerifyFunc)(CY_CRYPTO_BASE,
                                  cfContext->verResult, cfContext->digestType, (uint8_t const *)cfContext->hash,
                                  (uint8_t const *)cfContext->decryptedSignature, cfContext->decryptedSignatureLength);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_ECDSA_SIGN:
                          {
                              cy_stc_crypto_context_ecc_t *cfContext = myData->xdata;
                              myData->resp = Cy_Crypto_Core_ECC_SignHash(CY_CRYPTO_BASE,
                                  cfContext->src0, cfContext->datalen, cfContext->dst0,
                                  cfContext->key, cfContext->src1);
                          }
                          break;
  
                      case CY_CRYPTO_INSTR_ECDSA_VER:
                          {
                              cy_stc_crypto_context_ecc_t *cfContext = myData->xdata;
                              myData->resp = Cy_Crypto_Core_ECC_VerifyHash(CY_CRYPTO_BASE,
                                  cfContext->src1, cfContext->src0, cfContext->datalen,
                                  cfContext->dst0, cfContext->key);
                          }
                          break;
  
                      default:
                          myData->resp = CY_CRYPTO_NOT_SUPPORTED;
                          break;
                      }
                  }
  
                  if (CY_CRYPTO_SUCCESS == myData->resp)
                  {
                      myData->resp = Cy_Crypto_Core_CheckHwForErrors(myData);
                  }
              }
          }
  
          processData = NULL;
  
          /* Release the Crypto IPC channel with the Release interrupt */
          (void)Cy_IPC_Drv_LockRelease(Cy_IPC_Drv_GetIpcBaseAddress(myData->ipcChannel),
                  (NULL != myData->userCompleteCallback) ? (1uL << myData->releaseNotifierChannel) : CY_IPC_NO_NOTIFICATION);
      }
  }
  
  void Cy_Crypto_Server_GetDataHandler(void)
  {
      uint32_t interruptMasked;
  
      /*
       * Check that there is really the IPC Crypto Notify interrupt,
       * because the same line can be used for the IPC Crypto Release interrupt.
       */
  
      interruptMasked = Cy_IPC_Drv_ExtractAcquireMask(Cy_IPC_Drv_GetInterruptStatusMasked(
                                           Cy_IPC_Drv_GetIntrBaseAddr(cy_crypto_serverContext->acquireNotifierChannel)));
  
      if ((1uL << (cy_crypto_serverContext->ipcChannel)) == interruptMasked )
      {
          Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(cy_crypto_serverContext->acquireNotifierChannel), CY_IPC_NO_NOTIFICATION, interruptMasked);
  
          if(CY_IPC_DRV_SUCCESS == Cy_IPC_Drv_ReadMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(cy_crypto_serverContext->ipcChannel), (void**)&processData))
          {
              if (cy_crypto_serverContext->getDataHandlerPtr == NULL)
              {
                  Cy_Crypto_Server_Process();
              }
          }
      }
  }
  
  /*******************************************************************************
  * Function Name: Cy_Crypto_Core_CheckHwForErrors
  ****************************************************************************//**
  *
  * The function checks if a Crypto HW error occurred. If yes, copies the error
  * information from the Crypto registers to the communication structure.
  *
  * This function available for CM0+ core only.
  *
  * This function is internal and should not to be called directly by user software
  *
  * \param base
  * The pointer to the CRYPTO instance.
  *
  * \param cryptoContext
  * The pointer to cy_stc_crypto_context_t structure which stores
  * the Crypto driver context.
  *
  * \return
  * \ref cy_en_crypto_status_t
  *
  *******************************************************************************/
  static cy_en_crypto_status_t Cy_Crypto_Core_CheckHwForErrors(cy_stc_crypto_context_t *cryptoContext)
  {
      cy_en_crypto_status_t tmpResult = CY_CRYPTO_SUCCESS;
      uint32_t myErrorStatus0;
      uint32_t myErrorStatus1;
  
      CY_ASSERT(NULL != cryptoContext);
  
      if (false == cy_crypto_serverContext->isHwErrorOccured)
      {
          /* HW error is not captured before */
          myErrorStatus0 = REG_CRYPTO_ERROR_STATUS0(CY_CRYPTO_BASE);
          myErrorStatus1 = REG_CRYPTO_ERROR_STATUS1(CY_CRYPTO_BASE);
  
          if (_FLD2VAL(CRYPTO_ERROR_STATUS1_VALID, myErrorStatus1) == 1u)
          {
              tmpResult = CY_CRYPTO_HW_ERROR;
  
              cy_crypto_serverContext->isHwErrorOccured = true;
          }
      }
      else
      {
          /* HW error is already captured by error interrupt handler */
          myErrorStatus0 = cy_crypto_serverContext->hwErrorStatus.errorStatus0;
          myErrorStatus1 = cy_crypto_serverContext->hwErrorStatus.errorStatus1;
  
          if (_FLD2VAL(CRYPTO_ERROR_STATUS1_VALID, myErrorStatus1) == 1u)
          {
              tmpResult = CY_CRYPTO_HW_ERROR;
          }
  
          cy_crypto_serverContext->isHwErrorOccured = false;
      }
  
      cryptoContext->hwErrorStatus.errorStatus0 = myErrorStatus0;
      cryptoContext->hwErrorStatus.errorStatus1 = myErrorStatus1;
  
      return (tmpResult);
  }
  
  #endif /* CY_IP_MXCRYPTO */
  
  
  /* [] END OF FILE */
  