


  /*
   *  Object % CRYS_SST.c    : %
   *  State           :  %state%
   *  Creation date   :  Thu Aug 23 11:29:00 2007
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief This file contains the implementation of the Host side of the Host-Sep CRYS_SST operations.
   *
   *  \version CRYS_SST.c#1:incl:13
   *  \author arield
   *  \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
   *           All Rights reserved
   */



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


#include "DX_VOS_Mem.h"
#include "DX_VOS_Sem.h"
#include "error.h"
#include "CRYS_AES_error.h"
#include "CRYS_DES_error.h"
#include "CRYS_HMAC_error.h"
#include "CRYS_RSA_error.h"
#include "SEPDriver.h" 
#include "crys_host_op_code.h"
#include "CRYS_SST.h"

#ifdef SST_SEP_SIMULATOR_ENV
#include "crys_sst_native_duplicate_wrapper.h"
#endif


/************************ Defines ******************************/
/************************ Enums ********************************/
/************************ Typedefs  ****************************/
/************************ Context Structs  *********************/
/************************ Public Variables *********************/
/************************ Public Functions *********************/
/**
 * @brief This function is used to initialize the AES machine.
 *        To operate the AES machine, this should be the first function called.
 *
 * The function gets key from SST and calls CRYS_AES_Init
 *
 * @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 * @param[in] SessionId – the opened authenticator SessionId. 
 *
 * @param[in] ContextID_ptr - A pointer to the AES context buffer that is allocated by the user 
 *                       and is used for the AES machine operation.
 *
 * @param[in,out] IVCounter_ptr - This parameter is the buffer of the IV or counters on mode CTR.
 *                          In ECB mode this parameter is not used.
 *                          In CBC and MAC modes this parameter should contain the IV values.
 *                          In CTR mode this value should contain the init counter.
 *
 * @param[in] EncryptDecryptFlag - A flag specifying whether the AES should perform an Encrypt operation (0) 
 *                           or a Decrypt operation (1).
 *
 * @param[in] OperationMode - The operation mode: ECB, CBC, MAC, or CTR
 *
 *
 * @return CRYSError_t - On success the value CRYS_OK is returned, 
 *                        and on failure a value from CRYS_AES_error.h
 */

CIMPORT_C CRYSError_t  CRYS_SST_AES_Init(	SSTHandle_t               KeyHandle,
											SSTSessionId_t		 	  SessionId,
											CRYS_AESUserContext_t    *ContextID_ptr,
											CRYS_AES_IvCounter_t      IVCounter_ptr,
											CRYS_AES_EncryptMode_t    EncryptDecryptFlag,
											CRYS_AES_OperationMode_t  OperationMode,
											DxUint8_t				 *aWorkspace_ptr,
											DxUint32_t				  aWorkspaceSizeInBytes)
{
   /* offset into SRAM */
   DxUint32_t   sramOffset;
   
   /* read param */
   DxUint32_t   messageParam[6];
   
   /* max length */
   DxUint32_t   maxLength;
   
   /* The return error identifier */
   CRYSError_t  Error;
   
   aWorkspace_ptr = aWorkspace_ptr;
   aWorkspaceSizeInBytes = aWorkspaceSizeInBytes;
   /* FUNCTION LOGIC */
   
   /* ............... local initializations .............................. */
   /* -------------------------------------------------------------------- */
   
   /* initializing the Error to O.K */
   Error = CRYS_OK;
      
   /* ............... if not supported exit .............................. */
   /* -------------------------------------------------------------------- */   
                                 
   #ifndef 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 )
   {
      Error = CRYS_AES_INVALID_USER_CONTEXT_POINTER_ERROR;
      goto end_function;
   }   

   /* check if the operation mode is legal */
   if( OperationMode >= CRYS_AES_NumOfModes )
   {
      Error = CRYS_AES_ILLEGAL_OPERATION_MODE_ERROR;
      goto end_function;
   }       
      
#ifndef DX_NO_NULL_POINTER_CHECKING
   /* if the operation mode selected is CBC , MAC or CTR then check the validity of
      the IV counter pointer */    
   if( OperationMode != CRYS_AES_ECB_mode      &&
       OperationMode != CRYS_AES_XCBC_MAC_mode &&
       OperationMode != CRYS_AES_CMAC_mode     && 
       IVCounter_ptr == DX_NULL )
   {
      Error = CRYS_AES_INVALID_IV_OR_TWEAK_PTR_ERROR; /*CRYS_AES_INVALID_IV_PTR_ON_NON_ECB_MODE_ERROR;*/
      goto end_function;
   }   
#endif  
   

   /* Check the Encrypt / Decrypt flag validity */
   if( EncryptDecryptFlag >= CRYS_AES_EncryptNumOfOptions )
   {
      Error = CRYS_AES_INVALID_ENCRYPT_MODE_ERROR;
      goto end_function;
   }
   
   /* in mode CTR enable only the encrypt mode */
   if( OperationMode == CRYS_AES_CTR_mode && EncryptDecryptFlag == CRYS_AES_Decrypt )
   {
      Error = CRYS_AES_DECRYPT_MODE_NOT_ALLOWED_ON_CTR_MODE;
      goto end_function;
   }
    
   /* in MAC,XCBC,CMAC modes enable only:  encrypt mode  */
   if( (OperationMode == CRYS_AES_XCBC_MAC_mode || OperationMode == CRYS_AES_CMAC_mode || OperationMode == CRYS_AES_MAC_mode) && 
         EncryptDecryptFlag != CRYS_AES_Encrypt )
   {
      Error = CRYS_AES_DECRYPTION_NOT_ALLOWED_ON_THIS_MODE;
      goto end_function;
   }
   
   /* 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);
  
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_AES_INIT_OP_CODE;
   messageParam[1] = SessionId;
   messageParam[2] = KeyHandle.objDigest;
   messageParam[3] = KeyHandle.objId;
   messageParam[4] = EncryptDecryptFlag;
   messageParam[5] = OperationMode;
   
   /* send opcode and session */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            sizeof(DxUint32_t) * 2,
                            sizeof(DxUint32_t) * 2,
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send IV */
   if(IVCounter_ptr !=DX_NULL)
   {
	   maxLength = ((sizeof(CRYS_AES_IvCounter_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
	   Error = SEPDriver_WriteParamater((DxUint32_t)IVCounter_ptr , 
	                             sizeof(CRYS_AES_IvCounter_t) ,
	                             maxLength, 
	                             &sramOffset , 
	                             DX_FALSE);
   }
   else
   {
		sramOffset = sramOffset + sizeof(CRYS_AES_IvCounter_t);   	
   }
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send key handle and rest of params */
   Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[2],
                            sizeof(DxUint32_t) * 4,
                            sizeof(DxUint32_t) * 4,
                            &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_PROTOCOL_HOST_SST_AES_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_AESUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
   Error = SEPDriver_ReadParamater((DxUint32_t)ContextID_ptr,
                            sizeof(CRYS_AESUserContext_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_AES_SUPPORT */
   
}/* END OF CRYS_SST_AES_Init */   


/**
 * @brief This function is used to operate the AES machine in one integrated operation.
 *
 * The function gets key from SST and calls CRYS_AES
 *
 * @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 * @param[in] SessionId – the opened authenticator SessionId. 
 *
 * @param[in,out] IVCounter_ptr - This parameter is the buffer of the IV or counters on mode CTR.
 *                          In ECB mode this parameter is not used.
 *                          In CBC and MAC modes this parameter should contain the IV values.
 *                          In CTR mode this value shuld contain the init counter.
 *
 * @param[in] EncryptDecryptFlag - A flag specifying  whether the AES should perform an Encrypt operation (0) 
 *                           or a Decrypt operation (1).
 *
 * @param[in] OperationMode - The operation mode: ECB, CBC, MAC, or CTR.
 *
 * @param[in] DataIn_ptr - The pointer to the buffer of the input data to the AES. 
 *                   The pointer's value does not need to be word-aligned.
 *
 * @param[in] DataInSize - The size of the input data (must be not 0 and must be multiple of 16 bytes).
 *
 * @param[in,out] DataOut_ptr - The pointer to the buffer of the output data from the AES. 
 *                        The pointer's value does not need to be word-aligned.  
 *
 * @return CRYSError_t - On success the value CRYS_OK is returned, 
 *                        and on failure a value from CRYS_AES_error.h
 */

CIMPORT_C CRYSError_t  CRYS_SST_AES(	SSTHandle_t                 KeyHandle,
										SSTSessionId_t		 	    SessionId,
										CRYS_AES_IvCounter_t        IVCounter_ptr,       
										CRYS_AES_EncryptMode_t      EncryptDecryptFlag, 
										CRYS_AES_OperationMode_t    OperationMode,       
										DxUint8_t                  *DataIn_ptr,        
										DxUint32_t                  DataInSize,         
										DxUint8_t                  *DataOut_ptr,
										DxUint8_t				   *aWorkspace_ptr,
										DxUint32_t				    aWorkspaceSizeInBytes)

{    
   /* FUNCTION DECLERATIONS */

   /* 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;
   
   /* */
   DxUint32_t			        firstTableDataSize;
   
   /* sram offset */
   DxUint32_t             sramOffset;
  
   /* message parameter */
   DxUint32_t             messageParam[12];
   
    /* max length */
   DxUint32_t             maxLength;
   
    /* tail data length and temporary data length */
   DxUint32_t             remainingDataSize;
   DxUint32_t             dataForDma;
   
   /*---------------------------
      CODE
   -----------------------------*/
   /* ............... checking the parameters validity ................... */
   /* -------------------------------------------------------------------- */
   
   aWorkspace_ptr = aWorkspace_ptr;
   aWorkspaceSizeInBytes = aWorkspaceSizeInBytes;
  
   /* check if the operation mode is legal */
   if( OperationMode >= CRYS_AES_NumOfModes )
   {
      Error = CRYS_AES_ILLEGAL_OPERATION_MODE_ERROR;
      goto end_function;
   }       
      
#ifndef DX_NO_NULL_POINTER_CHECKING
   /* if the operation mode selected is CBC , MAC or CTR then check the validity of
      the IV counter pointer */    
   if( OperationMode != CRYS_AES_ECB_mode      &&
       OperationMode != CRYS_AES_XCBC_MAC_mode &&
       OperationMode != CRYS_AES_CMAC_mode     && 
       IVCounter_ptr == DX_NULL )
   {
      Error = CRYS_AES_INVALID_IV_OR_TWEAK_PTR_ERROR; /*CRYS_AES_INVALID_IV_PTR_ON_NON_ECB_MODE_ERROR;*/
      goto end_function;
   }   
#endif  
   

   /* Check the Encrypt / Decrypt flag validity */
   if( EncryptDecryptFlag >= CRYS_AES_EncryptNumOfOptions )
   {
      Error = CRYS_AES_INVALID_ENCRYPT_MODE_ERROR;
      goto end_function;
   }
   
   /* in mode CTR enable only the encrypt mode */
   if( OperationMode == CRYS_AES_CTR_mode && EncryptDecryptFlag == CRYS_AES_Decrypt )
   {
      Error = CRYS_AES_DECRYPT_MODE_NOT_ALLOWED_ON_CTR_MODE;
      goto end_function;
   }
    
   /* in MAC,XCBC,CMAC modes enable only:  encrypt mode  */
   if( (OperationMode == CRYS_AES_XCBC_MAC_mode || OperationMode == CRYS_AES_CMAC_mode || OperationMode == CRYS_AES_MAC_mode) && 
         EncryptDecryptFlag != CRYS_AES_Encrypt )
   {
      Error = CRYS_AES_DECRYPTION_NOT_ALLOWED_ON_THIS_MODE;
      goto end_function;
   }
   
   if( DataIn_ptr == DX_NULL )
   {
       Error = CRYS_AES_DATA_IN_POINTER_INVALID_ERROR;
       goto end_function;
   }
   
   if( DataOut_ptr == DX_NULL )
   {
       Error = CRYS_AES_DATA_OUT_POINTER_INVALID_ERROR;
       goto end_function;
   }
   
   /* ............... local initializations .............................. */
   /* -------------------------------------------------------------------- */
   
   /* initializing the Error to O.K */
   Error = CRYS_OK;

   #ifndef CRYS_NO_AES_SUPPORT                                 
  
   /* ............... calling the CRYS init function ...................... */
   /* --------------------------------------------------------------------- */
 
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function_no_unlock;
   }
   
    /*calculate tail data for specail modes that support unaligned data*/
    dataForDma = DataInSize;
    if((OperationMode == CRYS_AES_XCBC_MAC_mode) ||
       (OperationMode == CRYS_AES_CMAC_mode))
    {
      remainingDataSize = DataInSize % CRYS_AES_BLOCK_SIZE_IN_BYTES;
	  /*if data is aligned to 16bytes need to copy the whole last block but still send if for encryption*/
   	  if(DataInSize && !remainingDataSize)
   	  {
   	  	remainingDataSize = CRYS_AES_BLOCK_SIZE_IN_BYTES;	
   	  }
	  
	  /*if data is not aligned to 16 bytes, the remainig size will be copied and only aligned data will be send to DMA*/
   	  dataForDma = DataInSize - (remainingDataSize & 0xF); 	
   }
   else
   {
   	  remainingDataSize = 0x0;
   }
       


   /* prepare LLI table */
   Error = SEPDriver_PrepareSymDMATables((DxUint32_t)DataIn_ptr,
                                         (DxUint32_t)DataOut_ptr,
                                         dataForDma,
                                         CRYS_AES_BLOCK_SIZE_IN_BYTES,
                                         &firstInputLLITableAddr,
                                         &firstOutputLLITableAddr,
                                         &numInTableEntries,
                                         &numOutTableEntries,
                                         &firstTableDataSize);
   if(Error != DX_OK)
   {
       goto end_function;
   }
                                    
                                   
   /* send the message to SEP */
   sramOffset = 0;
   
   /* start the message */
   SEPDriver_StartMessage(&sramOffset);
 
   /* prepare message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_AES_OP_CODE;
   messageParam[1] = SessionId;
   messageParam[2] = KeyHandle.objDigest;
   messageParam[3] = KeyHandle.objId;
   messageParam[4] = EncryptDecryptFlag;
   messageParam[5] = OperationMode;
   messageParam[6] = firstInputLLITableAddr;
   messageParam[7] = numInTableEntries;
   messageParam[8] = firstOutputLLITableAddr;
   messageParam[9] = numOutTableEntries;
   messageParam[10] = firstTableDataSize;
   messageParam[11] = remainingDataSize;
  
   /* send message opcode and session */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                            sizeof(DxUint32_t) * 2,
                            sizeof(DxUint32_t) * 2,
                            &sramOffset , 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function;
   }
   
   /* send IV */
   if(IVCounter_ptr != DX_NULL)
   {
	   maxLength = ((sizeof(CRYS_AES_IvCounter_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
	   Error = SEPDriver_WriteParamater((DxUint32_t)IVCounter_ptr , 
	                             sizeof(CRYS_AES_IvCounter_t) , 
	                             maxLength,
	                             &sramOffset , 
	                             DX_FALSE);
   	
   }
   else
   {
		sramOffset = sramOffset + sizeof(CRYS_AES_IvCounter_t);   	
   }
   if(Error != DX_OK)
   {
       goto end_function;
   }
   
   /* send key handle and rest of params */
   Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[2],
                            sizeof(DxUint32_t) * 10,
                            sizeof(DxUint32_t) * 10, 
                            &sramOffset , 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function;
   }
   
   /* send tail data */
   Error = SEPDriver_WriteParamater((DxUint32_t)(DataIn_ptr + DataInSize - remainingDataSize) ,
                            remainingDataSize,
                            CRYS_AES_BLOCK_SIZE_IN_BYTES, 
                            &sramOffset , 
                            DX_TRUE);
   if(Error != DX_OK)
   {
       goto end_function;
   }
   /* end message */
   SEPDriver_EndMessage(sramOffset);
            
   /* wait for the response */
   Error = SEPDriver_POLL_FOR_REPONSE();
   if(Error != DX_OK)
   {
   	 goto end_function;
   }
   
   /*-------------------
      start reading message from the SEP 
   ---------------------*/ 
   
   /* free the tables */
   Error = SEPDriver_FreeDMATables();
   if(Error)
   {
     goto end_function;
   }
   
   /* start the message */
   Error = SEPDriver_StartIncomingMessage(&sramOffset);
   if(Error)
   {
     goto end_function;
   }
   
   /* 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;
   }
   
   /* check the opcode */
   if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_AES_OP_CODE)
   {
      Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
      goto end_function;
   }
   
   /* check the status */
   if(messageParam[1] != CRYS_OK)
   {
      Error = messageParam[1];
      goto end_function;
   }
   
   if(OperationMode == CRYS_AES_MAC_mode ||
		  OperationMode == CRYS_AES_XCBC_MAC_mode ||
		  OperationMode == CRYS_AES_CMAC_mode)
   {
      maxLength = ((sizeof(CRYS_AES_MAX_MAC_RESULT_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
      Error = SEPDriver_ReadParamater((DxUint32_t)DataOut_ptr ,  
                               sizeof(CRYS_AES_MAX_MAC_RESULT_t),
                               maxLength,
                               &sramOffset ,
                               DX_FALSE);
      if(Error != DX_OK)
      {
          goto end_function;
      }
   }
           
   /* ................. end of function ..................................... */
   /* ----------------------------------------------------------------------- */
   
end_function:
   
   /* lock access to the SEP */
   SEPDriver_Unlock();

end_function_no_unlock:
      
   return Error;
  
   #endif /* !CRYS_NO_AES_SUPPORT  */
   
}/* END OF CRYS_SST_AES */  

/**
 * @brief This function is used to initialize the DES machine.
 *        To operate the DES machine, this should be the first function called.
 *
 * The function gets key from SST and calls CRYS_DES_Init
 *
 * @param[in] ContextID_ptr  - A pointer to the DES context buffer allocated by the user 
 *                       that is used for the DES machine operation.
 *
 * @param[in,out] IV_ptr - The buffer of the IV.
 *                          In ECB mode this parameter is not used.
 *                          In CBC this parameter should contain the IV values.
 *
 * @param[in] EncryptDecryptFlag - A flag that determines whether the DES should perform 
 *                           an Encrypt operation (0) or a Decrypt operation (1).
 *
 * @param[in] OperationMode - The operation mode: ECB or CBC.
 *
 *
 * @return CRYSError_t - On success the value CRYS_OK is returned, 
 *                        and on failure a value from CRYS_error.h
 */

CIMPORT_C CRYSError_t  CRYS_SST_DES_Init(	SSTHandle_t             KeyHandle,
											SSTSessionId_t			SessionId,
											CRYS_DESUserContext_t    *ContextID_ptr,
											CRYS_DES_Iv_t            IV_ptr,
											CRYS_DES_EncryptMode_t   EncryptDecryptFlag,
											CRYS_DES_OperationMode_t OperationMode,
											DxUint8_t				*aWorkspace_ptr,
											DxUint32_t				aWorkspaceSizeInBytes)
{
  /* The return error identifier */
  CRYSError_t         Error;
  
  /* sram offset */
  DxUint32_t          sramOffset;
  
  /* read parameter */
  DxUint32_t          messageParam[6];
  
  /* max length */
  DxUint32_t          maxLength;
   
  /*-----------------------------
      CODE
  --------------------------------*/
  Error = CRYS_OK;

  aWorkspace_ptr = aWorkspace_ptr;
  aWorkspaceSizeInBytes = aWorkspaceSizeInBytes;

  #ifndef CRYS_NO_DES_SUPPORT                                      
    
  /* ............... checking the parameters validity ................... */
   
  /* if the users context ID pointer is DX_NULL return an error */
  if( ContextID_ptr == DX_NULL )
  {
    Error = CRYS_DES_INVALID_USER_CONTEXT_POINTER_ERROR;
    goto end_function;
  }   
      
  /* check if the operation mode is legal */
  if( OperationMode >= CRYS_DES_NumOfModes )
  {
    Error = CRYS_DES_ILLEGAL_OPERATION_MODE_ERROR;
    goto end_function;
  }       
      
  /* if the operation mode selected is CBC then check the validity of
     the IV counter pointer */    
  if( OperationMode == CRYS_DES_CBC_mode && IV_ptr == DX_NULL )
  {
    Error = CRYS_DES_INVALID_IV_PTR_ON_NON_ECB_MODE_ERROR;
    goto end_function;
  }   
      
  /* Check the Encrypt / Decrypt flag validity */
  if( EncryptDecryptFlag >= CRYS_DES_EncryptNumOfOptions )
  {
    Error = CRYS_DES_INVALID_ENCRYPT_MODE_ERROR;
    goto end_function;
  }
  
   /* 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);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_DES_INIT_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = EncryptDecryptFlag;
  messageParam[5] = OperationMode;
  
  /* send message opcode and session */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                           sizeof(DxUint32_t) * 2,
                           sizeof(DxUint32_t) * 2,
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  if(IV_ptr == DX_NULL)
  {
    sramOffset += sizeof(CRYS_DES_Iv_t);
  }
  else
  {
    /* send IV */
    Error = SEPDriver_WriteParamater((DxUint32_t)IV_ptr , 
                              sizeof(CRYS_DES_Iv_t) ,
                              sizeof(CRYS_DES_Iv_t), 
                              &sramOffset , 
                              DX_FALSE);
    if(Error != DX_OK)
    {
        goto end_function_unlock;
    }
  }
   
  /* send key and rest of params */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[2] , 
                           sizeof(DxUint32_t) * 4,
                           sizeof(DxUint32_t) * 4,
                           &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 != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_DES_INIT_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_DESUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)ContextID_ptr,
                           sizeof(CRYS_DESUserContext_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_DES_SUPPORT */                                    
   
}/* END OF CRYS_SST_DES_Init */   

/**
 * @brief This function is used to operate the DES machine in one integrated operation.
 *
 * The function gets key from SST and calls CRYS_DES
 *
 * @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 * @param[in] SessionId – the opened authenticator SessionId. 
 *
 * @param[in,out] IV_ptr - This parameter is the buffer of the IV.
 *                          In ECB mode this parameter is not used.
 *                          In CBC this parameter should contain the IV values.
 *
 * @param[in] EncryptDecryptFlag - A flag that determines if the DES should perform 
 *                           an Encrypt operation (0) or a Decrypt operation (1).
 *
 * @param[in] OperationMode - The operation mode: ECB or CBC.
 *
 * @param[in] DataIn_ptr - The pointer to the buffer of the input data to the DES.
 *                   The pointer does not need to be word-aligned.
 *
 * @param[in] DataInSize - The size of the input data (must be not 0 and must be multiple of 8 bytes).
 *
 * @param[in,out] DataOut_ptr - The pointer to the buffer of the output data from the DES. 
 *                        The pointer does not need to be word-aligned.  
 *
 * @return CRYSError_t - On success the value CRYS_OK is returned, 
 *                        and on failure a value from CRYS_error.h
 */
 
CIMPORT_C CRYSError_t  CRYS_SST_DES(SSTHandle_t             KeyHandle,
									SSTSessionId_t			SessionId,
									CRYS_DES_Iv_t            IV_ptr,
									CRYS_DES_EncryptMode_t   EncryptDecryptFlag,
									CRYS_DES_OperationMode_t OperationMode,             
									DxUint8_t                  *DataIn_ptr,              
									DxUint32_t                 DataInSize,              
									DxUint8_t                  *DataOut_ptr,
									DxUint8_t				*aWorkspace_ptr,
									DxUint32_t				aWorkspaceSizeInBytes)
{    
  /* 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;
  
  /**/
  DxUint32_t			    firstTableDataSize;
   
  /* sram offset */
  DxUint32_t          sramOffset;
  
  /* read parameter */
  DxUint32_t          messageParam[11];
   
  /*--------------------------------
      CODE
  ---------------------------------*/
  
  Error = CRYS_OK;

  aWorkspace_ptr = aWorkspace_ptr;
  aWorkspaceSizeInBytes = aWorkspaceSizeInBytes;
  
  #ifndef CRYS_NO_DES_SUPPORT                              

  /* if the users Data In pointer is illegal return an error */
  if( DataIn_ptr == DX_NULL )
  {
    Error = CRYS_DES_DATA_IN_POINTER_INVALID_ERROR;
    goto end_function;
  }
   
  /* if the users Data Out pointer is illegal return an error */
  if( DataOut_ptr == DX_NULL )
  {
    Error = CRYS_DES_DATA_OUT_POINTER_INVALID_ERROR;
    goto end_function;
  }
  
  /* checking that there is no overlapping between the data input and data out put buffer
     except the inplace case that is legal */
  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 )
      {
        Error = CRYS_DES_DATA_OUT_DATA_IN_OVERLAP_ERROR;
        goto end_function;
      }     
    }/* 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 )  
      {
        Error = CRYS_DES_DATA_OUT_DATA_IN_OVERLAP_ERROR;
        goto end_function;
      }   
    }/* end of DataOut_ptr > DataIn_ptr */   
      
  }/* end of DataIn_ptr != DataOut_ptr case */   

  /* if the data size is zero or not a multiple of 16 bytes return error */
  if( DataInSize == 0 || (DataInSize % CRYS_DES_BLOCK_SIZE_IN_BYTES) != 0 )
  {
    Error = CRYS_DES_DATA_SIZE_ILLEGAL;
    goto end_function;
  }
  
   /* 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);

  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_DES_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = EncryptDecryptFlag;
  messageParam[5] = OperationMode;

  /* send opcode and session */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                           sizeof(DxUint32_t) * 2,
                           sizeof(DxUint32_t) * 2,
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }

  if(DataInSize != CRYS_DES_BLOCK_SIZE_IN_BYTES)
  {
	/* prepare LLI table */
  	Error = SEPDriver_PrepareSymDMATables((DxUint32_t)DataIn_ptr,
    	                                    (DxUint32_t)DataOut_ptr,
        	                                DataInSize,
            	                            CRYS_DES_BLOCK_SIZE_IN_BYTES,
                	                        &firstInputLLITableAddr,
                    	                    &firstOutputLLITableAddr,
                        	                &numInTableEntries,
                            	            &numOutTableEntries,
                                	        &firstTableDataSize);
                                    
  	if(Error != DX_OK)
  	{
    	goto end_function_unlock;
  	}
   
  	messageParam[6] = firstInputLLITableAddr;
  	messageParam[7] = numInTableEntries;
  	messageParam[8] = firstOutputLLITableAddr;
  	messageParam[9] = numOutTableEntries;
  	messageParam[10] = firstTableDataSize;
  }
   
  /* send IV */
  if(IV_ptr == DX_NULL)
  {
    sramOffset += sizeof(CRYS_DES_Iv_t);
  }
  else
  {
    /* send IV */
    Error = SEPDriver_WriteParamater((DxUint32_t)IV_ptr , 
                              sizeof(CRYS_DES_Iv_t) ,
                              sizeof(CRYS_DES_Iv_t) , 
                              &sramOffset , 
                              DX_FALSE);
    if(Error != DX_OK)
    {
        goto end_function_unlock;
    }
  }
   
  /* send key handle and rest of params */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[2] , 
                           sizeof(DxUint32_t) * 4,
                           sizeof(DxUint32_t) * 4,
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }


  if(DataInSize != CRYS_DES_BLOCK_SIZE_IN_BYTES)
  {
	/* send the lli tables */
  	Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[6]  , 
                           			 sizeof(DxUint32_t) * 5,
                           			 sizeof(DxUint32_t) * 5,
                                     &sramOffset , 
                                     DX_TRUE);
  	if(Error != DX_OK)
  	{
    	  goto end_function_unlock;
  	}
  }
  else
  {
	/* In case of one block send the data */
  	Error = SEPDriver_WriteParamater((DxUint32_t)DataIn_ptr, 
                           DataInSize,
                           CRYS_DES_BLOCK_SIZE_IN_BYTES *2,
                           &sramOffset , 
                           DX_TRUE);
  	if(Error != DX_OK)
  	{
    	  goto end_function_unlock;
  	}

	/* send the data size */
  	Error = SEPDriver_WriteParamater((DxUint32_t)&DataInSize, 
                           sizeof(DxUint32_t),
                           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;
  }
   
  /*-------------------
    start reading message from the SEP 
  ---------------------*/ 
   
  if(DataInSize != CRYS_DES_BLOCK_SIZE_IN_BYTES)
  {
	  /* free the tables */
	  Error = SEPDriver_FreeDMATables();
	  if(Error != DX_OK)
	  {
	  	goto end_function_unlock;
	  }
  }
  /* start the message */
  Error = SEPDriver_StartIncomingMessage(&sramOffset);
  if(Error != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_DES_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;
  }

  if(DataInSize == CRYS_DES_BLOCK_SIZE_IN_BYTES)
  {
	  /* read the block  */
	  Error = SEPDriver_ReadParamater((DxUint32_t)DataOut_ptr , 
	                          DataInSize,
	                          DataInSize,
	                          &sramOffset , 
	                          DX_FALSE);
	  if(Error != DX_OK)
	  {
	      goto end_function_unlock;
	  }
  }
end_function_unlock:

  /* lock access to the SEP */
  SEPDriver_Unlock();
   
end_function:
   
  return Error;
   

  #endif /* CRYS_NO_DES_SUPPORT */
   
}/* END OF CRYS_SST_DES */   



/**
 * This function initializes the HMAC machine on the CRYS level.
 *
 * The function allocates and initializes the HMAC Context .
 *
 * The function receives as input a pointer to store the context handle to HMAC Context. 
 *
 * The function gets key from SST and calls CRYS_HMAC_Init
 *
 * @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 * @param[in] SessionId – the opened authenticator SessionId. 
 *
 * @param[in] ContextID_ptr - A pointer to the HMAC context buffer allocated by the user 
 *                       that is used for the HMAC machine operation.
 *
 * @param[in] OperationMode - The operation mode: MD5 or SHA1.
 *
 * @return CRYSError_t - On success the function returns the value CRYS_OK, 
 *			and on failure a non-ZERO error.
 *      
 */

CIMPORT_C CRYSError_t CRYS_SST_HMAC_Init(	SSTHandle_t             KeyHandle,
											SSTSessionId_t			SessionId,
											CRYS_HMACUserContext_t     *ContextID_ptr,
											CRYS_HASH_OperationMode_t  OperationMode,
											DxUint8_t			*aWorkspace_ptr,
											DxUint32_t			aWorkspaceSizeInBytes)
{
  /* The return error identifier */
  CRYSError_t Error;
  
  /* offset */
  DxUint32_t  sramOffset;
  
  /* read param */
  DxUint32_t  messageParam[5];
  
  /*--------------------
      CODE
  ----------------------*/
  
  Error = CRYS_OK;
    
  aWorkspace_ptr = aWorkspace_ptr;
  aWorkspaceSizeInBytes = aWorkspaceSizeInBytes;
  
  #ifndef CRYS_NO_HASH_SUPPORT                                      
      
  /* ............... checking the parameters validity ................... */
   
  /* if the users context ID pointer is DX_NULL return an error */
  if( ContextID_ptr == DX_NULL )
  {
    Error = CRYS_HMAC_INVALID_USER_CONTEXT_POINTER_ERROR;
    goto end_function;
  }
     
  /* check if the operation mode is legal */
  if( OperationMode >= CRYS_HASH_NumOfModes )
  {
    Error = CRYS_HMAC_ILLEGAL_OPERATION_MODE_ERROR;
    goto end_function;
  }
  
   /* 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);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_HMAC_INIT_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = OperationMode;
  
  /* send all params */
  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;
  }
              
  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 != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_HMAC_INIT_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 */
  Error = SEPDriver_ReadParamater((DxUint32_t)ContextID_ptr,
                           sizeof(CRYS_HMACUserContext_t),
                           sizeof(CRYS_HMACUserContext_t),
                           &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_HASH_SUPPORT */
                              
}/* END OF CRYS_SST_HMAC_Init */


/**
 * This function provides a HASH function for processing one buffer of data.
 *
 * The function gets key from SST and calls CRYS_HMAC
 *
 * @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 * @param[in] SessionId – the opened authenticator SessionId. 
 *
 * @param[in] OperationMode - The operation mode: MD5 or SHA1.
 *
 * @param[in] DataIn_ptr - A pointer to the buffer that stores the data to be hashed.
 * 
 * @param[in] DataSize - The size of the data to be hashed, in bytes. 
 *
 * @retval HmacResultBuff - A pointer to the target buffer where the 
 *                      HMAC result stored in the context is loaded to.
 *
 * @return CRYSError_t - On success the function returns CRYS_OK, 
 *				and on failure a non-ZERO error.
 *
 */

CIMPORT_C CRYSError_t CRYS_SST_HMAC  ( 	SSTHandle_t                 KeyHandle,
									    SSTSessionId_t				SessionId,
									    CRYS_HASH_OperationMode_t   OperationMode,
									    DxUint8_t                  *DataIn_ptr,
									    DxUint32_t                  DataSize,
									    CRYS_HASH_Result_t          HmacResultBuff,
									    DxUint8_t				   *aWorkspace_ptr,
									    DxUint32_t					aWorkspaceSizeInBytes)
{                         
  /* The return error identifier */
  CRYSError_t         Error;
   
  /* address of the first table in the input list */
  DxUint32_t          inputLLITableAddr;
   
  /* number of entries in each of the first tables */
  DxUint32_t          numEntriesInTable;
  
  /* first table data size */
  DxUint32_t          firstTableDataSize;
  
  /* offset */
  DxUint32_t          sramOffset;
  
  /* read parameter */
  DxUint32_t          messageParam[8];
  
  /* max length */
  DxUint32_t          maxLength;
  
  /* number of into the message from the start of user buffer */
  DxUint32_t          numBytesFromStart;
  
  /* number of into the message from the start of user buffer */
  DxUint32_t          numBytesFromEnd;
  
  /* block size */
  DxUint32_t          blockSize;
   
  /*-----------------------------
      CODE 
  -------------------------------*/
   
  /* ............... local initializations .............................. */
  Error = CRYS_OK;
  aWorkspace_ptr = aWorkspace_ptr;
  aWorkspaceSizeInBytes = aWorkspaceSizeInBytes;
  
  
  /* if the data size is zero return CRYS_OK - we just do not need to process any data */
  if( DataSize == 0 ) 
  {
    Error = CRYS_OK;
    goto end_function;
  }
   
  /* if the users Data In pointer is illegal and the data size is larger then 0 return an error */
  if( DataIn_ptr == DX_NULL )
  {
    Error = CRYS_HMAC_DATA_IN_POINTER_INVALID_ERROR;
    goto end_function;
  }
           
  /* larger then 2^29 (to prevant an overflow on the transition to bits ) 
     return error */
  if( DataSize >= (1 << 29) )
  {
    Error = CRYS_HMAC_DATA_SIZE_ILLEGAL;
    goto end_function;
  }

  /* check if the operation mode is legal */
  if( OperationMode >= CRYS_HASH_NumOfModes )
  {
    Error = CRYS_HMAC_ILLEGAL_OPERATION_MODE_ERROR;
    goto end_function;
  }
   
                   
  #ifndef CRYS_NO_HASH_SUPPORT  
  
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function;
   }
  
  /* calculate block size */
  switch(OperationMode)
  {
  	case CRYS_HASH_SHA1_mode:
  	case CRYS_HASH_SHA224_mode:
  	case CRYS_HASH_SHA256_mode:
  	case CRYS_HASH_MD5_mode:
  		blockSize = CRYS_HASH_BLOCK_SIZE_IN_BYTES;
  		break;
  	case CRYS_HASH_SHA384_mode:
  	case CRYS_HASH_SHA512_mode:
  		blockSize = CRYS_HASH_SHA2_BLOCK_SIZE_IN_BYTES;
  		break;
  	default:
  		return CRYS_HMAC_ILLEGAL_OPERATION_MODE_ERROR;
  }
 
  /* get the number of bytes from the beginning of the user buffer into the message */
  numBytesFromStart = 0;
  
  /* get the number of bytes from the beginning of the user buffer into the message */
  numBytesFromEnd = DataSize % blockSize;
   
  /* prepare tables for the input only */
  Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)DataIn_ptr ,
  												DataSize - (numBytesFromStart + numBytesFromEnd), 
  												blockSize,
			                                    &inputLLITableAddr , 
			                                    &numEntriesInTable,
			                                    &firstTableDataSize);
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
  
  /*----------------------------
      start sending message to SEP 
  -----------------------------*/
  sramOffset = 0;
   
  /* start the message */
  SEPDriver_StartMessage(&sramOffset);
    
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_HMAC_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = OperationMode;
  messageParam[5] = inputLLITableAddr;
  messageParam[6] = numEntriesInTable;
  messageParam[7] = firstTableDataSize;
  
  /* send opcode */
  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;
  }
  
  /* send the size of the first part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)&numBytesFromStart,
                                   sizeof(DxUint32_t),
                                   sizeof(DxUint32_t),
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the first part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)DataIn_ptr,
                                   numBytesFromStart,
                                   sizeof(DxUint32_t) * 32,
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the size of the last part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)&numBytesFromEnd,
                                   sizeof(DxUint32_t),
                                   sizeof(DxUint32_t),
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the last part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)(DataIn_ptr + DataSize - numBytesFromEnd),
                                   numBytesFromEnd,
                                   sizeof(DxUint32_t) * 32,
                                   &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 
  ---------------------*/
  
  /* free allocated tables */
  Error = SEPDriver_FreeDMATables();
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }
   
  /* start the message */
  Error = SEPDriver_StartIncomingMessage(&sramOffset);
  if(Error != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_HMAC_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 result */
  maxLength = ((sizeof(CRYS_HASH_Result_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)HmacResultBuff ,
                           sizeof(CRYS_HASH_Result_t) ,
                           maxLength,
                           &sramOffset ,
                           DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                           
end_function_unlock:

  /* unlock access to the SEP */
  SEPDriver_Unlock();                                          
                                                 
end_function:

  return Error;

  #endif /* !CRYS_NO_HASH_SUPPORT */
   
}/* END OF CRYS_SST_HMAC */



/**
 *  @brief
 *  This function gets key from the SST and than encrypt data according to the shcemes.
 *
 *	The actual macro that will be used by the user is:
 *	CRYS_SST_RSA_OAEP_Encrypt 	  - for v2.1
 *	CRYS_SST_RSA_PKCS1v15_Encrypt - for v1.5
 *	
 *  @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 *  @param[in] SessionId – the opened authenticator SessionId. 
 *
 *  @param[in] keyReadData_ptr - A pointer to a CRYS_RSAPrimeData_t 
 *  				that is used for the Encryption operation
 *  @param[in] hashFunc - The hash function to be used. 
 *                        Currently only CRYS_PKCS1_SHA1 is supported. 
 *                        The other hash functions recommended 
 *                        by PKCS#1 v2.1 are SHA-256/284/512.
 *  @param[in] L - The label input. 
 *                 Version 2.1 of the standard defines L as the empty string, 
 *                 so this argument is currently ignored. 
 * @param[in] Llen - The label length. 
 *                Version 2.1 of the standard defines L as the empty string, 
 *                so this argument is currently ignored.
 * @param[in] MGF - The mask generation function. PKCS#1 v2.1 defines MGF1, 
 *                  so the only value allowed here is CRYS_PKCS1_MGF1.
 * @param[in] DataIn_ptr - A pointer to the data to encrypt.
 * @param[in] DataSize - The size, in bytes, of the data to
 *                       encrypt. \note Must be <= (modulus_size - 2*Hash_output_length - 2).
 *
 * @param[out] Output_ptr - A pointer to the encrypted data. 
 *                          The buffer must be at least PubKey_ptr->N.len bytes long 
 *                          (that is, the size of the modulus, in bytes).
 * @param[in] PKCS1_ver - Ver 1.5 or 2.1, according to the functionality required
 *
 * @return CRYSError_t - CRYS_OK, CRYS_BAD_PARAM, CRYS_OUT_OF_RANGE
 */ 
   
CIMPORT_C CRYSError_t _DX_CRYS_SST_RSA_SCHEMES_Encrypt(	SSTHandle_t			        KeyHandle,
        												SSTSessionId_t				SessionId,
        												CRYS_SST_RSA_keys_and_prime_data_container_t *keyReadData_ptr,
        												CRYS_RSA_HASH_OpMode_t		hashFunc,
        												DxUint8_t					*L,
        												DxUint16_t					Llen,
        												CRYS_PKCS1_MGF_t			MGF,
        												DxUint8_t					*DataIn_ptr,
        												DxUint16_t					DataInSize,
        												DxUint8_t					*Output_ptr,
        												CRYS_PKCS1_version			PKCS1_ver)
{
  /* The return error identifier */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[9];
  
 
  /*-----------------------------------
      CODE
  -------------------------------------*/
   
  Error = CRYS_OK;    
  
  keyReadData_ptr = keyReadData_ptr;
    
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      

  /* ............... checking the parameters validity ................... */
       
  /* check if the hash operation mode is legal */
  if( hashFunc >= CRYS_RSA_HASH_NumOfModes)
  {
    Error = CRYS_RSA_HASH_ILLEGAL_OPERATION_MODE_ERROR;
    goto end_function;
  }
      
  /* check if the MGF operation mode is legal */   
  if(MGF >= CRYS_RSA_NumOfMGFFunctions)
  {
    Error = CRYS_RSA_MGF_ILLEGAL_ARG_ERROR;
    goto end_function;
  }
   	  
  /* check that the PKCS1 version argument is legal*/
  if(PKCS1_ver >= CRYS_RSA_NumOf_PKCS1_versions)
  {
    Error = CRYS_RSA_PKCS1_VER_ARG_ERROR;
    goto end_function;
  }
   
  /* if the users Data In pointer is illegal return an error */
  /* note - it is allowed to encrypt a message of size zero ; only on this case a NULL is allowed */
  if( DataIn_ptr == DX_NULL && DataInSize != 0)
  {
    Error = CRYS_RSA_DATA_POINTER_INVALID_ERROR;
    goto end_function;
  }
           
  /*If the output pointer is DX_NULL return Error*/   
  if(Output_ptr == DX_NULL)
  {
    Error = CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR;
    goto end_function;
  }
   
   /* 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);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_RSA_ENC_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = hashFunc;
  messageParam[5] = MGF;
  messageParam[6] = PKCS1_ver;
  messageParam[7] = Llen;
  messageParam[8] = DataInSize;
  
  /* send params */
  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;
  }
  
  /* write L */
  Error = SEPDriver_WriteParamater((DxUint32_t)L,
                                       Llen,
                                       sizeof(DxUint32_t) * 64,
                                       &sramOffset,
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* write data in  */
  Error = SEPDriver_WriteParamater((DxUint32_t)DataIn_ptr,
                                      DataInSize,
                                      sizeof(DxUint32_t) * 64,
                                      &sramOffset,
                                      DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  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 != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_RSA_ENC_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 data out  */
  Error = SEPDriver_ReadParamater((DxUint32_t)Output_ptr,
                                      64 * 4,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE);
  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_HASH_SUPPORT */
  #endif /* CRYS_NO_PKI_SUPPORT */
	  	
}/* END OF _DX_CRYS_SST_RSA_SCHEMES_Encrypt */	

/**
 *   @brief
 *   This function implements the Decrypt algorithm as defined
 *   in PKCS#1 v2.1 and PKCS#1 v1.5
 *
 *	The actual macro that will be used by the user is:
 *	CRYS_SST_RSA_OAEP_Decrypt		- for v2.1
 *	CRYS_SST_RSA_PKCS1v15_Decrypt	- for v1.5
 *
 *  @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 *  @param[in] SessionId – the opened authenticator SessionId. 
 *
 *   @param[in] PrimeData_ptr - A pointer to a CRYS_RSAPrimeData_t, 
 *   				which is used for the Encryption operation
 *   							                            
 *   @param[in] hashFunc - The hash function to be used. 
 *                         Currently only CRYS_PKCS1_SHA1 is supported. 
 *                         The other hash functions recommended by 
 *                         PKCS#1 v2.1 are SHA-256/284/512.
 *   @param[in] L - The label input. 
 *                  Version 2.1 of the standard defines L as the empty string, 
 *                  so this argument is currently ignored. 
 *   @param[in] Llen - The label length. 
 *                  Version 2.1 of the standard defines L as the empty string, 
 *                  so this argument is currently ignored.
 *   @param[in] MGF - The mask generation function. PKCS#1 v2.1 defines MGF1, 
 *                    so the only value allowed here is CRYS_PKCS1_MGF1.
 *   @param[in] Data_ptr - A pointer to the data to decrypt.
 *   @param[in] DataSize - The size, in bytes, of the data to decrypt. 
 *                         \note Must be <= the size of the modulus.
 *
 *   @param[out] Output_ptr - Pointer to the decrypted data. 
 *                            The buffer must be at least PrivKey_ptr->N.len bytes long 
 *                            (that is, the size of the modulus, in bytes).
 *   @param[in,out] OutputSize_ptr - The size of the Output_buffer ptr  [bytes].
 *                                   The input size value must be at least the size of the modulus 
 *                                   This value is updated with the actual number 
 *                                   of bytes that are loaded to Output_ptr buffer
 *
 *   @param[in] PKCS1_ver - Ver 1.5 or 2.1, according to the functionality required
 *
 *   @return CRYSError_t - CRYS_OK, CRYS_BAD_PARAM, CRYS_OUT_OF_RANGE
 **/
 
 CIMPORT_C CRYSError_t _DX_CRYS_SST_RSA_SCHEMES_Decrypt(SSTHandle_t				KeyHandle,
														SSTSessionId_t			SessionId,
														CRYS_SST_RSA_keys_and_prime_data_container_t *keyReadData_ptr,
														CRYS_RSA_HASH_OpMode_t	hashFunc,
														DxUint8_t				*L,
														DxUint16_t				Llen,
														CRYS_PKCS1_MGF_t		MGF,
														DxUint8_t				*Data_ptr,
														DxUint16_t				DataSize,
														DxUint8_t				*Output_ptr,
														DxUint16_t				*OutputSize_ptr,
														CRYS_PKCS1_version		PKCS1_ver)
{
  /* The return error identifier */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[9];
  

	/*--------------------------------------
	    CODE
	---------------------------------------*/
	
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
 
  Error = CRYS_OK;
  
  keyReadData_ptr = keyReadData_ptr;
  
  /* ............... checking the parameters validity ................... */
     	
  /* check if the hash operation mode is legal */
  if( hashFunc >= CRYS_RSA_HASH_NumOfModes)
  {
    Error = CRYS_RSA_HASH_ILLEGAL_OPERATION_MODE_ERROR;
    goto end_function;
  }
      
  /* check if the MGF operation mode is legal */   
  if(MGF >= CRYS_RSA_NumOfMGFFunctions)
  {
    Error = CRYS_RSA_MGF_ILLEGAL_ARG_ERROR;
    goto end_function;
  }
   	 
  /* check that the PKCS1 version argument is legal*/
  if(PKCS1_ver >= CRYS_RSA_NumOf_PKCS1_versions)
  {
    Error = CRYS_RSA_PKCS1_VER_ARG_ERROR;
    goto end_function;
  }
   	 
  /* if the users Data In pointer is illegal return an error */
  if( Data_ptr == DX_NULL )
  {
    Error = CRYS_RSA_DATA_POINTER_INVALID_ERROR;
    goto end_function;
  }
      
  /* if the data size is zero return error */
  if( DataSize == 0 )
  {
    Error = CRYS_RSA_INVALID_MESSAGE_DATA_SIZE;
    goto end_function;
  }
     
  /*If the output pointer is DX_NULL return Error*/   
  if(Output_ptr == DX_NULL)
  {
    Error = CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR;
    goto end_function;
  }
   	 
  /*If the output size pointer is DX_NULL return error*/
  if(OutputSize_ptr ==DX_NULL)
  {
    Error = CRYS_RSA_DECRYPT_OUTPUT_SIZE_POINTER_ERROR;
    goto end_function;
  }
  
   /* 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);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_RSA_DEC_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = hashFunc;
  messageParam[5] = MGF;
  messageParam[6] = PKCS1_ver;
  messageParam[7] = Llen;
  messageParam[8] = DataSize;
  
  /* send all params */
  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;
  }
   
  /* write L */
  Error = SEPDriver_WriteParamater((DxUint32_t)L,
                                       Llen,
                                       sizeof(DxUint32_t) * 64,
                                       &sramOffset,
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
 
  /* write data in  */
  Error = SEPDriver_WriteParamater((DxUint32_t)Data_ptr,
                                       DataSize,
                                       sizeof(DxUint32_t) * 64,
                                       &sramOffset,
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  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 != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_RSA_DEC_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 data out size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  *OutputSize_ptr = (DxUint16_t)messageParam[0];
                          
  /* read the data out  */
  Error = SEPDriver_ReadParamater((DxUint32_t)Output_ptr,
                                      *OutputSize_ptr,
                                       64 * 4,
                                       &sramOffset,
                                       DX_TRUE);
  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_HASH_SUPPORT */
  #endif /* CRYS_NO_PKI_SUPPORT */         
   
}/* END OF _DX_CRYS_SST_RSA_SCHEMES_Decrypt */


/**
 *  \brief RSA_SignInit initializes the Signing
 *  multi-call algorithm as defined in PKCS#1 v1.5 and 2.1
 *
 *	The actual macro that will be used by the user is:
 *	CRYS_SST_RSA_PSS_SignInit		 - for v2.1
 *	CRYS_SST_RSA_PKCS1v15_SignInit	 - for v1.5
 *
 *  This function does not do cryptographic processing. Rather, it
 *  prepares a context that is used by the Update
 *  and Finish functions.
 *  
 *  @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 *  @param[in] SessionId – the opened authenticator SessionId. 
 *
 *   @param[in,out] UserContext_ptr - A pointer to a Context. The value
 *                                returned here must be passed to
 *                                the Update and Finish functions.
 *   @param[in] hashFunc - The hash function to be used. Currently
 *                         only CRYS_PKCS1_SHA1 is supported. The
 *                         other hash functions recommended by PKCS#1
 *                         v2.1 are SHA-256/284/512.
 *   @param[in] MGF - The mask generation function. PKCS#1 v2.1
 *                    defines MGF1, so the only value allowed here is CRYS_PKCS1_MGF1.
 *   @param[in] SaltLen - The Length of the Salt buffer. relevant for PKCS#1 Ver 2.1 Only
 *   						Typical lengths are 0 and hLen (20 for SHA1)
 *   						The maximum length allowed is NSize - hLen - 2                    
 *   @param[in] PKCS1_ver - Ver 1.5 or 2.1, according to the functionality required
 *                       
 *   @return CRYSError_t - CRYS_OK, CRYS_BAD_PARAM
*/

				  
CIMPORT_C CRYSError_t _DX_CRYS_SST_RSA_SignInit(SSTHandle_t					KeyHandle,
												SSTSessionId_t				SessionId,
												CRYS_RSAPrivUserContext_t	*UserContext_ptr,
												CRYS_RSA_HASH_OpMode_t		hashFunc,
												CRYS_PKCS1_MGF_t			MGF,
												DxUint16_t					SaltLen,				  
												CRYS_PKCS1_version			PKCS1_ver,
												CRYS_SST_RSA_pair_keys_container_t* pairKeysCont_ptr, 
												DxUint8_t					*aWorkspace_ptr,
												DxUint32_t					aWorkspaceSizeInBytes )
{
  /* The return error identifier */
  CRYSError_t Error;
  
  /* offset */
  DxUint32_t  sramOffset;
  
  /* param read */
  DxUint32_t  messageParam[8];
  
  /* max length */
  DxUint32_t  maxLength;
   
  /*------------------------
      CODE
  --------------------------*/
   
  Error = CRYS_OK;

  aWorkspace_ptr = aWorkspace_ptr;
  aWorkspaceSizeInBytes = aWorkspaceSizeInBytes;
  pairKeysCont_ptr = pairKeysCont_ptr;
  
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
      
  /* ............... checking the parameters validity ................... */
   
  /* if the users context ID pointer is DX_NULL return an error */
  if( UserContext_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_USER_CONTEXT_POINTER_ERROR;
    goto end_function;
  }
   	  
  /* check if the hash operation mode is legal */
  if( hashFunc >= CRYS_RSA_HASH_NumOfModes)
  {
    Error = CRYS_RSA_HASH_ILLEGAL_OPERATION_MODE_ERROR;
    goto end_function;
  }
     
  /* check if the MGF operation mode is legal */   
  if(MGF >= CRYS_RSA_NumOfMGFFunctions)
  {
    Error = CRYS_RSA_MGF_ILLEGAL_ARG_ERROR;
    goto end_function;
  }
    
  /* check that the PKCS1 version argument is legal*/
  if(PKCS1_ver >= CRYS_RSA_NumOf_PKCS1_versions)
  {
    Error = CRYS_RSA_PKCS1_VER_ARG_ERROR;
    goto end_function;
  }

  /*According to the PKCS1 ver 2.1 standart it is not recommended to use MD5 hash
  therefore we do not support it */
  if(PKCS1_ver == CRYS_PKCS1_VER21 && hashFunc == CRYS_RSA_HASH_MD5_mode)
  {
    Error = CRYS_RSA_HASH_ILLEGAL_OPERATION_MODE_ERROR;
    goto end_function;
  }
  
   /* 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);
  
  /* prepare message */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_RSA_SIGN_INIT_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = hashFunc;
  messageParam[5] = MGF;
  messageParam[6] = SaltLen;
  messageParam[7] = PKCS1_ver;
  
  /* send params */
  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;
  }
  
  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 != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_RSA_SIGN_INIT_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_RSAPrivUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t); 
  Error = SEPDriver_ReadParamater((DxUint32_t)UserContext_ptr,
                                           sizeof(CRYS_RSAPrivUserContext_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_HASH_SUPPORT */
  #endif /* !CRYS_NO_PKI_SUPPORT */                                     

}/* _DX_CRYS_SST_RSA_SignInit */


/**
 *   @brief
 *   RSA_Sign implements the Signing algorithm as defined
 *   in PKCS#1 v1.5 or v2.1, using a single function
 *
 *   The actual macros that will be used by the user are:
 *   CRYS_SST_RSA_PKCS1v15_Sign		- for v1.5
 *   CRYS_SST_RSA_PKCS1v15_SHA1_Sign	- for v1.5 data is hashed with SHA1
 *   CRYS_SST_RSA_PKCS1v15_MD5_Sign	- for v1.5 data is hashed with MD5
 *   CRYS_SST_RSA_PSS_Sign			- for v2.1
 *   CRYS_SST_RSA_PSS_SHA1_Sign		- for v2.1 data is hashed with SHA1
 *					- for v2.1 MD5 is not supported, since 
 *					according to the PKCS#1 ver2.1 it is not recommended
 *  
 *  @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 *  @param[in] SessionId – the opened authenticator SessionId. 
 *
 *   @param[in] UserContext_ptr - A pointer to a Context. For the use of the 
 *   								function as a space to work on.
 *   @param[in] hashFunc - The hash function to be used. Currently
 *                         only CRYS_PKCS1_SHA1 and CRYS_PKCS1_MD5
 *                         are supported. 
 *   @param[in] MGF - The mask generation function. Only for PKCS#1 v2.1
 *                    defines MGF1, so the only value allowed for v2.1 
 *                    is CRYS_PKCS1_MGF1. 
 *   @param[in] SaltLen - The Length of the Salt buffer. relevant for PKCS#1 Ver 2.1 Only
 *   						Typical lengths are 0 and hLen (20 for SHA1)
 *   						The maximum length allowed is NSize - hLen - 2                                                                                       
 *   @param[in] DataIn_ptr - A pointer to the data to sign.
 *   @param[in] DataInSize - The size, in bytes, of the data to sign.
 *   @param[out] Output_ptr - A pointer to the signature. 
 *                            The buffer must be at least PrivKey_ptr->N.len bytes long 
 *                            (that is, the size of the modulus in bytes).
 *   @param[in,out] OutputSize_ptr - A pointer to the Signature Size value - the input value
 *                            is the signature buffer size allocated, the output value is 
 *                            the signature size actually used.
 *                            The buffer must be at least PrivKey_ptr->N.len bytes long 
 *                            (that is, the size of the modulus in bytes).
 *   @param[in] PKCS1_ver - Ver 1.5 or 2.1, according to the functionality required
 *      
 *   @return CRYSError_t - CRYS_OK,
 *                         CRYS_RSA_INVALID_USER_CONTEXT_POINTER_ERROR,
 *                         CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR,
 *                         CRYS_RSA_PRIV_KEY_VALIDATION_TAG_ERROR,
 *                         CRYS_RSA_HASH_ILLEGAL_OPERATION_MODE_ERROR,
 *                         CRYS_RSA_MGF_ILLEGAL_ARG_ERROR,
 *                         CRYS_RSA_PKCS1_VER_ARG_ERROR,
 *                         CRYS_RSA_INVALID_MESSAGE_DATA_SIZE,
 *                         CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR,
 *                         CRYS_RSA_INVALID_SIGNATURE_BUFFER_SIZE
*/

CIMPORT_C CRYSError_t _DX_CRYS_SST_RSA_Sign(SSTHandle_t					KeyHandle,
											SSTSessionId_t				SessionId,
											CRYS_RSAPrivUserContext_t	*UserContext_ptr,
											CRYS_RSA_HASH_OpMode_t		hashFunc,
											CRYS_PKCS1_MGF_t			MGF,
											DxUint16_t					SaltLen,				  			      
											DxUint8_t					*DataIn_ptr,
											DxUint32_t					DataInSize,
											DxUint8_t					*Output_ptr,
											DxUint16_t					*OutputSize_ptr,
											CRYS_PKCS1_version			PKCS1_ver,
											CRYS_SST_RSA_pair_keys_container_t* pairKeysCont_ptr, 
											DxUint8_t					*aWorkspace_ptr,
											DxUint32_t					aWorkspaceSizeInBytes )
{
  /* The return error identifier */
  CRYSError_t         Error;
   
  /* address of the first table in the input list */
  DxUint32_t          inputLLITableAddr;
   
  /* number of entries in each of the first tables */
  DxUint32_t          numEntriesInTable;
  
  /* first table data size */
  DxUint32_t          firstTableDataSize;
  
  /* offset */
  DxUint32_t          sramOffset;
  
  /* read parameter */
  DxUint32_t          messageParam[11]; 
  
  /* max length */
  DxUint32_t          maxLength;     
  /* number of into the message from the start of user buffer */
  DxUint32_t          numBytesFromStart;
  
  /* number of into the message from the start of user buffer */
  DxUint32_t          numBytesFromEnd;
  
  /* block size */
  DxUint32_t          blockSize;     

  /*----------------------
      CODE
  ------------------------*/
  
  UserContext_ptr=UserContext_ptr;
  aWorkspace_ptr = aWorkspace_ptr;
  aWorkspaceSizeInBytes = aWorkspaceSizeInBytes;
  pairKeysCont_ptr = pairKeysCont_ptr;
  
  Error = CRYS_OK;      
                   
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT 
  
  /* if the users Data In pointer is illegal return an error */
  if( DataIn_ptr == DX_NULL && DataInSize )
  {
    Error = CRYS_RSA_DATA_POINTER_INVALID_ERROR;
    goto end_function;
  }
    
  /* if the data size is larger then 2^29 (to prevant an overflow on the transition to bits ) 
     return error */
  if( DataInSize >= (1 << 29) )
  {
    Error = CRYS_RSA_INVALID_MESSAGE_DATA_SIZE;
    goto end_function;
  } 
  
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function;
   }                                 
  
  /* get block size */
  switch (hashFunc)
  {
  	case CRYS_RSA_HASH_SHA1_mode:
  	case CRYS_RSA_HASH_SHA224_mode:
  	case CRYS_RSA_HASH_SHA256_mode:
  	case CRYS_RSA_HASH_MD5_mode:
  		blockSize = CRYS_HASH_BLOCK_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_HASH_SHA384_mode:
  	case CRYS_RSA_HASH_SHA512_mode:
  		blockSize = CRYS_HASH_SHA2_BLOCK_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_MD5_mode:
  		blockSize = CRYS_HASH_MD5_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_SHA1_mode:
  		blockSize = CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_SHA224_mode:
  		blockSize = CRYS_HASH_SHA224_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_SHA256_mode:
  		blockSize = CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_SHA384_mode:
  		blockSize = CRYS_HASH_SHA384_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_SHA512_mode:
  		blockSize = CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES;
  		break;
  	default:
  		return CRYS_RSA_HASH_ILLEGAL_OPERATION_MODE_ERROR;
  }
  
  if (DataInSize <= blockSize)
  {
    /* set start input as data in size */
    numBytesFromStart = DataInSize;
    
    /* set end part to zero */
    numBytesFromEnd = 0;    
  }
  else
  {
    /* set start part to zero */
    numBytesFromStart = 0;
  
    /* get the number of bytes from the end of the user buffer into the message */
    numBytesFromEnd = DataInSize % blockSize;
  }
   
  /* prepare tables for the input only */
  Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)(DataIn_ptr + numBytesFromStart), 
                                                            DataInSize - (numBytesFromStart + numBytesFromEnd),
                                                            blockSize,
                                                            &inputLLITableAddr , 
                                                            &numEntriesInTable,
                                                            &firstTableDataSize ) ; 
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }                                    
 
	/*----------------------------
      start sending message to SEP 
  -----------------------------*/
  sramOffset = 0;
   
  /* start the message */
  SEPDriver_StartMessage(&sramOffset);
  
  /* prepare message */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_RSA_SIGN_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = hashFunc;
  messageParam[5] = MGF;
  messageParam[6] = SaltLen;
  messageParam[7] = PKCS1_ver;
  messageParam[8] = inputLLITableAddr;
  messageParam[9] = numEntriesInTable;
  messageParam[10] = firstTableDataSize;
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                           sizeof(DxUint32_t) * 11,
                           sizeof(DxUint32_t) * 11,
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the size of the first part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)&numBytesFromStart,
                                   sizeof(DxUint32_t),
                                   sizeof(DxUint32_t),
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the first part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)DataIn_ptr,
                                   numBytesFromStart,
                                   sizeof(DxUint32_t) * 32,
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the size of the last part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)&numBytesFromEnd,
                                   sizeof(DxUint32_t),
                                   sizeof(DxUint32_t),
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the last part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)(DataIn_ptr + DataInSize - numBytesFromEnd),
                                   numBytesFromEnd,
                                   sizeof(DxUint32_t) * 32,
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                              
  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 
  ---------------------*/
  
  /* free allocated tables */
  Error = SEPDriver_FreeDMATables();
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }

  /* start the message */
  Error = SEPDriver_StartIncomingMessage(&sramOffset);
  if(Error != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_RSA_SIGN_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 size out data */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  *OutputSize_ptr = (DxUint16_t)messageParam[0];
  
  /* read the result */
  maxLength = ((*OutputSize_ptr + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t); 
  Error = SEPDriver_ReadParamater((DxUint32_t)Output_ptr,
                           *OutputSize_ptr,
                            maxLength,
                            &sramOffset,
                            DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                           
end_function_unlock:

  /* unlock access to the SEP */
  SEPDriver_Unlock();                                          
                                                 
end_function:

  return Error;
	
  #endif /* !CRYS_NO_HASH_SUPPORT */
  #endif /* !CRYS_NO_PKI_SUPPORT */                                     

}/* END OF _DX_CRYS_SST_RSA_Sign */


/**
 *   @brief 
 *	 CRYS_SST_RSA_VerifyInit initializes the Verify
 *   multi-call algorithm as defined in PKCS#1 v1.5 and 2.1
 *
 *	The actual macro that will be used by the user is:
 *	CRYS_SST_RSA_PKCS1v15_VerifyInit - for v1.5
 *	CRYS_SST_RSA_PSS_VerifyInit		 - for v2.1
 *	
 *  @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 *  @param[in] SessionId – the opened authenticator SessionId. 
 *
 *   @param[in] UserContext_ptr - A pointer to the public Context
 *	                           structure of the User.
 *   @param[in] hashFunc - The hash function to be used. Currently
 *                         only CRYS_PKCS1_SHA1 and CRYS_PKCS1_MD5
 *                         are supported. The other hash functions
 *                         recommended by PKCS#1 v2.1 are
 *                         SHA-256/284/512. If PKCS1_ver is CRYS_PKCS1_VER15, then
 *			 the value CRYS_RSA_After_HASH_NOT_KNOWN_mode will allow
 *			 the signature data to determine the hash function to be used.
 *   @param[in] MGF - The mask generation function. Only for PKCS#1 v2.1
 *                    defines MGF1, so the only value allowed for v2.1 
 *                    is CRYS_PKCS1_MGF1.
 *   @param[in] SaltLen - The Length of the Salt buffer. relevant for PKCS#1 Ver 2.1 Only
 *   						Typical lengths are 0 and hLen (20 for SHA1)
 *   						The maximum length allowed is NSize - hLen - 2
 *                       If the salt length is not available in this process, the user can use the define:
 *                       CRYS_RSA_VERIFY_SALT_LENGTH_UNKNOWN
 *                       Security Note: it is recommended not to use this flag and to support the Salt length on each verify
 *  @param[in] PKCS1_ver - Ver 1.5 or 2.1, according to the functionality required
 *  
 *  @return CRYSError_t - CRYS_OK, CRYS_INVALID_SIGNATURE,
 *                        CRYS_BAD_PARAM, CRYS_OUT_OF_RANGE 
*/

CIMPORT_C CRYSError_t _DX_CRYS_SST_RSA_VerifyInit(	SSTHandle_t					KeyHandle,
													SSTSessionId_t				SessionId,
													CRYS_RSAPubUserContext_t	*UserContext_ptr,
													CRYS_RSA_HASH_OpMode_t		hashFunc,
													CRYS_PKCS1_MGF_t			MGF,
													DxUint16_t					SaltLen,
													CRYS_PKCS1_version			PKCS1_ver,
													CRYS_SST_RSA_pair_keys_container_t* pairKeysCont_ptr, 
													DxUint8_t					*aWorkspace_ptr,
													DxUint32_t					aWorkspaceSizeInBytes )
{
  /* The return error identifier */
  CRYSError_t Error;
  
  /* offset */
  DxUint32_t  sramOffset;
   
  /* read param */
  DxUint32_t  messageParam[8];
  
  /* max length */
  DxUint32_t  maxLength;
   
  /*----------------------------
       CODE
  ------------------------------*/
  
  Error = CRYS_OK;
    
  aWorkspace_ptr = aWorkspace_ptr;
  aWorkspaceSizeInBytes = aWorkspaceSizeInBytes;
  pairKeysCont_ptr = pairKeysCont_ptr;
  
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
      
  /* ............... checking the parameters validity ................... */
 
  /* if the users context ID pointer is DX_NULL return an error */
  if( UserContext_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_USER_CONTEXT_POINTER_ERROR;
    goto end_function;
  }
    	
  /* check if the hash operation mode is legal */
  if( hashFunc >= CRYS_RSA_HASH_NumOfModes)
  {
    Error = CRYS_RSA_HASH_ILLEGAL_OPERATION_MODE_ERROR;
    goto end_function;
  }
      
  /* check if the MGF operation mode is legal */   
  if(MGF >= CRYS_RSA_NumOfMGFFunctions)
  {
    Error = CRYS_RSA_MGF_ILLEGAL_ARG_ERROR;
    goto end_function;
  }
   	  
  /* check that the PKCS1 version argument is legal*/
  if(PKCS1_ver >= CRYS_RSA_NumOf_PKCS1_versions)
  {
    Error = CRYS_RSA_PKCS1_VER_ARG_ERROR;
    goto end_function;
  }
   
  /*According to the PKCS1 ver 2.1 standart it is not recommended to use MD5 hash
  therefore we do not support it */
  if(PKCS1_ver == CRYS_PKCS1_VER21 && hashFunc == CRYS_RSA_HASH_MD5_mode)
  {
    Error = CRYS_RSA_HASH_ILLEGAL_OPERATION_MODE_ERROR;
    goto end_function;
  }
  
   /* 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);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_RSA_VERIFY_INIT_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = hashFunc;
  messageParam[5] = MGF;
  messageParam[6] = SaltLen;
  messageParam[7] = PKCS1_ver;
  
  /* sendparams */
  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;
  }
   
  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 != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_RSA_VERIFY_INIT_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_RSAPubUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)UserContext_ptr,
                           sizeof(CRYS_RSAPubUserContext_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_HASH_SUPPORT */
  #endif /* !CRYS_NO_PKI_SUPPORT */                                     
	
}/* END OF _DX_CRYS_SST_RSA_VerifyInit */  

/**
 *  \brief CRYS_SST_RSA_Verify implements the RSASSA-PKCS1v15 algorithm
 *   in a single function, as defined in PKCS#1 v1.5 and v2.1
 *
 *	The actual macro that will be used by the users is:
 *	CRYS_SST_RSA_PKCS1v15_Verify			- for v1.5
 *	CRYS_SST_RSA_PKCS1v15_MD5_Verify		- for v1.5 data in is hashed with MD5
 *	CRYS_SST_RSA_PKCS1v15_SHA1_Verify		- for v1.5 data in is hashed with SHA1
 *	CRYS_SST_RSA_PSS_Verify					- for v2.1
 *	CRYS_SST_RSA_PSS_SHA1_Verify			- for v2.1 data in is hashed with SHA1
 *							- for v2.1 MD5 is not supported, since
 *							according to the PKCS#1 ver2.1 it is not recommended	
 *	
 *  @param[in] SSTHandle - Handle to the SST entry that contains the relevant key. 
 *
 *  @param[in] SessionId – the opened authenticator SessionId. 
 *
 *  @param[in] UserContext_ptr - A pointer to the public Context, 
 *  				for the use of the function as a space to work on
 *  @param[in] hashFunc - The hash function to be used. 
 *                        Currently only CRYS_PKCS1_SHA1 and CRYS_PKCS1_MD5
 *                        are supported. The other hash functions
 *                        recommended by PKCS#1 v2.1 are
 *                        SHA-256/284/512.  If PKCS1_ver is CRYS_PKCS1_VER15, then
 *			 the value CRYS_RSA_After_HASH_NOT_KNOWN_mode will allow
 *			 the signature data to determine the hash function to be used.
 *  @param[in] MGF - The mask generation function. only for PKCS#1 v2.1
 *                   defines MGF1, so the only value allowed for v2.1 
 *                   is CRYS_PKCS1_MGF1. 
 *  @param[in] SaltLen - The Length of the Salt buffer. relevant for PKCS#1 Ver 2.1 Only
 *  						Typical lengths are 0 and hLen (20 for SHA1)
 *  						The maximum length allowed is NSize - hLen - 2                                             
 *  @param[in] DataIn_ptr - A pointer to the data whose signature is
 *                        to be verified.
 *  @param[in] DataInSize - The size, in bytes, of the data whose
 *                        signature is to be verified.
 *  @param[in] Sig_ptr - A pointer to the signature to be verified. 
 *                      The length of the signature is PubKey_ptr->N.len bytes 
 *                      (that is, the size of the modulus, in bytes).
 * @param[in] PKCS1_ver - Ver 1.5 or 2.1, according to the functionality required
 *
 * @return CRYSError_t - CRYS_OK, CRYS_INVALID_SIGNATURE,
 *                        CRYS_BAD_PARAM, CRYS_OUT_OF_RANGE 
**/

CIMPORT_C CRYSError_t _DX_CRYS_SST_RSA_Verify(	SSTHandle_t					KeyHandle,
												SSTSessionId_t				SessionId,
												CRYS_RSAPubUserContext_t	*UserContext_ptr,
												CRYS_RSA_HASH_OpMode_t		hashFunc,
												CRYS_PKCS1_MGF_t			MGF,
												DxUint16_t					SaltLen,
												DxUint8_t					*DataIn_ptr,
												DxUint32_t					DataInSize,
												DxUint8_t					*Sig_ptr,
												CRYS_PKCS1_version			PKCS1_ver,
												CRYS_SST_RSA_pair_keys_container_t* pairKeysCont_ptr, 
												DxUint8_t					*aWorkspace_ptr,
												DxUint32_t					aWorkspaceSizeInBytes)
{
  /* The return error identifier */
  CRYSError_t         Error;
   
  /* address of the first table in the input list */
  DxUint32_t          inputLLITableAddr;
   
  /* number of entries in each of the first tables */
  DxUint32_t          numEntriesInTable;
  
  /* first table data size */
  DxUint32_t          firstTableDataSize;
  
  /* offset */
  DxUint32_t          sramOffset;
   
  /* read param */
  DxUint32_t          messageParam[11];
  
  /* number of into the message from the start of user buffer */
  DxUint32_t          numBytesFromStart;
  
  /* number of into the message from the start of user buffer */
  DxUint32_t          numBytesFromEnd;
  
  /* block size */
  DxUint32_t          blockSize;
  
  
  /*--------------------------------
      CODE
  ---------------------------------*/
  
  UserContext_ptr=UserContext_ptr;
  
  aWorkspace_ptr = aWorkspace_ptr;
  aWorkspaceSizeInBytes = aWorkspaceSizeInBytes;
  pairKeysCont_ptr = pairKeysCont_ptr;
  
  Error = CRYS_OK;      
  
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
  
  /* if the users Data In pointer is illegal and the data size is not 0 return an error */
  if( DataIn_ptr == DX_NULL && DataInSize )
  {
    Error = CRYS_RSA_DATA_POINTER_INVALID_ERROR;
    goto end_function;
  }
           
  /* if the data size is larger then 2^29 (to prevant an overflow on the transition to bits ) 
     return error */
  if( DataInSize >= (1UL << 29) )
  {
    Error = CRYS_RSA_INVALID_MESSAGE_DATA_SIZE;
    goto end_function;
  }
  
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function;
   }
  
  /* get block size */
  switch (hashFunc)
  {
  	case CRYS_RSA_HASH_SHA1_mode:
  	case CRYS_RSA_HASH_SHA224_mode:
  	case CRYS_RSA_HASH_SHA256_mode:
  	case CRYS_RSA_HASH_MD5_mode:
  		blockSize = CRYS_HASH_BLOCK_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_HASH_SHA384_mode:
  	case CRYS_RSA_HASH_SHA512_mode:
  		blockSize = CRYS_HASH_SHA2_BLOCK_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_MD5_mode:
  		blockSize = CRYS_HASH_MD5_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_SHA1_mode:
  		blockSize = CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_SHA224_mode:
  		blockSize = CRYS_HASH_SHA224_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_SHA256_mode:
  		blockSize = CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_SHA384_mode:
  		blockSize = CRYS_HASH_SHA384_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_RSA_After_SHA512_mode:
  		blockSize = CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES;
  		break;
    case CRYS_RSA_After_HASH_NOT_KNOWN_mode: /*used for PKCS1 v1.5 Verify only - possible to derive the hash mode from the signature*/
		blockSize = 0;
		break;
  	default:
  		return CRYS_RSA_HASH_ILLEGAL_OPERATION_MODE_ERROR;
  }
  
  if (DataInSize <= blockSize)
  {
    /* set start input as data in size */
    numBytesFromStart = DataInSize;
    
    /* set end part to zero */
    numBytesFromEnd = 0;
    
  }
  else
  {
    /* set start part to zero */
    numBytesFromStart = 0;
  
    /* get the number of bytes from the end of the user buffer into the message */
    numBytesFromEnd = DataInSize % blockSize;
  }
   
  /* prepare tables for the input only */
  Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)(DataIn_ptr + numBytesFromStart), 
                                                            DataInSize - (numBytesFromStart + numBytesFromEnd),
                                                            blockSize,
                                                            &inputLLITableAddr , 
                                                            &numEntriesInTable,
                                                            &firstTableDataSize ) ; 
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
  
  /*----------------------------
      start sending message to SEP 
  -----------------------------*/
  sramOffset = 0;
   
  /* start the message */
  SEPDriver_StartMessage(&sramOffset);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_RSA_VERIFY_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = hashFunc;
  messageParam[5] = MGF;
  messageParam[6] = SaltLen;
  messageParam[7] = PKCS1_ver;
  messageParam[8] = inputLLITableAddr;
  messageParam[9] = numEntriesInTable;
  messageParam[10] = firstTableDataSize;
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam ,
                           sizeof(DxUint32_t) * 11,
                           sizeof(DxUint32_t) * 11,
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  /* send the signature */
  Error = SEPDriver_WriteParamater((DxUint32_t)Sig_ptr , 
                             sizeof(DxUint32_t) * 64 ,
                             sizeof(DxUint32_t) * 64 , 
                             &sramOffset , 
                             DX_TRUE); 
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the size of the first part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)&numBytesFromStart,
                                   sizeof(DxUint32_t),
                                   sizeof(DxUint32_t),
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the first part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)DataIn_ptr,
                                   numBytesFromStart,
                                   sizeof(DxUint32_t) * 32,
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the size of the last part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)&numBytesFromEnd,
                                   sizeof(DxUint32_t),
                                   sizeof(DxUint32_t),
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send the last part of the input buffer */
  Error = SEPDriver_WriteParamater((DxUint32_t)(DataIn_ptr + DataInSize - numBytesFromEnd),
                                   numBytesFromEnd,
                                   sizeof(DxUint32_t) * 32,
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  SEPDriver_EndMessage(sramOffset);
            
  /* wait for the response */
  Error = SEPDriver_POLL_FOR_REPONSE();
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }
  
  /* free the tables */
  Error = SEPDriver_FreeDMATables();
  if(Error)
  {
    goto end_function_unlock;
  }
  
                                            
  /*-------------------
    start reading message from the SEP 
  ---------------------*/
   
  /* start the message */
  Error = SEPDriver_StartIncomingMessage(&sramOffset);
  if(Error != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_RSA_VERIFY_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 of function ................................ */   

end_function_unlock:   

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

  return Error; 

  #endif /* !CRYS_NO_HASH_SUPPORT */
  #endif /* !CRYS_NO_PKI_SUPPORT */                                     
    
}/* END OF _DX_CRYS_SST_RSA_Verify */


/**
 * @brief
 * CRYS_SST_RSA_PRIM_Encrypt implements the RSAEP algorithm as defined in PKCS#1 v2.1 6.1.1
 * 
 * @param[in] keyReadData_ptr - A pointer to a structure containing internal buffers
 * @param[in] Data_ptr - A pointer to the data to encrypt
 * @param[in] DataSize - The size, in bytes, of the data to encrypt.
 *                      \note This value must be <= the size of the modulus.
 * @param[out] Output_ptr - Pointer to the encrypted data.
 *                         The buffer must be at least PubKey_ptr->N.len bytes long 
 *                         (that is, the size of the modulus, in bytes).
 * 
 *   @return CRYSError_t - CRYS_OK,
 *                         CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR,
 *                         CRYS_RSA_PUB_KEY_VALIDATION_TAG_ERROR,
 *                         CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID,
 *                         CRYS_RSA_DATA_POINTER_INVALID_ERROR,
 *                         CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR,
 *                         CRYS_RSA_INVALID_MESSAGE_BUFFER_SIZE,
 *                         CRYS_RSA_INVALID_MESSAGE_DATA_SIZE,
 *                         CRYS_RSA_INVALID_MESSAGE_VAL
**/

CIMPORT_C CRYSError_t CRYS_SST_RSA_PRIM_Encrypt(SSTHandle_t			KeyHandle,
												SSTSessionId_t		SessionId,
												CRYS_SST_RSA_keys_and_prime_data_container_t *keyReadData_ptr,
												DxUint8_t           *Data_ptr,
												DxUint16_t          DataSize,
												DxUint8_t           *Output_ptr)
{
  /* The return error identifier */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[5];
  
  
  /*---------------------------------------
      CODE
  ----------------------------------------*/
       
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
 
  Error = CRYS_OK;
  
  keyReadData_ptr = keyReadData_ptr;
  
  /* if the users Data pointer is illegal return an error */
  if( Data_ptr == DX_NULL )
  {
    Error = CRYS_RSA_DATA_POINTER_INVALID_ERROR;
    goto end_function;
  }

  /* if the users output pointer is illegal return an error */
  if( Output_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR;
    goto end_function;
  }
   
       
   /* 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);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_RSA_PRIM_ENC_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = DataSize;
  
  /* send params */
  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;
  }
  
  /* write data in */
  Error = SEPDriver_WriteParamater((DxUint32_t)Data_ptr,
                                       DataSize,
                                       64 * sizeof(DxUint32_t),
                                       &sramOffset,
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  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 != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_RSA_PRIM_ENC_OP_CODE)
  {
    Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
    goto end_function_unlock;
  }
   
  /* read the status */
  if(messageParam[1] != CRYS_OK)
  {
    Error = messageParam[1];
    goto end_function_unlock;
  }
   
  /* read the data out  */
  Error = SEPDriver_ReadParamater((DxUint32_t)Output_ptr,
                                      64 * 4,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE);
  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_HASH_SUPPORT */
  #endif /* !CRYS_NO_PKI_SUPPORT */                                     

}/* END OF CRYS_SST_RSA_PRIM_Encrypt */


/**
 * @brief
 * CRYS_SST_RSA_PRIM_Decrypt implements the RSADP algorithm as defined in PKCS#1 v2.1 6.1.2
 * 
 *                            
 *   @param[in] keyReadData_ptr - A pointer to a structure containing internal buffers
 *                              required for the RSA operation                        
 *   @param[in] Data_ptr - A pointer to the data to be decrypted
 *   @param[in] DataSize - The size, in bytes, of the data to decrypt. 
 *                         \note Must be <= the size of the modulus.
 * 
 *   @param[out] Output_ptr - A pointer to the decrypted data.
 *                            The buffer must be at least PrivKey_ptr->N.len bytes long 
 *                            (that is, the size of the modulus, in bytes).
 * 
 *   @return CRYSError_t - CRYS_OK,
 *                         CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR,
 *                         CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID,
 *                         CRYS_RSA_PRIV_KEY_VALIDATION_TAG_ERROR,
 *                         CRYS_RSA_DATA_POINTER_INVALID_ERROR,
 *                         CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR,
 *                         CRYS_RSA_INVALID_MESSAGE_DATA_SIZE,
 *                         CRYS_RSA_INVALID_MESSAGE_VAL
**/
 
CIMPORT_C CRYSError_t CRYS_SST_RSA_PRIM_Decrypt(SSTHandle_t			KeyHandle,
												SSTSessionId_t		SessionId,
												CRYS_SST_RSA_keys_and_prime_data_container_t *keyReadData_ptr,
												DxUint8_t			*Data_ptr,
												DxUint16_t			DataSize,
												DxUint8_t			*Output_ptr)
{				  
  /* The return error identifier */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[5];
  

  /*-------------------------------------------
      CODE
  --------------------------------------------*/
                  
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
  
  Error = CRYS_OK;

  keyReadData_ptr = keyReadData_ptr;

  /* ............... checking the parameters pointers validity .......... */

  /* if the users Data pointer is DX_NULL return an error */
  if( Data_ptr == DX_NULL )
  {
    Error = CRYS_RSA_DATA_POINTER_INVALID_ERROR;
    goto end_function;
  }
   
  /* if the users Output pointer is DX_NULL return an error */
  if( Output_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR;
    goto end_function;
  }
  
   /* 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);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_SST_RSA_PRIM_DEC_OP_CODE;
  messageParam[1] = SessionId;
  messageParam[2] = KeyHandle.objDigest;
  messageParam[3] = KeyHandle.objId;
  messageParam[4] = DataSize;
  
  /* send params */
  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;
  }
  
  /* write data in */
  Error = SEPDriver_WriteParamater((DxUint32_t)Data_ptr,
                                      DataSize,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  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 != DX_OK)
  {
  	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_PROTOCOL_HOST_SST_RSA_PRIM_DEC_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 data out  */
  Error = SEPDriver_ReadParamater((DxUint32_t)Output_ptr,
                                      64 * 4,
                                      64 * 4,
                                      &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_HASH_SUPPORT */
  #endif /* !CRYS_NO_PKI_SUPPORT */                                     
  							       
}/* END OF CRYS_SST_RSA_PRIM_Decrypt */


