diff options
Diffstat (limited to 'xdelta1/libedsio/sha.c')
-rwxr-xr-x | xdelta1/libedsio/sha.c | 239 |
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 | |||
80 | static 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 | |||
142 | static 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 | |||
163 | void 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 | |||
177 | void 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 | |||
215 | void 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 | } | ||