summaryrefslogtreecommitdiff
path: root/xdelta1/libedsio/sha.c
diff options
context:
space:
mode:
Diffstat (limited to 'xdelta1/libedsio/sha.c')
-rwxr-xr-xxdelta1/libedsio/sha.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/xdelta1/libedsio/sha.c b/xdelta1/libedsio/sha.c
new file mode 100755
index 0000000..503fe85
--- /dev/null
+++ b/xdelta1/libedsio/sha.c
@@ -0,0 +1,239 @@
1/* NIST Secure Hash Algorithm */
2/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
3/* from Peter C. Gutmann's implementation as found in */
4/* Applied Cryptography by Bruce Schneier */
5/* Further modifications to include the "UNRAVEL" stuff, below */
6
7/* This code is in the public domain */
8
9#include "edsio.h"
10#include <string.h>
11
12#define SHA_BLOCKSIZE 64
13#define SHA_DIGESTSIZE 20
14
15/* UNRAVEL should be fastest & biggest */
16/* UNROLL_LOOPS should be just as big, but slightly slower */
17/* both undefined should be smallest and slowest */
18
19#define UNRAVEL
20/* #define UNROLL_LOOPS */
21
22/* by default, compile for little-endian machines (Intel, Vax) */
23/* change for big-endian machines; for machines which are neither, */
24/* you will need to change the definition of maybe_byte_reverse */
25
26#ifndef WORDS_BIGENDIAN /* from config.h */
27#define SHA_LITTLE_ENDIAN
28#endif
29
30/* NIST's proposed modification to SHA of 7/11/94 may be */
31/* activated by defining USE_MODIFIED_SHA; leave it off for now */
32#undef USE_MODIFIED_SHA
33
34/* SHA f()-functions */
35
36#define f1(x,y,z) ((x & y) | (~x & z))
37#define f2(x,y,z) (x ^ y ^ z)
38#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
39#define f4(x,y,z) (x ^ y ^ z)
40
41/* SHA constants */
42
43#define CONST1 0x5a827999L
44#define CONST2 0x6ed9eba1L
45#define CONST3 0x8f1bbcdcL
46#define CONST4 0xca62c1d6L
47
48/* 32-bit rotate */
49
50#define ROT32(x,n) ((x << n) | (x >> (32 - n)))
51
52/* the generic case, for when the overall rotation is not unraveled */
53
54#define FG(n) \
55 T = ROT32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n; \
56 E = D; D = C; C = ROT32(B,30); B = A; A = T
57
58/* specific cases, for when the overall rotation is unraveled */
59
60#define FA(n) \
61 T = ROT32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n; B = ROT32(B,30)
62
63#define FB(n) \
64 E = ROT32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n; A = ROT32(A,30)
65
66#define FC(n) \
67 D = ROT32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n; T = ROT32(T,30)
68
69#define FD(n) \
70 C = ROT32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n; E = ROT32(E,30)
71
72#define FE(n) \
73 B = ROT32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n; D = ROT32(D,30)
74
75#define FT(n) \
76 A = ROT32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n; C = ROT32(C,30)
77
78/* do SHA transformation */
79
80static void sha_transform(EdsioSHACtx *ctx)
81{
82 int i;
83 guint32 T, A, B, C, D, E, W[80], *WP;
84
85 for (i = 0; i < 16; ++i) {
86 W[i] = ctx->data[i];
87 }
88 for (i = 16; i < 80; ++i) {
89 W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
90#ifdef USE_MODIFIED_SHA
91 W[i] = ROT32(W[i], 1);
92#endif /* USE_MODIFIED_SHA */
93 }
94 A = ctx->digest[0];
95 B = ctx->digest[1];
96 C = ctx->digest[2];
97 D = ctx->digest[3];
98 E = ctx->digest[4];
99 WP = W;
100#ifdef UNRAVEL
101 FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
102 FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
103 FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
104 FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
105 FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
106 FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
107 FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
108 FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
109 ctx->digest[0] += E;
110 ctx->digest[1] += T;
111 ctx->digest[2] += A;
112 ctx->digest[3] += B;
113 ctx->digest[4] += C;
114#else /* !UNRAVEL */
115#ifdef UNROLL_LOOPS
116 FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
117 FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
118 FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
119 FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
120 FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
121 FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
122 FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
123 FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
124#else /* !UNROLL_LOOPS */
125 for (i = 0; i < 20; ++i) { FG(1); }
126 for (i = 20; i < 40; ++i) { FG(2); }
127 for (i = 40; i < 60; ++i) { FG(3); }
128 for (i = 60; i < 80; ++i) { FG(4); }
129#endif /* !UNROLL_LOOPS */
130 ctx->digest[0] += A;
131 ctx->digest[1] += B;
132 ctx->digest[2] += C;
133 ctx->digest[3] += D;
134 ctx->digest[4] += E;
135#endif /* !UNRAVEL */
136}
137
138#ifdef SHA_LITTLE_ENDIAN
139
140/* change endianness of data */
141
142static void maybe_byte_reverse(guint32 *buffer, int count)
143{
144 int i;
145 guint32 in;
146
147 count /= sizeof(guint32);
148 for (i = 0; i < count; ++i) {
149 in = *buffer;
150 *buffer++ = ((in << 24) & 0xff000000) | ((in << 8) & 0x00ff0000) |
151 ((in >> 8) & 0x0000ff00) | ((in >> 24) & 0x000000ff);
152 }
153}
154
155#else /* !SHA_LITTLE_ENDIAN */
156
157#define maybe_byte_reverse(a,b) /* do nothing */
158
159#endif /* SHA_LITTLE_ENDIAN */
160
161/* initialize the SHA digest */
162
163void edsio_sha_init(EdsioSHACtx *ctx)
164{
165 ctx->digest[0] = 0x67452301L;
166 ctx->digest[1] = 0xefcdab89L;
167 ctx->digest[2] = 0x98badcfeL;
168 ctx->digest[3] = 0x10325476L;
169 ctx->digest[4] = 0xc3d2e1f0L;
170 ctx->count_lo = 0L;
171 ctx->count_hi = 0L;
172 ctx->local = 0;
173}
174
175/* update the SHA digest */
176
177void edsio_sha_update(EdsioSHACtx *ctx, const guint8 *buffer, guint count)
178{
179 int i;
180
181 if ((ctx->count_lo + ((guint32) count << 3)) < ctx->count_lo) {
182 ++ctx->count_hi;
183 }
184 ctx->count_lo += (guint32) count << 3;
185 ctx->count_hi += (guint32) count >> 29;
186 if (ctx->local) {
187 i = SHA_BLOCKSIZE - ctx->local;
188 if (i > count) {
189 i = count;
190 }
191 memcpy(((guint8 *) ctx->data) + ctx->local, buffer, i);
192 count -= i;
193 buffer += i;
194 ctx->local += i;
195 if (ctx->local == SHA_BLOCKSIZE) {
196 maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE);
197 sha_transform(ctx);
198 } else {
199 return;
200 }
201 }
202 while (count >= SHA_BLOCKSIZE) {
203 memcpy(ctx->data, buffer, SHA_BLOCKSIZE);
204 buffer += SHA_BLOCKSIZE;
205 count -= SHA_BLOCKSIZE;
206 maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE);
207 sha_transform(ctx);
208 }
209 memcpy(ctx->data, buffer, count);
210 ctx->local = count;
211}
212
213/* finish computing the SHA digest */
214
215void edsio_sha_final(guint8* digest, EdsioSHACtx *ctx)
216{
217 int count;
218 guint32 lo_bit_count, hi_bit_count;
219
220 lo_bit_count = ctx->count_lo;
221 hi_bit_count = ctx->count_hi;
222 count = (int) ((lo_bit_count >> 3) & 0x3f);
223 ((guint8 *) ctx->data)[count++] = 0x80;
224 if (count > SHA_BLOCKSIZE - 8) {
225 memset(((guint8 *) ctx->data) + count, 0, SHA_BLOCKSIZE - count);
226 maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE);
227 sha_transform(ctx);
228 memset((guint8 *) ctx->data, 0, SHA_BLOCKSIZE - 8);
229 } else {
230 memset(((guint8 *) ctx->data) + count, 0,
231 SHA_BLOCKSIZE - 8 - count);
232 }
233 maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE);
234 ctx->data[14] = hi_bit_count;
235 ctx->data[15] = lo_bit_count;
236 sha_transform(ctx);
237
238 memcpy (digest, ctx->digest, 20);
239}