home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 September / Chip_2002-09_cd1.bin / zkuste / vbasic / Data / Utils / XZipComp.exe / XceedEncryption.Cab / F113005_TestVector.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-07-03  |  21.4 KB  |  650 lines

  1. /* Xceed Encryption Library - TestVector Sample Application
  2.  * Copyright (c) 2001 Xceed Software Inc.
  3.  *
  4.  * [TestVector.cpp]
  5.  *
  6.  * This console application tests the results of some Xceed Encryption Library
  7.  * functions against some static test vectors.
  8.  * It specifically tests:
  9.  *  - The Encrypt and Hash methods.
  10.  *
  11.  * This file is part of the Xceed Encryption Library sample 
  12.  * applications. The source code in this file is only intended as 
  13.  * a supplement to Xceed Encryption Library's documentation, 
  14.  * and is provided "as is", without warranty of any kind, either 
  15.  * expressed or implied. 
  16.  */
  17.  
  18. #include "stdafx.h"
  19.  
  20. #include <stdio.h>
  21. #include "TestVector.h"
  22.  
  23. // --------------------------------------------------------------------------
  24. //
  25. // Entry point of the application
  26. //
  27. // --------------------------------------------------------------------------
  28. int main( int argc, char* argv[] )
  29. {
  30.   CoInitialize( NULL );
  31.  
  32.   try
  33.   {
  34.     // Create an instance of the XceedEncryption coclass
  35.     IXceedEncryptionPtr piEnc;
  36.     piEnc.CreateInstance( CLSID_XceedEncryption );
  37.  
  38.     // Create an instance of the XceedHashing coclass
  39.     IXceedHashingPtr piHash;
  40.     piHash.CreateInstance( CLSID_XceedHashing );
  41.  
  42.     bool bAllPassed = true;
  43.  
  44.     // Test the Rijndael encryption method
  45.     if( !TestRijndael( piEnc ) )
  46.       bAllPassed = false;
  47.  
  48.     // Test the Twofish encryption method
  49.     if( !TestTwoFish( piEnc ) )
  50.       bAllPassed = false;
  51.  
  52.     // Test the SHA hashing method
  53.     if( !TestSHA( piHash ) )
  54.       bAllPassed = false;
  55.  
  56.     // Test the Haval hashing method
  57.     if( !TestHaval( piHash ) )
  58.       bAllPassed = false;
  59.  
  60.     if( bAllPassed )
  61.     {
  62.       printf( "\n\nAll tests passed!" );
  63.     }
  64.     else
  65.     {
  66.       printf( "\n\nSome test(s) failed!" );
  67.     }
  68.   }
  69.   catch( const _com_error& err )
  70.   {
  71.     // The generated wrapper classes throw _com_error exceptions when a COM error
  72.     // occurs.
  73.     printf( "Error %08x: %s\n", err.Error(), ( const char* )err.Description() );
  74.   }
  75.   catch( ... )
  76.   {
  77.     printf( "An unknown error occured.\n" );
  78.   }
  79.  
  80.   CoUninitialize();
  81.  
  82.   return 0;
  83. }
  84.  
  85. // --------------------------------------------------------------------------
  86. //
  87. // Test some Rijndael encryption results
  88. //
  89. // --------------------------------------------------------------------------
  90. bool TestRijndael( IXceedEncryptionPtr piEnc )
  91. {
  92.   // Create an instance of the XceedRijndaelEncryptionMethod coclass
  93.   IXceedRijndaelEncryptionMethodPtr piAES;
  94.   piAES.CreateInstance( CLSID_XceedRijndaelEncryptionMethod );
  95.  
  96.   // Assign the encryption method created above to the encryption object
  97.   piEnc->PutRefEncryptionMethod( IXceedEncryptDataPtr( piAES ) );
  98.   
  99.   // We use the templatized function TestSymmetricCipher, passing it the
  100.   // encryption object, the Rijndael method and the path and file name containing
  101.   // the test vectors.
  102.   return TestSymmetricCipher<IXceedRijndaelEncryptionMethodPtr>( piEnc, piAES, DATA_PATH "Rijndael.txt" );
  103. }
  104.  
  105. // --------------------------------------------------------------------------
  106. //
  107. // Test some TwoFish encryption results
  108. //
  109. // --------------------------------------------------------------------------
  110. bool TestTwoFish( IXceedEncryptionPtr piEnc )
  111. {
  112.   // Create an instance of the XceedTwofishEncryptionMethod coclass
  113.   IXceedTwofishEncryptionMethodPtr piTwofish;
  114.   piTwofish.CreateInstance( CLSID_XceedTwofishEncryptionMethod );
  115.  
  116.   // Assign the encryption method created above to the encryption object
  117.   piEnc->PutRefEncryptionMethod( IXceedEncryptDataPtr( piTwofish ) );
  118.  
  119.   // We use the templatized function TestSymmetricCipher, passing it the
  120.   // encryption object, the Twofish method and the path and file name containing
  121.   // the test vectors.
  122.   return TestSymmetricCipher<IXceedTwofishEncryptionMethodPtr>( piEnc, piTwofish, DATA_PATH "TwoFish.txt" );
  123. }
  124.  
  125. // --------------------------------------------------------------------------
  126. //
  127. // Test some SHA hash results
  128. //
  129. // --------------------------------------------------------------------------
  130. bool TestSHA( IXceedHashingPtr piHash )
  131. {
  132.   // Create an instance of the XceedSHAHashingMethod coclass
  133.   IXceedSHAHashingMethodPtr piSHA;
  134.   piSHA.CreateInstance( CLSID_XceedSHAHashingMethod );
  135.  
  136.   // Assign the hashing method created above to the hashing object
  137.   piHash->PutRefHashingMethod( IXceedHashDataPtr( piSHA ) );
  138.  
  139.   // We use the templatized function TestHash, passing it the
  140.   // encryption object, the SHA method and the path and file name containing
  141.   // the test vectors.
  142.   return TestHash<IXceedSHAHashingMethodPtr>( piHash, piSHA, DATA_PATH "SHA.txt" );
  143. }
  144.  
  145. // --------------------------------------------------------------------------
  146. //
  147. // Test some Haval hash results
  148. //
  149. // --------------------------------------------------------------------------
  150. bool TestHaval( IXceedHashingPtr piHash )
  151. {
  152.   // Create an instance of the XceedHavalHashingMethod coclass
  153.   IXceedHavalHashingMethodPtr piHav;
  154.   piHav.CreateInstance( CLSID_XceedHavalHashingMethod );
  155.  
  156.   // Assign the hashing method created above to the hashing object
  157.   piHash->PutRefHashingMethod( IXceedHashDataPtr( piHav ) );
  158.  
  159.   // We use the templatized function TestHash, passing it the
  160.   // encryption object, the Haval method and the path and file name containing
  161.   // the test vectors.
  162.   return TestHash<IXceedHavalHashingMethodPtr>( piHash, piHav, DATA_PATH "Haval.txt" );
  163. }
  164.  
  165. // --------------------------------------------------------------------------
  166. //
  167. // Generic function to test symmetric encryptions (Rijndael, Two-Fish)
  168. // This function assume that the different symmetric encryption method 
  169. // have the same interface.
  170. //
  171. // --------------------------------------------------------------------------
  172. template <typename T>
  173. bool TestSymmetricCipher( IXceedEncryptionPtr piEnc, 
  174.                           T piMethod, 
  175.                           const char* szFileName )
  176. {
  177.   bool bTestAllPassed = true;
  178.  
  179.   //Open the file containing the test vectors
  180.   HANDLE hFicIn = OpenTestVectorFile( szFileName );
  181.  
  182.   if( hFicIn != INVALID_HANDLE_VALUE )
  183.   {
  184.     BYTE  pcKey[MAX_KEY_SIZE];
  185.     short nKeySize = 0;
  186.     BYTE  pcPlainText[MAX_PLAIN_TEXT_SIZE];
  187.     DWORD dwPlainTextSize = 0;
  188.     BYTE  pcCipherText[MAX_CIPHER_TEXT_SIZE];
  189.     DWORD dwCipherTextSize = 0;
  190.     BYTE  pcInitVector[MAX_CIPHER_TEXT_SIZE];
  191.     short nInitVectorSize = 0;
  192.     int CptTest = 1;
  193.  
  194.     // Read each Test vector contained in the files. See the comment in the test
  195.     // vector files for more information.
  196.     while( ReadEncryptionTestVector( hFicIn, 
  197.                                      pcKey, &nKeySize, 
  198.                                      pcInitVector, &nInitVectorSize, 
  199.                                      pcPlainText, &dwPlainTextSize, 
  200.                                      pcCipherText, &dwCipherTextSize ) )
  201.     {
  202.       BYTE* pcEncrypted = NULL;
  203.       DWORD dwEncryptedSize = 0;
  204.       BYTE* pcDecrypted = NULL;
  205.       DWORD dwDecryptedSize = 0;
  206.       long lIdentical = FALSE;
  207.  
  208.       // Initialize the secret key read in the test vector file
  209.       piMethod->SetSecretKey( pcKey, nKeySize );
  210.       
  211.       if( nInitVectorSize > 0 )
  212.       {
  213.         // There was an InitVector in the test vector. Tell the encryption method that
  214.         // we are performing a CBC mode encryption and initialize the InitVector.
  215.         piMethod->EncryptionMode = emoChainedBlocks;
  216.         piMethod->SetInitVector( pcInitVector, nInitVectorSize );
  217.       }
  218.       else
  219.       {
  220.         // No initialization vector was provided in the current test vector. Tell
  221.         // the encryption method that we are performing a ECB mode encryption.
  222.         piMethod->EncryptionMode = emoFreeBlocks;
  223.       }
  224.       
  225.       // Encrypt the plain text
  226.       piEnc->Encrypt( pcPlainText, dwPlainTextSize, TRUE, &pcEncrypted, &dwEncryptedSize );
  227.       
  228.       if( nInitVectorSize > 0 )
  229.       {
  230.         // Compare the encrypted text produced by Xceed Encryption Library with
  231.         // the test vector cipher text. We ignore the first 128 bit (16 bytes) of the 
  232.         // encrypted text which contains the InitVector in the clear.
  233.         piEnc->Compare( pcEncrypted + 16, dwCipherTextSize, pcCipherText, dwCipherTextSize, &lIdentical );
  234.       }
  235.       else
  236.       {
  237.         // Compare the encrypted text produced by Xceed Encryption Library with
  238.         // the test vector cipher text.
  239.         piEnc->Compare( pcEncrypted, dwCipherTextSize, pcCipherText, dwCipherTextSize, &lIdentical );
  240.       }
  241.  
  242.       // Display the result of the comparison.
  243.       printf( "Test #%02d %s... Decryption ", CptTest, lIdentical ? "passed" : "failed" );
  244.  
  245.       if( !lIdentical )
  246.       {
  247.         bTestAllPassed = false;
  248.       }
  249.  
  250.       // Test the decrypt process
  251.       // Decrypt the cipher text
  252.       piEnc->Decrypt( pcEncrypted, dwEncryptedSize, TRUE, &pcDecrypted, &dwDecryptedSize );
  253.  
  254.       // Compare the decrypted text to the original plain text
  255.       piEnc->Compare( pcDecrypted, dwDecryptedSize, pcPlainText, dwPlainTextSize, &lIdentical );
  256.  
  257.       // Display the result of the comparison
  258.       printf( lIdentical ? "passed" : "failed" );
  259.       if( !lIdentical )
  260.       {
  261.         bTestAllPassed = false;
  262.       }
  263.  
  264.       // Free the memory allocated by the Xceed Encryption Library
  265.       CoTaskMemFree( pcEncrypted );
  266.       CoTaskMemFree( pcDecrypted );
  267.       printf( "\n" );
  268.       CptTest++;
  269.     }
  270.  
  271.     // Close the test vector file
  272.     CloseHandle( hFicIn );
  273.   }
  274.   else
  275.   {
  276.     printf( "Error opening test vector file\n" );
  277.     bTestAllPassed = false;
  278.   }
  279.  
  280.   return bTestAllPassed;
  281. }
  282.  
  283. // --------------------------------------------------------------------------
  284. //
  285. // Generic function to test hash function (SHA, Haval)
  286. // This function assume that the different symmetric encryption method 
  287. // have the same interface.
  288. //
  289. // --------------------------------------------------------------------------
  290. template <typename T>
  291. bool TestHash( IXceedHashingPtr piHash, 
  292.                T piMethod,
  293.                const char* szHashFileName )
  294. {
  295.   bool bTestAllPassed = true;
  296.  
  297.   //Open the file containing the test vectors
  298.   HANDLE hFicIn = OpenTestVectorFile( szHashFileName );
  299.  
  300.   if( hFicIn != INVALID_HANDLE_VALUE )
  301.   {
  302.     BYTE  pcMessage[MAX_MESSAGE_SIZE];
  303.     DWORD dwMessageSize = 0;
  304.     BYTE  pcDigest[MAX_MESSAGE_SIZE];
  305.     DWORD dwDigestSize = 0;
  306.     int CptTest = 1;
  307.  
  308.     // Read each Test vector contained in the files. See the comment in the test
  309.     // vector files for more information.
  310.     while( ReadTestVectorHash( hFicIn,  
  311.                                pcMessage, &dwMessageSize, 
  312.                                pcDigest, &dwDigestSize ) )
  313.     {
  314.       BYTE* pcHash = NULL;
  315.       short nHashSize = 0;
  316.       long lIdentical = FALSE;
  317.  
  318.       // Initialize the resulting hash size for the current test vector. The size
  319.       // is provided in bits to the Encryption Library; hence the "* 8".
  320.       piMethod->HashSize = static_cast<short>( dwDigestSize * 8 );
  321.  
  322.       // Hash the current test vector "message"
  323.       piHash->Hash( pcMessage, dwMessageSize, TRUE );
  324.  
  325.       // Extract the calculated hash value from the previous call
  326.       piMethod->GetHashValue( &pcHash, &nHashSize );
  327.  
  328.       // Compare the hash value calculated to the expected hash value of the
  329.       // current test vector.
  330.       piHash->Compare( pcDigest, dwDigestSize, pcHash, nHashSize, &lIdentical );
  331.  
  332.       // Display the comparison result
  333.       printf( "Test #%02d %s\n", CptTest, lIdentical ? "passed" : "failed" );
  334.  
  335.       if( !lIdentical )
  336.       {
  337.         bTestAllPassed = false;
  338.       }
  339.  
  340.       // Free the memory allocated by the Xceed Encryption Library
  341.       CoTaskMemFree( pcHash );
  342.       CptTest++;
  343.     }
  344.  
  345.     // Close the test vector file
  346.     CloseHandle( hFicIn );
  347.   }
  348.   else
  349.   {
  350.     printf( "Error opening test vector file\n" );
  351.     bTestAllPassed = false;
  352.   }
  353.  
  354.   return bTestAllPassed;
  355. }
  356.  
  357. // --------------------------------------------------------------------------
  358. //
  359. // Open the test vector file specified
  360. //
  361. // --------------------------------------------------------------------------
  362. HANDLE OpenTestVectorFile( const char* szFileName )
  363. {
  364.   HANDLE hFicIn = CreateFile( szFileName, GENERIC_READ, FILE_SHARE_WRITE & FILE_SHARE_READ, 
  365.                               NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  366.  
  367.   return hFicIn;
  368. }
  369.  
  370. // --------------------------------------------------------------------------
  371. //
  372. // Read a test vector from the specified encryption test vector file
  373. // returns true if succeeded.
  374. //
  375. // --------------------------------------------------------------------------
  376. bool ReadEncryptionTestVector( HANDLE hFicIn, 
  377.                                BYTE* pcKey, short* pnKeySize, 
  378.                                BYTE* pcInitVector, short* pnInitVectorSize, 
  379.                                BYTE* pcPlainText, DWORD* pdwPlainTextSize, 
  380.                                BYTE* pcCipherText, DWORD* pdwCipherTextSize )
  381. {
  382.   bool bVectorComplete = false;
  383.   bool bEndOfLine = false;
  384.   BYTE pcBuffer[BUFFER_SIZE] = "";
  385.   DWORD dwTotalRead = 0;
  386.   BYTE cByteRead;
  387.   DWORD dwRead = 0;
  388.   BYTE* pcBinaryBuffer = NULL;
  389.   DWORD dwBinaryBufferSize = 0;
  390.   
  391.   *pnKeySize = 0;
  392.   *pdwPlainTextSize = 0;
  393.   *pdwCipherTextSize = 0;
  394.   *pnInitVectorSize = 0;
  395.  
  396.   // Read one character at a time
  397.   while( ReadFile( hFicIn, &cByteRead, 1, &dwRead, NULL) && 
  398.          dwRead > 0 )
  399.   {
  400.     // Fill the buffer
  401.     if( dwTotalRead > sizeof( pcBuffer ) )
  402.     {
  403.       printf( "Buffer overflow while reading encryption test vector" );
  404.       break;
  405.     }
  406.  
  407.     if( cByteRead == 13 || cByteRead == 10 )
  408.     {
  409.       // We reach a end of line delimiter
  410.       bEndOfLine = true;
  411.     }
  412.     else
  413.     {
  414.       if( !bEndOfLine )
  415.       {
  416.         // The end of line is not reached already. We add the character
  417.         // read to the buffer.
  418.         pcBuffer[dwTotalRead] = cByteRead;
  419.         pcBuffer[dwTotalRead + 1] = '\0';
  420.         dwTotalRead++;
  421.       }
  422.       else
  423.       {
  424.         // The previous character(s) were end of line delimiter.
  425.         // We process the previous line read.
  426.         bEndOfLine = false;
  427.  
  428.         // We want to re-read the current character (the beginning of line)
  429.         // So we move the current file pointer to the previous character.
  430.         SetFilePointer( hFicIn, -1, 0, FILE_CURRENT );
  431.  
  432.         // We ignore blank lines
  433.         if( dwTotalRead > 0 )
  434.         {
  435.           if      ( pcBuffer[0] == '.' )
  436.           {
  437.             // We display this line skipping the beginning '.' which tell
  438.             // us that it's a comment line.
  439.             printf( "%s\n", pcBuffer + 1 );
  440.           }
  441.           else if ( pcBuffer[0] == 'k' && pcBuffer[1] == '=' )
  442.           {
  443.             // It's a secret key line
  444.             // Convert the hexadecimal representation of this key to a binary form
  445.             HexToBinary( (char*)(pcBuffer + 2), &pcBinaryBuffer, &dwBinaryBufferSize );
  446.             
  447.             // We return the secret key and the secret key size.
  448.             CopyMemory( pcKey, pcBinaryBuffer, dwBinaryBufferSize );
  449.             *pnKeySize = static_cast<short>(dwBinaryBufferSize);
  450.  
  451.             delete [] pcBinaryBuffer;
  452.           }
  453.           else if ( pcBuffer[0] == 'p' && pcBuffer[1] == '=' )
  454.           {
  455.             // It's a plain text line
  456.  
  457.             // Convert the hexadecimal representation of this key to a binary form
  458.             HexToBinary( (char*)(pcBuffer + 2), &pcBinaryBuffer, &dwBinaryBufferSize );
  459.  
  460.             // We return the plain text and the plain text size.
  461.             CopyMemory( pcPlainText, pcBinaryBuffer, dwBinaryBufferSize );
  462.             *pdwPlainTextSize = dwBinaryBufferSize;
  463.  
  464.             delete [] pcBinaryBuffer;
  465.           }
  466.           else if ( pcBuffer[0] == 'c' && pcBuffer[1] == '=' )
  467.           {
  468.             // It's a cipher text line
  469.  
  470.             // Convert the hexadecimal representation of this cipher text to a binary form
  471.             HexToBinary( (char*)(pcBuffer + 2), &pcBinaryBuffer, &dwBinaryBufferSize );
  472.  
  473.             // We return the cipher text and the cipher text size.
  474.             CopyMemory( pcCipherText, pcBinaryBuffer, dwBinaryBufferSize );
  475.             *pdwCipherTextSize = dwBinaryBufferSize;
  476.  
  477.             delete [] pcBinaryBuffer;
  478.           }
  479.           else if ( pcBuffer[0] == 'i' && pcBuffer[1] == '=' )
  480.           {
  481.             // It's a initialization vector line
  482.  
  483.             // Convert the hexadecimal representation of this InitVector to a binary form
  484.             HexToBinary( (char*)(pcBuffer + 2), &pcBinaryBuffer, &dwBinaryBufferSize );
  485.  
  486.             // We return the InitVector and the InitVector size.
  487.             CopyMemory( pcInitVector, pcBinaryBuffer, dwBinaryBufferSize );
  488.             *pnInitVectorSize = static_cast<short>(dwBinaryBufferSize);
  489.  
  490.             delete [] pcBinaryBuffer;
  491.           }
  492.         }
  493.  
  494.         // Clear the temporary buffer
  495.         dwTotalRead = 0;
  496.         pcBuffer[0] = '\0';
  497.  
  498.         if( *pnKeySize && *pdwPlainTextSize && *pdwCipherTextSize )
  499.         {
  500.           // So far, we have read the key, the plain text and the cipher
  501.           // text. We consider the test vector complete assuming that an
  502.           // initialization vector would have been read before.
  503.           bVectorComplete = true;
  504.           break;
  505.         }
  506.       }
  507.     }
  508.   }
  509.  
  510.   return bVectorComplete;
  511. }
  512.  
  513. // --------------------------------------------------------------------------
  514. //
  515. // Read a test vector from a Hash test vector file
  516. // returns true if succeeded.
  517. //
  518. // --------------------------------------------------------------------------
  519. bool   ReadTestVectorHash( HANDLE hFicIn, 
  520.                            BYTE* pcMessage, DWORD* pdwMessageSize, 
  521.                            BYTE* pcDigest, DWORD* pdwDigestSize )
  522. {
  523.   bool bVectorComplete = false;
  524.   bool bEndOfLine = false;
  525.   BYTE pcBuffer[MAX_MESSAGE_SIZE] = "";
  526.   DWORD dwTotalRead = 0;
  527.   BYTE cByteRead;
  528.   DWORD dwRead = 0;
  529.   
  530.   *pdwMessageSize = 0;
  531.   *pdwDigestSize = 0;
  532.  
  533.   // Read one character at a time
  534.   while( ReadFile( hFicIn, &cByteRead, 1, &dwRead, NULL) && 
  535.          dwRead > 0 )
  536.   {
  537.     // Fill the buffer
  538.     if( dwTotalRead > sizeof( pcBuffer ) )
  539.     {
  540.       printf( "Buffer overflow while reading hash test vector" );
  541.       break;
  542.     }
  543.  
  544.     if( cByteRead == 13 || cByteRead == 10 )
  545.     {
  546.       // We reach a end of line delimiter
  547.       bEndOfLine = true;
  548.     }
  549.     else
  550.     {
  551.       if( !bEndOfLine )
  552.       {
  553.         // The end of line is not reached already. We add the character
  554.         // read to the buffer.
  555.         pcBuffer[dwTotalRead] = cByteRead;
  556.         pcBuffer[dwTotalRead + 1] = '\0';
  557.         dwTotalRead++;
  558.       }
  559.       else
  560.       {
  561.         // The previous character(s) were end of line delimiter.
  562.         // We process the previous line read.
  563.         bEndOfLine = false;
  564.  
  565.         // We want to re-read the current character (the beginning of line)
  566.         // So we move the current file pointer to the previous character.
  567.         SetFilePointer( hFicIn, -1, 0, FILE_CURRENT );
  568.  
  569.         // We ignore blank lines
  570.         if( dwTotalRead > 0 )
  571.         {
  572.           if      ( pcBuffer[0] == '.' )
  573.           {
  574.             // We display this line skipping the beginning '.' which tell
  575.             // us that it's a comment line.
  576.             printf( "%s\n", pcBuffer + 1 );
  577.           }
  578.           else if ( pcBuffer[0] == 'm' && pcBuffer[1] == '=' )
  579.           {
  580.             // It's a "message" line (to hash)
  581.             // Return the message and the message size
  582.             lstrcpy( (char*)pcMessage, (char*)( pcBuffer + 2 ) );
  583.             *pdwMessageSize = lstrlen( (char*)pcMessage );
  584.           }
  585.           else if ( pcBuffer[0] == 'd' && pcBuffer[1] == '=' )
  586.           {
  587.             // It's a message digest line (expected hash value)
  588.             
  589.             BYTE* pcBinaryBuffer = NULL;
  590.             DWORD dwBinaryBufferSize = 0;
  591.  
  592.             // Convert the hexadecimal representation of this message digest 
  593.             // to a binary form
  594.             HexToBinary( (char*)(pcBuffer + 2), &pcBinaryBuffer, &dwBinaryBufferSize );
  595.  
  596.             // We return the message digest and the message digest size.
  597.             CopyMemory( pcDigest, pcBinaryBuffer, dwBinaryBufferSize );
  598.             *pdwDigestSize = dwBinaryBufferSize;
  599.  
  600.             delete [] pcBinaryBuffer;
  601.           }
  602.         }
  603.  
  604.         //Clear the temporary buffer
  605.         dwTotalRead = 0;
  606.         pcBuffer[0] = '\0';
  607.  
  608.         if( *pdwDigestSize && *pdwMessageSize )
  609.         {
  610.           // So far, we have read the message and the message digest
  611.           // We consider the test vector complete.
  612.           bVectorComplete = true;
  613.           break;
  614.         }
  615.       }
  616.     }
  617.   }
  618.  
  619.   return bVectorComplete;
  620. }
  621.  
  622. //------------------------------------------------------------------------------------
  623. // Convert a hexadecimal string to a byte array
  624. //------------------------------------------------------------------------------------
  625. void HexToBinary( LPCSTR sHexValue, BYTE** pcBinValue, DWORD* dwBinValueSize )
  626. {
  627.   long lHexLen = lstrlen( sHexValue );
  628.  
  629.   *pcBinValue = NULL;
  630.   *dwBinValueSize = 0;
  631.  
  632.   if( lHexLen > 0 )
  633.   {
  634.     *pcBinValue = new BYTE[ lHexLen / 2 + 1 ];
  635.     *dwBinValueSize = 0;
  636.  
  637.     long I = 0;
  638.     while( I < lstrlen( sHexValue ) )
  639.     {
  640.       int nTemp;
  641.  
  642.       sscanf( sHexValue + I, "%2x", &nTemp );
  643.       (*pcBinValue)[ *dwBinValueSize ] = (BYTE)nTemp;
  644.       (*dwBinValueSize)++;
  645.       I += 2;
  646.     }
  647.   }
  648. }
  649.  
  650.