
  /*
   *  Object %name    : %
   *  State           :  %state%
   *  Creation date   :  Thu Aug 16 10:47:55 2007
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief The Host-Sep protocol, Host side implementation.
   *
   *  \version CRYS_KMNG.c#1:csrc:6
   *  \author arield
   *  \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
   *           All Rights reserved
   */



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

#include "DX_VOS_Mem.h"
#include "DX_VOS_Memmap.h"
#include "DX_VOS_Sem.h"
#include "CRYS.h"
#include "error.h"
#include "CRYS_KMNG.h"
#include "CRYS_AES_error.h"
#include "CRYS_DES_error.h"
#include "CRYS_HMAC_error.h"
#include "CRYS_RSA_error.h"
#include "CRYS_DH_errors.h"
#include "SEPDriver.h" 
#include "crys_host_op_code.h"
#include "gen.h"

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



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


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


/************* Private function prototype ****************/


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

/**
 * @brief This function is used to initialize the AES context for KMNG.
 *        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] AES_WrappedKey_ptr - wrapped AES key from KMNG
 *
 * @param[in] ContextID_ptr - A pointer to the KMNG 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_KMNG_AES_Init(	KMNG_AES_WrappedKey_t		AES_WrappedKey_ptr,
											CRYS_AESUserContext_t		*ContextID_ptr,
											CRYS_AES_IvCounter_t		IVCounter_ptr,
											CRYS_AES_EncryptMode_t		EncryptDecryptFlag,
											CRYS_AES_OperationMode_t	OperationMode)
{
       /* offset into SRAM */
   DxUint32_t   sramOffset;
   
   /* read param */
   DxUint32_t   messageParam[3];
   
   /* max length */
   DxUint32_t   maxLength;
   
   /* The return error identifier */
   CRYSError_t  Error;
   
     
   /* FUNCTION LOGIC */
   
   /* ............... local initializations .............................. */
   /* -------------------------------------------------------------------- */
   
   /* initializing the Error to O.K */
   Error = CRYS_OK;
      
   /* ............... if not supported exit .............................. */
   /* -------------------------------------------------------------------- */   
      
  /*  kinda funny - no aes -> no wrap !
  RETURN_IF_AES_UNSUPPORTED( ContextID_ptr , IVCounter_ptr , OperationMode , 
                              OperationMode , EncryptDecryptFlag , OperationMode , 
                              is_secret_key , ccmWorkingContext_ptr , OperationMode , OperationMode );*/
                              
   #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;
   }
   
   if( AES_WrappedKey_ptr == DX_NULL )
   {
       Error = CRYS_AES_INVALID_KEY_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 message */
   messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_KMNG_AES_INIT_OP_CODE;
   messageParam[1] = EncryptDecryptFlag;
   messageParam[2] = OperationMode;
   
   /* send opcode */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                            sizeof(DxUint32_t),
                            sizeof(DxUint32_t),
                            &sramOffset,
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send IV */
   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);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send key */ 
   Error = SEPDriver_WriteParamater( (DxUint32_t)AES_WrappedKey_ptr , 
                             sizeof(KMNG_AES_WrappedKey_t) ,
                             sizeof(KMNG_AES_WrappedKey_t) , 
                             &sramOffset , 
                             DX_TRUE);
   if(Error != DX_OK)
   {
       goto end_function_unlock;
   }
   
   /* send rest of params */
   Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[1],
                            sizeof(DxUint32_t) * 2,
                            sizeof(DxUint32_t) * 2,
                            &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_KMNG_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 DX_KMNG_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] AES_WrappedKey_ptr - wrapped AES key from KMNG
 *
 * @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_KMNG_AES(	KMNG_AES_WrappedKey_t		AES_WrappedKey_ptr,
										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)
{    
   /* 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;
   
   /* size of data in the first table */
   DxUint32_t             firstTableSize;
   
   /* sram offset */
   DxUint32_t             sramOffset;
  
   /* message parameter */
   DxUint32_t             messageParam[9];
   
    /* max length */
   DxUint32_t             maxLength;
   
    /* tail data length and temporary data length */
   DxUint32_t             remainingDataSize;
   DxUint32_t             dataForDma;
   
   /*---------------------------
      CODE
   -----------------------------*/
   /* ............... checking the parameters validity ................... */
   /* -------------------------------------------------------------------- */

   /* 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( AES_WrappedKey_ptr == DX_NULL )
   {
       Error = CRYS_AES_INVALID_KEY_POINTER_ERROR;
       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,
                                         &firstTableSize); 
                                    
   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_KMNG_AES_OP_CODE;
   messageParam[1] = EncryptDecryptFlag;
   messageParam[2] = OperationMode;
   messageParam[3] = firstInputLLITableAddr;
   messageParam[4] = numInTableEntries;
   messageParam[5] = firstOutputLLITableAddr;
   messageParam[6] = numOutTableEntries;
   messageParam[7] = firstTableSize;
   messageParam[8] = remainingDataSize;
  
   /* send message param */
   Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                            sizeof(DxUint32_t),
                            sizeof(DxUint32_t),
                            &sramOffset , 
                            DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function;
   }
   
   /* send IV */
   Error = SEPDriver_WriteParamater((DxUint32_t)IVCounter_ptr , 
                             sizeof(CRYS_AES_IvCounter_t) , 
                             4 * 4,
                             &sramOffset , 
                             DX_FALSE);
   if(Error != DX_OK)
   {
       goto end_function;
   }
   
   /* send key */
   Error = SEPDriver_WriteParamater((DxUint32_t)AES_WrappedKey_ptr ,
                                        sizeof(KMNG_AES_WrappedKey_t) ,
                                        sizeof(KMNG_AES_WrappedKey_t) ,
                                        &sramOffset , 
                                        DX_TRUE);
   if(Error != DX_OK)
   {
       goto end_function;
   }
   
   /* send rest of params */
   Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[1],
                            sizeof(DxUint32_t) * 8,
                            sizeof(DxUint32_t) * 8, 
                            &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_KMNG_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 DX_KMNG_AES */  

/**
 * @brief This function is used to execute AES wrap using key(in the context) from the key management.
 *
 * The function unwraps the key from KMNG and calls CRYS_AES_Wrap
 *
 *
 * @param[in] AES_WrappedKey_ptr - wrapped AES key from KMNG
 *
 * @param[in]  DataIn_ptr - A pointer to plain text data to be wrapped
                            NOTE: Overlapping between the data input and data output buffer
                                  is not allowed, except the inplace case that is legal . 			
 * @param[in]  DataInLen  - Length of data in bytes. DataLen must be multiple of 
                            8 bytes and  must be in range [16,  2^28].
 * @param[out] WrapDataOut_ptr -	A pointer to buffer for output of wrapped data.
 * @param[in/out] WrapDataLen_ptr - A pointer to a buffer for input of size of 
                                    user passed buffer and for output actual 
                                    size of unwrapped data in bytes. Buffer size must 
                                    be not less than DataLen+CRYS_AES_WRAP_BLOCK_SIZE_IN_BYTES.                         
 * @return CRYSError_t - CRYS_OK, or error message                         
                         CRYS_AES_WRAP_ILLEGAL_DATA_PTR_ERROR            
                         CRYS_AES_WRAP_DATA_LENGTH_ERROR                 
                         CRYS_AES_WRAP_ILLEGAL_KEY_PTR_ERROR             
                         CRYS_AES_WRAP_KEY_LENGTH_ERROR                  
                         CRYS_AES_WRAP_ILLEGAL_WRAP_DATA_PTR_ERROR      
                         CRYS_AES_WRAP_ILLEGAL_WRAP_DATA_LEN_PTR_ERROR  
                         CRYS_AES_WRAP_ILLEGAL_WRAP_DATA_LENGTH_ERROR
						 CRYS_AES_WRAP_DATA_OUT_DATA_IN_OVERLAP_ERROR 
*/

CIMPORT_C CRYSError_t  CRYS_KMNG_AESWrap(	KMNG_AES_WrappedKey_t		AES_WrappedKey_ptr,
                      										DxUint8_t*              DataIn_ptr,      /*in*/   
                                          DxUint32_t              DataInLen,
                                          DxUint8_t*              WrapDataOut_ptr, /*out*/
                                          DxUint32_t*             WrapDataLen_ptr)
{
  /* The return error identifier */
  CRYSError_t            Error;
   
  /* sram offset */
  DxUint32_t             sramOffset;
  
  /* message parameter */
  DxUint32_t             messageParam[2];
   
  /* max length */
  DxUint32_t             maxLength;
   
  /*---------------------------
    CODE
  -----------------------------*/
  
  /* ............... checking the parameters validity ................... */
  /* -------------------------------------------------------------------- */
  if( AES_WrappedKey_ptr == DX_NULL )
  {
    Error = CRYS_AES_INVALID_KEY_POINTER_ERROR;
    goto end_function;
  }
   
  if( DataIn_ptr == DX_NULL )
  {
    Error = CRYS_AES_DATA_IN_POINTER_INVALID_ERROR;
    goto end_function;
  }
   
  if( WrapDataOut_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;
   }
                                      
  /* send the message to SEP */
  sramOffset = 0;
   
  /* start the message */
  SEPDriver_StartMessage(&sramOffset);
  
  /* prepare message */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_KMNG_AES_WRAP_OP_CODE;
  messageParam[1] = DataInLen;
   
  /* send message param */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                            sizeof(DxUint32_t),
                            sizeof(DxUint32_t),
                            &sramOffset , 
                            DX_FALSE);
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
  
  /* send wrapped key key */
  Error = SEPDriver_WriteParamater((DxUint32_t)AES_WrappedKey_ptr ,
                                    sizeof(KMNG_AES_WrappedKey_t) ,
                                    sizeof(KMNG_AES_WrappedKey_t) ,
                                    &sramOffset ,
                                    DX_TRUE);
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
  
  /* send data in length */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[1] , 
                            sizeof(DxUint32_t),
                            sizeof(DxUint32_t),
                            &sramOffset , 
                            DX_FALSE);
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
  
  /* send data in */
  maxLength = ((DataInLen + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)DataIn_ptr , 
                                   DataInLen , 
                                   maxLength,
                                   &sramOffset , 
                                   DX_TRUE);
  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;
  }
   
  /* 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_KMNG_AES_WRAP_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 length */
  Error = SEPDriver_ReadParamater((DxUint32_t)WrapDataLen_ptr , 
                                   sizeof(DxUint32_t),
                                   sizeof(DxUint32_t),
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
   
  /* read wrapped data */
  maxLength = ((*WrapDataLen_ptr + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)WrapDataOut_ptr , 
                                   *WrapDataLen_ptr ,
                                   maxLength, 
                                   &sramOffset , 
                                   DX_FALSE);
  
end_function_unlock:
   
  /* lock access to the SEP */
  SEPDriver_Unlock();
 
end_function:

#endif /* CRYS_NO_AES_SUPPORT */
  
  return Error;
}

/**
   @brief  The CRYS_KMNG_AESUnwrap is used to execute AES unwrap on data using the key from KMNG
   
   @param[in]  AES_WrappedKey_ptr - key strucutre from KMNG
   @param[in]  WrapDataIn_ptr - A pointer to wrapped data to be unwrapped 
                                NOTE: Overlapping between the data input and data output buffer
                                      is not allowed, except the inplace case that is legal . 			
   @param[in]  WrapDataInLen  - Length of wrapped data in bytes. DataLen must be multiple of 
                                8 bytes and  must be in range [24, 2^29].
   @param[out] DataOut_ptr     - A pointer to buffer for output of unwrapped data.
   @param[in/out]  DataOutLen_ptr - A pointer to a buffer for input of size of user passed 
                              buffer and for output of actual size of unwrapped data in bytes.
                              DataOutLen must be multiple of 8 bytes and must be not less
                              than WrapDataInLen - CRYS_AES_WRAP_BLOCK_SIZE_IN_BYTES.
                           
   @return CRYSError_t - CRYS_OK, or error message 
                         CRYS_AES_UNWRAP_WRAP_DATA_LENGTH_ERROR          
                         CRYS_AES_UNWRAP_ILLEGAL_KEY_PTR_ERROR           
                         CRYS_AES_UNWRAP_KEY_LEN_ERROR                   
                         CRYS_AES_UNWRAP_ILLEGAL_DATA_PTR_ERROR          
                         CRYS_AES_UNWRAP_ILLEGAL_DATA_LEN_PTR_ERROR      
                         CRYS_AES_UNWRAP_ILLEGAL_DATA_LENGTH_ERROR       
                         CRYS_AES_UNWRAP_FUNCTION_FAILED_ERROR 
						 CRYS_AES_UNWRAP_DATA_OUT_DATA_IN_OVERLAP_ERROR 
						 CRYS_AES_UNWRAP_IS_SECRET_KEY_FLAG_ILLEGAL_ERROR

    NOTE:  On error exiting from function the output buffer may be zeroed by the function.
                         
*/                               
CIMPORT_C  CRYSError_t CRYS_KMNG_AESUnwrap(KMNG_AES_WrappedKey_t  AES_WrappedKey_ptr,
                      										 DxUint8_t*             WrapDataIn_ptr, 
                      										 DxUint32_t             WrapDataInLen,
                      										 DxUint8_t*             DataOut_ptr,
                      										 DxUint32_t*            DataOutLen_ptr)
{
  /* The return error identifier */
  CRYSError_t            Error;
   
  /* sram offset */
  DxUint32_t             sramOffset;
  
  /* message parameter */
  DxUint32_t             messageParam[2];
   
  /* max length */
  DxUint32_t             maxLength;
   
  /*---------------------------
    CODE
  -----------------------------*/
  
  /* ............... checking the parameters validity ................... */
  /* -------------------------------------------------------------------- */
  if( AES_WrappedKey_ptr == DX_NULL )
  {
    Error = CRYS_AES_INVALID_KEY_POINTER_ERROR;
    goto end_function;
  }
   
  if( WrapDataIn_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;
   }
                                      
  /* send the message to SEP */
  sramOffset = 0;
   
  /* start the message */
  SEPDriver_StartMessage(&sramOffset);
  
  /* prepare message */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_KMNG_AES_UNWRAP_OP_CODE;
  messageParam[1] = WrapDataInLen;
   
  /* send message param */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                                    sizeof(DxUint32_t),
                                    sizeof(DxUint32_t),
                                    &sramOffset , 
                                    DX_FALSE);
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
  
  /* send wrapped key key */
  Error = SEPDriver_WriteParamater((DxUint32_t)AES_WrappedKey_ptr ,
                                    sizeof(KMNG_AES_WrappedKey_t) ,
                                    sizeof(KMNG_AES_WrappedKey_t) ,
                                    &sramOffset ,
                                    DX_TRUE);
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
  
  /* send data in length */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[1] , 
                                    sizeof(DxUint32_t),
                                    sizeof(DxUint32_t),
                                    &sramOffset , 
                                    DX_FALSE);
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
  
  /* send data in */
  maxLength = ((WrapDataInLen + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)WrapDataIn_ptr , 
                                   WrapDataInLen , 
                                   maxLength,
                                   &sramOffset , 
                                   DX_TRUE);
  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;
  }
   
  /* 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_KMNG_AES_UNWRAP_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 length */
  Error = SEPDriver_ReadParamater((DxUint32_t)DataOutLen_ptr , 
                                   sizeof(DxUint32_t),
                                   sizeof(DxUint32_t),
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
   
  /* read wrapped data */
  maxLength = ((*DataOutLen_ptr + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)DataOut_ptr , 
                                   *DataOutLen_ptr ,
                                   maxLength, 
                                   &sramOffset , 
                                   DX_FALSE);
  
end_function_unlock:
   
  /* lock access to the SEP */
  SEPDriver_Unlock();
 
end_function:

#endif /* CRYS_NO_AES_SUPPORT */
  
  return Error;
}

/**
 * @brief This function is used to initialize the DES machine.
 *        To operate the DES machine, this should be the first function called.
 *
 * @param[in] DES_WrappedKey_ptr - wrapped DES key from KMNG
 *
 * @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
 */

CEXPORT_C CRYSError_t  CRYS_KMNG_DES_Init(	KMNG_DES_WrappedKey_t	DES_WrappedKey_ptr,
											CRYS_DESUserContext_t    *ContextID_ptr,
											CRYS_DES_Iv_t            IV_ptr,
											CRYS_DES_EncryptMode_t   EncryptDecryptFlag,
											CRYS_DES_OperationMode_t OperationMode)
{
  /* The return error identifier */
  CRYSError_t         Error;
  
  /* sram offset */
  DxUint32_t          sramOffset;
  
  /* read parameter */
  DxUint32_t          messageParam[3];
  
  /* max length */
  DxUint32_t          maxLength;
   
  /*-----------------------------
      CODE
  --------------------------------*/
  Error = CRYS_OK;
                   
  #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 validity of the key pointer */
  if( DES_WrappedKey_ptr == DX_NULL )
  {
    Error = CRYS_DES_INVALID_KEY_POINTER_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_KMNG_DES_INIT_OP_CODE;
  messageParam[1] = EncryptDecryptFlag;
  messageParam[2] = OperationMode;
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  if(IV_ptr == DX_NULL)
  {
    sramOffset += 4 * sizeof(DxUint32_t);
  }
  else
  {
    /* send IV */
    Error = SEPDriver_WriteParamater((DxUint32_t)IV_ptr , 
                              sizeof(CRYS_DES_Iv_t) ,
                              4 * sizeof(DxUint32_t), 
                              &sramOffset , 
                              DX_FALSE);
    if(Error != DX_OK)
    {
        goto end_function_unlock;
    }
  }
   
  /* send key */
  Error = SEPDriver_WriteParamater((DxUint32_t)DES_WrappedKey_ptr , 
                            sizeof(KMNG_DES_WrappedKey_t) ,
                            sizeof(KMNG_DES_WrappedKey_t) , 
                            &sramOffset , 
                            DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  /* send rest of params */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[1] , 
                           sizeof(DxUint32_t) * 2,
                           sizeof(DxUint32_t) * 2,
                           &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_KMNG_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_KMNG_DES_Init */   

											

/**
 * @brief This function is used to operate the DES machine in one integrated operation.
 *
 *
 *
 * @param[in] DES_WrappedKey_ptr - wrapped DES key from KMNG
 *
 * @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_KMNG_DES(KMNG_DES_WrappedKey_t	DES_WrappedKey_ptr,
									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)
{    
  /* 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 input tables */
  DxUint32_t          numOutTableEntries;
  
  /* size of data in the first table */
  DxUint32_t          firstTableSize;
   
  /* sram offset */
  DxUint32_t          sramOffset;
  
  /* read parameter */
  DxUint32_t          messageParam[8];
   
  /*--------------------------------
      CODE
  ---------------------------------*/
  
  Error = CRYS_OK;

  #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;
  }
  
  /*check the validity of the key pointer */
  if( DES_WrappedKey_ptr == DX_NULL )
  {
    Error = CRYS_DES_INVALID_KEY_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_KMNG_DES_OP_CODE;
  messageParam[1] = EncryptDecryptFlag;
  messageParam[2] = OperationMode;

  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam,
                           sizeof(DxUint32_t) ,
                           sizeof(DxUint32_t) ,
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  /* send IV */
  if(IV_ptr == DX_NULL)
  {
    sramOffset += 4 * sizeof(DxUint32_t);
  }
  else
  {
    /* send IV */
    Error = SEPDriver_WriteParamater((DxUint32_t)IV_ptr , 
                              sizeof(CRYS_DES_Iv_t) ,
                              4 * sizeof(DxUint32_t), 
                              &sramOffset , 
                              DX_FALSE);
    if(Error != DX_OK)
    {
        goto end_function_unlock;
    }
  }
   
  /* send key */
  Error = SEPDriver_WriteParamater((DxUint32_t)DES_WrappedKey_ptr , 
                            sizeof(KMNG_DES_WrappedKey_t) ,
                            sizeof(KMNG_DES_WrappedKey_t) ,
                           &sramOffset , 
                           DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }

  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[1],
                           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,
                                		       &firstTableSize);                                    
  		if(Error != DX_OK)
  		{
   			goto end_function_unlock;
  		}
   
  		messageParam[3] = firstInputLLITableAddr;
  		messageParam[4] = numInTableEntries;
  		messageParam[5] = firstOutputLLITableAddr;
  		messageParam[6] = numOutTableEntries;
  		messageParam[7] = firstTableSize;
  
		/* send rest of params */
	  	Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[3] , 
	                           			 sizeof(DxUint32_t) * 5,
	                           			 sizeof(DxUint32_t) * 5,
	                           			 &sramOffset , 
	                           			 DX_FALSE);
	  if(Error != DX_OK)
	  {
	      goto end_function_unlock;
	  }
  }
  else
  {
		/* send the data in the message */
	  	Error = SEPDriver_WriteParamater((DxUint32_t)DataIn_ptr , 
	                           			 DataInSize,
	                           			 sizeof(DxUint32_t) * 4,
	                           			 &sramOffset , 
	                           			 DX_TRUE);
	  if(Error != DX_OK)
	  {
	      goto end_function_unlock;
	  }
		/* send the data in the message */
	  	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_KMNG_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 data (in case of 1 DES block)  */
	  Error = SEPDriver_ReadParamater((DxUint32_t)DataOut_ptr , 
	                          DataInSize,
	                          CRYS_DES_BLOCK_SIZE_IN_BYTES,
	                          &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_KMNG_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. 
 *
 * @param[in] HMAC_WrappedKey_ptr - wrapped HMAC key from KMNG
 *
 * @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_KMNG_HMAC_Init(	KMNG_HMAC_WrappedKey_t	HMAC_WrappedKey_ptr,
											CRYS_HMACUserContext_t     *ContextID_ptr,
											CRYS_HASH_OperationMode_t  OperationMode)
{
  /* The return error identifier */
  CRYSError_t Error;
  
  /* offset */
  DxUint32_t  sramOffset;
  
  /* read param */
  DxUint32_t  messageParam[2];
  
  /* max length */
  DxUint32_t  maxLength;
  
  /*--------------------
      CODE
  ----------------------*/
  
  Error = CRYS_OK;
                       
  #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;
  }
   
  /* check if the key pointer is valid */
  if( HMAC_WrappedKey_ptr == DX_NULL )
  {
    Error = CRYS_HMAC_INVALID_KEY_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_KMNG_HMAC_INIT_OP_CODE;
  messageParam[1] = OperationMode;
  
  /* send params */
  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 key */
  Error = SEPDriver_WriteParamater((DxUint32_t)HMAC_WrappedKey_ptr , 
                            sizeof(KMNG_HMAC_WrappedKey_t) ,
                            sizeof(KMNG_HMAC_WrappedKey_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_KMNG_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 */
  maxLength = ((sizeof(CRYS_HMACUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)ContextID_ptr,
                           sizeof(CRYS_HMACUserContext_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 */
                              
}/* END OF CRYS_KMNG_HMAC_Init */

/**
 * This function provides a HASH function for processing one buffer of data.
 *
 *
 * @param[in] HMAC_WrappedKey_ptr - wrapped HMAC key from KMNG
 *
 * @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_KMNG_HMAC(KMNG_HMAC_WrappedKey_t	HMAC_WrappedKey_ptr, 	
									 CRYS_HASH_OperationMode_t  OperationMode,
									 DxUint8_t                    *DataIn_ptr,
									 DxUint32_t                    DataSize,
									 CRYS_HASH_Result_t          HmacResultBuff)
{                         
  /* 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[6];
  
  /* 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;
  
  /* 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;
  }
   
  /* check if the key pointer is valid */
  if( HMAC_WrappedKey_ptr == DX_NULL )
  {
    Error = CRYS_HMAC_INVALID_KEY_POINTER_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 */
  /* 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_KMNG_HMAC_OP_CODE;
  messageParam[1] = OperationMode;
  messageParam[2] = inputLLITableAddr;
  messageParam[3] = numEntriesInTable;
  messageParam[4] = firstTableDataSize;
  
  /* send opcode */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam ,
                           sizeof(DxUint32_t) * 5,
                           sizeof(DxUint32_t) * 5, 
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send 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;
  }
   
  /* send key */
  Error = SEPDriver_WriteParamater((DxUint32_t)HMAC_WrappedKey_ptr , 
                            sizeof(KMNG_HMAC_WrappedKey_t) ,
                            sizeof(KMNG_HMAC_WrappedKey_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 
  ---------------------*/
  
  /* 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_KMNG_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_KMNG_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_KMNG_RSA_OAEP_Encrypt 	  - for v2.1
 *	CRYS_KMNG_RSA_PKCS1v15_Encrypt - for v1.5
 *	
 *
 * @param[in] CRYS_KMNG_RSA_PubWrappedKey_t - wrapped RSA public key from KMNG
 *
 *  @param[in] PrimeData_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_KMNG_RSA_SCHEMES_Encrypt(KMNG_RSA_WrappedKey_t		RSA_WrappedKey_ptr,
														CRYS_RSAPrimeData_t*		PrimeData_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[6];
  
 
  /*-----------------------------------
      CODE
  -------------------------------------*/
   
  Error = CRYS_OK;    
                 
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      

  /* ............... checking the parameters validity ................... */
   
  /* if the users context pointer is DX_NULL return an error */
  if( RSA_WrappedKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* checking the Prime Data pointer */
  if( PrimeData_ptr == DX_NULL )
  {
    Error = CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID;
    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;
  }
   
  /* 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_KMNG_RSA_ENC_OP_CODE;
  messageParam[1] = hashFunc;
  messageParam[2] = MGF;
  messageParam[3] = PKCS1_ver;
  messageParam[4] = Llen;
  messageParam[5] = DataInSize;
  
  /* 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 L */
  Error = SEPDriver_WriteParamater((DxUint32_t)L,
                                       Llen,
                                       64 * 4,
                                       &sramOffset,
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                           
  /* send params   */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[5] , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* write data in  */
  Error = SEPDriver_WriteParamater((DxUint32_t)DataIn_ptr,
                                      DataInSize,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* write public key */
  Error = SEPDriver_WriteParamater((DxUint32_t)RSA_WrappedKey_ptr,
                                       sizeof(KMNG_RSA_WrappedKey_t),
                                       sizeof(KMNG_RSA_WrappedKey_t),
                                       &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_KMNG_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_KMNG_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_KMNG_RSA_OAEP_Decrypt		- for v2.1
 *	CRYS_KMNG_RSA_PKCS1v15_Decrypt	- for v1.5
 *
 *
 *   @param[in] CRYS_KMNG_RSA_PrivWrappedKey_t - wrapped RSA private key from KMNG
 *
 *   @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_KMNG_RSA_SCHEMES_Decrypt(KMNG_RSA_WrappedKey_t	RSA_WrappedKey_ptr,
														CRYS_RSAPrimeData_t*	PrimeData_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[6];
  

	/*--------------------------------------
	    CODE
	---------------------------------------*/
	
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
 
  Error = CRYS_OK;
   
  /* ............... checking the parameters validity ................... */
   
  /* if the users context pointer is DX_NULL return an error */
  if( RSA_WrappedKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  if(PrimeData_ptr == DX_NULL)
  {
    Error = CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID;
    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;
  }
   	 
  /* 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_KMNG_RSA_DEC_OP_CODE;
  messageParam[1] = hashFunc;
  messageParam[2] = MGF;
  messageParam[3] = PKCS1_ver;
  messageParam[4] = Llen;
  messageParam[5] = 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 L */
  Error = SEPDriver_WriteParamater((DxUint32_t)L,
                                       Llen,
                                       64 * 4,
                                       &sramOffset,
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                           
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[5] , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &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;
  }
  
  /* write private key */
  Error = SEPDriver_WriteParamater((DxUint32_t)RSA_WrappedKey_ptr,
                                       sizeof(KMNG_RSA_WrappedKey_t),
                                       sizeof(KMNG_RSA_WrappedKey_t),
                                       &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_KMNG_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_KMNG_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_KMNG_RSA_PSS_SignInit		 - for v2.1
 *	CRYS_KMNG_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] CRYS_KMNG_RSA_PrivWrappedKey_t - wrapped RSA private key from KMNG
 *
 *   @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_KMNG_RSA_SignInit(KMNG_RSA_WrappedKey_t	RSA_WrappedKey_ptr,
												CRYS_RSAPrivUserContext_t	*UserContext_ptr,
												CRYS_RSA_HASH_OpMode_t		hashFunc,
												CRYS_PKCS1_MGF_t			MGF,
												DxUint16_t					SaltLen,				  
												CRYS_PKCS1_version			PKCS1_ver)
{
  /* The return error identifier */
  CRYSError_t Error;
  
  /* offset */
  DxUint32_t  sramOffset;
  
  /* param read */
  DxUint32_t  messageParam[5];
  
  /* max length */
  DxUint32_t  maxLength;
   
  /*------------------------
      CODE
  --------------------------*/
   
  Error = CRYS_OK;

  #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;
  }
   
  /*if the private key object is DX_NULL return an error*/   
  if (RSA_WrappedKey_ptr == DX_NULL)
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_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_KMNG_RSA_SIGN_INIT_OP_CODE;
  messageParam[1] = hashFunc;
  messageParam[2] = MGF;
  messageParam[3] = SaltLen;
  messageParam[4] = PKCS1_ver;
  
  /* 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;
  }
  
  /* send private key */
  Error = SEPDriver_WriteParamater((DxUint32_t)RSA_WrappedKey_ptr ,
                            sizeof(KMNG_RSA_WrappedKey_t),
                            sizeof(KMNG_RSA_WrappedKey_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_KMNG_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_KMNG_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_KMNG_RSA_PKCS1v15_Sign		- for v1.5
 *   CRYS_KMNG_RSA_PKCS1v15_SHA1_Sign	- for v1.5 data is hashed with SHA1
 *   CRYS_KMNG_RSA_PKCS1v15_MD5_Sign	- for v1.5 data is hashed with MD5
 *   CRYS_KMNG_RSA_PSS_Sign			- for v2.1
 *   CRYS_KMNG_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] CRYS_KMNG_RSA_PrivWrappedKey_t - wrapped RSA private key from KMNG
 *
 *   @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_KMNG_RSA_Sign(KMNG_RSA_WrappedKey_t	RSA_WrappedKey_ptr,
											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)
{
  /* 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
  ------------------------*/
  
  UserContext_ptr=UserContext_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;
  } 
  
  /*if the private key object is DX_NULL return an error*/   
  if (RSA_WrappedKey_ptr == DX_NULL)
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
    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_KMNG_RSA_SIGN_OP_CODE;
  messageParam[1] = hashFunc;
  messageParam[2] = MGF;
  messageParam[3] = SaltLen;
  messageParam[4] = PKCS1_ver;
  messageParam[5] = inputLLITableAddr;
  messageParam[6] = numEntriesInTable;
  messageParam[7] = firstTableDataSize;
  
  /* 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;
  }
  
  /* 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;
  }
   
  /* send private key */
  Error = SEPDriver_WriteParamater((DxUint32_t)RSA_WrappedKey_ptr ,
                            sizeof(KMNG_RSA_WrappedKey_t),
                            sizeof(KMNG_RSA_WrappedKey_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 
  ---------------------*/
  
  /* 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_KMNG_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_KMNG_RSA_Sign */


/**
 *   @brief 
 *	 CRYS_KMNG_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_KMNG_RSA_PKCS1v15_VerifyInit - for v1.5
 *	CRYS_KMNG_RSA_PSS_VerifyInit		 - for v2.1
 *
 *   @param[in] CRYS_KMNG_RSA_PubWrappedKey_t - wrapped RSA public key from KMNG
 *
 *   @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_KMNG_RSA_VerifyInit(KMNG_RSA_WrappedKey_t	RSA_WrappedKey_ptr,
													CRYS_RSAPubUserContext_t	*UserContext_ptr,
													CRYS_RSA_HASH_OpMode_t		hashFunc,
													CRYS_PKCS1_MGF_t			MGF,
													DxUint16_t					SaltLen,
													CRYS_PKCS1_version			PKCS1_ver)
{
  /* The return error identifier */
  CRYSError_t Error;
  
  /* offset */
  DxUint32_t  sramOffset;
   
  /* read param */
  DxUint32_t  messageParam[5];
  
  /* max length */
  DxUint32_t  maxLength;
   
  /*----------------------------
       CODE
  ------------------------------*/
  
  Error = CRYS_OK;
                
  #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;
  }
      
  /*if the private key object is DX_NULL return an error*/   
  if (RSA_WrappedKey_ptr == DX_NULL)
  {
    Error = CRYS_RSA_INVALID_PUB_KEY_STRUCT_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_KMNG_RSA_VERIFY_INIT_OP_CODE;
  messageParam[1] = hashFunc;
  messageParam[2] = MGF;
  messageParam[3] = SaltLen;
  messageParam[4] = PKCS1_ver;
  
  /* sendparams */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam, 
                           sizeof(DxUint32_t) * 5,
                           sizeof(DxUint32_t) * 5,
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send public key */
  Error = SEPDriver_WriteParamater((DxUint32_t)RSA_WrappedKey_ptr ,
                            sizeof(KMNG_RSA_WrappedKey_t),
                            sizeof(KMNG_RSA_WrappedKey_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_KMNG_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_KMNG_RSA_VerifyInit */  				  
												


/**
 *  \brief CRYS_KMNG_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_KMNG_RSA_PKCS1v15_Verify			- for v1.5
 *	CRYS_KMNG_RSA_PKCS1v15_MD5_Verify		- for v1.5 data in is hashed with MD5
 *	CRYS_KMNG_RSA_PKCS1v15_SHA1_Verify		- for v1.5 data in is hashed with SHA1
 *	CRYS_KMNG_RSA_PSS_Verify					- for v2.1
 *	CRYS_KMNG_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] CRYS_KMNG_RSA_PubWrappedKey_t - wrapped RSA public key from KMNG
 *
 *  @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_KMNG_RSA_Verify(KMNG_RSA_WrappedKey_t	RSA_WrappedKey_ptr,
												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)
{
  /* 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[8];
  
  /* 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;
  
  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_KMNG_RSA_VERIFY_OP_CODE;
  messageParam[1] = hashFunc;
  messageParam[2] = MGF;
  messageParam[3] = SaltLen;
  messageParam[4] = PKCS1_ver;
  messageParam[5] = inputLLITableAddr;
  messageParam[6] = numEntriesInTable;
  messageParam[7] = firstTableDataSize;
  
  /* 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;
  }
   
  /* 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;
  }
  
  /* send public key */
  Error = SEPDriver_WriteParamater((DxUint32_t)RSA_WrappedKey_ptr ,
                            sizeof(KMNG_RSA_WrappedKey_t),
                            sizeof(KMNG_RSA_WrappedKey_t),
                            &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_KMNG_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_KMNG_RSA_Verify */


/**
 * @brief
 * CRYS_KMNG_RSA_PRIM_Encrypt implements the RSAEP algorithm as defined in PKCS#1 v2.1 6.1.1
 * 
 * @param[in] CRYS_KMNG_RSA_PubWrappedKey_t - wrapped RSA public key from KMNG
 * @param[in] PrimeData_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_KMNG_RSA_PRIM_Encrypt(KMNG_RSA_WrappedKey_t	RSA_WrappedKey_ptr,
												CRYS_RSAPrimeData_t	        *PrimeData_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[2];
  
  
  /*---------------------------------------
      CODE
  ----------------------------------------*/
       
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
 
  Error = CRYS_OK;
   
   
  /* checking the key database handle pointer */
  if( RSA_WrappedKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }

  /* checking the Prime Data pointer */
  if( PrimeData_ptr == DX_NULL )
  {
    Error = CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID;
    goto end_function;
  }

  /* 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;
  }
   
      
  /* if the data size is larger then the internal buffer return error */
  if( DataSize > sizeof(PrimeData_ptr->DataIn) )
  {
    Error = CRYS_RSA_INVALID_PUB_KEY_STRUCT_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_KMNG_RSA_PRIM_ENC_OP_CODE;
  messageParam[1] = DataSize;
  
  /* send params */
  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;
  }
  
  /* write data in */
  Error = SEPDriver_WriteParamater((DxUint32_t)Data_ptr,
                                       DataSize,
                                       64 * 4,
                                       &sramOffset,
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* write public key */
  Error = SEPDriver_WriteParamater((DxUint32_t)RSA_WrappedKey_ptr,
                                       sizeof(KMNG_RSA_WrappedKey_t),
                                       sizeof(KMNG_RSA_WrappedKey_t),
                                       &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_KMNG_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_KMNG_RSA_PRIM_Encrypt */



/**
 * @brief
 * CRYS_KMNG_RSA_PRIM_Decrypt implements the RSADP algorithm as defined in PKCS#1 v2.1 6.1.2
 * 
 *   
 *   @param[in] CRYS_KMNG_RSA_PrivWrappedKey_t - wrapped RSA private key from KMNG
 *   @param[in] PrimeData_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_KMNG_RSA_PRIM_Decrypt(KMNG_RSA_WrappedKey_t	RSA_WrappedKey_ptr,
												CRYS_RSAPrimeData_t	        *PrimeData_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[2];
  

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

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

  /* ...... checking the key database handle pointer .................... */
  if( RSA_WrappedKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }

  /* ...... checking the Prime Data pointer .................... */
  if( PrimeData_ptr == DX_NULL )
  {
    Error = CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID;
    goto end_function;
  }
   
  /* 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_KMNG_RSA_PRIM_DEC_OP_CODE;
  messageParam[1] = DataSize;
  
  /* send params */
  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;
  }
  
  /* write data in */
  Error = SEPDriver_WriteParamater((DxUint32_t)Data_ptr,
                                      DataSize,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* write private key */
  Error = SEPDriver_WriteParamater((DxUint32_t)RSA_WrappedKey_ptr,
                                       sizeof(KMNG_RSA_WrappedKey_t),
                                       sizeof(KMNG_RSA_WrappedKey_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_KMNG_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_KMNG_RSA_PRIM_Decrypt */

/**
 * @brief CRYS_DH_PKCS3_GetSecretKey computes the shared secret key in the following computation:
 	SecretKey = ServerPubKey ^ ClientPrvKey mod Prime
 
  	Note: All buffers arguments are represented in Big-Endian
 
  @param[in] ServerPubKey_ptr   - Pointer to the Server public key octet string - 
  @param[in] ServerPubKeySize   - The Server Public key Size (in bytes)
  @param[in] UserPubKey_ptr		- a pointer to the publick key structure. used for the Exp operation function
                                  the struct doesn't need to be initialized
  @param[in] PrimeData_ptr 		- a pointer to a structure containing internal buffers
                                  the struct doesn't need to be initialized    
  @param[out] SecretKey_ptr 	- Pointer to the secret key octet string.
  							  	  This buffer should be at least PrimeSize Bytes
  							  
  @param[in/out] SecretKeySize_ptr - The user should provide the actual size in bytes of the buffer indicated by SecretKey_ptr
                                    The function will return the actual size in bytes of the output secret key

  @return CRYSError_t - On success CRYS_OK is returned, on failure an ERROR as defined CRYS_DH_error.h:
                        CRYS_DH_INVALID_ARGUMENT_POINTER_ERROR;      
   		                CRYS_DH_INVALID_ARGUMENT_SIZE_ERROR;
		                CRYS_DH_SECRET_KEY_SIZE_OUTPUT_ERROR;
*/
CIMPORT_C CRYSError_t CRYS_KMNG_DH_PKCS3_GetSecretKey(KMNG_DH_WrappedKey_t  DH_WrappedKey_ptr,
                          													  DxUint8_t*            ServerPubKey_ptr,
                          													  DxUint16_t            ServerPubKeySize,				                    
                          													  CRYS_DHUserPubKey_t*  UserPubKey_ptr,
                          													  CRYS_DHPrimeData_t*   PrimeData_ptr, 				                    
                          													  DxUint8_t*            SecretKey_ptr,
                          													  DxUint16_t*           SecretKeySize_ptr)
{
  /* The return error identifier */
  CRYSError_t       Error;

  /* sram offset */
  DxUint32_t        sramOffset;
  
  /* message parameters */
  DxUint32_t        messageParam[7];

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

                             
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
   
  /* ............... checking the parameters validity ................... */
  /* -------------------------------------------------------------------- */


  /* if an argument pointer is DX_NULL return an error */
  if( ServerPubKey_ptr == DX_NULL || SecretKey_ptr == DX_NULL)
  {
    return CRYS_DH_INVALID_ARGUMENT_POINTER_ERROR; 
  }
       
  /* lock access to the SEP */
  Error = SEPDriver_Lock();
   
  if(Error != DX_OK)
  {
    goto end_function_no_unlock;
  }
   
  /*----------------------------
    start sending message to SEP 
  -----------------------------*/
  
  sramOffset = 0;
   
  /* start the message */
  SEPDriver_StartMessage(&sramOffset);
  
  /* prepare message */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_KMNG_DH_PKCS3_GET_SECRET_KEY_OP_CODE;
  messageParam[1] = ServerPubKeySize;
 
  
  /* send params */
  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 server public key */
  Error = SEPDriver_WriteParamater((DxUint32_t)ServerPubKey_ptr , 
                                   ServerPubKeySize ,
                                   64 * sizeof(DxUint32_t), 
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                             
  /* send activated private key  */
  Error = SEPDriver_WriteParamater((DxUint32_t)DH_WrappedKey_ptr,
                                    sizeof(KMNG_DH_WrappedKey_t),
                                    sizeof(KMNG_DH_WrappedKey_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 
  ---------------------*/
   
  /* 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_KMNG_DH_PKCS3_GET_SECRET_KEY_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 secret key size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam,
                            sizeof(DxUint32_t),
                            sizeof(DxUint32_t),
                            &sramOffset,
                            DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                            
  *SecretKeySize_ptr = (DxUint16_t)messageParam[0];
                            
  /* read secret key */
  Error = SEPDriver_ReadParamater((DxUint32_t)SecretKey_ptr,
                           *SecretKeySize_ptr,
                           64 * sizeof(DxUint32_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_no_unlock:

  return Error;  

#endif /*CRYS_NO_HASH_SUPPORT*/
#endif /*CRYS_NO_PKI_SUPPORT*/  

}
