xref: /openbsd/gnu/usr.bin/perl/cpan/Digest-SHA/src/sha.c (revision e0680481)
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*e0680481Safresh1  * Copyright (C) 2003-2023 Mark Shelor, All Rights Reserved
7b39c5158Smillert  *
8*e0680481Safresh1  * Version: 6.04
9*e0680481Safresh1  * Sat Feb 25 12:00:50 PM MST 2023
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 
sha1(SHA * s,UCHR * block)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 
sha256(SHA * s,UCHR * block)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 */
w32mem(UCHR * mem,W32 w32)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 */
memw32(UCHR * mem)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 */
digcpy(SHA * s)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) */
statecpy(SHA * s,UCHR * buf)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 
282*e0680481Safresh1 #define SHA_INIT(s, algo, transform, state, state_t)			\
283b39c5158Smillert 	do {								\
284b8851fccSafresh1 		Zero(s, 1, SHA);					\
285b39c5158Smillert 		s->alg = algo; s->sha = sha ## transform;		\
286*e0680481Safresh1 		Copy(H0 ## algo, s->state, 8, state_t);			\
287b39c5158Smillert 		s->blocksize = SHA ## algo ## _BLOCK_BITS;		\
288b39c5158Smillert 		s->digestlen = SHA ## algo ## _DIGEST_BITS >> 3;	\
289b39c5158Smillert 	} while (0)
290b39c5158Smillert 
291b8851fccSafresh1 /* sharewind: resets digest object */
sharewind(SHA * s)29291f110e0Safresh1 static void sharewind(SHA *s)
293b39c5158Smillert {
294*e0680481Safresh1 	if      (s->alg == SHA1)   SHA_INIT(s, 1, 1, H32, SHA32);
295*e0680481Safresh1 	else if (s->alg == SHA224) SHA_INIT(s, 224, 256, H32, SHA32);
296*e0680481Safresh1 	else if (s->alg == SHA256) SHA_INIT(s, 256, 256, H32, SHA32);
297*e0680481Safresh1 	else if (s->alg == SHA384) SHA_INIT(s, 384, 512, H64, SHA64);
298*e0680481Safresh1 	else if (s->alg == SHA512) SHA_INIT(s, 512, 512, H64, SHA64);
299*e0680481Safresh1 	else if (s->alg == SHA512224) SHA_INIT(s, 512224, 512, H64, SHA64);
300*e0680481Safresh1 	else if (s->alg == SHA512256) SHA_INIT(s, 512256, 512, H64, SHA64);
301b39c5158Smillert }
302b39c5158Smillert 
303b8851fccSafresh1 /* shainit: initializes digest object */
shainit(SHA * s,int alg)304b8851fccSafresh1 static int shainit(SHA *s, int alg)
305b39c5158Smillert {
306b8851fccSafresh1 	if (alg >= SHA384 && !sha_384_512)
307b8851fccSafresh1 		return 0;
308b39c5158Smillert 	if (alg != SHA1 && alg != SHA224 && alg != SHA256 &&
309898184e3Ssthen 		alg != SHA384    && alg != SHA512 &&
310898184e3Ssthen 		alg != SHA512224 && alg != SHA512256)
311b8851fccSafresh1 		return 0;
312b39c5158Smillert 	s->alg = alg;
313b39c5158Smillert 	sharewind(s);
314b8851fccSafresh1 	return 1;
31591f110e0Safresh1 }
31691f110e0Safresh1 
317b39c5158Smillert /* shadirect: updates state directly (w/o going through s->block) */
shadirect(UCHR * bitstr,ULNG bitcnt,SHA * s)318b39c5158Smillert static ULNG shadirect(UCHR *bitstr, ULNG bitcnt, SHA *s)
319b39c5158Smillert {
320b39c5158Smillert 	ULNG savecnt = bitcnt;
321b39c5158Smillert 
322b39c5158Smillert 	while (bitcnt >= s->blocksize) {
323b39c5158Smillert 		s->sha(s, bitstr);
324b39c5158Smillert 		bitstr += (s->blocksize >> 3);
325b39c5158Smillert 		bitcnt -= s->blocksize;
326b39c5158Smillert 	}
327b39c5158Smillert 	if (bitcnt > 0) {
328b8851fccSafresh1 		Copy(bitstr, s->block, NBYTES(bitcnt), char);
329b39c5158Smillert 		s->blockcnt = bitcnt;
330b39c5158Smillert 	}
331b39c5158Smillert 	return(savecnt);
332b39c5158Smillert }
333b39c5158Smillert 
334b8851fccSafresh1 /* shabytes: updates state for byte-aligned data in s->block */
shabytes(UCHR * bitstr,ULNG bitcnt,SHA * s)335b39c5158Smillert static ULNG shabytes(UCHR *bitstr, ULNG bitcnt, SHA *s)
336b39c5158Smillert {
337b39c5158Smillert 	UINT offset;
338b39c5158Smillert 	UINT nbits;
339b39c5158Smillert 	ULNG savecnt = bitcnt;
340b39c5158Smillert 
341b39c5158Smillert 	offset = s->blockcnt >> 3;
342b39c5158Smillert 	if (s->blockcnt + bitcnt >= s->blocksize) {
343b39c5158Smillert 		nbits = s->blocksize - s->blockcnt;
344b8851fccSafresh1 		Copy(bitstr, s->block+offset, nbits>>3, char);
345b39c5158Smillert 		bitcnt -= nbits;
346b39c5158Smillert 		bitstr += (nbits >> 3);
347b39c5158Smillert 		s->sha(s, s->block), s->blockcnt = 0;
348b39c5158Smillert 		shadirect(bitstr, bitcnt, s);
349b39c5158Smillert 	}
350b39c5158Smillert 	else {
351b8851fccSafresh1 		Copy(bitstr, s->block+offset, NBYTES(bitcnt), char);
352b39c5158Smillert 		s->blockcnt += bitcnt;
353b39c5158Smillert 	}
354b39c5158Smillert 	return(savecnt);
355b39c5158Smillert }
356b39c5158Smillert 
357b8851fccSafresh1 /* shabits: updates state for bit-aligned data in s->block */
shabits(UCHR * bitstr,ULNG bitcnt,SHA * s)358b39c5158Smillert static ULNG shabits(UCHR *bitstr, ULNG bitcnt, SHA *s)
359b39c5158Smillert {
360b8851fccSafresh1 	ULNG i;
361b39c5158Smillert 
362b8851fccSafresh1 	for (i = 0UL; i < bitcnt; i++) {
363b8851fccSafresh1 		if (BITSET(bitstr, i))
3649f11ffb7Safresh1 			SETBIT(s->block, s->blockcnt);
365b8851fccSafresh1 		else
3669f11ffb7Safresh1 			CLRBIT(s->block, s->blockcnt);
3679f11ffb7Safresh1 		if (++s->blockcnt == s->blocksize)
368b39c5158Smillert 			s->sha(s, s->block), s->blockcnt = 0;
369b39c5158Smillert 	}
370b8851fccSafresh1 	return(bitcnt);
371b39c5158Smillert }
372b39c5158Smillert 
373b39c5158Smillert /* shawrite: triggers a state update using data in bitstr/bitcnt */
shawrite(UCHR * bitstr,ULNG bitcnt,SHA * s)37491f110e0Safresh1 static ULNG shawrite(UCHR *bitstr, ULNG bitcnt, SHA *s)
375b39c5158Smillert {
376b8851fccSafresh1 	if (!bitcnt)
377b39c5158Smillert 		return(0);
378b39c5158Smillert 	if (SHA_LO32(s->lenll += bitcnt) < bitcnt)
379b39c5158Smillert 		if (SHA_LO32(++s->lenlh) == 0)
380b39c5158Smillert 			if (SHA_LO32(++s->lenhl) == 0)
381b39c5158Smillert 				s->lenhh++;
382b39c5158Smillert 	if (s->blockcnt == 0)
383b39c5158Smillert 		return(shadirect(bitstr, bitcnt, s));
384b39c5158Smillert 	else if (s->blockcnt % 8 == 0)
385b39c5158Smillert 		return(shabytes(bitstr, bitcnt, s));
386b39c5158Smillert 	else
387b39c5158Smillert 		return(shabits(bitstr, bitcnt, s));
388b39c5158Smillert }
389b39c5158Smillert 
390b39c5158Smillert /* shafinish: pads remaining block(s) and computes final digest state */
shafinish(SHA * s)39191f110e0Safresh1 static void shafinish(SHA *s)
392b39c5158Smillert {
393b39c5158Smillert 	UINT lenpos, lhpos, llpos;
394b39c5158Smillert 
395b39c5158Smillert 	lenpos = s->blocksize == SHA1_BLOCK_BITS ? 448 : 896;
396b39c5158Smillert 	lhpos  = s->blocksize == SHA1_BLOCK_BITS ?  56 : 120;
397b39c5158Smillert 	llpos  = s->blocksize == SHA1_BLOCK_BITS ?  60 : 124;
398b39c5158Smillert 	SETBIT(s->block, s->blockcnt), s->blockcnt++;
399b39c5158Smillert 	while (s->blockcnt > lenpos)
400b39c5158Smillert 		if (s->blockcnt < s->blocksize)
401b39c5158Smillert 			CLRBIT(s->block, s->blockcnt), s->blockcnt++;
402b39c5158Smillert 		else
403b39c5158Smillert 			s->sha(s, s->block), s->blockcnt = 0;
404b39c5158Smillert 	while (s->blockcnt < lenpos)
405b39c5158Smillert 		CLRBIT(s->block, s->blockcnt), s->blockcnt++;
406b39c5158Smillert 	if (s->blocksize > SHA1_BLOCK_BITS) {
407b39c5158Smillert 		w32mem(s->block + 112, s->lenhh);
408b39c5158Smillert 		w32mem(s->block + 116, s->lenhl);
409b39c5158Smillert 	}
410b39c5158Smillert 	w32mem(s->block + lhpos, s->lenlh);
411b39c5158Smillert 	w32mem(s->block + llpos, s->lenll);
412b39c5158Smillert 	s->sha(s, s->block);
413b39c5158Smillert }
414b39c5158Smillert 
415b8851fccSafresh1 #define shadigest(state)	digcpy(state)
416b8851fccSafresh1 
4176fb12b70Safresh1 /* xmap: translation map for hexadecimal encoding */
418b8851fccSafresh1 static const char xmap[] =
4196fb12b70Safresh1 	"0123456789abcdef";
420b39c5158Smillert 
421b39c5158Smillert /* shahex: returns pointer to current digest (hexadecimal) */
shahex(SHA * s)42291f110e0Safresh1 static char *shahex(SHA *s)
423b39c5158Smillert {
424b8851fccSafresh1 	UINT i;
4256fb12b70Safresh1 	char *h;
4266fb12b70Safresh1 	UCHR *d;
427b39c5158Smillert 
4286fb12b70Safresh1 	d = digcpy(s);
429b39c5158Smillert 	s->hex[0] = '\0';
430b39c5158Smillert 	if (HEXLEN((size_t) s->digestlen) >= sizeof(s->hex))
431b39c5158Smillert 		return(s->hex);
4326fb12b70Safresh1 	for (i = 0, h = s->hex; i < s->digestlen; i++) {
4336fb12b70Safresh1 		*h++ = xmap[(*d >> 4) & 0x0f];
4346fb12b70Safresh1 		*h++ = xmap[(*d++   ) & 0x0f];
4356fb12b70Safresh1 	}
4366fb12b70Safresh1 	*h = '\0';
437b39c5158Smillert 	return(s->hex);
438b39c5158Smillert }
439b39c5158Smillert 
4406fb12b70Safresh1 /* bmap: translation map for Base 64 encoding */
441b8851fccSafresh1 static const char bmap[] =
442b39c5158Smillert 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
443b39c5158Smillert 
444b39c5158Smillert /* encbase64: encodes input (0 to 3 bytes) into Base 64 */
encbase64(UCHR * in,UINT n,char * out)445b8851fccSafresh1 static void encbase64(UCHR *in, UINT n, char *out)
446b39c5158Smillert {
447b39c5158Smillert 	UCHR byte[3] = {0, 0, 0};
448b39c5158Smillert 
449b39c5158Smillert 	out[0] = '\0';
450b39c5158Smillert 	if (n < 1 || n > 3)
451b39c5158Smillert 		return;
452b8851fccSafresh1 	Copy(in, byte, n, UCHR);
4536fb12b70Safresh1 	out[0] = bmap[byte[0] >> 2];
4546fb12b70Safresh1 	out[1] = bmap[((byte[0] & 0x03) << 4) | (byte[1] >> 4)];
4556fb12b70Safresh1 	out[2] = bmap[((byte[1] & 0x0f) << 2) | (byte[2] >> 6)];
4566fb12b70Safresh1 	out[3] = bmap[byte[2] & 0x3f];
457b39c5158Smillert 	out[n+1] = '\0';
458b39c5158Smillert }
459b39c5158Smillert 
460b39c5158Smillert /* shabase64: returns pointer to current digest (Base 64) */
shabase64(SHA * s)46191f110e0Safresh1 static char *shabase64(SHA *s)
462b39c5158Smillert {
463b8851fccSafresh1 	UINT n;
464b39c5158Smillert 	UCHR *q;
465b39c5158Smillert 	char out[5];
466b39c5158Smillert 
4676fb12b70Safresh1 	q = digcpy(s);
468b39c5158Smillert 	s->base64[0] = '\0';
46991f110e0Safresh1 	if (B64LEN((size_t) s->digestlen) >= sizeof(s->base64))
470b39c5158Smillert 		return(s->base64);
4716fb12b70Safresh1 	for (n = s->digestlen; n > 3; n -= 3, q += 3) {
472b39c5158Smillert 		encbase64(q, 3, out);
473b39c5158Smillert 		strcat(s->base64, out);
474b39c5158Smillert 	}
475b39c5158Smillert 	encbase64(q, n, out);
476b39c5158Smillert 	strcat(s->base64, out);
477b39c5158Smillert 	return(s->base64);
478b39c5158Smillert }
479b39c5158Smillert 
480b8851fccSafresh1 /* hmacinit: initializes HMAC-SHA digest object */
hmacinit(HMAC * h,int alg,UCHR * key,UINT keylen)481b8851fccSafresh1 static HMAC *hmacinit(HMAC *h, int alg, UCHR *key, UINT keylen)
482b39c5158Smillert {
48391f110e0Safresh1 	UINT i;
484b8851fccSafresh1 	SHA ksha;
48591f110e0Safresh1 
486b8851fccSafresh1 	Zero(h, 1, HMAC);
487b8851fccSafresh1 	if (!shainit(&h->isha, alg))
48891f110e0Safresh1 		return(NULL);
489b8851fccSafresh1 	if (!shainit(&h->osha, alg))
49091f110e0Safresh1 		return(NULL);
491b8851fccSafresh1 	if (keylen <= h->osha.blocksize / 8)
492b8851fccSafresh1 		Copy(key, h->key, keylen, char);
49391f110e0Safresh1 	else {
494b8851fccSafresh1 		if (!shainit(&ksha, alg))
49591f110e0Safresh1 			return(NULL);
496b8851fccSafresh1 		shawrite(key, keylen * 8, &ksha);
497b8851fccSafresh1 		shafinish(&ksha);
498b8851fccSafresh1 		Copy(digcpy(&ksha), h->key, ksha.digestlen, char);
49991f110e0Safresh1 	}
500b8851fccSafresh1 	h->digestlen = h->osha.digestlen;
501b8851fccSafresh1 	for (i = 0; i < h->osha.blocksize / 8; i++)
50291f110e0Safresh1 		h->key[i] ^= 0x5c;
503b8851fccSafresh1 	shawrite(h->key, h->osha.blocksize, &h->osha);
504b8851fccSafresh1 	for (i = 0; i < h->isha.blocksize / 8; i++)
50591f110e0Safresh1 		h->key[i] ^= (0x5c ^ 0x36);
506b8851fccSafresh1 	shawrite(h->key, h->isha.blocksize, &h->isha);
507b8851fccSafresh1 	Zero(h->key, sizeof(h->key), char);
50891f110e0Safresh1 	return(h);
50991f110e0Safresh1 }
51091f110e0Safresh1 
51191f110e0Safresh1 /* hmacwrite: triggers a state update using data in bitstr/bitcnt */
hmacwrite(UCHR * bitstr,ULNG bitcnt,HMAC * h)51291f110e0Safresh1 static ULNG hmacwrite(UCHR *bitstr, ULNG bitcnt, HMAC *h)
51391f110e0Safresh1 {
514b8851fccSafresh1 	return(shawrite(bitstr, bitcnt, &h->isha));
51591f110e0Safresh1 }
51691f110e0Safresh1 
51791f110e0Safresh1 /* hmacfinish: computes final digest state */
hmacfinish(HMAC * h)51891f110e0Safresh1 static void hmacfinish(HMAC *h)
51991f110e0Safresh1 {
520b8851fccSafresh1 	shafinish(&h->isha);
521b8851fccSafresh1 	shawrite(digcpy(&h->isha), h->isha.digestlen * 8, &h->osha);
522b8851fccSafresh1 	shafinish(&h->osha);
52391f110e0Safresh1 }
52491f110e0Safresh1 
525b8851fccSafresh1 #define hmacdigest(h)	digcpy(&(h)->osha)
526b8851fccSafresh1 
52791f110e0Safresh1 /* hmachex: returns pointer to digest (hexadecimal) */
hmachex(HMAC * h)52891f110e0Safresh1 static char *hmachex(HMAC *h)
52991f110e0Safresh1 {
530b8851fccSafresh1 	return(shahex(&h->osha));
53191f110e0Safresh1 }
53291f110e0Safresh1 
53391f110e0Safresh1 /* hmacbase64: returns pointer to digest (Base 64) */
hmacbase64(HMAC * h)53491f110e0Safresh1 static char *hmacbase64(HMAC *h)
53591f110e0Safresh1 {
536b8851fccSafresh1 	return(shabase64(&h->osha));
537b39c5158Smillert }
538