Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:56 2009

## Asterisk developer's documentation

- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Directories

# sha1.c

Go to the documentation of this file.

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