1220496Smarkm/*-
2220496Smarkm * Copyright 2005 Colin Percival
3220496Smarkm * All rights reserved.
4220496Smarkm *
5220496Smarkm * Redistribution and use in source and binary forms, with or without
6220496Smarkm * modification, are permitted provided that the following conditions
7220496Smarkm * are met:
8220496Smarkm * 1. Redistributions of source code must retain the above copyright
9220496Smarkm *    notice, this list of conditions and the following disclaimer.
10220496Smarkm * 2. Redistributions in binary form must reproduce the above copyright
11220496Smarkm *    notice, this list of conditions and the following disclaimer in the
12220496Smarkm *    documentation and/or other materials provided with the distribution.
13220496Smarkm *
14220496Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15220496Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16220496Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17220496Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18220496Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19220496Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20220496Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21220496Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22220496Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23220496Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24220496Smarkm * SUCH DAMAGE.
25220496Smarkm */
26220496Smarkm
27220496Smarkm#include <sys/cdefs.h>
28220496Smarkm__FBSDID("$FreeBSD$");
29220496Smarkm
30220496Smarkm#include <sys/endian.h>
31220496Smarkm#include <sys/types.h>
32220496Smarkm
33220496Smarkm#include <string.h>
34220496Smarkm
35220496Smarkm#include "sha512.h"
36220496Smarkm
37220496Smarkm#if BYTE_ORDER == BIG_ENDIAN
38220496Smarkm
39220496Smarkm/* Copy a vector of big-endian uint64_t into a vector of bytes */
40220496Smarkm#define be64enc_vect(dst, src, len)	\
41220496Smarkm	memcpy((void *)dst, (const void *)src, (size_t)len)
42220496Smarkm
43220496Smarkm/* Copy a vector of bytes into a vector of big-endian uint64_t */
44220496Smarkm#define be64dec_vect(dst, src, len)	\
45220496Smarkm	memcpy((void *)dst, (const void *)src, (size_t)len)
46220496Smarkm
47220496Smarkm#else /* BYTE_ORDER != BIG_ENDIAN */
48220496Smarkm
49220496Smarkm/*
50220496Smarkm * Encode a length len/4 vector of (uint64_t) into a length len vector of
51220496Smarkm * (unsigned char) in big-endian form.  Assumes len is a multiple of 8.
52220496Smarkm */
53220496Smarkmstatic void
54220496Smarkmbe64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
55220496Smarkm{
56220496Smarkm	size_t i;
57220496Smarkm
58220496Smarkm	for (i = 0; i < len / 8; i++)
59220496Smarkm		be64enc(dst + i * 8, src[i]);
60220496Smarkm}
61220496Smarkm
62220496Smarkm/*
63220496Smarkm * Decode a big-endian length len vector of (unsigned char) into a length
64220496Smarkm * len/4 vector of (uint64_t).  Assumes len is a multiple of 8.
65220496Smarkm */
66220496Smarkmstatic void
67220496Smarkmbe64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
68220496Smarkm{
69220496Smarkm	size_t i;
70220496Smarkm
71220496Smarkm	for (i = 0; i < len / 8; i++)
72220496Smarkm		dst[i] = be64dec(src + i * 8);
73220496Smarkm}
74220496Smarkm
75220496Smarkm#endif /* BYTE_ORDER != BIG_ENDIAN */
76220496Smarkm
77220496Smarkm/* Elementary functions used by SHA512 */
78220496Smarkm#define Ch(x, y, z)	((x & (y ^ z)) ^ z)
79220496Smarkm#define Maj(x, y, z)	((x & (y | z)) | (y & z))
80220496Smarkm#define SHR(x, n)	(x >> n)
81220496Smarkm#define ROTR(x, n)	((x >> n) | (x << (64 - n)))
82220496Smarkm#define S0(x)		(ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
83220496Smarkm#define S1(x)		(ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
84220496Smarkm#define s0(x)		(ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
85220496Smarkm#define s1(x)		(ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
86220496Smarkm
87220496Smarkm/* SHA512 round function */
88220496Smarkm#define RND(a, b, c, d, e, f, g, h, k)			\
89220496Smarkm	t0 = h + S1(e) + Ch(e, f, g) + k;		\
90220496Smarkm	t1 = S0(a) + Maj(a, b, c);			\
91220496Smarkm	d += t0;					\
92220496Smarkm	h  = t0 + t1;
93220496Smarkm
94220496Smarkm/* Adjusted round function for rotating state */
95220496Smarkm#define RNDr(S, W, i, k)			\
96220496Smarkm	RND(S[(80 - i) % 8], S[(81 - i) % 8],	\
97220496Smarkm	    S[(82 - i) % 8], S[(83 - i) % 8],	\
98220496Smarkm	    S[(84 - i) % 8], S[(85 - i) % 8],	\
99220496Smarkm	    S[(86 - i) % 8], S[(87 - i) % 8],	\
100220496Smarkm	    W[i] + k)
101220496Smarkm
102220496Smarkm/*
103220496Smarkm * SHA512 block compression function.  The 512-bit state is transformed via
104220496Smarkm * the 512-bit input block to produce a new state.
105220496Smarkm */
106220496Smarkmstatic void
107220496SmarkmSHA512_Transform(uint64_t * state, const unsigned char block[128])
108220496Smarkm{
109220496Smarkm	uint64_t W[80];
110220496Smarkm	uint64_t S[8];
111220496Smarkm	uint64_t t0, t1;
112220496Smarkm	int i;
113220496Smarkm
114220496Smarkm	/* 1. Prepare message schedule W. */
115220496Smarkm	be64dec_vect(W, block, 128);
116220496Smarkm	for (i = 16; i < 80; i++)
117220496Smarkm		W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
118220496Smarkm
119220496Smarkm	/* 2. Initialize working variables. */
120220496Smarkm	memcpy(S, state, 64);
121220496Smarkm
122220496Smarkm	/* 3. Mix. */
123220496Smarkm	RNDr(S, W, 0, 0x428a2f98d728ae22ULL);
124220496Smarkm	RNDr(S, W, 1, 0x7137449123ef65cdULL);
125220496Smarkm	RNDr(S, W, 2, 0xb5c0fbcfec4d3b2fULL);
126220496Smarkm	RNDr(S, W, 3, 0xe9b5dba58189dbbcULL);
127220496Smarkm	RNDr(S, W, 4, 0x3956c25bf348b538ULL);
128220496Smarkm	RNDr(S, W, 5, 0x59f111f1b605d019ULL);
129220496Smarkm	RNDr(S, W, 6, 0x923f82a4af194f9bULL);
130220496Smarkm	RNDr(S, W, 7, 0xab1c5ed5da6d8118ULL);
131220496Smarkm	RNDr(S, W, 8, 0xd807aa98a3030242ULL);
132220496Smarkm	RNDr(S, W, 9, 0x12835b0145706fbeULL);
133220496Smarkm	RNDr(S, W, 10, 0x243185be4ee4b28cULL);
134220496Smarkm	RNDr(S, W, 11, 0x550c7dc3d5ffb4e2ULL);
135220496Smarkm	RNDr(S, W, 12, 0x72be5d74f27b896fULL);
136220496Smarkm	RNDr(S, W, 13, 0x80deb1fe3b1696b1ULL);
137220496Smarkm	RNDr(S, W, 14, 0x9bdc06a725c71235ULL);
138220496Smarkm	RNDr(S, W, 15, 0xc19bf174cf692694ULL);
139220496Smarkm	RNDr(S, W, 16, 0xe49b69c19ef14ad2ULL);
140220496Smarkm	RNDr(S, W, 17, 0xefbe4786384f25e3ULL);
141220496Smarkm	RNDr(S, W, 18, 0x0fc19dc68b8cd5b5ULL);
142220496Smarkm	RNDr(S, W, 19, 0x240ca1cc77ac9c65ULL);
143220496Smarkm	RNDr(S, W, 20, 0x2de92c6f592b0275ULL);
144220496Smarkm	RNDr(S, W, 21, 0x4a7484aa6ea6e483ULL);
145220496Smarkm	RNDr(S, W, 22, 0x5cb0a9dcbd41fbd4ULL);
146220496Smarkm	RNDr(S, W, 23, 0x76f988da831153b5ULL);
147220496Smarkm	RNDr(S, W, 24, 0x983e5152ee66dfabULL);
148220496Smarkm	RNDr(S, W, 25, 0xa831c66d2db43210ULL);
149220496Smarkm	RNDr(S, W, 26, 0xb00327c898fb213fULL);
150220496Smarkm	RNDr(S, W, 27, 0xbf597fc7beef0ee4ULL);
151220496Smarkm	RNDr(S, W, 28, 0xc6e00bf33da88fc2ULL);
152220496Smarkm	RNDr(S, W, 29, 0xd5a79147930aa725ULL);
153220496Smarkm	RNDr(S, W, 30, 0x06ca6351e003826fULL);
154220496Smarkm	RNDr(S, W, 31, 0x142929670a0e6e70ULL);
155220496Smarkm	RNDr(S, W, 32, 0x27b70a8546d22ffcULL);
156220496Smarkm	RNDr(S, W, 33, 0x2e1b21385c26c926ULL);
157220496Smarkm	RNDr(S, W, 34, 0x4d2c6dfc5ac42aedULL);
158220496Smarkm	RNDr(S, W, 35, 0x53380d139d95b3dfULL);
159220496Smarkm	RNDr(S, W, 36, 0x650a73548baf63deULL);
160220496Smarkm	RNDr(S, W, 37, 0x766a0abb3c77b2a8ULL);
161220496Smarkm	RNDr(S, W, 38, 0x81c2c92e47edaee6ULL);
162220496Smarkm	RNDr(S, W, 39, 0x92722c851482353bULL);
163220496Smarkm	RNDr(S, W, 40, 0xa2bfe8a14cf10364ULL);
164220496Smarkm	RNDr(S, W, 41, 0xa81a664bbc423001ULL);
165220496Smarkm	RNDr(S, W, 42, 0xc24b8b70d0f89791ULL);
166220496Smarkm	RNDr(S, W, 43, 0xc76c51a30654be30ULL);
167220496Smarkm	RNDr(S, W, 44, 0xd192e819d6ef5218ULL);
168220496Smarkm	RNDr(S, W, 45, 0xd69906245565a910ULL);
169220496Smarkm	RNDr(S, W, 46, 0xf40e35855771202aULL);
170220496Smarkm	RNDr(S, W, 47, 0x106aa07032bbd1b8ULL);
171220496Smarkm	RNDr(S, W, 48, 0x19a4c116b8d2d0c8ULL);
172220496Smarkm	RNDr(S, W, 49, 0x1e376c085141ab53ULL);
173220496Smarkm	RNDr(S, W, 50, 0x2748774cdf8eeb99ULL);
174220496Smarkm	RNDr(S, W, 51, 0x34b0bcb5e19b48a8ULL);
175220496Smarkm	RNDr(S, W, 52, 0x391c0cb3c5c95a63ULL);
176220496Smarkm	RNDr(S, W, 53, 0x4ed8aa4ae3418acbULL);
177220496Smarkm	RNDr(S, W, 54, 0x5b9cca4f7763e373ULL);
178220496Smarkm	RNDr(S, W, 55, 0x682e6ff3d6b2b8a3ULL);
179220496Smarkm	RNDr(S, W, 56, 0x748f82ee5defb2fcULL);
180220496Smarkm	RNDr(S, W, 57, 0x78a5636f43172f60ULL);
181220496Smarkm	RNDr(S, W, 58, 0x84c87814a1f0ab72ULL);
182220496Smarkm	RNDr(S, W, 59, 0x8cc702081a6439ecULL);
183220496Smarkm	RNDr(S, W, 60, 0x90befffa23631e28ULL);
184220496Smarkm	RNDr(S, W, 61, 0xa4506cebde82bde9ULL);
185220496Smarkm	RNDr(S, W, 62, 0xbef9a3f7b2c67915ULL);
186220496Smarkm	RNDr(S, W, 63, 0xc67178f2e372532bULL);
187220496Smarkm	RNDr(S, W, 64, 0xca273eceea26619cULL);
188220496Smarkm	RNDr(S, W, 65, 0xd186b8c721c0c207ULL);
189220496Smarkm	RNDr(S, W, 66, 0xeada7dd6cde0eb1eULL);
190220496Smarkm	RNDr(S, W, 67, 0xf57d4f7fee6ed178ULL);
191220496Smarkm	RNDr(S, W, 68, 0x06f067aa72176fbaULL);
192220496Smarkm	RNDr(S, W, 69, 0x0a637dc5a2c898a6ULL);
193220496Smarkm	RNDr(S, W, 70, 0x113f9804bef90daeULL);
194220496Smarkm	RNDr(S, W, 71, 0x1b710b35131c471bULL);
195220496Smarkm	RNDr(S, W, 72, 0x28db77f523047d84ULL);
196220496Smarkm	RNDr(S, W, 73, 0x32caab7b40c72493ULL);
197220496Smarkm	RNDr(S, W, 74, 0x3c9ebe0a15c9bebcULL);
198220496Smarkm	RNDr(S, W, 75, 0x431d67c49c100d4cULL);
199220496Smarkm	RNDr(S, W, 76, 0x4cc5d4becb3e42b6ULL);
200220496Smarkm	RNDr(S, W, 77, 0x597f299cfc657e2aULL);
201220496Smarkm	RNDr(S, W, 78, 0x5fcb6fab3ad6faecULL);
202220496Smarkm	RNDr(S, W, 79, 0x6c44198c4a475817ULL);
203220496Smarkm
204220496Smarkm	/* 4. Mix local working variables into global state */
205220496Smarkm	for (i = 0; i < 8; i++)
206220496Smarkm		state[i] += S[i];
207220496Smarkm}
208220496Smarkm
209220496Smarkmstatic unsigned char PAD[128] = {
210220496Smarkm	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
211220496Smarkm	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
212220496Smarkm	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
213220496Smarkm	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
214220496Smarkm	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
215220496Smarkm	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
216220496Smarkm	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217220496Smarkm	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
218220496Smarkm};
219220496Smarkm
220220496Smarkm/* Add padding and terminating bit-count. */
221220496Smarkmstatic void
222220496SmarkmSHA512_Pad(SHA512_CTX * ctx)
223220496Smarkm{
224220496Smarkm	unsigned char len[16];
225220496Smarkm	uint64_t r, plen;
226220496Smarkm
227220496Smarkm	/*
228220496Smarkm	 * Convert length to a vector of bytes -- we do this now rather
229220496Smarkm	 * than later because the length will change after we pad.
230220496Smarkm	 */
231220496Smarkm	be64enc_vect(len, ctx->count, 16);
232220496Smarkm
233220496Smarkm	/* Add 1--128 bytes so that the resulting length is 112 mod 128 */
234220496Smarkm	r = (ctx->count[1] >> 3) & 0x7f;
235220496Smarkm	plen = (r < 112) ? (112 - r) : (240 - r);
236220496Smarkm	SHA512_Update(ctx, PAD, (size_t)plen);
237220496Smarkm
238220496Smarkm	/* Add the terminating bit-count */
239220496Smarkm	SHA512_Update(ctx, len, 16);
240220496Smarkm}
241220496Smarkm
242220496Smarkm/* SHA-512 initialization.  Begins a SHA-512 operation. */
243220496Smarkmvoid
244220496SmarkmSHA512_Init(SHA512_CTX * ctx)
245220496Smarkm{
246220496Smarkm
247220496Smarkm	/* Zero bits processed so far */
248220496Smarkm	ctx->count[0] = ctx->count[1] = 0;
249220496Smarkm
250220496Smarkm	/* Magic initialization constants */
251220496Smarkm	ctx->state[0] = 0x6a09e667f3bcc908ULL;
252220496Smarkm	ctx->state[1] = 0xbb67ae8584caa73bULL;
253220496Smarkm	ctx->state[2] = 0x3c6ef372fe94f82bULL;
254220496Smarkm	ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
255220496Smarkm	ctx->state[4] = 0x510e527fade682d1ULL;
256220496Smarkm	ctx->state[5] = 0x9b05688c2b3e6c1fULL;
257220496Smarkm	ctx->state[6] = 0x1f83d9abfb41bd6bULL;
258220496Smarkm	ctx->state[7] = 0x5be0cd19137e2179ULL;
259220496Smarkm}
260220496Smarkm
261220496Smarkm/* Add bytes into the hash */
262220496Smarkmvoid
263220496SmarkmSHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
264220496Smarkm{
265220496Smarkm	uint64_t bitlen[2];
266220496Smarkm	uint64_t r;
267220496Smarkm	const unsigned char *src = in;
268220496Smarkm
269220496Smarkm	/* Number of bytes left in the buffer from previous updates */
270220496Smarkm	r = (ctx->count[1] >> 3) & 0x7f;
271220496Smarkm
272220496Smarkm	/* Convert the length into a number of bits */
273220496Smarkm	bitlen[1] = ((uint64_t)len) << 3;
274220496Smarkm	bitlen[0] = ((uint64_t)len) >> 61;
275220496Smarkm
276220496Smarkm	/* Update number of bits */
277220496Smarkm	if ((ctx->count[1] += bitlen[1]) < bitlen[1])
278220496Smarkm		ctx->count[0]++;
279220496Smarkm	ctx->count[0] += bitlen[0];
280220496Smarkm
281220496Smarkm	/* Handle the case where we don't need to perform any transforms */
282220496Smarkm	if (len < 128 - r) {
283220496Smarkm		memcpy(&ctx->buf[r], src, len);
284220496Smarkm		return;
285220496Smarkm	}
286220496Smarkm
287220496Smarkm	/* Finish the current block */
288220496Smarkm	memcpy(&ctx->buf[r], src, 128 - r);
289220496Smarkm	SHA512_Transform(ctx->state, ctx->buf);
290220496Smarkm	src += 128 - r;
291220496Smarkm	len -= 128 - r;
292220496Smarkm
293220496Smarkm	/* Perform complete blocks */
294220496Smarkm	while (len >= 128) {
295220496Smarkm		SHA512_Transform(ctx->state, src);
296220496Smarkm		src += 128;
297220496Smarkm		len -= 128;
298220496Smarkm	}
299220496Smarkm
300220496Smarkm	/* Copy left over data into buffer */
301220496Smarkm	memcpy(ctx->buf, src, len);
302220496Smarkm}
303220496Smarkm
304220496Smarkm/*
305220496Smarkm * SHA-512 finalization.  Pads the input data, exports the hash value,
306220496Smarkm * and clears the context state.
307220496Smarkm */
308220496Smarkmvoid
309220496SmarkmSHA512_Final(unsigned char digest[64], SHA512_CTX * ctx)
310220496Smarkm{
311220496Smarkm
312220496Smarkm	/* Add padding */
313220496Smarkm	SHA512_Pad(ctx);
314220496Smarkm
315220496Smarkm	/* Write the hash */
316220496Smarkm	be64enc_vect(digest, ctx->state, 64);
317220496Smarkm
318220496Smarkm	/* Clear the context state */
319220496Smarkm	memset((void *)ctx, 0, sizeof(*ctx));
320220496Smarkm}
321