64a2fcca13e67426ceffbd19a5e3d6c1ab05b308
[rrq/maintain_lilo.git] / src / shs2.c
1 /* shs2.c -- NIST proposed Secure Hash Standard
2 */
3 /*
4    Written 2 September 1992, Peter C. Gutmann,
5    This implementation placed in the public domain.
6
7    Transcribed 2 October 2001, John Coffman.
8    Modified for FIPS PUB 180-1 (supercedes FIPS PUB 180)
9
10 */
11
12 #define _GNU_SOURCE
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "lilo.h"
17
18 #ifdef SHS_PASSWORDS
19
20 #include "shs2.h"
21
22 #define SHS_DEBUG  0
23 #define SHS_EXPAND 1
24
25 /*  The SHS f() - functions */
26
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)
31
32 /*  The SHS Mysterious Constants */
33
34 #define K1 0x5A827999L
35 #define K2 0x6ED9EBA1L
36 #define K3 0x8F1BBCDCL
37 #define K4 0xCA62C1D6L
38
39 /*  SHS initial values */
40
41 #define h0init 0x67452301L
42 #define h1init 0xEFCDAB89L
43 #define h2init 0x98BADCFEL
44 #define h3init 0x10325476L
45 #define h4init 0xC3D2E1F0L
46
47 /*  32-bit rotate -- uses shift kludge */
48
49 #define ROT(n,X) ((X<<n)|(X>>(32-n)))
50
51
52
53 /*  The initial expanding function */
54
55 #if SHS_EXPAND
56 #define expand(count) temp=W[count-3]^W[count-8]^W[count-14]^W[count-16], W[count]=ROT(1,temp)
57 #define w(t) W[t]
58 #else
59 #define w(t) (t<16?W[t]:(temp=W[(t+13)&15]^W[(t+8)&15]^W[(t+2)&15]^W[t&15],\
60 W[t&15]=ROT(1,temp)))
61 #endif
62
63 /*  The four SHS sub-rounds  */
64 #define subRound1(count) \
65    temp = f1(B,C,D) + K1 + E + w(count) + ROT(5,A),\
66    E = D,\
67    D = C,\
68    C = ROT(30,B),\
69    B = A,\
70    A = temp
71
72 #define subRound2(count) \
73    temp = f2(B,C,D) + K2 + E + w(count) + ROT(5,A),\
74    E = D,\
75    D = C,\
76    C = ROT(30,B),\
77    B = A,\
78    A = temp
79
80 #define subRound3(count) \
81    temp = f3(B,C,D) + K3 + E + w(count) + ROT(5,A),\
82    E = D,\
83    D = C,\
84    C = ROT(30,B),\
85    B = A,\
86    A = temp
87
88 #define subRound4(count) \
89    temp = f4(B,C,D) + K4 + E + w(count) + ROT(5,A),\
90    E = D,\
91    D = C,\
92    C = ROT(30,B),\
93    B = A,\
94    A = temp
95
96
97 SHS_INFO shsInfo;    /* global */
98 static
99 #if SHS_EXPAND
100    LONG W[80];
101 #else
102    LONG W[16];
103 #endif
104
105
106 /*  initialize the SHS values  */
107 void shsInit(void)
108 {
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;
114
115    shsInfo.countLo = shsInfo.countHi = 0L;
116 }
117
118
119 /*  perform the SHS transformation  */
120
121 static void shsTransform(void)
122 {
123    int i;
124    LONG A, B, C, D, E, temp;
125
126 /*  Step A.  Copy the data buffer into the work buffer */
127 /*  done  */
128 #if SHS_DEBUG>=1
129    for (i=0; i<16; i++)  printf("W[%d] = %08lX\n", i, W[i]);
130 #endif
131
132 /*  Step B.  Expand the 16 words into 64 temporary data words */
133 #if SHS_EXPAND
134    for (i=16; i<80; i++)  expand(i);
135 #endif
136
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];
143
144 /*  Step D.  Serious mangling, divided into 4 sub-rounds */
145    i = 0;
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);
150
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;
157
158 }
159
160 #ifdef LITTLE_ENDIAN
161 static void byteReverse(LONG buffer[], int byteCount)
162 {
163    int count;
164    LONG value;
165
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);
170    }
171 }
172 #endif
173
174
175 /*  Update SHS for a block of data */
176
177 void shsUpdate(BYTE *buffer, int count)
178 {
179    int remain;
180
181 /* calculate index of space remaining in the work buffer */
182    remain = shsInfo.countLo & (SHS_BLOCKSIZE-1);
183
184 /* update bitcount */
185    if ( (shsInfo.countLo + (LONG)count) < shsInfo.countLo )
186       shsInfo.countHi++;     /* carry into high bitcount */
187    shsInfo.countLo += (LONG)count;
188
189 /* Process data in SHS_BLOCKSIZE chunks */
190    while (count >= SHS_BLOCKSIZE-remain) {
191       memcpy((BYTE*)&W+remain, buffer, SHS_BLOCKSIZE-remain);
192 #ifdef LITTLE_ENDIAN
193       byteReverse(W, SHS_BLOCKSIZE);
194 #endif
195       shsTransform();
196       buffer += SHS_BLOCKSIZE-remain;
197       count -= SHS_BLOCKSIZE-remain;
198       remain = 0;
199    }
200
201 /* Handle any remaining bytes of data */
202    if (count) memcpy((BYTE*)&W+remain, buffer, count);
203 }
204
205
206 /*  Finalize the SHS function */
207 void shsFinal(void)
208 {
209    int count;
210
211 /* Compute number of bytes mod 64 */
212    count = shsInfo.countLo & (SHS_BLOCKSIZE-1);
213
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;
217
218 /* Pad out to 56 mod 64 */
219    if (count > 56) {
220       memset((BYTE*)W + count, 0, SHS_BLOCKSIZE-count);
221 #ifdef LITTLE_ENDIAN
222       byteReverse(W, SHS_BLOCKSIZE);
223 #endif
224       shsTransform ();
225
226 /* Now fill the next block with 56 bytes */
227       memset( W, 0, SHS_BLOCKSIZE-8);
228    }
229    else { /* Pad block to 56 bytes */
230       memset((BYTE*)W + count, 0, (SHS_BLOCKSIZE-8)-count);
231    }
232 #ifdef LITTLE_ENDIAN
233    byteReverse(W, SHS_BLOCKSIZE-8);
234 #endif
235 /* Append length in bits and transform */
236    W[14] = (shsInfo.countHi<<3) + (shsInfo.countLo>>29);
237    W[15] = shsInfo.countLo<<3;
238
239    shsTransform ();
240 }
241 #endif  /* SHS_PASSWORDS */
242 /* end shs2.c */
243