more handlers

Dependents:   bandwidth-meter-net mbedRail24v

Fork of Tiny-HTTPD by ban4jp -

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sha1.cpp Source File

sha1.cpp

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