
  /*
   *  Object %name    : %CRYS_EC_ELGAMAL.c
   *  State           :  %state%
   *  Creation date   :  18.05.2006
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief This module contains the functions used to encryption and decryption message using
   *   EC Elgamal algorithm.
   *
   *  \version CRYS_EC_ELGAMAL.c#1:csrc:1
   *  \author R.Levin
   *  \remarks Copyright (C) 2006 by Discretix Technologies Ltd.
   *           All Rights reserved
   */

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

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

#include <linux/module.h>
#include "CRYS_RND.h"
#include "CRYS_ECPKI_ELGAMAL.h"
#include "CRYS_ECPKI_error.h"
#include "SEPDriver.h"
#include "host_op_code.h"
#include "error.h"

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

/* canceling the lint warning:
  Info 740: Unusual pointer cast 
  (incompatible indirect types) */
/*lint --e{740} */

/* canceling the lint warning:
   Info 826: Suspicious pointer-to-pointer conversion 
   (area too small) */
/*lint --e{826} */

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


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

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

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

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

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

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



/*****************************************************************************************
 *		       _DX_ECPKI_ELGAMAL_Encrypt function	
 *                        											  
 *****************************************************************************************/
/**
   @brief: 	This function performs encryption of the message (transmitted key or any other 
            plain text)  with public key of the receiver  using EC Elgamal algorithm. 
			
            For calling this function from CRYS use the macro definition CRYS_ECPKI_ELGAMAL_Encrypt .
			
            Operation: The sender encrypts the message by the following sequence of steps:
			1. Checks validity of input pointers and parameters.
			2. Converts incoming message from big to little endian.
			3. Calls the LLF_ECPKI_ELGAMAL_Encrypt function, which performs encryption
			   according to Elgamal algorithm and outputs Encrypted message as two EC points V and B:
			4. Converts the encrypted message (V,B) into big endian form.
			5. Outputs the encrypted message as bytes array in big endian.
		    6. Exits.

			Assumptions: 
				1.	Public key W and EC domain parameters q, a, b, r, and G are valid and 
				    associated with each other; 
			    2.  Incoming receiver's public key must be in big endians.  
				3.	The size of incomming message f must be great than 0 and equal and less, than:
				        (size of EC modulus - 1)  - for case, that MSByte of modulus >= 100 :
                        (size of EC modulus - 2)  - for case, that MSByte of modulus < 100.
                    The size of the message must be agreed with the receiver (i.e. in both encrypt and decrypt 
					functions size of the plain message must be the same value).
                

   @param[in]  ReceiverUserPublKeyBE_ptr - A pointer to receiver public key (key in big endian).  
   @param[in]  MessageIn_ptr         - A pointer to message to be encrypted (message in big endian).
   @param[in]  MessageInSizeBytes    - A size of incoming message in bytes. The maximal size must be:
                                       MessageInSizeBytes <= ModulusSizeInBytes-1, but
									   if the value of MSByte of EC Domain modulus is less than 100,
									   then maximal size of the message must be decreased by one (now the
									   last condition is actual only for one of implemented domains - 
									   CRYS_ECPKI_DomainID_secp521r1).
   @param[in]  EncrMessageOut_ptr    - A pointer to buffer for encrypted message.
   @param[in,out] EncrMessOutSize_ptr- A pointer to size of uzer passed buffer for encrypted
                                       message (in) and actual size of encrypted message (out).
                                       Size of buffer must be not less, than 4*ModulusSizeInBytes. 
   @param[in]  IsEphemerKeyInternal  - A parameter defining whether ephemeral key internal or external (1,0).
   @param[in]  EphemerPrivKeyIn_ptr  - A pointer to ephemeral private key /user not uses this parameter/.
   @param[in]  EphemerPrivKeySizeBytes - A size (in bytes) of sender's ephemeral private key data, must be equal 
                                        or less than EC order size in bytes /user not uses this parameter/.
   @param[in]  TempData_ptr -          - A pointer to structure, containing temporary buffers of specified
                                         type.   
   @return CRYSError_t - CRYS_OK, 
                         CRYS_EC_ELGAMAL_ENCR_INVALID_RECEIVER_PUBL_KEY_PTR_ERROR
						 CRYS_EC_ELGAMAL_RECEIVER_PUBL_KEY_VALIDATION_TAG_ERROR
						 CRYS_EC_ELGAMAL_ENCR_INVALID_DOMAIN_ID_ERROR
						 CRYS_EC_ELGAMAL_ENCR_INVALID_MESSAGE_DATA_IN_PTR_ERROR
						 CRYS_EC_ELGAMAL_ENCR_INVALID_MESSAGE_DATA_IN_SIZE_ERROR						 
						 CRYS_EC_ELGAMAL_ENCR_INVALID_ENCR_MESSAGE_OUT_PTR_ERROR
						 CRYS_ECPKI_ELGAM_ENCR_INVALID_ENCR_MESSAGE_OUT_SIZE_PTR_ERROR
                      	 CRYS_ECPKI_ELGAM_ENCR_INVALID_ENCR_MESSAGE_OUT_SIZE_ERROR
						 CRYS_EC_ELGAMAL_ENCR_INVALID_TEMP_DATA_BUFFER_PTR_ERROR                         						 						 
						 CRYS_EC_ELGAMAL_ENCR_INVALID_EPHEMERAL_KEY_DATA_ERROR
						 CRYS_EC_ELGAMAL_ENCR_INVALID_EPHEMERAL_PRIV_KEY_SIZE_ERROR						 
*/  
CEXPORT_C CRYSError_t  _DX_ECPKI_ELGAMAL_Encrypt (CRYS_ECPKI_UserPublKey_t      *ReceiverUserPublKey_ptr, /*in*/
                                        					DxUint8_t                     *MessageIn_ptr,           /*in*/
                                        					DxUint32_t                    MessageInSizeBytes,      /*in*/
                                        					DxUint8_t                     *EncrMessageOut_ptr,      /*out*/
                                        					DxUint32_t                    *EncrMessOutSize_ptr,     /*in,out*/
                                                  DxInt8_t                      IsEphemerKeyInternal,    /*in*/
                                                  DxUint8_t                     *EphemerPrivKeyIn_ptr,    /*in*/ 
                                        					DxUint32_t                    EphemerPrivKeySizeBytes, /*in*/ 
                                        					CRYS_EC_ELGAMAL_TempData_t    *TempData_ptr             /*in*/ )
{
  /* the error identifier */
  CRYSError_t         Error;
  
  /* offset */
  DxUint32_t          sramOffset;
   
  /* read param */
  DxUint32_t          messageParam[4];
  
  /* max length */
  DxUint32_t          maxLength; 

  /*-----------------------------------------------
      CODE
  ----------------------------------------------------*/		 
                              
  Error = CRYS_OK;
                              
  #ifndef CRYS_NO_ECPKI_SUPPORT                                     

  /* ................. checking the validity of the input arguments ........ */
  /* ----------------------------------------------------------------------- */

      
  /* if the one of user passed pointers is NULL return an error  */
  if( ReceiverUserPublKey_ptr == DX_NULL )
  {
    Error = CRYS_EC_ELGAMAL_ENCR_INVALID_RECEIVER_PUBL_KEY_PTR_ERROR;
    goto end_function;
  }
    
  /* if the users MessageDataIn pointer is illegal return an error */
  if( MessageIn_ptr == DX_NULL  )
  {
    Error = CRYS_EC_ELGAMAL_ENCR_INVALID_MESSAGE_DATA_IN_PTR_ERROR;
    goto end_function;
  }
     

  /* if the users EncrMessageOut_ptr pointer is illegal return an error */
  if( EncrMessageOut_ptr == DX_NULL  )
  {
    Error = CRYS_EC_ELGAMAL_ENCR_INVALID_ENCR_MESSAGE_OUT_PTR_ERROR;
    goto end_function;
  }
    

  /* if the users EncrMessageOutSize_ptr pointer is illegal return an error */
  if( EncrMessOutSize_ptr == DX_NULL  )
  {
    Error = CRYS_EC_ELGAMAL_ENCR_INVALID_ENCR_MESS_OUT_SIZE_PTR_ERROR;
    goto end_function;
  }

  /* if the users TempData_ptr pointer is illegal return an error */
  if( TempData_ptr == DX_NULL  )
  {
    Error = CRYS_EC_ELGAMAL_ENCR_INVALID_TEMP_DATA_BUFFER_PTR_ERROR;
    goto end_function;
  }
 
  /* if illegal IsEphemerKeyInternal index value */
  if( (IsEphemerKeyInternal != 1) && (IsEphemerKeyInternal != 0) )
  {
    Error = CRYS_EC_ELGAMAL_ENCR_INVALID_EPHEMERAL_KEY_DATA_ERROR;
    goto end_function;
  }
   
  /* if the Ephemeral private key is not internal and  EphemerPrivKeyData_ptr = Null       
  or EphemerPrivKeySizeBytes == 0 return error */
  if( ( IsEphemerKeyInternal != 1 && (EphemerPrivKeyIn_ptr == DX_NULL || EphemerPrivKeySizeBytes == 0) ) )
  {
    Error = CRYS_EC_ELGAMAL_ENCR_INVALID_EPHEMERAL_KEY_DATA_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_ELGAMAL_ENC_OP_CODE;
  messageParam[1] = IsEphemerKeyInternal;
  messageParam[2] = EphemerPrivKeySizeBytes;
  messageParam[3] = MessageInSizeBytes;
  
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam ,
                           sizeof(DxUint32_t) * 3,
                           sizeof(DxUint32_t) * 3,
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  /* send the empehm key  */
  Error = SEPDriver_WriteParamater((DxUint32_t)EphemerPrivKeyIn_ptr , 
                            EphemerPrivKeySizeBytes ,
                            18 * 4 , 
                            &sramOffset , 
                            DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                            
  /* send data size */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[3] ,
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                           
  /* send the message  */
  Error = SEPDriver_WriteParamater((DxUint32_t)MessageIn_ptr , 
                            MessageInSizeBytes ,
                            18 * 4 , 
                            &sramOffset , 
                            DX_TRUE); 
  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)ReceiverUserPublKey_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_ELGAMAL_ENC_OP_CODE)
  {
    Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
    goto end_function_unlock;
  }
   
  /* check the status */
  if(messageParam[1] != CRYS_OK)
  {
    Error = messageParam[1];
    goto end_function_unlock;
  }
  
  /* data out size  */
  Error = SEPDriver_ReadParamater((DxUint32_t)EncrMessOutSize_ptr ,
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  /* read data out */
  maxLength = ((*EncrMessOutSize_ptr + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)EncrMessageOut_ptr ,
                          *EncrMessOutSize_ptr,
                          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_ECPKI_SUPPORT */                                   

}/* END OF CRYS_ECPKI_ELGAMAL_Encrypt */


EXPORT_SYMBOL(_DX_ECPKI_ELGAMAL_Encrypt);                                       

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




/*************************************************************************************
 *		       CRYS_ECPKI_ELGAMAL_Decrypt function	
 *                        											  
 *************************************************************************************/
/**
  @brief:  This function performs decryption of the encrypted message (transmitted key or any other 
        text) with private key of the receiver using EC Elgamal algorithm. 
 
        The Decrypting  primitive uses the following data as input:
	       - The EC Domain parameters (received through DomainID included in ReceiverUserPrivKey).
	       - The  message (V, B), which includes two EC points: 
                   V - the sender public key,  associated with the EC domain parameters and 
                   B - computed by sender by message and public key of receiver. 
                   The message must be in big endian bytes.

  <b>Operation:</b> The receiver decrypts the message by the following sequence of steps:
    1.  Checks validity of input parameters (partially).
	2.  Converts incoming message (V, B) to little endian form.
	3.  Calls the LLF_ECPKI_ELGAMAL_Decrypt function, which performs decryption
		according to Elgamal algorithm (used in WMDRM ), which performs all 
		decryption operations.
    4.  Converts decrypted message to big endian form.
    5.  Outputs the decrypted message as byte string of receiver passed length.   

	\Note: 1. The maximal size of decrypted message f, which may be derived right from encrypted message (V, B), 
	          is equalled:
                       - (size of EC modulus - 1)  - for case, that MSByte of modulus >= 100 :
                       - (size of EC modulus - 2)  - for case, that MSByte of modulus < 100.
	          The size of the decrypted message provided by receiver must be agreed with the sender 
			  (i.e. in both encrypt and decrypt functions the size of the plain message must be the same value).

   <b>Assumptions:</b> EC domain parameters q, a, b, r, and G are valid and associated with each other. 
 
   @param[in] ReceiverUserPrivKey_ptr    - A pointer to a receiver private key structure
   			                              (in affine coordinates).    				
   @param[in] EncrMessageIn_ptr          - The user passed pointer to the encrypted message 
                                           buffer.
   @param[in] EncrMessageSizeInBytes     - The size of input encrypted message. Must be equal to 
                                           4*(EC modulus size in bytes)   
   @param[out] DecrMessageOut_ptr        - The user passed pointer to buffer for output of  
   			                               decrypted message.
   @param[in/out] DecrMessageOutSize_ptr - A pointer to size of decrypted message: see note 1 above.
   @param[in] TempData_ptr               - A pointer to structure, containing temporary buffers of specified
                                           type.

   @return CRYSError_t - CRYS_OK,
                         CRYS_EC_ELGAMAL_DECR_INVALID_RECEIVER_PRIV_KEY_PTR_ERROR
                         CRYS_EC_ELGAMAL_RECEIVER_PRIV_KEY_VALIDATION_TAG_ERROR
                         CRYS_EC_ELGAMAL_DECR_INVALID_DOMAIN_ID_ERROR						   
						 CRYS_EC_ELGAMAL_DECR_INVALID_ENCR_MESSAGE_IN_PTR_ERROR 
						 CRYS_EC_ELGAMAL_DECR_INVALID_ENCR_MESSAGE_IN_SIZE_ERROR
						 CRYS_EC_ELGAMAL_DECR_INVALID_DECR_MESSAGE_OUT_PTR_ERROR
						 CRYS_EC_ELGAMAL_DECR_INVALID_DECR_MESSAGE_OUT_SIZE_PTR_ERROR
						 CRYS_EC_ELGAMAL_DECR_INVALID_DECR_MESSAGE_OUT_SIZE_ERROR
						 CRYS_EC_ELGAMAL_DECR_INVALID_TEMP_DATA_BUFFER_PTR_ERROR
						 
*/
CEXPORT_C CRYSError_t  CRYS_ECPKI_ELGAMAL_Decrypt (CRYS_ECPKI_UserPrivKey_t   *ReceiverUserPrivKey_ptr,  /*in*/	
                                          			   DxUint8_t                  *EncrMessageIn_ptr,        /*in*/
                                          				 DxUint32_t                 EncrMessageSizeInBytes,   /*in*/
                                          			   DxUint8_t                  *DecrMessageOut_ptr,       /*out*/
                                          				 DxUint32_t                 *DecrMessageOutSize_ptr,   /*in/out*/
                                          				 CRYS_EC_ELGAMAL_TempData_t *TempData_ptr              /*in*/ )

{				
  /* the error identifier */
  CRYSError_t         Error; 
  
  /* offset */
  DxUint32_t          sramOffset;
   
  /* read param */
  DxUint32_t          messageParam[4];
  
  /* max length */
  DxUint32_t          maxLength; 
   
  /*-------------------------------------
      CODE
  -----------------------------------------*/
                        
  #ifndef CRYS_NO_ECPKI_SUPPORT    
   
  /* initialize the error identifier to OK */
  Error = CRYS_OK;
                                 

  /* ................. checking the validity of the input arguments ........ */
  /* ----------------------------------------------------------------------- */

  /* if the one of user passed pointers is NULL return an error  */
  if( ReceiverUserPrivKey_ptr == DX_NULL )
  {
    Error = CRYS_EC_ELGAMAL_DECR_INVALID_RECEIVER_PRIV_KEY_PTR_ERROR;
    goto end_function;
  }
  
  /* if the users MessageDataIn pointer is illegal return an error */
  if( EncrMessageIn_ptr == DX_NULL  )
  {
    Error = CRYS_EC_ELGAMAL_DECR_INVALID_ENCR_MESSAGE_IN_PTR_ERROR;
    goto end_function;
  }
  
  /* if the users EncrMessageOut_ptr pointer is illegal return an error */
  if( DecrMessageOut_ptr == DX_NULL  )
  {
    Error = CRYS_EC_ELGAMAL_DECR_INVALID_DECR_MESSAGE_OUT_PTR_ERROR;
    goto end_function;
  }
    
  /* if the users EncrMessageOutSize_ptr pointer is illegal return an error */
  if( DecrMessageOutSize_ptr == DX_NULL  )
  {
    Error = CRYS_EC_ELGAMAL_DECR_INVALID_DECR_MESSAGE_OUT_SIZE_PTR_ERROR;
    goto end_function;
  }
      
  /* if the users TempData_ptr pointer is illegal return an error */
  if( TempData_ptr == DX_NULL  )
  {
    Error = CRYS_EC_ELGAMAL_DECR_INVALID_TEMP_DATA_BUFFER_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_ELGAMAL_DEC_OP_CODE;
  messageParam[1] = EncrMessageSizeInBytes;
  messageParam[2] = *DecrMessageOutSize_ptr;
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam ,
                           sizeof(DxUint32_t) * 3,
                           sizeof(DxUint32_t) * 3,
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                            
  /* send the message  */
  Error = SEPDriver_WriteParamater((DxUint32_t)EncrMessageIn_ptr , 
                            EncrMessageSizeInBytes ,
                            74 * 4 , 
                            &sramOffset , 
                            DX_TRUE); 
  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)ReceiverUserPrivKey_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_ELGAMAL_DEC_OP_CODE)
  {
    Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
    goto end_function_unlock;
  }
   
  /* check the status */
  if(messageParam[1] != CRYS_OK)
  {
    Error = messageParam[1];
    goto end_function_unlock;
  }
  
  /* data out size  */
  Error = SEPDriver_ReadParamater((DxUint32_t)DecrMessageOutSize_ptr ,
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  /* read data out */
  maxLength = ((*DecrMessageOutSize_ptr + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)DecrMessageOut_ptr ,
                          *DecrMessageOutSize_ptr,
                          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_ECPKI_SUPPORT */                                   

}/* END OF CRYS_ECPKI_ELGAMAL_Decrypt */                  

EXPORT_SYMBOL(CRYS_ECPKI_ELGAMAL_Decrypt);


