
  /*
   *  Object %name    : %
   *  State           :  %state%
   *  Creation date   :  Thu Jan 13 09:23:24 2005
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief A brief description of this module
   *
   *  \version CRYS_RSA_Verify.c#1:csrc:6
   *  \author ohads
   *  \remarks Copyright (C) 2004 by Discretix Technologies Ltd.
   *           All Rights reserved
   */



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

#include "DX_VOS_Mem.h"
#include "DX_VOS_Memmap.h" 
#include "CRYS_RSA_error.h"
#include "CRYS_RSA_Types.h"
#include "crys_host_op_code.h"
#include "error.h"
#include "SEPDriver.h"
#include "gen.h"

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



/************************ Enums ******************************/


/************************ Typedefs ******************************/


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


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


/************************ Private Functions ******************************/

/**

   \brief RSA_VerifyInit implements the Verify algorithm either for 
   OKCS1 Ver 1.5 or Ver 2.1
   
   @param[in,out] UserContext_ptr - Pointer to a Context. The value
                                returned here must be passed to
                                the Update and Finish functions.
   @param[in] UserPubKey_ptr - Pointer to the User public key data
	                           structure as built in the Build function.
   @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
                        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_BAD_PARAM
*/


CEXPORT_C CRYSError_t _DX_RSA_VerifyInit(CRYS_RSAPubUserContext_t*  UserContext_ptr,
                                         CRYS_RSAUserPubKey_t*      UserPubKey_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 (UserPubKey_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_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 */
  maxLength = ((sizeof(CRYS_RSAUserPubKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserPubKey_ptr ,
                            sizeof(CRYS_RSAUserPubKey_t),
                            maxLength,
                            &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_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_RSA_VerifyInit */  				  


/**********************************************************************************************************/
/**
 
 
   \brief RSA_VerifyUpdate the update phase for the Verify algorithm either for 
   PKCS1 Ver 1.5 or Ver 2.1 

   @param[in] UserContext_ptr - Pointer to a valid context as
                            returned by CRYS_RSA_VerifyInit.
   @param[in] Data_ptr - Pointer to the data whose signature is
                         to be verified.
   @param[in] DataSize - The size, in bytes, of the data whose
                         signature is to be verified.

   @return CRYSError_t - CRYS_OK, CRYS_BAD_PARAM
*/   

CEXPORT_C CRYSError_t _DX_RSA_VerifyUpdate(CRYS_RSAPubUserContext_t*    UserContext_ptr,
                                           DxUint8_t*                   DataIn_ptr,
                                           DxUint32_t                   DataInSize)
{
  /* 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[4];   
  
  /* max length */
  DxUint32_t          maxLength;
  
  /* hash mode */
  CRYS_RSA_HASH_OpMode_t  hashOperationMode;
  
  /* temp user context pointer */
  CRYS_HASHUserContext_t	 *hashUserContext_ptr;
  
  /* number of bytes to upate */
  DxUint32_t 		numBytesToUpdate;
  
  /* 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
  ---------------------------------*/
  
  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( UserContext_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_USER_CONTEXT_POINTER_ERROR;
    goto end_function;
  }
      
  /* 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 the hash operation mode */
  hashOperationMode = ((RSAPubContext_t *)UserContext_ptr->context_buff)->HashOperationMode;
  
  /* get the hash user context */
  hashUserContext_ptr = &((RSAPubContext_t *)UserContext_ptr->context_buff)->HashUserContext;
  
  /* get the number of bytes to update */ 
  numBytesToUpdate = ((HASHContext_t *)hashUserContext_ptr->context_buff)->NumOfBytesOnThePreviousUpdateBuff;

  /* get block size */
  switch (hashOperationMode)
  {
  	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;
  }
  
  /* check if we're in after hash mode. if not - calculate numBytesFromStart, DMA tables and numBytesFromEnd */
  if (hashOperationMode >= CRYS_RSA_HASH_MD5_mode && hashOperationMode  <= CRYS_RSA_HASH_SHA512_mode)
  {
    /* get the number of bytes from the beginning of the user buffer into the message */
    numBytesFromStart = (blockSize - numBytesToUpdate) % blockSize;
    if(DataInSize < numBytesFromStart)
    {
      numBytesFromStart = DataInSize;
    }

	
    /* get the number of bytes from the beginning of the user buffer into the message */
    numBytesFromEnd = (DataInSize - numBytesFromStart) % 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 ) ; 
  }
  else /* After hash mode */
  {
  	
  	numBytesFromEnd = 0;
  	
  	/* set data size to the first block */
  	numBytesFromStart = DataInSize;
  	
    /* initialize LLI table to zero */
    Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)DataIn_ptr, 
                                                            DataInSize - (numBytesFromStart + numBytesFromEnd),
                                                            0,
                                                            &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_RSA_VERIFY_UPDATE_OP_CODE;
  messageParam[1] = inputLLITableAddr;
  messageParam[2] = numEntriesInTable;
  messageParam[3] = firstTableDataSize;
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam ,
                           sizeof(DxUint32_t) * 4,
                           sizeof(DxUint32_t) * 4,
                           &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 context */
  maxLength = ((sizeof(CRYS_RSAPubUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserContext_ptr , 
                            sizeof(CRYS_RSAPubUserContext_t) , 
                            maxLength,
                            &sramOffset , 
                            DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  SEPDriver_EndMessage(sramOffset);
            
  /* wait for the response */
  Error = SEPDriver_POLL_FOR_REPONSE();
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }
   
  /*-------------------
    start reading message from the SEP 
  ---------------------*/
  
  /* free allocated tables */
  Error = SEPDriver_FreeDMATables();
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  } 
  
  /* start the message */
  Error = SEPDriver_StartIncomingMessage(&sramOffset);
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }
  
  /* read opcode + status  */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t) * 2,
                          sizeof(DxUint32_t) * 2,
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  /* check the opcode */
  if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCOL_HOST_RSA_VERIFY_UPDATE_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_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_RSA_VerifyUpdate */			      		
			      

/**********************************************************************************************************/
/**

   \brief RSA_VerifyFinish implements the Finish Phase of the Verify algorithm
   as defined in PKCS#1 v2.1 or PKCS#1 v1.5

   @param[in] UserContext_ptr - Pointer to a valid context as
                            returned by CRYS_RSA_PSS_VerifyInit.
                            

   @param[in] Sig_ptr - 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).

   @return CRYSError_t - CRYS_OK, CRYS_INVALID_SIGNATURE,
                         CRYS_BAD_PARAM, CRYS_OUT_OF_RANGE 
*/



CEXPORT_C CRYSError_t _DX_RSA_VerifyFinish(CRYS_RSAPubUserContext_t*  UserContext_ptr,
                                           DxUint8_t*                 Sig_ptr)			      
{
  /* 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                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
   
  /* ............... checking the parameters validity ................... */
   
  /* if the users context 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 users context pointer is DX_NULL return an error */
  if( Sig_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_SIGNATURE_BUFFER_POINTER;
    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_RSA_VERIFY_FINISH_OP_CODE;
  
  /* 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 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 context */
  maxLength = ((sizeof(CRYS_RSAPubUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserContext_ptr , 
                            sizeof(CRYS_RSAPubUserContext_t) ,
                            maxLength, 
                            &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_RSA_VERIFY_FINISH_OP_CODE)
  {
    Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
    goto end_function_unlock;
  }
   
  /* check the status */
  if(messageParam[1] != CRYS_OK)
  {
    Error = messageParam[1];
    goto end_function_unlock;
  }
                                           
  /* ...................... end 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_RSA_VerifyFinish */			      


/**********************************************************************************************************/
/**
   \brief CRYS_RSA_PKCS1v15_Verify implements the RSASSA-PKCS1v15 algorithm
   as defined in PKCS#1 v2.1 9.2

	The actual macro that will be used by the users is:
	CRYS_RSA_PKCS1v15_Verify
	
   @param[in] UserContext_ptr - Pointer to the public Context, for the use of the 
   								function as a space to work on			
   @param[in] UserPubKey_ptr - Pointer to the public key data
                           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. 
   @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 - 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 - 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 
*/

				     
CEXPORT_C CRYSError_t _DX_RSA_Verify(CRYS_RSAPubUserContext_t*  UserContext_ptr,
                                     CRYS_RSAUserPubKey_t*      UserPubKey_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];
  
  /* 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 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 (UserPubKey_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;
  }                                   
  
  /* 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;
  }
  
  /* if the users context pointer is DX_NULL return an error */
  if( Sig_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_SIGNATURE_BUFFER_POINTER;
    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 */
	if (hashFunc < CRYS_RSA_After_HASH_NOT_KNOWN_mode)
	{
	  numBytesFromEnd = DataInSize % blockSize;	
	}
	else
	{
	  numBytesFromEnd = 0;
	}
    
  }
  
  /* 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_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 */
  maxLength = ((sizeof(CRYS_RSAUserPubKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserPubKey_ptr ,
                            sizeof(CRYS_RSAUserPubKey_t),
                            maxLength,
                            &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_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_RSA_Verify */


