9c7367bb6029baf4537690a3b2892b863683b250
[samba.git] / lib / crypto / sha512.c
1 /*
2  * Copyright (c) 2006, 2010 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #include "replace.h"
35 #include "sha512.h"
36
37 #ifndef min
38 #define min(a,b) (((a)>(b))?(b):(a))
39 #endif
40
41 /* Vector Crays doesn't have a good 32-bit type, or more precisely,
42    int32_t as defined by <bind/bitypes.h> isn't 32 bits, and we don't
43    want to depend in being able to redefine this type.  To cope with
44    this we have to clamp the result in some places to [0,2^32); no
45    need to do this on other machines.  Did I say this was a mess?
46    */
47
48 #ifdef _CRAY
49 #define CRAYFIX(X) ((X) & 0xffffffff)
50 #else
51 #define CRAYFIX(X) (X)
52 #endif
53
54 static inline uint32_t
55 cshift (uint32_t x, unsigned int n)
56 {
57     x = CRAYFIX(x);
58     return CRAYFIX((x << n) | (x >> (32 - n)));
59 }
60
61 static inline uint64_t
62 cshift64 (uint64_t x, unsigned int n)
63 {
64   return ((uint64_t)x << (uint64_t)n) | ((uint64_t)x >> ((uint64_t)64 - (uint64_t)n));
65 }
66
67
68 #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
69 #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
70
71 #define ROTR(x,n)   (((x)>>(n)) | ((x) << (64 - (n))))
72
73 #define Sigma0(x)       (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
74 #define Sigma1(x)       (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
75 #define sigma0(x)       (ROTR(x,1)  ^ ROTR(x,8)  ^ ((x)>>7))
76 #define sigma1(x)       (ROTR(x,19) ^ ROTR(x,61) ^ ((x)>>6))
77
78 #define A m->counter[0]
79 #define B m->counter[1]
80 #define C m->counter[2]
81 #define D m->counter[3]
82 #define E m->counter[4]
83 #define F m->counter[5]
84 #define G m->counter[6]
85 #define H m->counter[7]
86
87 static const uint64_t constant_512[80] = {
88     0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
89     0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
90     0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
91     0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
92     0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
93     0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
94     0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
95     0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
96     0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
97     0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
98     0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
99     0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
100     0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
101     0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
102     0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
103     0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
104     0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
105     0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
106     0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
107     0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
108     0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
109     0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
110     0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
111     0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
112     0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
113     0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
114     0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
115     0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
116     0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
117     0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
118     0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
119     0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
120     0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
121     0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
122     0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
123     0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
124     0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
125     0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
126     0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
127     0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
128 };
129
130 void
131 samba_SHA512_Init (SHA512_CTX *m)
132 {
133     m->sz[0] = 0;
134     m->sz[1] = 0;
135     A = 0x6a09e667f3bcc908ULL;
136     B = 0xbb67ae8584caa73bULL;
137     C = 0x3c6ef372fe94f82bULL;
138     D = 0xa54ff53a5f1d36f1ULL;
139     E = 0x510e527fade682d1ULL;
140     F = 0x9b05688c2b3e6c1fULL;
141     G = 0x1f83d9abfb41bd6bULL;
142     H = 0x5be0cd19137e2179ULL;
143 }
144
145 static void
146 calc (SHA512_CTX *m, uint64_t *in)
147 {
148     uint64_t AA, BB, CC, DD, EE, FF, GG, HH;
149     uint64_t data[80];
150     int i;
151
152     AA = A;
153     BB = B;
154     CC = C;
155     DD = D;
156     EE = E;
157     FF = F;
158     GG = G;
159     HH = H;
160
161     for (i = 0; i < 16; ++i)
162         data[i] = in[i];
163     for (i = 16; i < 80; ++i)
164         data[i] = sigma1(data[i-2]) + data[i-7] +
165             sigma0(data[i-15]) + data[i - 16];
166
167     for (i = 0; i < 80; i++) {
168         uint64_t T1, T2;
169
170         T1 = HH + Sigma1(EE) + Ch(EE, FF, GG) + constant_512[i] + data[i];
171         T2 = Sigma0(AA) + Maj(AA,BB,CC);
172
173         HH = GG;
174         GG = FF;
175         FF = EE;
176         EE = DD + T1;
177         DD = CC;
178         CC = BB;
179         BB = AA;
180         AA = T1 + T2;
181     }
182
183     A += AA;
184     B += BB;
185     C += CC;
186     D += DD;
187     E += EE;
188     F += FF;
189     G += GG;
190     H += HH;
191 }
192
193 /*
194  * From `Performance analysis of MD5' by Joseph D. Touch <touch@isi.edu>
195  */
196
197 #if !defined(WORDS_BIGENDIAN) || defined(_CRAY)
198 static inline uint64_t
199 swap_uint64_t (uint64_t t)
200 {
201     uint64_t temp;
202
203     temp   = cshift64(t, 32);
204     temp = ((temp & 0xff00ff00ff00ff00ULL) >> 8) |
205            ((temp & 0x00ff00ff00ff00ffULL) << 8);
206     return ((temp & 0xffff0000ffff0000ULL) >> 16) |
207            ((temp & 0x0000ffff0000ffffULL) << 16);
208 }
209
210 struct x64{
211     uint64_t a;
212     uint64_t b;
213 };
214 #endif
215
216 void
217 samba_SHA512_Update (SHA512_CTX *m, const void *v, size_t len)
218 {
219     const unsigned char *p = v;
220     size_t old_sz = m->sz[0];
221     size_t offset;
222
223     m->sz[0] += len * 8;
224     if (m->sz[0] < old_sz)
225         ++m->sz[1];
226     offset = (old_sz / 8) % 128;
227     while(len > 0){
228         size_t l = min(len, 128 - offset);
229         memcpy(m->save + offset, p, l);
230         offset += l;
231         p += l;
232         len -= l;
233         if(offset == 128){
234 #if !defined(WORDS_BIGENDIAN) || defined(_CRAY)
235             int i;
236             uint64_t current[16];
237             struct x64 *us = (struct x64*)m->save;
238             for(i = 0; i < 8; i++){
239                 current[2*i+0] = swap_uint64_t(us[i].a);
240                 current[2*i+1] = swap_uint64_t(us[i].b);
241             }
242             calc(m, current);
243 #else
244             calc(m, (uint64_t*)m->save);
245 #endif
246             offset = 0;
247         }
248     }
249 }
250
251 void
252 samba_SHA512_Final (void *res, SHA512_CTX *m)
253 {
254     unsigned char zeros[128 + 16];
255     unsigned offset = (m->sz[0] / 8) % 128;
256     unsigned int dstart = (240 - offset - 1) % 128 + 1;
257
258     *zeros = 0x80;
259     memset (zeros + 1, 0, sizeof(zeros) - 1);
260     zeros[dstart+15] = (m->sz[0] >> 0) & 0xff;
261     zeros[dstart+14] = (m->sz[0] >> 8) & 0xff;
262     zeros[dstart+13] = (m->sz[0] >> 16) & 0xff;
263     zeros[dstart+12] = (m->sz[0] >> 24) & 0xff;
264     zeros[dstart+11] = (m->sz[0] >> 32) & 0xff;
265     zeros[dstart+10] = (m->sz[0] >> 40) & 0xff;
266     zeros[dstart+9]  = (m->sz[0] >> 48) & 0xff;
267     zeros[dstart+8]  = (m->sz[0] >> 56) & 0xff;
268
269     zeros[dstart+7] = (m->sz[1] >> 0) & 0xff;
270     zeros[dstart+6] = (m->sz[1] >> 8) & 0xff;
271     zeros[dstart+5] = (m->sz[1] >> 16) & 0xff;
272     zeros[dstart+4] = (m->sz[1] >> 24) & 0xff;
273     zeros[dstart+3] = (m->sz[1] >> 32) & 0xff;
274     zeros[dstart+2] = (m->sz[1] >> 40) & 0xff;
275     zeros[dstart+1] = (m->sz[1] >> 48) & 0xff;
276     zeros[dstart+0] = (m->sz[1] >> 56) & 0xff;
277     samba_SHA512_Update (m, zeros, dstart + 16);
278     {
279         int i;
280         unsigned char *r = (unsigned char*)res;
281
282         for (i = 0; i < 8; ++i) {
283             r[8*i+7] = m->counter[i] & 0xFF;
284             r[8*i+6] = (m->counter[i] >> 8) & 0xFF;
285             r[8*i+5] = (m->counter[i] >> 16) & 0xFF;
286             r[8*i+4] = (m->counter[i] >> 24) & 0xFF;
287             r[8*i+3] = (m->counter[i] >> 32) & 0XFF;
288             r[8*i+2] = (m->counter[i] >> 40) & 0xFF;
289             r[8*i+1] = (m->counter[i] >> 48) & 0xFF;
290             r[8*i]   = (m->counter[i] >> 56) & 0xFF;
291         }
292     }
293 }