/*
 *  Object %name    : %CRYS_ECPKI_KG.c
 *  State           :  %state%
 *  Creation date   :  02.02.2006
 *  Last modified   :  %modify_time%
 */
/** @file
 * \brief This module defines API of function for generating ECC private and public keys.
 *
 * \version CRYS_ECPKI_KG.c#1:csrc:1
 * \author  R.Levin
 * \remarks Copyright (C) 2006 by Discretix Technologies Ltd. All Rights reserved.
 */

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

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

#include "DX_VOS_Mem.h"
#include "CRYS_RND.h"
//#include "CRYS_COMMON.h"
//#include "CRYS_COMMON_math.h"

#include "CRYS_ECPKI_KG.h"
#include "CRYS_ECPKI_BUILD.h"
#include "CRYS_ECPKI_error.h"
#include "SEPDriver.h"
#include "crys_host_op_code.h"
#include "error.h"
//#include "CRYS_ECPKI_Local.h"

/* .............. LLF level includes and definitions.............. */
//#include "LLF_ECPKI_Export.h"

/* canceling the lint warning:
   Info 717: do ... while(0) */
/*lint --e{717} */

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

/* canceling the lint warning:
Info 716: while(1) ... */ 
/*lint --e{716} */

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

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

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

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

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

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

  /*****************  CRYS_ECPKI_GenKeyPair function   **********************/
  /**
   @brief Generates a pair of private and public keys  
          in little endian ordinary (non-Montgomery) form. 
	  
	  This function generates a new key pair and initializes 
	  the variables and structures so that these can be used by other EC primitives. 
	  The function performs the following:
		1. Checks the validity of all of the function inputs. If one of the received 
		    parameters is not valid, it returns an error. The major checks are:
		   - Whether DomainID is valid 
		   - Whether the user private key pointer(UserPrivKey_ptr) is not NULL 
		   - Whether the User Public Key pointer (UserPublKey_ptr) is not NULL 
		   - Whether the User passed temp data buffer is not NULL.
		2. Cleans buffers for private and public key structures.
		3. Calls the low level function  LLF_ECPKI_GenKeyPair.
		4. Outputs user public and private key structures in little endian form.
		5. Cleans temporary buffers. 
		6. Exits. 
 
   @param[in]  DomainID        - The enumerator variable defines current EC domain.
   @param[out] UserPrivKey_ptr - A pointer to the private key structure.                                  
   @param[out] UserPubKey_ptr  - A pointer to the public key structure.                                  
   @param[in]  TempData_ptr    - Temporary buffers of size defined in CRYS_ECPKI_KG_TempData_t.

   @return <b>CRYSError_t</b>: <br> 
			 CRYS_OK<br> 
                         CRYS_ECPKI_GEN_KEY_ILLEGAL_D0MAIN_ID_ERROR<br>
			 CRYS_ECPKI_GEN_KEY_INVALID_PRIVATE_KEY_PTR_ERROR<br>
			 CRYS_ECPKI_GEN_KEY_INVALID_PUBLIC_KEY_PTR_ERROR<br>
			 CRYS_ECPKI_GEN_KEY_INVALID_TEMP_DATA_PTR_ERROR<br>
*/
CEXPORT_C CRYSError_t CRYS_ECPKI_GenKeyPair(CRYS_ECPKI_DomainID_t  	    DomainID,	        /*in*/   
                              				    	CRYS_ECPKI_UserPrivKey_t   *UserPrivKey_ptr,    /*out*/
                              				 		  CRYS_ECPKI_UserPublKey_t   *UserPublKey_ptr,    /*out*/   
                                            CRYS_ECPKI_KG_TempData_t   *TempData_ptr        /*in*/ )
{
  /* the error identifier */
  CRYSError_t         Error;   
  
  /* offset */
  DxUint32_t          sramOffset;
   
  /* read param */
  DxUint32_t          messageParam[2];
  
  /* max length */
  DxUint32_t          maxLength; 

  /*---------------------------------------------
      CODE
  -------------------------------------------------*/
            
  #ifndef CRYS_NO_HASH_SUPPORT                                   
  #ifndef CRYS_NO_ECPKI_SUPPORT                                      

  /* ................. checking the validity of the pointer arguments ...... */
  /* ----------------------------------------------------------------------- */
   
  /* ...... checking the EC domain ID.................... */
  if( DomainID >= CRYS_ECPKI_DomainID_OffMode )
  {
    Error = CRYS_ECPKI_GEN_KEY_ILLEGAL_D0MAIN_ID_ERROR;
    goto end_function;
  }

  if( DomainID == CRYS_ECPKI_DomainID_EMPTY )
  {
    Error = CRYS_ECPKI_GEN_KEY_THIS_D0MAIN_IS_NOT_SUPPORTED_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the user private key pointer .......... */
  if( UserPrivKey_ptr == DX_NULL )
  {
    Error = CRYS_ECPKI_GEN_KEY_INVALID_PRIVATE_KEY_PTR_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the user public key pointer ........... */
  if( UserPublKey_ptr == DX_NULL )
  {
    Error = CRYS_ECPKI_GEN_KEY_INVALID_PUBLIC_KEY_PTR_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of temp buffers         .................. */
  if( TempData_ptr == DX_NULL )
  {
    Error = CRYS_ECPKI_GEN_KEY_INVALID_TEMP_DATA_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_KG_OP_CODE;
  messageParam[1] = DomainID;
  
  /* 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;
  }
  
  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_KG_OP_CODE)
  {
    Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
    goto end_function_unlock;
  }
   
  /* check the status */
  if(messageParam[1] != CRYS_OK)
  {
    Error = messageParam[1];
    goto end_function_unlock;
  }
  
  /* read the private key */
  maxLength = ((sizeof(CRYS_ECPKI_UserPrivKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)UserPrivKey_ptr , 
                          sizeof(CRYS_ECPKI_UserPrivKey_t) ,
                          maxLength,
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  /* read the public key */
  maxLength = ((sizeof(CRYS_ECPKI_UserPublKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)UserPublKey_ptr , 
                          sizeof(CRYS_ECPKI_UserPublKey_t) ,
                          maxLength,
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                                                   
  /* ...................... end of function ................................ */   

end_function_unlock:   

  /* lock access to the SEP */
  SEPDriver_Unlock();
  
                       
end_function:

  return Error; 

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

}/* END OF CRYS_ECPKI_GenKeyPair */                                       

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



