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