1 /* shs2.c -- NIST proposed Secure Hash Standard
4 Written 2 September 1992, Peter C. Gutmann,
5 This implementation placed in the public domain.
7 Transcribed 2 October 2001, John Coffman.
8 Modified for FIPS PUB 180-1 (supercedes FIPS PUB 180)
25 /* The SHS f() - functions */
27 #define f1(x,y,z) ((x&y)|(~x&z))
28 #define f2(x,y,z) (x^y^z)
29 #define f3(x,y,z) ((x&y)|(x&z)|(y&z))
30 #define f4(x,y,z) (x^y^z)
32 /* The SHS Mysterious Constants */
34 #define K1 0x5A827999L
35 #define K2 0x6ED9EBA1L
36 #define K3 0x8F1BBCDCL
37 #define K4 0xCA62C1D6L
39 /* SHS initial values */
41 #define h0init 0x67452301L
42 #define h1init 0xEFCDAB89L
43 #define h2init 0x98BADCFEL
44 #define h3init 0x10325476L
45 #define h4init 0xC3D2E1F0L
47 /* 32-bit rotate -- uses shift kludge */
49 #define ROT(n,X) ((X<<n)|(X>>(32-n)))
53 /* The initial expanding function */
56 #define expand(count) temp=W[count-3]^W[count-8]^W[count-14]^W[count-16], W[count]=ROT(1,temp)
59 #define w(t) (t<16?W[t]:(temp=W[(t+13)&15]^W[(t+8)&15]^W[(t+2)&15]^W[t&15],\
63 /* The four SHS sub-rounds */
64 #define subRound1(count) \
65 temp = f1(B,C,D) + K1 + E + w(count) + ROT(5,A),\
72 #define subRound2(count) \
73 temp = f2(B,C,D) + K2 + E + w(count) + ROT(5,A),\
80 #define subRound3(count) \
81 temp = f3(B,C,D) + K3 + E + w(count) + ROT(5,A),\
88 #define subRound4(count) \
89 temp = f4(B,C,D) + K4 + E + w(count) + ROT(5,A),\
97 SHS_INFO shsInfo; /* global */
106 /* initialize the SHS values */
109 shsInfo.digest[0] = h0init;
110 shsInfo.digest[1] = h1init;
111 shsInfo.digest[2] = h2init;
112 shsInfo.digest[3] = h3init;
113 shsInfo.digest[4] = h4init;
115 shsInfo.countLo = shsInfo.countHi = 0L;
119 /* perform the SHS transformation */
121 static void shsTransform(void)
124 LONG A, B, C, D, E, temp;
126 /* Step A. Copy the data buffer into the work buffer */
129 for (i=0; i<16; i++) printf("W[%d] = %08lX\n", i, W[i]);
132 /* Step B. Expand the 16 words into 64 temporary data words */
134 for (i=16; i<80; i++) expand(i);
137 /* Step C. Set up first buffer */
138 A = shsInfo.digest[0];
139 B = shsInfo.digest[1];
140 C = shsInfo.digest[2];
141 D = shsInfo.digest[3];
142 E = shsInfo.digest[4];
144 /* Step D. Serious mangling, divided into 4 sub-rounds */
146 for (; i<20; i++) subRound1(i);
147 for (; i<40; i++) subRound2(i);
148 for (; i<60; i++) subRound3(i);
149 for (; i<80; i++) subRound4(i);
151 /* Step E. Build message digest */
152 shsInfo.digest[0] += A;
153 shsInfo.digest[1] += B;
154 shsInfo.digest[2] += C;
155 shsInfo.digest[3] += D;
156 shsInfo.digest[4] += E;
161 static void byteReverse(LONG buffer[], int byteCount)
166 byteCount /= sizeof(LONG);
167 for (count=0; count<byteCount; count++) {
168 value = (buffer[count]<<16) | (buffer[count]>>16);
169 buffer[count] = ((value&0xff00ff00L)>>8)|((value&0x00ff00ffL)<<8);
175 /* Update SHS for a block of data */
177 void shsUpdate(BYTE *buffer, int count)
181 /* calculate index of space remaining in the work buffer */
182 remain = shsInfo.countLo & (SHS_BLOCKSIZE-1);
184 /* update bitcount */
185 if ( (shsInfo.countLo + (LONG)count) < shsInfo.countLo )
186 shsInfo.countHi++; /* carry into high bitcount */
187 shsInfo.countLo += (LONG)count;
189 /* Process data in SHS_BLOCKSIZE chunks */
190 while (count >= SHS_BLOCKSIZE-remain) {
191 memcpy((BYTE*)&W+remain, buffer, SHS_BLOCKSIZE-remain);
193 byteReverse(W, SHS_BLOCKSIZE);
196 buffer += SHS_BLOCKSIZE-remain;
197 count -= SHS_BLOCKSIZE-remain;
201 /* Handle any remaining bytes of data */
202 if (count) memcpy((BYTE*)&W+remain, buffer, count);
206 /* Finalize the SHS function */
211 /* Compute number of bytes mod 64 */
212 count = shsInfo.countLo & (SHS_BLOCKSIZE-1);
214 /* Set the first char of padding to 0x80. This is safe since there is
215 always at least one byte free */
216 ((BYTE*)W)[count++] = 0x80;
218 /* Pad out to 56 mod 64 */
220 memset((BYTE*)W + count, 0, SHS_BLOCKSIZE-count);
222 byteReverse(W, SHS_BLOCKSIZE);
226 /* Now fill the next block with 56 bytes */
227 memset( W, 0, SHS_BLOCKSIZE-8);
229 else { /* Pad block to 56 bytes */
230 memset((BYTE*)W + count, 0, (SHS_BLOCKSIZE-8)-count);
233 byteReverse(W, SHS_BLOCKSIZE-8);
235 /* Append length in bits and transform */
236 W[14] = (shsInfo.countHi<<3) + (shsInfo.countLo>>29);
237 W[15] = shsInfo.countLo<<3;
241 #endif /* SHS_PASSWORDS */