source: bootcd/isolinux/syslinux-6.03/com32/libutil/sha1hash.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 10.0 KB
Line 
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 2/03
60By H. Peter Anvin <hpa@zytor.com>
61Still 100% PD
62Modified to run on any hardware with <inttypes.h> and <netinet/in.h>
63Changed the driver program
64
65*/
66
67/*
68Test Vectors (from FIPS PUB 180-1)
69"abc"
70  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
71"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
72  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
73A million repetitions of "a"
74  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
75*/
76
77/* #define SHA1HANDSOFF  */
78
79#include <stdio.h>
80#include <string.h>
81#include <inttypes.h>
82#include <netinet/in.h>         /* For htonl/ntohl/htons/ntohs */
83
84#include "sha1.h"
85
86#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
87
88/* blk0() and blk() perform the initial expand. */
89/* I got the idea of expanding during the round function from SSLeay */
90#define blk0(i) (block->l[i] = ntohl(block->l[i]))
91#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
92    ^block->l[(i+2)&15]^block->l[i&15],1))
93
94/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
95#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
96#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
97#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
98#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
99#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
100
101#ifdef VERBOSE                  /* SAK */
102void SHAPrintContext(SHA1_CTX * context, char *msg)
103{
104    printf("%s (%d,%d) %x %x %x %x %x\n",
105           msg,
106           context->count[0], context->count[1],
107           context->state[0],
108           context->state[1],
109           context->state[2], context->state[3], context->state[4]);
110}
111#endif
112
113/* Hash a single 512-bit block. This is the core of the algorithm. */
114
115void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
116{
117    uint32_t a, b, c, d, e;
118    typedef union {
119        unsigned char c[64];
120        uint32_t l[16];
121    } CHAR64LONG16;
122    CHAR64LONG16 *block;
123#ifdef SHA1HANDSOFF
124    static unsigned char workspace[64];
125    block = (CHAR64LONG16 *) workspace;
126    memcpy(block, buffer, 64);
127#else
128    block = (CHAR64LONG16 *) buffer;
129#endif
130    /* Copy context->state[] to working vars */
131    a = state[0];
132    b = state[1];
133    c = state[2];
134    d = state[3];
135    e = state[4];
136    /* 4 rounds of 20 operations each. Loop unrolled. */
137    R0(a, b, c, d, e, 0);
138    R0(e, a, b, c, d, 1);
139    R0(d, e, a, b, c, 2);
140    R0(c, d, e, a, b, 3);
141    R0(b, c, d, e, a, 4);
142    R0(a, b, c, d, e, 5);
143    R0(e, a, b, c, d, 6);
144    R0(d, e, a, b, c, 7);
145    R0(c, d, e, a, b, 8);
146    R0(b, c, d, e, a, 9);
147    R0(a, b, c, d, e, 10);
148    R0(e, a, b, c, d, 11);
149    R0(d, e, a, b, c, 12);
150    R0(c, d, e, a, b, 13);
151    R0(b, c, d, e, a, 14);
152    R0(a, b, c, d, e, 15);
153    R1(e, a, b, c, d, 16);
154    R1(d, e, a, b, c, 17);
155    R1(c, d, e, a, b, 18);
156    R1(b, c, d, e, a, 19);
157    R2(a, b, c, d, e, 20);
158    R2(e, a, b, c, d, 21);
159    R2(d, e, a, b, c, 22);
160    R2(c, d, e, a, b, 23);
161    R2(b, c, d, e, a, 24);
162    R2(a, b, c, d, e, 25);
163    R2(e, a, b, c, d, 26);
164    R2(d, e, a, b, c, 27);
165    R2(c, d, e, a, b, 28);
166    R2(b, c, d, e, a, 29);
167    R2(a, b, c, d, e, 30);
168    R2(e, a, b, c, d, 31);
169    R2(d, e, a, b, c, 32);
170    R2(c, d, e, a, b, 33);
171    R2(b, c, d, e, a, 34);
172    R2(a, b, c, d, e, 35);
173    R2(e, a, b, c, d, 36);
174    R2(d, e, a, b, c, 37);
175    R2(c, d, e, a, b, 38);
176    R2(b, c, d, e, a, 39);
177    R3(a, b, c, d, e, 40);
178    R3(e, a, b, c, d, 41);
179    R3(d, e, a, b, c, 42);
180    R3(c, d, e, a, b, 43);
181    R3(b, c, d, e, a, 44);
182    R3(a, b, c, d, e, 45);
183    R3(e, a, b, c, d, 46);
184    R3(d, e, a, b, c, 47);
185    R3(c, d, e, a, b, 48);
186    R3(b, c, d, e, a, 49);
187    R3(a, b, c, d, e, 50);
188    R3(e, a, b, c, d, 51);
189    R3(d, e, a, b, c, 52);
190    R3(c, d, e, a, b, 53);
191    R3(b, c, d, e, a, 54);
192    R3(a, b, c, d, e, 55);
193    R3(e, a, b, c, d, 56);
194    R3(d, e, a, b, c, 57);
195    R3(c, d, e, a, b, 58);
196    R3(b, c, d, e, a, 59);
197    R4(a, b, c, d, e, 60);
198    R4(e, a, b, c, d, 61);
199    R4(d, e, a, b, c, 62);
200    R4(c, d, e, a, b, 63);
201    R4(b, c, d, e, a, 64);
202    R4(a, b, c, d, e, 65);
203    R4(e, a, b, c, d, 66);
204    R4(d, e, a, b, c, 67);
205    R4(c, d, e, a, b, 68);
206    R4(b, c, d, e, a, 69);
207    R4(a, b, c, d, e, 70);
208    R4(e, a, b, c, d, 71);
209    R4(d, e, a, b, c, 72);
210    R4(c, d, e, a, b, 73);
211    R4(b, c, d, e, a, 74);
212    R4(a, b, c, d, e, 75);
213    R4(e, a, b, c, d, 76);
214    R4(d, e, a, b, c, 77);
215    R4(c, d, e, a, b, 78);
216    R4(b, c, d, e, a, 79);
217    /* Add the working vars back into context.state[] */
218    state[0] += a;
219    state[1] += b;
220    state[2] += c;
221    state[3] += d;
222    state[4] += e;
223    /* Wipe variables */
224    a = b = c = d = e = 0;
225}
226
227/* SHA1Init - Initialize new context */
228
229void SHA1Init(SHA1_CTX * context)
230{
231    /* SHA1 initialization constants */
232    context->state[0] = 0x67452301;
233    context->state[1] = 0xEFCDAB89;
234    context->state[2] = 0x98BADCFE;
235    context->state[3] = 0x10325476;
236    context->state[4] = 0xC3D2E1F0;
237    context->count[0] = context->count[1] = 0;
238}
239
240/* Run your data through this. */
241
242void SHA1Update(SHA1_CTX * context, const unsigned char *data, uint32_t len)
243{                               /*
244                                   JHB */
245    uint32_t i, j;              /* JHB */
246
247#ifdef VERBOSE
248    SHAPrintContext(context, "before");
249#endif
250    j = (context->count[0] >> 3) & 63;
251    if ((context->count[0] += len << 3) < (len << 3))
252        context->count[1]++;
253    context->count[1] += (len >> 29);
254    if ((j + len) > 63) {
255        memcpy(&context->buffer[j], data, (i = 64 - j));
256        SHA1Transform(context->state, context->buffer);
257        for (; i + 63 < len; i += 64) {
258            SHA1Transform(context->state, &data[i]);
259        }
260        j = 0;
261    } else
262        i = 0;
263    memcpy(&context->buffer[j], &data[i], len - i);
264#ifdef VERBOSE
265    SHAPrintContext(context, "after ");
266#endif
267}
268
269/* Add padding and return the message digest. */
270
271void SHA1Final(unsigned char digest[20], SHA1_CTX * context)
272{
273    uint32_t i;                 /* JHB */
274    unsigned char finalcount[8];
275
276    for (i = 0; i < 8; i++) {
277        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
278                                         >> ((3 - (i & 3)) * 8)) & 255);        /* Endian independent */
279    }
280    SHA1Update(context, (unsigned char *)"\200", 1);
281    while ((context->count[0] & 504) != 448) {
282        SHA1Update(context, (unsigned char *)"\0", 1);
283    }
284    SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform()
285                                         */
286    for (i = 0; i < 20; i++) {
287        digest[i] = (unsigned char)
288            ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
289    }
290    /* Wipe variables */
291    i = 0;                      /* JHB */
292    memset(context->buffer, 0, 64);
293    memset(context->state, 0, 20);
294    memset(context->count, 0, 8);
295    memset(finalcount, 0, 8);   /* SWR */
296#ifdef SHA1HANDSOFF             /* make SHA1Transform overwrite it's own static vars */
297    SHA1Transform(context->state, context->buffer);
298#endif
299}
300
301/*************************************************************/
302
303/* This is not quite the MIME base64 algorithm: it uses _ instead of /,
304   and instead of padding the output with = characters we just make the
305   output shorter. */
306char *mybase64(uint8_t digest[20])
307{
308    static const char charz[] =
309        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_";
310    uint8_t input[21];
311    static char output[28];
312    int i, j;
313    uint8_t *p;
314    char *q;
315    uint32_t bv;
316
317    memcpy(input, digest, 20);
318    input[20] = 0;              /* Pad to multiple of 3 bytes */
319
320    p = input;
321    q = output;
322    for (i = 0; i < 7; i++) {
323        bv = (p[0] << 16) | (p[1] << 8) | p[2];
324        p += 3;
325        for (j = 0; j < 4; j++) {
326            *q++ = charz[(bv >> 18) & 0x3f];
327            bv <<= 6;
328        }
329    }
330    *--q = '\0';                /* The last character is not significant */
331    return output;
332}
333
334#ifdef FOR_TESTING_ONLY
335
336int main(int argc, char **argv)
337{
338    int i;
339    SHA1_CTX context;
340    uint8_t digest[20], buffer[16384];
341    FILE *file;
342
343    if (argc < 2) {
344        file = stdin;
345    } else {
346        if (!(file = fopen(argv[1], "rb"))) {
347            fputs("Unable to open file.", stderr);
348            return (-1);
349        }
350    }
351    SHA1Init(&context);
352    while (!feof(file)) {       /* note: what if ferror(file) */
353        i = fread(buffer, 1, 16384, file);
354        SHA1Update(&context, buffer, i);
355    }
356    SHA1Final(digest, &context);
357    fclose(file);
358
359    puts(mybase64(digest));
360
361    return 0;
362}
363
364#endif
Note: See TracBrowser for help on using the repository browser.