xref: /freebsd/sys/crypto/sha2/sha512c.c (revision 6680cfe8e0eec4427716ab50d73ab8231dd9ab28)
17a3f5d11SAllan Jude /*-
27a3f5d11SAllan Jude  * Copyright 2005 Colin Percival
31780e407SAllan Jude  * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
47a3f5d11SAllan Jude  * All rights reserved.
57a3f5d11SAllan Jude  *
67a3f5d11SAllan Jude  * Redistribution and use in source and binary forms, with or without
77a3f5d11SAllan Jude  * modification, are permitted provided that the following conditions
87a3f5d11SAllan Jude  * are met:
97a3f5d11SAllan Jude  * 1. Redistributions of source code must retain the above copyright
107a3f5d11SAllan Jude  *    notice, this list of conditions and the following disclaimer.
117a3f5d11SAllan Jude  * 2. Redistributions in binary form must reproduce the above copyright
127a3f5d11SAllan Jude  *    notice, this list of conditions and the following disclaimer in the
137a3f5d11SAllan Jude  *    documentation and/or other materials provided with the distribution.
147a3f5d11SAllan Jude  *
157a3f5d11SAllan Jude  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
167a3f5d11SAllan Jude  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
177a3f5d11SAllan Jude  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
187a3f5d11SAllan Jude  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
197a3f5d11SAllan Jude  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
207a3f5d11SAllan Jude  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
217a3f5d11SAllan Jude  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
227a3f5d11SAllan Jude  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
237a3f5d11SAllan Jude  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
247a3f5d11SAllan Jude  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
257a3f5d11SAllan Jude  * SUCH DAMAGE.
267a3f5d11SAllan Jude  */
277a3f5d11SAllan Jude 
287a3f5d11SAllan Jude #include <sys/cdefs.h>
297a3f5d11SAllan Jude __FBSDID("$FreeBSD$");
307a3f5d11SAllan Jude 
317a3f5d11SAllan Jude #include <sys/endian.h>
327a3f5d11SAllan Jude #include <sys/types.h>
337a3f5d11SAllan Jude 
347a3f5d11SAllan Jude #ifdef _KERNEL
357a3f5d11SAllan Jude #include <sys/systm.h>
367a3f5d11SAllan Jude #else
377a3f5d11SAllan Jude #include <string.h>
387a3f5d11SAllan Jude #endif
397a3f5d11SAllan Jude 
407a3f5d11SAllan Jude #include "sha512.h"
411780e407SAllan Jude #include "sha512t.h"
427a3f5d11SAllan Jude #include "sha384.h"
4371bf1c4cSAndrew Turner #include "sha512c_impl.h"
4471bf1c4cSAndrew Turner 
4571bf1c4cSAndrew Turner #if defined(ARM64_SHA512)
4671bf1c4cSAndrew Turner #include <sys/auxv.h>
4771bf1c4cSAndrew Turner #include <machine/ifunc.h>
4871bf1c4cSAndrew Turner #endif
497a3f5d11SAllan Jude 
507a3f5d11SAllan Jude #if BYTE_ORDER == BIG_ENDIAN
517a3f5d11SAllan Jude 
527a3f5d11SAllan Jude /* Copy a vector of big-endian uint64_t into a vector of bytes */
537a3f5d11SAllan Jude #define be64enc_vect(dst, src, len)	\
547a3f5d11SAllan Jude 	memcpy((void *)dst, (const void *)src, (size_t)len)
557a3f5d11SAllan Jude 
567a3f5d11SAllan Jude /* Copy a vector of bytes into a vector of big-endian uint64_t */
577a3f5d11SAllan Jude #define be64dec_vect(dst, src, len)	\
587a3f5d11SAllan Jude 	memcpy((void *)dst, (const void *)src, (size_t)len)
597a3f5d11SAllan Jude 
607a3f5d11SAllan Jude #else /* BYTE_ORDER != BIG_ENDIAN */
617a3f5d11SAllan Jude 
627a3f5d11SAllan Jude /*
63*6680cfe8SSebastian Huber  * Encode a length (len + 7) / 8 vector of (uint64_t) into a length len
64*6680cfe8SSebastian Huber  * vector of (unsigned char) in big-endian form.  Assumes len is a
65*6680cfe8SSebastian Huber  * multiple of 4.
667a3f5d11SAllan Jude  */
67*6680cfe8SSebastian Huber static inline void
687a3f5d11SAllan Jude be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
697a3f5d11SAllan Jude {
707a3f5d11SAllan Jude 	size_t i;
717a3f5d11SAllan Jude 
727a3f5d11SAllan Jude 	for (i = 0; i < len / 8; i++)
737a3f5d11SAllan Jude 		be64enc(dst + i * 8, src[i]);
74*6680cfe8SSebastian Huber 	if (len % 8 == 4)
75*6680cfe8SSebastian Huber 		be32enc(dst + i * 8, src[i] >> 32);
767a3f5d11SAllan Jude }
777a3f5d11SAllan Jude 
787a3f5d11SAllan Jude /*
797a3f5d11SAllan Jude  * Decode a big-endian length len vector of (unsigned char) into a length
80*6680cfe8SSebastian Huber  * len/8 vector of (uint64_t).  Assumes len is a multiple of 8.
817a3f5d11SAllan Jude  */
82*6680cfe8SSebastian Huber static inline void
837a3f5d11SAllan Jude be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
847a3f5d11SAllan Jude {
857a3f5d11SAllan Jude 	size_t i;
867a3f5d11SAllan Jude 
877a3f5d11SAllan Jude 	for (i = 0; i < len / 8; i++)
887a3f5d11SAllan Jude 		dst[i] = be64dec(src + i * 8);
897a3f5d11SAllan Jude }
907a3f5d11SAllan Jude 
917a3f5d11SAllan Jude #endif /* BYTE_ORDER != BIG_ENDIAN */
927a3f5d11SAllan Jude 
93696c3895SColin Percival /* SHA512 round constants. */
94696c3895SColin Percival static const uint64_t K[80] = {
95696c3895SColin Percival 	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
96696c3895SColin Percival 	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
97696c3895SColin Percival 	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
98696c3895SColin Percival 	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
99696c3895SColin Percival 	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
100696c3895SColin Percival 	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
101696c3895SColin Percival 	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
102696c3895SColin Percival 	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
103696c3895SColin Percival 	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
104696c3895SColin Percival 	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
105696c3895SColin Percival 	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
106696c3895SColin Percival 	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
107696c3895SColin Percival 	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
108696c3895SColin Percival 	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
109696c3895SColin Percival 	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
110696c3895SColin Percival 	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
111696c3895SColin Percival 	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
112696c3895SColin Percival 	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
113696c3895SColin Percival 	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
114696c3895SColin Percival 	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
115696c3895SColin Percival 	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
116696c3895SColin Percival 	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
117696c3895SColin Percival 	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
118696c3895SColin Percival 	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
119696c3895SColin Percival 	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
120696c3895SColin Percival 	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
121696c3895SColin Percival 	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
122696c3895SColin Percival 	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
123696c3895SColin Percival 	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
124696c3895SColin Percival 	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
125696c3895SColin Percival 	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
126696c3895SColin Percival 	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
127696c3895SColin Percival 	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
128696c3895SColin Percival 	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
129696c3895SColin Percival 	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
130696c3895SColin Percival 	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
131696c3895SColin Percival 	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
132696c3895SColin Percival 	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
133696c3895SColin Percival 	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
134696c3895SColin Percival 	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
135696c3895SColin Percival };
136696c3895SColin Percival 
1377a3f5d11SAllan Jude /* Elementary functions used by SHA512 */
1387a3f5d11SAllan Jude #define Ch(x, y, z)	((x & (y ^ z)) ^ z)
1397a3f5d11SAllan Jude #define Maj(x, y, z)	((x & (y | z)) | (y & z))
1407a3f5d11SAllan Jude #define SHR(x, n)	(x >> n)
1417a3f5d11SAllan Jude #define ROTR(x, n)	((x >> n) | (x << (64 - n)))
1427a3f5d11SAllan Jude #define S0(x)		(ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
1437a3f5d11SAllan Jude #define S1(x)		(ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
1447a3f5d11SAllan Jude #define s0(x)		(ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
1457a3f5d11SAllan Jude #define s1(x)		(ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
1467a3f5d11SAllan Jude 
1477a3f5d11SAllan Jude /* SHA512 round function */
1487a3f5d11SAllan Jude #define RND(a, b, c, d, e, f, g, h, k)			\
149696c3895SColin Percival 	h += S1(e) + Ch(e, f, g) + k;			\
150696c3895SColin Percival 	d += h;						\
151696c3895SColin Percival 	h += S0(a) + Maj(a, b, c);
1527a3f5d11SAllan Jude 
1537a3f5d11SAllan Jude /* Adjusted round function for rotating state */
154696c3895SColin Percival #define RNDr(S, W, i, ii)			\
1557a3f5d11SAllan Jude 	RND(S[(80 - i) % 8], S[(81 - i) % 8],	\
1567a3f5d11SAllan Jude 	    S[(82 - i) % 8], S[(83 - i) % 8],	\
1577a3f5d11SAllan Jude 	    S[(84 - i) % 8], S[(85 - i) % 8],	\
1587a3f5d11SAllan Jude 	    S[(86 - i) % 8], S[(87 - i) % 8],	\
159696c3895SColin Percival 	    W[i + ii] + K[i + ii])
160696c3895SColin Percival 
161696c3895SColin Percival /* Message schedule computation */
162696c3895SColin Percival #define MSCH(W, ii, i)				\
163696c3895SColin Percival 	W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
1647a3f5d11SAllan Jude 
1657a3f5d11SAllan Jude /*
1667a3f5d11SAllan Jude  * SHA512 block compression function.  The 512-bit state is transformed via
1677a3f5d11SAllan Jude  * the 512-bit input block to produce a new state.
1687a3f5d11SAllan Jude  */
1697a3f5d11SAllan Jude static void
17071bf1c4cSAndrew Turner #if defined(ARM64_SHA512)
17171bf1c4cSAndrew Turner SHA512_Transform_c(uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH])
17271bf1c4cSAndrew Turner #else
1737a3f5d11SAllan Jude SHA512_Transform(uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH])
17471bf1c4cSAndrew Turner #endif
1757a3f5d11SAllan Jude {
1767a3f5d11SAllan Jude 	uint64_t W[80];
1777a3f5d11SAllan Jude 	uint64_t S[8];
1787a3f5d11SAllan Jude 	int i;
1797a3f5d11SAllan Jude 
180696c3895SColin Percival 	/* 1. Prepare the first part of the message schedule W. */
1817a3f5d11SAllan Jude 	be64dec_vect(W, block, SHA512_BLOCK_LENGTH);
1827a3f5d11SAllan Jude 
1837a3f5d11SAllan Jude 	/* 2. Initialize working variables. */
1847a3f5d11SAllan Jude 	memcpy(S, state, SHA512_DIGEST_LENGTH);
1857a3f5d11SAllan Jude 
1867a3f5d11SAllan Jude 	/* 3. Mix. */
187696c3895SColin Percival 	for (i = 0; i < 80; i += 16) {
188696c3895SColin Percival 		RNDr(S, W, 0, i);
189696c3895SColin Percival 		RNDr(S, W, 1, i);
190696c3895SColin Percival 		RNDr(S, W, 2, i);
191696c3895SColin Percival 		RNDr(S, W, 3, i);
192696c3895SColin Percival 		RNDr(S, W, 4, i);
193696c3895SColin Percival 		RNDr(S, W, 5, i);
194696c3895SColin Percival 		RNDr(S, W, 6, i);
195696c3895SColin Percival 		RNDr(S, W, 7, i);
196696c3895SColin Percival 		RNDr(S, W, 8, i);
197696c3895SColin Percival 		RNDr(S, W, 9, i);
198696c3895SColin Percival 		RNDr(S, W, 10, i);
199696c3895SColin Percival 		RNDr(S, W, 11, i);
200696c3895SColin Percival 		RNDr(S, W, 12, i);
201696c3895SColin Percival 		RNDr(S, W, 13, i);
202696c3895SColin Percival 		RNDr(S, W, 14, i);
203696c3895SColin Percival 		RNDr(S, W, 15, i);
204696c3895SColin Percival 
205696c3895SColin Percival 		if (i == 64)
206696c3895SColin Percival 			break;
207696c3895SColin Percival 		MSCH(W, 0, i);
208696c3895SColin Percival 		MSCH(W, 1, i);
209696c3895SColin Percival 		MSCH(W, 2, i);
210696c3895SColin Percival 		MSCH(W, 3, i);
211696c3895SColin Percival 		MSCH(W, 4, i);
212696c3895SColin Percival 		MSCH(W, 5, i);
213696c3895SColin Percival 		MSCH(W, 6, i);
214696c3895SColin Percival 		MSCH(W, 7, i);
215696c3895SColin Percival 		MSCH(W, 8, i);
216696c3895SColin Percival 		MSCH(W, 9, i);
217696c3895SColin Percival 		MSCH(W, 10, i);
218696c3895SColin Percival 		MSCH(W, 11, i);
219696c3895SColin Percival 		MSCH(W, 12, i);
220696c3895SColin Percival 		MSCH(W, 13, i);
221696c3895SColin Percival 		MSCH(W, 14, i);
222696c3895SColin Percival 		MSCH(W, 15, i);
223696c3895SColin Percival 	}
2247a3f5d11SAllan Jude 
2257a3f5d11SAllan Jude 	/* 4. Mix local working variables into global state */
2267a3f5d11SAllan Jude 	for (i = 0; i < 8; i++)
2277a3f5d11SAllan Jude 		state[i] += S[i];
2287a3f5d11SAllan Jude }
2297a3f5d11SAllan Jude 
23071bf1c4cSAndrew Turner #if defined(ARM64_SHA512)
23171bf1c4cSAndrew Turner static void
23271bf1c4cSAndrew Turner SHA512_Transform_arm64(uint64_t * state,
23371bf1c4cSAndrew Turner     const unsigned char block[SHA512_BLOCK_LENGTH])
23471bf1c4cSAndrew Turner {
23571bf1c4cSAndrew Turner 	SHA512_Transform_arm64_impl(state, block, K);
23671bf1c4cSAndrew Turner }
23771bf1c4cSAndrew Turner 
23871bf1c4cSAndrew Turner DEFINE_UIFUNC(static, void, SHA512_Transform,
23971bf1c4cSAndrew Turner     (uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH]))
24071bf1c4cSAndrew Turner {
24171bf1c4cSAndrew Turner 	u_long hwcap;
24271bf1c4cSAndrew Turner 
24371bf1c4cSAndrew Turner 	if (elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)) == 0) {
24471bf1c4cSAndrew Turner 		if ((hwcap & HWCAP_SHA512) != 0) {
24571bf1c4cSAndrew Turner 			return (SHA512_Transform_arm64);
24671bf1c4cSAndrew Turner 		}
24771bf1c4cSAndrew Turner 	}
24871bf1c4cSAndrew Turner 
24971bf1c4cSAndrew Turner 	return (SHA512_Transform_c);
25071bf1c4cSAndrew Turner }
25171bf1c4cSAndrew Turner #endif
25271bf1c4cSAndrew Turner 
2537a3f5d11SAllan Jude static unsigned char PAD[SHA512_BLOCK_LENGTH] = {
2547a3f5d11SAllan Jude 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2557a3f5d11SAllan Jude 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2567a3f5d11SAllan Jude 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2577a3f5d11SAllan Jude 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2587a3f5d11SAllan Jude 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2597a3f5d11SAllan Jude 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2607a3f5d11SAllan Jude 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2617a3f5d11SAllan Jude 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2627a3f5d11SAllan Jude };
2637a3f5d11SAllan Jude 
2647a3f5d11SAllan Jude /* Add padding and terminating bit-count. */
2657a3f5d11SAllan Jude static void
2667a3f5d11SAllan Jude SHA512_Pad(SHA512_CTX * ctx)
2677a3f5d11SAllan Jude {
268696c3895SColin Percival 	size_t r;
2697a3f5d11SAllan Jude 
270696c3895SColin Percival 	/* Figure out how many bytes we have buffered. */
2717a3f5d11SAllan Jude 	r = (ctx->count[1] >> 3) & 0x7f;
2727a3f5d11SAllan Jude 
273696c3895SColin Percival 	/* Pad to 112 mod 128, transforming if we finish a block en route. */
274696c3895SColin Percival 	if (r < 112) {
275696c3895SColin Percival 		/* Pad to 112 mod 128. */
276696c3895SColin Percival 		memcpy(&ctx->buf[r], PAD, 112 - r);
277696c3895SColin Percival 	} else {
278696c3895SColin Percival 		/* Finish the current block and mix. */
279696c3895SColin Percival 		memcpy(&ctx->buf[r], PAD, 128 - r);
280696c3895SColin Percival 		SHA512_Transform(ctx->state, ctx->buf);
281696c3895SColin Percival 
282696c3895SColin Percival 		/* The start of the final block is all zeroes. */
283696c3895SColin Percival 		memset(&ctx->buf[0], 0, 112);
284696c3895SColin Percival 	}
285696c3895SColin Percival 
286696c3895SColin Percival 	/* Add the terminating bit-count. */
287696c3895SColin Percival 	be64enc_vect(&ctx->buf[112], ctx->count, 16);
288696c3895SColin Percival 
289696c3895SColin Percival 	/* Mix in the final block. */
290696c3895SColin Percival 	SHA512_Transform(ctx->state, ctx->buf);
2917a3f5d11SAllan Jude }
2927a3f5d11SAllan Jude 
2937a3f5d11SAllan Jude /* SHA-512 initialization.  Begins a SHA-512 operation. */
2947a3f5d11SAllan Jude void
2957a3f5d11SAllan Jude SHA512_Init(SHA512_CTX * ctx)
2967a3f5d11SAllan Jude {
2977a3f5d11SAllan Jude 
2987a3f5d11SAllan Jude 	/* Zero bits processed so far */
2997a3f5d11SAllan Jude 	ctx->count[0] = ctx->count[1] = 0;
3007a3f5d11SAllan Jude 
3017a3f5d11SAllan Jude 	/* Magic initialization constants */
3027a3f5d11SAllan Jude 	ctx->state[0] = 0x6a09e667f3bcc908ULL;
3037a3f5d11SAllan Jude 	ctx->state[1] = 0xbb67ae8584caa73bULL;
3047a3f5d11SAllan Jude 	ctx->state[2] = 0x3c6ef372fe94f82bULL;
3057a3f5d11SAllan Jude 	ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
3067a3f5d11SAllan Jude 	ctx->state[4] = 0x510e527fade682d1ULL;
3077a3f5d11SAllan Jude 	ctx->state[5] = 0x9b05688c2b3e6c1fULL;
3087a3f5d11SAllan Jude 	ctx->state[6] = 0x1f83d9abfb41bd6bULL;
3097a3f5d11SAllan Jude 	ctx->state[7] = 0x5be0cd19137e2179ULL;
3107a3f5d11SAllan Jude }
3117a3f5d11SAllan Jude 
3127a3f5d11SAllan Jude /* Add bytes into the hash */
3137a3f5d11SAllan Jude void
3147a3f5d11SAllan Jude SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
3157a3f5d11SAllan Jude {
3167a3f5d11SAllan Jude 	uint64_t bitlen[2];
3177a3f5d11SAllan Jude 	uint64_t r;
3187a3f5d11SAllan Jude 	const unsigned char *src = in;
3197a3f5d11SAllan Jude 
3207a3f5d11SAllan Jude 	/* Number of bytes left in the buffer from previous updates */
3217a3f5d11SAllan Jude 	r = (ctx->count[1] >> 3) & 0x7f;
3227a3f5d11SAllan Jude 
3237a3f5d11SAllan Jude 	/* Convert the length into a number of bits */
3247a3f5d11SAllan Jude 	bitlen[1] = ((uint64_t)len) << 3;
3257a3f5d11SAllan Jude 	bitlen[0] = ((uint64_t)len) >> 61;
3267a3f5d11SAllan Jude 
3277a3f5d11SAllan Jude 	/* Update number of bits */
3287a3f5d11SAllan Jude 	if ((ctx->count[1] += bitlen[1]) < bitlen[1])
3297a3f5d11SAllan Jude 		ctx->count[0]++;
3307a3f5d11SAllan Jude 	ctx->count[0] += bitlen[0];
3317a3f5d11SAllan Jude 
3327a3f5d11SAllan Jude 	/* Handle the case where we don't need to perform any transforms */
3337a3f5d11SAllan Jude 	if (len < SHA512_BLOCK_LENGTH - r) {
3347a3f5d11SAllan Jude 		memcpy(&ctx->buf[r], src, len);
3357a3f5d11SAllan Jude 		return;
3367a3f5d11SAllan Jude 	}
3377a3f5d11SAllan Jude 
3387a3f5d11SAllan Jude 	/* Finish the current block */
3397a3f5d11SAllan Jude 	memcpy(&ctx->buf[r], src, SHA512_BLOCK_LENGTH - r);
3407a3f5d11SAllan Jude 	SHA512_Transform(ctx->state, ctx->buf);
3417a3f5d11SAllan Jude 	src += SHA512_BLOCK_LENGTH - r;
3427a3f5d11SAllan Jude 	len -= SHA512_BLOCK_LENGTH - r;
3437a3f5d11SAllan Jude 
3447a3f5d11SAllan Jude 	/* Perform complete blocks */
3457a3f5d11SAllan Jude 	while (len >= SHA512_BLOCK_LENGTH) {
3467a3f5d11SAllan Jude 		SHA512_Transform(ctx->state, src);
3477a3f5d11SAllan Jude 		src += SHA512_BLOCK_LENGTH;
3487a3f5d11SAllan Jude 		len -= SHA512_BLOCK_LENGTH;
3497a3f5d11SAllan Jude 	}
3507a3f5d11SAllan Jude 
3517a3f5d11SAllan Jude 	/* Copy left over data into buffer */
3527a3f5d11SAllan Jude 	memcpy(ctx->buf, src, len);
3537a3f5d11SAllan Jude }
3547a3f5d11SAllan Jude 
3557a3f5d11SAllan Jude /*
3567a3f5d11SAllan Jude  * SHA-512 finalization.  Pads the input data, exports the hash value,
3577a3f5d11SAllan Jude  * and clears the context state.
3587a3f5d11SAllan Jude  */
3597a3f5d11SAllan Jude void
360571ebf76SConrad Meyer SHA512_Final(unsigned char digest[static SHA512_DIGEST_LENGTH], SHA512_CTX *ctx)
3617a3f5d11SAllan Jude {
3627a3f5d11SAllan Jude 
3637a3f5d11SAllan Jude 	/* Add padding */
3647a3f5d11SAllan Jude 	SHA512_Pad(ctx);
3657a3f5d11SAllan Jude 
3667a3f5d11SAllan Jude 	/* Write the hash */
3677a3f5d11SAllan Jude 	be64enc_vect(digest, ctx->state, SHA512_DIGEST_LENGTH);
3687a3f5d11SAllan Jude 
3697a3f5d11SAllan Jude 	/* Clear the context state */
37066bdf50fSXin LI 	explicit_bzero(ctx, sizeof(*ctx));
3717a3f5d11SAllan Jude }
3727a3f5d11SAllan Jude 
3731780e407SAllan Jude /*** SHA-512t: *********************************************************/
3741780e407SAllan Jude /*
3751780e407SAllan Jude  * the SHA512t transforms are identical to SHA512 so reuse the existing function
3761780e407SAllan Jude  */
3771780e407SAllan Jude void
3781780e407SAllan Jude SHA512_224_Init(SHA512_CTX * ctx)
3791780e407SAllan Jude {
3801780e407SAllan Jude 
3811780e407SAllan Jude 	/* Zero bits processed so far */
3821780e407SAllan Jude 	ctx->count[0] = ctx->count[1] = 0;
3831780e407SAllan Jude 
3841780e407SAllan Jude 	/* Magic initialization constants */
3851780e407SAllan Jude 	ctx->state[0] = 0x8c3d37c819544da2ULL;
3861780e407SAllan Jude 	ctx->state[1] = 0x73e1996689dcd4d6ULL;
3871780e407SAllan Jude 	ctx->state[2] = 0x1dfab7ae32ff9c82ULL;
3881780e407SAllan Jude 	ctx->state[3] = 0x679dd514582f9fcfULL;
3891780e407SAllan Jude 	ctx->state[4] = 0x0f6d2b697bd44da8ULL;
3901780e407SAllan Jude 	ctx->state[5] = 0x77e36f7304c48942ULL;
3911780e407SAllan Jude 	ctx->state[6] = 0x3f9d85a86a1d36c8ULL;
3921780e407SAllan Jude 	ctx->state[7] = 0x1112e6ad91d692a1ULL;
3931780e407SAllan Jude }
3941780e407SAllan Jude 
3951780e407SAllan Jude void
3961780e407SAllan Jude SHA512_224_Update(SHA512_CTX * ctx, const void *in, size_t len)
3971780e407SAllan Jude {
3981780e407SAllan Jude 
3991780e407SAllan Jude 	SHA512_Update(ctx, in, len);
4001780e407SAllan Jude }
4011780e407SAllan Jude 
4021780e407SAllan Jude void
4031780e407SAllan Jude SHA512_224_Final(unsigned char digest[static SHA512_224_DIGEST_LENGTH], SHA512_CTX * ctx)
4041780e407SAllan Jude {
4051780e407SAllan Jude 
4061780e407SAllan Jude 	/* Add padding */
4071780e407SAllan Jude 	SHA512_Pad(ctx);
4081780e407SAllan Jude 
4091780e407SAllan Jude 	/* Write the hash */
4101780e407SAllan Jude 	be64enc_vect(digest, ctx->state, SHA512_224_DIGEST_LENGTH);
4111780e407SAllan Jude 
4121780e407SAllan Jude 	/* Clear the context state */
41366bdf50fSXin LI 	explicit_bzero(ctx, sizeof(*ctx));
4141780e407SAllan Jude }
4151780e407SAllan Jude 
4161780e407SAllan Jude void
4171780e407SAllan Jude SHA512_256_Init(SHA512_CTX * ctx)
4181780e407SAllan Jude {
4191780e407SAllan Jude 
4201780e407SAllan Jude 	/* Zero bits processed so far */
4211780e407SAllan Jude 	ctx->count[0] = ctx->count[1] = 0;
4221780e407SAllan Jude 
4231780e407SAllan Jude 	/* Magic initialization constants */
4241780e407SAllan Jude 	ctx->state[0] = 0x22312194fc2bf72cULL;
4251780e407SAllan Jude 	ctx->state[1] = 0x9f555fa3c84c64c2ULL;
4261780e407SAllan Jude 	ctx->state[2] = 0x2393b86b6f53b151ULL;
4271780e407SAllan Jude 	ctx->state[3] = 0x963877195940eabdULL;
4281780e407SAllan Jude 	ctx->state[4] = 0x96283ee2a88effe3ULL;
4291780e407SAllan Jude 	ctx->state[5] = 0xbe5e1e2553863992ULL;
4301780e407SAllan Jude 	ctx->state[6] = 0x2b0199fc2c85b8aaULL;
4311780e407SAllan Jude 	ctx->state[7] = 0x0eb72ddc81c52ca2ULL;
4321780e407SAllan Jude }
4331780e407SAllan Jude 
4341780e407SAllan Jude void
4351780e407SAllan Jude SHA512_256_Update(SHA512_CTX * ctx, const void *in, size_t len)
4361780e407SAllan Jude {
4371780e407SAllan Jude 
4381780e407SAllan Jude 	SHA512_Update(ctx, in, len);
4391780e407SAllan Jude }
4401780e407SAllan Jude 
4411780e407SAllan Jude void
4421780e407SAllan Jude SHA512_256_Final(unsigned char digest[static SHA512_256_DIGEST_LENGTH], SHA512_CTX * ctx)
4431780e407SAllan Jude {
4441780e407SAllan Jude 
4451780e407SAllan Jude 	/* Add padding */
4461780e407SAllan Jude 	SHA512_Pad(ctx);
4471780e407SAllan Jude 
4481780e407SAllan Jude 	/* Write the hash */
4491780e407SAllan Jude 	be64enc_vect(digest, ctx->state, SHA512_256_DIGEST_LENGTH);
4501780e407SAllan Jude 
4511780e407SAllan Jude 	/* Clear the context state */
45266bdf50fSXin LI 	explicit_bzero(ctx, sizeof(*ctx));
4531780e407SAllan Jude }
4541780e407SAllan Jude 
4557a3f5d11SAllan Jude /*** SHA-384: *********************************************************/
4567a3f5d11SAllan Jude /*
4577a3f5d11SAllan Jude  * the SHA384 and SHA512 transforms are identical, so SHA384 is skipped
4587a3f5d11SAllan Jude  */
4597a3f5d11SAllan Jude 
4607a3f5d11SAllan Jude /* SHA-384 initialization.  Begins a SHA-384 operation. */
4617a3f5d11SAllan Jude void
4627a3f5d11SAllan Jude SHA384_Init(SHA384_CTX * ctx)
4637a3f5d11SAllan Jude {
4647a3f5d11SAllan Jude 
4657a3f5d11SAllan Jude 	/* Zero bits processed so far */
4667a3f5d11SAllan Jude 	ctx->count[0] = ctx->count[1] = 0;
4677a3f5d11SAllan Jude 
4687a3f5d11SAllan Jude 	/* Magic initialization constants */
4697a3f5d11SAllan Jude 	ctx->state[0] = 0xcbbb9d5dc1059ed8ULL;
4707a3f5d11SAllan Jude 	ctx->state[1] = 0x629a292a367cd507ULL;
4717a3f5d11SAllan Jude 	ctx->state[2] = 0x9159015a3070dd17ULL;
4727a3f5d11SAllan Jude 	ctx->state[3] = 0x152fecd8f70e5939ULL;
4737a3f5d11SAllan Jude 	ctx->state[4] = 0x67332667ffc00b31ULL;
4747a3f5d11SAllan Jude 	ctx->state[5] = 0x8eb44a8768581511ULL;
4757a3f5d11SAllan Jude 	ctx->state[6] = 0xdb0c2e0d64f98fa7ULL;
4767a3f5d11SAllan Jude 	ctx->state[7] = 0x47b5481dbefa4fa4ULL;
4777a3f5d11SAllan Jude }
4787a3f5d11SAllan Jude 
4797a3f5d11SAllan Jude /* Add bytes into the SHA-384 hash */
4807a3f5d11SAllan Jude void
4817a3f5d11SAllan Jude SHA384_Update(SHA384_CTX * ctx, const void *in, size_t len)
4827a3f5d11SAllan Jude {
4837a3f5d11SAllan Jude 
4847a3f5d11SAllan Jude 	SHA512_Update((SHA512_CTX *)ctx, in, len);
4857a3f5d11SAllan Jude }
4867a3f5d11SAllan Jude 
4877a3f5d11SAllan Jude /*
4887a3f5d11SAllan Jude  * SHA-384 finalization.  Pads the input data, exports the hash value,
4897a3f5d11SAllan Jude  * and clears the context state.
4907a3f5d11SAllan Jude  */
4917a3f5d11SAllan Jude void
492571ebf76SConrad Meyer SHA384_Final(unsigned char digest[static SHA384_DIGEST_LENGTH], SHA384_CTX *ctx)
4937a3f5d11SAllan Jude {
4947a3f5d11SAllan Jude 
4957a3f5d11SAllan Jude 	/* Add padding */
4967a3f5d11SAllan Jude 	SHA512_Pad((SHA512_CTX *)ctx);
4977a3f5d11SAllan Jude 
4987a3f5d11SAllan Jude 	/* Write the hash */
4997a3f5d11SAllan Jude 	be64enc_vect(digest, ctx->state, SHA384_DIGEST_LENGTH);
5007a3f5d11SAllan Jude 
5017a3f5d11SAllan Jude 	/* Clear the context state */
50266bdf50fSXin LI 	explicit_bzero(ctx, sizeof(*ctx));
5037a3f5d11SAllan Jude }
5047a3f5d11SAllan Jude 
5057a3f5d11SAllan Jude #ifdef WEAK_REFS
5067a3f5d11SAllan Jude /* When building libmd, provide weak references. Note: this is not
5077a3f5d11SAllan Jude    activated in the context of compiling these sources for internal
5087a3f5d11SAllan Jude    use in libcrypt.
5097a3f5d11SAllan Jude  */
5107a3f5d11SAllan Jude #undef SHA512_Init
5117a3f5d11SAllan Jude __weak_reference(_libmd_SHA512_Init, SHA512_Init);
5127a3f5d11SAllan Jude #undef SHA512_Update
5137a3f5d11SAllan Jude __weak_reference(_libmd_SHA512_Update, SHA512_Update);
5147a3f5d11SAllan Jude #undef SHA512_Final
5157a3f5d11SAllan Jude __weak_reference(_libmd_SHA512_Final, SHA512_Final);
5167a3f5d11SAllan Jude #undef SHA512_Transform
5177a3f5d11SAllan Jude __weak_reference(_libmd_SHA512_Transform, SHA512_Transform);
5187a3f5d11SAllan Jude 
5191780e407SAllan Jude #undef SHA512_224_Init
5201780e407SAllan Jude __weak_reference(_libmd_SHA512_224_Init, SHA512_224_Init);
5211780e407SAllan Jude #undef SHA512_224_Update
5221780e407SAllan Jude __weak_reference(_libmd_SHA512_224_Update, SHA512_224_Update);
5231780e407SAllan Jude #undef SHA512_224_Final
5241780e407SAllan Jude __weak_reference(_libmd_SHA512_224_Final, SHA512_224_Final);
5251780e407SAllan Jude 
5261780e407SAllan Jude #undef SHA512_256_Init
5271780e407SAllan Jude __weak_reference(_libmd_SHA512_256_Init, SHA512_256_Init);
5281780e407SAllan Jude #undef SHA512_256_Update
5291780e407SAllan Jude __weak_reference(_libmd_SHA512_256_Update, SHA512_256_Update);
5301780e407SAllan Jude #undef SHA512_256_Final
5311780e407SAllan Jude __weak_reference(_libmd_SHA512_256_Final, SHA512_256_Final);
5321780e407SAllan Jude 
5337a3f5d11SAllan Jude #undef SHA384_Init
5347a3f5d11SAllan Jude __weak_reference(_libmd_SHA384_Init, SHA384_Init);
5357a3f5d11SAllan Jude #undef SHA384_Update
5367a3f5d11SAllan Jude __weak_reference(_libmd_SHA384_Update, SHA384_Update);
5377a3f5d11SAllan Jude #undef SHA384_Final
5387a3f5d11SAllan Jude __weak_reference(_libmd_SHA384_Final, SHA384_Final);
5397a3f5d11SAllan Jude #endif
540