Commit | Line | Data |
---|---|---|
05128928 NC |
1 | /* |
2 | * sha.c: routines to compute SHA-1/224/256/384/512 digests | |
3 | * | |
4 | * Ref: NIST FIPS PUB 180-2 Secure Hash Standard | |
5 | * | |
77d2a621 | 6 | * Copyright (C) 2003-2006 Mark Shelor, All Rights Reserved |
05128928 | 7 | * |
dcbcf62d SP |
8 | * Version: 5.37 |
9 | * Mon May 8 04:30:09 MST 2006 | |
05128928 NC |
10 | * |
11 | */ | |
12 | ||
13 | #include <stdio.h> | |
14 | #include <stdlib.h> | |
15 | #include <stddef.h> | |
16 | #include <string.h> | |
17 | #include <ctype.h> | |
18 | #include "sha.h" | |
19 | #include "sha64bit.h" | |
20 | ||
21 | #define W32 SHA32 /* useful abbreviations */ | |
22 | #define C32 SHA32_CONST | |
23 | #define SR32 SHA32_SHR | |
24 | #define SL32 SHA32_SHL | |
25 | #define LO32 SHA_LO32 | |
26 | #define UCHR unsigned char | |
27 | #define UINT unsigned int | |
28 | #define ULNG unsigned long | |
29 | #define VP void * | |
30 | ||
31 | #define ROTR(x, n) (SR32(x, n) | SL32(x, 32-(n))) | |
32 | #define ROTL(x, n) (SL32(x, n) | SR32(x, 32-(n))) | |
33 | ||
34 | #define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) | |
35 | #define Pa(x, y, z) ((x) ^ (y) ^ (z)) | |
36 | #define Ma(x, y, z) (((x) & (y)) | ((z) & ((x) | (y)))) | |
37 | ||
38 | #define SIGMA0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) | |
39 | #define SIGMA1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) | |
40 | #define sigma0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SR32(x, 3)) | |
41 | #define sigma1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SR32(x, 10)) | |
42 | ||
43 | #define K1 C32(0x5a827999) /* SHA-1 constants */ | |
44 | #define K2 C32(0x6ed9eba1) | |
45 | #define K3 C32(0x8f1bbcdc) | |
46 | #define K4 C32(0xca62c1d6) | |
47 | ||
48 | static W32 K256[64] = /* SHA-224/256 constants */ | |
49 | { | |
50 | C32(0x428a2f98), C32(0x71374491), C32(0xb5c0fbcf), C32(0xe9b5dba5), | |
51 | C32(0x3956c25b), C32(0x59f111f1), C32(0x923f82a4), C32(0xab1c5ed5), | |
52 | C32(0xd807aa98), C32(0x12835b01), C32(0x243185be), C32(0x550c7dc3), | |
53 | C32(0x72be5d74), C32(0x80deb1fe), C32(0x9bdc06a7), C32(0xc19bf174), | |
54 | C32(0xe49b69c1), C32(0xefbe4786), C32(0x0fc19dc6), C32(0x240ca1cc), | |
55 | C32(0x2de92c6f), C32(0x4a7484aa), C32(0x5cb0a9dc), C32(0x76f988da), | |
56 | C32(0x983e5152), C32(0xa831c66d), C32(0xb00327c8), C32(0xbf597fc7), | |
57 | C32(0xc6e00bf3), C32(0xd5a79147), C32(0x06ca6351), C32(0x14292967), | |
58 | C32(0x27b70a85), C32(0x2e1b2138), C32(0x4d2c6dfc), C32(0x53380d13), | |
59 | C32(0x650a7354), C32(0x766a0abb), C32(0x81c2c92e), C32(0x92722c85), | |
60 | C32(0xa2bfe8a1), C32(0xa81a664b), C32(0xc24b8b70), C32(0xc76c51a3), | |
61 | C32(0xd192e819), C32(0xd6990624), C32(0xf40e3585), C32(0x106aa070), | |
62 | C32(0x19a4c116), C32(0x1e376c08), C32(0x2748774c), C32(0x34b0bcb5), | |
63 | C32(0x391c0cb3), C32(0x4ed8aa4a), C32(0x5b9cca4f), C32(0x682e6ff3), | |
64 | C32(0x748f82ee), C32(0x78a5636f), C32(0x84c87814), C32(0x8cc70208), | |
65 | C32(0x90befffa), C32(0xa4506ceb), C32(0xbef9a3f7), C32(0xc67178f2) | |
66 | }; | |
67 | ||
68 | static W32 H01[5] = /* SHA-1 initial hash value */ | |
69 | { | |
70 | C32(0x67452301), C32(0xefcdab89), C32(0x98badcfe), | |
71 | C32(0x10325476), C32(0xc3d2e1f0) | |
72 | }; | |
73 | ||
74 | static W32 H0224[8] = /* SHA-224 initial hash value */ | |
75 | { | |
76 | C32(0xc1059ed8), C32(0x367cd507), C32(0x3070dd17), C32(0xf70e5939), | |
77 | C32(0xffc00b31), C32(0x68581511), C32(0x64f98fa7), C32(0xbefa4fa4) | |
78 | }; | |
79 | ||
80 | static W32 H0256[8] = /* SHA-256 initial hash value */ | |
81 | { | |
82 | C32(0x6a09e667), C32(0xbb67ae85), C32(0x3c6ef372), C32(0xa54ff53a), | |
83 | C32(0x510e527f), C32(0x9b05688c), C32(0x1f83d9ab), C32(0x5be0cd19) | |
84 | }; | |
85 | ||
86 | static void sha1(s, block) /* SHA-1 transform */ | |
87 | SHA *s; | |
88 | UCHR *block; | |
89 | { | |
90 | W32 a, b, c, d, e; | |
91 | SHA_STO_CLASS W32 W[16]; | |
92 | W32 *wp = W; | |
93 | W32 *H = (W32 *) s->H; | |
94 | ||
95 | SHA32_SCHED(W, block); | |
96 | ||
97 | /* | |
98 | * Use SHA-1 alternate method from FIPS PUB 180-2 (ref. 6.1.3) | |
99 | * | |
100 | * To improve performance, unroll the loop and consolidate assignments | |
101 | * by changing the roles of variables "a" through "e" at each step. | |
102 | * Note that the variable "T" is no longer needed. | |
103 | */ | |
104 | ||
105 | #define M1(a, b, c, d, e, f, k, w) \ | |
106 | e += ROTL(a, 5) + f(b, c, d) + k + w; \ | |
107 | b = ROTL(b, 30) | |
108 | ||
109 | #define M11(f, k, w) M1(a, b, c, d, e, f, k, w); | |
110 | #define M12(f, k, w) M1(e, a, b, c, d, f, k, w); | |
111 | #define M13(f, k, w) M1(d, e, a, b, c, f, k, w); | |
112 | #define M14(f, k, w) M1(c, d, e, a, b, f, k, w); | |
113 | #define M15(f, k, w) M1(b, c, d, e, a, f, k, w); | |
114 | ||
115 | #define W11(s) W[(s+ 0) & 0xf] | |
116 | #define W12(s) W[(s+13) & 0xf] | |
117 | #define W13(s) W[(s+ 8) & 0xf] | |
118 | #define W14(s) W[(s+ 2) & 0xf] | |
119 | ||
120 | #define A1(s) (W11(s) = ROTL(W11(s) ^ W12(s) ^ W13(s) ^ W14(s), 1)) | |
121 | ||
122 | a = H[0]; b = H[1]; c = H[2]; d = H[3]; e = H[4]; | |
123 | ||
124 | M11(Ch, K1, *wp++); M12(Ch, K1, *wp++); M13(Ch, K1, *wp++); | |
125 | M14(Ch, K1, *wp++); M15(Ch, K1, *wp++); M11(Ch, K1, *wp++); | |
126 | M12(Ch, K1, *wp++); M13(Ch, K1, *wp++); M14(Ch, K1, *wp++); | |
127 | M15(Ch, K1, *wp++); M11(Ch, K1, *wp++); M12(Ch, K1, *wp++); | |
128 | M13(Ch, K1, *wp++); M14(Ch, K1, *wp++); M15(Ch, K1, *wp++); | |
129 | M11(Ch, K1, *wp ); M12(Ch, K1, A1( 0)); M13(Ch, K1, A1( 1)); | |
130 | M14(Ch, K1, A1( 2)); M15(Ch, K1, A1( 3)); M11(Pa, K2, A1( 4)); | |
131 | M12(Pa, K2, A1( 5)); M13(Pa, K2, A1( 6)); M14(Pa, K2, A1( 7)); | |
132 | M15(Pa, K2, A1( 8)); M11(Pa, K2, A1( 9)); M12(Pa, K2, A1(10)); | |
133 | M13(Pa, K2, A1(11)); M14(Pa, K2, A1(12)); M15(Pa, K2, A1(13)); | |
134 | M11(Pa, K2, A1(14)); M12(Pa, K2, A1(15)); M13(Pa, K2, A1( 0)); | |
135 | M14(Pa, K2, A1( 1)); M15(Pa, K2, A1( 2)); M11(Pa, K2, A1( 3)); | |
136 | M12(Pa, K2, A1( 4)); M13(Pa, K2, A1( 5)); M14(Pa, K2, A1( 6)); | |
137 | M15(Pa, K2, A1( 7)); M11(Ma, K3, A1( 8)); M12(Ma, K3, A1( 9)); | |
138 | M13(Ma, K3, A1(10)); M14(Ma, K3, A1(11)); M15(Ma, K3, A1(12)); | |
139 | M11(Ma, K3, A1(13)); M12(Ma, K3, A1(14)); M13(Ma, K3, A1(15)); | |
140 | M14(Ma, K3, A1( 0)); M15(Ma, K3, A1( 1)); M11(Ma, K3, A1( 2)); | |
141 | M12(Ma, K3, A1( 3)); M13(Ma, K3, A1( 4)); M14(Ma, K3, A1( 5)); | |
142 | M15(Ma, K3, A1( 6)); M11(Ma, K3, A1( 7)); M12(Ma, K3, A1( 8)); | |
143 | M13(Ma, K3, A1( 9)); M14(Ma, K3, A1(10)); M15(Ma, K3, A1(11)); | |
144 | M11(Pa, K4, A1(12)); M12(Pa, K4, A1(13)); M13(Pa, K4, A1(14)); | |
145 | M14(Pa, K4, A1(15)); M15(Pa, K4, A1( 0)); M11(Pa, K4, A1( 1)); | |
146 | M12(Pa, K4, A1( 2)); M13(Pa, K4, A1( 3)); M14(Pa, K4, A1( 4)); | |
147 | M15(Pa, K4, A1( 5)); M11(Pa, K4, A1( 6)); M12(Pa, K4, A1( 7)); | |
148 | M13(Pa, K4, A1( 8)); M14(Pa, K4, A1( 9)); M15(Pa, K4, A1(10)); | |
149 | M11(Pa, K4, A1(11)); M12(Pa, K4, A1(12)); M13(Pa, K4, A1(13)); | |
150 | M14(Pa, K4, A1(14)); M15(Pa, K4, A1(15)); | |
151 | ||
152 | H[0] += a; H[1] += b; H[2] += c; H[3] += d; H[4] += e; | |
153 | } | |
154 | ||
155 | static void sha256(s, block) /* SHA-224/256 transform */ | |
156 | SHA *s; | |
157 | UCHR *block; | |
158 | { | |
159 | W32 a, b, c, d, e, f, g, h, T1; | |
160 | SHA_STO_CLASS W32 W[16]; | |
161 | W32 *kp = K256; | |
162 | W32 *wp = W; | |
163 | W32 *H = (W32 *) s->H; | |
164 | ||
165 | SHA32_SCHED(W, block); | |
166 | ||
167 | /* | |
168 | * Use same technique as in sha1() | |
169 | * | |
170 | * To improve performance, unroll the loop and consolidate assignments | |
171 | * by changing the roles of variables "a" through "h" at each step. | |
172 | * Note that the variable "T2" is no longer needed. | |
173 | */ | |
174 | ||
175 | #define M2(a, b, c, d, e, f, g, h, w) \ | |
176 | T1 = h + SIGMA1(e) + Ch(e, f, g) + (*kp++) + w; \ | |
177 | h = T1 + SIGMA0(a) + Ma(a, b, c); d += T1; | |
178 | ||
179 | #define W21(s) W[(s+ 0) & 0xf] | |
180 | #define W22(s) W[(s+14) & 0xf] | |
181 | #define W23(s) W[(s+ 9) & 0xf] | |
182 | #define W24(s) W[(s+ 1) & 0xf] | |
183 | ||
184 | #define A2(s) (W21(s) += sigma1(W22(s)) + W23(s) + sigma0(W24(s))) | |
185 | ||
186 | #define M21(w) M2(a, b, c, d, e, f, g, h, w) | |
187 | #define M22(w) M2(h, a, b, c, d, e, f, g, w) | |
188 | #define M23(w) M2(g, h, a, b, c, d, e, f, w) | |
189 | #define M24(w) M2(f, g, h, a, b, c, d, e, w) | |
190 | #define M25(w) M2(e, f, g, h, a, b, c, d, w) | |
191 | #define M26(w) M2(d, e, f, g, h, a, b, c, w) | |
192 | #define M27(w) M2(c, d, e, f, g, h, a, b, w) | |
193 | #define M28(w) M2(b, c, d, e, f, g, h, a, w) | |
194 | ||
195 | a = H[0]; b = H[1]; c = H[2]; d = H[3]; | |
196 | e = H[4]; f = H[5]; g = H[6]; h = H[7]; | |
197 | ||
198 | M21( *wp++); M22( *wp++); M23( *wp++); M24( *wp++); | |
199 | M25( *wp++); M26( *wp++); M27( *wp++); M28( *wp++); | |
200 | M21( *wp++); M22( *wp++); M23( *wp++); M24( *wp++); | |
201 | M25( *wp++); M26( *wp++); M27( *wp++); M28( *wp ); | |
202 | M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3)); | |
203 | M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7)); | |
204 | M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11)); | |
205 | M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15)); | |
206 | M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3)); | |
207 | M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7)); | |
208 | M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11)); | |
209 | M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15)); | |
210 | M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3)); | |
211 | M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7)); | |
212 | M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11)); | |
213 | M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15)); | |
214 | ||
215 | H[0] += a; H[1] += b; H[2] += c; H[3] += d; | |
216 | H[4] += e; H[5] += f; H[6] += g; H[7] += h; | |
217 | } | |
218 | ||
219 | #include "sha64bit.c" | |
220 | ||
221 | #define SETBIT(s, pos) s[(pos) >> 3] |= (0x01 << (7 - (pos) % 8)) | |
222 | #define CLRBIT(s, pos) s[(pos) >> 3] &= ~(0x01 << (7 - (pos) % 8)) | |
223 | #define NBYTES(nbits) ((nbits) > 0 ? 1 + (((nbits) - 1) >> 3) : 0) | |
224 | #define HEXLEN(nbytes) ((nbytes) << 1) | |
225 | #define B64LEN(nbytes) (((nbytes) % 3 == 0) ? ((nbytes) / 3) * 4 \ | |
226 | : ((nbytes) / 3) * 4 + ((nbytes) % 3) + 1) | |
227 | ||
228 | /* w32mem: writes 32-bit word to memory in big-endian order */ | |
229 | static void w32mem(mem, w32) | |
230 | UCHR *mem; | |
231 | W32 w32; | |
232 | { | |
233 | int i; | |
234 | ||
235 | for (i = 0; i < 4; i++) | |
236 | *mem++ = (UCHR) (SR32(w32, 24-i*8) & 0xff); | |
237 | } | |
238 | ||
239 | /* digcpy: writes current state to digest buffer */ | |
240 | static void digcpy(s) | |
241 | SHA *s; | |
242 | { | |
243 | UINT i; | |
244 | UCHR *d = s->digest; | |
245 | W32 *p32 = (W32 *) s->H; | |
246 | W64 *p64 = (W64 *) s->H; | |
247 | ||
248 | if (s->alg <= SHA256) | |
249 | for (i = 0; i < 8; i++, d += 4) | |
250 | w32mem(d, *p32++); | |
251 | else | |
252 | for (i = 0; i < 8; i++, d += 8) { | |
253 | w32mem(d, (W32) ((*p64 >> 16) >> 16)); | |
254 | w32mem(d+4, (W32) (*p64++ & SHA32_MAX)); | |
255 | } | |
256 | } | |
257 | ||
258 | #define SHA_INIT(algo, transform) \ | |
259 | do { \ | |
260 | memset(s, 0, sizeof(SHA)); \ | |
261 | s->alg = algo; s->sha = sha ## transform; \ | |
262 | memcpy(s->H, H0 ## algo, sizeof(H0 ## algo)); \ | |
263 | s->blocksize = SHA ## algo ## _BLOCK_BITS; \ | |
264 | s->digestlen = SHA ## algo ## _DIGEST_BITS >> 3; \ | |
265 | } while (0) | |
266 | ||
267 | /* sharewind: re-initializes the digest object */ | |
268 | void sharewind(s) | |
269 | SHA *s; | |
270 | { | |
271 | if (s->alg == SHA1) SHA_INIT(1, 1); | |
272 | else if (s->alg == SHA224) SHA_INIT(224, 256); | |
273 | else if (s->alg == SHA256) SHA_INIT(256, 256); | |
274 | else if (s->alg == SHA384) SHA_INIT(384, 512); | |
275 | else if (s->alg == SHA512) SHA_INIT(512, 512); | |
276 | } | |
277 | ||
278 | /* shaopen: creates a new digest object */ | |
279 | SHA *shaopen(alg) | |
280 | int alg; | |
281 | { | |
282 | SHA *s; | |
283 | ||
284 | if (alg != SHA1 && alg != SHA224 && alg != SHA256 && | |
285 | alg != SHA384 && alg != SHA512) | |
286 | return(NULL); | |
287 | if (alg >= SHA384 && !sha_384_512) | |
288 | return(NULL); | |
289 | SHA_newz(0, s, 1, SHA); | |
290 | if (s == NULL) | |
291 | return(NULL); | |
292 | s->alg = alg; | |
293 | sharewind(s); | |
294 | return(s); | |
295 | } | |
296 | ||
297 | /* shadirect: updates state directly (w/o going through s->block) */ | |
298 | static ULNG shadirect(bitstr, bitcnt, s) | |
299 | UCHR *bitstr; | |
300 | ULNG bitcnt; | |
301 | SHA *s; | |
302 | { | |
303 | ULNG savecnt = bitcnt; | |
304 | ||
305 | while (bitcnt >= s->blocksize) { | |
306 | s->sha(s, bitstr); | |
307 | bitstr += (s->blocksize >> 3); | |
308 | bitcnt -= s->blocksize; | |
309 | } | |
310 | if (bitcnt > 0) { | |
311 | memcpy(s->block, bitstr, NBYTES(bitcnt)); | |
312 | s->blockcnt = bitcnt; | |
313 | } | |
314 | return(savecnt); | |
315 | } | |
316 | ||
317 | /* shabytes: updates state for byte-aligned input data */ | |
318 | static ULNG shabytes(bitstr, bitcnt, s) | |
319 | UCHR *bitstr; | |
320 | ULNG bitcnt; | |
321 | SHA *s; | |
322 | { | |
323 | UINT offset; | |
324 | UINT nbits; | |
325 | ULNG savecnt = bitcnt; | |
326 | ||
327 | offset = s->blockcnt >> 3; | |
328 | if (s->blockcnt + bitcnt >= s->blocksize) { | |
329 | nbits = s->blocksize - s->blockcnt; | |
330 | memcpy(s->block+offset, bitstr, nbits>>3); | |
331 | bitcnt -= nbits; | |
332 | bitstr += (nbits >> 3); | |
333 | s->sha(s, s->block), s->blockcnt = 0; | |
334 | shadirect(bitstr, bitcnt, s); | |
335 | } | |
336 | else { | |
337 | memcpy(s->block+offset, bitstr, NBYTES(bitcnt)); | |
338 | s->blockcnt += bitcnt; | |
339 | } | |
340 | return(savecnt); | |
341 | } | |
342 | ||
343 | /* shabits: updates state for bit-aligned input data */ | |
344 | static ULNG shabits(bitstr, bitcnt, s) | |
345 | UCHR *bitstr; | |
346 | ULNG bitcnt; | |
347 | SHA *s; | |
348 | { | |
349 | UINT i; | |
350 | UINT gap; | |
351 | ULNG nbits; | |
352 | UCHR buf[1<<9]; | |
353 | UINT bufsize = sizeof(buf); | |
354 | ULNG bufbits = (ULNG) bufsize << 3; | |
355 | UINT nbytes = NBYTES(bitcnt); | |
356 | ULNG savecnt = bitcnt; | |
357 | ||
358 | gap = 8 - s->blockcnt % 8; | |
359 | s->block[s->blockcnt>>3] &= ~0 << gap; | |
360 | s->block[s->blockcnt>>3] |= *bitstr >> (8 - gap); | |
361 | s->blockcnt += bitcnt < gap ? bitcnt : gap; | |
362 | if (bitcnt < gap) | |
363 | return(savecnt); | |
364 | if (s->blockcnt == s->blocksize) | |
365 | s->sha(s, s->block), s->blockcnt = 0; | |
366 | if ((bitcnt -= gap) == 0) | |
367 | return(savecnt); | |
368 | while (nbytes > bufsize) { | |
369 | for (i = 0; i < bufsize; i++) | |
370 | buf[i] = bitstr[i] << gap | bitstr[i+1] >> (8-gap); | |
371 | nbits = bitcnt < bufbits ? bitcnt : bufbits; | |
372 | shabytes(buf, nbits, s); | |
373 | bitcnt -= nbits, bitstr += bufsize, nbytes -= bufsize; | |
374 | } | |
375 | for (i = 0; i < nbytes - 1; i++) | |
376 | buf[i] = bitstr[i] << gap | bitstr[i+1] >> (8-gap); | |
377 | buf[nbytes-1] = bitstr[nbytes-1] << gap; | |
378 | shabytes(buf, bitcnt, s); | |
379 | return(savecnt); | |
380 | } | |
381 | ||
382 | /* shawrite: triggers a state update using data in bitstr/bitcnt */ | |
383 | ULNG shawrite(bitstr, bitcnt, s) | |
384 | UCHR *bitstr; | |
385 | ULNG bitcnt; | |
386 | SHA *s; | |
387 | { | |
388 | if (bitcnt < 1) | |
389 | return(0); | |
390 | if (SHA_LO32(s->lenll += bitcnt) < bitcnt) | |
391 | if (SHA_LO32(++s->lenlh) == 0) | |
392 | if (SHA_LO32(++s->lenhl) == 0) | |
393 | s->lenhh++; | |
394 | if (s->blockcnt == 0) | |
395 | return(shadirect(bitstr, bitcnt, s)); | |
396 | else if (s->blockcnt % 8 == 0) | |
397 | return(shabytes(bitstr, bitcnt, s)); | |
398 | else | |
399 | return(shabits(bitstr, bitcnt, s)); | |
400 | } | |
401 | ||
402 | /* shafinish: pads remaining block(s) and computes final digest state */ | |
403 | void shafinish(s) | |
404 | SHA *s; | |
405 | { | |
406 | UINT lenpos, lhpos, llpos; | |
407 | ||
408 | lenpos = s->blocksize == SHA1_BLOCK_BITS ? 448 : 896; | |
409 | lhpos = s->blocksize == SHA1_BLOCK_BITS ? 56 : 120; | |
410 | llpos = s->blocksize == SHA1_BLOCK_BITS ? 60 : 124; | |
411 | SETBIT(s->block, s->blockcnt), s->blockcnt++; | |
412 | while (s->blockcnt > lenpos) | |
413 | if (s->blockcnt < s->blocksize) | |
414 | CLRBIT(s->block, s->blockcnt), s->blockcnt++; | |
415 | else | |
416 | s->sha(s, s->block), s->blockcnt = 0; | |
417 | while (s->blockcnt < lenpos) | |
418 | CLRBIT(s->block, s->blockcnt), s->blockcnt++; | |
419 | if (s->blocksize > SHA1_BLOCK_BITS) { | |
420 | w32mem(s->block + 112, s->lenhh); | |
421 | w32mem(s->block + 116, s->lenhl); | |
422 | } | |
423 | w32mem(s->block + lhpos, s->lenlh); | |
424 | w32mem(s->block + llpos, s->lenll); | |
425 | s->sha(s, s->block); | |
426 | } | |
427 | ||
428 | /* shadigest: returns pointer to current digest (binary) */ | |
429 | UCHR *shadigest(s) | |
430 | SHA *s; | |
431 | { | |
432 | digcpy(s); | |
433 | return(s->digest); | |
434 | } | |
435 | ||
436 | /* shahex: returns pointer to current digest (hexadecimal) */ | |
437 | char *shahex(s) | |
438 | SHA *s; | |
439 | { | |
440 | int i; | |
441 | ||
442 | digcpy(s); | |
443 | s->hex[0] = '\0'; | |
444 | if (HEXLEN((size_t) s->digestlen) >= sizeof(s->hex)) | |
445 | return(s->hex); | |
446 | for (i = 0; i < s->digestlen; i++) | |
447 | sprintf(s->hex+i*2, "%02x", s->digest[i]); | |
448 | return(s->hex); | |
449 | } | |
450 | ||
451 | /* map: translation map for Base 64 encoding */ | |
452 | static char map[] = | |
453 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
454 | ||
455 | /* encbase64: encodes input (0 to 3 bytes) into Base 64 */ | |
456 | static void encbase64(in, n, out) | |
457 | UCHR *in; | |
458 | int n; | |
459 | char *out; | |
460 | { | |
461 | UCHR byte[3] = {0, 0, 0}; | |
462 | ||
463 | out[0] = '\0'; | |
464 | if (n < 1 || n > 3) | |
465 | return; | |
466 | memcpy(byte, in, n); | |
467 | out[0] = map[byte[0] >> 2]; | |
468 | out[1] = map[((byte[0] & 0x03) << 4) | (byte[1] >> 4)]; | |
469 | out[2] = map[((byte[1] & 0x0f) << 2) | (byte[2] >> 6)]; | |
470 | out[3] = map[byte[2] & 0x3f]; | |
471 | out[n+1] = '\0'; | |
472 | } | |
473 | ||
474 | /* shabase64: returns pointer to current digest (Base 64) */ | |
475 | char *shabase64(s) | |
476 | SHA *s; | |
477 | { | |
478 | int n; | |
479 | UCHR *q; | |
480 | char out[5]; | |
481 | ||
482 | digcpy(s); | |
483 | s->base64[0] = '\0'; | |
484 | if (B64LEN(s->digestlen) >= sizeof(s->base64)) | |
485 | return(s->base64); | |
486 | for (n = s->digestlen, q = s->digest; n > 3; n -= 3, q += 3) { | |
487 | encbase64(q, 3, out); | |
488 | strcat(s->base64, out); | |
489 | } | |
490 | encbase64(q, n, out); | |
491 | strcat(s->base64, out); | |
492 | return(s->base64); | |
493 | } | |
494 | ||
495 | /* shadsize: returns length of digest in bytes */ | |
496 | int shadsize(s) | |
497 | SHA *s; | |
498 | { | |
499 | return(s->digestlen); | |
500 | } | |
501 | ||
502 | /* shadup: duplicates current digest object */ | |
503 | SHA *shadup(s) | |
504 | SHA *s; | |
505 | { | |
506 | SHA *p; | |
507 | ||
508 | SHA_new(0, p, 1, SHA); | |
509 | if (p == NULL) | |
510 | return(NULL); | |
511 | memcpy(p, s, sizeof(SHA)); | |
512 | return(p); | |
513 | } | |
514 | ||
515 | /* shadump: dumps digest object to a human-readable ASCII file */ | |
516 | int shadump(file, s) | |
517 | char *file; | |
518 | SHA *s; | |
519 | { | |
dcbcf62d | 520 | int i, j; |
05128928 NC |
521 | SHA_FILE *f; |
522 | UCHR *p = shadigest(s); | |
523 | ||
524 | if (file == NULL || strlen(file) == 0) | |
525 | f = SHA_stdout(); | |
526 | else if ((f = SHA_open(file, "w")) == NULL) | |
527 | return(0); | |
528 | SHA_fprintf(f, "alg:%d\nH", s->alg); | |
529 | for (i = 0; i < 8; i++) | |
1d49bf1b | 530 | for (j = 0; j < (UINT) (s->alg <= 256 ? 4 : 8); j++) |
05128928 NC |
531 | SHA_fprintf(f, "%s%02x", j==0 ? ":" : "", *p++); |
532 | SHA_fprintf(f, "\nblock"); | |
dcbcf62d | 533 | for (i = 0; i < (int) (s->blocksize >> 3); i++) |
05128928 NC |
534 | SHA_fprintf(f, ":%02x", s->block[i]); |
535 | SHA_fprintf(f, "\nblockcnt:%u\n", s->blockcnt); | |
536 | SHA_fprintf(f, "lenhh:%lu\nlenhl:%lu\nlenlh:%lu\nlenll:%lu\n", | |
537 | (ULNG) LO32(s->lenhh), (ULNG) LO32(s->lenhl), | |
538 | (ULNG) LO32(s->lenlh), (ULNG) LO32(s->lenll)); | |
539 | if (f != SHA_stdout()) | |
540 | SHA_close(f); | |
541 | return(1); | |
542 | } | |
543 | ||
544 | /* fgetstr: reads (and returns pointer to) next line of file */ | |
545 | static char *fgetstr(line, maxsize, f) | |
546 | char *line; | |
547 | UINT maxsize; | |
548 | SHA_FILE *f; | |
549 | { | |
550 | char *p; | |
551 | ||
552 | if (SHA_feof(f) || maxsize == 0) | |
553 | return(NULL); | |
554 | for (p = line; !SHA_feof(f) && maxsize > 1; maxsize--) | |
555 | if ((*p++ = SHA_getc(f)) == '\n') | |
556 | break; | |
557 | *p = '\0'; | |
558 | return(line); | |
559 | } | |
560 | ||
561 | /* empty: returns true if line contains only whitespace characters */ | |
562 | static int empty(line) | |
563 | char *line; | |
564 | { | |
565 | char *p; | |
566 | ||
567 | for (p = line; *p; p++) | |
568 | if (!isspace(*p)) | |
569 | return(0); | |
570 | return(1); | |
571 | } | |
572 | ||
573 | /* getval: null-terminates field value, and sets pointer to rest of line */ | |
574 | static char *getval(line, pprest) | |
575 | char *line; | |
576 | char **pprest; | |
577 | { | |
578 | char *p, *v; | |
579 | ||
580 | for (v = line; *v == ':' || isspace(*v); v++) | |
581 | ; | |
582 | for (p = v; *p; p++) { | |
583 | if (*p == ':' || isspace(*p)) { | |
584 | *p++ = '\0'; | |
585 | break; | |
586 | } | |
587 | } | |
588 | *pprest = p; | |
589 | return(p == v ? NULL : v); | |
590 | } | |
591 | ||
592 | /* types of values present in dump file */ | |
593 | #define T_C 1 /* character */ | |
594 | #define T_I 2 /* normal integer */ | |
595 | #define T_L 3 /* 32-bit value */ | |
596 | #define T_Q 4 /* 64-bit value */ | |
597 | ||
598 | /* ldvals: checks next line in dump file against tag, and loads values */ | |
599 | static int ldvals(f, tag, type, pval, reps, base) | |
600 | SHA_FILE *f; | |
601 | char *tag; | |
602 | int type; | |
603 | void *pval; | |
604 | int reps; | |
605 | int base; | |
606 | { | |
607 | char *p, *pr, line[512]; | |
608 | UCHR *pc = (UCHR *) pval; UINT *pi = (UINT *) pval; | |
609 | W32 *pl = (W32 *) pval; W64 *pq = (W64 *) pval; | |
610 | ||
611 | while ((p = fgetstr(line, sizeof(line), f)) != NULL) | |
612 | if (line[0] != '#' && !empty(line)) | |
613 | break; | |
614 | if (p == NULL || strcmp(getval(line, &pr), tag) != 0) | |
615 | return(0); | |
616 | while (reps-- > 0) { | |
617 | if ((p = getval(pr, &pr)) == NULL) | |
618 | return(1); | |
619 | switch (type) { | |
620 | case T_C: *pc++ = (UCHR) strtoul(p, NULL, base); break; | |
621 | case T_I: *pi++ = (UINT) strtoul(p, NULL, base); break; | |
622 | case T_L: *pl++ = (W32 ) strtoul(p, NULL, base); break; | |
623 | case T_Q: *pq++ = (W64 ) strto64(p ); break; | |
624 | } | |
625 | } | |
626 | return(1); | |
627 | } | |
628 | ||
629 | /* closeall: closes dump file and de-allocates digest object */ | |
630 | static SHA *closeall(f, s) | |
631 | SHA_FILE *f; | |
632 | SHA *s; | |
633 | { | |
634 | if (f != NULL && f != SHA_stdin()) | |
635 | SHA_close(f); | |
636 | if (s != NULL) | |
637 | shaclose(s); | |
638 | return(NULL); | |
639 | } | |
640 | ||
641 | /* shaload: creates digest object corresponding to contents of dump file */ | |
642 | SHA *shaload(file) | |
643 | char *file; | |
644 | { | |
645 | int alg; | |
646 | SHA *s = NULL; | |
647 | SHA_FILE *f; | |
648 | ||
649 | if (file == NULL || strlen(file) == 0) | |
650 | f = SHA_stdin(); | |
651 | else if ((f = SHA_open(file, "r")) == NULL) | |
652 | return(NULL); | |
653 | if ( | |
654 | /* avoid parens by exploiting precedence of (type)&-> */ | |
655 | !ldvals(f,"alg",T_I,(VP)&alg,1,10) || | |
656 | ((s = shaopen(alg)) == NULL) || | |
657 | !ldvals(f,"H",alg<=SHA256?T_L:T_Q,(VP)s->H,8,16) || | |
658 | !ldvals(f,"block",T_C,(VP)s->block,s->blocksize/8,16) || | |
659 | !ldvals(f,"blockcnt",T_I,(VP)&s->blockcnt,1,10) || | |
660 | (alg <= SHA256 && s->blockcnt >= SHA1_BLOCK_BITS) || | |
661 | (alg >= SHA384 && s->blockcnt >= SHA384_BLOCK_BITS) || | |
662 | !ldvals(f,"lenhh",T_L,(VP)&s->lenhh,1,10) || | |
663 | !ldvals(f,"lenhl",T_L,(VP)&s->lenhl,1,10) || | |
664 | !ldvals(f,"lenlh",T_L,(VP)&s->lenlh,1,10) || | |
665 | !ldvals(f,"lenll",T_L,(VP)&s->lenll,1,10) | |
666 | ) | |
667 | return(closeall(f, s)); | |
668 | if (f != SHA_stdin()) | |
669 | SHA_close(f); | |
670 | return(s); | |
671 | } | |
672 | ||
673 | /* shaclose: de-allocates digest object */ | |
674 | int shaclose(s) | |
675 | SHA *s; | |
676 | { | |
677 | if (s != NULL) { | |
678 | memset(s, 0, sizeof(SHA)); | |
679 | SHA_free(s); | |
680 | } | |
681 | return(0); | |
682 | } |