/*
* Creation date : Wed Mar 07 12:57:17 2007
* Last modified : %modify_time%
*/
/** @file
* \brief This file contains implementation of 
* LLF_RSA_KG functions.
*
* \version LLF_RSA_KG.c#1:csrc:1
* \author Pavel Sasunkevich
* \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
* All Rights reserved
*/

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

#include "LLF_RSA_KG.h"
#include "LLF_RSA_Common.h"
#include "LLF_ECPKI_Common.h"

/************************ Defines *****************************/
/************************ Enums *******************************/
/************************ Typedefs ****************************/
/************************ Global Data *************************/
/************************ Private function prototype **********/
/************************ Private Functions *******************/
/************************ Public Functions ********************/

/**
****************************************************************
* Function Name: 
*  LLF_RSA_KG_GenerateKeyPairInMode
*
* Inputs:
*  @param PubExp_ptr [in] - The pointer to the public exponent (public key);
*  @param PubExpSizeInBytes [in] - The public exponent size in bits;
*  @param KeySize [in] - The size of the key, in bits.
*  @param UserPrivKey_ptr [out] - A pointer to the private key structure;
*  @param UserPubKey_ptr  [out] - A pointer to the public key structure.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code:
*     - CE2_RSA_INVALID_EXPONENT_POINTER_ERROR,
*     - CE2_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR,
*     - CE2_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR,
*     - CE2_RSA_INVALID_MODULUS_SIZE,
*     - CE2_RSA_INVALID_EXPONENT_SIZE.
*
* \brief \b
* Description:
*  LLF_RSA_KG_GenerateKeyPairInMode generates a Pair of public and
*  private keys on CRT mode.
*
* \b
* Algorithm:
*  -# Register and initialize prng and hash;
*  -# Generate RSA private and public keys using exponent and key
*     size;
*  -# Build public and private keys using previously generated 
*     RSA keys and using LLF_RSA_rsakey_TO_UserPubKey,
*     LLF_RSA_rsakey_TO_UserPrivKey.
***************************************************************/
CE2Error_t LLF_RSA_KG_GenerateKeyPairInMode(
                        DxUint8_t            *PubExp_ptr,		/* in */
                        DxUint16_t            PubExpSizeInBytes,/* in */
                        DxUint32_t            KeySize,			/* in */
                        CE2_RSAUserPrivKey_t *UserPrivKey_ptr,	/* out */
                        CE2_RSAUserPubKey_t  *UserPubKey_ptr,	/* out */
						            DxUint16_t mode)
{
  CE2Error_t  error, result = CE2_OK;
  DxUint32_t e = 0;
  prng_state prng;
  rsa_key key = {0};
  int wprng, error_code, i;

  ltc_mp = ltm_desc;

  /* Init prng 'Fortuna' */
  error = LLF_ECPKI_PRNG_Init(&prng, &wprng);
  if (error != CE2_OK) {
    result = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto error_case;
  }

  /* Convert public exponent from big-endian format */
  for (i = 0; i < PubExpSizeInBytes; ++i) {
    e |= PubExp_ptr[PubExpSizeInBytes - 1 - i] << (i*8);
  }

  /* Make KeySize bits RSA key */
  error_code = rsa_make_key(&prng, wprng, KeySize >> 3, e, &key);
  if (error_code != CRYPT_OK) {
    result = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto error_case;
  }

  /* Convert public RSA LibTomCrypt key to the internal format */
  error_code = LLF_RSA_rsakey_TO_UserPubKey(&key, UserPubKey_ptr);
  if (error_code != CRYPT_OK) {
    result = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto error_case;
  }

  /* Convert private RSA LibTomCrypt key to the internal format */
  error_code = LLF_RSA_rsakey_TO_UserPrivKey(&key, UserPrivKey_ptr, mode);
  if (error_code != CRYPT_OK) {
    result = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto error_case;
  }

error_case:
  fortuna_done(&prng);
  rsa_free(&key);
  return result;
} /* End of LLF_RSA_KG_GenerateKeyPairInMode */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_KG_GenerateKeyPair
*
* Inputs:
*  @param PubExp_ptr [in] - The pointer to the public exponent (public key);
*  @param PubExpSizeInBytes [in] - The public exponent size in bits;
*  @param KeySize [in] - The size of the key, in bits;
*  @param UserPrivKey_ptr [out] - A pointer to the private key structure;
*  @param UserPubKey_ptr  [out] - A pointer to the public key structure.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code:
*     - CE2_RSA_INVALID_EXPONENT_POINTER_ERROR,
*     - CE2_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR,
*     - CE2_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR,
*     - CE2_RSA_KEY_GEN_DATA_STRUCT_POINTER_INVALID,
*     - CE2_RSA_INVALID_MODULUS_SIZE,
*     - CE2_RSA_INVALID_EXPONENT_SIZE.
*
* \brief \b
* Description:
*  LLF_RSA_KG_GenerateKeyPair generates a Pair of public and
*  private keys on non CRT mode.
*
* \b
* Algorithm:
*  -# Register and initialize prng and hash;
*  -# Generate RSA private and public keys using exponent and key
*     size;
*  -# Build public and private keys using previously generated 
*     RSA keys and using LLF_RSA_rsakey_TO_UserPubKey,
*     LLF_RSA_rsakey_TO_UserPrivKey.
***************************************************************/
CE2Error_t LLF_RSA_KG_GenerateKeyPair(
                        DxUint8_t            *PubExp_ptr,		/* in */
                        DxUint16_t            PubExpSizeInBytes,/* in */
                        DxUint32_t            KeySize,			/* in */
                        CE2_RSAUserPrivKey_t *UserPrivKey_ptr,	/* out */
                        CE2_RSAUserPubKey_t  *UserPubKey_ptr)	/* out */
{
	return LLF_RSA_KG_GenerateKeyPairInMode(
		PubExp_ptr, PubExpSizeInBytes, KeySize,
		UserPrivKey_ptr, UserPubKey_ptr, CE2_RSA_PRIVATE_KEY_NON_CRT_MODE);
} /* End of LLF_RSA_KG_GenerateKeyPair */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_KG_GenerateKeyPairCRT
*
* Inputs:
*  @param PubExp_ptr [in] - The pointer to the public exponent (public key);
*  @param PubExpSizeInBytes [in] - The public exponent size in bits;
*  @param KeySize [in] - The size of the key, in bits;
*  @param UserPrivKey_ptr [out] - A pointer to the private key structure;
*  @param UserPubKey_ptr  [out] - A pointer to the public key structure.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_KG_GenerateKeyPairCRT generates a Pair of public and
*  private keys on CRT mode.
*
* \b
* Algorithm:
*  -# Register and initialize prng and hash;
*  -# Generate RSA private and public keys using exponent and key
*     size;
*  -# Build public and private keys using previously generated 
*     RSA keys and using LLF_RSA_rsakey_TO_UserPubKey,
*     LLF_RSA_rsakey_TO_UserPrivKey on CRT mode.
***************************************************************/
CE2Error_t LLF_RSA_KG_GenerateKeyPairCRT(
                        DxUint8_t            *PubExp_ptr,		/* in */
                        DxUint16_t            PubExpSizeInBytes,/* in */
                        DxUint32_t            KeySize,			/* in */
                        CE2_RSAUserPrivKey_t *UserPrivKey_ptr,	/* out */
                        CE2_RSAUserPubKey_t  *UserPubKey_ptr)	/* out */
{
	return LLF_RSA_KG_GenerateKeyPairInMode(
		PubExp_ptr, PubExpSizeInBytes, KeySize,
		UserPrivKey_ptr, UserPubKey_ptr, CE2_RSA_PRIVATE_KEY_CRT_MODE);
} /* End of LLF_RSA_KG_GenerateKeyPairCRT */


