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

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

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

#include <linux/module.h>
#include "CRYS_ECPKI_ECDSA.h"
#include "CRYS_ECPKI_error.h"
#include "SEPDriver.h"
#include "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_Sign_Init function
 **************************************************************************/
/**
   \brief    
   The CRYS_ECDSA_Sign_Init functions user shall call first to perform the 
   EC DSA Signing operation.

   The function performs the following steps:
   -# Validates all the inputs of the function. If one of the received 
      parameters is not valid, the function returns an error. 
   -# Decrypts the received context to the working context after capturing 
      the working context by calling the CRYS_CCM_GetContext() function.
   -# Initializes the working context and other variables and structures. 
   -# Calls the CRYS_HASH_Init() function.
   -# Calls the CRYS_CCM_EncryptAndReleaseContext() function to encrypt 
      the information in the working context, store it in the user's 
      received context, and then release the working context.
   -# Exits the handler with the OK code.

   This function does not do ECDSA cryptographic processing. Rather, it
   prepares a context that is used by the Update() and Finish() functions.
   
   NOTE: Using of HASH functions with HASH size great, than EC modulus size, is not recommended!
   
   
   @param[in,out] SignUserContext_ptr A pointer to the user buffer for signing data.
   @param[in] 	  SignerPrivKey_ptr   A pointer to the private key that will be used to 
                                      sign the data.
   @param[in]     HashMode            Defines the hash mode used for DSA.

   @return <b>CRYSError_t</b>: <br> 
			 CRYS_OK<br>
			 CRYS_ECDSA_SIGN_INVALID_USER_CONTEXT_PTR_ERROR
			 CRYS_ECDSA_SIGN_INVALID_USER_PRIV_KEY_PTR_ERROR
			 CRYS_ECDSA_SIGN_USER_PRIV_KEY_VALIDATION_TAG_ERROR
			 CRYS_ECDSA_SIGN_INVALID_DOMAIN_ID_ERROR
			 CRYS_ECDSA_SIGN_ILLEGAL_HASH_OP_MODE_ERROR		 
*/
CEXPORT_C CRYSError_t CRYS_ECDSA_SignInit(CRYS_ECDSA_SignUserContext_t  *SignUserContext_ptr, /*in/out*/
              								            CRYS_ECPKI_UserPrivKey_t      *SignerPrivKey_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
  --------------------------------------*/
   
  /* 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 ID pointer is DX_NULL return an error */
  if(SignUserContext_ptr == DX_NULL )
  {
    Error = CRYS_ECDSA_SIGN_INVALID_USER_CONTEXT_PTR_ERROR;
    goto end_function;
  }
      
  /*if the private key pointer is DX_NULL or its validation tag is not valid return an error*/   
  if (SignerPrivKey_ptr == DX_NULL)
  {
    Error = CRYS_ECDSA_SIGN_INVALID_USER_PRIV_KEY_PTR_ERROR;
    goto end_function;
  }
  	   	  
  /* check if the hash operation mode is legal */
  if(HashMode >= CRYS_ECPKI_HASH_NumOfModes)
  {
    Error = CRYS_ECDSA_SIGN_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_SIGN_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 private key */
  maxLength = ((sizeof(CRYS_ECPKI_UserPrivKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)SignerPrivKey_ptr ,
                            sizeof(CRYS_ECPKI_UserPrivKey_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_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 data out */
  maxLength = ((sizeof(CRYS_ECDSA_SignUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)SignUserContext_ptr ,
                          sizeof(CRYS_ECDSA_SignUserContext_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_SignInit */

EXPORT_SYMBOL(CRYS_ECDSA_SignInit);



/**************************************************************************
 *	              CRYS_ECDSA_Sign_Update function
 **************************************************************************/
/**
   @brief  Performs a hash  operation on data allocated by the user 
           before finally signing it.
  
   	   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] SignUserContext_ptr A pointer to the user buffer for signing the 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_SIGN_INVALID_USER_CONTEXT_PTR_ERROR
                         CRYS_ECDSA_SIGN_USER_CONTEXT_VALIDATION_TAG_ERROR
			 CRYS_ECDSA_SIGN_INVALID_MESSAGE_DATA_IN_PTR_ERROR 
			 CRYS_ECDSA_SIGN_INVALID_MESSAGE_DATA_IN_SIZE_ERROR
			 CRYS_ECDSA_SIGN_ILLEGAL_HASH_OP_MODE_ERROR
		 										 
 */
CEXPORT_C CRYSError_t CRYS_ECDSA_SignUpdate(CRYS_ECDSA_SignUserContext_t  *SignUserContext_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; 

  /*-----------------------------------
      CODE
  --------------------------------------*/
  
  /* 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( SignUserContext_ptr == DX_NULL )
  {
    Error = CRYS_ECDSA_SIGN_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_SIGN_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_SIGN_INVALID_MESSAGE_DATA_IN_SIZE_ERROR;
    goto end_function;
  }
      
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function;
   }

  /* prepare tables for the input only */
  Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)MessageDataIn_ptr , 
                                                            DataInSize ,
                                                            &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_SIGN_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 context */
  maxLength = ((sizeof(CRYS_ECDSA_SignUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)SignUserContext_ptr ,
                            sizeof(CRYS_ECDSA_SignUserContext_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 != CRYS_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_SIGN_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_SignUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)SignUserContext_ptr ,
                          sizeof(CRYS_ECDSA_SignUserContext_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_SignUpdate */

EXPORT_SYMBOL(CRYS_ECDSA_SignUpdate);




/**************************************************************************
 *	              _DX_ECDSA_Sign_Finish function
 **************************************************************************/
/**
   @brief  Performs initialization of variables and structures, calls the hash function  
           for the last block of data (if necessary) and then calculates digital 
		   signature according to the EC DSA algorithm.
   	   
   	   NOTE: Using of HASH functions with HASH size great, than EC modulus size, 
	         is not recommended!

   @param[in] SignUserContext_ptr      A pointer to the user buffer for signing database.
   @param[in] SignatureOut_ptr         A pointer to a buffer for output of signature.
   @param[in,out] SignatureOutSize_ptr The size of a user passed buffer for signature (in)
                                       and size of actual signature (out). The size of buffer 
									   must be not less than 2*OrderSizeInBytes.
   @param[out] IsEphemerKeyInternal    A parameter defining whether the ephemeral key 
                                       is internal or external (1 or 0).
   @param[out] EphemerKeyData_ptr      A pointer to external ephemeral key data. The buffer must
                                       to contain the following data placed continuously:
									    - ephemeral private key  - 4*(ModSizeInWords + 1 ) bytes,
										- ephemeral public key X - 4*ModSizeInWords bytes,
										- ephemeral public key Y - 4*ModSizeInWords bytes.
   @return <b>CRYSError_t</b>: <br> 
			 CRYS_OK<br>
                         CRYS_ECDSA_SIGN_INVALID_USER_CONTEXT_PTR_ERROR <br>
			 CRYS_ECDSA_SIGN_USER_CONTEXT_VALIDATION_TAG_ERROR <br>
			 CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_PTR_ERROR <br>
			 CRYS_ECDSA_SIGN_ILLEGAL_HASH_OP_MODE_ERROR <br>
			 CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_PTR_ERROR <br>
			 CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_ERROR <br>
			 CRYS_ECDSA_SIGN_INVALID_DOMAIN_ID_ERROR <br>
			 CRYS_ECDSA_SIGN_INVALID_IS_EPHEMER_KEY_INTERNAL_ERROR <br>
			 CRYS_ECDSA_SIGN_INVALID_EPHEMERAL_KEY_PTR_ERROR <br>
**/
CEXPORT_C  CRYSError_t _DX_ECDSA_SignFinish(CRYS_ECDSA_SignUserContext_t   *SignUserContext_ptr, /*in*/ 
                              							DxUint8_t                      *SignatureOut_ptr,    /*out*/
                              							DxUint32_t                     *SignatureOutSize_ptr,/*in/out*/
                                            DxInt8_t                       IsEphemerKeyInternal, /*in*/
                                            DxUint32_t                     *EphemerKeyData_ptr   /*in*/ ) 
{
  /* 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_ECPKI_SUPPORT                                      
   
  /* ............... checking the parameters validity ................... */
  /* -------------------------------------------------------------------- */
   
  /* if the users context pointer is DX_NULL return an error */
  if( SignUserContext_ptr == DX_NULL )
  {
    Error = CRYS_ECDSA_SIGN_INVALID_USER_CONTEXT_PTR_ERROR;
    goto end_function;
  }
        
  /* if the users SignatureOut pointer is illegal return an error */
  if( SignatureOut_ptr == DX_NULL  )
  {
    Error = CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_PTR_ERROR;
    goto end_function;
  }
   
  /* if the users SignatureOutSize pointer is illegal return an error */
  if( SignatureOutSize_ptr == DX_NULL  )
  {
    Error = CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_PTR_ERROR;
    goto end_function;
  }

  /* if user set an illegal IsEphemerKeyInternal value or illegal pointer return an error */
  if( IsEphemerKeyInternal != 1 && IsEphemerKeyInternal != 0  )
  {
    Error = CRYS_ECDSA_SIGN_INVALID_IS_EPHEMER_KEY_INTERNAL_ERROR;
    goto end_function;
  }
     
  if( IsEphemerKeyInternal == 0 && EphemerKeyData_ptr == DX_NULL )
  {
    Error = CRYS_ECDSA_SIGN_INVALID_EPHEMERAL_KEY_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_SIGN_FINISH_OP_CODE;
  messageParam[1] = IsEphemerKeyInternal;
  
  /* 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)EphemerKeyData_ptr ,
                            55 * 4,
                            55 * 4,
                            &sramOffset,
                            DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send context */
  maxLength = ((sizeof(CRYS_ECDSA_SignUserContext_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)SignUserContext_ptr ,
                            sizeof(CRYS_ECDSA_SignUserContext_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_SIGN_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;
  }
  
  /* read data out length */
  Error = SEPDriver_ReadParamater((DxUint32_t)SignatureOutSize_ptr ,
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  /* read data out */
  maxLength = ((*SignatureOutSize_ptr + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)SignatureOut_ptr ,
                          *SignatureOutSize_ptr,
                          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_SignFinish */

EXPORT_SYMBOL(_DX_ECDSA_SignFinish);



/**************************************************************************
 *	              CRYS_ECDSA_Sign - integrated function
 **************************************************************************/
/**
   @brief  Performs all of the ECDSA signing 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,out] SignUserContext_ptr - A pointer to the user buffer for signing database.
   @param[in]     SignerPrivKey_ptr   - A pointer to a user private key structure.    				
   @param[in]     HashMode            - The enumerator variable defines hash function to be used.                         
   @param[in] 	  MessageDataIn_ptr   - A message data for calculation of hash.   			
   @param[in]     MessageSizeInBytes  - A size of block of message data in bytes. 
   @param[in]     SignatureOut_ptr    - A pointer to a buffer for output of signature.                         
   @param[in,out] SignatureOutSize_ptr- Size of user passed buffer for signature (in)
                                        and size of actual signature (out). The size of buffer 
									    must be not less than 2*OrderSizeInBytes.
   @return <b>CRYSError_t</b>: <br> 
			 CRYS_OK<br>
			 CRYS_ECDSA_SIGN_INVALID_USER_CONTEXT_PTR_ERROR<br>
			 CRYS_ECDSA_SIGN_USER_CONTEXT_VALIDATION_TAG_ERROR<br>
 		     CRYS_ECDSA_SIGN_INVALID_USER_PRIV_KEY_PTR_ERROR<br>
			 CRYS_ECDSA_SIGN_USER_PRIV_KEY_VALIDATION_TAG_ERROR<br>
			 CRYS_ECDSA_SIGN_ILLEGAL_HASH_OP_MODE_ERROR <br>                         
			 CRYS_ECDSA_SIGN_INVALID_MESSAGE_DATA_IN_PTR_ERROR<br> 
			 CRYS_ECDSA_SIGN_INVALID_MESSAGE_DATA_IN_SIZE_ERROR<br>
			 CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_PTR_ERROR<br>
			 CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_PTR_ERROR<br>
             CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_ERROR<br>			 
			 CRYS_ECDSA_SIGN_INVALID_DOMAIN_ID_ERROR <br>			 
**/
CEXPORT_C CRYSError_t CRYS_ECDSA_Sign(CRYS_ECDSA_SignUserContext_t  *SignUserContext_ptr,     /*in/out*/
                            					CRYS_ECPKI_UserPrivKey_t      *SignerPrivKey_ptr,       /*in*/
                            					CRYS_ECPKI_HASH_OpMode_t       HashMode,                /*in*/
                            					DxUint8_t                     *MessageDataIn_ptr,       /*in*/ 
                            					DxUint32_t                     MessageSizeInBytes,      /*in*/
                            					DxUint8_t                     *SignatureOut_ptr,        /*out*/ 
                            					DxUint32_t                    *SignatureOutSize_ptr     /*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; 

  /*---------------------------------
      CODE
  ------------------------------------*/
  
  SignUserContext_ptr = SignUserContext_ptr;
  
  /* .................. initializing local variables ................... */
  /* ------------------------------------------------------------------- */   
   
  /* initializing the Error to O.K */
  Error = CRYS_OK;      
   
                         
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_ECPKI_SUPPORT                                      
 
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function_no_unlock;
   }

  /* prepare tables for the input only */
  Error = SEPDriver_PREPARE_INPUT_SYM_DMA_TABLE((DxUint32_t)MessageDataIn_ptr , 
                                                            MessageSizeInBytes ,
                                                            &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_SIGN_OP_CODE;
  messageParam[1] = HashMode;
  messageParam[2] = inputLLITableAddr;
  messageParam[3] = numEntriesInTable;
  messageParam[4] = firstTableDataSize;
  messageParam[5] = 1;
  
  /* 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 ephermal key */
  sramOffset += 55 * 4;
  
  /* send private key */
  maxLength = ((sizeof(CRYS_ECPKI_UserPrivKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)SignerPrivKey_ptr ,
                            sizeof(CRYS_ECPKI_UserPrivKey_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_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 data out size */
  Error = SEPDriver_ReadParamater((DxUint32_t)SignatureOutSize_ptr ,
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  /* read data out */
  maxLength = ((*SignatureOutSize_ptr + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)SignatureOut_ptr ,
                          *SignatureOutSize_ptr,
                          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_no_unlock:

  return Error;

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

}/* END OF CRYS_ECDSA_Sign */

EXPORT_SYMBOL(CRYS_ECDSA_Sign);

