 /*
   *  Object %name    : %CRYS_ECDSA_Verify.c
   *  State           :  %state%
   *  Creation date   :  16.01.2007
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief This module contains the functions used to verifying the ECDSA signature.
   *
   *  \version CRYS_ECDSA_Verify.c#1:csrc:1
   *  \author R.Levin
   *  \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
   *           All Rights reserved
   */

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

/* .............. CRYS level includes ................. */
#include "DX_VOS_Mem.h"
#include "DX_VOS_Memmap.h"
#include "CRYS_ECPKI_error.h"
#include "CRYS_ECPKI_ECDSA.h"
#include "SEPDriver.h"
#include "crys_host_op_code.h"
#include "error.h"
#include "gen.h"

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

/* canceling the lint warning:
   Warning 548: else expected */
/*lint --e{548} */

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

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

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

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

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

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

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

/**************************************************************************
 *	              CRYS_ECDSA_VerifyInit  function
 **************************************************************************/
/**
   @brief  Prepares a context that is used by the Update and Finish functions
           but does not perform elliptic curve cryptographic processing

		    The function:
			- Receives and decrypts user data (working context). 
			- Checks input parameters of  ECDSA Vrifying primitive.
			- Calls hash init function.
			- Initializes variables and structures for calling next functions.
			- Encrypts and releases working context.
			
			NOTE: Using of HASH functions with HASH size great, than EC modulus size, 
			is not recommended!

   @param[in,out] VerifyUserContext_ptr - A pointer to the user buffer for verifying database.
   @param[in] SignerPublKey_ptr - A pointer to a Signer public key structure.
   @param[in] HashMode - The enumerator variable defines the hash function to be used.
   
   @return <b>CRYSError_t</b>: <br> 
			 CRYS_OK<br>
                         CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR <br>
			 CRYS_ECDSA_VERIFY_INVALID_SIGNER_PUBL_KEY_PTR_ERROR <br>
                         CRYS_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR <br>
                         CRYS_ECDSA_VERIFY_INVALID_DOMAIN_ID_ERROR <br>
			 CRYS_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR <br>
**/
CEXPORT_C CRYSError_t CRYS_ECDSA_VerifyInit(CRYS_ECDSA_VerifyUserContext_t  *VerifyUserContext_ptr, /*in/out*/
                          								  CRYS_ECPKI_UserPublKey_t        *SignerPublKey_ptr,     /*in*/
                          								  CRYS_ECPKI_HASH_OpMode_t        HashMode               /*in*/ )
{
  /* The return error identifier */
  CRYSError_t         Error;
  
  /* offset */
  DxUint32_t          sramOffset;
   
  /* read param */
  DxUint32_t          messageParam[2];
  
  /* max length */
  DxUint32_t          maxLength; 
   
  /*-------------------------------------
      CODE
  ---------------------------------------*/
  
   
  /* ............... local initializations .............................. */
  /* -------------------------------------------------------------------- */
   
  /* initializing the Error to OK */
  Error = CRYS_OK;

                            
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_ECPKI_SUPPORT    
                                   
      
  /* ............... checking the parameters validity ................... */
  /* -------------------------------------------------------------------- */
   
  /* if the users context ID pointer is DX_NULL return an error */
  if( VerifyUserContext_ptr == DX_NULL )
  {
    Error = CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR;
    goto end_function;
  }
      
  /*if the private key object is DX_NULL return an error*/   
  if (SignerPublKey_ptr == DX_NULL)
  {
    Error = CRYS_ECDSA_VERIFY_INVALID_SIGNER_PUBL_KEY_PTR_ERROR;
    goto end_function;
  }
  
  /* check if the hash operation mode is legal */
  if( HashMode >= CRYS_ECPKI_HASH_NumOfModes)
  {
    Error = CRYS_ECDSA_VERIFY_ILLEGAL_HASH_OP_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_ECC_VERIFY_INIT_OP_CODE;
  messageParam[1] = HashMode;
  
  /* 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 public key */
  maxLength = ((sizeof(CRYS_ECPKI_UserPublKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)SignerPublKey_ptr ,
                            sizeof(CRYS_ECPKI_UserPublKey_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_ECC_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 data out */
  maxLength = ((sizeof(CRYS_ECDSA_VerifyUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)VerifyUserContext_ptr ,
                          sizeof(CRYS_ECDSA_VerifyUserContext_t),
                          maxLength,
                          &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_ECPKI_SUPPORT */                                     

}/* _DX_ECDSA_VerifyInit */



/**************************************************************************
 *	              CRYS_ECDSA_VerifyUpdate function
 **************************************************************************/
/**
   @brief  Performs a hash  operation on data allocated by the user 
           before finally verifying its signature.
  
   	   In case user divides signing data by block, he must call the Update function 
   	   continuously a number of times until processing of the entire data block is complete.
   	   
       NOTE: Using of HASH functions with HASH size great, than EC modulus size, 
             is not recommended!

   @param[in,out] VerifyUserContext_ptr A pointer to the user buffer for verifying database.
   @param[in] 	  MessageDataIn_ptr   Message data for calculating Hash.   	
   @param[in]     DataInSize            The size of the message data block, in bytes.
   
   @return <b>CRYSError_t</b>: <br> 
			 CRYS_OK<br>
                         CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR <br>
			 CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR <br>
			 CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR <br>
			 CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR <br>
			 CRYS_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR <br>
 **/
CEXPORT_C CRYSError_t CRYS_ECDSA_VerifyUpdate(CRYS_ECDSA_VerifyUserContext_t  *VerifyUserContext_ptr, /*in/out*/
                          								    DxUint8_t                       *MessageDataIn_ptr,     /* in */ 
                          							  	  DxUint32_t                      DataInSize             /* in */ )
{
  /* The return error identifier */
  CRYSError_t         Error;
  
  /* offset */
  DxUint32_t          sramOffset;
   
  /* read param */
  DxUint32_t          messageParam[4];
  
  /* max length */
  DxUint32_t          maxLength;
   
  /* 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; 
  
  CRYS_HASHUserContext_t* HashUserContext_ptr;
  
  /* 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; 
  
  /* number of bytes to upate */
  DxUint32_t 		numBytesToUpdate;

  /* hash mode */
  CRYS_ECPKI_HASH_OpMode_t  hashOperationMode;

  /* block size */
  DxUint32_t              blockSize;


  /*---------------------------------
      CODE
  --------------------------------------*/
  
  /* .................. initializing local variables ................... */
  /* ------------------------------------------------------------------- */   
   
  /* initializing the Error to O.K */
  Error = CRYS_OK;      
                           
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_ECPKI_SUPPORT                                      
   
  /* ............... checking the parameters validity ................... */
  /* -------------------------------------------------------------------- */
   
  /* if the users context pointer is DX_NULL return an error */
  if( VerifyUserContext_ptr == DX_NULL )
  {
    Error = CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR;
    goto end_function;
  }
     
  /* if the users MessageDataIn pointer is illegal return an error */
  if( MessageDataIn_ptr == DX_NULL && DataInSize )
  {
    Error = CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR;
    goto end_function;
  }
     
  /* if the data size is larger then 2^29 (to prevent an overflow on the transition to bits ) 
  return error */
  if( DataInSize >= (1UL << 29) )
  {
    Error = CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR;
    goto end_function;
  }
            
  /* lock access to the SEP */
  Error = SEPDriver_Lock();
   
  if(Error != DX_OK)
  {
    goto end_function;
  }
  
  /* get the number of bytes from the beginning of the user buffer into the message */
  hashOperationMode = ((ECDSA_VerifyContext_t*)(VerifyUserContext_ptr->context_buff))->HashMode;
  
  /* get block size */
  switch (hashOperationMode)
  {
  	case CRYS_ECPKI_HASH_SHA1_mode:
  	case CRYS_ECPKI_HASH_SHA224_mode:
  	case CRYS_ECPKI_HASH_SHA256_mode:
  		blockSize = CRYS_HASH_BLOCK_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_HASH_SHA384_mode:
  	case CRYS_ECPKI_HASH_SHA512_mode:
  		blockSize = CRYS_HASH_SHA2_BLOCK_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_AFTER_HASH_SHA1_mode:
  		blockSize = CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_AFTER_HASH_SHA224_mode:
  		blockSize = CRYS_HASH_SHA224_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_AFTER_HASH_SHA256_mode:
  		blockSize = CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_AFTER_HASH_SHA384_mode:
  		blockSize = CRYS_HASH_SHA384_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_AFTER_HASH_SHA512_mode:
  		blockSize = CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES;
  		break;
  	default:
  		return CRYS_ECDSA_SIGN_ILLEGAL_HASH_OP_MODE_ERROR;
  }
  
  /* check if we're in after hash mode. if not - calculate numBytesFromStart, DMA tables and numBytesFromEnd */
  if (hashOperationMode >= CRYS_ECPKI_HASH_SHA1_mode && hashOperationMode  <= CRYS_ECPKI_HASH_SHA512_mode)
  {
    /* get the number of bytes from the beginning of the user buffer into the message */
    HashUserContext_ptr = &((ECDSA_VerifyContext_t*)(VerifyUserContext_ptr->context_buff))->HashUserContext;
    /* get the number of bytes to update */ 
    numBytesToUpdate = ((HASHContext_t*)(HashUserContext_ptr->context_buff))->NumOfBytesOnThePreviousUpdateBuff;
    
    /* 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;

  }
  else /* After hash mode */
  {
  	numBytesFromEnd = 0;
  	
  	/* set data size to the first block */
  	numBytesFromStart = DataInSize;  	
  }
  
  /* prepare tables for the input only */
  Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)(MessageDataIn_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_ECC_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)MessageDataIn_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)(MessageDataIn_ptr + DataInSize - numBytesFromEnd),
                                   numBytesFromEnd,
                                   sizeof(DxUint32_t) * 32,
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send context */
  maxLength = ((sizeof(CRYS_ECDSA_VerifyUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)VerifyUserContext_ptr ,
                            sizeof(CRYS_ECDSA_VerifyUserContext_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;
  }
  
  /* free allocated tables */
  Error = SEPDriver_FreeDMATables();
  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_ECC_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 data out */
  maxLength = ((sizeof(CRYS_ECDSA_VerifyUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)VerifyUserContext_ptr ,
                          sizeof(CRYS_ECDSA_VerifyUserContext_t),
                          maxLength,
                          &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_ECPKI_SUPPORT */                                     

}/* CRYS_ECDSA_VerifyUpdate */

				  

/**************************************************************************
 *	              CRYS_ECDSA_VerifyFinish function
 **************************************************************************/
/**
   @brief  Performs initialization of variables and structures, 
           calls the hash function for the last block of data (if necessary),  
   		   than calls LLF_ECDSA_VerifyCalcCall function for verifying signature  
		   according to EC DSA algorithm.

       NOTE: Using of HASH functions with HASH size great, than EC modulus size, 
			 is not recommended!	   

   @param[in] VerifyUserContext_ptr - A pointer to the user buffer for verifying the database.
   @param[in] SignatureIn_ptr       - A pointer to a buffer for the signature to be compared
   @param[in] SignatureSizeBytes    - The size of a user passed signature (must be 2*OrderSizeInBytes).

   @return <b>CRYSError_t</b>: <br>
              CRYS_OK <br>
			  CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR <br>
			  CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR <br>
			  CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR <br>
			  CRYS_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR <br>
			  CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_SIZE_ERROR <br>			  
			  CRYS_ECDSA_VERIFY_INVALID_DOMAIN_ID_ERROR <br>
**/
CEXPORT_C CRYSError_t CRYS_ECDSA_VerifyFinish(CRYS_ECDSA_VerifyUserContext_t  *VerifyUserContext_ptr, /*in*/ 
                                							DxUint8_t                       *SignatureIn_ptr,       /*in*/
                                							DxUint32_t                      SignatureSizeBytes      /*in*/  )
{
  /* The return error identifier */
  CRYSError_t         Error;
  
  /* offset */
  DxUint32_t          sramOffset;
   
  /* read param */
  DxUint32_t          messageParam[2];
  
  /* max length */
  DxUint32_t          maxLength; 

  /*-----------------------------
      CODE
  -------------------------------*/
   
  /* .................. initializing local variables ................... */
  /* ------------------------------------------------------------------- */   
   
  /* initializing the Error to O.K */
  Error = CRYS_OK;      
                        
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_ECPKI_SUPPORT                                      
   
  /* ............... checking the parameters validity ................... */
  /* -------------------------------------------------------------------- */
   
  /* if the users context pointer is DX_NULL return an error */
  if( VerifyUserContext_ptr == DX_NULL )
  {
    Error = CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR;
    goto end_function;
  }
      
  /* if the users Signature pointer is illegal then return an error */
  if( SignatureIn_ptr == DX_NULL  )
  {
    Error = CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_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_ECC_VERIFY_FINISH_OP_CODE;
  messageParam[1] = SignatureSizeBytes;
  
  /* 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 signature */
  Error = SEPDriver_WriteParamater((DxUint32_t)SignatureIn_ptr ,
                            SignatureSizeBytes,
                            38 * 4,
                            &sramOffset,
                            DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send context */
  maxLength = ((sizeof(CRYS_ECDSA_VerifyUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)VerifyUserContext_ptr ,
                            sizeof(CRYS_ECDSA_VerifyUserContext_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_ECC_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_ECPKI_SUPPORT */                                     
				    
}/* End DX_ECDSA_VerifyFinish */

/**************************************************************************
 *	              CRYS_ECDSA_Verify integrated function
 **************************************************************************/
/**
   @brief  Performs all ECDSA verifying operations simultaneously. 
		   
	   This function simply calls the Init, Update and Finish functions continuously.  
   	   This function's prototype is similar to the prototypes of the called functions 
   	   and includes all of their input and output arguments.
   	   
       NOTE: Using of HASH functions with HASH size great, than EC modulus size, 
			 is not recommended!
   	   

   @param[in]  VerifyUserContext_ptr - A pointer to the user buffer for verifying database.
   @param[in]  UserPublKey_ptr       - A pointer to a user public key structure.
   @param[in]  HashMode              - The enumerator variable defines the hash function to be used.
   @param[in]  MessageDataIn_ptr     - Message data for calculating hash.   			
   @param[in]  MessageSizeInBytes    - Size of block of message data in bytes.       
   @param[in]  SignatureIn_ptr       - A pointer to a buffer for output of signature. 
   @param[in]  SignatureSizeBytes    - Size of signature, in bytes (must be 2*OrderSizeInBytes).
                                       
   @return <b>CRYSError_t</b>: <br> 
              CRYS_OK <br>
              CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR <br> 
              CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR <br>
              CRYS_ECDSA_VERIFY_INVALID_DOMAIN_ID_ERROR <br>
              CRYS_ECDSA_VERIFY_INVALID_SIGNER_PUBL_KEY_PTR_ERROR <br>
              CRYS_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR <br>
              CRYS_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR <br>                
              CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR <br>
              CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR <br>						                        
              CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR <br>						 
              CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_SIZE_ERROR <br>
**/
CEXPORT_C CRYSError_t CRYS_ECDSA_Verify (CRYS_ECDSA_VerifyUserContext_t *VerifyUserContext_ptr, /*in/out*/
                              					 CRYS_ECPKI_UserPublKey_t       *UserPublKey_ptr,        /*in*/
                              					 CRYS_ECPKI_HASH_OpMode_t        HashMode,               /*in*/
                              					 DxUint8_t                      *SignatureIn_ptr,        /*in*/
                              					 DxUint32_t                      SignatureSizeBytes,     /*in*/
                              					 DxUint8_t                      *MessageDataIn_ptr,      /*in*/ 
                              					 DxUint32_t                      MessageSizeInBytes      /*in*/ )
{
  /* The return error identifier */
  CRYSError_t         Error;
  
  /* offset */
  DxUint32_t          sramOffset;
   
  /* read param */
  DxUint32_t          messageParam[6];
  
  /* max length */
  DxUint32_t          maxLength;
   
  /* 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;
  
  /* 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
  ------------------------------------*/
   
  /* .................. initializing local variables ................... */
  /* ------------------------------------------------------------------- */   
   
  /* initializing the Error to O.K */
  Error = CRYS_OK;      
  
  VerifyUserContext_ptr = VerifyUserContext_ptr;
                          
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_ECPKI_SUPPORT   
  
  /* if the users context ID pointer is DX_NULL return an error */
   if( VerifyUserContext_ptr == DX_NULL )
   {
        Error = CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR;
        goto end_function_no_unlock;
   }
      
   /*if the public key object is DX_NULL return an error*/   
   if (UserPublKey_ptr == DX_NULL)
   {
        Error = CRYS_ECDSA_VERIFY_INVALID_SIGNER_PUBL_KEY_PTR_ERROR; 
        goto end_function_no_unlock;
   }    
  
  /* if the users MessageDataIn pointer is illegal return an error */
  if( MessageDataIn_ptr == DX_NULL && MessageSizeInBytes )
  {
    Error = CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR;
    goto end_function_no_unlock;
  }
     
  
  /* if the users Signature pointer is illegal then return an error */
  if( SignatureIn_ptr == DX_NULL  )
  {
    Error = CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR;
    goto end_function_no_unlock;
  }
 
  /* lock access to the SEP */
  Error = SEPDriver_Lock();
   
  if(Error != DX_OK)
  {
    goto end_function_no_unlock;
  }
  
  /* get block size */
  switch (HashMode)
  {
  	case CRYS_ECPKI_HASH_SHA1_mode:
  	case CRYS_ECPKI_HASH_SHA224_mode:
  	case CRYS_ECPKI_HASH_SHA256_mode:
  		blockSize = CRYS_HASH_BLOCK_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_HASH_SHA384_mode:
  	case CRYS_ECPKI_HASH_SHA512_mode:
  		blockSize = CRYS_HASH_SHA2_BLOCK_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_AFTER_HASH_SHA1_mode:
  		blockSize = CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_AFTER_HASH_SHA224_mode:
  		blockSize = CRYS_HASH_SHA224_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_AFTER_HASH_SHA256_mode:
  		blockSize = CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_AFTER_HASH_SHA384_mode:
  		blockSize = CRYS_HASH_SHA384_DIGEST_SIZE_IN_BYTES;
  		break;
  	case CRYS_ECPKI_AFTER_HASH_SHA512_mode:
  		blockSize = CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES;
  		break;
  	default:
  		return CRYS_ECDSA_SIGN_ILLEGAL_HASH_OP_MODE_ERROR;
  }
  
  if (MessageSizeInBytes <= blockSize)
  {
    /* set start input as data in size */
    numBytesFromStart = MessageSizeInBytes;
    
    /* 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 = MessageSizeInBytes % blockSize;
  }
  
  /* prepare tables for the input only */
  Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)MessageDataIn_ptr,
                                                            MessageSizeInBytes - (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_ECC_VERIFY_OP_CODE;
  messageParam[1] = HashMode;
  messageParam[2] = inputLLITableAddr;
  messageParam[3] = numEntriesInTable;
  messageParam[4] = firstTableDataSize;
  messageParam[5] = SignatureSizeBytes;
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam ,
                           sizeof(DxUint32_t) * 6,
                           sizeof(DxUint32_t) * 6,
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                           
  /* send signature */
  Error = SEPDriver_WriteParamater((DxUint32_t)SignatureIn_ptr ,
                                    SignatureSizeBytes,
                                    38 * 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)MessageDataIn_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)(MessageDataIn_ptr + MessageSizeInBytes - numBytesFromEnd),
                                   numBytesFromEnd,
                                   sizeof(DxUint32_t) * 32,
                                   &sramOffset , 
                                   DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send public key */
  maxLength = ((sizeof(CRYS_ECPKI_UserPublKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserPublKey_ptr ,
                            sizeof(CRYS_ECPKI_UserPublKey_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;
  }
  
  
  /* 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_ECC_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_no_unlock:
  
  return Error;

   #endif /* !CRYS_NO_HASH_SUPPORT */
   #endif /* !CRYS_NO_ECPKI_SUPPORT */                                     

}/* END OF CRYS_ECDSA_Verify */

