summaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2003-07-03 09:41:41 +0000
committerEric Andersen <andersen@codepoet.org>2003-07-03 09:41:41 +0000
commit61f6db130e9c2b524d99a34d623c6d05732c6c21 (patch)
treeff442de26fd023e892bec6ffa4197b502679a447 /coreutils
parenta63d09a51772caca2e33b7103d447a06d688bb92 (diff)
downloadbusybox-w32-61f6db130e9c2b524d99a34d623c6d05732c6c21.tar.gz
busybox-w32-61f6db130e9c2b524d99a34d623c6d05732c6c21.tar.bz2
busybox-w32-61f6db130e9c2b524d99a34d623c6d05732c6c21.zip
As implemented, sha1sum would sometimes give the wrong answer.
This fixes it and uses faster sha1 code from Dr. Gladman. -Erik
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/sha1sum.c407
1 files changed, 298 insertions, 109 deletions
diff --git a/coreutils/sha1sum.c b/coreutils/sha1sum.c
index 7071fb6b7..1148aac19 100644
--- a/coreutils/sha1sum.c
+++ b/coreutils/sha1sum.c
@@ -1,13 +1,10 @@
1/* 1/*
2 * Based on shasum from http://www.netsw.org/crypto/hash/ 2 * Based on shasum from http://www.netsw.org/crypto/hash/
3 * 3 * Majorly hacked up to use Dr Brian Gladman's sha1 code
4 * shasum fixed with reference to coreutils and the nist fip180-1 document
5 * which is incorrect, in section 5
6 * - ft(B,C,D) = (B AND C) OR ((NOT B) AND D) ( 0 <= t <= 19)
7 * + ft(B,C,D) = (D XOR (B AND (C XOR D))) ( 0 <= t <= 19)
8 * 4 *
9 * Copyright (C) 1999 Scott G. Miller 5 * Copyright (C) 1999 Scott G. Miller
10 * Copyright (C) 2003 Glenn L. McGrath 6 * Copyright (C) 2003 Glenn L. McGrath
7 * Copyright (C) 2003 Erik Andersen
11 * 8 *
12 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -29,137 +26,325 @@
29#include <stdio.h> 26#include <stdio.h>
30#include <stdlib.h> 27#include <stdlib.h>
31#include <string.h> 28#include <string.h>
29#include <limits.h>
30#include <stdint.h>
32#include <endian.h> 31#include <endian.h>
32#include <byteswap.h>
33#include "busybox.h" 33#include "busybox.h"
34 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 */
85typedef 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
35#if __BYTE_ORDER == __BIG_ENDIAN 93#if __BYTE_ORDER == __BIG_ENDIAN
36# define SWAP(n) (n) 94# define swap_b32(x) (x)
95#elif defined(bswap_32)
96# define swap_b32(x) bswap_32(x)
37#else 97#else
38# define SWAP(n) \ 98# define swap_b32(x) ((rotl32((x), 8) & 0x00ff00ff) | (rotl32((x), 24) & 0xff00ff00))
39 (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
40#endif 99#endif
41 100
42#define f1(X,Y,Z) (Z ^ (X & (Y ^ Z))) 101#define SHA1_MASK (SHA1_BLOCK_SIZE - 1)
43#define f2(X,Y,Z) (X ^ Y ^ Z)
44#define f3(X,Y,Z) ((X & Y) | (Z & (X | Y)))
45 102
46#define rol1(x) (x<<1) | ((x>>31) & 1) 103/* reverse byte order in 32-bit words */
47#define rol5(x) ((x<<5) | ((x>>27) & 0x1f)) 104#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
48#define rol30(x) (x<<30) | ((x>>2) & 0x3fffffff) 105#define parity(x,y,z) ((x) ^ (y) ^ (z))
106#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
49 107
50static void sha_hash(unsigned int *data, int *hash) 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
114void sha1_compile(sha1_ctx ctx[1])
51{ 115{
52 RESERVE_CONFIG_BUFFER(word, 80 * sizeof(unsigned int)); 116 uint32_t w[80], i, a, b, c, d, e, t;
53 int *W = (unsigned int *) &word; 117
54 int a = hash[0]; 118 /* note that words are compiled from the buffer into 32-bit */
55 int b = hash[1]; 119 /* words in big-endian order so an order reversal is needed */
56 int c = hash[2]; 120 /* here on little endian machines */
57 int d = hash[3]; 121 for(i = 0; i < SHA1_BLOCK_SIZE / 4; ++i)
58 int e = hash[4]; 122 w[i] = swap_b32(ctx->wbuf[i]);
59 int t; 123
60 int TEMP; 124 for(i = SHA1_BLOCK_SIZE / 4; i < 80; ++i)
61 125 w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
62 for (t = 0; t < 16; t++) { 126
63 W[t] = SWAP(data[t]); 127 a = ctx->hash[0];
64 } 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}
65 159
66 /** Data expansion from 16 to 80 blocks **/ 160void sha1_begin(sha1_ctx ctx[1])
67 for (t = 16; t < 80; t++) { 161{
68 int x = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; 162 ctx->count[0] = ctx->count[1] = 0;
69 W[t] = rol1(x); 163 ctx->hash[0] = 0x67452301;
70 } 164 ctx->hash[1] = 0xefcdab89;
165 ctx->hash[2] = 0x98badcfe;
166 ctx->hash[3] = 0x10325476;
167 ctx->hash[4] = 0xc3d2e1f0;
168}
71 169
72 /** Main loops **/ 170/* SHA1 hash data in an array of bytes into hash buffer and call the */
73 for (t = 0; t < 20; t++) { 171/* hash_compile function as required. */
74 TEMP = rol5(a) + f1(b, c, d) + e + W[t] + 0x5a827999; 172void sha1_hash(const unsigned char data[], unsigned int len, sha1_ctx ctx[1])
75 e = d; 173{
76 d = c; 174 uint32_t pos = (uint32_t)(ctx->count[0] & SHA1_MASK),
77 c = rol30(b); 175 freeb = SHA1_BLOCK_SIZE - pos;
78 b = a; 176 const unsigned char *sp = data;
79 a = TEMP; 177
80 } 178 if((ctx->count[0] += len) < len)
81 for (; t < 40; t++) { 179 ++(ctx->count[1]);
82 TEMP = rol5(a) + f2(b, c, d) + e + W[t] + 0x6ed9eba1;
83 e = d;
84 d = c;
85 c = rol30(b);
86 b = a;
87 a = TEMP;
88 }
89 for (; t < 60; t++) {
90 TEMP = rol5(a) + f3(b, c, d) + e + W[t] + 0x8f1bbcdc;
91 e = d;
92 d = c;
93 c = rol30(b);
94 b = a;
95 a = TEMP;
96 }
97 for (; t < 80; t++) {
98 TEMP = rol5(a) + f2(b, c, d) + e + W[t] + 0xca62c1d6;
99 e = d;
100 d = c;
101 c = rol30(b);
102 b = a;
103 a = TEMP;
104 }
105 180
106 RELEASE_CONFIG_BUFFER(word); 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 }
107 187
108 hash[0] += a; 188 memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
109 hash[1] += b;
110 hash[2] += c;
111 hash[3] += d;
112 hash[4] += e;
113} 189}
114 190
115static char sha1sum_stream(FILE *fd, unsigned int *hashval) 191/* SHA1 Final padding and digest calculation */
192#if __BYTE_ORDER == __LITTLE_ENDIAN
193static uint32_t mask[4] =
194 { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff };
195static uint32_t bits[4] =
196 { 0x00000080, 0x00008000, 0x00800000, 0x80000000 };
197#else
198static uint32_t mask[4] =
199 { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 };
200static uint32_t bits[4] =
201 { 0x80000000, 0x00800000, 0x00008000, 0x00000080 };
202#endif
203
204void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
116{ 205{
117 RESERVE_CONFIG_BUFFER(buffer, 64); 206 uint32_t i, cnt = (uint32_t)(ctx->count[0] & SHA1_MASK);
118 int length = 0; 207
119 208 /* mask out the rest of any partial 32-bit word and then set */
120 hashval[0] = 0x67452301; 209 /* the next byte to 0x80. On big-endian machines any bytes in */
121 hashval[1] = 0xefcdab89; 210 /* the buffer will be at the top end of 32 bit words, on little */
122 hashval[2] = 0x98badcfe; 211 /* endian machines they will be at the bottom. Hence the AND */
123 hashval[3] = 0x10325476; 212 /* and OR masks above are reversed for little endian systems */
124 hashval[4] = 0xc3d2e1f0; 213 ctx->wbuf[cnt >> 2] = (ctx->wbuf[cnt >> 2] & mask[cnt & 3]) | bits[cnt & 3];
125 214
126 while (!feof(fd) && !ferror(fd)) { 215 /* we need 9 or more empty positions, one for the padding byte */
127 int c = fread(&buffer, 1, 64, fd); 216 /* (above) and eight for the length count. If there is not */
128 length += c; 217 /* enough space pad and empty the buffer */
129 if (feof(fd) || ferror(fd)) { 218 if(cnt > SHA1_BLOCK_SIZE - 9)
130 int i; 219 {
131 for (i = c; i < 61; i++) { 220 if(cnt < 60) ctx->wbuf[15] = 0;
132 if (i == c) { 221 sha1_compile(ctx);
133 buffer[i] = 0x80; 222 cnt = 0;
134 } 223 }
135 else if (i == 60) { 224 else /* compute a word index for the empty buffer positions */
136 /* This ends up being swaped twice */ 225 cnt = (cnt >> 2) + 1;
137 ((unsigned int *) &buffer)[15] = SWAP(length * 8); 226
138 } else { 227 while(cnt < 14) /* and zero pad all but last two positions */
139 buffer[i] = 0; 228 ctx->wbuf[cnt++] = 0;
140 } 229
141 } 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
246void 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
267static 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;
142 } 305 }
143 sha_hash((unsigned int *) &buffer, hashval); 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;
144 } 314 }
145 315
146 RELEASE_CONFIG_BUFFER(buffer); 316 /* Process buffer */
317 sha1_hash(buffer, BLOCKSIZE, cx);
318 }
319
320process_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
329all_done:
147 330
148 return(EXIT_SUCCESS); 331 RELEASE_CONFIG_BUFFER(buffer);
332 return result;
149} 333}
150 334
151#define FLAG_SILENT 1 335#define FLAG_SILENT 1
152#define FLAG_CHECK 2 336#define FLAG_CHECK 2
153#define FLAG_WARN 4 337#define FLAG_WARN 4
154 338
155static unsigned char *hash_bin_to_hex(unsigned int *hash_value, unsigned char hash_length) 339static unsigned char *hash_bin_to_hex(unsigned char *hash_value, unsigned char hash_length)
156{ 340{
157 unsigned char x; 341 int x, len, max;
158 unsigned char *hex_value; 342 unsigned char *hex_value;
159 343
160 hex_value = xmalloc(hash_length * 8); 344 max = (hash_length * 2) + 2;
161 for (x = 0; x < hash_length; x++) { 345 hex_value = xmalloc(max);
162 sprintf(&hex_value[x * 8], "%08x", hash_value[x]); 346 for (x = len = 0; x < hash_length; x++) {
347 len += snprintf(hex_value+len, max-len, "%02x", hash_value[x]);
163 } 348 }
164 return(hex_value); 349 return(hex_value);
165} 350}
@@ -178,9 +363,11 @@ FILE *wfopen_file_or_stdin(const char *file_ptr)
178} 363}
179 364
180/* This could become a common function for md5 as well, by using md5_stream */ 365/* This could become a common function for md5 as well, by using md5_stream */
181extern int authenticate(int argc, char **argv, char (*hash_ptr)(FILE *stream, unsigned int *hashval), const unsigned char hash_length) 366extern int authenticate(int argc, char **argv,
367 int (*hash_ptr)(FILE *stream, unsigned char *hashval),
368 const unsigned char hash_length)
182{ 369{
183 unsigned int hash_value[hash_length]; 370 unsigned char hash_value[hash_length];
184 unsigned int flags; 371 unsigned int flags;
185 int return_value = EXIT_SUCCESS; 372 int return_value = EXIT_SUCCESS;
186 373
@@ -245,6 +432,7 @@ extern int authenticate(int argc, char **argv, char (*hash_ptr)(FILE *stream, un
245 line_ptr++; 432 line_ptr++;
246 stream = bb_wfopen(line_ptr, "r"); 433 stream = bb_wfopen(line_ptr, "r");
247 if (hash_ptr(stream, hash_value) == EXIT_FAILURE) { 434 if (hash_ptr(stream, hash_value) == EXIT_FAILURE) {
435 bb_perror_msg("%s", file_ptr);
248 return_value = EXIT_FAILURE; 436 return_value = EXIT_FAILURE;
249 } 437 }
250 if (fclose(stream) == EOF) { 438 if (fclose(stream) == EOF) {
@@ -280,6 +468,7 @@ extern int authenticate(int argc, char **argv, char (*hash_ptr)(FILE *stream, un
280 continue; 468 continue;
281 } 469 }
282 if (hash_ptr(stream, hash_value) == EXIT_FAILURE) { 470 if (hash_ptr(stream, hash_value) == EXIT_FAILURE) {
471 bb_perror_msg("%s", file_ptr);
283 return_value = EXIT_FAILURE; 472 return_value = EXIT_FAILURE;
284 } 473 }
285 else if (!flags & FLAG_SILENT) { 474 else if (!flags & FLAG_SILENT) {
@@ -299,5 +488,5 @@ extern int authenticate(int argc, char **argv, char (*hash_ptr)(FILE *stream, un
299 488
300extern int sha1sum_main(int argc, char **argv) 489extern int sha1sum_main(int argc, char **argv)
301{ 490{
302 return (authenticate(argc, argv, sha1sum_stream, 5)); 491 return (authenticate(argc, argv, sha1sum_stream, SHA1_HASH_SIZE));
303} 492}