TSP: The Transport Sample Protocol



Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

bb_sha1.c

00001 /*
00002  * This code has been taken from RFC 3174 on 
00003  * http://ww.rfc-editors.org/
00004  * File has been renamed to bb_sha1.[hc] to avoid name clash.
00005  * 
00006  *  sha1.c
00007  *
00008  *  Description:
00009  *      This file implements the Secure Hashing Algorithm 1 as
00010  *      defined in FIPS PUB 180-1 published April 17, 1995.
00011  *
00012  *      The SHA-1, produces a 160-bit message digest for a given
00013  *      data stream.  It should take about 2**n steps to find a
00014  *      message with the same digest as a given message and
00015  *      2**(n/2) to find any two messages with the same digest,
00016  *      when n is the digest size in bits.  Therefore, this
00017  *      algorithm can serve as a means of providing a
00018  *      "fingerprint" for a message.
00019  *
00020  *  Portability Issues:
00021  *      SHA-1 is defined in terms of 32-bit "words".  This code
00022  *      uses <stdint.h> (included via "sha1.h" to define 32 and 8
00023  *      bit unsigned integer types.  If your C compiler does not
00024  *      support 32 bit unsigned integers, this code is not
00025  *      appropriate.
00026  *
00027  *  Caveats:
00028  *      SHA-1 is designed to work with messages less than 2^64 bits
00029  *      long.  Although SHA-1 allows a message digest to be generated
00030  *      for messages of any number of bits less than 2^64, this
00031  *      implementation only works with messages with a length that is
00032  *      a multiple of the size of an 8-bit character.
00033  *
00034  */
00035 #include "bb_sha1.h"
00036 
00037 /*
00038  *  Define the SHA1 circular left shift macro
00039  */
00040 #define SHA1CircularShift(bits,word) \
00041                 (((word) << (bits)) | ((word) >> (32-(bits))))
00042 
00043 /* Local Function Prototyptes */
00044 void SHA1PadMessage(SHA1Context *);
00045 void SHA1ProcessMessageBlock(SHA1Context *);
00046 
00047 /*
00048  *  SHA1Reset
00049  *
00050  *  Description:
00051  *      This function will initialize the SHA1Context in preparation
00052  *      for computing a new SHA1 message digest.
00053  *
00054  *  Parameters:
00055  *      context: [in/out]
00056  *          The context to reset.
00057  *
00058  *  Returns:
00059  *      sha Error Code.
00060  *
00061  */
00062 int SHA1Reset(SHA1Context *context)
00063 {
00064     if (!context)
00065     {
00066         return shaNull;
00067     }
00068 
00069     context->Length_Low             = 0;
00070     context->Length_High            = 0;
00071     context->Message_Block_Index    = 0;
00072 
00073     context->Intermediate_Hash[0]   = 0x67452301;
00074     context->Intermediate_Hash[1]   = 0xEFCDAB89;
00075     context->Intermediate_Hash[2]   = 0x98BADCFE;
00076     context->Intermediate_Hash[3]   = 0x10325476;
00077     context->Intermediate_Hash[4]   = 0xC3D2E1F0;
00078 
00079     context->Computed   = 0;
00080     context->Corrupted  = 0;
00081 
00082     return shaSuccess;
00083 }
00084 
00085 /*
00086  *  SHA1Result
00087  *
00088  *  Description:
00089  *      This function will return the 160-bit message digest into the
00090  *      Message_Digest array  provided by the caller.
00091  *      NOTE: The first octet of hash is stored in the 0th element,
00092  *            the last octet of hash in the 19th element.
00093  *
00094  *  Parameters:
00095  *      context: [in/out]
00096  *          The context to use to calculate the SHA-1 hash.
00097  *      Message_Digest: [out]
00098  *          Where the digest is returned.
00099  *
00100  *  Returns:
00101  *      sha Error Code.
00102  *
00103  */
00104 int SHA1Result( SHA1Context *context,
00105                 uint8_t Message_Digest[SHA1HashSize])
00106 {
00107     int i;
00108 
00109     if (!context || !Message_Digest)
00110     {
00111         return shaNull;
00112     }
00113 
00114     if (context->Corrupted)
00115     {
00116         return context->Corrupted;
00117     }
00118 
00119     if (!context->Computed)
00120     {
00121         SHA1PadMessage(context);
00122         for(i=0; i<64; ++i)
00123         {
00124             /* message may be sensitive, clear it out */
00125             context->Message_Block[i] = 0;
00126         }
00127         context->Length_Low = 0;    /* and clear length */
00128         context->Length_High = 0;
00129         context->Computed = 1;
00130     }
00131 
00132     for(i = 0; i < SHA1HashSize; ++i)
00133     {
00134         Message_Digest[i] = context->Intermediate_Hash[i>>2]
00135                             >> 8 * ( 3 - ( i & 0x03 ) );
00136     }
00137 
00138     return shaSuccess;
00139 }
00140 
00141 /*
00142  *  SHA1Input
00143  *
00144  *  Description:
00145  *      This function accepts an array of octets as the next portion
00146  *      of the message.
00147  *
00148  *  Parameters:
00149  *      context: [in/out]
00150  *          The SHA context to update
00151  *      message_array: [in]
00152  *          An array of characters representing the next portion of
00153  *          the message.
00154  *      length: [in]
00155  *          The length of the message in message_array
00156  *
00157  *  Returns:
00158  *      sha Error Code.
00159  *
00160  */
00161 int SHA1Input(    SHA1Context    *context,
00162                   const uint8_t  *message_array,
00163                   unsigned       length)
00164 {
00165     if (!length)
00166     {
00167         return shaSuccess;
00168     }
00169 
00170     if (!context || !message_array)
00171     {
00172         return shaNull;
00173     }
00174 
00175     if (context->Computed)
00176     {
00177         context->Corrupted = shaStateError;
00178         return shaStateError;
00179     }
00180 
00181     if (context->Corrupted)
00182     {
00183          return context->Corrupted;
00184     }
00185     while(length-- && !context->Corrupted)
00186     {
00187     context->Message_Block[context->Message_Block_Index++] =
00188                     (*message_array & 0xFF);
00189 
00190     context->Length_Low += 8;
00191     if (context->Length_Low == 0)
00192     {
00193         context->Length_High++;
00194         if (context->Length_High == 0)
00195         {
00196             /* Message is too long */
00197             context->Corrupted = 1;
00198         }
00199     }
00200 
00201     if (context->Message_Block_Index == 64)
00202     {
00203         SHA1ProcessMessageBlock(context);
00204     }
00205 
00206     message_array++;
00207     }
00208 
00209     return shaSuccess;
00210 }
00211 
00212 /*
00213  *  SHA1ProcessMessageBlock
00214  *
00215  *  Description:
00216  *      This function will process the next 512 bits of the message
00217  *      stored in the Message_Block array.
00218  *
00219  *  Parameters:
00220  *      None.
00221  *
00222  *  Returns:
00223  *      Nothing.
00224  *
00225  *  Comments:
00226  *      Many of the variable names in this code, especially the
00227  *      single character names, were used because those were the
00228  *      names used in the publication.
00229  *
00230  *
00231  */
00232 void SHA1ProcessMessageBlock(SHA1Context *context)
00233 {
00234     const uint32_t K[] =    {       /* Constants defined in SHA-1   */
00235                             0x5A827999,
00236                             0x6ED9EBA1,
00237                             0x8F1BBCDC,
00238                             0xCA62C1D6
00239                             };
00240     int           t;                 /* Loop counter                */
00241     uint32_t      temp;              /* Temporary word value        */
00242     uint32_t      W[80];             /* Word sequence               */
00243     uint32_t      A, B, C, D, E;     /* Word buffers                */
00244 
00245     /*
00246      *  Initialize the first 16 words in the array W
00247      */
00248     for(t = 0; t < 16; t++)
00249     {
00250         W[t] = context->Message_Block[t * 4] << 24;
00251         W[t] |= context->Message_Block[t * 4 + 1] << 16;
00252         W[t] |= context->Message_Block[t * 4 + 2] << 8;
00253         W[t] |= context->Message_Block[t * 4 + 3];
00254     }
00255 
00256     for(t = 16; t < 80; t++)
00257     {
00258        W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
00259     }
00260 
00261     A = context->Intermediate_Hash[0];
00262     B = context->Intermediate_Hash[1];
00263     C = context->Intermediate_Hash[2];
00264     D = context->Intermediate_Hash[3];
00265     E = context->Intermediate_Hash[4];
00266 
00267     for(t = 0; t < 20; t++)
00268     {
00269         temp =  SHA1CircularShift(5,A) +
00270                 ((B & C) | ((~B) & D)) + E + W[t] + K[0];
00271         E = D;
00272         D = C;
00273         C = SHA1CircularShift(30,B);
00274         B = A;
00275         A = temp;
00276     }
00277 
00278     for(t = 20; t < 40; t++)
00279     {
00280         temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
00281         E = D;
00282         D = C;
00283         C = SHA1CircularShift(30,B);
00284         B = A;
00285         A = temp;
00286     }
00287 
00288     for(t = 40; t < 60; t++)
00289     {
00290         temp = SHA1CircularShift(5,A) +
00291                ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
00292         E = D;
00293         D = C;
00294         C = SHA1CircularShift(30,B);
00295         B = A;
00296         A = temp;
00297     }
00298 
00299     for(t = 60; t < 80; t++)
00300     {
00301         temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
00302         E = D;
00303         D = C;
00304         C = SHA1CircularShift(30,B);
00305         B = A;
00306         A = temp;
00307     }
00308 
00309     context->Intermediate_Hash[0] += A;
00310     context->Intermediate_Hash[1] += B;
00311     context->Intermediate_Hash[2] += C;
00312     context->Intermediate_Hash[3] += D;
00313     context->Intermediate_Hash[4] += E;
00314 
00315     context->Message_Block_Index = 0;
00316 }
00317 
00318 
00319 /*
00320  *  SHA1PadMessage
00321  *
00322  *  Description:
00323  *      According to the standard, the message must be padded to an even
00324  *      512 bits.  The first padding bit must be a '1'.  The last 64
00325  *      bits represent the length of the original message.  All bits in
00326  *      between should be 0.  This function will pad the message
00327  *      according to those rules by filling the Message_Block array
00328  *      accordingly.  It will also call the ProcessMessageBlock function
00329  *      provided appropriately.  When it returns, it can be assumed that
00330  *      the message digest has been computed.
00331  *
00332  *  Parameters:
00333  *      context: [in/out]
00334  *          The context to pad
00335  *      ProcessMessageBlock: [in]
00336  *          The appropriate SHA*ProcessMessageBlock function
00337  *  Returns:
00338  *      Nothing.
00339  *
00340  */
00341 
00342 void SHA1PadMessage(SHA1Context *context)
00343 {
00344     /*
00345      *  Check to see if the current message block is too small to hold
00346      *  the initial padding bits and length.  If so, we will pad the
00347      *  block, process it, and then continue padding into a second
00348      *  block.
00349      */
00350     if (context->Message_Block_Index > 55)
00351     {
00352         context->Message_Block[context->Message_Block_Index++] = 0x80;
00353         while(context->Message_Block_Index < 64)
00354         {
00355             context->Message_Block[context->Message_Block_Index++] = 0;
00356         }
00357 
00358         SHA1ProcessMessageBlock(context);
00359 
00360         while(context->Message_Block_Index < 56)
00361         {
00362             context->Message_Block[context->Message_Block_Index++] = 0;
00363         }
00364     }
00365     else
00366     {
00367         context->Message_Block[context->Message_Block_Index++] = 0x80;
00368         while(context->Message_Block_Index < 56)
00369         {
00370             context->Message_Block[context->Message_Block_Index++] = 0;
00371         }
00372     }
00373 
00374     /*
00375      *  Store the message length as the last 8 octets
00376      */
00377     context->Message_Block[56] = context->Length_High >> 24;
00378     context->Message_Block[57] = context->Length_High >> 16;
00379     context->Message_Block[58] = context->Length_High >> 8;
00380     context->Message_Block[59] = context->Length_High;
00381     context->Message_Block[60] = context->Length_Low >> 24;
00382     context->Message_Block[61] = context->Length_Low >> 16;
00383     context->Message_Block[62] = context->Length_Low >> 8;
00384     context->Message_Block[63] = context->Length_Low;
00385 
00386     SHA1ProcessMessageBlock(context);
00387 }
Framework Home Page.

Beware !! TSP wave is coming...