Fix tar -j support
[oweals/busybox.git] / coreutils / sha1sum.c
1 /*
2  *  Based on shasum from http://www.netsw.org/crypto/hash/
3  *  Majorly hacked up to use Dr Brian Gladman's sha1 code
4  *
5  *  Copyright (C) 1999 Scott G. Miller
6  *  Copyright (C) 2003 Glenn L. McGrath
7  *  Copyright (C) 2003 Erik Andersen
8  * 
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22  */
23
24 #include <stdio.h>
25 #include <getopt.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <limits.h>
30 #include <stdint.h>
31 #include <endian.h>
32 #include <byteswap.h>
33 #include "busybox.h"
34
35
36 /*
37  ---------------------------------------------------------------------------
38  Begin Dr. Gladman's sha1 code
39  ---------------------------------------------------------------------------
40 */
41
42 /*
43  ---------------------------------------------------------------------------
44  Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
45  All rights reserved.
46
47  LICENSE TERMS
48
49  The free distribution and use of this software in both source and binary 
50  form is allowed (with or without changes) provided that:
51
52    1. distributions of this source code include the above copyright 
53       notice, this list of conditions and the following disclaimer;
54
55    2. distributions in binary form include the above copyright
56       notice, this list of conditions and the following disclaimer
57       in the documentation and/or other associated materials;
58
59    3. the copyright holder's name is not used to endorse products 
60       built using this software without specific written permission. 
61
62  ALTERNATIVELY, provided that this notice is retained in full, this product
63  may be distributed under the terms of the GNU General Public License (GPL),
64  in which case the provisions of the GPL apply INSTEAD OF those given above.
65  
66  DISCLAIMER
67
68  This software is provided 'as is' with no explicit or implied warranties
69  in respect of its properties, including, but not limited to, correctness 
70  and/or fitness for purpose.
71  ---------------------------------------------------------------------------
72  Issue Date: 10/11/2002
73
74  This is a byte oriented version of SHA1 that operates on arrays of bytes
75  stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
76 */
77
78 #define SHA1_BLOCK_SIZE  64
79 #define SHA1_DIGEST_SIZE 20
80 #define SHA1_HASH_SIZE   SHA1_DIGEST_SIZE
81 #define SHA2_GOOD        0
82 #define SHA2_BAD         1
83
84 /* type to hold the SHA1 context  */
85 typedef struct
86 {   uint32_t count[2];
87     uint32_t hash[5];
88     uint32_t wbuf[16];
89 } sha1_ctx;
90
91 #define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
92
93 #if __BYTE_ORDER == __BIG_ENDIAN
94 # define swap_b32(x) (x)
95 #elif defined(bswap_32)
96 # define swap_b32(x) bswap_32(x)
97 #else
98 # define swap_b32(x) ((rotl32((x), 8) & 0x00ff00ff) | (rotl32((x), 24) & 0xff00ff00))
99 #endif
100
101 #define SHA1_MASK   (SHA1_BLOCK_SIZE - 1)
102
103 /* reverse byte order in 32-bit words   */
104 #define ch(x,y,z)       (((x) & (y)) ^ (~(x) & (z)))
105 #define parity(x,y,z)   ((x) ^ (y) ^ (z))
106 #define maj(x,y,z)      (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
107
108 /* A normal version as set out in the FIPS. This version uses   */
109 /* partial loop unrolling and is optimised for the Pentium 4    */
110 #define rnd(f,k)    \
111     t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; \
112     e = d; d = c; c = rotl32(b, 30); b = t
113
114 void sha1_compile(sha1_ctx ctx[1])
115 {
116     uint32_t    w[80], i, a, b, c, d, e, t;
117
118     /* note that words are compiled from the buffer into 32-bit */
119     /* words in big-endian order so an order reversal is needed */
120     /* here on little endian machines                           */
121     for(i = 0; i < SHA1_BLOCK_SIZE / 4; ++i)
122         w[i] = swap_b32(ctx->wbuf[i]);
123
124     for(i = SHA1_BLOCK_SIZE / 4; i < 80; ++i)
125         w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
126
127     a = ctx->hash[0];
128     b = ctx->hash[1];
129     c = ctx->hash[2];
130     d = ctx->hash[3];
131     e = ctx->hash[4];
132
133     for(i = 0; i < 20; ++i)
134     {
135         rnd(ch, 0x5a827999);    
136     }
137
138     for(i = 20; i < 40; ++i)
139     {
140         rnd(parity, 0x6ed9eba1);
141     }
142
143     for(i = 40; i < 60; ++i)
144     {
145         rnd(maj, 0x8f1bbcdc);
146     }
147
148     for(i = 60; i < 80; ++i)
149     {
150         rnd(parity, 0xca62c1d6);
151     }
152
153     ctx->hash[0] += a; 
154     ctx->hash[1] += b; 
155     ctx->hash[2] += c; 
156     ctx->hash[3] += d; 
157     ctx->hash[4] += e;
158 }
159
160 void sha1_begin(sha1_ctx ctx[1])
161 {
162     ctx->count[0] = ctx->count[1] = 0;
163     ctx->hash[0] = 0x67452301;
164     ctx->hash[1] = 0xefcdab89;
165     ctx->hash[2] = 0x98badcfe;
166     ctx->hash[3] = 0x10325476;
167     ctx->hash[4] = 0xc3d2e1f0;
168 }
169
170 /* SHA1 hash data in an array of bytes into hash buffer and call the        */
171 /* hash_compile function as required.                                       */
172 void sha1_hash(const unsigned char data[], unsigned int len, sha1_ctx ctx[1])
173 {
174     uint32_t pos = (uint32_t)(ctx->count[0] & SHA1_MASK), 
175             freeb = SHA1_BLOCK_SIZE - pos;
176     const unsigned char *sp = data;
177
178     if((ctx->count[0] += len) < len)
179         ++(ctx->count[1]);
180
181     while(len >= freeb)     /* tranfer whole blocks while possible  */
182     {
183         memcpy(((unsigned char*)ctx->wbuf) + pos, sp, freeb);
184         sp += freeb; len -= freeb; freeb = SHA1_BLOCK_SIZE; pos = 0; 
185         sha1_compile(ctx);
186     }
187
188     memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
189 }
190
191 /* SHA1 Final padding and digest calculation  */
192 #if __BYTE_ORDER == __LITTLE_ENDIAN
193 static uint32_t  mask[4] = 
194         {   0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff };
195 static uint32_t  bits[4] = 
196         {   0x00000080, 0x00008000, 0x00800000, 0x80000000 };
197 #else
198 static uint32_t  mask[4] = 
199         {   0x00000000, 0xff000000, 0xffff0000, 0xffffff00 };
200 static uint32_t  bits[4] = 
201         {   0x80000000, 0x00800000, 0x00008000, 0x00000080 };
202 #endif
203
204 void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
205 {
206     uint32_t    i, cnt = (uint32_t)(ctx->count[0] & SHA1_MASK);
207
208     /* mask out the rest of any partial 32-bit word and then set    */
209     /* the next byte to 0x80. On big-endian machines any bytes in   */
210     /* the buffer will be at the top end of 32 bit words, on little */
211     /* endian machines they will be at the bottom. Hence the AND    */
212     /* and OR masks above are reversed for little endian systems    */
213     ctx->wbuf[cnt >> 2] = (ctx->wbuf[cnt >> 2] & mask[cnt & 3]) | bits[cnt & 3];
214
215     /* we need 9 or more empty positions, one for the padding byte  */
216     /* (above) and eight for the length count.  If there is not     */
217     /* enough space pad and empty the buffer                        */
218     if(cnt > SHA1_BLOCK_SIZE - 9)
219     {
220         if(cnt < 60) ctx->wbuf[15] = 0;
221         sha1_compile(ctx);
222         cnt = 0;
223     }
224     else    /* compute a word index for the empty buffer positions  */
225         cnt = (cnt >> 2) + 1;
226
227     while(cnt < 14) /* and zero pad all but last two positions      */ 
228         ctx->wbuf[cnt++] = 0;
229     
230     /* assemble the eight byte counter in the buffer in big-endian  */
231     /* format                                                       */
232
233     ctx->wbuf[14] = swap_b32((ctx->count[1] << 3) | (ctx->count[0] >> 29));
234     ctx->wbuf[15] = swap_b32(ctx->count[0] << 3);
235
236     sha1_compile(ctx);
237
238     /* extract the hash value as bytes in case the hash buffer is   */
239     /* misaligned for 32-bit words                                  */
240
241     for(i = 0; i < SHA1_DIGEST_SIZE; ++i)
242         hval[i] = (unsigned char)(ctx->hash[i >> 2] >> 8 * (~i & 3));
243 }
244
245 #if 0
246 void sha1(unsigned char hval[], const unsigned char data[], unsigned int len)
247 {   sha1_ctx    cx[1];
248
249     sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx);
250 }
251 #endif
252
253 /*
254  ---------------------------------------------------------------------------
255  End of Dr. Gladman's sha1 code
256  ---------------------------------------------------------------------------
257 */
258
259 /* Using a larger blocksize can make things _much_ faster
260  * by avoiding a zillion tiny little reads */
261 #define BLOCKSIZE 65536
262 /* Ensure that BLOCKSIZE is a multiple of 64.  */
263 #if BLOCKSIZE % SHA1_BLOCK_SIZE != 0
264 # error "BLOCKSIZE not a multiple of 64"
265 #endif
266
267 static int sha1sum_stream(FILE *stream, unsigned char *hashval)
268 {
269     int result = 0;
270     sha1_ctx cx[1];
271     size_t sum, n;
272     RESERVE_CONFIG_BUFFER(buffer, BLOCKSIZE + 72);
273
274     /* Initialize the computation context.  */
275     sha1_begin(cx);
276
277     /* Iterate over full file contents.  */
278     while (1) 
279     {
280         /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
281            computation function processes the whole buffer so that with the
282            next round of the loop another block can be read.  */
283         sum = 0;
284
285         /* Read block.  Take care for partial reads.  */
286         while (1)
287         {
288             n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
289             sum += n;
290
291             if (sum == BLOCKSIZE)
292                 break;
293
294             if (n == 0) {
295                 /* Check for the error flag IFF N == 0, so that we don't
296                    exit the loop after a partial read due to e.g., EAGAIN
297                    or EWOULDBLOCK.  */
298                 if (feof (stream)) {
299                     sum = 0;
300                     goto process_partial_block;
301                 }
302                 if (ferror (stream)) {
303                     result++;
304                     goto all_done;
305                 }
306                 goto process_partial_block;
307             }
308
309             /* We've read at least one byte, so ignore errors.  But always
310                check for EOF, since feof may be true even though N > 0.
311                Otherwise, we could end up calling fread after EOF.  */
312             if (feof (stream))
313                 goto process_partial_block;
314         }
315
316         /* Process buffer */
317         sha1_hash(buffer, BLOCKSIZE, cx);
318     }
319
320 process_partial_block:
321
322     /* Process any remaining bytes.  */
323     if (sum > 0)
324         sha1_hash(buffer, sum, cx);
325
326     /* Finalize and write the hash into our buffer.  */
327     sha1_end(hashval, cx);
328
329 all_done:
330
331     RELEASE_CONFIG_BUFFER(buffer);
332     return result;
333 }
334
335 #define FLAG_SILENT     1
336 #define FLAG_CHECK      2
337 #define FLAG_WARN       4
338
339 static unsigned char *hash_bin_to_hex(unsigned char *hash_value, unsigned char hash_length)
340 {
341         int x, len, max;
342         unsigned char *hex_value;
343
344         max = (hash_length * 2) + 2;
345         hex_value = xmalloc(max);
346         for (x = len = 0; x < hash_length; x++) {
347             len += snprintf(hex_value+len, max-len, "%02x", hash_value[x]);
348         }
349         return(hex_value);
350 }
351
352 FILE *wfopen_file_or_stdin(const char *file_ptr)
353 {
354         FILE *stream;
355
356         if ((file_ptr[0] == '-') && (file_ptr[1] == '\0')) {
357                 stream = stdin;
358         } else {
359                 stream = bb_wfopen(file_ptr, "r");
360         }
361
362         return(stream);
363 }
364
365 /* This could become a common function for md5 as well, by using md5_stream */
366 extern int authenticate(int argc, char **argv, 
367         int (*hash_ptr)(FILE *stream, unsigned char *hashval), 
368         const unsigned char hash_length)
369 {
370         unsigned char hash_value[hash_length];
371         unsigned int flags;
372         int return_value = EXIT_SUCCESS;
373
374 #ifdef CONFIG_FEATURE_SHA1SUM_CHECK
375         flags = bb_getopt_ulflags(argc, argv, "scw");
376 #else
377         flags = bb_getopt_ulflags(argc, argv, "s");
378 #endif
379
380 #ifdef CONFIG_FEATURE_SHA1SUM_CHECK
381         if (!(flags & FLAG_CHECK)) {
382                 if (flags & FLAG_SILENT) {
383                         bb_error_msg_and_die("the -s option is meaningful only when verifying checksums");
384                 }
385                 else if (flags & FLAG_WARN) {
386                         bb_error_msg_and_die("the -w option is meaningful only when verifying checksums");
387                 }
388         }
389 #endif
390
391         if (argc == optind) {
392                 argv[argc++] = "-";
393         }
394
395 #ifdef CONFIG_FEATURE_SHA1SUM_CHECK
396         if (flags & FLAG_CHECK) {
397                 FILE *pre_computed_stream;
398                 int count_total = 0;
399                 int count_failed = 0;
400                 unsigned char *file_ptr = argv[optind];
401
402                 if (optind + 1 != argc) {
403                         bb_error_msg_and_die("only one argument may be specified when using -c");
404                 }
405                 pre_computed_stream = wfopen_file_or_stdin(file_ptr);
406                 while (!feof(pre_computed_stream) && !ferror(pre_computed_stream)) {
407                         FILE *stream;
408                         char *line;
409                         char *line_ptr;
410                         char *hex_value;
411
412                         line = bb_get_chomped_line_from_file(pre_computed_stream);
413                         if (line == NULL) {
414                                 break;
415                         }
416                         count_total++;
417                         line_ptr = strchr(line, ' ');
418                         if (line_ptr == NULL) {
419                                 if (flags & FLAG_WARN) {
420                                         bb_error_msg("Invalid format");
421                                 }
422                                 free(line);
423                                 continue;
424                         }
425                         *line_ptr = '\0';
426                         line_ptr++;
427                         if ((flags & FLAG_WARN) && (*line_ptr != ' ')) {
428                                 bb_error_msg("Invalid format");
429                                 free(line);
430                                 continue;
431                         }
432                         line_ptr++;
433                         stream = bb_wfopen(line_ptr, "r");
434                         if (hash_ptr(stream, hash_value) == EXIT_FAILURE) {
435                                 bb_perror_msg("%s", file_ptr);
436                                 return_value = EXIT_FAILURE;
437                         }
438                         if (fclose(stream) == EOF) {
439                                 bb_perror_msg("Couldnt close file %s", file_ptr);
440                         }                               
441                         hex_value = hash_bin_to_hex(hash_value, hash_length);
442                         printf("%s: ", line_ptr);
443                         if (strcmp(hex_value, line) != 0) {
444                                 puts("FAILED");
445                                 count_failed++;
446                         } else {
447                                 puts("ok");
448                         }
449                         free(line);
450                 }
451                 if (count_failed) {
452                         bb_error_msg("WARNING: %d of %d computed checksum did NOT match", count_failed, count_total);
453                 }
454                 if (bb_fclose_nonstdin(pre_computed_stream) == EOF) {
455                         bb_perror_msg_and_die("Couldnt close file %s", file_ptr);
456                 }
457         } else
458 #endif
459                 while (optind < argc) {
460                         FILE *stream;
461                         unsigned char *file_ptr = argv[optind];
462
463                         optind++;
464
465                         stream = wfopen_file_or_stdin(file_ptr);
466                         if (stream == NULL) {
467                                 return_value = EXIT_FAILURE;
468                                 continue;
469                         }
470                         if (hash_ptr(stream, hash_value) == EXIT_FAILURE) {
471                                 bb_perror_msg("%s", file_ptr);
472                                 return_value = EXIT_FAILURE;
473                         }
474                         else if (!flags & FLAG_SILENT) {
475                                 char *hex_value = hash_bin_to_hex(hash_value, hash_length);
476                                 printf("%s  %s\n", hex_value, file_ptr);
477                                 free(hex_value);
478                         }
479
480                         if (bb_fclose_nonstdin(stream) == EOF) {
481                                 bb_perror_msg("Couldnt close file %s", file_ptr);
482                                 return_value = EXIT_FAILURE;
483                         }
484                 }
485
486         return(return_value);
487 }
488
489 extern int sha1sum_main(int argc, char **argv)
490 {
491         return (authenticate(argc, argv, sha1sum_stream, SHA1_HASH_SIZE));
492 }