/*
* Creation date : Mon Mar 05 15:42:59 2007
* Last modified : %modify_time%
*/
/** @file
* \brief This file contains implementation of 
* LLF_RSA_BUILD functions.
*
* \version LLF_RSA_BUILD.c#1:csrc:1
* \author Pavel Sasunkevich
* \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
* All Rights reserved
*/

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

#include "LLF_RSA_BUILD.h"
#include "LLF_RSA_Common.h"
#include "tommath.h"

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

/**
****************************************************************
* Function Name: 
*  LLF_RSA_Build_PubKey
*
* Inputs:
*  @param UserPubKey_ptr [in/out] - A pointer to the public key structure;
*  @param Exponent_ptr [in] - A pointer to the exponent stream of bytes;
*  @param ExponentSize [in] - The size of the exponent, in bytes;
*  @param Modulus_ptr  [in] - A pointer to the modulus stream of bytes;
*  @param ModulusSize  [in] - The size of the modulus, in bytes.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_Build_PubKey populates a CE2RSAPubKey_t structure with
*  the provided modulus and exponent.
*
* \b
* Algorithm:
*  -# Initialize rsa key values (e and N);
*  -# Convert public exponent (e) and modulus exponent (N)
*     from entire buffer to big number mp_int;
*  -# Extrude public exponent (e) and modulus exponent (N)
	  from big numbers to output public key buffer.
***************************************************************/
CE2Error_t LLF_RSA_Build_PubKey(CE2_RSAUserPubKey_t *UserPubKey_ptr, /* out */
                                DxUint8_t *Exponent_ptr,	/* in */
                                DxUint16_t ExponentSize,	/* in */
                                DxUint8_t *Modulus_ptr,		/* in */
                                DxUint16_t ModulusSize )	/* in */
{
	CE2RSAPubKey_t * pubKey = (CE2RSAPubKey_t *)UserPubKey_ptr->PublicKeyDbBuff;
	int error_code = CE2_OK;

	void * e = 0;	// big number for Exponent_ptr
	void * N = 0;	// big number for Modulus_ptr

	/* Reset output key. */
	memset(UserPubKey_ptr, 0, sizeof(CE2_RSAUserPubKey_t));
	UserPubKey_ptr->valid_tag = sizeof(CE2_RSAUserPubKey_t);

	/* Initialize to use math descriptor. */
	ltc_mp = ltm_desc;

	/* Initialize rsa key values: public exponent (e), modulus exponent (N). */
	ltc_init_multi(&e, &N, 0);

	/* Convert public exponent (e) and modulus exponent (N)
	from entire buffer to big number mp_int: */

	/* Initialize public exponent (e) from input buffer. */
	error_code = mp_read_unsigned_bin(e, Exponent_ptr, ExponentSize);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Initialize modulus exponent (N) from input buffer. */
	error_code = mp_read_unsigned_bin(N, Modulus_ptr, ModulusSize);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Extrude public exponent (e) and modulus exponent (N)
	from big numbers to output public key buffer: */

	/* Get public exponent (e) from imported key and it size. */
	error_code = mp_to_unsigned_bin(e, (unsigned char *)pubKey->e);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	pubKey->eSizeInBits = mp_count_bits(e);

	/* Get modulus exponent (N) from imported key and it size. */
	error_code = mp_to_unsigned_bin(N, (unsigned char *)pubKey->n);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	pubKey->nSizeInBits = mp_count_bits(N);

exit_label:
	mp_clear_multi(e, N, 0);
	return error_code;
} /* End of LLF_RSA_Build_PubKey */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_Build_PrivKey
*
* Inputs:
*  @param UserPrivKey_ptr [out] - A pointer to the public key structure.
*  @param PrivExponent_ptr [in] - A pointer to the private exponent stream of bytes;
*  @param PrivExponentSize [in] - The size of the private exponent, in bytes;
*  @param PubExponent_ptr  [in]- A pointer to the public exponent stream of bytes;
*  @param PubExponentSize  [in]- The size of the public exponent, in bytes;
*  @param Modulus_ptr      [in]- A pointer to the modulus stream of bytes.
*  @param ModulusSize      [in]- The size of the modulus, in bytes. 
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  CE2_RSA_Build_PrivKey populates a CE2RSAPrivKey_t structure with
* the provided modulus and exponent, marking the key as a "non-CRT" key
*
* \b
* Algorithm:
*  -# Initialize rsa key values (e and N);
*  -# Convert public exponent (e), private exponent (d),
*     modulus exponent (N) from entire buffer to big number mp_int;
*  -# Extrude public exponent (e), private exponent (d),
*     modulus exponent (N) from big numbers to output public key buffer.
***************************************************************/
CE2Error_t LLF_RSA_Build_PrivKey(CE2_RSAUserPrivKey_t   *UserPrivKey_ptr,	/* out */
	                             DxUint8_t              *PrivExponent_ptr,	/* in */
                                 DxUint16_t              PrivExponentSize,	/* in */
                                 DxUint8_t              *PubExponent_ptr,	/* in */
                                 DxUint16_t              PubExponentSize,	/* in */
                                 DxUint8_t              *Modulus_ptr,		/* in */
                                 DxUint16_t              ModulusSize )		/* in */
{
	CE2RSAPrivKey_t * privKey = (CE2RSAPrivKey_t *)UserPrivKey_ptr->PrivateKeyDbBuff;
	int error_code = CE2_OK;

	void * e = 0;	// big number for PubExponent_ptr
	void * d = 0;	// big number for PrivExponent_ptr
	void * N = 0;	// big number for Modulus_ptr

	/* Reset output key. */
	memset(UserPrivKey_ptr, 0, sizeof(CE2_RSAUserPrivKey_t));
	UserPrivKey_ptr->valid_tag = sizeof(CE2_RSAUserPrivKey_t);

	/* Set private key mode to non CRT, CRT parameters are not calculated */
	privKey->mode = CE2_RSA_PRIVATE_KEY_NON_CRT_MODE;

	/* Initialize to use math descriptor. */
	ltc_mp = ltm_desc;

	/* Initialize rsa key values:
	public exponent (e), private exponent (d), modulus exponent (N). */
	ltc_init_multi(&e, &d, &N, 0);

	/* Convert public exponent (e), private exponent (d),
	modulus exponent (N) from entire buffer to big number mp_int: */

	/* Initialize public exponent (e) from input buffer. */
	error_code = mp_read_unsigned_bin(e, PubExponent_ptr, PubExponentSize);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Initialize private exponent (d) from input buffer. */
	error_code = mp_read_unsigned_bin(d, PrivExponent_ptr, PrivExponentSize);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Initialize modulus exponent (N) from input buffer. */
	error_code = mp_read_unsigned_bin(N, Modulus_ptr, ModulusSize);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Extrude public exponent (e), private exponent (d),
	modulus exponent (N) from big numbers to output public key buffer: */

	/* Get public exponent (e) from imported key and it size. */
	error_code = mp_to_unsigned_bin(e, (unsigned char *)privKey->e);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	privKey->eSizeInBits = mp_count_bits(e);

	/* Get private exponent (d) from imported key and it size. */
	error_code = mp_to_unsigned_bin(d, (unsigned char *)privKey->d);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	privKey->dSizeInBits = mp_count_bits(d);

	/* Get modulus exponent (N) from imported key and it size. */
	error_code = mp_to_unsigned_bin(N, (unsigned char *)privKey->n);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	privKey->nSizeInBits = mp_count_bits(N);

exit_label:
	mp_clear_multi(e, d, N, 0);
	return error_code;
} /* End of LLF_RSA_Build_PrivKey */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_Build_PrivKeyCRT
*
* Inputs:
*  @param UserPrivKey_ptr [out] - A pointer to the public key structure.
*  @param P_ptr  [in] - A pointer to the first factor stream of bytes;
*  @param PSize  [in] - The size of the first factor, in bytes;
*  @param Q_ptr  [in] - A pointer to the second factor stream of bytes;
*  @param QSize  [in] - The size of the second factor, in bytes;
*  @param dP_ptr [in] - A pointer to the first factor's CRT exponent stream of bytes;
*  @param dPSize [in] - The size of the first factor's CRT exponent, in bytes;
*  @param dQ_ptr [in] - A pointer to the second factor's CRT exponent stream of bytes;
*  @param dQSize [in] - The size of the second factor's CRT exponent, in bytes;
*  @param qInv_ptr [in] - A pointer to the first CRT coefficient stream of bytes;
*  @param qInvSize [in] - The size of the first CRT coefficient, in bytes.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_Build_PrivKeyCRT populates a CE2RSAPrivKey_t structure with
*  the provided parameters, marking the key as a "CRT" key.
*
* \b
* Algorithm:
*  -# Initialize rsa key values:
*     p factor of N (p), q factor of N (q), d mod (p - 1) CRT param (dP),
*     d mod (q - 1) CRT param (dQ) and 1/q mod p CRT param (qP);
*  -# Convert previous inicialized rsa key values from entire buffers
*     to big number mp_int;
*  -# Extrude values of p, q, dP, dQ and qP from big numbers to
*     output public key buffer.
***************************************************************/
CE2Error_t LLF_RSA_Build_PrivKeyCRT(
                                 CE2_RSAUserPrivKey_t *UserPrivKey_ptr,	/* out */
                                 DxUint8_t *P_ptr, 	/* in */
                                 DxUint16_t PSize,	/* in */
                                 DxUint8_t *Q_ptr,	/* in */
                                 DxUint16_t QSize,	/* in */
                                 DxUint8_t *dP_ptr, /* in */
                                 DxUint16_t dPSize,	/* in */
                                 DxUint8_t *dQ_ptr,	/* in */
                                 DxUint16_t dQSize,	/* in */
                                 DxUint8_t *qInv_ptr,	/* in */
                                 DxUint16_t qInvSize )	/* in */
{

	CE2RSAPrivKey_t * privKey = (CE2RSAPrivKey_t *)UserPrivKey_ptr->PrivateKeyDbBuff;
	int error_code = CE2_OK;

	void * N = 0;	// big number for N
  void * e = 0;	// big number for e
  void * d = 0;	// big number for d
	void * p = 0;	// big number for P_ptr
	void * q = 0;	// big number for Q_ptr
	void * dP = 0;	// big number for dP_ptr
	void * dQ = 0;	// big number for dQ_ptr
	void * qP = 0;	// big number for qInv_ptr

	/* Reset output key. */
  memset(privKey->n, 0, sizeof(privKey->n));
  memset(privKey->e, 0, sizeof(privKey->e));
  memset(privKey->d, 0, sizeof(privKey->d));
	memset(privKey->p, 0, sizeof(privKey->p));
	memset(privKey->q, 0, sizeof(privKey->q));
	memset(privKey->dP, 0, sizeof(privKey->dP));
	memset(privKey->dQ, 0, sizeof(privKey->dQ));
	memset(privKey->qP, 0, sizeof(privKey->qP));
	UserPrivKey_ptr->valid_tag = sizeof(CE2_RSAUserPrivKey_t);

	/* Initialize to use math descriptor. */
	ltc_mp = ltm_desc;

	/* Initialize rsa key values:
	p factor of N (p), q factor of N (q), d mod (p - 1) CRT param (dP),
	d mod (q - 1) CRT param (dQ) and 1/q mod p CRT param (qP). 
  e - Public Exponent, d - Private Exponent */
	ltc_init_multi(&p, &q, &dP, &dQ, &qP, &N, &e, &d, 0);

	/* Convert previous inicialized rsa key values from entire buffers
	to big number mp_int: */

	/* Initialize p factor of N (p) from input buffer. */
	error_code = mp_read_unsigned_bin(p, P_ptr, PSize);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Initialize q factor of N (q) from input buffer. */
	error_code = mp_read_unsigned_bin(q, Q_ptr, QSize);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Initialize d mod (p - 1) CRT param (dP) from input buffer. */
	error_code = mp_read_unsigned_bin(dP, dP_ptr, dPSize);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Initialize d mod (q - 1) CRT param (dQ) from input buffer. */
	error_code = mp_read_unsigned_bin(dQ, dQ_ptr, dQSize);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Initialize 1/q mod p CRT param (qP) from input buffer. */
	error_code = mp_read_unsigned_bin(qP, qInv_ptr, qInvSize);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Extrude
	p factor of N (p), q factor of N (q), d mod (p - 1) CRT param (dP),
	d mod (q - 1) CRT param (dQ) and 1/q mod p CRT param (qP)
	from big numbers to output public key buffer: */

	/* Get p factor of N (p) from imported key and it size. */
	error_code = mp_to_unsigned_bin(p, (unsigned char *)privKey->p);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	privKey->pSizeInBits = mp_count_bits(p);

	/* Get q factor of N (q) from imported key and it size. */
	error_code = mp_to_unsigned_bin(q, (unsigned char *)privKey->q);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	privKey->qSizeInBits = mp_count_bits(q);

	/* Get d mod (p - 1) CRT param (dP) from imported key and it size. */
	error_code = mp_to_unsigned_bin(dP, (unsigned char *)privKey->dP);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	privKey->dPSizeInBits = mp_count_bits(dP);

	/* Get d mod (q - 1) CRT param (dQ) from imported key and it size. */
	error_code = mp_to_unsigned_bin(dQ, (unsigned char *)privKey->dQ);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	privKey->dQSizeInBits = mp_count_bits(dQ);

	/* Get 1/q mod p CRT param (qP) from imported key and it size. */
	error_code = mp_to_unsigned_bin(qP, (unsigned char *)privKey->qP);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	privKey->qPSizeInBits = mp_count_bits(qP);

	/* Set private key mode to CRT, CRT parameters are calculated */
	privKey->mode = CE2_RSA_PRIVATE_KEY_CRT_MODE;

  /*********************/
  /* Calculate N, e, d */
  /*********************/
  /* Calculate N */
  error_code = mp_mul(p, q, N);
  if (error_code != CRYPT_OK) {
    error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto exit_label;
  }

  /* Calculate e */
  /* p = p - 1 */
  error_code = mp_sub_d(p, 1, p);
  if (error_code != CRYPT_OK) {
    error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto exit_label;
  }
  /* e = inv(dP) mod (p - 1) */
  error_code = mp_invmod(dP, p, e);
  if (error_code != CRYPT_OK) {
    error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto exit_label;
  }

  /* Calculate d */
  /* q = q - 1 */
  error_code = mp_sub_d(q, 1, q);
  if (error_code != CRYPT_OK) {
    error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto exit_label;
  }
  /* q = (q - 1)*(p - 1) */
  error_code = mp_mul(q, p, q);
  if (error_code != CRYPT_OK) {
    error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto exit_label;
  }
  /* d = inv(e) mod (p - 1)(q - 1) */
  error_code = mp_invmod(e, q, d);
  if (error_code != CRYPT_OK) {
    error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto exit_label;
  }

  /* Get N */
	error_code = mp_to_unsigned_bin(N, (unsigned char *)privKey->n);
	if (error_code != CRYPT_OK)	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}
	privKey->nSizeInBits = mp_count_bits(N);

  /* Get e */
  error_code = mp_to_unsigned_bin(e, (unsigned char *)privKey->e);
  if (error_code != CRYPT_OK) {
    error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto exit_label;
  }
  privKey->eSizeInBits = mp_count_bits(e);

  /* Get d */
  error_code = mp_to_unsigned_bin(d, (unsigned char *)privKey->d);
  if (error_code != CRYPT_OK) {
    error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
    goto exit_label;
  }
  privKey->dSizeInBits = mp_count_bits(d);

exit_label:
	mp_clear_multi(p, q, dP, dQ, qP, N, e, d, 0);
	return error_code;
} /* End of LLF_RSA_Build_PrivKeyCRT */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_Get_PubKey
*
* Inputs:
*  @param UserPubKey_ptr [in] - A pointer to the public key structure. 
*  @param Exponent_ptr   [out] - A pointer to the exponent stream of bytes
*  @param ExponentSize_ptr [in/out] - the size of the exponent buffer in bytes,
*         it is updated to the actual size of the exponent, in bytes. 
*  @param Modulus_ptr    [in] - A pointer to the modulus stream of bytes.
*  @param ModulusSize_ptr [in/out] - the size of the modulus buffer in bytes,
*         it is updated to the actual size of the modulus, in bytes.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_Get_PubKey gets the e,n public key from the database.
*
* \b
* Algorithm:
*  -# Import RSA key from input key buffer to e and N values;
*  -# Extrude public exponent (e) and modulus exponent (N) and
*     calculate their sizes;
***************************************************************/
CE2Error_t LLF_RSA_Get_PubKey(  CE2_RSAUserPubKey_t *UserPubKey_ptr, /* in */
                                DxUint8_t  *Exponent_ptr,		/* out */
                                DxUint16_t *ExponentSize_ptr,	/* in, out */
                                DxUint8_t  *Modulus_ptr,		/* out */
                                DxUint16_t *ModulusSize_ptr )	/* in, out */
{
	CE2RSAPubKey_t * pubKey = (CE2RSAPubKey_t *)UserPubKey_ptr->PublicKeyDbBuff;
	int error_code = CE2_OK;
	int es, ms;

	void * e = 0;	// big number for Exponent_ptr
	void * N = 0;	// big number for Modulus_ptr
  
	/* Initialize to use math descriptor. */
	ltc_mp = ltm_desc;

	/* Initialize rsa key values: public exponent (e), modulus exponent (N). */
	ltc_init_multi(&e, &N, 0);

	/* Exponent initialization: e and N. */

	/* Put public exponent (e) from inputted buffer into our big number e. */
	error_code = mp_read_unsigned_bin(
		e, (unsigned char*)pubKey->e, BITS2BYTES(pubKey->eSizeInBits));
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Put modulus exponent (N) from inputted buffer into our big number N. */
	error_code = mp_read_unsigned_bin(
		N, (unsigned char *)pubKey->n, BITS2BYTES(pubKey->nSizeInBits));
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Check if sizes of input buffers are good for the exponents. */
	es = mp_unsigned_bin_size(e);
	ms = mp_unsigned_bin_size(N);
	
	error_code = (*ExponentSize_ptr < es || *ModulusSize_ptr < ms)
		? (CE2_LLF_RSA_MODULE_ERROR_BASE) : (CE2_OK);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	*ExponentSize_ptr = es;
	*ModulusSize_ptr = ms;

	/* Extrude exponents: e and N. */

	/* Get public exponent (e) from previous created number e. */
	error_code = mp_to_unsigned_bin(e, Exponent_ptr);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Get modulus exponent (N) from previous created number N. */
	error_code = mp_to_unsigned_bin(N, Modulus_ptr);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	if (((*Modulus_ptr) >> 7) != 0x01)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

exit_label:
	mp_clear_multi(e, N, 0);
	return error_code;
} /* End of LLF_RSA_Get_PubKey */

/**
****************************************************************
* Function Name: 
*  CE2_RSA_Get_ModSizeFromPubKey
*
* Inputs:
*  @param UserPubKey_ptr [in] - A pointer to the public key structure,
*         as returned by CE2_RSA_Build_PubKey.
*  @param ModulusSize_ptr [out] -  The actual size of the modulus, in bytes;
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*   The function gets modulus size from public key.
*
* \b
* Algorithm:
*  -# Get from input public key size of modulus exponent in bits 
*     and convert it into bytes.
***************************************************************/
CE2Error_t LLF_RSA_Get_ModSizeFromPubKey(
                                CE2_RSAUserPubKey_t *UserPubKey_ptr,/* in */
                                DxUint16_t *ModulusSize_ptr )		/* out */
{
	*ModulusSize_ptr =
		(DxUint16_t)
		(BITS2BYTES(
			((CE2RSAPubKey_t *)(UserPubKey_ptr->PublicKeyDbBuff))->nSizeInBits
		));

	return CE2_OK;
} /* End of LLF_RSA_Get_ModSizeFromPubKey */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_Get_PrivKey
*
* Inputs:
*  @param UserPrivKey_ptr [in] - A pointer to the private key structure;
*  @param PrivExponent_ptr [out] - A pointer to the exponent stream of bytes;
*  @param PrivExponentSize_ptr [in/out] - the size of the exponent buffer in bytes,
*         it is updated to the actual size of the exponent, in bytes;
*  @param PubExponent_ptr [out] - a pointer to the public exponent stream of bytes;
*  @param PubExponentSize_ptr [in/out] - the size of the exponent buffer in bytes,
*         it is updated to the actual size of the exponent, in bytes;
*  @param Modulus_ptr     [out] - A pointer to the modulus stream of bytes.
*  @param ModulusSize_ptr [in/out] - the size of the modolous buffer in bytes,
*         it is updated to the actual size of the modolous, in bytes.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_Get_PrivKey gets the D, n private key from the database.
*
* \b
* Algorithm:
*  -# Initialize rsa key values: public exponent (e),
*     private exponent (d), modulus exponent (N) using input values;
*  -# Extrude public exponent (e), private exponent (d) and
*     modulus exponent (N) from variables and calculate their sizes.
***************************************************************/
CE2Error_t LLF_RSA_Get_PrivKey( CE2_RSAUserPrivKey_t *UserPrivKey_ptr,		/* in */
				                DxUint8_t            *PrivExponent_ptr,		/* out */
				                DxUint16_t           *PrivExponentSize_ptr,	/* in, out */
				                DxUint8_t            *PubExponent_ptr,		/* out */
				                DxUint16_t           *PubExponentSize_ptr,	/* in, out */
				                DxUint8_t            *Modulus_ptr,			/* out */
				                DxUint16_t           *ModulusSize_ptr )		/* in, out */
{
	CE2RSAPrivKey_t * privKey = (CE2RSAPrivKey_t *)UserPrivKey_ptr->PrivateKeyDbBuff;
	int error_code = CE2_OK;
	int pues, pres, ms;

	void * e = 0;	// big number for PubExponent_ptr
	void * d = 0;	// big number for PrivExponent_ptr
	void * N = 0;	// big number for Modulus_ptr
  
	/* Initialize to use math descriptor. */
	ltc_mp = ltm_desc;

	/* Initialize rsa key values:
	public exponent (e), private exponent (d), modulus exponent (N). */
	ltc_init_multi(&e, &d, &N, 0);

	/* Exponent initialization: e , d and N. */

	/* Put public exponent (e) from inputted buffer into our big number e. */
	error_code = mp_read_unsigned_bin(
		e, (unsigned char*)privKey->e, BITS2BYTES(privKey->eSizeInBits));
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Put private exponent (d) from inputted buffer into our big number d. */
	error_code = mp_read_unsigned_bin(
		d, (unsigned char*)privKey->d, BITS2BYTES(privKey->dSizeInBits));
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Put modulus exponent (N) from inputted buffer into our big number N. */
	error_code = mp_read_unsigned_bin(
		N, (unsigned char *)privKey->n, BITS2BYTES(privKey->nSizeInBits));
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Check if sizes of input buffers are good for the exponents. */
	pues = mp_unsigned_bin_size(e);
	pres = mp_unsigned_bin_size(d);
	ms = mp_unsigned_bin_size(N);

	error_code = (*PubExponentSize_ptr < pues || *PrivExponentSize_ptr < pres ||
		*ModulusSize_ptr < ms) ? (CE2_LLF_RSA_MODULE_ERROR_BASE) : (CE2_OK);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	*PubExponentSize_ptr = pues;
	*PrivExponentSize_ptr = pres;
	*ModulusSize_ptr = ms;

	/* Extrude exponents: e, d and N. */

	/* Get public exponent (e) from previous created number e. */
	error_code = mp_to_unsigned_bin(e, PubExponent_ptr);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Get private exponent (d) from previous created number d. */
	error_code = mp_to_unsigned_bin(d, PrivExponent_ptr);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Get modulus exponent (N) from previous created number N. */
	error_code = mp_to_unsigned_bin(N, Modulus_ptr);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

exit_label:
	mp_clear_multi(e, d, N, 0);
	return error_code;
} /* End of LLF_RSA_Get_PrivKey */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_Get_PrivKeyCRT
*
* Inputs:
*  @param UserPrivKey_ptr [in] - a pointer to the publick key structure;
*  @param P_ptr [out] - a pointer to the first factor stream of bytes;
*  @param PSize_ptr [in/out] - the size of the first factor buffer in bytes, it is
*         updated to the actual size of the first factor, in bytes;
*  @param Q_ptr [out] - a pointer to the second factor stream of bytes;
*  @param QSize_ptr [in/out] - the size of the second factor buffer in bytes , it is
*         updated to the actual size of the second factor, in bytes;
*  @param dP_ptr [out] - a pointer to the first factors CRT exponent stream of bytes;
*  @param dPSize_ptr [in/out] - 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 dQ_ptr [out] - a pointer to the second factors CRT exponent stream of bytes;
*  @param dQSize_ptr [in/out] - 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 qInv_ptr [out] - a pointer to the first CRT coefficient stream of bytes;
*  @param qInvSize_ptr [in/out] - the size of the first CRT coefficient buffer in bytes, it is
*         updated to the actual size of the first CRT coefficient, in bytes.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_Get_PrivKey gets the p,q,dP,dQ,qP parts of private key
*  from the database.
*
* \b
* Algorithm:
*  -# Initialize rsa key values: p, q, dP, dQ and qP;
*  -# Initialize rsa key using data from entire public key;
*  -# Extrude rsa key variables from p, q, dP, dQ and qP into
*     the output variables.
***************************************************************/
CE2Error_t LLF_RSA_Get_PrivKeyCRT(
				                CE2_RSAUserPrivKey_t *UserPrivKey_ptr,	/* in */
				                DxUint8_t  *P_ptr,		/* out */
				                DxUint16_t *PSize_ptr,	/* in, out */
				                DxUint8_t  *Q_ptr,		/* out */
				                DxUint16_t *QSize_ptr,	/* in */
				                DxUint8_t  *dP_ptr, 	/* out */
				                DxUint16_t *dPSize_ptr,	/* in, out */
				                DxUint8_t  *dQ_ptr,		/* out */
				                DxUint16_t *dQSize_ptr,	/* in, out */
				                DxUint8_t  *qInv_ptr,	/* out */
				                DxUint16_t *qInvSize_ptr)/* in, out */
{
	CE2RSAPrivKey_t * privKey = (CE2RSAPrivKey_t *)UserPrivKey_ptr->PrivateKeyDbBuff;
	int error_code = CE2_OK;
	int ps, qs, dPs, dQs, qPs;

	void * p = 0;	// big number for P_ptr
	void * q = 0;	// big number for Q_ptr
	void * dP = 0;	// big number for dP_ptr
	void * dQ = 0;	// big number for dQ_ptr
	void * qP = 0;	// big number for qInv_ptr

	/* Initialize to use math descriptor. */
	ltc_mp = ltm_desc;

	/* Initialize rsa key values: p, q, dP, dQ and qP. */
	ltc_init_multi(&p, &q, &dP, &dQ, &qP, 0);

	/* Initialize rsa key values by data from entire buffers */

	/* Put p factor of N (p) from inputted buffer into our big number p. */
	error_code = mp_read_unsigned_bin(
		p, (unsigned char*)privKey->p, BITS2BYTES(privKey->pSizeInBits));
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Put q factor of N (q) from inputted buffer into our big number q. */
	error_code = mp_read_unsigned_bin(
		q, (unsigned char *)privKey->q, BITS2BYTES(privKey->qSizeInBits));
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Put d mod (p - 1) CRT param (dP) from inputted buffer into our big number dP. */
	error_code = mp_read_unsigned_bin(
		dP, (unsigned char *)privKey->dP, BITS2BYTES(privKey->dPSizeInBits));
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Put d mod (q - 1) CRT param (dQ) from inputted buffer into our big number dQ. */
	error_code = mp_read_unsigned_bin(
		dQ, (unsigned char *)privKey->dQ, BITS2BYTES(privKey->dQSizeInBits));
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Put 1/q mod p CRT param (qP) from inputted buffer into our big number qP. */
	error_code = mp_read_unsigned_bin(
		qP, (unsigned char *)privKey->qP, BITS2BYTES(privKey->qPSizeInBits));
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Check if sizes of input buffers are good for the exponents. */
	ps = mp_unsigned_bin_size(p);
	qs = mp_unsigned_bin_size(q);
	dPs = mp_unsigned_bin_size(dP);
	dQs = mp_unsigned_bin_size(dQ);
	qPs = mp_unsigned_bin_size(qP);

	error_code =
		(*PSize_ptr < ps || *QSize_ptr < qs || *dPSize_ptr < dPs ||
		*dQSize_ptr < dQs || *qInvSize_ptr < qPs) ? (CE2_LLF_RSA_MODULE_ERROR_BASE) : (CE2_OK);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	*PSize_ptr = ps;
	*QSize_ptr = qs;
	*dPSize_ptr = dPs;
	*dQSize_ptr = dQs;
	*qInvSize_ptr = qPs;

	/* Extrude rsa key variables: p, q, dP, dQ and qP. */

	/* Get p factor of N (p) from previous created number p. */
	error_code = mp_to_unsigned_bin(p, P_ptr);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Get q factor of N (q) from previous created number q. */
	error_code = mp_to_unsigned_bin(q, Q_ptr);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Get d mod (p - 1) CRT param (dP) from previous created number dP. */
	error_code = mp_to_unsigned_bin(dP, dP_ptr);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Get d mod (q - 1) CRT param (dQ) from previous created number dQ. */
	error_code = mp_to_unsigned_bin(dQ, dQ_ptr);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

	/* Get 1/q mod p CRT param (qP) from previous created number qP. */
	error_code = mp_to_unsigned_bin(qP, qInv_ptr);
	if (error_code != CRYPT_OK)
	{
		error_code = CE2_LLF_RSA_MODULE_ERROR_BASE;
		goto exit_label;
	}

exit_label:
	mp_clear_multi(p, q, dP, dQ, qP, 0);
	return error_code;
} /* End of LLF_RSA_Get_PrivKeyCRT */
