182095Simp/*	$NetBSD: sha512.c,v 1.2 2017/01/28 21:31:47 christos Exp $	*/
299638Simp
382095Simp/*
482095Simp * Copyright (c) 2006, 2010 Kungliga Tekniska H��gskolan
582095Simp * (Royal Institute of Technology, Stockholm, Sweden).
682095Simp * All rights reserved.
782095Simp *
882095Simp * Redistribution and use in source and binary forms, with or without
982095Simp * modification, are permitted provided that the following conditions
1082095Simp * are met:
1182095Simp *
1282095Simp * 1. Redistributions of source code must retain the above copyright
1382095Simp *    notice, this list of conditions and the following disclaimer.
1482095Simp *
1582095Simp * 2. Redistributions in binary form must reproduce the above copyright
1682095Simp *    notice, this list of conditions and the following disclaimer in the
1782095Simp *    documentation and/or other materials provided with the distribution.
1882095Simp *
1982095Simp * 3. Neither the name of the Institute nor the names of its contributors
2082095Simp *    may be used to endorse or promote products derived from this software
2182095Simp *    without specific prior written permission.
2282095Simp *
2382095Simp * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2482095Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25141580Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2682095Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2799638Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2882095Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2982447Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3082095Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3182095Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32119169Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3382095Simp * SUCH DAMAGE.
3482095Simp */
3599637Simp
3682095Simp#include <config.h>
3782095Simp#include <krb5/roken.h>
3882095Simp
39101805Sru#include "hash.h"
4082095Simp#include "sha.h"
4182095Simp
4282095Simp#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
4382095Simp#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
4499637Simp
4582095Simp#define ROTR(x,n)   (((x)>>(n)) | ((x) << (64 - (n))))
4699637Simp
4782095Simp#define Sigma0(x)	(ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
4899637Simp#define Sigma1(x)	(ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
4982095Simp#define sigma0(x)	(ROTR(x,1)  ^ ROTR(x,8)  ^ ((x)>>7))
5082095Simp#define sigma1(x)	(ROTR(x,19) ^ ROTR(x,61) ^ ((x)>>6))
5182095Simp
5282095Simp#define A m->counter[0]
5382447Simp#define B m->counter[1]
5482095Simp#define C m->counter[2]
5582095Simp#define D m->counter[3]
5682095Simp#define E m->counter[4]
5782095Simp#define F m->counter[5]
5882447Simp#define G m->counter[6]
59119169Simp#define H m->counter[7]
6082095Simp
6182447Simpstatic const uint64_t constant_512[80] = {
6282447Simp    0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
6382095Simp    0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
6482095Simp    0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
6582095Simp    0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
6682095Simp    0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
6782095Simp    0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
6882095Simp    0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
6982095Simp    0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
7082447Simp    0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
7182095Simp    0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
7282095Simp    0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
7382095Simp    0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
74119169Simp    0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
7582447Simp    0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
7682095Simp    0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
7782095Simp    0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
7882095Simp    0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
7982447Simp    0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
8082095Simp    0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
8182095Simp    0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
8282095Simp    0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
8382095Simp    0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
8482095Simp    0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
8582095Simp    0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
8682447Simp    0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
8782095Simp    0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
8882095Simp    0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
8982095Simp    0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
9082095Simp    0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
9182095Simp    0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
9282095Simp    0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
9399637Simp    0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
9482447Simp    0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
9582095Simp    0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
9682095Simp    0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
9782095Simp    0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
9882095Simp    0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
9982095Simp    0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
10082095Simp    0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
10182447Simp    0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
10282095Simp};
10399637Simp
104int
105SHA512_Init (SHA512_CTX *m)
106{
107    m->sz[0] = 0;
108    m->sz[1] = 0;
109    A = 0x6a09e667f3bcc908ULL;
110    B = 0xbb67ae8584caa73bULL;
111    C = 0x3c6ef372fe94f82bULL;
112    D = 0xa54ff53a5f1d36f1ULL;
113    E = 0x510e527fade682d1ULL;
114    F = 0x9b05688c2b3e6c1fULL;
115    G = 0x1f83d9abfb41bd6bULL;
116    H = 0x5be0cd19137e2179ULL;
117    return 1;
118}
119
120static void
121calc (SHA512_CTX *m, uint64_t *in)
122{
123    uint64_t AA, BB, CC, DD, EE, FF, GG, HH;
124    uint64_t data[80];
125    int i;
126
127    AA = A;
128    BB = B;
129    CC = C;
130    DD = D;
131    EE = E;
132    FF = F;
133    GG = G;
134    HH = H;
135
136    for (i = 0; i < 16; ++i)
137	data[i] = in[i];
138    for (i = 16; i < 80; ++i)
139	data[i] = sigma1(data[i-2]) + data[i-7] +
140	    sigma0(data[i-15]) + data[i - 16];
141
142    for (i = 0; i < 80; i++) {
143	uint64_t T1, T2;
144
145	T1 = HH + Sigma1(EE) + Ch(EE, FF, GG) + constant_512[i] + data[i];
146	T2 = Sigma0(AA) + Maj(AA,BB,CC);
147
148	HH = GG;
149	GG = FF;
150	FF = EE;
151	EE = DD + T1;
152	DD = CC;
153	CC = BB;
154	BB = AA;
155	AA = T1 + T2;
156    }
157
158    A += AA;
159    B += BB;
160    C += CC;
161    D += DD;
162    E += EE;
163    F += FF;
164    G += GG;
165    H += HH;
166}
167
168/*
169 * From `Performance analysis of MD5' by Joseph D. Touch <touch@isi.edu>
170 */
171
172#if !defined(WORDS_BIGENDIAN) || defined(_CRAY)
173static inline uint64_t
174swap_uint64_t (uint64_t t)
175{
176    uint64_t temp;
177
178    temp   = cshift64(t, 32);
179    temp = ((temp & 0xff00ff00ff00ff00ULL) >> 8) |
180           ((temp & 0x00ff00ff00ff00ffULL) << 8);
181    return ((temp & 0xffff0000ffff0000ULL) >> 16) |
182           ((temp & 0x0000ffff0000ffffULL) << 16);
183}
184
185struct x64{
186    uint64_t a;
187    uint64_t b;
188};
189#endif
190
191int
192SHA512_Update (SHA512_CTX *m, const void *v, size_t len)
193{
194    const unsigned char *p = v;
195    size_t old_sz = m->sz[0];
196    size_t offset;
197
198    m->sz[0] += len * 8;
199    if (m->sz[0] < old_sz)
200	++m->sz[1];
201    offset = (old_sz / 8) % 128;
202    while(len > 0){
203	size_t l = min(len, 128 - offset);
204	memcpy(m->save + offset, p, l);
205	offset += l;
206	p += l;
207	len -= l;
208	if(offset == 128){
209#if !defined(WORDS_BIGENDIAN) || defined(_CRAY)
210	    int i;
211	    uint64_t current[16];
212	    struct x64 *us = (struct x64*)m->save;
213	    for(i = 0; i < 8; i++){
214		current[2*i+0] = swap_uint64_t(us[i].a);
215		current[2*i+1] = swap_uint64_t(us[i].b);
216	    }
217	    calc(m, current);
218#else
219	    calc(m, (uint64_t*)m->save);
220#endif
221	    offset = 0;
222	}
223    }
224    return 1;
225}
226
227int
228SHA512_Final (void *res, SHA512_CTX *m)
229{
230    unsigned char zeros[128 + 16];
231    unsigned offset = (m->sz[0] / 8) % 128;
232    unsigned int dstart = (240 - offset - 1) % 128 + 1;
233
234    *zeros = 0x80;
235    memset (zeros + 1, 0, sizeof(zeros) - 1);
236    zeros[dstart+15] = (m->sz[0] >> 0) & 0xff;
237    zeros[dstart+14] = (m->sz[0] >> 8) & 0xff;
238    zeros[dstart+13] = (m->sz[0] >> 16) & 0xff;
239    zeros[dstart+12] = (m->sz[0] >> 24) & 0xff;
240    zeros[dstart+11] = (m->sz[0] >> 32) & 0xff;
241    zeros[dstart+10] = (m->sz[0] >> 40) & 0xff;
242    zeros[dstart+9]  = (m->sz[0] >> 48) & 0xff;
243    zeros[dstart+8]  = (m->sz[0] >> 56) & 0xff;
244
245    zeros[dstart+7] = (m->sz[1] >> 0) & 0xff;
246    zeros[dstart+6] = (m->sz[1] >> 8) & 0xff;
247    zeros[dstart+5] = (m->sz[1] >> 16) & 0xff;
248    zeros[dstart+4] = (m->sz[1] >> 24) & 0xff;
249    zeros[dstart+3] = (m->sz[1] >> 32) & 0xff;
250    zeros[dstart+2] = (m->sz[1] >> 40) & 0xff;
251    zeros[dstart+1] = (m->sz[1] >> 48) & 0xff;
252    zeros[dstart+0] = (m->sz[1] >> 56) & 0xff;
253    SHA512_Update (m, zeros, dstart + 16);
254    {
255	int i;
256	unsigned char *r = (unsigned char*)res;
257
258	for (i = 0; i < 8; ++i) {
259	    r[8*i+7] = m->counter[i] & 0xFF;
260	    r[8*i+6] = (m->counter[i] >> 8) & 0xFF;
261	    r[8*i+5] = (m->counter[i] >> 16) & 0xFF;
262	    r[8*i+4] = (m->counter[i] >> 24) & 0xFF;
263	    r[8*i+3] = (m->counter[i] >> 32) & 0XFF;
264	    r[8*i+2] = (m->counter[i] >> 40) & 0xFF;
265	    r[8*i+1] = (m->counter[i] >> 48) & 0xFF;
266	    r[8*i]   = (m->counter[i] >> 56) & 0xFF;
267	}
268    }
269    return 1;
270}
271
272int
273SHA384_Init(SHA384_CTX *m)
274{
275    m->sz[0] = 0;
276    m->sz[1] = 0;
277    A = 0xcbbb9d5dc1059ed8ULL;
278    B = 0x629a292a367cd507ULL;
279    C = 0x9159015a3070dd17ULL;
280    D = 0x152fecd8f70e5939ULL;
281    E = 0x67332667ffc00b31ULL;
282    F = 0x8eb44a8768581511ULL;
283    G = 0xdb0c2e0d64f98fa7ULL;
284    H = 0x47b5481dbefa4fa4ULL;
285    return 1;
286}
287
288int
289SHA384_Update (SHA384_CTX *m, const void *v, size_t len)
290{
291    SHA512_Update(m, v, len);
292    return 1;
293}
294
295int
296SHA384_Final (void *res, SHA384_CTX *m)
297{
298    unsigned char data[SHA512_DIGEST_LENGTH];
299    SHA512_Final(data, m);
300    memcpy(res, data, SHA384_DIGEST_LENGTH);
301    return 1;
302}
303
304