/*
*  Object %name    : %
*  State           :  %state%
*  Creation date   :  Mar 29 2007
*  Last modified   :  %modify_time%
*/
/** @file
*  \brief A brief description of this module
*
*  \version CE2_TST_C2.h#1:incl:1
*  \author Yermalayeu Ihar
*  \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
*           All Rights reserved
*/

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

#include <memory.h>
#include "CryptoEngine2.h"
#include "CE2_TST_Common.h"
#include "CE2_TST_C2.h"

/************************ Defines *******************************/
#define CE2_TST_OTF_DATA_SIZE_1 32
/************************ Enums *********************************/
/************************ Typedefs ******************************/
/************************ Global Data ***************************/
DxUint8_t CE2_TST_OTF_InputData1[CE2_TST_OTF_DATA_SIZE_1] = {
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};

DxUint8_t CE2_TST_OTF_AES_Key[] = {
  0x3c,0xe0,0xfe,0x74,0xcf,0xf4,0x98,0x68,0xf1,0xd6,0x59,0x24,0xf8,0x52,0x75,0x66
};

DxUint8_t CE2_TST_OTF_DES_Key[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};

/*********************** Private Function ***********************/
/************************ Public Functions **********************/
/*****************************************************************************
* Function Name:                                                           
* 	CE2_TST_OTF_AES2AES2HASH 		
* 
* Inputs:
*  @param[in/out] out - output stream for logs;
*
* Outputs:
*  @return - On success returns CE2_TST_VALID; else returns CE2_TST_FAILED.
*
* Description:																	
* 	Verify functionality of DX_AES2AES2HASH_OTF() function;
*
* Algorithm:		
*  -#  											
******************************************************************************/	
DxStatus CE2_TST_OTF_AES2AES2HASH(FILE *out)
{
  DxStatus result = CE2_TST_VALID, error;
  DxUint8_t tmp1[CE2_TST_OTF_DATA_SIZE_1], tmp2[CE2_TST_OTF_DATA_SIZE_1],
    output[CE2_TST_OTF_DATA_SIZE_1];
  CE2_HASH_Result_t controlHash1, controlHash2, testHash;

  PrintTestBeginMsg(out, __FUNCTION__);

  /* Make control data */
  error = DX_AES(0, CE2_TST_OTF_AES_Key, CE2_AES_Key128BitSize, CE2_AES_Encrypt,
    CE2_AES_ECB_mode, CE2_TST_OTF_InputData1, CE2_TST_OTF_DATA_SIZE_1, tmp1);
  if (error != CE2_OK) {
    fprintf(out, "Can't make control data (first AES encryption)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }
  error = DX_AES(0, CE2_TST_OTF_AES_Key, CE2_AES_Key128BitSize, CE2_AES_Encrypt,
    CE2_AES_ECB_mode, tmp1, CE2_TST_OTF_DATA_SIZE_1, tmp2);
  if (error != CE2_OK) {
    fprintf(out, "Can't make control data (second AES encryption)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }
  error = CE2_HASH(CE2_HASH_SHA1_mode, tmp1, CE2_TST_OTF_DATA_SIZE_1, controlHash1);
  if (error != CE2_OK) {
    fprintf(out, "Can't make control data (Hash 1)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }
  error = CE2_HASH(CE2_HASH_SHA1_mode, tmp2, CE2_TST_OTF_DATA_SIZE_1, controlHash2);
  if (error != CE2_OK) {
    fprintf(out, "Can't make control data (Hash 2)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }

  /* Make test (2 AES keys)*/
  error = DX_AES2AES2HASH_OTF(0, CE2_TST_OTF_AES_Key, CE2_AES_Key128BitSize, CE2_AES_Encrypt,
    CE2_AES_ECB_mode, 0, CE2_TST_OTF_AES_Key, CE2_AES_Key128BitSize, CE2_AES_Encrypt,
    CE2_AES_ECB_mode, CE2_HASH_ChiperData, CE2_HASH_SHA1_mode, CE2_TST_OTF_InputData1, 
    CE2_TST_OTF_DATA_SIZE_1, output, testHash);
  if (error != CE2_OK) {
    fprintf(out, "Can't make OTF operation (2 AES keys)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }

  /* Verify  result:*/
  if (memcmp(tmp2, output, CE2_TST_OTF_DATA_SIZE_1) != 0) {
    fprintf(out, "Wrong OTF output(2 AES keys)\n");
    result |= CE2_TST_FAILED;
  }
  /* Verify  hash:*/
  if (memcmp(testHash, controlHash2, CE2_HASH_SHA1_DIGEST_SIZE_IN_BYTES) != 0) {
    fprintf(out, "Wrong OTF output(2 AES keys)\n");
    result |= CE2_TST_FAILED;
  }

  /* Make test (1 AES key)*/
  error = DX_AES2AES2HASH_OTF(0, CE2_TST_OTF_AES_Key, CE2_AES_Key128BitSize, CE2_AES_Encrypt,
    CE2_AES_ECB_mode, 0, 0, CE2_AES_Key128BitSize, CE2_AES_Encrypt,
    CE2_AES_ECB_mode, CE2_HASH_ChiperData, CE2_HASH_SHA1_mode, CE2_TST_OTF_InputData1, 
    CE2_TST_OTF_DATA_SIZE_1, output, testHash);
  if (error != CE2_OK) {
    fprintf(out, "Can't make OTF operation (1 AES key)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }

  /* Verify  result:*/
  if (memcmp(tmp1, output, CE2_TST_OTF_DATA_SIZE_1) != 0) {
    fprintf(out, "Wrong OTF output (1 AES key\n");
    result |= CE2_TST_FAILED;
  }
  /* Verify  hash:*/
  if (memcmp(testHash, controlHash1, CE2_HASH_SHA1_DIGEST_SIZE_IN_BYTES) != 0) {
    fprintf(out, "Wrong OTF output (1 AES key\n");
    result |= CE2_TST_FAILED;
  }

end_test:
  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}

/*****************************************************************************
* Function Name:                                                           
* 	CE2_TST_OTF_AES2DES2HASH 		
* 
* Inputs:
*  @param[in/out] out - output stream for logs;
*
* Outputs:
*  @return - On success returns CE2_TST_VALID; else returns CE2_TST_FAILED.
*
* Description:																	
* 	Verify functionality of DX_AES2DES2HASH_OTF() function;
*
* Algorithm:		
*  -#  											
******************************************************************************/	
DxStatus CE2_TST_OTF_AES2DES2HASH(FILE *out)
{
  DxStatus result = CE2_TST_VALID, error;
  DxUint8_t tmp1[CE2_TST_OTF_DATA_SIZE_1], tmp2[CE2_TST_OTF_DATA_SIZE_1],
    output[CE2_TST_OTF_DATA_SIZE_1];
  CE2_HASH_Result_t controlHash, testHash;

  PrintTestBeginMsg(out, __FUNCTION__);

  /* Make control data */
  error = DX_AES(0, CE2_TST_OTF_AES_Key, CE2_AES_Key128BitSize, CE2_AES_Encrypt,
    CE2_AES_ECB_mode, CE2_TST_OTF_InputData1, CE2_TST_OTF_DATA_SIZE_1, tmp1);
  if (error != CE2_OK) {
    fprintf(out, "Can't make control data (first AES encryption)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }
  error = CE2_DES(0, (CE2_DES_Key_t*)CE2_TST_OTF_DES_Key, CE2_DES_1_KeyInUse, 
    CE2_DES_Encrypt, CE2_DES_ECB_mode, tmp1, CE2_TST_OTF_DATA_SIZE_1, tmp2);
  if (error != CE2_OK) {
    fprintf(out, "Can't make control data (second DES encryption)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }
  error = CE2_HASH(CE2_HASH_SHA1_mode, tmp1, CE2_TST_OTF_DATA_SIZE_1, controlHash);
  if (error != CE2_OK) {
    fprintf(out, "Can't make control data (Hash)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }

  /* Make test */
  error = DX_AES2DES2HASH_OTF(0, CE2_TST_OTF_AES_Key, CE2_AES_Key128BitSize, CE2_AES_Encrypt,
    CE2_AES_ECB_mode, 0, (CE2_DES_Key_t*)CE2_TST_OTF_DES_Key, CE2_DES_1_KeyInUse, 
    CE2_DES_Encrypt, CE2_DES_ECB_mode, CE2_HASH_ChiperFirstBlock, CE2_HASH_SHA1_mode, 
    CE2_TST_OTF_InputData1, CE2_TST_OTF_DATA_SIZE_1, output, testHash);
  if (error != CE2_OK) {
    fprintf(out, "Can't make OTF operation\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }

  /* Verify  result:*/
  if (memcmp(tmp2, output, CE2_TST_OTF_DATA_SIZE_1) != 0) {
    fprintf(out, "Wrong OTF output\n");
    result |= CE2_TST_FAILED;
  }
  /* Verify  hash:*/
  if (memcmp(testHash, controlHash, CE2_HASH_SHA1_DIGEST_SIZE_IN_BYTES) != 0) {
    fprintf(out, "Wrong OTF output\n");
    result |= CE2_TST_FAILED;
  }

end_test:
  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}

/*****************************************************************************
* Function Name:                                                           
* 	CE2_TST_OTF_DES2AES2HASH 		
* 
* Inputs:
*  @param[in/out] out - output stream for logs;
*
* Outputs:
*  @return - On success returns CE2_TST_VALID; else returns CE2_TST_FAILED.
*
* Description:																	
* 	Verify functionality of DX_DES2AES2HASH_OTF() function;
*
* Algorithm:		
*  -#  											
******************************************************************************/	
DxStatus CE2_TST_OTF_DES2AES2HASH(FILE *out)
{
  DxStatus result = CE2_TST_VALID, error;
  DxUint8_t tmp1[CE2_TST_OTF_DATA_SIZE_1], tmp2[CE2_TST_OTF_DATA_SIZE_1],
    output[CE2_TST_OTF_DATA_SIZE_1];
  CE2_HASH_Result_t controlHash, testHash;

  PrintTestBeginMsg(out, __FUNCTION__);

  /* Make control data */
  error = CE2_DES(0, (CE2_DES_Key_t*)CE2_TST_OTF_DES_Key, CE2_DES_1_KeyInUse, 
    CE2_DES_Encrypt, CE2_DES_ECB_mode, CE2_TST_OTF_InputData1, CE2_TST_OTF_DATA_SIZE_1, 
    tmp1);
  if (error != CE2_OK) {
    fprintf(out, "Can't make control data (first DES encryption)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }
  error = DX_AES(0, CE2_TST_OTF_AES_Key, CE2_AES_Key128BitSize, CE2_AES_Encrypt,
    CE2_AES_ECB_mode, tmp1, CE2_TST_OTF_DATA_SIZE_1, tmp2);
  if (error != CE2_OK) {
    fprintf(out, "Can't make control data (second AES encryption)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }
  error = CE2_HASH(CE2_HASH_SHA1_mode, CE2_TST_OTF_InputData1, 
    CE2_TST_OTF_DATA_SIZE_1, controlHash);
  if (error != CE2_OK) {
    fprintf(out, "Can't make control data (Hash)\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }

  /* Make test */
  error = DX_DES2AES2HASH_OTF(0, (CE2_DES_Key_t*)CE2_TST_OTF_DES_Key, CE2_DES_1_KeyInUse, 
    CE2_DES_Encrypt, CE2_DES_ECB_mode, 0, CE2_TST_OTF_AES_Key, CE2_AES_Key128BitSize, CE2_AES_Encrypt,
    CE2_AES_ECB_mode, CE2_HASH_PainText, CE2_HASH_SHA1_mode, 
    CE2_TST_OTF_InputData1, CE2_TST_OTF_DATA_SIZE_1, output, testHash);
  if (error != CE2_OK) {
    fprintf(out, "Can't make OTF operation\n");
    result |= CE2_TST_FAILED;
    goto end_test;
  }

  /* Verify  result:*/
  if (memcmp(tmp2, output, CE2_TST_OTF_DATA_SIZE_1) != 0) {
    fprintf(out, "Wrong OTF output\n");
    result |= CE2_TST_FAILED;
  }
  /* Verify  hash:*/
  if (memcmp(testHash, controlHash, CE2_HASH_SHA1_DIGEST_SIZE_IN_BYTES) != 0) {
    fprintf(out, "Wrong OTF output\n");
    result |= CE2_TST_FAILED;
  }

end_test:
  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}
