  /*
   *  Object %CRYS_RSA_PRIME.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 ****************/

#include "DX_VOS_Mem.h"
#include "CRYS_RSA_error.h"
#include "CRYS_RSA_PRIM.h"
#include "error.h"
#include "crys_host_op_code.h"
#include "SEPDriver.h"

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

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


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


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

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

/**
@brief
CRYS_RSA_PRIM_Encrypt implements the RSAEP algorithm as defined in PKCS#1 v2.1 6.1.1

  @param[in] UserPubKey_ptr - Pointer to the public key data structure.
  @param[in] PrimeData_ptr - a pointer to a structure containing internal buffers
  @param[in] Data_ptr - Pointer to the data to encrypt.
  @param[in] DataSize - The size, in bytes, of the data to
                        encrypt. \note Must be <= the size of the
                        modulus.
  @param[out] Output_ptr - Pointer to the encrypted data, the buffer
                           must be at least PubKey_ptr->N.len bytes
                           long (that is, the size of the modulus, in
                           bytes).

  @return CRYSError_t - CRYS_OK,
                        CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR,
                        CRYS_RSA_PUB_KEY_VALIDATION_TAG_ERROR,
                        CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID,
                        CRYS_RSA_DATA_POINTER_INVALID_ERROR,
                        CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR,
                        CRYS_RSA_INVALID_MESSAGE_BUFFER_SIZE,
                        CRYS_RSA_INVALID_MESSAGE_DATA_SIZE,
                        CRYS_RSA_INVALID_MESSAGE_VAL
 */
CEXPORT_C CRYSError_t CRYS_RSA_PRIM_Encrypt(CRYS_RSAUserPubKey_t*   UserPubKey_ptr,
                                            CRYS_RSAPrimeData_t*    PrimeData_ptr,
                                            DxUint8_t*              Data_ptr,
                                            DxUint16_t              DataSize,
                                            DxUint8_t*              Output_ptr)
{
  /* The return error identifier */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[2];
  
  /* maximum parameter length */
  DxUint32_t    maxLength;
  
  /*---------------------------------------
      CODE
  ----------------------------------------*/
       
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
 
  Error = CRYS_OK;
   
   
  /* 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 Prime Data pointer */
  if( PrimeData_ptr == DX_NULL )
  {
    Error = CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID;
    goto end_function;
  }

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

  /* if the users output pointer is illegal return an error */
  if( Output_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR;
    goto end_function;
  }
   
      
  /* if the data size is larger then the internal buffer return error */
  if( DataSize > sizeof(PrimeData_ptr->DataIn) )
  {
    Error = CRYS_RSA_INVALID_PUB_KEY_STRUCT_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_PRIM_ENC_OP_CODE;
  messageParam[1] = DataSize;
  
  /* 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;
  }
  
  /* write data in */
  Error = SEPDriver_WriteParamater((DxUint32_t)Data_ptr,
                                       DataSize,
                                       64 * 4,
                                       &sramOffset,
                                       DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* write 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_PRIM_ENC_OP_CODE)
  {
    Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
    goto end_function_unlock;
  }
   
  /* read the status */
  if(messageParam[1] != CRYS_OK)
  {
    Error = messageParam[1];
    goto end_function_unlock;
  }
   
  /* read the data out  */
  Error = SEPDriver_ReadParamater((DxUint32_t)Output_ptr,
                                      64 * 4,
                                      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_PRIM_Encrypt */

/**
@brief
CRYS_RSA_PRIM_Decrypt implements the RSADP algorithm as defined in PKCS#1 v2.1 6.1.2

  @param[in] PrivKey_ptr - Pointer to the private key data
                           structure. \note The representation (pair
                           or quintiple) and hence the algorithm (CRT
                           or not) is determined by the Private Key
                           data structure. Using CRYS_Build_PrivKey or
                           CRYS_Build_PrivKeyCRT determines which
                           algorithm will be used.
                           
  @param[in] PrimeData_ptr - a pointer to a structure containing internal buffers
                             required for the RSA operation.                           
  @param[in] Data_ptr - Pointer to the data to be decrypted.
  @param[in] DataSize - The size, in bytes, of the data to
                        decrypt. \note Must be <= the size of the
                        modulus. 

  @param[out] Output_ptr - Pointer to the decrypted data, the buffer
                           must be at least PrivKey_ptr->N.len bytes
                           long (that is, the size of the modulus, in bytes).

  @return CRYSError_t - CRYS_OK,
                        CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR,
                        CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID,
                        CRYS_RSA_PRIV_KEY_VALIDATION_TAG_ERROR,
                        CRYS_RSA_DATA_POINTER_INVALID_ERROR,
                        CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR,
                        CRYS_RSA_INVALID_MESSAGE_DATA_SIZE,
                        CRYS_RSA_INVALID_MESSAGE_VAL
 */

CEXPORT_C CRYSError_t CRYS_RSA_PRIM_Decrypt(CRYS_RSAUserPrivKey_t*  UserPrivKey_ptr,
                                            CRYS_RSAPrimeData_t*    PrimeData_ptr,
                                            DxUint8_t*              Data_ptr,
                                            DxUint16_t              DataSize,
                                            DxUint8_t*              Output_ptr)
{				  
  /* The return error identifier */
  CRYSError_t   Error;
  
  /* offset */
  DxUint32_t    sramOffset;
  
  /* read parameter */
  DxUint32_t    messageParam[2];
  
  /* maximum parameter length */
  DxUint32_t    maxLength;
  
  /*-------------------------------------------
      CODE
  --------------------------------------------*/
                  
  #ifndef CRYS_NO_HASH_SUPPORT                                      
  #ifndef CRYS_NO_PKI_SUPPORT                                      
  
  Error = CRYS_OK;

  /* ............... checking the parameters pointers validity .......... */

  /* ...... 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 Prime Data pointer .................... */
  if( PrimeData_ptr == DX_NULL )
  {
    Error = CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID;
    goto end_function;
  }
   
  /* if the users Data pointer is DX_NULL return an error */
  if( Data_ptr == DX_NULL )
  {
    Error = CRYS_RSA_DATA_POINTER_INVALID_ERROR;
    goto end_function;
  }
   
  /* if the users Output pointer is DX_NULL return an error */
  if( Output_ptr == DX_NULL )
  {
    Error = CRYS_RSA_INVALID_OUTPUT_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_PRIM_DEC_OP_CODE;
  messageParam[1] = DataSize;
  
  /* 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;
  }
  
  /* write data in */
  Error = SEPDriver_WriteParamater((DxUint32_t)Data_ptr,
                                      DataSize,
                                      64 * 4,
                                      &sramOffset,
                                      DX_TRUE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* write 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_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_PRIM_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;
  }
   
  /* read the data out  */
  Error = SEPDriver_ReadParamater((DxUint32_t)Output_ptr,
                                      DataSize,
                                      64 * 4,
                                      &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_HASH_SUPPORT */
  #endif /* !CRYS_NO_PKI_SUPPORT */                                     
  							       
}/* END OF CRYS_RSA_PRIM_Decrypt */
