
  /*
   *  Object %name    : %
   *  State           :  %state%
   *  Creation date   :  25 Dec. 2008
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief A brief description of this module
   *
   *  \version CRYS_AESCCM.c#1:csrc:6
   *  \author R.Levin
   *  \remarks Copyright (C) 2008 by Discretix Technologies Ltd.
   *           All Rights reserved
   */



/************* Include Files ****************/

/* .............. CRYS level includes ................. */

#include "DX_VOS_Mem.h"
#include "DX_VOS_Memmap.h"
#include "DX_VOS_Sem.h"
#include "error.h"
#include "CRYS_AESCCM_error.h"
#include "CRYS_AESCCM.h"
#include "CRYS_COMMON.h"
#include "SEPDriver.h" 
#include "crys_host_op_code.h"
#include "gen.h"


/* .............. LLF level includes .................. */

 
/******************************** Defines ******************************/

/* canceling the lint warning:
   Use of goto is deprecated */
/*lint --e{801} */

/************************* MACROS ***************************************/

/* this macro is required to remove compilers warnings if the AESCCM 
   is not supported */
#if (defined CRYS_NO_AESCCM_SUPPORT || defined CRYS_NO_AES_SUPPORT)
#define RETURN_IF_AESCCM_UNSUPPORTED( a , b , c , d , e , f , g , h , i , j , k , l , m , n , o , p , q , r , s , t , u , v , w , x, y ) \
  (a)=0;(b)=0;(c)=0;(d)=0;(e)=0;(f)=0;(g)=0;(h)=0;(i)=0;(j)=0;(k)=0;(l)=0;(m)=0;(n)=0;(o)=0;(p)=0;(q)=0;(r)=0;(s)=0; \
  (t)=0;(u)=0;(v)=0;(w)=0;(x)=0;(y)=0; \
  (a)=(a);(b)=(b);(c)=(c);(d)=(d);(e)=(e);(f)=(f);(g)=(g);(h)=(h);(i)=(i);(j)=(j);(k)=(k);(l)=(l);(m)=(m);(n)=(n); \
  (o)=o;(p)=p;(q)=q;(r)=r;(s)=s;(t)=t;(u)=u;(v)=v;(w)=w;(x)=x;(y)=y; \
   return CRYS_AESCCM_IS_NOT_SUPPORTED
#else  /* !CRYS_NO_AESCCM_SUPPORT */
#define RETURN_IF_AESCCM_UNSUPPORTED( a , b , c , d , e , f , g , h , i , j , k , l , m , n , o , p , q , r , s , t ,u , v , w , x, y) 
#endif /* !CRYS_NO_AESCCM_SUPPORT */


#ifndef CRYS_NO_EXT_IF_MODE_SUPPORT
extern CRYSError_t  CRYS_CALLBACK_Handler();
#else
#define CRYS_CALLBACK_Handler DX_NULL
#endif

/* the minimum and maximum macros */
#undef min
#define min( a , b ) ( ( (a) < (b) ) ? (a) : (b) )

#undef max    
#define max( a , b ) ( ( (a) > (b) ) ? (a) : (b) )

/************************ Global Data ***********************************/

/********************* Private functions  *******************************/

/************************ Public Functions ******************************/


/****************************************************************************************************/
/** 
* @brief This function transfers the AESCCM_init function parameters from HOST to
*        SEP and backwards for operating AESCCM_init    .
*
*        1. Validates all of the inputs of the function. If one of the received 
*           parameters is not valid it shall return an error:
*        2. Locks the access to SEP.
*        3. Initializes the message buffers by input parameners and send the message to SEP.
*        4. Wait to SEP response and reads the replay message into output parameters and buffers.
*        5. Setss sizes of formatted additional (without padding) and text data in the 
*           RemainAsize and RemainTextSize fields of CCM context.
*        6. Unlocks the SEP.
*        7. Exits the handler with the Error code.
*
*         
* @param[in] ContextID_ptr - A pointer to the AESCCM context buffer, that is allocated by the user 
*                            and is used for the AESCCM operations.
* @param[in] EncrDecrMode  - Enumerator variable defining operation mode (0 - encrypt; 1 - decrypt).
* @param[in] CCM_Key       - A buffer, containing the AESCCM key passed by user (predefined size 128 bits).
* @param[in] AdataSize     - Full size of additional data in bytes, which must be processed.  
*                            Limitation in our implementation is: AdataSize < 2^32. If Adata is absent, 
*                            then AdataSize = 0.
* @param[in] TextSizeQ     - The full size of text data (in bytes), which must be processed by CCM. 
*                            Limitation in our implementation is: TextSizeQ < 2^32 on decrypt mode 
*                            and less, than 2^32-SizeOfT on encrypt mode. 
* @param[in] QFieldSize    - Byte-size of formatted field for writing significant bytes of the TextSizeQ 
*                            value. Valid values: [2,3,4,5,6,7,8]. 
* @param[in] N_ptr	       - A pointer to Nonce - unique value assigned to all data passed into CCM.
*                            Bytes order - big endian form (MSB is the first).
* @param[in] SizeOfN       - The size of the user passed Nonce (in bytes). 	Valid values: 
*                            7 <= SizeOfN <= (15-QFieldSize). 
* @param[in] SizeOfT	   - Size of AESCCM MAC output T in bytes. Valid values: [4,6,8,10,12,14,16].   
*
*
* @return CRYSError_t - On success CRYS_OK is returned, on failure an error according to CRYS_AESCCM_error.h
*
*/
CEXPORT_C CRYSError_t  CRYS_AESCCM_Init( 
										CRYS_AESCCM_UserContext_t   *ContextID_ptr,
										CRYS_AES_EncryptMode_t       EncrDecrMode,
										CRYS_AESCCM_Key_t            CCM_Key,   /*AESCCM key*/            
										DxUint32_t                   AdataSize, /*full size of additional data*/
										DxUint32_t                   TextSizeQ, /*full size of text data*/
										DxUint8_t                    QFieldSize,/*size of Q field in control block*/
										DxUint8_t                   *N_ptr,     /*Nonce*/
										DxUint8_t                    SizeOfN,   /*size of N buffer*/
										DxUint8_t                    SizeOfT )  /*size of CCM-MAC (T) */

{
   /* FUNCTION DECLARATIONS */

   /* The return error identifiers */
   CRYSError_t Error;
   
   DxUint32_t sramOffset;

   /* message parameters */
   DxUint32_t  messageParam[12] = {0};
   
   /* max length of message */
   DxUint32_t  maxLength;
   
      
   /* FUNCTION LOGIC */
   
   /* ............... local initializations .............................. */
   /* -------------------------------------------------------------------- */
   
   /* initializing the Error to O.K */
   Error = CRYS_OK;
      
   /* ............... if not supported exit .............................. */
   /* -------------------------------------------------------------------- */   
    
   RETURN_IF_AESCCM_UNSUPPORTED( ContextID_ptr , EncrDecrMode , CCM_Key[0] , AdataSize , 
                                 TextSizeQ , QFieldSize , N_ptr , SizeOfN , SizeOfT , 
                                 sramOffset , messageParam , maxLength , temp_ptr , 
								 Error , Error , Error , Error , Error , Error , 
								 Error , Error , Error , Error , Error , Error);
                              
#if !(defined CRYS_NO_AESCCM_SUPPORT || defined CRYS_NO_AES_SUPPORT)                              
      
   /* -------------------------------------------------------------------- */
   /* ............... checking the parameters validity ................... */
   /* -------------------------------------------------------------------- */
   
   /* if the users context ID pointer is DX_NULL return an error */
   if( ContextID_ptr == DX_NULL )
      return CRYS_AESCCM_INVALID_USER_CONTEXT_POINTER_ERROR;
      
   /* Check the Encrypt / Decrypt mode */
   if( EncrDecrMode >= CRYS_AES_EncryptNumOfOptions )
	   return  CRYS_AESCCM_INVALID_ENCRYPT_MODE_ERROR;

   /* check Key and Nonce pointers */    
   if( CCM_Key == DX_NULL || N_ptr == DX_NULL )
      return  CRYS_AESCCM_ILLEGAL_PARAMETER_PTR_ERROR;     
   
   /* check the Q field size: according to our implementation QFieldSize <= 4*/ 
   if( QFieldSize < 2 || QFieldSize > 8 )      
	   return  CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR;

   /* check, that actual size of TextData is not great, than its control field size */
   if( (QFieldSize < 4) && ((TextSizeQ >> (QFieldSize*8)) > 0) )
      return CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR;

   /* check Nonce size. Note: QFieldSize + SizeOfN <= 15 */ 
   if( SizeOfN < 7 || SizeOfN > 15 - QFieldSize )      
      return  CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR; 

    /* check CCM MAC size: [4,6,8,10,12,14,16] */ 
   if( SizeOfT < 4   || SizeOfT > 16  || (SizeOfT & 1) != 0 )      
	   return  CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR;


   /*----------------------------*/
   /*  lock access to the SEP    */
   /*----------------------------*/
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function;
   }
   
   /*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);

   /* set input parameters into message buffer */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_INIT_OP_CODE;
   messageParam[1] = EncrDecrMode;
   messageParam[2] = AdataSize;
   messageParam[3] = TextSizeQ;
   messageParam[4] = QFieldSize;
   messageParam[5] = SizeOfN;
   messageParam[6] = SizeOfT;
   
   /* send opcode, key and next 3 arguments */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            7*sizeof(DxUint32_t),
                            7*sizeof(DxUint32_t),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* copy Key and Nonce into the message */
   DX_VOS_MemSetZero( (DxUint8_t*)messageParam, 2*CRYS_AES_BLOCK_SIZE_IN_BYTES );
   DX_VOS_FastMemCpy( (DxUint8_t*)messageParam, (DxUint8_t*)CCM_Key, sizeof(CRYS_AESCCM_Key_t));
   DX_VOS_FastMemCpy( (DxUint8_t*)messageParam + CRYS_AES_BLOCK_SIZE_IN_BYTES, N_ptr, SizeOfN);

   /* send Nonce */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                             8*sizeof(DxUint32_t),
                             8*sizeof(DxUint32_t), 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*---------------------------------------------*/
   /*  reading the replay message from the SEP    */
   /*---------------------------------------------*/
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DxUint32_t)messageParam,
                            sizeof(DxUint32_t) * 2,
                            sizeof(DxUint32_t) * 2,
                            &sramOffset ,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_INIT_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check status */
   if(messageParam[1] != CRYS_OK)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
   
   /* read the context */
   maxLength = ((sizeof(CRYS_AESCCM_UserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);

   Error = SEPDriver_ReadParamater((DxUint32_t)ContextID_ptr,
                            sizeof(CRYS_AESCCM_UserContext_t),
                            maxLength,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
                                 
   /* ...................... end of function ................................ */   

end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();


end_function:   

 return Error;

  
#endif /* !CRYS_NO_AESCCM_SUPPORT */
   

}/* END OF CRYS_AESCCM_Init */   
                         


/****************************************************************************************************/
/** 
* @brief This function transfers the CRYS_AESCCM_BlockAdata function parameters from HOST to
*        SEP and backwards for operating CRYS_AESCCM_BlockAdata on SEP.
*
*        1. Validates all of the inputs of the function. If one of the received 
*           parameters is not valid it shall return an error:
*        2. Locks the access to SEP.
*        3. Initializes the message buffers by input parameners and send the message to SEP.
*        4. Wait to SEP response and reads the replay message into output parameters and buffers.
*        5. Setss sizes of formatted additional (without padding) and text data in the 
*           RemainAsize and RemainTextSize fields of CCM context.
*        6. Unlocks the SEP.
*        7. Exits the handler with the Error code.
*
* @param[in] ContextID_ptr - A pointer to the AESCCM context buffer allocated by the user that
*                            is used for the AESCCM machine operation. This should be the same 
*                            context that was used on the previous call of this session.
* @param[in] DataIn_ptr - A pointer to the buffer of the input additional data. 
*                         The pointer does not need to be aligned. On CSI input mode the 
*                         pointer must be equal to value (0xFFFFFFFC | DataInAlignment). 
* @param[in] DataInSize   - A size of the additional data in bytes. 
* @return CRYSError_t - On success CRYS_OK is returned, on failure an error according to
*                       CRYS_AESCCM_error.h
*   Notes:   
*      1. Temporary the CSI input or output are not allowed on CCM mode.
*      2. Size of input data in each intermediate block must be multiple of 16 bytes and great, than 0, 
*         excluding the last block which may have any size.
*
*/
CEXPORT_C CRYSError_t  CRYS_AESCCM_BlockAdata( 
											CRYS_AESCCM_UserContext_t    *ContextID_ptr,   
											DxUint8_t                    *DataIn_ptr,
											DxUint32_t                    DataInSize )
 {                              
   /* FUNCTION DECLARATIONS */

   /* The return error identifier */
   CRYSError_t Error;
   
    /* address of the first table in the input list */
   DxUint32_t         firstInputLLITableAddr;
   
   /* number of entries in  the first input tables */
   DxUint32_t         numInTableEntries;
   
   /* size of data in the first table */
   DxUint32_t         firstTableSize;
   
   /* sram offset */
   DxUint32_t         sramOffset;
  
   /* message parameters */
   DxUint32_t         messageParam[10] = {0};
   
   /* max length */
   DxUint32_t         maxLength;
   
   /* remaining Data size  */
   DxUint32_t         remainDataSize, dataForDmaSize, dataSizeToContext;
   
   AESCCM_Context_t    *ccmWorkingContext_ptr;
   
   CRYS_AESCCM_DataType_t CurrentDataType;
  

   /******************* FUNCTION LOGIC *************************************/
  
   /* ............... local initializations .............................. */
   /* -------------------------------------------------------------------- */
   
   /* initializing the Error to O.K */
   Error = CRYS_OK;

   /* ............... if not supported exit .............................. */
   /* -------------------------------------------------------------------- */   
      
   RETURN_IF_AESCCM_UNSUPPORTED( 
                          ContextID_ptr , DataIn_ptr , DataInSize , Error , firstInputLLITableAddr , 
                          numInTableEntries , firstTableSize , sramOffset , messageParam , 
                          maxLength , remainDataSize ,  dataForDmaSize , dataSizeToContext ,                           
                          ccmWorkingContext_ptr , CurrentDataType , Error , Error , Error , Error , 
						  Error , Error , Error , Error , Error , Error );
                              

#if !(defined CRYS_NO_AESCCM_SUPPORT || defined CRYS_NO_AES_SUPPORT)

   /* -------------------------------------------------------------------- */
   /* ............... checking the parameters validity ................... */
   /* -------------------------------------------------------------------- */

   /* if the users context ID pointer is DX_NULL return an error */
   if( ContextID_ptr == DX_NULL )   
      return CRYS_AESCCM_INVALID_USER_CONTEXT_POINTER_ERROR;
   
   /* if the users Data In pointer is illegal return an error */
   if( DataIn_ptr == DX_NULL )   
      return CRYS_AESCCM_DATA_IN_POINTER_INVALID_ERROR;

   if( (DxUint32_t)DataIn_ptr >= DX_CSI )   
   	   return CRYS_AESCCM_CSI_IN_OUT_ILLEGAL_MODE_ERROR; 
  

	   
   /* ----------------------------------------------------------------------- */ 
   /* ...... checking the data size and data in / out overlapping ........... */
   /* ----------------------------------------------------------------------- */ 

   /* set variables */
   ccmWorkingContext_ptr  = (AESCCM_Context_t*)ContextID_ptr->context_buff;
   CurrentDataType = ccmWorkingContext_ptr->CurrentDataType;
   
   /* check the data type mode */
   if( CurrentDataType > CRYS_AESCCM_LastAdata )
   	   return  CRYS_AESCCM_ILLEGAL_DATA_TYPE_ERROR;
 
    /* if all Adata was processed, then additional block is not permitted:  return an Error */
   if( ccmWorkingContext_ptr->RemainAdataSize == 0 )
   	   return  CRYS_AESCCM_ADDITIONAL_BLOCK_NOT_PERMITTED_ERROR;

   /* if size of all Adata to process equal to 0, then return error */
   if( DataInSize + ccmWorkingContext_ptr->lastBlockSize == 0 )	   
   	   return  CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;

   /* check that DataInSize is not great, than remaining Adata size */
   if( DataInSize + ccmWorkingContext_ptr->lastBlockSize > ccmWorkingContext_ptr->RemainAdataSize )
   	   return  CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;
   
   if( DataInSize + ccmWorkingContext_ptr->lastBlockSize < ccmWorkingContext_ptr->RemainAdataSize )
   {
	   /* if data size is not multiple of 16 bytes */
	   if( DataInSize % CRYS_AES_BLOCK_SIZE_IN_BYTES != 0 || 
	       DataInSize == 0 )   

		   return CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL; 
   }
   
   
   /* ------------------------------------------------------------------------------ */
   /* ..........................  setting message parameters ....................... */   
   /* ------------------------------------------------------------------------------ */
 
   /* send the message to SEP */
   
   sramOffset = 0;
   maxLength = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
   
   /* set input parameters into message buffer */
 
   /* set op code into message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_BLOCK_ADATA_OP_CODE;


   /* zeroe head-tail message bufers for padding data by 0-s */
   DX_VOS_MemSetZero( (DxUint8_t*)&messageParam[1], 2*CRYS_AES_BLOCK_SIZE_IN_BYTES );

   /* set Adata into message head buffer for filling the context lastBlock in SEP */
   if( ccmWorkingContext_ptr->lastBlockSize + DataInSize >= CRYS_AES_BLOCK_SIZE_IN_BYTES )
   {
	   /* the size of the data to write into context */
	   dataSizeToContext = CRYS_AES_BLOCK_SIZE_IN_BYTES - ccmWorkingContext_ptr->lastBlockSize;
       
       /* copy data to head of message*/    
       DX_VOS_FastMemCpy( (DxUint8_t*)&messageParam[1], DataIn_ptr, dataSizeToContext);
       
       /* update input pointer and size */
	   DataIn_ptr += dataSizeToContext;
   }
   
   else /* may occur only for last block */
   {   
       dataSizeToContext = DataInSize;
      
       DX_VOS_FastMemCpy( (DxUint8_t*)&messageParam[1], DataIn_ptr, 
		                  min(CRYS_AES_BLOCK_SIZE_IN_BYTES - ccmWorkingContext_ptr->lastBlockSize, DataInSize) );
   }
   
   /* calculate remaining size (not full last AES block) for sending it by tail of message */
   remainDataSize = (DataInSize - dataSizeToContext) % CRYS_AES_BLOCK_SIZE_IN_BYTES; 
   
   /* size of data for transferring by DMA */
   dataForDmaSize = DataInSize - dataSizeToContext - remainDataSize;
 

   /* set remaining data into tail of the message */
   if ( remainDataSize > 0 )
   {
	   DX_VOS_FastMemCpy( (DxUint8_t*)&(messageParam[1])+CRYS_AES_BLOCK_SIZE_IN_BYTES, DataIn_ptr + dataForDmaSize,  
		                   remainDataSize );
   }

   
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
      goto End;
   }

   /* send head-tail message              */
   /*-------------------------------------*/
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            sizeof(DxUint32_t) * 9,
                            sizeof(DxUint32_t) * 9,
                            &sramOffset, 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   

   /* send other parameters               */
   /*-------------------------------------*/
   
   /* set message head and tail sizes into message buffer */
   messageParam[0] = dataSizeToContext; /* head */
   messageParam[1] = remainDataSize;    /* tail */
 
   /*  create MLLI table for input data   */
   Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)DataIn_ptr,
                                                 dataForDmaSize,
                                                 CRYS_AES_BLOCK_SIZE_IN_BYTES,
                                                 &firstInputLLITableAddr,
                                                 &numInTableEntries,
                                             &firstTableSize); 
   if(Error != DX_OK)
   {
      goto end_function_unlock;
   }
   
   /* set MLLI paramters: address, entries count and LLI data size */
   messageParam[2] = firstInputLLITableAddr;  /* MLLI tab addr */
   messageParam[3] = numInTableEntries;       /* MLLI tab enries count */
   messageParam[4] = firstTableSize;          /* MLLI data size */

   /* send the sizes and LLI parameters message */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            sizeof(DxUint32_t) * 5,
                            sizeof(DxUint32_t) * 5,
                            &sramOffset, 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /*   send context                      */
   /*-------------------------------------*/
   
   maxLength = ((sizeof(CRYS_AESCCM_UserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);

   Error = SEPDriver_WriteParamater((DxUint32_t)ContextID_ptr , 
                            sizeof(CRYS_AESCCM_UserContext_t) ,
                            maxLength, 
                            &sramOffset , 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   
   /* end message                        */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_WaitForResponse(SEP_DRIVER_POLLING , 0 , CRYS_CALLBACK_Handler , SEP_DRIVER_TIMEOUT_WAIT_FOR_INIFINITY);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------------------------------------------
      start reading replay message from the SEP 
   ---------------------------------------------------------*/ 
   
   /* free the tables */
   Error = SEPDriver_FreeDMATables();
   if(Error)
   {
       goto end_function_unlock;
   }
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
       goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DxUint32_t)messageParam,
                           sizeof(DxUint32_t) * 2,
                           sizeof(DxUint32_t) * 2, 
                           &sramOffset,
                           DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_BLOCK_ADATA_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check the status */
   if(messageParam[1] != CRYS_OK)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }

   /* read the context */
   maxLength = ((sizeof(CRYS_AESCCM_UserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);

   Error = SEPDriver_ReadParamater((DxUint32_t)ContextID_ptr,
                           sizeof(CRYS_AESCCM_UserContext_t),
                           maxLength,
                           &sramOffset,
                           DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
end_function_unlock:

   /* lock access to the SEP */
   SEPDriver_Unlock();
   
End:

 
   /* ................. end of function ..................................... */
   /* ----------------------------------------------------------------------- */
  
   return Error;
   
#endif /* !CRYS_NO_AESCCM_SUPPORT */


}/* END OF CRYS_AESCCM_BlockAdata */ 


/****************************************************************************************************/
/** 
* @brief This function transfers the CRYS_AESCCM_BlockTextData function parameters from HOST to
*        SEP and backwards for operating CRYS_AESCCM_BlockTextData on SEP.
*
*        1. Validates all of the inputs of the function. If one of the received 
*           parameters is not valid it shall return an error:
*        2. Locks the access to SEP.
*        3. Initializes the message buffers by input parameners and send the message to SEP.
*        4. Wait to SEP response and reads the replay message into output parameters and buffers.
*        5. Setss sizes of formatted additional (without padding) and text data in the 
*           RemainAsize and RemainTextSize fields of CCM context.
*        6. Unlocks the SEP.
*        7. Exits the handler with the Error code.
*
* @param[in] ContextID_ptr - A pointer to the AESCCM context buffer allocated by the user that
*                            is used for the AES machine operation. This should be the same 
*                            context that was used on the previous call of this session.
* @param[in] DataIn_ptr - A pointer to the buffer of the input data (plain or cipher text). 
*                         The pointer does not need to be aligned. On CSI input mode the 
*                         pointer must be equal to value (0xFFFFFFFC | DataInAlignment). 
* @param[in] DataInSize  - A size of the data block in bytes: must be multiple of 16 bytes and not Null.
*                          The block of data must be not a last block, that means:
*                            - on Encrypt mode: DataInSize < CCM_Context->RemainTextSize;
*                            - on Decrypt mode: DataInSize < CCM_Context->RemainTextSize - SizeOfT;
* @param[in] DataOut_ptr - A pointer to the output buffer (cipher or plain text). 
*                          The pointer does not need to be aligned. On CSI input mode the 
*                          pointer must be equal to value (0xFFFFFFFC | DataOutAlignment).
*                          Size of the output buffer must be not less, than DataInSize. 
*
* @return CRYSError_t - On success CRYS_OK is returned, on failure a
*                       value MODULE_* CRYS_AESCCM_error.h
*   Notes:   
*      1. Temporary the CSI input or output are not allowed on CCM mode.
*      2. Overlapping of the in-out buffers is not allowed, excluding the in placement case:
*         DataIn_ptr = DataOut_ptr.
*
*/
CEXPORT_C CRYSError_t  CRYS_AESCCM_BlockTextData( 
												CRYS_AESCCM_UserContext_t    *ContextID_ptr,   
												DxUint8_t                    *DataIn_ptr,
												DxUint32_t                    DataInSize,
												DxUint8_t                    *DataOut_ptr )
 {                              
   /* FUNCTION DECLARATIONS */

   /* The return error identifier */
   CRYSError_t Error;
   
    /* address of the first table in the input list */
   DxUint32_t         firstInputLLITableAddr;
   
   /* address of the first table in the output list */
   DxUint32_t         firstOutputLLITableAddr;
   
   /* number of entries in  the first input tables */
   DxUint32_t         numInTableEntries;
   
   /* number of entries in  the first pitput tables */
   DxUint32_t         numOutTableEntries;
   
   /* size of data in the first table */
   DxUint32_t         firstTableSize;
   
   /* sram offset */
   DxUint32_t         sramOffset;
  
   /* message parameters */
   DxUint32_t         messageParam[10] = {0};
   
   /* max length */
   DxUint32_t         maxLength;
   
   AESCCM_Context_t    *ccmWorkingContext_ptr;
   

   /******************* FUNCTION LOGIC *************************************/
  
 
   /* ............... local initializations .............................. */
   /* -------------------------------------------------------------------- */
   
   /* initializing the Error to O.K */
   Error = CRYS_OK;

   /* ............... if not supported exit .............................. */
   /* -------------------------------------------------------------------- */   
      
   RETURN_IF_AESCCM_UNSUPPORTED( 
                          ContextID_ptr , DataIn_ptr , DataInSize , DataOut_ptr , firstInputLLITableAddr , 
                          firstOutputLLITableAddr , numInTableEntries , numOutTableEntries , firstTableSize ,
                          sramOffset , messageParam , maxLength , ccmWorkingContext_ptr , Error ,  Error ,                               
                          Error , Error , Error , Error , Error , Error , Error , Error , Error , Error );
                              
#if !(defined CRYS_NO_AESCCM_SUPPORT || defined CRYS_NO_AES_SUPPORT)


	/* ............... first checking the parameters ...................... */
	/* -------------------------------------------------------------------- */

	/* if the users context ID pointer is DX_NULL return an error */
	if( ContextID_ptr == DX_NULL )   
		return CRYS_AESCCM_INVALID_USER_CONTEXT_POINTER_ERROR;

	/* if the users Data In pointer is illegal return an error */
	if( DataIn_ptr == DX_NULL )   
		return CRYS_AESCCM_DATA_IN_POINTER_INVALID_ERROR;

	/* if the Data In size is 0, return an error */
	if( DataInSize == 0 )   
		return CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;

	if( ((DxUint32_t)DataIn_ptr >= DX_CSI) /*&& ((DxUint32_t)DataOut_ptr >= DX_CSI)*/ )   
		return CRYS_AESCCM_CSI_IN_OUT_ILLEGAL_MODE_ERROR; 

	/* if the users Data Out pointer is illegal return an error */
	if( DataOut_ptr == DX_NULL )   
		return CRYS_AESCCM_DATA_OUT_POINTER_INVALID_ERROR;
   
	/* check that DataInsize is multiple of AES-block size */
	if( DataInSize % CRYS_AES_BLOCK_SIZE_IN_BYTES != 0 )
		return CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR;


	/* ...... checking the data size and data in/out overlapping ............. */
	/* ----------------------------------------------------------------------- */ 
	
    /* set variables */
    ccmWorkingContext_ptr  = (AESCCM_Context_t*)ContextID_ptr->context_buff;


	/* ...... checking the data size and data in/out overlapping ............. */
	/* ----------------------------------------------------------------------- */ 

	/* check that the current block is not the last block (i.e. DataInSize is not less, 
	   than remaining TextData size according to Encrypt-Decrypt mode */
	if( ccmWorkingContext_ptr->CCM_EncryptMode == CRYS_AES_Encrypt  )
	{
		/* check that the current block is not the last block */
		if( ccmWorkingContext_ptr->RemainTextSize == 0 )
		{	  
			Error = CRYS_AESCCM_ADDITIONAL_BLOCK_NOT_PERMITTED_ERROR;
			goto End;
		}

		if( DataInSize >= ccmWorkingContext_ptr->RemainTextSize )
		{	  
			Error = CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;
			goto End;
		}
	}
	else  /* Decrypt mode */
	{
		if( ccmWorkingContext_ptr->RemainTextSize < ccmWorkingContext_ptr->SizeOfT )
		{	  
			Error = CRYS_AESCCM_ADDITIONAL_BLOCK_NOT_PERMITTED_ERROR;
			goto End;
		}

		if( ccmWorkingContext_ptr->RemainTextSize < DataInSize )
		{	  
			Error = CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;
			goto End;
		}
	}

	/* check overlapping of input-output buffers: overlapping is not allowed, excluding 
	   in placement, i.e. DataIn_ptr = DataOut_ptr */
	if( DataIn_ptr != DataOut_ptr )
	{
		/* checking the case that the input buffer is in a higher address then the output buffer */
		if ( DataIn_ptr > DataOut_ptr )
		{
			/* if after adding the size to the data out pointer it is larger then the data in pointer, 
			return the overlap error */
			if( DataOut_ptr + DataInSize > DataIn_ptr )   

				return CRYS_AESCCM_DATA_OUT_DATA_IN_OVERLAP_ERROR; 

		}/* end of DataIn_ptr > DataOut_ptr */   

		/* checking the case that the output buffer is in a higher address then the input buffer */      
		else
		{
			/* if after adding the size to the data in pointer it is larger then the data out pointer 
			return the overlap error */
			if( DataIn_ptr + DataInSize > DataOut_ptr )   

				return CRYS_AESCCM_DATA_OUT_DATA_IN_OVERLAP_ERROR; 

		}/* end of DataOut_ptr > DataIn_ptr */   
	}
	   
     
   /* ------------------------------------------------------------------------------ */
   /* ..........................  setting message parameters ....................... */   
   /* ------------------------------------------------------------------------------ */
 
   /* send the message to SEP */
   
   sramOffset = 0;
   maxLength = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);


   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
      goto End;
   }
   
   /* set op code into message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_BLOCK_TDATA_OP_CODE;

 
   /* ............... create MLLI table for in/out data .................. */
   /*----------------------------------------------------------------------*/
   
   Error = SEPDriver_PrepareSymDMATables(  (DxUint32_t)DataIn_ptr,
                                           (DxUint32_t)DataOut_ptr,
                                           DataInSize,
                                           CRYS_AES_BLOCK_SIZE_IN_BYTES/*tabBlockSizer*/,
                                           &firstInputLLITableAddr,
                                           &firstOutputLLITableAddr,
                                           &numInTableEntries,
                                           &numOutTableEntries,
                                           &firstTableSize); 
   if(Error != DX_OK)
   {
      goto end_function_unlock;
   }
	   
   /* set MLLI paramters: address, entries count and LLI data size */
   
   messageParam[1] = firstInputLLITableAddr;   /* MLLI tab addr */
   messageParam[2] = numInTableEntries;        /* MLLI tab enries count */
   messageParam[3] = firstOutputLLITableAddr;  /* MLLI tab addr */
   messageParam[4] = numOutTableEntries;       /* MLLI tab enries count */
   messageParam[5] = firstTableSize;           /* MLLI data size */

 
   /* send the LLI message */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
		                            sizeof(DxUint32_t) * 6,
		                            sizeof(DxUint32_t) * 6,
		                            &sramOffset, 
		                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send context */
   maxLength = ((sizeof(CRYS_AESCCM_UserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);

   Error = SEPDriver_WriteParamater((DxUint32_t)ContextID_ptr , 
		                            sizeof(CRYS_AESCCM_UserContext_t) ,
		                            maxLength, 
		                            &sramOffset , 
		                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_WaitForResponse(SEP_DRIVER_POLLING , 0 , CRYS_CALLBACK_Handler , SEP_DRIVER_TIMEOUT_WAIT_FOR_INIFINITY);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------------------------------------------
      start reading message from the SEP 
   ---------------------------------------------------------*/ 
   
   /* free the tables */
   Error = SEPDriver_FreeDMATables();
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
    goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater(
                           (DxUint32_t)messageParam,
                           sizeof(DxUint32_t) * 2,
                           sizeof(DxUint32_t) * 2, 
                           &sramOffset,
                           DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_BLOCK_TDATA_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check the status */
   if(messageParam[1] != CRYS_OK)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }

   
   /* read the context */
   maxLength = ((sizeof(CRYS_AESCCM_UserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);

   Error = SEPDriver_ReadParamater((DxUint32_t)ContextID_ptr,
                           sizeof(CRYS_AESCCM_UserContext_t),
                           maxLength,
                           &sramOffset,
                           DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
end_function_unlock:

   /* lock access to the SEP */
   SEPDriver_Unlock();
   
End:
   /* ................. end of function ..................................... */
   /* ----------------------------------------------------------------------- */
  
   return Error;
   
#endif /* !CRYS_NO_AESCCM_SUPPORT */


}/* END OF CRYS_AESCCM_BlockTextData */



/****************************************************************************************************/
/** 
* @brief This function transfers the CRYS_AESCCM_BlockLastTextData function parameters from HOST to
*        SEP and backwards for operating CRYS_AESCCM_BlockLastTextData on SEP.
*
*        1. Validates all of the inputs of the function. If one of the received 
*           parameters is not valid it shall return an error:
*        2. Locks the access to SEP.
*        3. Initializes the message buffers by input parameners and send the message to SEP.
*        4. Wait to SEP response and reads the replay message into output parameters and buffers.
*        5. Setss sizes of formatted additional (without padding) and text data in the 
*           RemainAsize and RemainTextSize fields of CCM context.
*        6. Unlocks the SEP.
*        7. Exits the handler with the Error code.
*
* @param[in] ContextID_ptr - A pointer to the AESCCM context buffer, allocated by the user, 
*                          that is used for the AESCCM operations. This should be the same 
*                          context that was used on the previous call of this session.
* @param[in] DataIn_ptr  - A pointer to the buffer of the input data (plain or cipher text). 
*                          The pointer does not need to be aligned. On CSI input mode the 
*                          pointer must be equal to value (0xFFFFFFFC | DataInAlignment). 
* @param[in] DataInSize  - A size of the data block in bytes. The size must be:
*                            - on encrypt mode: (2^32 - SizeOfT) > DataInSize >= 0;
*                            - on Decrypt mode: 2^32 > DataInSize >= SizeOfT (SizeOfT from context).
* @param[in] DataOut_ptr - A pointer to the output buffer (cipher or plain text). If on decrypt mode
*                          user passes only SizeOfT bytes the DataOut_ptr may be equal to NULL. 
*                          The pointer does not need to be aligned. On CSI input mode the 
*                          pointer must be equal to value (0xFFFFFFFC | DataOutAlignment).
* @param[in] DataOutSize - A size of the output buffer in bytes. The output size must be:
*                            - on encrypt mode: DataOutSize = DataInSize + SizeOfT;
*                            - on Decrypt mode: DataOutSize = DataInSize - SizeOfT;.
*
* @return CRYSError_t - On success CRYS_OK is returned, on failure a 
*                       value MODULE_* CRYS_AESCCM_error.h
*   Notes:   
*      1. Temporary the CSI input or output are not allowed on CCM mode.
*      2. Overlapping of the in-out buffers is not allowed, excluding the in placement case:
*         DataIn_ptr = DataOut_ptr.
*      3. If on decrypt mode user passes only SizeOfT bytes (encrypted CCM_MAC), then the 
*         DataOut_ptr may be equal to NULL.
*
*/
CEXPORT_C CRYSError_t  CRYS_AESCCM_BlockLastTextData( 
												CRYS_AESCCM_UserContext_t    *ContextID_ptr,   
												DxUint8_t                    *DataIn_ptr,
												DxUint32_t                    DataInSize,
												DxUint8_t                    *DataOut_ptr,
												DxUint32_t                    DataOutSize )
 {                              
   /* FUNCTION DECLARATIONS */

   /* The return error identifier */
   CRYSError_t Error;
   
    /* address of the first table in the input list */
   DxUint32_t         firstInputLLITableAddr;
   
   /* address of the first table in the output list */
   DxUint32_t         firstOutputLLITableAddr;
   
   /* number of entries in  the first input tables */
   DxUint32_t         numInTableEntries;
   
   /* number of entries in  the first pitput tables */
   DxUint32_t         numOutTableEntries;
   
   /* size of data in the first table */
   DxUint32_t         firstTableSize;
   
   /* sram offset */
   DxUint32_t         sramOffset;
  
   /* message parameters */
   DxUint32_t         messageParam[10];
   
   /* max length */
   DxUint32_t         maxLength;
   
   /* data sizes  */
   DxUint32_t  plainTextSize;
   DxUint32_t  tailSize, macSize;

   
   AESCCM_Context_t    *ccmWorkingContext_ptr;
   
  

   /******************* FUNCTION LOGIC *************************************/
  
   /* ............... local initializations .............................. */
   /* -------------------------------------------------------------------- */
   
   /* initializing the Error to O.K */
   Error = CRYS_OK;

   /* ............... if not supported exit .............................. */
   /* -------------------------------------------------------------------- */   
      
   RETURN_IF_AESCCM_UNSUPPORTED( 
                          ContextID_ptr , DataIn_ptr , DataInSize , DataOut_ptr , DataOutSize , 
                          firstInputLLITableAddr , firstOutputLLITableAddr , numInTableEntries ,
                          numOutTableEntries , firstTableSize , sramOffset , messageParam , maxLength ,                               
                          plainTextSize , tailSize , macSize , dataForDmaSize , ccmWorkingContext_ptr , 
                          Error ,Error , Error , Error ,  Error , Error , Error );
                              

#if !(defined CRYS_NO_AESCCM_SUPPORT || defined CRYS_NO_AES_SUPPORT)

   /* -------------------------------------------------------------------- */
   /* ............... checking the parameters validity ................... */
   /* -------------------------------------------------------------------- */

	/* if the users context ID pointer is DX_NULL return an error */
	if( ContextID_ptr == DX_NULL )   
		return CRYS_AESCCM_INVALID_USER_CONTEXT_POINTER_ERROR;

	/* if the users Data In pointer is illegal return an error */
	if( DataIn_ptr == DX_NULL )   
		return CRYS_AESCCM_DATA_IN_POINTER_INVALID_ERROR;

	/* if the Data In size is 0, return an error */
	if( DataInSize == 0 )   
		return CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;

	if( ((DxUint32_t)DataIn_ptr >= DX_CSI) /*&& ((DxUint32_t)DataOut_ptr >= DX_CSI)*/ )   
		return CRYS_AESCCM_CSI_IN_OUT_ILLEGAL_MODE_ERROR; 

	/* if the users Data Out pointer is illegal return an error */
	if( DataOut_ptr == DX_NULL )   
		return CRYS_AESCCM_DATA_OUT_POINTER_INVALID_ERROR;

    /* set variables */
    ccmWorkingContext_ptr  = (AESCCM_Context_t*)ContextID_ptr->context_buff;
    macSize = ccmWorkingContext_ptr->SizeOfT;


	/* ...... checking the data sizes and data in/out overlapping ............ */
	/* ----------------------------------------------------------------------- */ 

	/* check that the current block is the last: i.e. DataInSize is equal to 
	   remaining TextData size */
	if( DataInSize != ccmWorkingContext_ptr->RemainTextSize )
	{	  
		Error = CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;
		goto End;
	}

	/* check the data Sizes on decrypt mode */
	if( ccmWorkingContext_ptr->CCM_EncryptMode == CRYS_AES_Decrypt)
	{

		if( DataInSize <= macSize )
		{
			Error = CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;
			goto End;
		}

		plainTextSize = DataInSize - macSize;

		if( DataOutSize != plainTextSize )
		{
			Error = CRYS_AESCCM_DATA_OUT_SIZE_INVALID_ERROR;
			goto End;
		}
	}
	else /* check on encrypt mode */
	{
		
		/* check, that text dataIn size */
		if( DataInSize  >= 0xFFFFFFFF - macSize )
			return  CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL; 

		if( DataInSize == 0 )
		{
			Error = CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;
			goto End;
		}

		plainTextSize = DataInSize;

        /* check text dataOut size */
		if( DataOutSize != DataInSize + macSize )
		{
			Error = CRYS_AESCCM_DATA_OUT_SIZE_INVALID_ERROR;
			goto End;
		}
	}
    
	/* check overlapping of input-output buffers: overlapping is not allowed, excluding 
	   in placement, i.e. DataIn_ptr = DataOut_ptr */
	if( DataIn_ptr != DataOut_ptr )
	{
		/* checking the case that the input buffer is in a higher address then the output buffer */
		if ( DataIn_ptr > DataOut_ptr )
		{
			/* if begin of DataIn buffer is inside the DataOut buffer, return the overlap error */			
			if( DataIn_ptr < DataOut_ptr + DataOutSize  )
			{
				Error = CRYS_AESCCM_DATA_OUT_DATA_IN_OVERLAP_ERROR;
				goto End;
			}
		}/* end of DataIn_ptr > DataOut_ptr */   

		/* checking the case, that the output buffer is in a lower address then the input buffer */      
		else
		{
			/* if begin of DataOut buffer is inside the DataIn buffer, return the overlap error */
			if( DataOut_ptr < DataIn_ptr + DataInSize  )
			{
				Error = CRYS_AESCCM_DATA_OUT_DATA_IN_OVERLAP_ERROR; 
				goto End;
			}
		}/* end of DataOut_ptr > DataIn_ptr */ 
	}
	   
     
   /* ------------------------------------------------------------------------------ */
   /* ..........................  setting message parameters ....................... */   
   /* ------------------------------------------------------------------------------ */
 
   /* send the message to SEP */
   
   sramOffset = 0;
   maxLength = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);

   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
      goto End;
   }
   
   /* set op code into message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_BLOCK_LAST_TDATA_OP_CODE;

   /* zeroe head-ccmMac message bufers for padding data by 0-s */
   DX_VOS_MemSetZero( (DxUint8_t*)messageParam+4, 2*CRYS_AES_BLOCK_SIZE_IN_BYTES );

 
   /* set remaining plain TextData ( size < 16 bytes) into message tail buffer */
   tailSize = plainTextSize % CRYS_AES_BLOCK_SIZE_IN_BYTES;

   /* copy data to tail */    
   DX_VOS_FastMemCpy( (DxUint8_t*)messageParam+4, DataIn_ptr + plainTextSize - tailSize, tailSize);
   
   /* on decrypt mode set encrypted MAC into message */
   if( ccmWorkingContext_ptr->CCM_EncryptMode == CRYS_AES_Decrypt )
   {
       DX_VOS_FastMemCpy( (DxUint8_t*)messageParam + 4 + CRYS_AES_BLOCK_SIZE_IN_BYTES, 
                          DataIn_ptr + plainTextSize, macSize );
   }
   

   /* send tail and encrypted ccmMAC messages */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            sizeof(DxUint32_t) * 9,
                            sizeof(DxUint32_t) * 9,
                            &sramOffset, 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

  
   /* send other parameters        */
   /*------------------------------*/
   
   /* set tail and ccmMAC sizes into message  buffer */
   messageParam[0] = tailSize; 
   messageParam[1] = macSize;
 
   /*  create MLLI table for in/out data          */
   
   if( plainTextSize >= CRYS_AES_BLOCK_SIZE_IN_BYTES )
   {
     Error = SEPDriver_PrepareSymDMATables((DxUint32_t)DataIn_ptr,
                                           (DxUint32_t)DataOut_ptr,
                                           plainTextSize - tailSize,
                                           CRYS_AES_BLOCK_SIZE_IN_BYTES/*tabBlockSizer*/,
                                           &firstInputLLITableAddr,
                                           &firstOutputLLITableAddr,
                                           &numInTableEntries,
                                           &numOutTableEntries,
                                           &firstTableSize); 
	   if(Error != DX_OK)
	   {
	      goto end_function_unlock;
	   }
	   
	   /* set MLLI paramters: address, entries count and LLI data size */
	   messageParam[2] = firstInputLLITableAddr;   /* MLLI tab addr */
	   messageParam[3] = numInTableEntries;        /* MLLI tab enries count */
	   messageParam[4] = firstOutputLLITableAddr;  /* MLLI tab addr */
	   messageParam[5] = numOutTableEntries;       /* MLLI tab enries count */
	   messageParam[6] = firstTableSize;           /* MLLI data size */
   }
   
   else
   {
	   messageParam[2] = 0;   /* in MLLI tab addr */
	   messageParam[3] = 0;   /* in MLLI tab enries count */
   	   messageParam[4] = 0;   /* out MLLI tab addr */
	   messageParam[5] = 0;   /* out MLLI tab enries count */
	   messageParam[6] = 0;   /* MLLI data size */
   }

   /* send the LLI message */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
		                            sizeof(DxUint32_t) * 7,
		                            sizeof(DxUint32_t) * 7,
		                            &sramOffset, 
		                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send context */
   maxLength = ((sizeof(CRYS_AESCCM_UserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);

   Error = SEPDriver_WriteParamater((DxUint32_t)ContextID_ptr , 
		                            sizeof(CRYS_AESCCM_UserContext_t) ,
		                            maxLength, 
		                            &sramOffset , 
		                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_WaitForResponse(SEP_DRIVER_POLLING , 0 , CRYS_CALLBACK_Handler , SEP_DRIVER_TIMEOUT_WAIT_FOR_INIFINITY);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------------------------------------------
      start reading message from the SEP 
   ---------------------------------------------------------*/ 
   
   /* free the tables */
   Error = SEPDriver_FreeDMATables();
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
    goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater(
                           (DxUint32_t)messageParam,
                           sizeof(DxUint32_t) * 2,
                           sizeof(DxUint32_t) * 2, 
                           &sramOffset,
                           DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_BLOCK_LAST_TDATA_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check the status */
   if(messageParam[1] != CRYS_OK)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }

   /* read tail and ccmMac from SEP               */
   /*---------------------------------------------*/

   Error = SEPDriver_ReadParamater(
                           (DxUint32_t)messageParam,
                           8 * sizeof(DxUint32_t),
                           8 * sizeof(DxUint32_t),
                           &sramOffset,
                           DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
  
   /* output remainder of processed data */
   if( tailSize > 0 )
   {
      /* copy tail data into output */
      DX_VOS_FastMemCpy( DataOut_ptr + plainTextSize - tailSize, (DxUint8_t*)&messageParam[0], tailSize );
   }

   /* on encrypt mode copy encrypted ccmMac into output text buffer */
   if( ccmWorkingContext_ptr->CCM_EncryptMode == CRYS_AES_Encrypt )
   {
      DX_VOS_FastMemCpy( DataOut_ptr + plainTextSize, (DxUint8_t*)&messageParam[4], macSize );
   }

   /* read the context */
   maxLength = ((sizeof(CRYS_AESCCM_UserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);

   Error = SEPDriver_ReadParamater((DxUint32_t)ContextID_ptr,
                           sizeof(CRYS_AESCCM_UserContext_t),
                           maxLength,
                           &sramOffset,
                           DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
end_function_unlock:

   /* lock access to the SEP */
   SEPDriver_Unlock();
   
End:

 
   /* ................. end of function ..................................... */
   /* ----------------------------------------------------------------------- */
  
   return Error;
   
#endif /* !CRYS_NO_AESCCM_SUPPORT */


}/* END OF CRYS_AESCCM_BlockLastTextData */ 



/****************************************************************************************************/
/** 
* @brief This function transfers the CRYS_AESCCM_Finish function parameters from HOST to
*        SEP and backwards for operating the CRYS_AESCCM_Finish function on SEP.
*
*        1. Validates all of the inputs of the function. If one of the received 
*           parameters is not valid it shall return an error:
*        2. Locks the access to SEP.
*        3. Initializes the message buffers by input parameners and send the message to SEP.
*        4. Wait to SEP response and reads the replay message into output parameters and buffers.
*        6. Unlocks the SEP.
*        7. Exits the handler with the Error code.
*
 * @param[in] ContextID_ptr - A pointer to the AESCCM context buffer allocated by the user that
 *                            should be the same context that was used on the previous call
 *                            of this session.
 *
 * @return CRYSError_t    - On success CRYS_OK is returned, on failure an error according to CRYS_AESCCM_error.h.
 *
 */
CEXPORT_C CRYSError_t  CRYS_AESCCM_Finish( CRYS_AESCCM_UserContext_t   *ContextID_ptr )
{                              
   
   /* FUNCTION DECLARATIONS */

   /* The return error identifier */
   CRYSError_t  Error;
   
   /* sram offset */
   DxUint32_t   sramOffset;
   
   /* read parameter */
   DxUint32_t   messageParam[2];
   
   /* max length */
   DxUint32_t   maxLength;
  
   /*-----------------------
      CODE
   ------------------------*/
  
   /* ............... if not supported exit .............................. */
   /* -------------------------------------------------------------------- */   
      
   RETURN_IF_AESCCM_UNSUPPORTED( 
                          ContextID_ptr , sramOffset ,messageParam , maxLength , Error ,  Error , Error ,  
                          Error ,Error , Error , Error ,  Error , Error , Error , Error , Error , Error ,
                          Error ,Error , Error , Error ,  Error , Error , Error , Error );
                              

#if !(defined CRYS_NO_AESCCM_SUPPORT || defined CRYS_NO_AES_SUPPORT)


   /* initializing the Error to O.K */
   Error = CRYS_OK; 
   
   /* for preventing compiler warnings */
   ContextID_ptr->valid_tag = ContextID_ptr->valid_tag;
                               
   
   /* ............... checking the parameters validity ................... */
   /* -------------------------------------------------------------------- */

   /* if the users context ID pointer is DX_NULL return an error */
   if( ContextID_ptr == DX_NULL )
   {
      Error = CRYS_AESCCM_INVALID_USER_CONTEXT_POINTER_ERROR;
      goto end_function;
   }
   
   
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function;
   }
   
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
  
   /* prepare message  */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_FINISH_OP_CODE;
   
   /* send message */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            sizeof(DxUint32_t),
                            sizeof(DxUint32_t),
                            &sramOffset, 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send context */
   maxLength = ((sizeof(CRYS_AESCCM_UserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
   Error = SEPDriver_WriteParamater((DxUint32_t)ContextID_ptr , 
                             sizeof(CRYS_AESCCM_UserContext_t) , 
                             maxLength,
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* end message */
   SEPDriver_EndMessage(sramOffset);
   
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/ 
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
    goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater((DxUint32_t)messageParam ,
                           sizeof(DxUint32_t) * 2,
                           sizeof(DxUint32_t) * 2,
                           &sramOffset , 
                           DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_FINISH_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check the status */
   if(messageParam[1] != CRYS_OK)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }
  
end_function_unlock:
          
   /* lock access to the SEP */
   SEPDriver_Unlock();
      
   /* ................. end of function ..................................... */
   /* ----------------------------------------------------------------------- */
end_function:
  
   return Error;
   
#endif /* !CRYS_NO_AESCCM_SUPPORT */   
   
 
}/* END OF CRYS_AESCCM_Finish */ 



/****************************************************************************************************/
/**
 * @brief This function is used to perform the AES_CCM operation in one integrated process. 
 *
 *        The function preforms CCM algorithm according to NIST 800-38C by call the CRYS_CCM
 *        Init, Block and Finish functions. 
 *
 *        The input-output parameters of the function are the following:
 *
 * @param[in] EncrDecrMode  - Enumerator variable defining operation mode (0 - encrypt; 1 - decrypt).
 * @param[in] CCM_Key       - A buffer, containing the AESCCM key passed by user (predefined size 128 bits).
 * @param[in] QFieldSize    - Byte-size of formatted field for writing significant bytes of the TextSizeQ 
 *                            value. Valid values: [2,3,4,5,6,7,8]. 
 * @param[in] N_ptr	        - A pointer to Nonce - unique value assigned to all data passed into CCM.
 *                            Bytes order - big endian form (MSB is the first).
 * @param[in] SizeOfN       - The size of the user passed Nonce (in bytes). 	Valid values: 
 *                            7 <= SizeOfN <= (15-QFieldSize). 
 * @param[in] ADataIn_ptr    - A pointer to the additional data buffer. The pointer does 
 *                             not need to be aligned. On CSI input mode the pointer must be equal to 
 *                             value (0xFFFFFFFC | DataInAlignment). 
 * @param[in] ADataInSize    - The size of the additional data in bytes;  
 * @param[in] TextDataIn_ptr - A pointer to the input text data buffer (plain or cipher according to
 *                             encrypt-decrypt mode). The pointer does not need to be aligned.
 *                             On CSI input mode the pointer must be equal to value (0xFFFFFFFC | DataInAlignment). 
 * @param[in] TextDataInSize - The size of the input text data in bytes;  
 * @param[out] TextDataOut_ptr - The output text data pointer (cipher or plain text data). 
 * @param[in] TextDataOutSize  - The size of the output text data buffer. The size of buffer must be enough 
 *                               for output the data:
 *                                   - on Encrypt mode: TextDataOutSize >= TextDataInSize + SizeOfT.
 *                                   - on Decrypt mode: TextDataOutSize >= TextDataInSize - SizeOfT.
 * @param[in] SizeOfT	   - Size of AES-CCM MAC output T in bytes. Valid values: [4,6,8,10,12,14,16].   
 *
 * @return CRYSError_t - On success CRYS_OK is returned, on failure a value defined in CRYS_AESCCM_error.h
 *
 *     NOTES: 1. Temporarily it is not allowed, that both the Input and the Output simultaneously 
 *               were on CSI mode.
 *
 */
CEXPORT_C CRYSError_t  CRYS_AESCCM( 
								   CRYS_AES_EncryptMode_t       EncrDecrMode,   /* CCM encrypt-decrypt mode*/
								   CRYS_AESCCM_Key_t            CCM_Key,        /*AES-CCM key*/            
								   DxUint8_t                    QFieldSize,     /*size of Q field in control block*/
								   DxUint8_t                   *N_ptr,          /*Nonce*/
								   DxUint8_t                    SizeOfN,        /*size of N buffer*/
								   DxUint8_t                   *ADataIn_ptr,    /*input data pointer*/
								   DxUint32_t                   ADataInSize,    /*input data size*/
								   DxUint8_t                   *TextDataIn_ptr, /*input data pointer*/
								   DxUint32_t                   TextDataInSize, /*input data size*/
								   DxUint8_t                   *TextDataOut_ptr,/*output data pointer*/
								   DxUint32_t                   TextDataOutSize,/*output data size*/
								   DxUint8_t                    SizeOfT  )      /* size of CCM-MAC */
{    
   /* FUNCTION DECLARATIONS */

   /* The return error identifier */
   CRYSError_t            Error;
   
   /* address of the first table in the input list */
   DxUint32_t             firstInputLLITableAddr;
   
   /* address of the first table in the output list */
   DxUint32_t             firstOutputLLITableAddr;
   
   /* number of entries in the first input tables */
   DxUint32_t             numInTableEntries;
   
   /* number of entries in the first output tables */
   DxUint32_t             numOutTableEntries;
   
   /* first table data size */
   DxUint32_t             firstTableSize;
   
   /* sram offset */
   DxUint32_t             sramOffset;
  
   /* message parameter */
   DxUint32_t             messageParam[11];
   
   /* data sizes  */
   DxUint32_t  plainTextSize, remainDataSize;
   DxUint32_t  tailSize, dataForDmaSize, dataSizeToContext, SizeOfA;

   
   AESCCM_Context_t    *ccmWorkingContext_ptr;


   /*---------------------------
      CODE
   -----------------------------*/
    
   /* ............... local initializations .............................. */
   /* -------------------------------------------------------------------- */
   
   /* initializing the Error to O.K */
   Error = CRYS_OK;

   dataForDmaSize = dataForDmaSize;
   dataSizeToContext = dataSizeToContext;
   SizeOfA = SizeOfA;
   
   Error = Error;

   /* ............... if not supported exit .............................. */
   /* -------------------------------------------------------------------- */   
      
   RETURN_IF_AESCCM_UNSUPPORTED( 
                          EncrDecrMode , CCM_Key[0] , QFieldSize , N_ptr , SizeOfN , 
                          ADataIn_ptr , ADataInSize , TextDataIn_ptr , TextDataInSize , 
                          TextDataOut_ptr , TextDataOutSize , SizeOfT , firstInputLLITableAddr ,
                          firstOutputLLITableAddr , numInTableEntries , numOutTableEntries ,
                          firstTableSize , sramOffset , sramOffset , messageParam , 
                          maxLength , plainTextSize , remainingDataSize , tailSize , 
                          ccmWorkingContext_ptr->ccm_MAC );                               

                              

#if !(defined CRYS_NO_AESCCM_SUPPORT || defined CRYS_NO_AES_SUPPORT)
   
   /* -------------------------------------------------------------------- */
   /* ............... checking the Init parameters validity .............. */
   /* -------------------------------------------------------------------- */

   /* Check the Encrypt / Decrypt mode */
   if( EncrDecrMode >= CRYS_AES_EncryptNumOfOptions )
	   return  CRYS_AESCCM_INVALID_ENCRYPT_MODE_ERROR;

   /* check Key and Nonce pointers */    
   if( CCM_Key == DX_NULL || N_ptr == DX_NULL )
      return  CRYS_AESCCM_ILLEGAL_PARAMETER_PTR_ERROR;     
   
   /* check the Q field size: according to our implementation QFieldSize <= 4*/ 
   if( QFieldSize < 2 || QFieldSize > 8 )      
	   return  CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR;

   /* check Nonce size. Note: QFieldSize + SizeOfN <= 15 */ 
   if( SizeOfN < 7 || SizeOfN > 15 - QFieldSize )      
      return  CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR; 

    /* check CCM MAC size: [4,6,8,10,12,14,16] */ 
   if( SizeOfT < 4   || SizeOfT > 16  || (SizeOfT & 1) != 0 )      
	   return  CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR;


   /* ----------------------------------------------------------------------- */ 
   /* ...... checking the Adata size and pointer ............................ */
   /* ----------------------------------------------------------------------- */ 

   /* if the users Data In pointer is illegal return an error */
   if( ADataIn_ptr == DX_NULL && ADataInSize != 0 )   
      return CRYS_AESCCM_ILLEGAL_PARAMETER_ERROR;

   if( (DxUint32_t)ADataIn_ptr >= DX_CSI )   
   	   return CRYS_AESCCM_CSI_IN_OUT_ILLEGAL_MODE_ERROR; 
   

   /* ----------------------------------------------------------------------- */ 
   /* ...... checking the Text data sizes and pointers ...................... */
   /* ----------------------------------------------------------------------- */ 
	/* if the users Data In pointer is illegal return an error */
	if( TextDataIn_ptr == DX_NULL )   
		return CRYS_AESCCM_DATA_IN_POINTER_INVALID_ERROR;

	/* if the Data In size is 0, return an error */
	if( TextDataInSize == 0 )   
		return CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;

	if( ((DxUint32_t)TextDataIn_ptr >= DX_CSI) /*&& ((DxUint32_t)TextDataOut_ptr >= DX_CSI)*/ )   
		return CRYS_AESCCM_CSI_IN_OUT_ILLEGAL_MODE_ERROR; 

	/* if the users Data Out pointer is illegal return an error */
	if( TextDataOut_ptr == DX_NULL )   
		return CRYS_AESCCM_DATA_OUT_POINTER_INVALID_ERROR;


	/* ...... checking the Text data sizes and data in/out overlapping ....... */
	/* ----------------------------------------------------------------------- */ 

	/* check the data Sizes on decrypt mode */
	if( EncrDecrMode == CRYS_AES_Decrypt)
	{
		if( TextDataInSize <= SizeOfT )
			return CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;
		
		plainTextSize = TextDataInSize - SizeOfT;

		if( TextDataOutSize != plainTextSize )
			return CRYS_AESCCM_DATA_OUT_SIZE_INVALID_ERROR;
	}
	else /* check on encrypt mode */
	{
		plainTextSize = TextDataInSize;
		
		/* check, that text dataIn size */
		if( TextDataInSize  >= 0xFFFFFFFF - SizeOfT )
			return  CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL; 

		if( TextDataInSize == 0 )
			return CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL;

        /* check text dataOut size */
		if( TextDataOutSize != TextDataInSize + SizeOfT )
			return CRYS_AESCCM_DATA_OUT_SIZE_INVALID_ERROR;
	}
    
	/* check overlapping of input-output buffers: overlapping is not allowed, excluding 
	   in placement, i.e. DataIn_ptr = DataOut_ptr */
	if( TextDataIn_ptr != TextDataOut_ptr )
	{
		/* checking the case that the input buffer is in a higher address, than the output buffer */
		if ( TextDataIn_ptr > TextDataOut_ptr )
		{
			/* if begin of DataIn buffer is inside the DataOut buffer, return the overlap error */			
			if( TextDataIn_ptr < TextDataOut_ptr + TextDataOutSize  )
				return CRYS_AESCCM_DATA_OUT_DATA_IN_OVERLAP_ERROR;
			
		}/* end of DataIn_ptr > DataOut_ptr */   

		/* checking the case, that the output buffer is in a lower address then the input buffer */      
		else
		{
			/* if begin of DataOut buffer is inside the DataIn buffer, return the overlap error */
			if( TextDataOut_ptr < TextDataIn_ptr + TextDataInSize  )
				return CRYS_AESCCM_DATA_OUT_DATA_IN_OVERLAP_ERROR; 
			
		}/* end of DataOut_ptr > DataIn_ptr */ 
	}

   /* --------------------------------------------------------------------- */
   /* ............... setting the CRYS_AESCCM function parameters ......... */
   /* --------------------------------------------------------------------- */
 
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function;
   }
   

  /*----------------------------
      start sending message to SEP 
   -----------------------------*/
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
   
   
   /* --------------------------------------------------------------------- */
   /* ............... CRYS_AESCCM_Init function parameters ................ */
   /* --------------------------------------------------------------------- */

   /* set input parameters into message buffer */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_OP_CODE;
   messageParam[1] = EncrDecrMode;
   
   DX_VOS_FastMemCpy( &messageParam[2], CCM_Key, 4*CRYS_AESCCM_KEY_SIZE_WORDS );
   
   messageParam[6] = ADataInSize;
   messageParam[7] = TextDataInSize;
   messageParam[8] = QFieldSize;
   messageParam[9] = SizeOfN;
   messageParam[10] = SizeOfT;
   
   /* send opcode, key and next 3 arguments */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            11*sizeof(DxUint32_t),
                            11*sizeof(DxUint32_t),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send Nonce */
   DX_VOS_FastMemCpy( messageParam, N_ptr, SizeOfN );
   DX_VOS_MemSetZero( (DxUint8_t*)messageParam + SizeOfN, CRYS_AES_BLOCK_SIZE_IN_BYTES - SizeOfN );
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                             4*sizeof(DxUint32_t),
                             4*sizeof(DxUint32_t), 
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   

   /* --------------------------------------------------------------------- */
   /* ............... CRYS_AESCCM_Adata parameters ........................ */
   /* --------------------------------------------------------------------- */
   
   /* set size of field A in Adata block B1 */
   if ( ADataInSize >= 0xff00 ) /* if ASize >= 2^16 - 2^8, then set 0xff||0xfe||ASize */
   {
	   SizeOfA = 6;
   }
   else if ( ADataInSize > 0 ) 
   {
	   SizeOfA = 2;
   }
   else /* no Adata */
   {
	   SizeOfA = 0;
   }

   /* zeroe head-tail message bufers for padding data by 0-s */
   DX_VOS_MemSetZero( (DxUint8_t*)messageParam, 2*CRYS_AES_BLOCK_SIZE_IN_BYTES );

   /* set Adata into message head buffer for filling the context lastBlock in SEP */
   if( SizeOfA + ADataInSize >= CRYS_AES_BLOCK_SIZE_IN_BYTES )
   {
	   /* the size of the data to write into context */
	   dataSizeToContext = CRYS_AES_BLOCK_SIZE_IN_BYTES - SizeOfA;
       
       /* copy data to head of message*/    
       DX_VOS_FastMemCpy( (DxUint8_t*)messageParam, ADataIn_ptr, dataSizeToContext);
       
       /* update input pointer and size */
	   ADataIn_ptr += dataSizeToContext;
   }
   
   else /* may occur only for last block */
   {   
       dataSizeToContext = ADataInSize;
      
       DX_VOS_FastMemCpy( (DxUint8_t*)messageParam, ADataIn_ptr, 
		                  min(CRYS_AES_BLOCK_SIZE_IN_BYTES - SizeOfA, ADataInSize) );
   }
   
   /* calculate remaining size (not full last AES block) for sending it by tail of message */
   remainDataSize = (ADataInSize - dataSizeToContext) % CRYS_AES_BLOCK_SIZE_IN_BYTES; 
   
   /* size of data for transferring by DMA */
   dataForDmaSize = ADataInSize - dataSizeToContext - remainDataSize;
 

   /* set remaining data into tail of the message */
   if ( remainDataSize > 0 )
   {
	   DX_VOS_FastMemCpy( (DxUint8_t*)messageParam+CRYS_AES_BLOCK_SIZE_IN_BYTES, ADataIn_ptr + dataForDmaSize,  
		                   remainDataSize );
   }

   /* send Adata head-tail message        */
   /*-------------------------------------*/
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            sizeof(DxUint32_t) * 8,
                            sizeof(DxUint32_t) * 8,
                            &sramOffset, 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   

   /* set message head and tail sizes into message buffer */
   messageParam[0] = dataSizeToContext; 
   messageParam[1] = remainDataSize;
 
   /* ............... create MLLI table for input Adata .................. */
   Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)ADataIn_ptr,
                                                 dataForDmaSize,
                                                 CRYS_AES_BLOCK_SIZE_IN_BYTES/*tabBlockSize*/,
                                                 &firstInputLLITableAddr,
                                                 &numInTableEntries,
                                                 &firstTableSize); 
   if(Error != DX_OK)
   {
      goto end_function_unlock;
   }
   
   /* set MLLI paramters:  */
   messageParam[2] = firstInputLLITableAddr;  /* MLLI tab addr */
   messageParam[3] = numInTableEntries;       /* MLLI tab enries count */
   messageParam[4] = firstTableSize;          /* MLLI data size */
   	
   /* send the Adata LLI message */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            5*sizeof(DxUint32_t),
                            5*sizeof(DxUint32_t),
                            &sramOffset, 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }


   /* --------------------------------------------------------------------- */
   /* .......... CRYS_AESCCM_LastTextData parameters ...................... */
   /* --------------------------------------------------------------------- */

   /* zero tail-ccmMac message bufers for padding data by 0-s */
   DX_VOS_MemSetZero( (DxUint8_t*)messageParam, 2*CRYS_AES_BLOCK_SIZE_IN_BYTES );

   /* set remaining plain TextData ( size < 16 bytes) into message tail buffer */
   tailSize = plainTextSize % CRYS_AES_BLOCK_SIZE_IN_BYTES;
   
   dataForDmaSize = plainTextSize - tailSize;
   
   /* copy data to tail */    
   DX_VOS_FastMemCpy( (DxUint8_t*)messageParam,TextDataIn_ptr+plainTextSize - tailSize, tailSize);
   
   /* on decrypt mode set encrypted MAC into message CCMMAC buffer */
   if( ccmWorkingContext_ptr->CCM_EncryptMode == CRYS_AES_Decrypt )
   {
       DX_VOS_FastMemCpy( (DxUint8_t*)messageParam + CRYS_AES_BLOCK_SIZE_IN_BYTES, 
                          TextDataIn_ptr + plainTextSize, SizeOfT );
   }
   
   /* send tail and encrypted ccmMAC messages */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            8*sizeof(DxUint32_t),
                            8*sizeof(DxUint32_t),
                            &sramOffset, 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

  
   /* send other parameters        */
   /*------------------------------*/
   
   /* set tail and ccmMAC sizes into message  buffer */
   messageParam[0] = tailSize; 
   messageParam[1] = SizeOfT;
 
   /*  create MLLI table for in/out data          */   
   Error = SEPDriver_PrepareSymDMATables((DxUint32_t)TextDataIn_ptr,
                                       (DxUint32_t)TextDataOut_ptr,
                                       dataForDmaSize,
                                       CRYS_AES_BLOCK_SIZE_IN_BYTES/*tabBlockSizer*/,
                                       &firstInputLLITableAddr,
                                       &firstOutputLLITableAddr,
                                       &numInTableEntries,
                                       &numOutTableEntries,
                                       &firstTableSize); 
   if(Error != DX_OK)
   {
      goto end_function_unlock;
   }
   
   /* set MLLI paramters: address, entries count and LLI data size */
   messageParam[2] = firstInputLLITableAddr;   /* MLLI tab addr */
   messageParam[3] = numInTableEntries;        /* MLLI tab enries count */
   messageParam[4] = firstOutputLLITableAddr;  /* MLLI tab addr */
   messageParam[5] = numOutTableEntries;       /* MLLI tab enries count */
   messageParam[6] = firstTableSize;           /* MLLI data size */

   /* send the LLI message */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
		                            sizeof(DxUint32_t) * 7,
		                            sizeof(DxUint32_t) * 7,
		                            &sramOffset, 
		                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }

 
    
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_WaitForResponse(SEP_DRIVER_POLLING , 0 , CRYS_CALLBACK_Handler , SEP_DRIVER_TIMEOUT_WAIT_FOR_INIFINITY);
   if(Error != DX_OK)
   {
     goto end_function_unlock;
   }

   /*--------------------------------------------------------------*/
   /*   start reading replay message from the SEP                  */
   /*--------------------------------------------------------------*/ 
   
   /* free the tables */
   Error = SEPDriver_FreeDMATables();
   if(Error)
   {
      goto end_function_unlock;
   }
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
    	goto end_function_unlock;
   }
   
   /* read opcode + status  */
   Error = SEPDriver_ReadParamater(
                           (DxUint32_t)messageParam,
                           sizeof(DxUint32_t) * 2,
                           sizeof(DxUint32_t) * 2, 
                           &sramOffset,
                           DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_AESCCM_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function_unlock;
   }
   
   /* check the status */
   if(messageParam[1] != CRYS_OK)
   {
      Error = messageParam[1];
      goto end_function_unlock;
   }

   /* read tail and ccmMac from SEP               */
   /*---------------------------------------------*/

   Error = SEPDriver_ReadParamater(
                           (DxUint32_t)messageParam,
                           8 * sizeof(DxUint32_t),
                           8 * sizeof(DxUint32_t),
                           &sramOffset,
                           DX_FALSE);
 
   if(Error != DX_OK && Error != CRYS_AESCCM_CCM_MAC_INVALID_ERROR )
   {
       goto end_function_unlock;
   }
  
   /* copy tail data into output and set output pointer to ccmMac position */
   if( tailSize > 0 )
   {
      /* copy the data into output */
      DX_VOS_FastMemCpy( TextDataOut_ptr + dataForDmaSize, (DxUint8_t*)messageParam, tailSize );
   }

   /* update pointes to ccmMAC output position */
   TextDataOut_ptr += plainTextSize;
   
   /* copy ccmMac into output */
   if( EncrDecrMode == CRYS_AES_Encrypt )
   {
      DX_VOS_FastMemCpy( TextDataOut_ptr, (DxUint8_t*)messageParam + CRYS_AES_BLOCK_SIZE_IN_BYTES, SizeOfT );
   }

   
          
   /* ................. end of function ..................................... */
   /* ----------------------------------------------------------------------- */
   
end_function_unlock:
   
   /* lock access to the SEP */
   SEPDriver_Unlock();

end_function:
      
   return Error;
  
#endif /* !CRYS_NO_AES_SUPPORT || !CRYS_NO_AESCCM_SUPPORT  */
   
}/* END OF CRYS_AES_CCM */







