/src/nettle/sha512-compress.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* sha512-compress.c  | 
2  |  |  | 
3  |  |    The compression function of the sha512 hash function.  | 
4  |  |  | 
5  |  |    Copyright (C) 2001, 2010 Niels Möller  | 
6  |  |  | 
7  |  |    This file is part of GNU Nettle.  | 
8  |  |  | 
9  |  |    GNU Nettle is free software: you can redistribute it and/or  | 
10  |  |    modify it under the terms of either:  | 
11  |  |  | 
12  |  |      * the GNU Lesser General Public License as published by the Free  | 
13  |  |        Software Foundation; either version 3 of the License, or (at your  | 
14  |  |        option) any later version.  | 
15  |  |  | 
16  |  |    or  | 
17  |  |  | 
18  |  |      * the GNU General Public License as published by the Free  | 
19  |  |        Software Foundation; either version 2 of the License, or (at your  | 
20  |  |        option) any later version.  | 
21  |  |  | 
22  |  |    or both in parallel, as here.  | 
23  |  |  | 
24  |  |    GNU Nettle is distributed in the hope that it will be useful,  | 
25  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of  | 
26  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  | 
27  |  |    General Public License for more details.  | 
28  |  |  | 
29  |  |    You should have received copies of the GNU General Public License and  | 
30  |  |    the GNU Lesser General Public License along with this program.  If  | 
31  |  |    not, see http://www.gnu.org/licenses/.  | 
32  |  | */  | 
33  |  |  | 
34  |  | #if HAVE_CONFIG_H  | 
35  |  | # include "config.h"  | 
36  |  | #endif  | 
37  |  |  | 
38  |  | #ifndef SHA512_DEBUG  | 
39  |  | # define SHA512_DEBUG 0  | 
40  |  | #endif  | 
41  |  |  | 
42  |  | #if SHA512_DEBUG  | 
43  |  | # include <stdio.h>  | 
44  |  | # define DEBUG(i) \  | 
45  |  |   fprintf(stderr, "%2d: %8lx %8lx %8lx %8lx\n    %8lx %8lx %8lx %8lx\n", \  | 
46  |  |     i, A, B, C, D ,E, F, G, H)  | 
47  |  | #else  | 
48  |  | # define DEBUG(i)  | 
49  |  | #endif  | 
50  |  |  | 
51  |  | #include <assert.h>  | 
52  |  | #include <stdlib.h>  | 
53  |  | #include <string.h>  | 
54  |  |  | 
55  |  | #include "sha2.h"  | 
56  |  | #include "sha2-internal.h"  | 
57  |  |  | 
58  |  | #include "macros.h"  | 
59  |  |  | 
60  |  | /* A block, treated as a sequence of 64-bit words. */  | 
61  | 0  | #define SHA512_DATA_LENGTH 16  | 
62  |  |  | 
63  |  | /* For fat builds */  | 
64  |  | #if HAVE_NATIVE_sha512_compress  | 
65  |  | void  | 
66  |  | _nettle_sha512_compress_c (uint64_t *state, const uint8_t *input, const uint64_t *k);  | 
67  |  | #define _nettle_sha512_compress _nettle_sha512_compress_c  | 
68  |  | #endif  | 
69  |  |  | 
70  |  | /* The SHA512 functions. The Choice function is the same as the SHA1  | 
71  |  |    function f1, and the majority function is the same as the SHA1 f3  | 
72  |  |    function, and the same as for SHA256. */  | 
73  |  |  | 
74  | 0  | #define Choice(x,y,z)   ( (z) ^ ( (x) & ( (y) ^ (z) ) ) )   | 
75  | 0  | #define Majority(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )  | 
76  |  |  | 
77  | 0  | #define S0(x) (ROTL64(36,(x)) ^ ROTL64(30,(x)) ^ ROTL64(25,(x)))   | 
78  | 0  | #define S1(x) (ROTL64(50,(x)) ^ ROTL64(46,(x)) ^ ROTL64(23,(x)))  | 
79  |  |  | 
80  |  | #define s0(x) (ROTL64(63,(x)) ^ ROTL64(56,(x)) ^ ((x) >> 7))  | 
81  |  | #define s1(x) (ROTL64(45,(x)) ^ ROTL64(3,(x)) ^ ((x) >> 6))  | 
82  |  |  | 
83  |  | /* The initial expanding function. The hash function is defined over  | 
84  |  |    an 64-word expanded input array W, where the first 16 are copies of  | 
85  |  |    the input data, and the remaining 64 are defined by  | 
86  |  |  | 
87  |  |         W[ t ] = s1(W[t-2]) + W[t-7] + s0(W[i-15]) + W[i-16]  | 
88  |  |  | 
89  |  |    This implementation generates these values on the fly in a circular  | 
90  |  |    buffer.  | 
91  |  | */  | 
92  |  |  | 
93  |  | #define EXPAND(W,i) \  | 
94  |  | ( W[(i) & 15 ] += (s1(W[((i)-2) & 15]) + W[((i)-7) & 15] + s0(W[((i)-15) & 15])) )  | 
95  |  |  | 
96  |  | /* The prototype SHA sub-round.  The fundamental sub-round is:  | 
97  |  |  | 
98  |  |         T1 = h + S1(e) + Choice(e,f,g) + K[t] + W[t]  | 
99  |  |   T2 = S0(a) + Majority(a,b,c)  | 
100  |  |   a' = T1+T2  | 
101  |  |   b' = a  | 
102  |  |   c' = b  | 
103  |  |   d' = c  | 
104  |  |   e' = d + T1  | 
105  |  |   f' = e  | 
106  |  |   g' = f  | 
107  |  |   h' = g  | 
108  |  |  | 
109  |  |    but this is implemented by unrolling the loop 8 times and renaming  | 
110  |  |    the variables  | 
111  |  |    ( h, a, b, c, d, e, f, g ) = ( a, b, c, d, e, f, g, h ) each  | 
112  |  |    iteration. This code is then replicated 8, using the next 8 values  | 
113  |  |    from the W[] array each time */  | 
114  |  |  | 
115  |  | /* It's crucial that DATA is only used once, as that argument will  | 
116  |  |  * have side effects. */  | 
117  | 0  | #define ROUND(a,b,c,d,e,f,g,h,k,data) do { \ | 
118  | 0  |   h += S1(e) + Choice(e,f,g) + k + data; \  | 
119  | 0  |   d += h;         \  | 
120  | 0  |   h += S0(a) + Majority(a,b,c);      \  | 
121  | 0  | } while (0)  | 
122  |  |  | 
123  |  | void  | 
124  |  | _nettle_sha512_compress(uint64_t *state, const uint8_t *input, const uint64_t *k)  | 
125  | 0  | { | 
126  | 0  |   uint64_t data[SHA512_DATA_LENGTH];  | 
127  | 0  |   uint64_t A, B, C, D, E, F, G, H;     /* Local vars */  | 
128  | 0  |   unsigned i;  | 
129  | 0  |   uint64_t *d;  | 
130  |  | 
  | 
131  | 0  |   for (i = 0; i < SHA512_DATA_LENGTH; i++, input += 8)  | 
132  | 0  |     { | 
133  | 0  |       data[i] = READ_UINT64(input);  | 
134  | 0  |     }  | 
135  |  |  | 
136  |  |   /* Set up first buffer and local data buffer */  | 
137  | 0  |   A = state[0];  | 
138  | 0  |   B = state[1];  | 
139  | 0  |   C = state[2];  | 
140  | 0  |   D = state[3];  | 
141  | 0  |   E = state[4];  | 
142  | 0  |   F = state[5];  | 
143  | 0  |   G = state[6];  | 
144  | 0  |   H = state[7];  | 
145  |  |     | 
146  |  |   /* Heavy mangling */  | 
147  |  |   /* First 16 subrounds that act on the original data */  | 
148  |  | 
  | 
149  | 0  |   DEBUG(-1);  | 
150  | 0  |   for (i = 0, d = data; i<16; i+=8, k += 8, d+= 8)  | 
151  | 0  |     { | 
152  | 0  |       ROUND(A, B, C, D, E, F, G, H, k[0], d[0]); DEBUG(i);  | 
153  | 0  |       ROUND(H, A, B, C, D, E, F, G, k[1], d[1]); DEBUG(i+1);  | 
154  | 0  |       ROUND(G, H, A, B, C, D, E, F, k[2], d[2]);  | 
155  | 0  |       ROUND(F, G, H, A, B, C, D, E, k[3], d[3]);  | 
156  | 0  |       ROUND(E, F, G, H, A, B, C, D, k[4], d[4]);  | 
157  | 0  |       ROUND(D, E, F, G, H, A, B, C, k[5], d[5]);  | 
158  | 0  |       ROUND(C, D, E, F, G, H, A, B, k[6], d[6]); DEBUG(i+6);  | 
159  | 0  |       ROUND(B, C, D, E, F, G, H, A, k[7], d[7]); DEBUG(i+7);  | 
160  | 0  |     }  | 
161  |  |     | 
162  | 0  |   for (; i<80; i += 16, k+= 16)  | 
163  | 0  |     { | 
164  | 0  |       ROUND(A, B, C, D, E, F, G, H, k[ 0], EXPAND(data,  0)); DEBUG(i);  | 
165  | 0  |       ROUND(H, A, B, C, D, E, F, G, k[ 1], EXPAND(data,  1)); DEBUG(i+1);  | 
166  | 0  |       ROUND(G, H, A, B, C, D, E, F, k[ 2], EXPAND(data,  2)); DEBUG(i+2);  | 
167  | 0  |       ROUND(F, G, H, A, B, C, D, E, k[ 3], EXPAND(data,  3));  | 
168  | 0  |       ROUND(E, F, G, H, A, B, C, D, k[ 4], EXPAND(data,  4));  | 
169  | 0  |       ROUND(D, E, F, G, H, A, B, C, k[ 5], EXPAND(data,  5));  | 
170  | 0  |       ROUND(C, D, E, F, G, H, A, B, k[ 6], EXPAND(data,  6));  | 
171  | 0  |       ROUND(B, C, D, E, F, G, H, A, k[ 7], EXPAND(data,  7));  | 
172  | 0  |       ROUND(A, B, C, D, E, F, G, H, k[ 8], EXPAND(data,  8));  | 
173  | 0  |       ROUND(H, A, B, C, D, E, F, G, k[ 9], EXPAND(data,  9));  | 
174  | 0  |       ROUND(G, H, A, B, C, D, E, F, k[10], EXPAND(data, 10));  | 
175  | 0  |       ROUND(F, G, H, A, B, C, D, E, k[11], EXPAND(data, 11));  | 
176  | 0  |       ROUND(E, F, G, H, A, B, C, D, k[12], EXPAND(data, 12));  | 
177  | 0  |       ROUND(D, E, F, G, H, A, B, C, k[13], EXPAND(data, 13));  | 
178  | 0  |       ROUND(C, D, E, F, G, H, A, B, k[14], EXPAND(data, 14)); DEBUG(i+14);  | 
179  | 0  |       ROUND(B, C, D, E, F, G, H, A, k[15], EXPAND(data, 15)); DEBUG(i+15);  | 
180  | 0  |     }  | 
181  |  |  | 
182  |  |   /* Update state */  | 
183  | 0  |   state[0] += A;  | 
184  | 0  |   state[1] += B;  | 
185  | 0  |   state[2] += C;  | 
186  | 0  |   state[3] += D;  | 
187  | 0  |   state[4] += E;  | 
188  | 0  |   state[5] += F;  | 
189  | 0  |   state[6] += G;  | 
190  | 0  |   state[7] += H;  | 
191  |  | #if SHA512_DEBUG  | 
192  |  |   fprintf(stderr, "99: %8lx %8lx %8lx %8lx\n    %8lx %8lx %8lx %8lx\n",  | 
193  |  |     state[0], state[1], state[2], state[3],  | 
194  |  |     state[4], state[5], state[6], state[7]);  | 
195  |  | #endif  | 
196  | 0  | }  |