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

const char* DomainID_Names[] = {
  "",
  "WMDRM10",
  "secp160k1", 
  "secp160r1",
  "secp160r2",
  "secp192k1",
  "secp192r1", 
  "secp224k1",
  "secp224r1", 
  "secp256k1",
  "secp256r1", 
  "secp384r1", 
  "secp521r1" 
};

const char* HashMode_Names[] = {
  "SHA1",
  "SHA224",
  "SHA256",
  "SHA384",
  "SHA512",
  "After_SHA1",
  "After_SHA224",
  "After_SHA256",
  "After_SHA384",
  "After_SHA512"
};

/*
 \brief 
 CE2_TST_ECC_KeyExportImport() - Verify functionality of functions:
 1. CE2_ECPKI_GenKeyPair();
 2. CE2_ECPKI_ExportPublKey();
 3. CE2_ECPKI_BuildPublKey();
 4. CE2_ECPKI_ExportPrivKey();
 5. CE2_ECPKI_BuildPrivKey();

 @param[in] out - output stream for logs;
 @return - On success returns CE2_TST_VALID; else returns CE2_TST_FAILED.
*/
DxStatus CE2_TST_ECC_KeyExportImport(FILE *out)
{
  CE2_ECPKI_UserPrivKey_t UserPrivKey, UserPrivKey_FromExport;
  CE2_ECPKI_UserPublKey_t UserPublKey, UserPublKey_FromExport;
  DxStatus result = CE2_TST_VALID;
  CE2Error_t error = CE2_OK;
  DxUint8_t exportBuffer[1024];
  DxUint32_t size; 
  int i_domain_id;
  unsigned int i_byte;

  PrintTestBeginMsg(out, __FUNCTION__);

  for (i_domain_id = CE2_ECPKI_DomainID_WMDRM10;
    i_domain_id < CE2_ECPKI_DomainID_OffMode; i_domain_id++) {
    error = CE2_ECPKI_GenKeyPair((CE2_ECPKI_DomainID_t)i_domain_id,
      &UserPrivKey, &UserPublKey);
    if (error != CE2_OK) {
      fprintf(out, "Can't generate key pair with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }
    
    /* Public keys */
    size = 1024;
    error = CE2_ECPKI_ExportPublKey(&UserPublKey, CE2_EC_PointUncompressed, 
      exportBuffer, &size);
    if (error != CE2_OK) {
      fprintf(out, "Can't export public key with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }

    error = CE2_ECPKI_BuildPublKey((CE2_ECPKI_DomainID_t)i_domain_id, 
      exportBuffer, size, &UserPublKey_FromExport);
    if (error != CE2_OK) 
    {
      fprintf(out, "Can't build public key with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }

    if (UserPublKey_FromExport.DomainID != UserPublKey.DomainID)
    {
      fprintf(out, "Wrong domain in built public key with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
    }
    if (UserPublKey_FromExport.valid_tag != UserPublKey.valid_tag)
    {
      fprintf(out, "Wrong size in built public key with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      fprintf(out, "%d != %d.\n", 
        UserPublKey_FromExport.valid_tag, UserPublKey.valid_tag);
      result |= CE2_TST_FAILED;
    }
    if (memcmp(UserPublKey_FromExport.PublKeyDbBuff,
      UserPublKey.PublKeyDbBuff, UserPublKey.valid_tag) != 0)
    {
      fprintf(out, "Wrong key data in built public key with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      for (i_byte = 0; i_byte < UserPublKey.valid_tag; i_byte++) {
        if (UserPublKey_FromExport.PublKeyDbBuff[i_byte] !=
          UserPublKey.PublKeyDbBuff[i_byte]) {
          fprintf(out, "Wrong '%d' byte: (%X != %X).\n", i_byte,
            UserPublKey_FromExport.PublKeyDbBuff[i_byte],
            UserPublKey.PublKeyDbBuff[i_byte]); 
        }
      }
      result |= CE2_TST_FAILED;
    }

    /* Private keys */
    size = 1024;
    error = CE2_ECPKI_ExportPrivKey(&UserPrivKey, exportBuffer, &size);
    if (error != CE2_OK) {
      fprintf(out, "Can't export private key with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }

    error = CE2_ECPKI_BuildPrivKey((CE2_ECPKI_DomainID_t)i_domain_id, 
      exportBuffer, size, &UserPrivKey_FromExport);
    if (error != CE2_OK) 
    {
      fprintf(out, "Can't build private key with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }

    if (UserPrivKey_FromExport.DomainID != UserPrivKey.DomainID)
    {
      fprintf(out, "Wrong domain in built private key with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
    }
    if (UserPrivKey_FromExport.valid_tag != UserPrivKey.valid_tag)
    {
      fprintf(out, "Wrong size in built private key with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
    }
    if (memcmp(UserPrivKey_FromExport.PrivKeyDbBuff,
      UserPrivKey.PrivKeyDbBuff, UserPrivKey.valid_tag) != 0)
    {
      fprintf(out, "Wrong key data size in built private key with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      for (i_byte = 0; i_byte < UserPrivKey.valid_tag; i_byte++) {
        if (UserPrivKey_FromExport.PrivKeyDbBuff[i_byte] !=
          UserPrivKey.PrivKeyDbBuff[i_byte]) {
            fprintf(out, "Wrong '%d' byte: (%X != %X).\n", i_byte,
              UserPrivKey_FromExport.PrivKeyDbBuff[i_byte],
              UserPrivKey.PrivKeyDbBuff[i_byte]); 
        }
      }
      result |= CE2_TST_FAILED;
    }
  }

  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}
/*
  \brief 
  CE2_TST_ECC_DH() - Verify functionality of functions:
  1. CE2_ECDH_SVDP_DH();

  @param[in] out - output stream for logs;
  @return - On success returns CE2_TST_VALID; else returns CE2_TST_FAILED.
*/
DxStatus CE2_TST_ECC_DH(FILE *out)
{
  CE2_ECPKI_UserPrivKey_t UserPrivKey1, UserPrivKey2;
  CE2_ECPKI_UserPublKey_t UserPublKey1, UserPublKey2;
  DxStatus result = CE2_TST_VALID;
  CE2Error_t error = CE2_OK;
  DxUint8_t sharedSecret1[1024], sharedSecret2[1024];
  DxUint32_t size1 = 1024, size2 = 1024; 
  int i_domain_id;

  PrintTestBeginMsg(out, __FUNCTION__);

  for (i_domain_id = CE2_ECPKI_DomainID_WMDRM10;
    i_domain_id < CE2_ECPKI_DomainID_OffMode; i_domain_id++) {
    error = CE2_ECPKI_GenKeyPair((CE2_ECPKI_DomainID_t)i_domain_id,
      &UserPrivKey1, &UserPublKey1);
    if (error != CE2_OK) {
      fprintf(out, "Can't generate key pair with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }
    error = CE2_ECPKI_GenKeyPair((CE2_ECPKI_DomainID_t)i_domain_id,
      &UserPrivKey2, &UserPublKey2);
    if (error != CE2_OK) {
      fprintf(out, "Can't generate key pair with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }

    size1 = 1024;
    error = CE2_ECDH_SVDP_DH(&UserPublKey2, &UserPrivKey1, sharedSecret1, &size1);
    if (error != CE2_OK) {
      fprintf(out, "Can't create shared secret for user 1 with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }
    size2 = 1024;
    error = CE2_ECDH_SVDP_DH(&UserPublKey1, &UserPrivKey2, sharedSecret2, &size2);
    if (error != CE2_OK) {
      fprintf(out, "Can't create shared secret for user 2 with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }

    if (size1 != size2) {
      fprintf(out, "Different size of shared secret  with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }
    if (memcmp(sharedSecret1, sharedSecret2, size1) != 0) {
      fprintf(out, "Different shared secret with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }
  }

  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}

/*
\brief 
  CE2_TST_ECC_ElGamal_EncDec() - Verify functionality of functions:
  1. CE2_ECPKI_ELGAMAL_Encrypt();
  2. CE2_ECPKI_ELGAMAL_Decrypt();

  @param[in] out - output stream for logs;
  @return - On success returns CE2_TST_VALID; else returns CE2_TST_FAILED.
*/
DxStatus CE2_TST_ECC_ElGamal_EncDec(FILE *out)
{
  CE2_ECPKI_UserPrivKey_t UserPrivKey;
  CE2_ECPKI_UserPublKey_t UserPublKey;
  DxStatus result = CE2_TST_VALID;
  CE2Error_t error = CE2_OK;
  DxUint8_t  testMessage[] = "Test message.";
  DxUint8_t planText[1024], cryptText[1024];
  DxUint32_t sizePlanText, sizeCryptText, i_byte, 
    testMessageSize = sizeof(testMessage) - 1; 
  int i_domain_id;

  PrintTestBeginMsg(out, __FUNCTION__);

  for (i_domain_id = CE2_ECPKI_DomainID_WMDRM10;
    i_domain_id < CE2_ECPKI_DomainID_OffMode; 
    i_domain_id++) {
    error = CE2_ECPKI_GenKeyPair((CE2_ECPKI_DomainID_t)i_domain_id,
      &UserPrivKey, &UserPublKey);
    if (error != CE2_OK) {
      fprintf(out, "Can't generate key pair with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }
   
    sizeCryptText = 1024;
    error = CE2_ECPKI_ELGAMAL_Encrypt(&UserPublKey, testMessage, testMessageSize, 
      cryptText, &sizeCryptText);
    if (error != CE2_OK) {
      fprintf(out, "Can't encrypt message with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }
    
    sizePlanText = testMessageSize;
    error = CE2_ECPKI_ELGAMAL_Decrypt(&UserPrivKey, cryptText, sizeCryptText, 
      planText, &sizePlanText);
    if (error != CE2_OK) {
      fprintf(out, "Can't decrypt message with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }

    //if (sizePlanText != testMessageSize) {
    //  fprintf(out, "Different size of original and decrypted message with '%s' domain ID.\n" , 
    //    DomainID_Names[i_domain_id]);
    //  result |= CE2_TST_FAILED;
    //  continue;
    //}
    if (memcmp(planText, testMessage, testMessageSize) != 0) {
      fprintf(out, "Different original and decrypted message with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      for (i_byte = 0; i_byte < testMessageSize; i_byte++) {
        if (testMessage[i_byte] != planText[i_byte]) {
            fprintf(out, "Wrong '%d' byte: (%X != %X).\n", i_byte,
              testMessage[i_byte], planText[i_byte]); 
        }
      }
      result |= CE2_TST_FAILED;
      continue;
    }
  }
  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}

/*
\brief 
  CE2_TST_ECC_ECDSA() - Verify functionality of functions:
  1. CE2_ECDSA_Sign();
  2. CE2_ECDSA_Verify();

  @param[in] out - output stream for logs;
  @return - On success returns CE2_TST_VALID; else returns CE2_TST_FAILED.
*/
DxStatus CE2_TST_ECC_ECDSA(FILE *out)
{
  CE2_ECPKI_UserPrivKey_t UserPrivKey;
  CE2_ECPKI_UserPublKey_t UserPublKey;

	DxUint8_t* eph_key = (DxUint8_t*)&CE2_TST_ECC_ECDSA;
	DxUint32_t key_size = 0xFF;

  DxStatus result = CE2_TST_VALID;
  CE2Error_t error = CE2_OK;
  DxUint8_t  testMessage[] = "Test message.";
  DxUint8_t sign[1024];
  DxUint32_t signSize, 
    testMessageSize = sizeof(testMessage) - 1; 
  int i_domain_id, i_hash_mode;
  unsigned int i;

  PrintTestBeginMsg(out, __FUNCTION__);
  
  for (i_domain_id = CE2_ECPKI_DomainID_WMDRM10;
    i_domain_id < CE2_ECPKI_DomainID_OffMode; 
    i_domain_id++) {
    error = CE2_ECPKI_GenKeyPair((CE2_ECPKI_DomainID_t)i_domain_id,
      &UserPrivKey, &UserPublKey);
    if (error != CE2_OK) {
      fprintf(out, "Can't generate key pair with '%s' domain ID.\n" , 
        DomainID_Names[i_domain_id]);
      result |= CE2_TST_FAILED;
      continue;
    }
    for (i_hash_mode = CE2_ECPKI_HASH_SHA1_mode;
      i_hash_mode < CE2_ECPKI_HASH_NumOfModes; 
      i_hash_mode++) {
      signSize = 1024;
      error = CE2_ECDSA_Sign(&UserPrivKey, (CE2_ECPKI_HASH_OpMode_t)i_hash_mode, 
        testMessage, testMessageSize, sign, &signSize );
      if (error != CE2_OK) {
        fprintf(out, "Can't sign message with '%s' domain ID and '%s' hash mode.\n", 
          DomainID_Names[i_domain_id], HashMode_Names[i_hash_mode]);
        result |= CE2_TST_FAILED;
        continue;
      }
        
      error = CE2_ECDSA_Verify(&UserPublKey, (CE2_ECPKI_HASH_OpMode_t)i_hash_mode, 
        sign, signSize, testMessage, testMessageSize);
      if (error != CE2_OK) {
        fprintf(out, "Wrong message sign with '%s' domain ID and '%s' hash mode.\n", 
          DomainID_Names[i_domain_id], HashMode_Names[i_hash_mode]);

        fprintf(out, "\n");
        for(i = 0; i < UserPublKey.valid_tag; i++) {
          fprintf(out, "%X", (UserPublKey.PublKeyDbBuff[i]/0x10));
          fprintf(out, "%X ", (UserPublKey.PublKeyDbBuff[i])&0x0F);
        }
        fprintf(out, "\n");

        fprintf(out, "\n");
        for(i = 0; i < UserPrivKey.valid_tag; i++) {
          fprintf(out, "%X", (UserPrivKey.PrivKeyDbBuff[i]/0x10));
          fprintf(out, "%X ", (UserPrivKey.PrivKeyDbBuff[i])&0x0F);
        }
        fprintf(out, "\n");

        fprintf(out, "signSize = %d\n", signSize);
        fprintf(out, "\n");
        for(i = 0; i < signSize && i < 256; i++) {
          fprintf(out, "%X", (sign[i]/0x10));
          fprintf(out, "%X ", (sign[i])&0x0F);
        }
        fprintf(out, "\n");

        result |= CE2_TST_FAILED;
//        i_hash_mode--;
        continue;
      }
    }
  }

  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}

//-------------------------------------------------------------------------

DxStatus BugCheck_2007_03_28(FILE *out)
{
  DxStatus result = CE2_TST_VALID;

  // input data to sign:
  DxUint8_t 	TST_input_data[1536] = 
  {
    0x41,0x1f,0xd6,0xbc,0x3d,0x77,0xd0,0x5f,0xb0,0x71,0x00,0xf6,0x27,0xa7,0x55,0xf8,
    0xb4,0xc7,0x5a,0x31,0xeb,0xce,0x51,0x19,0x94,0x21,0xa6,0xac,0xb8,0xf5,0xbb,0x01,
    0xa8,0xd6,0xfa,0x2b,0x47,0xde,0x8c,0x36,0x04,0x2a,0x32,0x55,0x7c,0xf5,0xde,0x2e
  };

  DxUint32_t	TST_input_dataSize = 48;

  //  CE2_ECPKI_UserPrivKey_t  userParallelPrivKey1;
  //  CE2_ECPKI_UserPublKey_t  userParallelPublKey1;
  CE2_ECPKI_UserPublKey_t  CE2_PublKey;
  CE2_ECPKI_UserPrivKey_t  CE2_PrivKey;

  // exported public key data:
  DxUint8_t ExportedPublKeyBuffer[0x28] = 
  {
    0x5D, 0x3E, 0x72, 0x79, 0xCD, 0x31, 0x80, 0x59, 0x7B, 0xFC, 0x70, 
    0xB3, 0x2, 0x9, 0x6D, 0x93, 0x59, 0xE2, 0x10, 0x1B, 0x27, 
    0x72, 0x16, 0x45, 0xA0, 0x37, 0x9A, 0xFE, 0x2B, 0x36, 0xEB, 
    0xBF, 0x7B, 0x3, 0x45, 0xC, 0xBF, 0x5F, 0x19, 0x98
  };

  // exported private key data (size = 0x14):
  DxUint8_t ExportedPrivKeyBuffer[20] = 
  {
    0x34, 0x0, 0x79, 0x55, 0x51, 0xB1, 0x84, 0x59, 0xFC, 0x11, 0x46, 
    0x59, 0xF9, 0xC9, 0x2B, 0x80, 0x8C, 0xC9, 0xFD, 0xF7
  };


  DxUint32_t TST_SignitureSize1 = 0x28;
  DxUint32_t TST_SignatureSize2 = 0x28;

  //  CE2_ECPKI_PublKey_t publKey;

  // signature after CRYS_Sign function:
  DxUint8_t  TST_output_signiture1[1536] = 
  {
    0x3, 0x54, 0xBB, 0xE5, 0x5C, 0x7E, 0x4, 0x3B, 0xC1, 0xD7, 0x23, 
    0x17, 0xD0, 0x6B, 0x55, 0x36, 0x70, 0x63, 0x27, 0xFA, 0x29, 
    0x37, 0xE3, 0xB4, 0xA8, 0x9, 0x81, 0x23, 0x38, 0xDA, 0xDE, 
    0xC, 0xA8, 0xEB, 0x3E, 0x42, 0xEF, 0x9C, 0xDF, 0x5B

  };
  DxUint8_t  TST_output_signature2[1536]; 

  PrintTestBeginMsg(out, __FUNCTION__);

  if (CE2_ECPKI_BuildPublKey(
    CE2_ECPKI_DomainID_WMDRM10, 
    ExportedPublKeyBuffer,
    0x28,
    &CE2_PublKey) != CE2_OK)
  {
    fprintf(out, "Can't build CE2 public key!\n");
    result |= CE2_TST_FAILED;
  }

  if (CE2_ECPKI_BuildPrivKey(
    CE2_ECPKI_DomainID_WMDRM10, 
    ExportedPrivKeyBuffer,
    0x14,
    &CE2_PrivKey) != CE2_OK)
  {
    fprintf(out, "Can't build CE2 private key!\n");
    result |= CE2_TST_FAILED;
  }

  if(CE2_ECDSA_Sign(&CE2_PrivKey, 
    (CE2_ECPKI_HASH_OpMode_t)CE2_ECPKI_HASH_SHA1_mode,
    TST_input_data,
    TST_input_dataSize,
    TST_output_signature2,
    &TST_SignatureSize2) != CE2_OK)
  {
    fprintf(out, "Can't CE2 sign!\n");
    result |= CE2_TST_FAILED;
  }

  // see that this function failures with given arguments: 
  if (CE2_ECDSA_Verify ( &CE2_PublKey,
    (CE2_ECPKI_HASH_OpMode_t)CE2_ECPKI_HASH_SHA1_mode,
    TST_output_signiture1,
    TST_SignitureSize1,
    TST_input_data,
    TST_input_dataSize ) != CE2_OK) 
  {
    fprintf(out, "Can't CRYS's sign verify!\n");
    result |= CE2_TST_FAILED;
  }

  if (CE2_ECDSA_Verify (&CE2_PublKey,
    (CE2_ECPKI_HASH_OpMode_t)CE2_ECPKI_HASH_SHA1_mode,
    TST_output_signature2,
    TST_SignatureSize2,
    TST_input_data,
    TST_input_dataSize) != CE2_OK)
  {
    fprintf(out, "Can't CE2's sign verify!\n");
    result |= CE2_TST_FAILED;
  }

  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}

DxStatus BugCheck_2007_04_10(FILE *out)
{
  DxStatus result = CE2_TST_VALID;
  // input data to sign:
  DxUint8_t 	TST_input_data[1536] = 
  {
    0x41,0x1f,0xd6,0xbc,0x3d,0x77,0xd0,0x5f,0xb0,0x71,0x00,0xf6,0x27,0xa7,0x55,0xf8,
    0xb4,0xc7,0x5a,0x31,0xeb,0xce,0x51,0x19,0x94,0x21,0xa6,0xac,0xb8,0xf5,0xbb,0x01,
    0xa8,0xd6,0xfa,0x2b,0x47,0xde,0x8c,0x36,0x04,0x2a,0x32,0x55,0x7c,0xf5,0xde,0x2e
  };

  DxUint32_t	TST_input_dataSize = 48;

  //  CE2_ECPKI_UserPrivKey_t  userParallelPrivKey1;
  //  CE2_ECPKI_UserPublKey_t  userParallelPublKey1;
  CE2_ECPKI_UserPublKey_t  CE2_PublKey;
  CE2_ECPKI_UserPrivKey_t  CE2_PrivKey;

  // exported public key data:
  DxUint8_t ExportedPublKeyBuffer[0x29] = 
  {
    0x4, 0xA, 0x94, 0xF6, 0x6B, 0x62, 0xC6, 0xC9, 0x13, 0x93, 0x5C, 0x58, 0x9, 0xAF, 
    0x95, 0x10, 0x84, 0xDA, 0x1E, 0xE3, 0xD6, 0xC4, 0x84, 0x47, 0xB3, 0x69, 0x55, 0x29, 
    0x6E, 0xF, 0x3F, 0x6C, 0xCD, 0x63, 0xB5, 0xBE, 0x1E, 0x23, 0x56, 0x8, 0xBF
  };

  // exported private key data (size = 0x14):
  DxUint8_t ExportedPrivKeyBuffer[20] = 
  {
    0xC6, 0x6E, 0xE, 0x5A, 0x68, 0x18, 0x5C, 0x99, 0x8A, 0x32, 0xE0, 0xEF, 0x45, 0x25, 
    0xD5, 0x86, 0xB, 0x8F, 0x46, 0x73
  };


  DxUint32_t TST_SignitureSize1 = 0x2a;
  DxUint32_t TST_SignatureSize2 = 0x2a;

  //  CE2_ECPKI_PublKey_t publKey;

  // signature after CRYS_Sign function:
  DxUint8_t  TST_output_signiture1[1536] = 
  {
    0x0, 0xC, 0xD, 0xF, 0x5F, 0x7, 0x6B, 0x1D, 0xD1, 0xFE, 0xC3, 0x14, 0x3C, 0xD7, 0x5F, 
    0x5A, 0x63, 0x7, 0x2C, 0x62, 0x14, 0x0, 0x5C, 0x4D, 0x61, 0xC7, 0xE0, 0xB1, 0x2D, 
    0xF1, 0x7F, 0xD0, 0x16, 0x73, 0xA9, 0x42, 0xBB, 0x7F, 0xF5, 0x4C, 0xD2, 0x7

  };
  DxUint8_t  TST_output_signature2[1536]; 

  PrintTestBeginMsg(out, __FUNCTION__);

  if (CE2_ECPKI_BuildPublKey(
    CE2_ECPKI_DomainID_secp160r2, 
    ExportedPublKeyBuffer,
    0x29,
    &CE2_PublKey) != CE2_OK)
  {
    fprintf(out, "Can't build public key!\n");
    result |= CE2_TST_FAILED;
  }

  if (CE2_ECPKI_BuildPrivKey(
    CE2_ECPKI_DomainID_secp160r2, 
    ExportedPrivKeyBuffer,
    0x14,
    &CE2_PrivKey) != CE2_OK)
  {
    fprintf(out, "Can't build private key!\n");
    result |= CE2_TST_FAILED;
  }

  if(CE2_ECDSA_Sign(&CE2_PrivKey, 
    (CE2_ECPKI_HASH_OpMode_t)CE2_ECPKI_HASH_SHA1_mode,
    TST_input_data,
    TST_input_dataSize,
    TST_output_signature2,
    &TST_SignatureSize2) != CE2_OK) 
  {
    fprintf(out, "Can't CE2 sign!\n");
    result |= CE2_TST_FAILED;
  }


  // see that this function failures with given arguments: 
  if (CE2_ECDSA_Verify (&CE2_PublKey,
    (CE2_ECPKI_HASH_OpMode_t)CE2_ECPKI_HASH_SHA1_mode,
    TST_output_signiture1,
    TST_SignitureSize1,
    TST_input_data,
    TST_input_dataSize) != CE2_OK) 
  {
    fprintf(out, "Can't CRYS's sign verify!\n");
    result |= CE2_TST_FAILED;
  }

  if (CE2_ECDSA_Verify (&CE2_PublKey,
    (CE2_ECPKI_HASH_OpMode_t)CE2_ECPKI_HASH_SHA1_mode,
    TST_output_signature2,
    TST_SignatureSize2,
    TST_input_data,
    TST_input_dataSize) != CE2_OK)
  {
    fprintf(out, "Can't CE2's sign verify!\n");
    result |= CE2_TST_FAILED;
  }

  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}

DxStatus BugCheck_2007_04_26(FILE *out)
{
  DxStatus result = CE2_TST_VALID;

  DxUint8_t 	TST_input_data[1536] = 
  {
    0x45, 0x2B, 0xCE, 0xE9, 0xE7, 0x27, 0xF7, 0x20, 0x88, 0xBF, 0x89, 

    0xFF, 0x4B, 0x93, 0x31, 0x14, 0x4B, 0x8F, 0x25, 0x6, 0xD0, 

    0x7D, 0xBE, 0x57, 0x19, 0x6B, 0x74, 0x2F, 0xCB, 0xC0, 0x1D, 

    0x7D, 0x3D, 0xD2, 0x81, 0x76, 0xF5, 0x99, 0x1B, 0x2B, 0xCF, 

    0x83, 0xF1, 0x38, 0xE4, 0xD5, 0x13, 0xBB, 0x10, 0xa1
  };

  DxUint32_t	TST_input_dataSize = 0x32;

  //  CE2_ECPKI_UserPrivKey_t  userParallelPrivKey1;
  //  CE2_ECPKI_UserPublKey_t  userParallelPublKey1;
  CE2_ECPKI_UserPublKey_t  CE2_PublKey;

  DxUint32_t              publKeySize = 0x29;

  // exported public key data:
  DxUint8_t ExportedPublKeyBuffer[0x29] = 
  {
    0x4, 0x92, 0x7D, 0x9F, 0xF0, 0x8D, 0x4A, 0xEB, 0xA7, 0x6D, 0xF4, 0x27, 0x64, 
    0x9A, 0x54, 0x54, 0xD5, 0x72, 0xF5, 0xB8, 0x5E, 0x6F, 0xF6, 0x89, 0x86, 0x93, 
    0xE6, 0xC6, 0xC2, 0xE8, 0xAF, 0x78, 0xB4, 0xD1, 0x94, 0x4B, 0x8D, 0x3F, 0x8, 
    0x25, 0x1E
  };

  // exported private key data (size = 0x14):
  DxUint8_t ExportedPrivKeyBuffer[20] = 
  {
    0x39, 0xF3, 0x44, 0x24, 0x1C, 0x6F, 0x34, 0xD3, 0xD5, 0xF2, 0xE, 0xC2, 
    0x5F, 0xE3, 0x87, 0xA8, 0xD1, 0x9E, 0x78, 0x36
  };


  DxUint32_t TST_SignitureSize1 = 0x2A;

  // CE2_ECPKI_PublKey_t publKey;

  // signature after CRYS_Sign function:
  DxUint8_t  TST_output_signiture1[1536] = 
  {
    0x0, 0xB7, 0xBB, 0xCF, 0x52, 0xAB, 0xAE, 0x92, 0x48, 0x67, 0xA5, 0x30, 0x7E, 
    0x6B, 0xEA, 0x7F, 0xEE, 0xFA, 0x59, 0x23, 0xA1, 0x0, 0xA1, 0x28, 0x5A, 0xCF, 
    0xC1, 0xBE, 0x50, 0xC6, 0x18, 0x17, 0xF, 0x78, 0x37, 0x76, 0x19, 0xC9, 0x13, 
    0xA6, 0xE9, 0xDB
  };

  PrintTestBeginMsg(out, __FUNCTION__);

  if (CE2_ECPKI_BuildPublKey(
    CE2_ECPKI_DomainID_secp160r1, 
    ExportedPublKeyBuffer,
    publKeySize,
    &CE2_PublKey) != CE2_OK)
  {
    fprintf(out, "Can't build public key!\n");
    result |= CE2_TST_FAILED;
  }

  // see that this function failures with given arguments: 
  if (CE2_ECDSA_Verify (&CE2_PublKey,
    (CE2_ECPKI_HASH_OpMode_t)CE2_ECPKI_HASH_SHA256_mode,
    TST_output_signiture1,
    TST_SignitureSize1,
    TST_input_data,
    TST_input_dataSize) != CE2_OK)
  {
    fprintf(out, "Can't verify CRYS sign!\n");
    result |= CE2_TST_FAILED;
  }


  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}

DxStatus CE2_TST_ECC_ECDSA_ZeroMessage(FILE *out)
{
  CE2_ECPKI_UserPrivKey_t UserPrivKey;
  CE2_ECPKI_UserPublKey_t UserPublKey;
  DxStatus result = CE2_TST_VALID;
  CE2Error_t error = CE2_OK;
  DxUint8_t  *pTestMessage = DX_NULL;
  DxUint8_t sign[1024];
  DxUint32_t signSize, testMessageSize = 0; 
  int i_domain_id, i_hash_mode;

  PrintTestBeginMsg(out, __FUNCTION__);

  for (i_domain_id = CE2_ECPKI_DomainID_WMDRM10;
    i_domain_id < CE2_ECPKI_DomainID_OffMode; 
    i_domain_id++) {
      error = CE2_ECPKI_GenKeyPair((CE2_ECPKI_DomainID_t)i_domain_id,
        &UserPrivKey, &UserPublKey);
      if (error != CE2_OK) {
        fprintf(out, "Can't generate key pair with '%s' domain ID.\n" , 
          DomainID_Names[i_domain_id]);
        result |= CE2_TST_FAILED;
        continue;
      }
      for (i_hash_mode = CE2_ECPKI_HASH_SHA1_mode;
        i_hash_mode < CE2_ECPKI_HASH_NumOfModes; 
        i_hash_mode++) {
          signSize = 1024;
          error = CE2_ECDSA_Sign(&UserPrivKey, (CE2_ECPKI_HASH_OpMode_t)i_hash_mode, 
            pTestMessage, testMessageSize, sign, &signSize );
          if (error != CE2_OK) {
            fprintf(out, "Can't sign message with '%s' domain ID and '%s' hash mode.\n", 
              DomainID_Names[i_domain_id], HashMode_Names[i_hash_mode]);
            result |= CE2_TST_FAILED;
            continue;
          }

          error = CE2_ECDSA_Verify(&UserPublKey, (CE2_ECPKI_HASH_OpMode_t)i_hash_mode, 
            sign, signSize, pTestMessage, testMessageSize);
          if (error != CE2_OK) {
            fprintf(out, "Wrong message sign with '%s' domain ID and '%s' hash mode.\n", 
              DomainID_Names[i_domain_id], HashMode_Names[i_hash_mode]);
            result |= CE2_TST_FAILED;
            continue;
          }
      }
  }

  PrintTestEndMsg(out, __FUNCTION__, result);

  return result;
}
