root / trunk / util / sha1.c

Revision 302, 10.4 kB (checked in by saurik, 5 months ago)

Replaced codesign with ldid -S.

Line 
1/*
2 *  sha1.c
3 *
4 *  Description:
5 *      This file implements the Secure Hashing Algorithm 1 as
6 *      defined in FIPS PUB 180-1 published April 17, 1995.
7 *
8 *      The SHA-1, produces a 160-bit message digest for a given
9 *      data stream.  It should take about 2**n steps to find a
10 *      message with the same digest as a given message and
11 *      2**(n/2) to find any two messages with the same digest,
12 *      when n is the digest size in bits.  Therefore, this
13 *      algorithm can serve as a means of providing a
14 *      "fingerprint" for a message.
15 *
16 *  Portability Issues:
17 *      SHA-1 is defined in terms of 32-bit "words".  This code
18 *      uses <stdint.h> (included via "sha1.h" to define 32 and 8
19 *      bit unsigned integer types.  If your C compiler does not
20 *      support 32 bit unsigned integers, this code is not
21 *      appropriate.
22 *
23 *  Caveats:
24 *      SHA-1 is designed to work with messages less than 2^64 bits
25 *      long.  Although SHA-1 allows a message digest to be generated
26 *      for messages of any number of bits less than 2^64, this
27 *      implementation only works with messages with a length that is
28 *      a multiple of the size of an 8-bit character.
29 *
30 */
31
32#include "sha1.h"
33
34/*
35 *  Define the SHA1 circular left shift macro
36 */
37#define SHA1CircularShift(bits,word) \
38                (((word) << (bits)) | ((word) >> (32-(bits))))
39
40/* Local Function Prototyptes */
41void SHA1PadMessage(SHA1Context *);
42void SHA1ProcessMessageBlock(SHA1Context *);
43
44/*
45 *  SHA1Reset
46 *
47 *  Description:
48 *      This function will initialize the SHA1Context in preparation
49 *      for computing a new SHA1 message digest.
50 *
51 *  Parameters:
52 *      context: [in/out]
53 *          The context to reset.
54 *
55 *  Returns:
56 *      sha Error Code.
57 *
58 */
59int SHA1Reset(SHA1Context *context)
60{
61    if (!context)
62    {
63        return shaNull;
64    }
65
66    context->Length_Low             = 0;
67    context->Length_High            = 0;
68    context->Message_Block_Index    = 0;
69
70    context->Intermediate_Hash[0]   = 0x67452301;
71    context->Intermediate_Hash[1]   = 0xEFCDAB89;
72    context->Intermediate_Hash[2]   = 0x98BADCFE;
73    context->Intermediate_Hash[3]   = 0x10325476;
74    context->Intermediate_Hash[4]   = 0xC3D2E1F0;
75
76    context->Computed   = 0;
77    context->Corrupted  = 0;
78
79    return shaSuccess;
80}
81
82/*
83 *  SHA1Result
84 *
85 *  Description:
86 *      This function will return the 160-bit message digest into the
87 *      Message_Digest array  provided by the caller.
88 *      NOTE: The first octet of hash is stored in the 0th element,
89 *            the last octet of hash in the 19th element.
90 *
91 *  Parameters:
92 *      context: [in/out]
93 *          The context to use to calculate the SHA-1 hash.
94 *      Message_Digest: [out]
95 *          Where the digest is returned.
96 *
97 *  Returns:
98 *      sha Error Code.
99 *
100 */
101int SHA1Result( SHA1Context *context,
102                uint8_t Message_Digest[SHA1HashSize])
103{
104    int i;
105
106    if (!context || !Message_Digest)
107    {
108        return shaNull;
109    }
110
111    if (context->Corrupted)
112    {
113        return context->Corrupted;
114    }
115
116    if (!context->Computed)
117    {
118        SHA1PadMessage(context);
119        for(i=0; i<64; ++i)
120        {
121            /* message may be sensitive, clear it out */
122            context->Message_Block[i] = 0;
123        }
124        context->Length_Low = 0;    /* and clear length */
125        context->Length_High = 0;
126        context->Computed = 1;
127
128    }
129
130    for(i = 0; i < SHA1HashSize; ++i)
131    {
132        Message_Digest[i] = context->Intermediate_Hash[i>>2]
133                            >> 8 * ( 3 - ( i & 0x03 ) );
134    }
135
136    return shaSuccess;
137}
138
139/*
140 *  SHA1Input
141 *
142 *  Description:
143 *      This function accepts an array of octets as the next portion
144 *      of the message.
145 *
146 *  Parameters:
147 *      context: [in/out]
148 *          The SHA context to update
149 *      message_array: [in]
150 *          An array of characters representing the next portion of
151 *          the message.
152 *      length: [in]
153 *          The length of the message in message_array
154 *
155 *  Returns:
156 *      sha Error Code.
157 *
158 */
159int SHA1Input(    SHA1Context    *context,
160                  const uint8_t  *message_array,
161                  unsigned       length)
162{
163    if (!length)
164    {
165        return shaSuccess;
166    }
167
168    if (!context || !message_array)
169    {
170        return shaNull;
171    }
172
173    if (context->Computed)
174    {
175        context->Corrupted = shaStateError;
176
177        return shaStateError;
178    }
179
180    if (context->Corrupted)
181    {
182         return context->Corrupted;
183    }
184    while(length-- && !context->Corrupted)
185    {
186    context->Message_Block[context->Message_Block_Index++] =
187                    (*message_array & 0xFF);
188
189    context->Length_Low += 8;
190    if (context->Length_Low == 0)
191    {
192        context->Length_High++;
193        if (context->Length_High == 0)
194        {
195            /* Message is too long */
196            context->Corrupted = 1;
197        }
198    }
199
200    if (context->Message_Block_Index == 64)
201    {
202        SHA1ProcessMessageBlock(context);
203    }
204
205    message_array++;
206    }
207
208    return shaSuccess;
209}
210
211/*
212 *  SHA1ProcessMessageBlock
213 *
214 *  Description:
215 *      This function will process the next 512 bits of the message
216 *      stored in the Message_Block array.
217 *
218 *  Parameters:
219 *      None.
220 *
221 *  Returns:
222 *      Nothing.
223 *
224 *  Comments:
225
226 *      Many of the variable names in this code, especially the
227 *      single character names, were used because those were the
228 *      names used in the publication.
229 *
230 *
231 */
232void SHA1ProcessMessageBlock(SHA1Context *context)
233{
234    const uint32_t K[] =    {       /* Constants defined in SHA-1   */
235                            0x5A827999,
236                            0x6ED9EBA1,
237                            0x8F1BBCDC,
238                            0xCA62C1D6
239                            };
240    int           t;                 /* Loop counter                */
241    uint32_t      temp;              /* Temporary word value        */
242    uint32_t      W[80];             /* Word sequence               */
243    uint32_t      A, B, C, D, E;     /* Word buffers                */
244
245    /*
246     *  Initialize the first 16 words in the array W
247     */
248    for(t = 0; t < 16; t++)
249    {
250        W[t] = context->Message_Block[t * 4] << 24;
251        W[t] |= context->Message_Block[t * 4 + 1] << 16;
252        W[t] |= context->Message_Block[t * 4 + 2] << 8;
253        W[t] |= context->Message_Block[t * 4 + 3];
254    }
255
256    for(t = 16; t < 80; t++)
257    {
258       W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
259    }
260
261    A = context->Intermediate_Hash[0];
262    B = context->Intermediate_Hash[1];
263    C = context->Intermediate_Hash[2];
264    D = context->Intermediate_Hash[3];
265    E = context->Intermediate_Hash[4];
266
267    for(t = 0; t < 20; t++)
268    {
269        temp =  SHA1CircularShift(5,A) +
270                ((B & C) | ((~B) & D)) + E + W[t] + K[0];
271        E = D;
272        D = C;
273        C = SHA1CircularShift(30,B);
274
275        B = A;
276        A = temp;
277    }
278
279    for(t = 20; t < 40; t++)
280    {
281        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
282        E = D;
283        D = C;
284        C = SHA1CircularShift(30,B);
285        B = A;
286        A = temp;
287    }
288
289    for(t = 40; t < 60; t++)
290    {
291        temp = SHA1CircularShift(5,A) +
292               ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
293        E = D;
294        D = C;
295        C = SHA1CircularShift(30,B);
296        B = A;
297        A = temp;
298    }
299
300    for(t = 60; t < 80; t++)
301    {
302        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
303        E = D;
304        D = C;
305        C = SHA1CircularShift(30,B);
306        B = A;
307        A = temp;
308    }
309
310    context->Intermediate_Hash[0] += A;
311    context->Intermediate_Hash[1] += B;
312    context->Intermediate_Hash[2] += C;
313    context->Intermediate_Hash[3] += D;
314    context->Intermediate_Hash[4] += E;
315
316    context->Message_Block_Index = 0;
317}
318
319/*
320 *  SHA1PadMessage
321 *
322
323 *  Description:
324 *      According to the standard, the message must be padded to an even
325 *      512 bits.  The first padding bit must be a '1'.  The last 64
326 *      bits represent the length of the original message.  All bits in
327 *      between should be 0.  This function will pad the message
328 *      according to those rules by filling the Message_Block array
329 *      accordingly.  It will also call the ProcessMessageBlock function
330 *      provided appropriately.  When it returns, it can be assumed that
331 *      the message digest has been computed.
332 *
333 *  Parameters:
334 *      context: [in/out]
335 *          The context to pad
336 *      ProcessMessageBlock: [in]
337 *          The appropriate SHA*ProcessMessageBlock function
338 *  Returns:
339 *      Nothing.
340 *
341 */
342
343void SHA1PadMessage(SHA1Context *context)
344{
345    /*
346     *  Check to see if the current message block is too small to hold
347     *  the initial padding bits and length.  If so, we will pad the
348     *  block, process it, and then continue padding into a second
349     *  block.
350     */
351    if (context->Message_Block_Index > 55)
352    {
353        context->Message_Block[context->Message_Block_Index++] = 0x80;
354        while(context->Message_Block_Index < 64)
355        {
356            context->Message_Block[context->Message_Block_Index++] = 0;
357        }
358
359        SHA1ProcessMessageBlock(context);
360
361        while(context->Message_Block_Index < 56)
362        {
363            context->Message_Block[context->Message_Block_Index++] = 0;
364        }
365    }
366    else
367    {
368        context->Message_Block[context->Message_Block_Index++] = 0x80;
369        while(context->Message_Block_Index < 56)
370        {
371
372            context->Message_Block[context->Message_Block_Index++] = 0;
373        }
374    }
375
376    /*
377     *  Store the message length as the last 8 octets
378     */
379    context->Message_Block[56] = context->Length_High >> 24;
380    context->Message_Block[57] = context->Length_High >> 16;
381    context->Message_Block[58] = context->Length_High >> 8;
382    context->Message_Block[59] = context->Length_High;
383    context->Message_Block[60] = context->Length_Low >> 24;
384    context->Message_Block[61] = context->Length_Low >> 16;
385    context->Message_Block[62] = context->Length_Low >> 8;
386    context->Message_Block[63] = context->Length_Low;
387
388    SHA1ProcessMessageBlock(context);
389}
Note: See TracBrowser for help on using the browser.