  /*
   *  Object %CRYS_RSA_BUILD.c    : %
   *  State           :  %state%
   *  Creation date   :  Wed Nov 17 17:25:55 2004
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief this module contains the routines used to create the public and private keys
   *         database and routines to check the validity of the private and public keys database. 
   *
   *  \version CRYS_RSA_BUILD.c#1:csrc:6
   *  \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_RSA_error.h"
#include "CRYS_RSA_BUILD.h"
#include "error.h"
#include "crys_host_op_code.h"
#include "SEPDriver.h"

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

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


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


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


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

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

/******************************************************************************************
   @brief CRYS_RSA_Build_PubKey populates a CRYSRSAPubKey_t structure with
   the provided modulus and exponent.
   
   assumption : the modulus and the exponent are presented in big endian.
   
   @param[out] PubKey_ptr - a pointer to the public key structure. This structure will be used as
                           an input to the CRYS_RSA_PRIM_Encrypt API.
 
   @param[in] Exponent_ptr - a pointer to the exponent stream of bytes ( Big endian ).
   @param[in] ExponentSize - The size of the exponent in bytes.  
   @param[in] Modulus_ptr  - a pointer to the modulus stream of bytes ( Big endian ) the MS bit must be set to '1'.
   @param[in] ModulusSize  - The size of the modulus in bytes. Size supported are:   
							   - for PKI without PKA: HW: all 32 bytes multiples between 64 - 256;
							   - for PKI with PKA: HW all 4 bytes multiples between 64 - 264;
*/
CEXPORT_C CRYSError_t CRYS_RSA_Build_PubKey(  CRYS_RSAUserPubKey_t*   UserPubKey_ptr,
                  				                    DxUint8_t*              Exponent_ptr,
                  				                    DxUint16_t              ExponentSize,
                  				                    DxUint8_t*              Modulus_ptr,
                  				                    DxUint16_t              ModulusSize )
{
  /* the Error return code identifier */
  CRYSError_t   Error = CRYS_OK; 
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[3];
  
  /* max length */
  DxUint32_t    maxLength;

  /*-------------------------------------
      CODE
  -------------------------------------*/
                 
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
   
  /* ................. checking the validity of the pointer arguments ....... */
   
  /* ...... checking the key database handle pointer .................... */
  if( UserPubKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the exponent pointer ............... */
  if( Exponent_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_EXPONENT_POINTER_ERROR;
    goto end_function;
  }
   
  /* ...... checking the validity of the modulus pointer .............. */
  if( Modulus_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_MODULUS_POINTER_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_RSA_BUILD_PUB_KEY_OP_CODE;
  messageParam[1] = ExponentSize;
  messageParam[2] = ModulusSize;
  
  /* 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 exponent */
  Error = SEPDriver_WriteParamater((DxUint32_t)Exponent_ptr ,
                            ExponentSize, 
                            64 * 4 , 
                            &sramOffset , 
                            DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[2] , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
    
  /* send modulus */
  Error = SEPDriver_WriteParamater((DxUint32_t)Modulus_ptr ,
                            ModulusSize, 
                            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_BUILD_PUB_KEY_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 private 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_Build_PubKey */

/******************************************************************************************
   @brief CRYS_RSA_Build_PrivKey populates a CRYSRSAPrivKey_t structure with
          the provided modulus and exponent, marking the key as a "non-CRT" key.

          Assumption : the modulus and the exponent are presented in big endian.
 
   @param[out] UserPrivKey_ptr - a pointer to the public key structure. this structure will be used as
                           an input to the CRYS_RSA_PRIM_Decrypt API.
 
   @param[in] PrivExponent_ptr - a pointer to the private exponent stream of bytes ( Big endian ).
   @param[in] PrivExponentSize - The size of the private exponent in bytes.
   @param[in] PubExponent_ptr - a pointer to the public exponent stream of bytes ( Big endian ).
   @param[in] PubExponentSize - The size of the public exponent in bytes.    
   @param[in] Modulus_ptr  - a pointer to the modulus stream of bytes ( Little endian ) the MS bit must be set to '1'.
   @param[in] ModulusSize  - The size of the modulus in bytes. Sizes supported are:   
								   - for PKI without PKA: HW: all 32 bytes multiples between 64 - 256;
								   - for PKI with PKA: HW all 4 bytes multiples between 64 - 264;
*/
CEXPORT_C CRYSError_t CRYS_RSA_Build_PrivKey(CRYS_RSAUserPrivKey_t*   UserPrivKey_ptr,
                  				                   DxUint8_t*               PrivExponent_ptr,
                  				                   DxUint16_t               PrivExponentSize,
                  				                   DxUint8_t*               PubExponent_ptr,
                  				                   DxUint16_t               PubExponentSize,
                  				                   DxUint8_t*               Modulus_ptr,
                  				                   DxUint16_t               ModulusSize )
{				                   
  /* the Error return code identifier */
  CRYSError_t   Error = CRYS_OK; 
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[5];
  
  /* max length */
  DxUint32_t    maxLength;

  /*--------------------------------------------
      CODE
  ---------------------------------------------*/              
 
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
 
  /* ................. checking the validity of the pointer arguments ....... */
   
  /* ...... checking the key database handle pointer .................... */
  if( UserPrivKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the exponent pointer ............... */
  if( PrivExponent_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_EXPONENT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the modulus pointer .............. */
  if( Modulus_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_MODULUS_POINTER_ERROR;
    goto end_function;
  }

  /* ...... checking the validity of the modulus size, private exponent can not be more than 256 bytes .............. */
  if( PrivExponentSize > (CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS /8 ))
  {
		Error = CRYS_RSA_INVALID_EXPONENT_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_BUILD_PRIV_KEY_OP_CODE;
  messageParam[1] = 1; /* NO CRT */
  messageParam[2] = PrivExponentSize;
  messageParam[3] = PubExponentSize;
  messageParam[4] = ModulusSize;
   
  /* 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 priv exponent */
  Error = SEPDriver_WriteParamater((DxUint32_t)PrivExponent_ptr , 
                                       PrivExponentSize , 
                                       64 * 4,
                                       &sramOffset , 
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send params */
  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 pub exponent */
  Error = SEPDriver_WriteParamater((DxUint32_t)PubExponent_ptr , 
                                       PubExponentSize ,
                                       64 * 4, 
                                       &sramOffset , 
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[4] , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
    
  /* send modulus */
  Error = SEPDriver_WriteParamater((DxUint32_t)Modulus_ptr , 
                                       ModulusSize,
                                       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_BUILD_PRIV_KEY_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 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;
  }
                                      
  /* ...................... 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_Build_PrivKey */



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

   @brief CRYS_RSA_Build_PrivKeyCRT populates a CRYSRSAPrivKey_t structure with
          the provided parameters, marking the key as a "CRT" key.

   @param[out] UserPrivKey_ptr - A pointer to the public key structure. 
                            This structure is used as input to the CRYS_RSA_PRIM_Decrypt API.
 
   @param[in] P_ptr - A pointer to the first factor stream of bytes (Big-Endian format)
   @param[in] PSize - The size of the first factor, in bytes.
   @param[in] Q_ptr - A pointer to the second factor stream of bytes (Big-Endian format)
   @param[in] QSize - The size of the second factor, in bytes.
   @param[in] dP_ptr - A pointer to the first factor's CRT exponent stream of bytes (Big-Endian format)
   @param[in] dPSize - The size of the first factor's CRT exponent, in bytes.
   @param[in] dQ_ptr - A pointer to the second factor's CRT exponent stream of bytes (Big-Endian format)
   @param[in] dQSize - The size of the second factor's CRT exponent, in bytes.
   @param[in] qInv_ptr - A pointer to the first CRT coefficient stream of bytes (Big-Endian format)
   @param[in] qInvSize - The size of the first CRT coefficient, in bytes.

*/

CEXPORT_C CRYSError_t CRYS_RSA_Build_PrivKeyCRT(CRYS_RSAUserPrivKey_t*  UserPrivKey_ptr,
                  				                      DxUint8_t*              P_ptr, 
                  				                      DxUint16_t              PSize,
                  				                      DxUint8_t*              Q_ptr,
                  				                      DxUint16_t              QSize,
                  				                      DxUint8_t*              dP_ptr, 
                  				                      DxUint16_t              dPSize,
                  				                      DxUint8_t*              dQ_ptr,
                  				                      DxUint16_t              dQSize,
                  				                      DxUint8_t*              qInv_ptr,
                  				                      DxUint16_t              qInvSize)
{				                   
  /* the Error return code identifier */
  CRYSError_t   Error = CRYS_OK; 
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[7];
  
  /* max length */
  DxUint32_t    maxLength;
  
  /*----------------------------------------
      CODE
  -----------------------------------------*/
             
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      

  /* ................. checking the validity of the pointer arguments ....... */
   
  /* ...... checking the key database handle pointer .................... */
  if( UserPrivKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
   
  /* checking the first factor pointer validity */
  if( P_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_FIRST_FACTOR_POINTER_ERROR;
    goto end_function;
  }
  
  /* checking the second factor pointer validity */
  if( Q_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_SECOND_FACTOR_POINTER_ERROR;
    goto end_function;
  }
   
  /* checking the first factor exponenet pointer validity */
  if( dP_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_FIRST_FACTOR_EXP_PTR_ERROR;
    goto end_function;
  }
   
  /* checking the second factor exponent pointer validity */
  if( dQ_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_SECOND_FACTOR_EXP_PTR_ERROR;
    goto end_function;
  }
 
  /* checking the CRT coefficient */
  if( qInv_ptr == DX_NULL ) 
  {
    Error = CRYS_RSA_INVALID_CRT_COEFFICIENT_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_RSA_BUILD_PRIV_KEY_OP_CODE;
  messageParam[1] = 0; /* CRT */
  messageParam[2] = PSize;
  messageParam[3] = QSize;
  messageParam[4] = dPSize;
  messageParam[5] = dQSize;
  messageParam[6] = qInvSize;
  
  /* 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 p */
  Error = SEPDriver_WriteParamater((DxUint32_t)P_ptr , 
                                       PSize,
                                       64 * 4 , 
                                       &sramOffset , 
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send params */
  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 q */
  Error = SEPDriver_WriteParamater((DxUint32_t)Q_ptr , 
                                       QSize,
                                       64 * 4 , 
                                       &sramOffset , 
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[4] , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
    
  /* send dp */
  Error = SEPDriver_WriteParamater((DxUint32_t)dP_ptr , 
                                       dPSize,
                                       64 * 4 , 
                                       &sramOffset , 
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[5] , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
    
  /* send dq */
  Error = SEPDriver_WriteParamater((DxUint32_t)dQ_ptr , 
                                       dQSize,
                                       64 * 4 , 
                                       &sramOffset , 
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)&messageParam[6] , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
    
  /* send inv */
  Error = SEPDriver_WriteParamater((DxUint32_t)qInv_ptr , 
                                       qInvSize,
                                       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_BUILD_PRIV_KEY_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 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;
  }
                                      
  /* ...................... 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_Build_PrivKeyCRT */

/******************************************************************************************
   @brief CRYS_RSA_Get_PubKey gets the e,n public key from the database.
   
   @param[in] UserPubKey_ptr - A pointer to the public key structure. 
                               This structure is used as input to the CRYS_RSA_PRIM_Encrypt API.
 
   @param[out] Exponent_ptr - A pointer to the exponent stream of bytes (Big-Endian format)
   @param[in,out] ExponentSize_ptr - the size of the exponent buffer in bytes, it is updated to the 
                  actual size of the exponent, in bytes.  
   @param[out] Modulus_ptr  - A pointer to the modulus stream of bytes (Big-Endian format).
			   The MS (most significant) bit must be set to '1'.
   @param[in,out] ModulusSize_ptr  - the size of the modulus buffer in bytes, it is updated to the 
                  actual size of the modulus, in bytes.

   NOTE: All members of input UserPrivKey structure must be initialized, including public key
         e pointer and it size.

*/
CEXPORT_C CRYSError_t CRYS_RSA_Get_PubKey(  CRYS_RSAUserPubKey_t*   UserPubKey_ptr,
                  				                  DxUint8_t*              Exponent_ptr,
                  				                  DxUint16_t*             ExponentSize_ptr,
                  				                  DxUint8_t*              Modulus_ptr,
                  				                  DxUint16_t*             ModulusSize_ptr )
{
  /* error */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[2];
  
  /* max length */
  DxUint32_t    maxLength;	
   
  #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( UserPubKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the exponent pointer ............... */
  if( Exponent_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_EXPONENT_POINTER_ERROR;
    goto end_function;
  }
   
  /* ...... checking the validity of the modulus pointer .............. */
  if( Modulus_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_MODULUS_POINTER_ERROR;
    goto end_function;
  }
  
  if( ExponentSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_EXP_BUFFER_SIZE_POINTER;
    goto end_function;
  }

  if( ModulusSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_MOD_BUFFER_SIZE_POINTER;
    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_GET_PUB_KEY_OP_CODE;
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
    
  /* send public key  */
  maxLength = ((sizeof(CRYS_RSAUserPubKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserPubKey_ptr , 
                                       sizeof(CRYS_RSAUserPubKey_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_RSA_GET_PUB_KEY_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 public exponent size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE); 
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  /* if the size of the exponent is too small return error */
  if ((DxUint16_t)messageParam[0] > *ExponentSize_ptr)
  {
    Error = CRYS_RSA_INVALID_EXPONENT_SIZE;
    goto end_function_unlock;
  }
  
  *ExponentSize_ptr =  (DxUint16_t)messageParam[0];
                                            
  /* read pub exponent */
  Error = SEPDriver_ReadParamater((DxUint32_t)Exponent_ptr,
                                      *ExponentSize_ptr,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE); 
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* read modulus size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE); 
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  /* if the size of the modulus is to small return error */
  if ((DxUint16_t)messageParam[0] > *ModulusSize_ptr)
  {
    Error = CRYS_RSA_INVALID_MODULUS_SIZE;
    goto end_function_unlock;
  }
  
  *ModulusSize_ptr = (DxUint16_t)messageParam[0];                                            
  
  /* read modulus  */
  Error = SEPDriver_ReadParamater((DxUint32_t)Modulus_ptr,
                                      *ModulusSize_ptr,
                                      64 * 4,
                                      &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_Get_PubKey */   

/******************************************************************************************
   @brief CRYS_RSA_Get_ModSizeFromPubKey extracts the modulus size from a given public key data structure.
   
   @param[in] UserPubKey_ptr - A pointer to the public key structure, as returned by
                               CRYS_RSA_Build_PubKey.
 
   @param[out] ModulusSize_ptr  -  The actual size of the modulus, in bytes.  
*/
CEXPORT_C CRYSError_t CRYS_RSA_Get_ModSizeFromPubKey(CRYS_RSAUserPubKey_t*    UserPubKey_ptr,
				                                             DxUint16_t*              ModulusSize_ptr )
{	
  /* error */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[2];
  
  /* 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( UserPubKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
  
  /* checking the modolous size output pointer validity */
  if( ModulusSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_MOD_BUFFER_SIZE_POINTER;
    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_MOD_SIZE_OP_CODE;
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
    
  /* send context */
  maxLength = ((sizeof(CRYS_RSAUserPubKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserPubKey_ptr , 
                                       sizeof(CRYS_RSAUserPubKey_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_RSA_MOD_SIZE_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 modulus size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);  
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  *ModulusSize_ptr = (DxUint16_t)messageParam[0];                                       
                                      
  /* ...................... 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_Get_ModSizeFromPubKey */   

/******************************************************************************************
   @brief CRYS_RSA_Get_PrivKey gets the D,e,n of private key from the database.
   
   @param[in] UserPrivKey_ptr - A pointer to the private key structure. 
                               This structure is used as input to the CRYS_RSA_PRIM_Decrypt API.
 
   @param[out] PrivExponent_ptr - A pointer to the exponent stream of bytes (Big-Endian format)

   @param[in/out] PrivExponentSize - the size of the exponent buffer in bytes , it is updated to the 
                  actual size of the exponent, in bytes.  

   @param[out] PubExponent_ptr - a pointer to the public exponent stream of bytes ( Big endian ).
   
   @param[in/out] PubExponentSize - the size of the exponent buffer in bytes , it is updated to the 
                  actual size of the exponent, in bytes.    
   
   @param[out] Modulus_ptr  - A pointer to the modulus stream of bytes (Big-Endian format).
			   The MS (most significant) bit must be set to '1'.

   @param[in/out] ModulusSize_ptr  - the size of the modulus buffer in bytes , it is updated to the 
                  actual size of the modulus, in bytes.  
*/
CEXPORT_C CRYSError_t CRYS_RSA_Get_PrivKey(CRYS_RSAUserPrivKey_t*   UserPrivKey_ptr,
                				                   DxUint8_t*               PrivExponent_ptr,
                				                   DxUint16_t*              PrivExponentSize_ptr,
                				                   DxUint8_t*               PubExponent_ptr,
                				                   DxUint16_t*              PubExponentSize_ptr,
                				                   DxUint8_t*               Modulus_ptr,
                				                   DxUint16_t*              ModulusSize_ptr )
{	
  /* error */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[2];
  
  /* 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( UserPrivKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the private exponent pointer ............... */
  if( PrivExponent_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_EXPONENT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the public exponent pointer ............... */
  if( PubExponent_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_EXPONENT_POINTER_ERROR;
    goto end_function;
  }
        
  /* ...... checking the validity of the modulus pointer .............. */
  if( Modulus_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_MODULUS_POINTER_ERROR;
    goto end_function;
  }

  if( PrivExponentSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_EXP_BUFFER_SIZE_POINTER;
    goto end_function;
  }

  if( PubExponentSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_EXP_BUFFER_SIZE_POINTER;
    goto end_function;
  }

  if( ModulusSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_MOD_BUFFER_SIZE_POINTER;
    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_GET_PRIV_KEY_OP_CODE;
  messageParam[1] = 1;
  
  /* 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_RSAUserPrivKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserPrivKey_ptr , 
                                       sizeof(CRYS_RSAUserPrivKey_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_RSA_GET_PRIV_KEY_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 private size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  if (*PrivExponentSize_ptr < (DxUint16_t)messageParam[0])
  {
    Error = CRYS_RSA_INVALID_EXPONENT_SIZE;
    goto end_function_unlock;        
  }
  
  *PrivExponentSize_ptr = (DxUint16_t)messageParam[0]; 
                        
  /* read private exponent */
  Error = SEPDriver_ReadParamater((DxUint32_t)PrivExponent_ptr,
                                      *PrivExponentSize_ptr,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE); 
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                           
  /* read public size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  if (*PubExponentSize_ptr < (DxUint16_t)messageParam[0])
  {
    Error = CRYS_RSA_INVALID_EXPONENT_SIZE;
    goto end_function_unlock;        
  }
  
  *PubExponentSize_ptr = (DxUint16_t)messageParam[0];
  
  /* read public */
  Error = SEPDriver_ReadParamater((DxUint32_t)PubExponent_ptr,
                                      *PubExponentSize_ptr,
                                      64 * 4,
                                      &sramOffset,
                                       DX_TRUE); 
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                              
  
  /* read modulus size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  if (*ModulusSize_ptr < (DxUint16_t)messageParam[0])
  {
    Error = CRYS_RSA_INVALID_MODULUS_SIZE;
    goto end_function_unlock;        
  }
  
  *ModulusSize_ptr = (DxUint16_t)messageParam[0];
  
  /* read modulus */
  Error = SEPDriver_ReadParamater((DxUint32_t)Modulus_ptr,
                                      *ModulusSize_ptr,
                                      64 * 4,
                                      &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_Get_PrivKey */   

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

   @brief CRYS_RSA_Get_PrivKeyCRT exports a CRYSRSAPrivKey_t structure data

   @param[In] UserPrivKey_ptr - a pointer to the public key structure. this structure will be used as
                            an input to the CRYS_RSA_PRIM_Decrypt API.
 
   @param[out] P_ptr - a pointer to the first factor stream of bytes ( Big endian ).
   @param[in/out] PSize_ptr - the size of the first factor buffer in bytes , it is updated to the 
                  actual size of the first factor, in bytes.
   @param[out] Q_ptr - a pointer to the second factor stream of bytes ( Big endian ).
   @param[in/out] QSize_ptr - the size of the second factor buffer in bytes , it is updated to the 
                  actual size of the second factor, in bytes.
   @param[out] dP_ptr - a pointer to the first factors CRT exponent stream of bytes ( Big endian ).
   @param[in/out] dPSize_ptr - the size of the first factor exponent buffer in bytes , it is updated to the 
                  actual size of the first factor exponent, in bytes.
   @param[out] dQ_ptr - a pointer to the second factors CRT exponent stream of bytes ( Big endian ).
   @param[in/out] dQSize_ptr - the size of the second factors CRT exponent buffer in bytes , it is updated to the 
                  actual size of the second factors CRT exponent, in bytes.
   @param[out] qInv_ptr - a pointer to the first CRT coefficient stream of bytes ( Big endian ).
   @param[in/out] qInvSize_ptr -  the size of the first CRT coefficient buffer in bytes , it is updated to the 
                  actual size of the first CRT coefficient, in bytes.
*/

CEXPORT_C CRYSError_t CRYS_RSA_Get_PrivKeyCRT(CRYS_RSAUserPrivKey_t*    UserPrivKey_ptr,
                				                      DxUint8_t*                P_ptr, 
                				                      DxUint16_t*               PSize_ptr,
                				                      DxUint8_t*                Q_ptr,
                				                      DxUint16_t*               QSize_ptr,
                				                      DxUint8_t*                dP_ptr, 
                				                      DxUint16_t*               dPSize_ptr,
                				                      DxUint8_t*                dQ_ptr,
                				                      DxUint16_t*               dQSize_ptr,
                				                      DxUint8_t*                qInv_ptr,
                				                      DxUint16_t*               qInvSize_ptr)
{				                   
  /* error */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[2];
  
  /* max length */
  DxUint32_t    maxLength;
  
  /*---------------------------------------
      CODE
  -----------------------------------------*/
  
  Error = CRYS_OK;
  
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
 
   /* ................. checking the validity of the pointer arguments ....... */
   /* ------------------------------------------------------------------------ */
   
  /* ...... checking the key database handle pointer .................... */
  if( UserPrivKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* checking the first factor pointer validity */
  if( P_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_FIRST_FACTOR_POINTER_ERROR;
    goto end_function;
  }

  /* checking the first factor size pointer validity */
  if( PSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_FIRST_FACTOR_SIZE_POINTER_ERROR;
    goto end_function;
  }
  
  /* checking the second factor pointer validity */
  if( Q_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_SECOND_FACTOR_POINTER_ERROR;
    goto end_function;
  }
   
  /* checking the second factor size pointer validity */
  if( QSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_SECOND_FACTOR_SIZE_POINTER_ERROR;
    goto end_function;
  }
  
  /* checking the first factor exponenet pointer validity */
  if( dP_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_FIRST_FACTOR_EXP_PTR_ERROR;
    goto end_function;
  }
 
  /* checking the first factor exponenet size pointer validity */
  if( dPSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_FIRST_FACTOR_EXP_SIZE_PTR_ERROR;
    goto end_function;
  }

  /* checking the second factor exponent pointer validity */
  if( dQ_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_SECOND_FACTOR_EXP_PTR_ERROR;
    goto end_function;
  }
   
  /* checking the second factor exponent size pointer validity */
  if( dQSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_SECOND_FACTOR_EXP_SIZE_PTR_ERROR;
    goto end_function;
  }
      
  /* checking the CRT coefficient */
  if( qInv_ptr == DX_NULL )  
  {
    Error = CRYS_RSA_INVALID_CRT_COEFFICIENT_PTR_ERROR;
    goto end_function;
  }
 
  /* checking the CRT coefficient */
  if( qInvSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_CRT_COEFFICIENT_SIZE_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_RSA_GET_PRIV_KEY_OP_CODE;
  messageParam[1] = 0;
   
  /* 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_RSAUserPrivKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserPrivKey_ptr , 
                                       sizeof(CRYS_RSAUserPrivKey_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_RSA_GET_PRIV_KEY_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 p size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  *PSize_ptr =  (DxUint16_t)messageParam[0];
                         
  /* read p */
  Error = SEPDriver_ReadParamater((DxUint32_t)P_ptr,
                                      *PSize_ptr,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE); 
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                           
  /* read q size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  *QSize_ptr =  (DxUint16_t)messageParam[0];
  
  /* read q */
  Error = SEPDriver_ReadParamater((DxUint32_t)Q_ptr,
                                      *QSize_ptr,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                           
  /* read dP size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  *dPSize_ptr =  (DxUint16_t)messageParam[0];
  
  /* read dP */
  Error = SEPDriver_ReadParamater((DxUint32_t)dP_ptr,
                                      *dPSize_ptr,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE);  
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* read dq size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  *dQSize_ptr =  (DxUint16_t)messageParam[0];
  
  /* read dq */
  Error = SEPDriver_ReadParamater((DxUint32_t)dQ_ptr,
                                      *dQSize_ptr,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                           
  /* read dInv size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  *qInvSize_ptr =  (DxUint16_t)messageParam[0];
  
  /* read dInv */
  Error = SEPDriver_ReadParamater((DxUint32_t)qInv_ptr,
                                      *qInvSize_ptr,
                                      64 * 4,
                                      &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_Get_PrivKeyCRT */   

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

   @brief CRYS_RSA_Get_PrivKeyModulus export the modulus vector from CRYSRSAPrivKey_t structure.

   @param[out] UserPrivKey_ptr - a pointer to the private key structure. 
 
   @param[out] N_ptr - a pointer to the modulus vector of bytes ( Big endian ).
   @param[in/out] NSize_ptr - the size of the modulus buffer in bytes , it is updated to the 
                  actual size in bytes.
*/

CEXPORT_C CRYSError_t CRYS_RSA_Get_PrivKeyModulus(CRYS_RSAUserPrivKey_t *UserPrivKey_ptr,
				                      			  DxUint8_t *N_ptr, 
				                     	 		  DxUint16_t *NSize_ptr)
{
  /* error */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[2];
  
  /* max length */
  DxUint32_t    maxLength;	
   
  #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( UserPrivKey_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
    goto end_function;
  }
      
  /* ...... checking the validity of the exponent pointer ............... */
   
  /* ...... checking the validity of the modulus pointer .............. */
  if( NSize_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_MODULUS_POINTER_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_RSA_GET_PRIV_KEY_MODULUS_OP_CODE;
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam , 
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
    
  /* send public key  */
  maxLength = ((sizeof(CRYS_RSAUserPrivKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserPrivKey_ptr , 
                                       sizeof(CRYS_RSAUserPrivKey_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_RSA_GET_PRIV_KEY_MODULUS_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 public exponent size */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam , 
                          sizeof(DxUint32_t),
                          sizeof(DxUint32_t),
                          &sramOffset , 
                          DX_FALSE); 
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                          
  *NSize_ptr =  (DxUint16_t)messageParam[0];
                                            
  /* read pub exponent */
  Error = SEPDriver_ReadParamater((DxUint32_t)N_ptr,
                                      *NSize_ptr,
                                      64 * 4,
                                      &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 */                                     
 
	
}
