Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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