
  /*
   *  Object %name    : %
   *  State           :  %state%
   *  Creation date   :  Sun Mar 06 16:41:01 2005
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief A brief description of this module
   *
   *  \version CRYS_RSA_KG.c#1:csrc:1
   *  \author adams
   *  \remarks Copyright (C) 2004 by Discretix Technologies Ltd.
   *           All Rights reserved
   */



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

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

#include "DX_VOS_Mem.h"
#include "CRYS_RND.h"
#include "CRYS_RSA_KG.h"
#include "CRYS_RSA_error.h"
#include "error.h"
#include "crys_host_op_code.h"
#include "SEPDriver.h"


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


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



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


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


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

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


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

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

/**
   @brief CRYS_RSA_KG_GenerateKeyPair generates a Pair of public and private keys on non CRT mode.
 
   @param[in] PubExp_ptr - The pointer to the public exponent (public key)
   @param[in] PubExpSizeInBytes - The public exponent size in bits.
   @param[in] KeySize  - The size of the key, in bits. Supported sizes are:
                            - for PKI without PKA HW: all 256 bit multiples between 512 - 2048;
                            - for PKI with PKA: HW all 32 bit multiples between 512 - 2112;
   @param[out] UserPrivKey_ptr - A pointer to the private key structure. 
                           This structure is used as input to the CRYS_RSA_PRIM_Decrypt API.
   @param[out] UserPubKey_ptr - A pointer to the public key structure. 
                           This structure is used as input to the CRYS_RSA_PRIM_Encrypt API.
   @param[in] KeyGenData_ptr - a pointer to a structure required for the KeyGen operation.                       

   @return CRYSError_t - CRYS_OK,
                         CRYS_RSA_INVALID_EXPONENT_POINTER_ERROR,
                         CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR,
                         CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR,
                         CRYS_RSA_KEY_GEN_DATA_STRUCT_POINTER_INVALID,
                         CRYS_RSA_INVALID_MODULUS_SIZE,
                         CRYS_RSA_INVALID_EXPONENT_SIZE
*/

CEXPORT_C CRYSError_t CRYS_RSA_KG_GenerateKeyPair(DxUint8_t*              PubExp_ptr,
                                                  DxUint16_t              PubExpSizeInBytes, 
                                                  DxUint32_t              KeySize,
                                                  CRYS_RSAUserPrivKey_t*  UserPrivKey_ptr,
                                                  CRYS_RSAUserPubKey_t*   UserPubKey_ptr,
                                                  CRYS_RSAKGData_t*       KeyGenData_ptr )
{
  /* the error identifier */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[4];
  
  /* max length */
  DxUint32_t    maxLength;
      
  /*-------------------------------------
      CODE
  --------------------------------------*/
  
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      

  Error = CRYS_OK;
   
  /* ................. checking the validity of the pointer arguments ....... */
  
  /* ...... checking the key database handle pointer .................... */
  if( PubExp_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_EXPONENT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the exponent pointer ............... */
  if( UserPrivKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the modulus pointer .............. */
  if( UserPubKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the keygen data .................. */
  if( KeyGenData_ptr == DX_NULL )
  {
    Error = CRYS_RSA_KEY_GEN_DATA_STRUCT_POINTER_INVALID;
    goto end_function;
  }
      
  /* ...... checking the required key size ............................ */
  if( ( KeySize < CRYS_RSA_MIN_VALID_KEY_SIZE_VALUE_IN_BITS ) ||
      ( KeySize > CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS ) ||
      ( KeySize % CRYS_RSA_VALID_KEY_SIZE_MULTIPLE_VALUE_IN_BITS ) )
  {
    Error = CRYS_RSA_INVALID_MODULUS_SIZE;
    goto end_function;
  }
  
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function;
   }
  
  /*----------------------------
      start sending message to SEP 
  -----------------------------*/
  sramOffset = 0;
   
  /* start the message */
  SEPDriver_StartMessage(&sramOffset);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_RSA_KG_OP_CODE;
  messageParam[1] = 1;
  messageParam[2] = KeySize;
  messageParam[3] = PubExpSizeInBytes;
  
  /* 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 exponent */
  Error = SEPDriver_WriteParamater((DxUint32_t)PubExp_ptr , 
                            PubExpSizeInBytes,
                            64 * 4 , 
                            &sramOffset , 
                            DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  SEPDriver_EndMessage(sramOffset);
            
  /* wait for the response */
  Error = SEPDriver_POLL_FOR_REPONSE();
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }
   
  /*-------------------
    start reading message from the SEP 
  ---------------------*/
   
  /* start the message */
  Error = SEPDriver_StartIncomingMessage(&sramOffset);
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }
   
  /* read opcode + status */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t) * 2,
                          sizeof(DxUint32_t) * 2,
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  /* check the opcode */
  if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCOL_HOST_RSA_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_RSAUserPrivKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)UserPrivKey_ptr,
                           sizeof(CRYS_RSAUserPrivKey_t),
                           maxLength,
                           &sramOffset,
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                              
  /* read public key */
  maxLength = ((sizeof(CRYS_RSAUserPubKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)UserPubKey_ptr,
                           sizeof(CRYS_RSAUserPubKey_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_PKI_SUPPORT */                                     

}/* END OF CRYS_RSA_KG_GenerateKeyPair */                                       

                                      
/***********************************************************************************************/
/**
   @brief CRYS_RSA_KG_GenerateKeyPairCRT generates a Pair of public and private keys on CRT mode.

   @param[in] PubExp_ptr - The pointer to the public exponent (public key)
   @param[in] PubExpSizeInBytes - The public exponent size in bits. 
   @param[in] KeySize  - The size of the key, in bits. Supported sizes are:
                            - for PKI without PKA HW: all 256 bit multiples between 512 - 2048;
                            - for PKI with PKA: HW all 32 bit multiples between 512 - 2112;
   @param[out] UserPrivKey_ptr - A pointer to the private key structure. 
                           This structure is used as input to the CRYS_RSA_PRIM_Decrypt API.
   @param[out] UserPubKey_ptr - A pointer to the public key structure. 
                           This structure is used as input to the CRYS_RSA_PRIM_Encryped API.
   @param[in] KeyGenData_ptr - a pointer to a structure required for the KeyGen operation.                       

   @return CRYSError_t - CRYS_OK,
                         CRYS_RSA_INVALID_EXPONENT_POINTER_ERROR,
                         CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR,
                         CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR,
                         CRYS_RSA_KEY_GEN_DATA_STRUCT_POINTER_INVALID,
                         CRYS_RSA_INVALID_MODULUS_SIZE,
                         CRYS_RSA_INVALID_EXPONENT_SIZE
*/

CEXPORT_C CRYSError_t CRYS_RSA_KG_GenerateKeyPairCRT(DxUint8_t*               PubExp_ptr,
                                                     DxUint16_t               PubExpSizeInBytes, 
                                                     DxUint32_t               KeySize,
                                                     CRYS_RSAUserPrivKey_t*   UserPrivKey_ptr,
                                                     CRYS_RSAUserPubKey_t*    UserPubKey_ptr,
                                                     CRYS_RSAKGData_t*        KeyGenData_ptr )
{
  /* the error identifier */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[4];
  
  /* max length */
  DxUint32_t    maxLength;
      
  /*-----------------------------------------
      CODE
  --------------------------------------------*/             
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT 
  
  Error = CRYS_OK;
   
  /* ................. checking the validity of the pointer arguments ....... */
  
  /* ...... checking the key database handle pointer .................... */
  if( PubExp_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_EXPONENT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the exponent pointer ............... */
  if( UserPrivKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the modulus pointer .............. */
  if( UserPubKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the keygen data .................. */
  if( KeyGenData_ptr == DX_NULL )
  {
    Error = CRYS_RSA_KEY_GEN_DATA_STRUCT_POINTER_INVALID;
    goto end_function;
  }
      
  /* ...... checking the required key size ............................ */
  if( ( KeySize < CRYS_RSA_MIN_VALID_KEY_SIZE_VALUE_IN_BITS ) ||
      ( KeySize > CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS ) ||
      ( KeySize % CRYS_RSA_VALID_KEY_SIZE_MULTIPLE_VALUE_IN_BITS ) )
  {
    Error = CRYS_RSA_INVALID_MODULUS_SIZE;
    goto end_function;
  }
  
   /* lock access to the SEP */
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function;
   }
  
  /*----------------------------
      start sending message to SEP 
  -----------------------------*/
  sramOffset = 0;
   
  /* start the message */
  SEPDriver_StartMessage(&sramOffset);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCOL_HOST_RSA_KG_OP_CODE;
  messageParam[1] = 0;
  messageParam[2] = KeySize;
  messageParam[3] = PubExpSizeInBytes;
  
  /* 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 exponent */
  Error = SEPDriver_WriteParamater((DxUint32_t)PubExp_ptr ,
                            PubExpSizeInBytes, 
                            64 * 4 , 
                            &sramOffset , 
                            DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  SEPDriver_EndMessage(sramOffset);
            
  /* wait for the response */
  Error = SEPDriver_POLL_FOR_REPONSE();
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }
   
  /*-------------------
    start reading message from the SEP 
  ---------------------*/
   
  /* start the message */
  Error = SEPDriver_StartIncomingMessage(&sramOffset);
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }
   
  /* read opcode + status */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t) * 2,
                          sizeof(DxUint32_t) * 2,
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  /* check the opcode */
  if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCOL_HOST_RSA_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_RSAUserPrivKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)UserPrivKey_ptr,
                           sizeof(CRYS_RSAUserPrivKey_t),
                           maxLength,
                           &sramOffset,
                           DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                              
  /* read public key */
  maxLength = ((sizeof(CRYS_RSAUserPubKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)UserPubKey_ptr,
                           sizeof(CRYS_RSAUserPubKey_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_PKI_SUPPORT */                                     

}/* END OF CRYS_RSA_KG_GenerateKeyPairCRT */
