xref: /openbsd/gnu/usr.bin/perl/cpan/Digest-SHA/src/sha.c (revision 9f11ffb7)
1b39c5158Smillert /*
2b39c5158Smillert  * sha.c: routines to compute SHA-1/224/256/384/512 digests
3b39c5158Smillert  *
46fb12b70Safresh1  * Ref: NIST FIPS PUB 180-4 Secure Hash Standard
5b39c5158Smillert  *
6*9f11ffb7Safresh1  * Copyright (C) 2003-2017 Mark Shelor, All Rights Reserved
7b39c5158Smillert  *
8*9f11ffb7Safresh1  * Version: 6.01
9*9f11ffb7Safresh1  * Mon Dec 25 00:08:08 MST 2017
10b39c5158Smillert  *
11b39c5158Smillert  */
12b39c5158Smillert 
13b39c5158Smillert #include <stdio.h>
14b39c5158Smillert #include <stdlib.h>
15b39c5158Smillert #include <stddef.h>
16b39c5158Smillert #include <string.h>
17b39c5158Smillert #include <ctype.h>
18b39c5158Smillert #include "sha.h"
19b39c5158Smillert #include "sha64bit.h"
20b39c5158Smillert 
21b39c5158Smillert #define W32	SHA32			/* useful abbreviations */
22b39c5158Smillert #define C32	SHA32_CONST
23b39c5158Smillert #define SR32	SHA32_SHR
24b39c5158Smillert #define SL32	SHA32_SHL
25b39c5158Smillert #define LO32	SHA_LO32
26b39c5158Smillert #define UCHR	unsigned char
27b39c5158Smillert #define UINT	unsigned int
28b39c5158Smillert #define ULNG	unsigned long
29b39c5158Smillert #define VP	void *
30b39c5158Smillert 
31b39c5158Smillert #define ROTR(x, n)	(SR32(x, n) | SL32(x, 32-(n)))
32b39c5158Smillert #define ROTL(x, n)	(SL32(x, n) | SR32(x, 32-(n)))
33b39c5158Smillert 
34b39c5158Smillert #define Ch(x, y, z)	((z) ^ ((x) & ((y) ^ (z))))
35b39c5158Smillert #define Pa(x, y, z)	((x) ^ (y) ^ (z))
36b39c5158Smillert #define Ma(x, y, z)	(((x) & (y)) | ((z) & ((x) | (y))))
37b39c5158Smillert 
38b39c5158Smillert #define SIGMA0(x)	(ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
39b39c5158Smillert #define SIGMA1(x)	(ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
40b39c5158Smillert #define sigma0(x)	(ROTR(x,  7) ^ ROTR(x, 18) ^ SR32(x,  3))
41b39c5158Smillert #define sigma1(x)	(ROTR(x, 17) ^ ROTR(x, 19) ^ SR32(x, 10))
42b39c5158Smillert 
43b39c5158Smillert #define K1	C32(0x5a827999)		/* SHA-1 constants */
44b39c5158Smillert #define K2	C32(0x6ed9eba1)
45b39c5158Smillert #define K3	C32(0x8f1bbcdc)
46b39c5158Smillert #define K4	C32(0xca62c1d6)
47b39c5158Smillert 
48b8851fccSafresh1 static const W32 K256[64] =		/* SHA-224/256 constants */
49b39c5158Smillert {
50b39c5158Smillert 	C32(0x428a2f98), C32(0x71374491), C32(0xb5c0fbcf), C32(0xe9b5dba5),
51b39c5158Smillert 	C32(0x3956c25b), C32(0x59f111f1), C32(0x923f82a4), C32(0xab1c5ed5),
52b39c5158Smillert 	C32(0xd807aa98), C32(0x12835b01), C32(0x243185be), C32(0x550c7dc3),
53b39c5158Smillert 	C32(0x72be5d74), C32(0x80deb1fe), C32(0x9bdc06a7), C32(0xc19bf174),
54b39c5158Smillert 	C32(0xe49b69c1), C32(0xefbe4786), C32(0x0fc19dc6), C32(0x240ca1cc),
55b39c5158Smillert 	C32(0x2de92c6f), C32(0x4a7484aa), C32(0x5cb0a9dc), C32(0x76f988da),
56b39c5158Smillert 	C32(0x983e5152), C32(0xa831c66d), C32(0xb00327c8), C32(0xbf597fc7),
57b39c5158Smillert 	C32(0xc6e00bf3), C32(0xd5a79147), C32(0x06ca6351), C32(0x14292967),
58b39c5158Smillert 	C32(0x27b70a85), C32(0x2e1b2138), C32(0x4d2c6dfc), C32(0x53380d13),
59b39c5158Smillert 	C32(0x650a7354), C32(0x766a0abb), C32(0x81c2c92e), C32(0x92722c85),
60b39c5158Smillert 	C32(0xa2bfe8a1), C32(0xa81a664b), C32(0xc24b8b70), C32(0xc76c51a3),
61b39c5158Smillert 	C32(0xd192e819), C32(0xd6990624), C32(0xf40e3585), C32(0x106aa070),
62b39c5158Smillert 	C32(0x19a4c116), C32(0x1e376c08), C32(0x2748774c), C32(0x34b0bcb5),
63b39c5158Smillert 	C32(0x391c0cb3), C32(0x4ed8aa4a), C32(0x5b9cca4f), C32(0x682e6ff3),
64b39c5158Smillert 	C32(0x748f82ee), C32(0x78a5636f), C32(0x84c87814), C32(0x8cc70208),
65b39c5158Smillert 	C32(0x90befffa), C32(0xa4506ceb), C32(0xbef9a3f7), C32(0xc67178f2)
66b39c5158Smillert };
67b39c5158Smillert 
68b8851fccSafresh1 static const W32 H01[8] =		/* SHA-1 initial hash value */
69b39c5158Smillert {
70b8851fccSafresh1 	C32(0x67452301), C32(0xefcdab89), C32(0x98badcfe), C32(0x10325476),
71b8851fccSafresh1 	C32(0xc3d2e1f0), C32(0x00000000), C32(0x00000000), C32(0x00000000)
72b39c5158Smillert };
73b39c5158Smillert 
74b8851fccSafresh1 static const W32 H0224[8] =		/* SHA-224 initial hash value */
75b39c5158Smillert {
76b39c5158Smillert 	C32(0xc1059ed8), C32(0x367cd507), C32(0x3070dd17), C32(0xf70e5939),
77b39c5158Smillert 	C32(0xffc00b31), C32(0x68581511), C32(0x64f98fa7), C32(0xbefa4fa4)
78b39c5158Smillert };
79b39c5158Smillert 
80b8851fccSafresh1 static const W32 H0256[8] =		/* SHA-256 initial hash value */
81b39c5158Smillert {
82b39c5158Smillert 	C32(0x6a09e667), C32(0xbb67ae85), C32(0x3c6ef372), C32(0xa54ff53a),
83b39c5158Smillert 	C32(0x510e527f), C32(0x9b05688c), C32(0x1f83d9ab), C32(0x5be0cd19)
84b39c5158Smillert };
85b39c5158Smillert 
86b39c5158Smillert static void sha1(SHA *s, UCHR *block)		/* SHA-1 transform */
87b39c5158Smillert {
88b39c5158Smillert 	W32 a, b, c, d, e;
8991f110e0Safresh1 	W32 W[16];
90b39c5158Smillert 	W32 *wp = W;
91b8851fccSafresh1 	W32 *H = s->H32;
92b39c5158Smillert 
93b39c5158Smillert 	SHA32_SCHED(W, block);
94b39c5158Smillert 
95b39c5158Smillert /*
966fb12b70Safresh1  * Use SHA-1 alternate method from FIPS PUB 180-4 (ref. 6.1.3)
97b39c5158Smillert  *
98b39c5158Smillert  * To improve performance, unroll the loop and consolidate assignments
99b39c5158Smillert  * by changing the roles of variables "a" through "e" at each step.
100b39c5158Smillert  * Note that the variable "T" is no longer needed.
101b39c5158Smillert  */
102b39c5158Smillert 
103b39c5158Smillert #define M1(a, b, c, d, e, f, k, w)		\
104b39c5158Smillert 	e += ROTL(a, 5) + f(b, c, d) + k + w;	\
105b39c5158Smillert 	b =  ROTL(b, 30)
106b39c5158Smillert 
107b39c5158Smillert #define M11(f, k, w)	M1(a, b, c, d, e, f, k, w);
108b39c5158Smillert #define M12(f, k, w)	M1(e, a, b, c, d, f, k, w);
109b39c5158Smillert #define M13(f, k, w)	M1(d, e, a, b, c, f, k, w);
110b39c5158Smillert #define M14(f, k, w)	M1(c, d, e, a, b, f, k, w);
111b39c5158Smillert #define M15(f, k, w)	M1(b, c, d, e, a, f, k, w);
112b39c5158Smillert 
113b39c5158Smillert #define W11(s)	W[(s+ 0) & 0xf]
114b39c5158Smillert #define W12(s)	W[(s+13) & 0xf]
115b39c5158Smillert #define W13(s)	W[(s+ 8) & 0xf]
116b39c5158Smillert #define W14(s)	W[(s+ 2) & 0xf]
117b39c5158Smillert 
118b39c5158Smillert #define A1(s)	(W11(s) = ROTL(W11(s) ^ W12(s) ^ W13(s) ^ W14(s), 1))
119b39c5158Smillert 
120b39c5158Smillert 	a = H[0]; b = H[1]; c = H[2]; d = H[3]; e = H[4];
121b39c5158Smillert 
122b39c5158Smillert 	M11(Ch, K1,  *wp++); M12(Ch, K1,  *wp++); M13(Ch, K1,  *wp++);
123b39c5158Smillert 	M14(Ch, K1,  *wp++); M15(Ch, K1,  *wp++); M11(Ch, K1,  *wp++);
124b39c5158Smillert 	M12(Ch, K1,  *wp++); M13(Ch, K1,  *wp++); M14(Ch, K1,  *wp++);
125b39c5158Smillert 	M15(Ch, K1,  *wp++); M11(Ch, K1,  *wp++); M12(Ch, K1,  *wp++);
126b39c5158Smillert 	M13(Ch, K1,  *wp++); M14(Ch, K1,  *wp++); M15(Ch, K1,  *wp++);
127b39c5158Smillert 	M11(Ch, K1,  *wp  ); M12(Ch, K1, A1( 0)); M13(Ch, K1, A1( 1));
128b39c5158Smillert 	M14(Ch, K1, A1( 2)); M15(Ch, K1, A1( 3)); M11(Pa, K2, A1( 4));
129b39c5158Smillert 	M12(Pa, K2, A1( 5)); M13(Pa, K2, A1( 6)); M14(Pa, K2, A1( 7));
130b39c5158Smillert 	M15(Pa, K2, A1( 8)); M11(Pa, K2, A1( 9)); M12(Pa, K2, A1(10));
131b39c5158Smillert 	M13(Pa, K2, A1(11)); M14(Pa, K2, A1(12)); M15(Pa, K2, A1(13));
132b39c5158Smillert 	M11(Pa, K2, A1(14)); M12(Pa, K2, A1(15)); M13(Pa, K2, A1( 0));
133b39c5158Smillert 	M14(Pa, K2, A1( 1)); M15(Pa, K2, A1( 2)); M11(Pa, K2, A1( 3));
134b39c5158Smillert 	M12(Pa, K2, A1( 4)); M13(Pa, K2, A1( 5)); M14(Pa, K2, A1( 6));
135b39c5158Smillert 	M15(Pa, K2, A1( 7)); M11(Ma, K3, A1( 8)); M12(Ma, K3, A1( 9));
136b39c5158Smillert 	M13(Ma, K3, A1(10)); M14(Ma, K3, A1(11)); M15(Ma, K3, A1(12));
137b39c5158Smillert 	M11(Ma, K3, A1(13)); M12(Ma, K3, A1(14)); M13(Ma, K3, A1(15));
138b39c5158Smillert 	M14(Ma, K3, A1( 0)); M15(Ma, K3, A1( 1)); M11(Ma, K3, A1( 2));
139b39c5158Smillert 	M12(Ma, K3, A1( 3)); M13(Ma, K3, A1( 4)); M14(Ma, K3, A1( 5));
140b39c5158Smillert 	M15(Ma, K3, A1( 6)); M11(Ma, K3, A1( 7)); M12(Ma, K3, A1( 8));
141b39c5158Smillert 	M13(Ma, K3, A1( 9)); M14(Ma, K3, A1(10)); M15(Ma, K3, A1(11));
142b39c5158Smillert 	M11(Pa, K4, A1(12)); M12(Pa, K4, A1(13)); M13(Pa, K4, A1(14));
143b39c5158Smillert 	M14(Pa, K4, A1(15)); M15(Pa, K4, A1( 0)); M11(Pa, K4, A1( 1));
144b39c5158Smillert 	M12(Pa, K4, A1( 2)); M13(Pa, K4, A1( 3)); M14(Pa, K4, A1( 4));
145b39c5158Smillert 	M15(Pa, K4, A1( 5)); M11(Pa, K4, A1( 6)); M12(Pa, K4, A1( 7));
146b39c5158Smillert 	M13(Pa, K4, A1( 8)); M14(Pa, K4, A1( 9)); M15(Pa, K4, A1(10));
147b39c5158Smillert 	M11(Pa, K4, A1(11)); M12(Pa, K4, A1(12)); M13(Pa, K4, A1(13));
148b39c5158Smillert 	M14(Pa, K4, A1(14)); M15(Pa, K4, A1(15));
149b39c5158Smillert 
150b39c5158Smillert 	H[0] += a; H[1] += b; H[2] += c; H[3] += d; H[4] += e;
151b39c5158Smillert }
152b39c5158Smillert 
153b39c5158Smillert static void sha256(SHA *s, UCHR *block)		/* SHA-224/256 transform */
154b39c5158Smillert {
155b39c5158Smillert 	W32 a, b, c, d, e, f, g, h, T1;
15691f110e0Safresh1 	W32 W[16];
157b8851fccSafresh1 	const W32 *kp = K256;
158b39c5158Smillert 	W32 *wp = W;
159b8851fccSafresh1 	W32 *H = s->H32;
160b39c5158Smillert 
161b39c5158Smillert 	SHA32_SCHED(W, block);
162b39c5158Smillert 
163b39c5158Smillert /*
164b39c5158Smillert  * Use same technique as in sha1()
165b39c5158Smillert  *
166b39c5158Smillert  * To improve performance, unroll the loop and consolidate assignments
167b39c5158Smillert  * by changing the roles of variables "a" through "h" at each step.
168b39c5158Smillert  * Note that the variable "T2" is no longer needed.
169b39c5158Smillert  */
170b39c5158Smillert 
171b39c5158Smillert #define M2(a, b, c, d, e, f, g, h, w)				\
172b39c5158Smillert 	T1 = h  + SIGMA1(e) + Ch(e, f, g) + (*kp++) + w;	\
173b39c5158Smillert 	h  = T1 + SIGMA0(a) + Ma(a, b, c); d += T1;
174b39c5158Smillert 
175b39c5158Smillert #define W21(s)	W[(s+ 0) & 0xf]
176b39c5158Smillert #define W22(s)	W[(s+14) & 0xf]
177b39c5158Smillert #define W23(s)	W[(s+ 9) & 0xf]
178b39c5158Smillert #define W24(s)	W[(s+ 1) & 0xf]
179b39c5158Smillert 
180b39c5158Smillert #define A2(s)	(W21(s) += sigma1(W22(s)) + W23(s) + sigma0(W24(s)))
181b39c5158Smillert 
182b39c5158Smillert #define M21(w)	M2(a, b, c, d, e, f, g, h, w)
183b39c5158Smillert #define M22(w)	M2(h, a, b, c, d, e, f, g, w)
184b39c5158Smillert #define M23(w)	M2(g, h, a, b, c, d, e, f, w)
185b39c5158Smillert #define M24(w)	M2(f, g, h, a, b, c, d, e, w)
186b39c5158Smillert #define M25(w)	M2(e, f, g, h, a, b, c, d, w)
187b39c5158Smillert #define M26(w)	M2(d, e, f, g, h, a, b, c, w)
188b39c5158Smillert #define M27(w)	M2(c, d, e, f, g, h, a, b, w)
189b39c5158Smillert #define M28(w)	M2(b, c, d, e, f, g, h, a, w)
190b39c5158Smillert 
191b39c5158Smillert 	a = H[0]; b = H[1]; c = H[2]; d = H[3];
192b39c5158Smillert 	e = H[4]; f = H[5]; g = H[6]; h = H[7];
193b39c5158Smillert 
194b39c5158Smillert 	M21( *wp++); M22( *wp++); M23( *wp++); M24( *wp++);
195b39c5158Smillert 	M25( *wp++); M26( *wp++); M27( *wp++); M28( *wp++);
196b39c5158Smillert 	M21( *wp++); M22( *wp++); M23( *wp++); M24( *wp++);
197b39c5158Smillert 	M25( *wp++); M26( *wp++); M27( *wp++); M28( *wp  );
198b39c5158Smillert 	M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3));
199b39c5158Smillert 	M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7));
200b39c5158Smillert 	M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11));
201b39c5158Smillert 	M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15));
202b39c5158Smillert 	M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3));
203b39c5158Smillert 	M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7));
204b39c5158Smillert 	M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11));
205b39c5158Smillert 	M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15));
206b39c5158Smillert 	M21(A2( 0)); M22(A2( 1)); M23(A2( 2)); M24(A2( 3));
207b39c5158Smillert 	M25(A2( 4)); M26(A2( 5)); M27(A2( 6)); M28(A2( 7));
208b39c5158Smillert 	M21(A2( 8)); M22(A2( 9)); M23(A2(10)); M24(A2(11));
209b39c5158Smillert 	M25(A2(12)); M26(A2(13)); M27(A2(14)); M28(A2(15));
210b39c5158Smillert 
211b39c5158Smillert 	H[0] += a; H[1] += b; H[2] += c; H[3] += d;
212b39c5158Smillert 	H[4] += e; H[5] += f; H[6] += g; H[7] += h;
213b39c5158Smillert }
214b39c5158Smillert 
215b39c5158Smillert #include "sha64bit.c"
216b39c5158Smillert 
217b8851fccSafresh1 #define BITSET(s, pos)	s[(pos) >> 3] &  (UCHR)  (0x01 << (7 - (pos) % 8))
218b8851fccSafresh1 #define SETBIT(s, pos)	s[(pos) >> 3] |= (UCHR)  (0x01 << (7 - (pos) % 8))
219b8851fccSafresh1 #define CLRBIT(s, pos)	s[(pos) >> 3] &= (UCHR) ~(0x01 << (7 - (pos) % 8))
22091f110e0Safresh1 #define NBYTES(nbits)	(((nbits) + 7) >> 3)
221b39c5158Smillert #define HEXLEN(nbytes)	((nbytes) << 1)
222b39c5158Smillert #define B64LEN(nbytes)	(((nbytes) % 3 == 0) ? ((nbytes) / 3) * 4 \
223b39c5158Smillert 			: ((nbytes) / 3) * 4 + ((nbytes) % 3) + 1)
224b39c5158Smillert 
225b39c5158Smillert /* w32mem: writes 32-bit word to memory in big-endian order */
2266fb12b70Safresh1 static UCHR *w32mem(UCHR *mem, W32 w32)
227b39c5158Smillert {
228b39c5158Smillert 	int i;
229b39c5158Smillert 
230b39c5158Smillert 	for (i = 0; i < 4; i++)
231b39c5158Smillert 		*mem++ = (UCHR) (SR32(w32, 24-i*8) & 0xff);
2326fb12b70Safresh1 	return(mem);
2336fb12b70Safresh1 }
2346fb12b70Safresh1 
2356fb12b70Safresh1 /* memw32: returns 32-bit word from memory written in big-endian order */
2366fb12b70Safresh1 static W32 memw32(UCHR *mem)
2376fb12b70Safresh1 {
2386fb12b70Safresh1 	int i;
2396fb12b70Safresh1 	W32 w = 0;
2406fb12b70Safresh1 
2416fb12b70Safresh1 	for (i = 0; i < 4; i++)
2426fb12b70Safresh1 		w = (w << 8) + *mem++;
2436fb12b70Safresh1 	return(w);
244b39c5158Smillert }
245b39c5158Smillert 
246b39c5158Smillert /* digcpy: writes current state to digest buffer */
2476fb12b70Safresh1 static UCHR *digcpy(SHA *s)
248b39c5158Smillert {
2496fb12b70Safresh1 	int i;
250b39c5158Smillert 	UCHR *d = s->digest;
251b8851fccSafresh1 	W32 *p32 = s->H32;
252b8851fccSafresh1 	W64 *p64 = s->H64;
253b39c5158Smillert 
254b39c5158Smillert 	if (s->alg <= SHA256)
255b39c5158Smillert 		for (i = 0; i < 8; i++, d += 4)
256b39c5158Smillert 			w32mem(d, *p32++);
257b39c5158Smillert 	else
258b39c5158Smillert 		for (i = 0; i < 8; i++, d += 8) {
259b39c5158Smillert 			w32mem(d, (W32) ((*p64 >> 16) >> 16));
260b39c5158Smillert 			w32mem(d+4, (W32) (*p64++ & SHA32_MAX));
261b39c5158Smillert 		}
2626fb12b70Safresh1 	return(s->digest);
2636fb12b70Safresh1 }
2646fb12b70Safresh1 
2656fb12b70Safresh1 /* statecpy: writes buffer to current state (opposite of digcpy) */
2666fb12b70Safresh1 static UCHR *statecpy(SHA *s, UCHR *buf)
2676fb12b70Safresh1 {
2686fb12b70Safresh1 	int i;
269b8851fccSafresh1 	W32 *p32 = s->H32;
270b8851fccSafresh1 	W64 *p64 = s->H64;
2716fb12b70Safresh1 
2726fb12b70Safresh1 	if (s->alg <= SHA256)
2736fb12b70Safresh1 		for (i = 0; i < 8; i++, buf += 4)
2746fb12b70Safresh1 			*p32++ = memw32(buf);
2756fb12b70Safresh1 	else
2766fb12b70Safresh1 		for (i = 0; i < 8; i++, buf += 8)
277b8851fccSafresh1 			*p64++ = (((W64)memw32(buf) << 16) << 16) +
2786fb12b70Safresh1 					memw32(buf+4);
2796fb12b70Safresh1 	return(buf);
280b39c5158Smillert }
281b39c5158Smillert 
282b8851fccSafresh1 #define SHA_INIT(s, algo, transform) 					\
283b39c5158Smillert 	do {								\
284b8851fccSafresh1 		Zero(s, 1, SHA);					\
285b39c5158Smillert 		s->alg = algo; s->sha = sha ## transform;		\
286b8851fccSafresh1 		if (s->alg <= SHA256)					\
287b8851fccSafresh1 			Copy(H0 ## algo, s->H32, 8, SHA32);		\
288b8851fccSafresh1 		else							\
289b8851fccSafresh1 			Copy(H0 ## algo, s->H64, 8, SHA64);		\
290b39c5158Smillert 		s->blocksize = SHA ## algo ## _BLOCK_BITS;		\
291b39c5158Smillert 		s->digestlen = SHA ## algo ## _DIGEST_BITS >> 3;	\
292b39c5158Smillert 	} while (0)
293b39c5158Smillert 
294b8851fccSafresh1 /* sharewind: resets digest object */
29591f110e0Safresh1 static void sharewind(SHA *s)
296b39c5158Smillert {
297b8851fccSafresh1 	if      (s->alg == SHA1)   SHA_INIT(s, 1, 1);
298b8851fccSafresh1 	else if (s->alg == SHA224) SHA_INIT(s, 224, 256);
299b8851fccSafresh1 	else if (s->alg == SHA256) SHA_INIT(s, 256, 256);
300b8851fccSafresh1 	else if (s->alg == SHA384) SHA_INIT(s, 384, 512);
301b8851fccSafresh1 	else if (s->alg == SHA512) SHA_INIT(s, 512, 512);
302b8851fccSafresh1 	else if (s->alg == SHA512224) SHA_INIT(s, 512224, 512);
303b8851fccSafresh1 	else if (s->alg == SHA512256) SHA_INIT(s, 512256, 512);
304b39c5158Smillert }
305b39c5158Smillert 
306b8851fccSafresh1 /* shainit: initializes digest object */
307b8851fccSafresh1 static int shainit(SHA *s, int alg)
308b39c5158Smillert {
309b8851fccSafresh1 	if (alg >= SHA384 && !sha_384_512)
310b8851fccSafresh1 		return 0;
311b39c5158Smillert 	if (alg != SHA1 && alg != SHA224 && alg != SHA256 &&
312898184e3Ssthen 		alg != SHA384    && alg != SHA512 &&
313898184e3Ssthen 		alg != SHA512224 && alg != SHA512256)
314b8851fccSafresh1 		return 0;
315b39c5158Smillert 	s->alg = alg;
316b39c5158Smillert 	sharewind(s);
317b8851fccSafresh1 	return 1;
31891f110e0Safresh1 }
31991f110e0Safresh1 
320b39c5158Smillert /* shadirect: updates state directly (w/o going through s->block) */
321b39c5158Smillert static ULNG shadirect(UCHR *bitstr, ULNG bitcnt, SHA *s)
322b39c5158Smillert {
323b39c5158Smillert 	ULNG savecnt = bitcnt;
324b39c5158Smillert 
325b39c5158Smillert 	while (bitcnt >= s->blocksize) {
326b39c5158Smillert 		s->sha(s, bitstr);
327b39c5158Smillert 		bitstr += (s->blocksize >> 3);
328b39c5158Smillert 		bitcnt -= s->blocksize;
329b39c5158Smillert 	}
330b39c5158Smillert 	if (bitcnt > 0) {
331b8851fccSafresh1 		Copy(bitstr, s->block, NBYTES(bitcnt), char);
332b39c5158Smillert 		s->blockcnt = bitcnt;
333b39c5158Smillert 	}
334b39c5158Smillert 	return(savecnt);
335b39c5158Smillert }
336b39c5158Smillert 
337b8851fccSafresh1 /* shabytes: updates state for byte-aligned data in s->block */
338b39c5158Smillert static ULNG shabytes(UCHR *bitstr, ULNG bitcnt, SHA *s)
339b39c5158Smillert {
340b39c5158Smillert 	UINT offset;
341b39c5158Smillert 	UINT nbits;
342b39c5158Smillert 	ULNG savecnt = bitcnt;
343b39c5158Smillert 
344b39c5158Smillert 	offset = s->blockcnt >> 3;
345b39c5158Smillert 	if (s->blockcnt + bitcnt >= s->blocksize) {
346b39c5158Smillert 		nbits = s->blocksize - s->blockcnt;
347b8851fccSafresh1 		Copy(bitstr, s->block+offset, nbits>>3, char);
348b39c5158Smillert 		bitcnt -= nbits;
349b39c5158Smillert 		bitstr += (nbits >> 3);
350b39c5158Smillert 		s->sha(s, s->block), s->blockcnt = 0;
351b39c5158Smillert 		shadirect(bitstr, bitcnt, s);
352b39c5158Smillert 	}
353b39c5158Smillert 	else {
354b8851fccSafresh1 		Copy(bitstr, s->block+offset, NBYTES(bitcnt), char);
355b39c5158Smillert 		s->blockcnt += bitcnt;
356b39c5158Smillert 	}
357b39c5158Smillert 	return(savecnt);
358b39c5158Smillert }
359b39c5158Smillert 
360b8851fccSafresh1 /* shabits: updates state for bit-aligned data in s->block */
361b39c5158Smillert static ULNG shabits(UCHR *bitstr, ULNG bitcnt, SHA *s)
362b39c5158Smillert {
363b8851fccSafresh1 	ULNG i;
364b39c5158Smillert 
365b8851fccSafresh1 	for (i = 0UL; i < bitcnt; i++) {
366b8851fccSafresh1 		if (BITSET(bitstr, i))
367*9f11ffb7Safresh1 			SETBIT(s->block, s->blockcnt);
368b8851fccSafresh1 		else
369*9f11ffb7Safresh1 			CLRBIT(s->block, s->blockcnt);
370*9f11ffb7Safresh1 		if (++s->blockcnt == s->blocksize)
371b39c5158Smillert 			s->sha(s, s->block), s->blockcnt = 0;
372b39c5158Smillert 	}
373b8851fccSafresh1 	return(bitcnt);
374b39c5158Smillert }
375b39c5158Smillert 
376b39c5158Smillert /* shawrite: triggers a state update using data in bitstr/bitcnt */
37791f110e0Safresh1 static ULNG shawrite(UCHR *bitstr, ULNG bitcnt, SHA *s)
378b39c5158Smillert {
379b8851fccSafresh1 	if (!bitcnt)
380b39c5158Smillert 		return(0);
381b39c5158Smillert 	if (SHA_LO32(s->lenll += bitcnt) < bitcnt)
382b39c5158Smillert 		if (SHA_LO32(++s->lenlh) == 0)
383b39c5158Smillert 			if (SHA_LO32(++s->lenhl) == 0)
384b39c5158Smillert 				s->lenhh++;
385b39c5158Smillert 	if (s->blockcnt == 0)
386b39c5158Smillert 		return(shadirect(bitstr, bitcnt, s));
387b39c5158Smillert 	else if (s->blockcnt % 8 == 0)
388b39c5158Smillert 		return(shabytes(bitstr, bitcnt, s));
389b39c5158Smillert 	else
390b39c5158Smillert 		return(shabits(bitstr, bitcnt, s));
391b39c5158Smillert }
392b39c5158Smillert 
393b39c5158Smillert /* shafinish: pads remaining block(s) and computes final digest state */
39491f110e0Safresh1 static void shafinish(SHA *s)
395b39c5158Smillert {
396b39c5158Smillert 	UINT lenpos, lhpos, llpos;
397b39c5158Smillert 
398b39c5158Smillert 	lenpos = s->blocksize == SHA1_BLOCK_BITS ? 448 : 896;
399b39c5158Smillert 	lhpos  = s->blocksize == SHA1_BLOCK_BITS ?  56 : 120;
400b39c5158Smillert 	llpos  = s->blocksize == SHA1_BLOCK_BITS ?  60 : 124;
401b39c5158Smillert 	SETBIT(s->block, s->blockcnt), s->blockcnt++;
402b39c5158Smillert 	while (s->blockcnt > lenpos)
403b39c5158Smillert 		if (s->blockcnt < s->blocksize)
404b39c5158Smillert 			CLRBIT(s->block, s->blockcnt), s->blockcnt++;
405b39c5158Smillert 		else
406b39c5158Smillert 			s->sha(s, s->block), s->blockcnt = 0;
407b39c5158Smillert 	while (s->blockcnt < lenpos)
408b39c5158Smillert 		CLRBIT(s->block, s->blockcnt), s->blockcnt++;
409b39c5158Smillert 	if (s->blocksize > SHA1_BLOCK_BITS) {
410b39c5158Smillert 		w32mem(s->block + 112, s->lenhh);
411b39c5158Smillert 		w32mem(s->block + 116, s->lenhl);
412b39c5158Smillert 	}
413b39c5158Smillert 	w32mem(s->block + lhpos, s->lenlh);
414b39c5158Smillert 	w32mem(s->block + llpos, s->lenll);
415b39c5158Smillert 	s->sha(s, s->block);
416b39c5158Smillert }
417b39c5158Smillert 
418b8851fccSafresh1 #define shadigest(state)	digcpy(state)
419b8851fccSafresh1 
4206fb12b70Safresh1 /* xmap: translation map for hexadecimal encoding */
421b8851fccSafresh1 static const char xmap[] =
4226fb12b70Safresh1 	"0123456789abcdef";
423b39c5158Smillert 
424b39c5158Smillert /* shahex: returns pointer to current digest (hexadecimal) */
42591f110e0Safresh1 static char *shahex(SHA *s)
426b39c5158Smillert {
427b8851fccSafresh1 	UINT i;
4286fb12b70Safresh1 	char *h;
4296fb12b70Safresh1 	UCHR *d;
430b39c5158Smillert 
4316fb12b70Safresh1 	d = digcpy(s);
432b39c5158Smillert 	s->hex[0] = '\0';
433b39c5158Smillert 	if (HEXLEN((size_t) s->digestlen) >= sizeof(s->hex))
434b39c5158Smillert 		return(s->hex);
4356fb12b70Safresh1 	for (i = 0, h = s->hex; i < s->digestlen; i++) {
4366fb12b70Safresh1 		*h++ = xmap[(*d >> 4) & 0x0f];
4376fb12b70Safresh1 		*h++ = xmap[(*d++   ) & 0x0f];
4386fb12b70Safresh1 	}
4396fb12b70Safresh1 	*h = '\0';
440b39c5158Smillert 	return(s->hex);
441b39c5158Smillert }
442b39c5158Smillert 
4436fb12b70Safresh1 /* bmap: translation map for Base 64 encoding */
444b8851fccSafresh1 static const char bmap[] =
445b39c5158Smillert 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
446b39c5158Smillert 
447b39c5158Smillert /* encbase64: encodes input (0 to 3 bytes) into Base 64 */
448b8851fccSafresh1 static void encbase64(UCHR *in, UINT n, char *out)
449b39c5158Smillert {
450b39c5158Smillert 	UCHR byte[3] = {0, 0, 0};
451b39c5158Smillert 
452b39c5158Smillert 	out[0] = '\0';
453b39c5158Smillert 	if (n < 1 || n > 3)
454b39c5158Smillert 		return;
455b8851fccSafresh1 	Copy(in, byte, n, UCHR);
4566fb12b70Safresh1 	out[0] = bmap[byte[0] >> 2];
4576fb12b70Safresh1 	out[1] = bmap[((byte[0] & 0x03) << 4) | (byte[1] >> 4)];
4586fb12b70Safresh1 	out[2] = bmap[((byte[1] & 0x0f) << 2) | (byte[2] >> 6)];
4596fb12b70Safresh1 	out[3] = bmap[byte[2] & 0x3f];
460b39c5158Smillert 	out[n+1] = '\0';
461b39c5158Smillert }
462b39c5158Smillert 
463b39c5158Smillert /* shabase64: returns pointer to current digest (Base 64) */
46491f110e0Safresh1 static char *shabase64(SHA *s)
465b39c5158Smillert {
466b8851fccSafresh1 	UINT n;
467b39c5158Smillert 	UCHR *q;
468b39c5158Smillert 	char out[5];
469b39c5158Smillert 
4706fb12b70Safresh1 	q = digcpy(s);
471b39c5158Smillert 	s->base64[0] = '\0';
47291f110e0Safresh1 	if (B64LEN((size_t) s->digestlen) >= sizeof(s->base64))
473b39c5158Smillert 		return(s->base64);
4746fb12b70Safresh1 	for (n = s->digestlen; n > 3; n -= 3, q += 3) {
475b39c5158Smillert 		encbase64(q, 3, out);
476b39c5158Smillert 		strcat(s->base64, out);
477b39c5158Smillert 	}
478b39c5158Smillert 	encbase64(q, n, out);
479b39c5158Smillert 	strcat(s->base64, out);
480b39c5158Smillert 	return(s->base64);
481b39c5158Smillert }
482b39c5158Smillert 
483b8851fccSafresh1 /* hmacinit: initializes HMAC-SHA digest object */
484b8851fccSafresh1 static HMAC *hmacinit(HMAC *h, int alg, UCHR *key, UINT keylen)
485b39c5158Smillert {
48691f110e0Safresh1 	UINT i;
487b8851fccSafresh1 	SHA ksha;
48891f110e0Safresh1 
489b8851fccSafresh1 	Zero(h, 1, HMAC);
490b8851fccSafresh1 	if (!shainit(&h->isha, alg))
49191f110e0Safresh1 		return(NULL);
492b8851fccSafresh1 	if (!shainit(&h->osha, alg))
49391f110e0Safresh1 		return(NULL);
494b8851fccSafresh1 	if (keylen <= h->osha.blocksize / 8)
495b8851fccSafresh1 		Copy(key, h->key, keylen, char);
49691f110e0Safresh1 	else {
497b8851fccSafresh1 		if (!shainit(&ksha, alg))
49891f110e0Safresh1 			return(NULL);
499b8851fccSafresh1 		shawrite(key, keylen * 8, &ksha);
500b8851fccSafresh1 		shafinish(&ksha);
501b8851fccSafresh1 		Copy(digcpy(&ksha), h->key, ksha.digestlen, char);
50291f110e0Safresh1 	}
503b8851fccSafresh1 	h->digestlen = h->osha.digestlen;
504b8851fccSafresh1 	for (i = 0; i < h->osha.blocksize / 8; i++)
50591f110e0Safresh1 		h->key[i] ^= 0x5c;
506b8851fccSafresh1 	shawrite(h->key, h->osha.blocksize, &h->osha);
507b8851fccSafresh1 	for (i = 0; i < h->isha.blocksize / 8; i++)
50891f110e0Safresh1 		h->key[i] ^= (0x5c ^ 0x36);
509b8851fccSafresh1 	shawrite(h->key, h->isha.blocksize, &h->isha);
510b8851fccSafresh1 	Zero(h->key, sizeof(h->key), char);
51191f110e0Safresh1 	return(h);
51291f110e0Safresh1 }
51391f110e0Safresh1 
51491f110e0Safresh1 /* hmacwrite: triggers a state update using data in bitstr/bitcnt */
51591f110e0Safresh1 static ULNG hmacwrite(UCHR *bitstr, ULNG bitcnt, HMAC *h)
51691f110e0Safresh1 {
517b8851fccSafresh1 	return(shawrite(bitstr, bitcnt, &h->isha));
51891f110e0Safresh1 }
51991f110e0Safresh1 
52091f110e0Safresh1 /* hmacfinish: computes final digest state */
52191f110e0Safresh1 static void hmacfinish(HMAC *h)
52291f110e0Safresh1 {
523b8851fccSafresh1 	shafinish(&h->isha);
524b8851fccSafresh1 	shawrite(digcpy(&h->isha), h->isha.digestlen * 8, &h->osha);
525b8851fccSafresh1 	shafinish(&h->osha);
52691f110e0Safresh1 }
52791f110e0Safresh1 
528b8851fccSafresh1 #define hmacdigest(h)	digcpy(&(h)->osha)
529b8851fccSafresh1 
53091f110e0Safresh1 /* hmachex: returns pointer to digest (hexadecimal) */
53191f110e0Safresh1 static char *hmachex(HMAC *h)
53291f110e0Safresh1 {
533b8851fccSafresh1 	return(shahex(&h->osha));
53491f110e0Safresh1 }
53591f110e0Safresh1 
53691f110e0Safresh1 /* hmacbase64: returns pointer to digest (Base 64) */
53791f110e0Safresh1 static char *hmacbase64(HMAC *h)
53891f110e0Safresh1 {
539b8851fccSafresh1 	return(shabase64(&h->osha));
540b39c5158Smillert }
541