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