/*
* Creation date : 
* Last modified : %modify_time%
*/
/** @file
* \brief This file contains implementation of 
*           Utils low level functions. 
*
* \version LLF_Utils.c#1:csrc:1
* \author Yermalayeu Ihar
* \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
* All Rights reserved
*/

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

#include "LLF_Utils.h"
#include "LLF_RSA_Common.h"
#include "tomcrypt.h"
#include "tommath.h"

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

/**
****************************************************************
* Function Name: 
* LLF_MulNum
*
*  @param Buf1_ptr [in] - A pointer to buffer with first big-endian number;
*  @param Buf1SizeInBits [in] - The size of the first number in bits;
*  @param Buf2_ptr [in] - A pointer to buffer with second big-endian number; 
*  @param Buf2SizeInBits [in] - The size of the second number in bits;
*  @param Res_ptr [out] - A pointer to the buffer with output big-endian number; 
*  @param ResSizeInBytes_ptr [in/out] - The size of the output number in bytes.
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code:
*   - CE2_UTILS_INVALID_POINTER_ERROR
*
* \brief \b 
* Description:
*  This function multiplicate two big number and store result in output buffer;
*
*  \b 
* Algorithm:
*  -# Convert numbers to LibTomCrypt format;
*  -# Make multiplication with using LibTomCrypt; 
*  -# Convert result to output big-endian format.
***************************************************************/
CE2Error_t LLF_MulNum( 
                      DxUint32_t *Buf1_ptr, 
                      DxUint32_t Buf1SizeInBits,
                      DxUint32_t *Buf2_ptr, 
                      DxUint32_t Buf2SizeInBits,
                      DxUint32_t *Res_ptr, 
                      DxUint32_t *ResSizeInBytes_ptr)
{
  void *a, *b, *c;
  CE2Error_t result = CE2_OK;
  int error_code;
  DxUint32_t size;

  /* Convert numbers to LibTomCrypt format */
  ltc_mp = ltm_desc;
  error_code = ltc_init_multi(&a, &b, &c, NULL);
  if (error_code != CRYPT_OK) {
    return CE2_LLF_UTILS_MODULE_ERROR_BASE;
  }
  /* Read Buf1_ptr */
  error_code = ltc_mp.unsigned_read(a, (unsigned char*)Buf1_ptr, 
    BITS2BYTES(Buf1SizeInBits));
  if (error_code != CRYPT_OK) {
    result = CE2_LLF_UTILS_MODULE_ERROR_BASE;
    goto error_case;
  }
  /* Read Buf2_ptr */
  error_code = ltc_mp.unsigned_read(b, (unsigned char*)Buf2_ptr, 
    BITS2BYTES(Buf2SizeInBits));
  if (error_code != CRYPT_OK) {
    result = CE2_LLF_UTILS_MODULE_ERROR_BASE;
    goto error_case;
  }

  /* Make multiplication with using LibTomCrypt */
  error_code = ltc_mp.mul(a, b, c);
  if (error_code != CRYPT_OK) {
    result = CE2_LLF_UTILS_MODULE_ERROR_BASE;
    goto error_case;
  }

  /* Convert result to output big-endian format */
  size = ltc_mp.unsigned_size(c);
  if (size > *ResSizeInBytes_ptr) {
    *ResSizeInBytes_ptr = size;
    result = CE2_LLF_UTILS_MODULE_ERROR_BASE;
    goto error_case;
  }
  *ResSizeInBytes_ptr = size;
  error_code = ltc_mp.unsigned_write(c, (unsigned char*)Res_ptr);
  if (error_code != CRYPT_OK) {
    result = CE2_LLF_UTILS_MODULE_ERROR_BASE;
    goto error_case;
  }

error_case:
  ltc_deinit_multi(a, b, c, NULL);
  return result;
} /* End of LLF_MulNum */

/**
****************************************************************
* Function Name: 
* LLF_GetBufferEffectiveSizeInBits
*
*  @param Buffer_ptr [in] - A pointer to buffer with big-endian number;
*  @param BufferSizeInBytes [in] - The size of the buffer;
*  @param EffectiveSizeInBits_ptr [out] - A output pointer with effective 
*                                         size in bits.
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code:
*   - CE2_UTILS_INVALID_POINTER_ERROR
*
* \brief \b 
* Description:
*  Get effective size in bits for given buffer with big number in 
*  big-endian format.
*
*  \b 
* Algorithm:
*  -# Convert number to LibTomCrypt format;
*  -# Getting its effective size in bits with using LibTomCrypt; 
***************************************************************/
CE2Error_t LLF_GetBufferEffectiveSizeInBits(
  DxUint8_t  *Buffer_ptr,
  DxUint16_t BufferSizeInBytes,
  DxUint32_t *EffectiveSizeInBits_ptr)
{
  void *a;
  CE2Error_t result = CE2_OK;
  int error_code;

  /* Convert numbers to LibTomCrypt format */
  ltc_mp = ltm_desc;
  error_code = ltc_init_multi(&a, NULL);
  if (error_code != CRYPT_OK) {
    return CE2_LLF_UTILS_MODULE_ERROR_BASE;
  }
  /* Read Buffer_ptr */
  error_code = ltc_mp.unsigned_read(a, (unsigned char*)Buffer_ptr, 
    BufferSizeInBytes);
  if (error_code != CRYPT_OK) {
    result = CE2_LLF_UTILS_MODULE_ERROR_BASE;
    goto error_case;
  }

  /* Getting its effective size in bits with using LibTomCrypt */
  *EffectiveSizeInBits_ptr = ltc_mp.count_bits(a);

error_case:
  ltc_deinit_multi(a, NULL);
  return result;
} /* End of LLF_GetBufferEffectiveSizeInBits */
