1/*
2SHA-1 in C
3By Steve Reid <sreid@sea-to-sky.net>
4100% Public Domain
5
6-----------------
7Modified 7/98
8By James H. Brown <jbrown@burgoyne.com>
9Still 100% Public Domain
10
11Corrected a problem which generated improper hash values on 16 bit machines
12Routine SHA1Update changed from
13  void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
14len)
15to
16  void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
17long len)
18
19The 'len' parameter was declared an int which works fine on 32 bit machines.
20However, on 16 bit machines an int is too small for the shifts being done
21against
22it.  This caused the hash function to generate incorrect values if len was
23greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
24
25Since the file IO in main() reads 16K at a time, any file 8K or larger would
26be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
27"a"s).
28
29I also changed the declaration of variables i & j in SHA1Update to
30unsigned long from unsigned int for the same reason.
31
32These changes should make no difference to any 32 bit implementations since
33an
34int and a long are the same size in those environments.
35
36--
37I also corrected a few compiler warnings generated by Borland C.
381. Added #include <process.h> for exit() prototype
392. Removed unused variable 'j' in SHA1Final
403. Changed exit(0) to return(0) at end of main.
41
42ALL changes I made can be located by searching for comments containing 'JHB'
43-----------------
44Modified 8/98
45By Steve Reid <sreid@sea-to-sky.net>
46Still 100% public domain
47
481- Removed #include <process.h> and used return() instead of exit()
492- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
503- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
51
52-----------------
53Modified 4/01
54By Saul Kravitz <Saul.Kravitz@celera.com>
55Still 100% PD
56Modified to run on Compaq Alpha hardware.
57
58-----------------
59Modified 07/2002
60By Ralph Giles <giles@ghostscript.com>
61Still 100% public domain
62modified for use with stdint types, autoconf
63code cleanup, removed attribution comments
64switched SHA1Final() argument order for consistency
65use SHA1_ prefix for public api
66move public api to sha1.h
67*/
68
69/*
70Test Vectors (from FIPS PUB 180-1)
71"abc"
72  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
73"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
74  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
75A million repetitions of "a"
76  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
77*/
78
79#include <stdio.h>
80#include <string.h>
81#include <stdlib.h>
82
83#include "sha1.h"
84
85#if defined(_MSC_VER)
86#pragma warning(disable : 4267)
87#pragma warning(disable : 4996)
88#pragma warning(disable : 4100)
89#endif
90
91void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
92
93#define rol ROTL32
94
95/* blk0() and blk() perform the initial expand. */
96/* I got the idea of expanding during the round function from SSLeay */
97/* FIXME: can we do this in an endian-proof way? */
98
99#ifdef WORDS_BIGENDIAN
100#define blk0(i) block->l[i]
101#else
102#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) | (rol(block->l[i],8)&0x00FF00FF))
103#endif
104#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] ^ block->l[(i+2)&15]^block->l[i&15],1))
105
106/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
107#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
108#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
109#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
110#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
111#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
112
113
114/* Hash a single 512-bit block. This is the core of the algorithm. */
115void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
116{
117    uint32_t a, b, c, d, e;
118    typedef union {
119        uint8_t c[64];
120        uint32_t l[16];
121    } CHAR64LONG16;
122    CHAR64LONG16* block;
123
124    block = (CHAR64LONG16*)buffer;
125
126    /* Copy context->state[] to working vars */
127    a = state[0];
128    b = state[1];
129    c = state[2];
130    d = state[3];
131    e = state[4];
132
133    /* 4 rounds of 20 operations each. Loop unrolled. */
134    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
135    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
136    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
137    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
138    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
139    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
140    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
141    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
142    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
143    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
144    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
145    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
146    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
147    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
148    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
149    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
150    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
151    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
152    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
153    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
154
155    /* Add the working vars back into context.state[] */
156    state[0] += a;
157    state[1] += b;
158    state[2] += c;
159    state[3] += d;
160    state[4] += e;
161
162    /* Wipe variables */
163    a = b = c = d = e = 0;
164}
165
166
167/* SHA1Init - Initialize new context */
168void SHA1_Init(SHA1_CTX* context)
169{
170    /* SHA1 initialization constants */
171    context->state[0] = 0x67452301;
172    context->state[1] = 0xEFCDAB89;
173    context->state[2] = 0x98BADCFE;
174    context->state[3] = 0x10325476;
175    context->state[4] = 0xC3D2E1F0;
176    context->count[0] = 0;
177  context->count[1] = 0;
178}
179
180
181/* Run your data through this. */
182void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len)
183{
184    size_t i, j;
185
186    j = (context->count[0] >> 3) & 63;
187    if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
188
189    context->count[1] += (len >> 29);
190
191    if ((j + len) > 63)
192  {
193        memcpy(&context->buffer[j], data, (i = 64-j));
194        SHA1_Transform(context->state, context->buffer);
195
196        for ( ; i + 63 < len; i += 64)
197    {
198            SHA1_Transform(context->state, data + i);
199        }
200
201        j = 0;
202    }
203    else i = 0;
204    memcpy(&context->buffer[j], &data[i], len - i);
205}
206
207
208/* Add padding and return the message digest. */
209void SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST_SIZE])
210{
211    uint32_t i;
212    uint8_t  finalcount[8];
213
214    for (i = 0; i < 8; i++) {
215        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
216         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
217    }
218    SHA1_Update(context, (uint8_t *)"\200", 1);
219    while ((context->count[0] & 504) != 448) {
220        SHA1_Update(context, (uint8_t *)"\0", 1);
221    }
222    SHA1_Update(context, finalcount, 8);  /* Should cause a SHA1_Transform() */
223    for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
224        digest[i] = (uint8_t)
225         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
226    }
227
228    /* Wipe variables */
229    i = 0;
230    memset(context->buffer, 0, 64);
231    memset(context->state, 0, 20);
232    memset(context->count, 0, 8);
233    memset(finalcount, 0, 8);	/* SWR */
234}
235
236//-----------------------------------------------------------------------------
237
238void sha1_32a ( const void * key, int len, uint32_t seed, void * out )
239{
240  SHA1_CTX context;
241
242  uint8_t digest[20];
243
244  SHA1_Init(&context);
245  SHA1_Update(&context, (uint8_t*)key, len);
246  SHA1_Final(&context, digest);
247
248  memcpy(out,&digest[0],4);
249}
250
251//-----------------------------------------------------------------------------
252// self test
253
254//#define TEST
255
256#ifdef TEST
257
258static char *test_data[] = {
259    "abc",
260    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
261    "A million repetitions of 'a'"};
262static char *test_results[] = {
263    "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
264    "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1",
265    "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"};
266
267
268void digest_to_hex(const uint8_t digest[SHA1_DIGEST_SIZE], char *output)
269{
270    int i,j;
271    char *c = output;
272
273    for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) {
274        for (j = 0; j < 4; j++) {
275            sprintf(c,"%02X", digest[i*4+j]);
276            c += 2;
277        }
278        sprintf(c, " ");
279        c += 1;
280    }
281    *(c - 1) = '\0';
282}
283
284int main(int argc, char** argv)
285{
286    int k;
287    SHA1_CTX context;
288    uint8_t digest[20];
289    char output[80];
290
291    fprintf(stdout, "verifying SHA-1 implementation... ");
292
293    for (k = 0; k < 2; k++){
294        SHA1_Init(&context);
295        SHA1_Update(&context, (uint8_t*)test_data[k], strlen(test_data[k]));
296        SHA1_Final(&context, digest);
297  digest_to_hex(digest, output);
298
299        if (strcmp(output, test_results[k])) {
300            fprintf(stdout, "FAIL\n");
301            fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[k]);
302            fprintf(stderr,"\t%s returned\n", output);
303            fprintf(stderr,"\t%s is correct\n", test_results[k]);
304            return (1);
305        }
306    }
307    /* million 'a' vector we feed separately */
308    SHA1_Init(&context);
309    for (k = 0; k < 1000000; k++)
310        SHA1_Update(&context, (uint8_t*)"a", 1);
311    SHA1_Final(&context, digest);
312    digest_to_hex(digest, output);
313    if (strcmp(output, test_results[2])) {
314        fprintf(stdout, "FAIL\n");
315        fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[2]);
316        fprintf(stderr,"\t%s returned\n", output);
317        fprintf(stderr,"\t%s is correct\n", test_results[2]);
318        return (1);
319    }
320
321    /* success */
322    fprintf(stdout, "ok\n");
323    return(0);
324}
325#endif /* TEST */
326