/src/krb5/src/lib/crypto/builtin/sha1/shs.c
Line | Count | Source |
1 | | /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
2 | | #include "shs.h" |
3 | | #ifdef HAVE_SYS_TYPES_H |
4 | | #include <sys/types.h> |
5 | | #endif |
6 | | #include <string.h> |
7 | | |
8 | | #ifdef K5_BUILTIN_SHA1 |
9 | | |
10 | | /* The SHS f()-functions. The f1 and f3 functions can be optimized to |
11 | | save one boolean operation each - thanks to Rich Schroeppel, |
12 | | rcs@cs.arizona.edu for discovering this */ |
13 | | |
14 | 431k | #define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ |
15 | 431k | #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ |
16 | 431k | #define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ |
17 | 431k | #define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ |
18 | | |
19 | | /* The SHS Mysterious Constants */ |
20 | | |
21 | | #define K1 0x5A827999L /* Rounds 0-19 */ |
22 | | #define K2 0x6ED9EBA1L /* Rounds 20-39 */ |
23 | | #define K3 0x8F1BBCDCL /* Rounds 40-59 */ |
24 | | #define K4 0xCA62C1D6L /* Rounds 60-79 */ |
25 | | |
26 | | /* SHS initial values */ |
27 | | |
28 | 6.68k | #define h0init 0x67452301L |
29 | 6.68k | #define h1init 0xEFCDAB89L |
30 | 6.68k | #define h2init 0x98BADCFEL |
31 | 6.68k | #define h3init 0x10325476L |
32 | 6.68k | #define h4init 0xC3D2E1F0L |
33 | | |
34 | | /* Note that it may be necessary to add parentheses to these macros if they |
35 | | are to be called with expressions as arguments */ |
36 | | |
37 | | /* 32-bit rotate left - kludged with shifts */ |
38 | | |
39 | 3.45M | #define ROTL(n,X) ((((X) << (n)) & 0xffffffff) | ((X) >> (32 - n))) |
40 | | |
41 | | /* The initial expanding function. The hash function is defined over an |
42 | | 80-word expanded input array W, where the first 16 are copies of the input |
43 | | data, and the remaining 64 are defined by |
44 | | |
45 | | W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ] |
46 | | |
47 | | This implementation generates these values on the fly in a circular |
48 | | buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this |
49 | | optimization. |
50 | | |
51 | | The updated SHS changes the expanding function by adding a rotate of 1 |
52 | | bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor |
53 | | for this information */ |
54 | | |
55 | | #ifdef NEW_SHS |
56 | | #define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ |
57 | | W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ))) |
58 | | #else |
59 | | #define expand(W,i) ( W[ i & 15 ] ^= W[ (i - 14) & 15 ] ^ \ |
60 | | W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) |
61 | | #endif /* NEW_SHS */ |
62 | | |
63 | | /* The prototype SHS sub-round. The fundamental sub-round is: |
64 | | |
65 | | a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; |
66 | | b' = a; |
67 | | c' = ROTL( 30, b ); |
68 | | d' = c; |
69 | | e' = d; |
70 | | |
71 | | but this is implemented by unrolling the loop 5 times and renaming the |
72 | | variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. |
73 | | This code is then replicated 20 times for each of the 4 functions, using |
74 | | the next 20 values from the W[] array each time */ |
75 | | |
76 | | #define subRound(a, b, c, d, e, f, k, data) \ |
77 | 1.72M | ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, \ |
78 | 1.72M | e &= 0xffffffff, b = ROTL( 30, b ) ) |
79 | | |
80 | | /* Initialize the SHS values */ |
81 | | |
82 | | void shsInit(SHS_INFO *shsInfo) |
83 | 6.68k | { |
84 | | /* Set the h-vars to their initial values */ |
85 | 6.68k | shsInfo->digest[ 0 ] = h0init; |
86 | 6.68k | shsInfo->digest[ 1 ] = h1init; |
87 | 6.68k | shsInfo->digest[ 2 ] = h2init; |
88 | 6.68k | shsInfo->digest[ 3 ] = h3init; |
89 | 6.68k | shsInfo->digest[ 4 ] = h4init; |
90 | | |
91 | | /* Initialise bit count */ |
92 | 6.68k | shsInfo->countLo = shsInfo->countHi = 0; |
93 | 6.68k | } |
94 | | |
95 | | /* Perform the SHS transformation. Note that this code, like MD5, seems to |
96 | | break some optimizing compilers due to the complexity of the expressions |
97 | | and the size of the basic block. It may be necessary to split it into |
98 | | sections, e.g. based on the four subrounds |
99 | | |
100 | | Note that this corrupts the shsInfo->data area */ |
101 | | |
102 | | static void SHSTransform (SHS_LONG *digest, const SHS_LONG *data); |
103 | | |
104 | | static |
105 | | void SHSTransform(SHS_LONG *digest, const SHS_LONG *data) |
106 | 21.5k | { |
107 | 21.5k | SHS_LONG A, B, C, D, E; /* Local vars */ |
108 | 21.5k | SHS_LONG eData[ 16 ]; /* Expanded data */ |
109 | | |
110 | | /* Set up first buffer and local data buffer */ |
111 | 21.5k | A = digest[ 0 ]; |
112 | 21.5k | B = digest[ 1 ]; |
113 | 21.5k | C = digest[ 2 ]; |
114 | 21.5k | D = digest[ 3 ]; |
115 | 21.5k | E = digest[ 4 ]; |
116 | 21.5k | memcpy(eData, data, sizeof (eData)); |
117 | | |
118 | | #if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) |
119 | | |
120 | | { |
121 | | int i; |
122 | | SHS_LONG temp; |
123 | | for (i = 0; i < 20; i++) { |
124 | | SHS_LONG x = (i < 16) ? eData[i] : expand(eData, i); |
125 | | subRound(A, B, C, D, E, f1, K1, x); |
126 | | temp = E, E = D, D = C, C = B, B = A, A = temp; |
127 | | } |
128 | | for (i = 20; i < 40; i++) { |
129 | | subRound(A, B, C, D, E, f2, K2, expand(eData, i)); |
130 | | temp = E, E = D, D = C, C = B, B = A, A = temp; |
131 | | } |
132 | | for (i = 40; i < 60; i++) { |
133 | | subRound(A, B, C, D, E, f3, K3, expand(eData, i)); |
134 | | temp = E, E = D, D = C, C = B, B = A, A = temp; |
135 | | } |
136 | | for (i = 60; i < 80; i++) { |
137 | | subRound(A, B, C, D, E, f4, K4, expand(eData, i)); |
138 | | temp = E, E = D, D = C, C = B, B = A, A = temp; |
139 | | } |
140 | | } |
141 | | |
142 | | #else |
143 | | |
144 | | /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */ |
145 | 21.5k | subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); |
146 | 21.5k | subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); |
147 | 21.5k | subRound( D, E, A, B, C, f1, K1, eData[ 2 ] ); |
148 | 21.5k | subRound( C, D, E, A, B, f1, K1, eData[ 3 ] ); |
149 | 21.5k | subRound( B, C, D, E, A, f1, K1, eData[ 4 ] ); |
150 | 21.5k | subRound( A, B, C, D, E, f1, K1, eData[ 5 ] ); |
151 | 21.5k | subRound( E, A, B, C, D, f1, K1, eData[ 6 ] ); |
152 | 21.5k | subRound( D, E, A, B, C, f1, K1, eData[ 7 ] ); |
153 | 21.5k | subRound( C, D, E, A, B, f1, K1, eData[ 8 ] ); |
154 | 21.5k | subRound( B, C, D, E, A, f1, K1, eData[ 9 ] ); |
155 | 21.5k | subRound( A, B, C, D, E, f1, K1, eData[ 10 ] ); |
156 | 21.5k | subRound( E, A, B, C, D, f1, K1, eData[ 11 ] ); |
157 | 21.5k | subRound( D, E, A, B, C, f1, K1, eData[ 12 ] ); |
158 | 21.5k | subRound( C, D, E, A, B, f1, K1, eData[ 13 ] ); |
159 | 21.5k | subRound( B, C, D, E, A, f1, K1, eData[ 14 ] ); |
160 | 21.5k | subRound( A, B, C, D, E, f1, K1, eData[ 15 ] ); |
161 | 21.5k | subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) ); |
162 | 21.5k | subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) ); |
163 | 21.5k | subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) ); |
164 | 21.5k | subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) ); |
165 | | |
166 | 21.5k | subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) ); |
167 | 21.5k | subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) ); |
168 | 21.5k | subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) ); |
169 | 21.5k | subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) ); |
170 | 21.5k | subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) ); |
171 | 21.5k | subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) ); |
172 | 21.5k | subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) ); |
173 | 21.5k | subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) ); |
174 | 21.5k | subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) ); |
175 | 21.5k | subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) ); |
176 | 21.5k | subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) ); |
177 | 21.5k | subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) ); |
178 | 21.5k | subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) ); |
179 | 21.5k | subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) ); |
180 | 21.5k | subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) ); |
181 | 21.5k | subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) ); |
182 | 21.5k | subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) ); |
183 | 21.5k | subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) ); |
184 | 21.5k | subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) ); |
185 | 21.5k | subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) ); |
186 | | |
187 | 21.5k | subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) ); |
188 | 21.5k | subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) ); |
189 | 21.5k | subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) ); |
190 | 21.5k | subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) ); |
191 | 21.5k | subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) ); |
192 | 21.5k | subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) ); |
193 | 21.5k | subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) ); |
194 | 21.5k | subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) ); |
195 | 21.5k | subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) ); |
196 | 21.5k | subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) ); |
197 | 21.5k | subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) ); |
198 | 21.5k | subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) ); |
199 | 21.5k | subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) ); |
200 | 21.5k | subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) ); |
201 | 21.5k | subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) ); |
202 | 21.5k | subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) ); |
203 | 21.5k | subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) ); |
204 | 21.5k | subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) ); |
205 | 21.5k | subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) ); |
206 | 21.5k | subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) ); |
207 | | |
208 | 21.5k | subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) ); |
209 | 21.5k | subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) ); |
210 | 21.5k | subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) ); |
211 | 21.5k | subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) ); |
212 | 21.5k | subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) ); |
213 | 21.5k | subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) ); |
214 | 21.5k | subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) ); |
215 | 21.5k | subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) ); |
216 | 21.5k | subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) ); |
217 | 21.5k | subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) ); |
218 | 21.5k | subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) ); |
219 | 21.5k | subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) ); |
220 | 21.5k | subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) ); |
221 | 21.5k | subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) ); |
222 | 21.5k | subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) ); |
223 | 21.5k | subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) ); |
224 | 21.5k | subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) ); |
225 | 21.5k | subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); |
226 | 21.5k | subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); |
227 | 21.5k | subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) ); |
228 | | |
229 | 21.5k | #endif |
230 | | |
231 | | /* Build message digest */ |
232 | 21.5k | digest[ 0 ] += A; |
233 | 21.5k | digest[ 0 ] &= 0xffffffff; |
234 | 21.5k | digest[ 1 ] += B; |
235 | 21.5k | digest[ 1 ] &= 0xffffffff; |
236 | 21.5k | digest[ 2 ] += C; |
237 | 21.5k | digest[ 2 ] &= 0xffffffff; |
238 | 21.5k | digest[ 3 ] += D; |
239 | 21.5k | digest[ 3 ] &= 0xffffffff; |
240 | 21.5k | digest[ 4 ] += E; |
241 | 21.5k | digest[ 4 ] &= 0xffffffff; |
242 | 21.5k | } |
243 | | |
244 | | /* Update SHS for a block of data */ |
245 | | |
246 | | void shsUpdate(SHS_INFO *shsInfo, const SHS_BYTE *buffer, unsigned int count) |
247 | 14.3k | { |
248 | 14.3k | SHS_LONG tmp; |
249 | 14.3k | unsigned int dataCount; |
250 | 14.3k | int canfill; |
251 | 14.3k | SHS_LONG *lp; |
252 | | |
253 | | /* Update bitcount */ |
254 | 14.3k | tmp = shsInfo->countLo; |
255 | 14.3k | shsInfo->countLo = tmp + (((SHS_LONG) count) << 3 ); |
256 | 14.3k | if ((shsInfo->countLo &= 0xffffffff) < tmp) |
257 | 0 | shsInfo->countHi++; /* Carry from low to high */ |
258 | 14.3k | shsInfo->countHi += count >> 29; |
259 | | |
260 | | /* Get count of bytes already in data */ |
261 | 14.3k | dataCount = (tmp >> 3) & 0x3F; |
262 | | |
263 | | /* Handle any leading odd-sized chunks */ |
264 | 14.3k | if (dataCount) { |
265 | 1.84k | lp = shsInfo->data + dataCount / 4; |
266 | 1.84k | dataCount = SHS_DATASIZE - dataCount; |
267 | 1.84k | canfill = (count >= dataCount); |
268 | | |
269 | 1.84k | if (dataCount % 4) { |
270 | | /* Fill out a full 32 bit word first if needed -- this |
271 | | is not very efficient (computed shift amount), |
272 | | but it shouldn't happen often. */ |
273 | 772 | while (dataCount % 4 && count > 0) { |
274 | 227 | *lp |= (SHS_LONG) *buffer++ << ((--dataCount % 4) * 8); |
275 | 227 | count--; |
276 | 227 | } |
277 | 545 | lp++; |
278 | 545 | } |
279 | 11.1k | while (lp < shsInfo->data + 16) { |
280 | 10.4k | if (count < 4) { |
281 | 1.15k | *lp = 0; |
282 | 1.15k | switch (count % 4) { |
283 | 57 | case 3: |
284 | 57 | *lp |= (SHS_LONG) buffer[2] << 8; |
285 | 144 | case 2: |
286 | 144 | *lp |= (SHS_LONG) buffer[1] << 16; |
287 | 196 | case 1: |
288 | 196 | *lp |= (SHS_LONG) buffer[0] << 24; |
289 | 1.15k | } |
290 | 1.15k | count = 0; |
291 | 1.15k | break; /* out of while loop */ |
292 | 1.15k | } |
293 | 9.27k | *lp++ = load_32_be(buffer); |
294 | 9.27k | buffer += 4; |
295 | 9.27k | count -= 4; |
296 | 9.27k | } |
297 | 1.84k | if (canfill) { |
298 | 655 | SHSTransform(shsInfo->digest, shsInfo->data); |
299 | 655 | } |
300 | 1.84k | } |
301 | | |
302 | | /* Process data in SHS_DATASIZE chunks */ |
303 | 28.0k | while (count >= SHS_DATASIZE) { |
304 | 13.6k | lp = shsInfo->data; |
305 | 232k | while (lp < shsInfo->data + 16) { |
306 | 218k | *lp++ = load_32_be(buffer); |
307 | 218k | buffer += 4; |
308 | 218k | } |
309 | 13.6k | SHSTransform(shsInfo->digest, shsInfo->data); |
310 | 13.6k | count -= SHS_DATASIZE; |
311 | 13.6k | } |
312 | | |
313 | 14.3k | if (count > 0) { |
314 | 7.18k | lp = shsInfo->data; |
315 | 44.1k | while (count > 4) { |
316 | 37.0k | *lp++ = load_32_be(buffer); |
317 | 37.0k | buffer += 4; |
318 | 37.0k | count -= 4; |
319 | 37.0k | } |
320 | 7.18k | *lp = 0; |
321 | 7.18k | switch (count % 4) { |
322 | 5.09k | case 0: |
323 | 5.09k | *lp |= ((SHS_LONG) buffer[3]); |
324 | 5.87k | case 3: |
325 | 5.87k | *lp |= ((SHS_LONG) buffer[2]) << 8; |
326 | 6.21k | case 2: |
327 | 6.21k | *lp |= ((SHS_LONG) buffer[1]) << 16; |
328 | 7.18k | case 1: |
329 | 7.18k | *lp |= ((SHS_LONG) buffer[0]) << 24; |
330 | 7.18k | } |
331 | 7.18k | } |
332 | 14.3k | } |
333 | | |
334 | | /* Final wrapup - pad to SHS_DATASIZE-byte boundary with the bit pattern |
335 | | 1 0* (64-bit count of bits processed, MSB-first) */ |
336 | | |
337 | | void shsFinal(SHS_INFO *shsInfo) |
338 | 6.68k | { |
339 | 6.68k | int count; |
340 | 6.68k | SHS_LONG *lp; |
341 | | |
342 | | /* Compute number of bytes mod 64 */ |
343 | 6.68k | count = (int) shsInfo->countLo; |
344 | 6.68k | count = (count >> 3) & 0x3F; |
345 | | |
346 | | /* Set the first char of padding to 0x80. This is safe since there is |
347 | | always at least one byte free */ |
348 | 6.68k | lp = shsInfo->data + count / 4; |
349 | 6.68k | switch (count % 4) { |
350 | 800 | case 3: |
351 | 800 | *lp++ |= (SHS_LONG) 0x80; |
352 | 800 | break; |
353 | 400 | case 2: |
354 | 400 | *lp++ |= (SHS_LONG) 0x80 << 8; |
355 | 400 | break; |
356 | 980 | case 1: |
357 | 980 | *lp++ |= (SHS_LONG) 0x80 << 16; |
358 | 980 | break; |
359 | 4.50k | case 0: |
360 | 4.50k | *lp++ = (SHS_LONG) 0x80 << 24; |
361 | 6.68k | } |
362 | | |
363 | | /* at this point, lp can point *past* shsInfo->data. If it points |
364 | | there, just Transform and reset. If it points to the last |
365 | | element, set that to zero. This pads out to 64 bytes if not |
366 | | enough room for length words */ |
367 | | |
368 | 6.68k | if (lp == shsInfo->data + 15) |
369 | 307 | *lp++ = 0; |
370 | | |
371 | 6.68k | if (lp == shsInfo->data + 16) { |
372 | 559 | SHSTransform(shsInfo->digest, shsInfo->data); |
373 | 559 | lp = shsInfo->data; |
374 | 559 | } |
375 | | |
376 | | /* Pad out to 56 bytes */ |
377 | 61.2k | while (lp < shsInfo->data + 14) |
378 | 54.5k | *lp++ = 0; |
379 | | |
380 | | /* Append length in bits and transform */ |
381 | 6.68k | *lp++ = shsInfo->countHi; |
382 | 6.68k | *lp++ = shsInfo->countLo; |
383 | 6.68k | SHSTransform(shsInfo->digest, shsInfo->data); |
384 | 6.68k | } |
385 | | |
386 | | #endif /* K5_BUILTIN_SHA1 */ |