1 /* shs2.c - NIST proposed Secure Hash Standard
3 Written 2 September 1992, Peter C. Gutmann;
4 This implementation placed in the public domain.
6 Transcribed 2 October 2001, John Coffman;
7 Modified for FIPS PUB 180-1 (supercedes FIPS PUB 180).
24 /* The SHS f() - functions */
26 #define f1(x,y,z) ((x&y)|(~x&z))
27 #define f2(x,y,z) (x^y^z)
28 #define f3(x,y,z) ((x&y)|(x&z)|(y&z))
29 #define f4(x,y,z) (x^y^z)
31 /* The SHS Mysterious Constants */
33 #define K1 0x5A827999L
34 #define K2 0x6ED9EBA1L
35 #define K3 0x8F1BBCDCL
36 #define K4 0xCA62C1D6L
38 /* SHS initial values */
40 #define h0init 0x67452301L
41 #define h1init 0xEFCDAB89L
42 #define h2init 0x98BADCFEL
43 #define h3init 0x10325476L
44 #define h4init 0xC3D2E1F0L
46 /* 32-bit rotate -- uses shift kludge */
48 #define ROT(n,X) ((X<<n)|(X>>(32-n)))
52 /* The initial expanding function */
55 #define expand(count) temp=W[count-3]^W[count-8]^W[count-14]^W[count-16], W[count]=ROT(1,temp)
58 #define w(t) (t<16?W[t]:(temp=W[(t+13)&15]^W[(t+8)&15]^W[(t+2)&15]^W[t&15],\
62 /* The four SHS sub-rounds */
63 #define subRound1(count) \
64 temp = f1(B,C,D) + K1 + E + w(count) + ROT(5,A),\
71 #define subRound2(count) \
72 temp = f2(B,C,D) + K2 + E + w(count) + ROT(5,A),\
79 #define subRound3(count) \
80 temp = f3(B,C,D) + K3 + E + w(count) + ROT(5,A),\
87 #define subRound4(count) \
88 temp = f4(B,C,D) + K4 + E + w(count) + ROT(5,A),\
96 SHS_INFO shsInfo; /* global */
105 /* initialize the SHS values */
108 shsInfo.digest[0] = h0init;
109 shsInfo.digest[1] = h1init;
110 shsInfo.digest[2] = h2init;
111 shsInfo.digest[3] = h3init;
112 shsInfo.digest[4] = h4init;
114 shsInfo.countLo = shsInfo.countHi = 0L;
118 /* perform the SHS transformation */
120 static void shsTransform(void)
123 LONG A, B, C, D, E, temp;
125 /* Step A. Copy the data buffer into the work buffer */
128 for (i=0; i<16; i++) printf("W[%d] = %08" PRIX32 "\n", i, W[i]);
131 /* Step B. Expand the 16 words into 64 temporary data words */
133 for (i=16; i<80; i++) expand(i);
136 /* Step C. Set up first buffer */
137 A = shsInfo.digest[0];
138 B = shsInfo.digest[1];
139 C = shsInfo.digest[2];
140 D = shsInfo.digest[3];
141 E = shsInfo.digest[4];
143 /* Step D. Serious mangling, divided into 4 sub-rounds */
145 for (; i<20; i++) subRound1(i);
146 for (; i<40; i++) subRound2(i);
147 for (; i<60; i++) subRound3(i);
148 for (; i<80; i++) subRound4(i);
150 /* Step E. Build message digest */
151 shsInfo.digest[0] += A;
152 shsInfo.digest[1] += B;
153 shsInfo.digest[2] += C;
154 shsInfo.digest[3] += D;
155 shsInfo.digest[4] += E;
160 static void byteReverse(LONG buffer[], int byteCount)
165 byteCount /= sizeof(LONG);
166 for (count=0; count<byteCount; count++) {
167 value = (buffer[count]<<16) | (buffer[count]>>16);
168 buffer[count] = ((value&0xff00ff00L)>>8)|((value&0x00ff00ffL)<<8);
174 /* Update SHS for a block of data */
176 void shsUpdate(BYTE *buffer, int count)
180 /* calculate index of space remaining in the work buffer */
181 remain = shsInfo.countLo & (SHS_BLOCKSIZE-1);
183 /* update bitcount */
184 if ( (shsInfo.countLo + (LONG)count) < shsInfo.countLo )
185 shsInfo.countHi++; /* carry into high bitcount */
186 shsInfo.countLo += (LONG)count;
188 /* Process data in SHS_BLOCKSIZE chunks */
189 while (count >= SHS_BLOCKSIZE-remain) {
190 memcpy((BYTE*)&W+remain, buffer, SHS_BLOCKSIZE-remain);
192 byteReverse(W, SHS_BLOCKSIZE);
195 buffer += SHS_BLOCKSIZE-remain;
196 count -= SHS_BLOCKSIZE-remain;
200 /* Handle any remaining bytes of data */
201 if (count) memcpy((BYTE*)&W+remain, buffer, count);
205 /* Finalize the SHS function */
210 /* Compute number of bytes mod 64 */
211 count = shsInfo.countLo & (SHS_BLOCKSIZE-1);
213 /* Set the first char of padding to 0x80. This is safe since there is
214 always at least one byte free */
215 ((BYTE*)W)[count++] = 0x80;
217 /* Pad out to 56 mod 64 */
219 memset((BYTE*)W + count, 0, SHS_BLOCKSIZE-count);
221 byteReverse(W, SHS_BLOCKSIZE);
225 /* Now fill the next block with 56 bytes */
226 memset( W, 0, SHS_BLOCKSIZE-8);
228 else { /* Pad block to 56 bytes */
229 memset((BYTE*)W + count, 0, (SHS_BLOCKSIZE-8)-count);
232 byteReverse(W, SHS_BLOCKSIZE-8);
234 /* Append length in bits and transform */
235 W[14] = (shsInfo.countHi<<3) + (shsInfo.countLo>>29);
236 W[15] = shsInfo.countLo<<3;
240 #endif /* SHS_PASSWORDS */