DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/mt32/sha1/sha1.cpp
00001 /*
00002  *  sha1.cpp
00003  *
00004  *  Copyright (C) 1998, 2009
00005  *  Paul E. Jones <paulej@packetizer.com>
00006  *  All Rights Reserved.
00007  *
00008  *****************************************************************************
00009  *  $Id: sha1.cpp 12 2009-06-22 19:34:25Z paulej $
00010  *****************************************************************************
00011  *
00012  *  Description:
00013  *      This class implements the Secure Hashing Standard as defined
00014  *      in FIPS PUB 180-1 published April 17, 1995.
00015  *
00016  *      The Secure Hashing Standard, which uses the Secure Hashing
00017  *      Algorithm (SHA), produces a 160-bit message digest for a
00018  *      given data stream.  In theory, it is highly improbable that
00019  *      two messages will produce the same message digest.  Therefore,
00020  *      this algorithm can serve as a means of providing a "fingerprint"
00021  *      for a message.
00022  *
00023  *  Portability Issues:
00024  *      SHA-1 is defined in terms of 32-bit "words".  This code was
00025  *      written with the expectation that the processor has at least
00026  *      a 32-bit machine word size.  If the machine word size is larger,
00027  *      the code should still function properly.  One caveat to that
00028  *      is that the input functions taking characters and character arrays
00029  *      assume that only 8 bits of information are stored in each character.
00030  *
00031  *  Caveats:
00032  *      SHA-1 is designed to work with messages less than 2^64 bits long.
00033  *      Although SHA-1 allows a message digest to be generated for
00034  *      messages of any number of bits less than 2^64, this implementation
00035  *      only works with messages with a length that is a multiple of 8
00036  *      bits.
00037  *
00038  */
00039 
00040 
00041 #include "sha1.h"
00042 
00043 /*  
00044  *  SHA1
00045  *
00046  *  Description:
00047  *      This is the constructor for the sha1 class.
00048  *
00049  *  Parameters:
00050  *      None.
00051  *
00052  *  Returns:
00053  *      Nothing.
00054  *
00055  *  Comments:
00056  *
00057  */
00058 SHA1::SHA1()
00059 {
00060     Reset();
00061 }
00062 
00063 /*  
00064  *  ~SHA1
00065  *
00066  *  Description:
00067  *      This is the destructor for the sha1 class
00068  *
00069  *  Parameters:
00070  *      None.
00071  *
00072  *  Returns:
00073  *      Nothing.
00074  *
00075  *  Comments:
00076  *
00077  */
00078 SHA1::~SHA1()
00079 {
00080     // The destructor does nothing
00081 }
00082 
00083 /*  
00084  *  Reset
00085  *
00086  *  Description:
00087  *      This function will initialize the sha1 class member variables
00088  *      in preparation for computing a new message digest.
00089  *
00090  *  Parameters:
00091  *      None.
00092  *
00093  *  Returns:
00094  *      Nothing.
00095  *
00096  *  Comments:
00097  *
00098  */
00099 void SHA1::Reset()
00100 {
00101     Length_Low          = 0;
00102     Length_High         = 0;
00103     Message_Block_Index = 0;
00104 
00105     H[0]        = 0x67452301;
00106     H[1]        = 0xEFCDAB89;
00107     H[2]        = 0x98BADCFE;
00108     H[3]        = 0x10325476;
00109     H[4]        = 0xC3D2E1F0;
00110 
00111     Computed    = false;
00112     Corrupted   = false;
00113 }
00114 
00115 /*  
00116  *  Result
00117  *
00118  *  Description:
00119  *      This function will return the 160-bit message digest into the
00120  *      array provided.
00121  *
00122  *  Parameters:
00123  *      message_digest_array: [out]
00124  *          This is an array of five unsigned integers which will be filled
00125  *          with the message digest that has been computed.
00126  *
00127  *  Returns:
00128  *      True if successful, false if it failed.
00129  *
00130  *  Comments:
00131  *
00132  */
00133 bool SHA1::Result(unsigned *message_digest_array)
00134 {
00135     int i;                                  // Counter
00136 
00137     if (Corrupted)
00138     {
00139         return false;
00140     }
00141 
00142     if (!Computed)
00143     {
00144         PadMessage();
00145         Computed = true;
00146     }
00147 
00148     for(i = 0; i < 5; i++)
00149     {
00150         message_digest_array[i] = H[i];
00151     }
00152 
00153     return true;
00154 }
00155 
00156 /*  
00157  *  Input
00158  *
00159  *  Description:
00160  *      This function accepts an array of octets as the next portion of
00161  *      the message.
00162  *
00163  *  Parameters:
00164  *      message_array: [in]
00165  *          An array of characters representing the next portion of the
00166  *          message.
00167  *
00168  *  Returns:
00169  *      Nothing.
00170  *
00171  *  Comments:
00172  *
00173  */
00174 void SHA1::Input(   const unsigned char *message_array,
00175                     unsigned            length)
00176 {
00177     if (!length)
00178     {
00179         return;
00180     }
00181 
00182     if (Computed || Corrupted)
00183     {
00184         Corrupted = true;
00185         return;
00186     }
00187 
00188     while(length-- && !Corrupted)
00189     {
00190         Message_Block[Message_Block_Index++] = (*message_array & 0xFF);
00191 
00192         Length_Low += 8;
00193         Length_Low &= 0xFFFFFFFF;               // Force it to 32 bits
00194         if (Length_Low == 0)
00195         {
00196             Length_High++;
00197             Length_High &= 0xFFFFFFFF;          // Force it to 32 bits
00198             if (Length_High == 0)
00199             {
00200                 Corrupted = true;               // Message is too long
00201             }
00202         }
00203 
00204         if (Message_Block_Index == 64)
00205         {
00206             ProcessMessageBlock();
00207         }
00208 
00209         message_array++;
00210     }
00211 }
00212 
00213 /*  
00214  *  Input
00215  *
00216  *  Description:
00217  *      This function accepts an array of octets as the next portion of
00218  *      the message.
00219  *
00220  *  Parameters:
00221  *      message_array: [in]
00222  *          An array of characters representing the next portion of the
00223  *          message.
00224  *      length: [in]
00225  *          The length of the message_array
00226  *
00227  *  Returns:
00228  *      Nothing.
00229  *
00230  *  Comments:
00231  *
00232  */
00233 void SHA1::Input(   const char  *message_array,
00234                     unsigned    length)
00235 {
00236     Input((unsigned char *) message_array, length);
00237 }
00238 
00239 /*  
00240  *  Input
00241  *
00242  *  Description:
00243  *      This function accepts a single octets as the next message element.
00244  *
00245  *  Parameters:
00246  *      message_element: [in]
00247  *          The next octet in the message.
00248  *
00249  *  Returns:
00250  *      Nothing.
00251  *
00252  *  Comments:
00253  *
00254  */
00255 void SHA1::Input(unsigned char message_element)
00256 {
00257     Input(&message_element, 1);
00258 }
00259 
00260 /*  
00261  *  Input
00262  *
00263  *  Description:
00264  *      This function accepts a single octet as the next message element.
00265  *
00266  *  Parameters:
00267  *      message_element: [in]
00268  *          The next octet in the message.
00269  *
00270  *  Returns:
00271  *      Nothing.
00272  *
00273  *  Comments:
00274  *
00275  */
00276 void SHA1::Input(char message_element)
00277 {
00278     Input((unsigned char *) &message_element, 1);
00279 }
00280 
00281 /*  
00282  *  operator<<
00283  *
00284  *  Description:
00285  *      This operator makes it convenient to provide character strings to
00286  *      the SHA1 object for processing.
00287  *
00288  *  Parameters:
00289  *      message_array: [in]
00290  *          The character array to take as input.
00291  *
00292  *  Returns:
00293  *      A reference to the SHA1 object.
00294  *
00295  *  Comments:
00296  *      Each character is assumed to hold 8 bits of information.
00297  *
00298  */
00299 SHA1& SHA1::operator<<(const char *message_array)
00300 {
00301     const char *p = message_array;
00302 
00303     while(*p)
00304     {
00305         Input(*p);
00306         p++;
00307     }
00308 
00309     return *this;
00310 }
00311 
00312 /*  
00313  *  operator<<
00314  *
00315  *  Description:
00316  *      This operator makes it convenient to provide character strings to
00317  *      the SHA1 object for processing.
00318  *
00319  *  Parameters:
00320  *      message_array: [in]
00321  *          The character array to take as input.
00322  *
00323  *  Returns:
00324  *      A reference to the SHA1 object.
00325  *
00326  *  Comments:
00327  *      Each character is assumed to hold 8 bits of information.
00328  *
00329  */
00330 SHA1& SHA1::operator<<(const unsigned char *message_array)
00331 {
00332     const unsigned char *p = message_array;
00333 
00334     while(*p)
00335     {
00336         Input(*p);
00337         p++;
00338     }
00339 
00340     return *this;
00341 }
00342 
00343 /*  
00344  *  operator<<
00345  *
00346  *  Description:
00347  *      This function provides the next octet in the message.
00348  *
00349  *  Parameters:
00350  *      message_element: [in]
00351  *          The next octet in the message
00352  *
00353  *  Returns:
00354  *      A reference to the SHA1 object.
00355  *
00356  *  Comments:
00357  *      The character is assumed to hold 8 bits of information.
00358  *
00359  */
00360 SHA1& SHA1::operator<<(const char message_element)
00361 {
00362     Input((unsigned char *) &message_element, 1);
00363 
00364     return *this;
00365 }
00366 
00367 /*  
00368  *  operator<<
00369  *
00370  *  Description:
00371  *      This function provides the next octet in the message.
00372  *
00373  *  Parameters:
00374  *      message_element: [in]
00375  *          The next octet in the message
00376  *
00377  *  Returns:
00378  *      A reference to the SHA1 object.
00379  *
00380  *  Comments:
00381  *      The character is assumed to hold 8 bits of information.
00382  *
00383  */
00384 SHA1& SHA1::operator<<(const unsigned char message_element)
00385 {
00386     Input(&message_element, 1);
00387 
00388     return *this;
00389 }
00390 
00391 /*  
00392  *  ProcessMessageBlock
00393  *
00394  *  Description:
00395  *      This function will process the next 512 bits of the message
00396  *      stored in the Message_Block array.
00397  *
00398  *  Parameters:
00399  *      None.
00400  *
00401  *  Returns:
00402  *      Nothing.
00403  *
00404  *  Comments:
00405  *      Many of the variable names in this function, especially the single
00406  *      character names, were used because those were the names used
00407  *      in the publication.
00408  *
00409  */
00410 void SHA1::ProcessMessageBlock()
00411 {
00412     const unsigned K[] =    {               // Constants defined for SHA-1
00413                                 0x5A827999,
00414                                 0x6ED9EBA1,
00415                                 0x8F1BBCDC,
00416                                 0xCA62C1D6
00417                             };
00418     int         t;                          // Loop counter
00419     unsigned    temp;                       // Temporary word value
00420     unsigned    W[80];                      // Word sequence
00421     unsigned    A, B, C, D, E;              // Word buffers
00422 
00423     /*
00424      *  Initialize the first 16 words in the array W
00425      */
00426     for(t = 0; t < 16; t++)
00427     {
00428         W[t] = ((unsigned) Message_Block[t * 4]) << 24;
00429         W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
00430         W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
00431         W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
00432     }
00433 
00434     for(t = 16; t < 80; t++)
00435     {
00436        W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
00437     }
00438 
00439     A = H[0];
00440     B = H[1];
00441     C = H[2];
00442     D = H[3];
00443     E = H[4];
00444 
00445     for(t = 0; t < 20; t++)
00446     {
00447         temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
00448         temp &= 0xFFFFFFFF;
00449         E = D;
00450         D = C;
00451         C = CircularShift(30,B);
00452         B = A;
00453         A = temp;
00454     }
00455 
00456     for(t = 20; t < 40; t++)
00457     {
00458         temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
00459         temp &= 0xFFFFFFFF;
00460         E = D;
00461         D = C;
00462         C = CircularShift(30,B);
00463         B = A;
00464         A = temp;
00465     }
00466 
00467     for(t = 40; t < 60; t++)
00468     {
00469         temp = CircularShift(5,A) +
00470                ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
00471         temp &= 0xFFFFFFFF;
00472         E = D;
00473         D = C;
00474         C = CircularShift(30,B);
00475         B = A;
00476         A = temp;
00477     }
00478 
00479     for(t = 60; t < 80; t++)
00480     {
00481         temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
00482         temp &= 0xFFFFFFFF;
00483         E = D;
00484         D = C;
00485         C = CircularShift(30,B);
00486         B = A;
00487         A = temp;
00488     }
00489 
00490     H[0] = (H[0] + A) & 0xFFFFFFFF;
00491     H[1] = (H[1] + B) & 0xFFFFFFFF;
00492     H[2] = (H[2] + C) & 0xFFFFFFFF;
00493     H[3] = (H[3] + D) & 0xFFFFFFFF;
00494     H[4] = (H[4] + E) & 0xFFFFFFFF;
00495 
00496     Message_Block_Index = 0;
00497 }
00498 
00499 /*  
00500  *  PadMessage
00501  *
00502  *  Description:
00503  *      According to the standard, the message must be padded to an even
00504  *      512 bits.  The first padding bit must be a '1'.  The last 64 bits
00505  *      represent the length of the original message.  All bits in between
00506  *      should be 0.  This function will pad the message according to those
00507  *      rules by filling the message_block array accordingly.  It will also
00508  *      call ProcessMessageBlock() appropriately.  When it returns, it
00509  *      can be assumed that the message digest has been computed.
00510  *
00511  *  Parameters:
00512  *      None.
00513  *
00514  *  Returns:
00515  *      Nothing.
00516  *
00517  *  Comments:
00518  *
00519  */
00520 void SHA1::PadMessage()
00521 {
00522     /*
00523      *  Check to see if the current message block is too small to hold
00524      *  the initial padding bits and length.  If so, we will pad the
00525      *  block, process it, and then continue padding into a second block.
00526      */
00527     if (Message_Block_Index > 55)
00528     {
00529         Message_Block[Message_Block_Index++] = 0x80;
00530         while(Message_Block_Index < 64)
00531         {
00532             Message_Block[Message_Block_Index++] = 0;
00533         }
00534 
00535         ProcessMessageBlock();
00536 
00537         while(Message_Block_Index < 56)
00538         {
00539             Message_Block[Message_Block_Index++] = 0;
00540         }
00541     }
00542     else
00543     {
00544         Message_Block[Message_Block_Index++] = 0x80;
00545         while(Message_Block_Index < 56)
00546         {
00547             Message_Block[Message_Block_Index++] = 0;
00548         }
00549 
00550     }
00551 
00552     /*
00553      *  Store the message length as the last 8 octets
00554      */
00555     Message_Block[56] = (Length_High >> 24) & 0xFF;
00556     Message_Block[57] = (Length_High >> 16) & 0xFF;
00557     Message_Block[58] = (Length_High >> 8) & 0xFF;
00558     Message_Block[59] = (Length_High) & 0xFF;
00559     Message_Block[60] = (Length_Low >> 24) & 0xFF;
00560     Message_Block[61] = (Length_Low >> 16) & 0xFF;
00561     Message_Block[62] = (Length_Low >> 8) & 0xFF;
00562     Message_Block[63] = (Length_Low) & 0xFF;
00563 
00564     ProcessMessageBlock();
00565 }
00566 
00567 
00568 /*  
00569  *  CircularShift
00570  *
00571  *  Description:
00572  *      This member function will perform a circular shifting operation.
00573  *
00574  *  Parameters:
00575  *      bits: [in]
00576  *          The number of bits to shift (1-31)
00577  *      word: [in]
00578  *          The value to shift (assumes a 32-bit integer)
00579  *
00580  *  Returns:
00581  *      The shifted value.
00582  *
00583  *  Comments:
00584  *
00585  */
00586 unsigned SHA1::CircularShift(int bits, unsigned word)
00587 {
00588     return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits));
00589 }