source: lib/sha1.c @ f68fd5f

3.0.2
Last change on this file since f68fd5f was 523fb23, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-08-11T08:08:39Z

Implement MSNP15 SSO (Sadistic Sign-On).

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