xref: /freebsd/sys/crypto/sha2/sha512c.c (revision 81de655acd2ebdf104dc4a332eaee5e62b8440a2)
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 #include <sys/endian.h>
307a3f5d11SAllan Jude #include <sys/types.h>
317a3f5d11SAllan Jude 
327a3f5d11SAllan Jude #ifdef _KERNEL
337a3f5d11SAllan Jude #include <sys/systm.h>
347a3f5d11SAllan Jude #else
357a3f5d11SAllan Jude #include <string.h>
367a3f5d11SAllan Jude #endif
377a3f5d11SAllan Jude 
387a3f5d11SAllan Jude #include "sha512.h"
391780e407SAllan Jude #include "sha512t.h"
407a3f5d11SAllan Jude #include "sha384.h"
4171bf1c4cSAndrew Turner #include "sha512c_impl.h"
4271bf1c4cSAndrew Turner 
4371bf1c4cSAndrew Turner #if defined(ARM64_SHA512)
4471bf1c4cSAndrew Turner #include <sys/auxv.h>
4571bf1c4cSAndrew Turner #include <machine/ifunc.h>
4671bf1c4cSAndrew Turner #endif
477a3f5d11SAllan Jude 
487a3f5d11SAllan Jude #if BYTE_ORDER == BIG_ENDIAN
497a3f5d11SAllan Jude 
507a3f5d11SAllan Jude /* Copy a vector of big-endian uint64_t into a vector of bytes */
517a3f5d11SAllan Jude #define be64enc_vect(dst, src, len)	\
527a3f5d11SAllan Jude 	memcpy((void *)dst, (const void *)src, (size_t)len)
537a3f5d11SAllan Jude 
547a3f5d11SAllan Jude /* Copy a vector of bytes into a vector of big-endian uint64_t */
557a3f5d11SAllan Jude #define be64dec_vect(dst, src, len)	\
567a3f5d11SAllan Jude 	memcpy((void *)dst, (const void *)src, (size_t)len)
577a3f5d11SAllan Jude 
587a3f5d11SAllan Jude #else /* BYTE_ORDER != BIG_ENDIAN */
597a3f5d11SAllan Jude 
607a3f5d11SAllan Jude /*
61*6680cfe8SSebastian Huber  * Encode a length (len + 7) / 8 vector of (uint64_t) into a length len
62*6680cfe8SSebastian Huber  * vector of (unsigned char) in big-endian form.  Assumes len is a
63*6680cfe8SSebastian Huber  * multiple of 4.
647a3f5d11SAllan Jude  */
65*6680cfe8SSebastian Huber static inline void
be64enc_vect(unsigned char * dst,const uint64_t * src,size_t len)667a3f5d11SAllan Jude be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
677a3f5d11SAllan Jude {
687a3f5d11SAllan Jude 	size_t i;
697a3f5d11SAllan Jude 
707a3f5d11SAllan Jude 	for (i = 0; i < len / 8; i++)
717a3f5d11SAllan Jude 		be64enc(dst + i * 8, src[i]);
72*6680cfe8SSebastian Huber 	if (len % 8 == 4)
73*6680cfe8SSebastian Huber 		be32enc(dst + i * 8, src[i] >> 32);
747a3f5d11SAllan Jude }
757a3f5d11SAllan Jude 
767a3f5d11SAllan Jude /*
777a3f5d11SAllan Jude  * Decode a big-endian length len vector of (unsigned char) into a length
78*6680cfe8SSebastian Huber  * len/8 vector of (uint64_t).  Assumes len is a multiple of 8.
797a3f5d11SAllan Jude  */
80*6680cfe8SSebastian Huber static inline void
be64dec_vect(uint64_t * dst,const unsigned char * src,size_t len)817a3f5d11SAllan Jude be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
827a3f5d11SAllan Jude {
837a3f5d11SAllan Jude 	size_t i;
847a3f5d11SAllan Jude 
857a3f5d11SAllan Jude 	for (i = 0; i < len / 8; i++)
867a3f5d11SAllan Jude 		dst[i] = be64dec(src + i * 8);
877a3f5d11SAllan Jude }
887a3f5d11SAllan Jude 
897a3f5d11SAllan Jude #endif /* BYTE_ORDER != BIG_ENDIAN */
907a3f5d11SAllan Jude 
91696c3895SColin Percival /* SHA512 round constants. */
92696c3895SColin Percival static const uint64_t K[80] = {
93696c3895SColin Percival 	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
94696c3895SColin Percival 	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
95696c3895SColin Percival 	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
96696c3895SColin Percival 	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
97696c3895SColin Percival 	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
98696c3895SColin Percival 	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
99696c3895SColin Percival 	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
100696c3895SColin Percival 	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
101696c3895SColin Percival 	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
102696c3895SColin Percival 	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
103696c3895SColin Percival 	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
104696c3895SColin Percival 	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
105696c3895SColin Percival 	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
106696c3895SColin Percival 	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
107696c3895SColin Percival 	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
108696c3895SColin Percival 	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
109696c3895SColin Percival 	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
110696c3895SColin Percival 	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
111696c3895SColin Percival 	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
112696c3895SColin Percival 	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
113696c3895SColin Percival 	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
114696c3895SColin Percival 	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
115696c3895SColin Percival 	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
116696c3895SColin Percival 	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
117696c3895SColin Percival 	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
118696c3895SColin Percival 	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
119696c3895SColin Percival 	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
120696c3895SColin Percival 	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
121696c3895SColin Percival 	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
122696c3895SColin Percival 	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
123696c3895SColin Percival 	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
124696c3895SColin Percival 	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
125696c3895SColin Percival 	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
126696c3895SColin Percival 	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
127696c3895SColin Percival 	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
128696c3895SColin Percival 	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
129696c3895SColin Percival 	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
130696c3895SColin Percival 	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
131696c3895SColin Percival 	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
132696c3895SColin Percival 	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
133696c3895SColin Percival };
134696c3895SColin Percival 
1357a3f5d11SAllan Jude /* Elementary functions used by SHA512 */
1367a3f5d11SAllan Jude #define Ch(x, y, z)	((x & (y ^ z)) ^ z)
1377a3f5d11SAllan Jude #define Maj(x, y, z)	((x & (y | z)) | (y & z))
1387a3f5d11SAllan Jude #define SHR(x, n)	(x >> n)
1397a3f5d11SAllan Jude #define ROTR(x, n)	((x >> n) | (x << (64 - n)))
1407a3f5d11SAllan Jude #define S0(x)		(ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
1417a3f5d11SAllan Jude #define S1(x)		(ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
1427a3f5d11SAllan Jude #define s0(x)		(ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
1437a3f5d11SAllan Jude #define s1(x)		(ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
1447a3f5d11SAllan Jude 
1457a3f5d11SAllan Jude /* SHA512 round function */
1467a3f5d11SAllan Jude #define RND(a, b, c, d, e, f, g, h, k)			\
147696c3895SColin Percival 	h += S1(e) + Ch(e, f, g) + k;			\
148696c3895SColin Percival 	d += h;						\
149696c3895SColin Percival 	h += S0(a) + Maj(a, b, c);
1507a3f5d11SAllan Jude 
1517a3f5d11SAllan Jude /* Adjusted round function for rotating state */
152696c3895SColin Percival #define RNDr(S, W, i, ii)			\
1537a3f5d11SAllan Jude 	RND(S[(80 - i) % 8], S[(81 - i) % 8],	\
1547a3f5d11SAllan Jude 	    S[(82 - i) % 8], S[(83 - i) % 8],	\
1557a3f5d11SAllan Jude 	    S[(84 - i) % 8], S[(85 - i) % 8],	\
1567a3f5d11SAllan Jude 	    S[(86 - i) % 8], S[(87 - i) % 8],	\
157696c3895SColin Percival 	    W[i + ii] + K[i + ii])
158696c3895SColin Percival 
159696c3895SColin Percival /* Message schedule computation */
160696c3895SColin Percival #define MSCH(W, ii, i)				\
161696c3895SColin Percival 	W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
1627a3f5d11SAllan Jude 
1637a3f5d11SAllan Jude /*
1647a3f5d11SAllan Jude  * SHA512 block compression function.  The 512-bit state is transformed via
1657a3f5d11SAllan Jude  * the 512-bit input block to produce a new state.
1667a3f5d11SAllan Jude  */
1677a3f5d11SAllan Jude static void
16871bf1c4cSAndrew Turner #if defined(ARM64_SHA512)
SHA512_Transform_c(uint64_t * state,const unsigned char block[SHA512_BLOCK_LENGTH])16971bf1c4cSAndrew Turner SHA512_Transform_c(uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH])
17071bf1c4cSAndrew Turner #else
1717a3f5d11SAllan Jude SHA512_Transform(uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH])
17271bf1c4cSAndrew Turner #endif
1737a3f5d11SAllan Jude {
1747a3f5d11SAllan Jude 	uint64_t W[80];
1757a3f5d11SAllan Jude 	uint64_t S[8];
1767a3f5d11SAllan Jude 	int i;
1777a3f5d11SAllan Jude 
178696c3895SColin Percival 	/* 1. Prepare the first part of the message schedule W. */
1797a3f5d11SAllan Jude 	be64dec_vect(W, block, SHA512_BLOCK_LENGTH);
1807a3f5d11SAllan Jude 
1817a3f5d11SAllan Jude 	/* 2. Initialize working variables. */
1827a3f5d11SAllan Jude 	memcpy(S, state, SHA512_DIGEST_LENGTH);
1837a3f5d11SAllan Jude 
1847a3f5d11SAllan Jude 	/* 3. Mix. */
185696c3895SColin Percival 	for (i = 0; i < 80; i += 16) {
186696c3895SColin Percival 		RNDr(S, W, 0, i);
187696c3895SColin Percival 		RNDr(S, W, 1, i);
188696c3895SColin Percival 		RNDr(S, W, 2, i);
189696c3895SColin Percival 		RNDr(S, W, 3, i);
190696c3895SColin Percival 		RNDr(S, W, 4, i);
191696c3895SColin Percival 		RNDr(S, W, 5, i);
192696c3895SColin Percival 		RNDr(S, W, 6, i);
193696c3895SColin Percival 		RNDr(S, W, 7, i);
194696c3895SColin Percival 		RNDr(S, W, 8, i);
195696c3895SColin Percival 		RNDr(S, W, 9, i);
196696c3895SColin Percival 		RNDr(S, W, 10, i);
197696c3895SColin Percival 		RNDr(S, W, 11, i);
198696c3895SColin Percival 		RNDr(S, W, 12, i);
199696c3895SColin Percival 		RNDr(S, W, 13, i);
200696c3895SColin Percival 		RNDr(S, W, 14, i);
201696c3895SColin Percival 		RNDr(S, W, 15, i);
202696c3895SColin Percival 
203696c3895SColin Percival 		if (i == 64)
204696c3895SColin Percival 			break;
205696c3895SColin Percival 		MSCH(W, 0, i);
206696c3895SColin Percival 		MSCH(W, 1, i);
207696c3895SColin Percival 		MSCH(W, 2, i);
208696c3895SColin Percival 		MSCH(W, 3, i);
209696c3895SColin Percival 		MSCH(W, 4, i);
210696c3895SColin Percival 		MSCH(W, 5, i);
211696c3895SColin Percival 		MSCH(W, 6, i);
212696c3895SColin Percival 		MSCH(W, 7, i);
213696c3895SColin Percival 		MSCH(W, 8, i);
214696c3895SColin Percival 		MSCH(W, 9, i);
215696c3895SColin Percival 		MSCH(W, 10, i);
216696c3895SColin Percival 		MSCH(W, 11, i);
217696c3895SColin Percival 		MSCH(W, 12, i);
218696c3895SColin Percival 		MSCH(W, 13, i);
219696c3895SColin Percival 		MSCH(W, 14, i);
220696c3895SColin Percival 		MSCH(W, 15, i);
221696c3895SColin Percival 	}
2227a3f5d11SAllan Jude 
2237a3f5d11SAllan Jude 	/* 4. Mix local working variables into global state */
2247a3f5d11SAllan Jude 	for (i = 0; i < 8; i++)
2257a3f5d11SAllan Jude 		state[i] += S[i];
2267a3f5d11SAllan Jude }
2277a3f5d11SAllan Jude 
22871bf1c4cSAndrew Turner #if defined(ARM64_SHA512)
22971bf1c4cSAndrew Turner static void
SHA512_Transform_arm64(uint64_t * state,const unsigned char block[SHA512_BLOCK_LENGTH])23071bf1c4cSAndrew Turner SHA512_Transform_arm64(uint64_t * state,
23171bf1c4cSAndrew Turner     const unsigned char block[SHA512_BLOCK_LENGTH])
23271bf1c4cSAndrew Turner {
23371bf1c4cSAndrew Turner 	SHA512_Transform_arm64_impl(state, block, K);
23471bf1c4cSAndrew Turner }
23571bf1c4cSAndrew Turner 
23671bf1c4cSAndrew Turner DEFINE_UIFUNC(static, void, SHA512_Transform,
23771bf1c4cSAndrew Turner     (uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH]))
23871bf1c4cSAndrew Turner {
23971bf1c4cSAndrew Turner 	u_long hwcap;
24071bf1c4cSAndrew Turner 
24171bf1c4cSAndrew Turner 	if (elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)) == 0) {
24271bf1c4cSAndrew Turner 		if ((hwcap & HWCAP_SHA512) != 0) {
24371bf1c4cSAndrew Turner 			return (SHA512_Transform_arm64);
24471bf1c4cSAndrew Turner 		}
24571bf1c4cSAndrew Turner 	}
24671bf1c4cSAndrew Turner 
24771bf1c4cSAndrew Turner 	return (SHA512_Transform_c);
24871bf1c4cSAndrew Turner }
24971bf1c4cSAndrew Turner #endif
25071bf1c4cSAndrew Turner 
2517a3f5d11SAllan Jude static unsigned char PAD[SHA512_BLOCK_LENGTH] = {
2527a3f5d11SAllan Jude 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2537a3f5d11SAllan Jude 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2547a3f5d11SAllan Jude 	0, 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 };
2617a3f5d11SAllan Jude 
2627a3f5d11SAllan Jude /* Add padding and terminating bit-count. */
2637a3f5d11SAllan Jude static void
SHA512_Pad(SHA512_CTX * ctx)2647a3f5d11SAllan Jude SHA512_Pad(SHA512_CTX * ctx)
2657a3f5d11SAllan Jude {
266696c3895SColin Percival 	size_t r;
2677a3f5d11SAllan Jude 
268696c3895SColin Percival 	/* Figure out how many bytes we have buffered. */
2697a3f5d11SAllan Jude 	r = (ctx->count[1] >> 3) & 0x7f;
2707a3f5d11SAllan Jude 
271696c3895SColin Percival 	/* Pad to 112 mod 128, transforming if we finish a block en route. */
272696c3895SColin Percival 	if (r < 112) {
273696c3895SColin Percival 		/* Pad to 112 mod 128. */
274696c3895SColin Percival 		memcpy(&ctx->buf[r], PAD, 112 - r);
275696c3895SColin Percival 	} else {
276696c3895SColin Percival 		/* Finish the current block and mix. */
277696c3895SColin Percival 		memcpy(&ctx->buf[r], PAD, 128 - r);
278696c3895SColin Percival 		SHA512_Transform(ctx->state, ctx->buf);
279696c3895SColin Percival 
280696c3895SColin Percival 		/* The start of the final block is all zeroes. */
281696c3895SColin Percival 		memset(&ctx->buf[0], 0, 112);
282696c3895SColin Percival 	}
283696c3895SColin Percival 
284696c3895SColin Percival 	/* Add the terminating bit-count. */
285696c3895SColin Percival 	be64enc_vect(&ctx->buf[112], ctx->count, 16);
286696c3895SColin Percival 
287696c3895SColin Percival 	/* Mix in the final block. */
288696c3895SColin Percival 	SHA512_Transform(ctx->state, ctx->buf);
2897a3f5d11SAllan Jude }
2907a3f5d11SAllan Jude 
2917a3f5d11SAllan Jude /* SHA-512 initialization.  Begins a SHA-512 operation. */
2927a3f5d11SAllan Jude void
SHA512_Init(SHA512_CTX * ctx)2937a3f5d11SAllan Jude SHA512_Init(SHA512_CTX * ctx)
2947a3f5d11SAllan Jude {
2957a3f5d11SAllan Jude 
2967a3f5d11SAllan Jude 	/* Zero bits processed so far */
2977a3f5d11SAllan Jude 	ctx->count[0] = ctx->count[1] = 0;
2987a3f5d11SAllan Jude 
2997a3f5d11SAllan Jude 	/* Magic initialization constants */
3007a3f5d11SAllan Jude 	ctx->state[0] = 0x6a09e667f3bcc908ULL;
3017a3f5d11SAllan Jude 	ctx->state[1] = 0xbb67ae8584caa73bULL;
3027a3f5d11SAllan Jude 	ctx->state[2] = 0x3c6ef372fe94f82bULL;
3037a3f5d11SAllan Jude 	ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
3047a3f5d11SAllan Jude 	ctx->state[4] = 0x510e527fade682d1ULL;
3057a3f5d11SAllan Jude 	ctx->state[5] = 0x9b05688c2b3e6c1fULL;
3067a3f5d11SAllan Jude 	ctx->state[6] = 0x1f83d9abfb41bd6bULL;
3077a3f5d11SAllan Jude 	ctx->state[7] = 0x5be0cd19137e2179ULL;
3087a3f5d11SAllan Jude }
3097a3f5d11SAllan Jude 
3107a3f5d11SAllan Jude /* Add bytes into the hash */
3117a3f5d11SAllan Jude void
SHA512_Update(SHA512_CTX * ctx,const void * in,size_t len)3127a3f5d11SAllan Jude SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
3137a3f5d11SAllan Jude {
3147a3f5d11SAllan Jude 	uint64_t bitlen[2];
3157a3f5d11SAllan Jude 	uint64_t r;
3167a3f5d11SAllan Jude 	const unsigned char *src = in;
3177a3f5d11SAllan Jude 
3187a3f5d11SAllan Jude 	/* Number of bytes left in the buffer from previous updates */
3197a3f5d11SAllan Jude 	r = (ctx->count[1] >> 3) & 0x7f;
3207a3f5d11SAllan Jude 
3217a3f5d11SAllan Jude 	/* Convert the length into a number of bits */
3227a3f5d11SAllan Jude 	bitlen[1] = ((uint64_t)len) << 3;
3237a3f5d11SAllan Jude 	bitlen[0] = ((uint64_t)len) >> 61;
3247a3f5d11SAllan Jude 
3257a3f5d11SAllan Jude 	/* Update number of bits */
3267a3f5d11SAllan Jude 	if ((ctx->count[1] += bitlen[1]) < bitlen[1])
3277a3f5d11SAllan Jude 		ctx->count[0]++;
3287a3f5d11SAllan Jude 	ctx->count[0] += bitlen[0];
3297a3f5d11SAllan Jude 
3307a3f5d11SAllan Jude 	/* Handle the case where we don't need to perform any transforms */
3317a3f5d11SAllan Jude 	if (len < SHA512_BLOCK_LENGTH - r) {
3327a3f5d11SAllan Jude 		memcpy(&ctx->buf[r], src, len);
3337a3f5d11SAllan Jude 		return;
3347a3f5d11SAllan Jude 	}
3357a3f5d11SAllan Jude 
3367a3f5d11SAllan Jude 	/* Finish the current block */
3377a3f5d11SAllan Jude 	memcpy(&ctx->buf[r], src, SHA512_BLOCK_LENGTH - r);
3387a3f5d11SAllan Jude 	SHA512_Transform(ctx->state, ctx->buf);
3397a3f5d11SAllan Jude 	src += SHA512_BLOCK_LENGTH - r;
3407a3f5d11SAllan Jude 	len -= SHA512_BLOCK_LENGTH - r;
3417a3f5d11SAllan Jude 
3427a3f5d11SAllan Jude 	/* Perform complete blocks */
3437a3f5d11SAllan Jude 	while (len >= SHA512_BLOCK_LENGTH) {
3447a3f5d11SAllan Jude 		SHA512_Transform(ctx->state, src);
3457a3f5d11SAllan Jude 		src += SHA512_BLOCK_LENGTH;
3467a3f5d11SAllan Jude 		len -= SHA512_BLOCK_LENGTH;
3477a3f5d11SAllan Jude 	}
3487a3f5d11SAllan Jude 
3497a3f5d11SAllan Jude 	/* Copy left over data into buffer */
3507a3f5d11SAllan Jude 	memcpy(ctx->buf, src, len);
3517a3f5d11SAllan Jude }
3527a3f5d11SAllan Jude 
3537a3f5d11SAllan Jude /*
3547a3f5d11SAllan Jude  * SHA-512 finalization.  Pads the input data, exports the hash value,
3557a3f5d11SAllan Jude  * and clears the context state.
3567a3f5d11SAllan Jude  */
3577a3f5d11SAllan Jude void
SHA512_Final(unsigned char digest[static SHA512_DIGEST_LENGTH],SHA512_CTX * ctx)358571ebf76SConrad Meyer SHA512_Final(unsigned char digest[static SHA512_DIGEST_LENGTH], SHA512_CTX *ctx)
3597a3f5d11SAllan Jude {
3607a3f5d11SAllan Jude 
3617a3f5d11SAllan Jude 	/* Add padding */
3627a3f5d11SAllan Jude 	SHA512_Pad(ctx);
3637a3f5d11SAllan Jude 
3647a3f5d11SAllan Jude 	/* Write the hash */
3657a3f5d11SAllan Jude 	be64enc_vect(digest, ctx->state, SHA512_DIGEST_LENGTH);
3667a3f5d11SAllan Jude 
3677a3f5d11SAllan Jude 	/* Clear the context state */
36866bdf50fSXin LI 	explicit_bzero(ctx, sizeof(*ctx));
3697a3f5d11SAllan Jude }
3707a3f5d11SAllan Jude 
3711780e407SAllan Jude /*** SHA-512t: *********************************************************/
3721780e407SAllan Jude /*
3731780e407SAllan Jude  * the SHA512t transforms are identical to SHA512 so reuse the existing function
3741780e407SAllan Jude  */
3751780e407SAllan Jude void
SHA512_224_Init(SHA512_CTX * ctx)3761780e407SAllan Jude SHA512_224_Init(SHA512_CTX * ctx)
3771780e407SAllan Jude {
3781780e407SAllan Jude 
3791780e407SAllan Jude 	/* Zero bits processed so far */
3801780e407SAllan Jude 	ctx->count[0] = ctx->count[1] = 0;
3811780e407SAllan Jude 
3821780e407SAllan Jude 	/* Magic initialization constants */
3831780e407SAllan Jude 	ctx->state[0] = 0x8c3d37c819544da2ULL;
3841780e407SAllan Jude 	ctx->state[1] = 0x73e1996689dcd4d6ULL;
3851780e407SAllan Jude 	ctx->state[2] = 0x1dfab7ae32ff9c82ULL;
3861780e407SAllan Jude 	ctx->state[3] = 0x679dd514582f9fcfULL;
3871780e407SAllan Jude 	ctx->state[4] = 0x0f6d2b697bd44da8ULL;
3881780e407SAllan Jude 	ctx->state[5] = 0x77e36f7304c48942ULL;
3891780e407SAllan Jude 	ctx->state[6] = 0x3f9d85a86a1d36c8ULL;
3901780e407SAllan Jude 	ctx->state[7] = 0x1112e6ad91d692a1ULL;
3911780e407SAllan Jude }
3921780e407SAllan Jude 
3931780e407SAllan Jude void
SHA512_224_Update(SHA512_CTX * ctx,const void * in,size_t len)3941780e407SAllan Jude SHA512_224_Update(SHA512_CTX * ctx, const void *in, size_t len)
3951780e407SAllan Jude {
3961780e407SAllan Jude 
3971780e407SAllan Jude 	SHA512_Update(ctx, in, len);
3981780e407SAllan Jude }
3991780e407SAllan Jude 
4001780e407SAllan Jude void
SHA512_224_Final(unsigned char digest[static SHA512_224_DIGEST_LENGTH],SHA512_CTX * ctx)4011780e407SAllan Jude SHA512_224_Final(unsigned char digest[static SHA512_224_DIGEST_LENGTH], SHA512_CTX * ctx)
4021780e407SAllan Jude {
4031780e407SAllan Jude 
4041780e407SAllan Jude 	/* Add padding */
4051780e407SAllan Jude 	SHA512_Pad(ctx);
4061780e407SAllan Jude 
4071780e407SAllan Jude 	/* Write the hash */
4081780e407SAllan Jude 	be64enc_vect(digest, ctx->state, SHA512_224_DIGEST_LENGTH);
4091780e407SAllan Jude 
4101780e407SAllan Jude 	/* Clear the context state */
41166bdf50fSXin LI 	explicit_bzero(ctx, sizeof(*ctx));
4121780e407SAllan Jude }
4131780e407SAllan Jude 
4141780e407SAllan Jude void
SHA512_256_Init(SHA512_CTX * ctx)4151780e407SAllan Jude SHA512_256_Init(SHA512_CTX * ctx)
4161780e407SAllan Jude {
4171780e407SAllan Jude 
4181780e407SAllan Jude 	/* Zero bits processed so far */
4191780e407SAllan Jude 	ctx->count[0] = ctx->count[1] = 0;
4201780e407SAllan Jude 
4211780e407SAllan Jude 	/* Magic initialization constants */
4221780e407SAllan Jude 	ctx->state[0] = 0x22312194fc2bf72cULL;
4231780e407SAllan Jude 	ctx->state[1] = 0x9f555fa3c84c64c2ULL;
4241780e407SAllan Jude 	ctx->state[2] = 0x2393b86b6f53b151ULL;
4251780e407SAllan Jude 	ctx->state[3] = 0x963877195940eabdULL;
4261780e407SAllan Jude 	ctx->state[4] = 0x96283ee2a88effe3ULL;
4271780e407SAllan Jude 	ctx->state[5] = 0xbe5e1e2553863992ULL;
4281780e407SAllan Jude 	ctx->state[6] = 0x2b0199fc2c85b8aaULL;
4291780e407SAllan Jude 	ctx->state[7] = 0x0eb72ddc81c52ca2ULL;
4301780e407SAllan Jude }
4311780e407SAllan Jude 
4321780e407SAllan Jude void
SHA512_256_Update(SHA512_CTX * ctx,const void * in,size_t len)4331780e407SAllan Jude SHA512_256_Update(SHA512_CTX * ctx, const void *in, size_t len)
4341780e407SAllan Jude {
4351780e407SAllan Jude 
4361780e407SAllan Jude 	SHA512_Update(ctx, in, len);
4371780e407SAllan Jude }
4381780e407SAllan Jude 
4391780e407SAllan Jude void
SHA512_256_Final(unsigned char digest[static SHA512_256_DIGEST_LENGTH],SHA512_CTX * ctx)4401780e407SAllan Jude SHA512_256_Final(unsigned char digest[static SHA512_256_DIGEST_LENGTH], SHA512_CTX * ctx)
4411780e407SAllan Jude {
4421780e407SAllan Jude 
4431780e407SAllan Jude 	/* Add padding */
4441780e407SAllan Jude 	SHA512_Pad(ctx);
4451780e407SAllan Jude 
4461780e407SAllan Jude 	/* Write the hash */
4471780e407SAllan Jude 	be64enc_vect(digest, ctx->state, SHA512_256_DIGEST_LENGTH);
4481780e407SAllan Jude 
4491780e407SAllan Jude 	/* Clear the context state */
45066bdf50fSXin LI 	explicit_bzero(ctx, sizeof(*ctx));
4511780e407SAllan Jude }
4521780e407SAllan Jude 
4537a3f5d11SAllan Jude /*** SHA-384: *********************************************************/
4547a3f5d11SAllan Jude /*
4557a3f5d11SAllan Jude  * the SHA384 and SHA512 transforms are identical, so SHA384 is skipped
4567a3f5d11SAllan Jude  */
4577a3f5d11SAllan Jude 
4587a3f5d11SAllan Jude /* SHA-384 initialization.  Begins a SHA-384 operation. */
4597a3f5d11SAllan Jude void
SHA384_Init(SHA384_CTX * ctx)4607a3f5d11SAllan Jude SHA384_Init(SHA384_CTX * ctx)
4617a3f5d11SAllan Jude {
4627a3f5d11SAllan Jude 
4637a3f5d11SAllan Jude 	/* Zero bits processed so far */
4647a3f5d11SAllan Jude 	ctx->count[0] = ctx->count[1] = 0;
4657a3f5d11SAllan Jude 
4667a3f5d11SAllan Jude 	/* Magic initialization constants */
4677a3f5d11SAllan Jude 	ctx->state[0] = 0xcbbb9d5dc1059ed8ULL;
4687a3f5d11SAllan Jude 	ctx->state[1] = 0x629a292a367cd507ULL;
4697a3f5d11SAllan Jude 	ctx->state[2] = 0x9159015a3070dd17ULL;
4707a3f5d11SAllan Jude 	ctx->state[3] = 0x152fecd8f70e5939ULL;
4717a3f5d11SAllan Jude 	ctx->state[4] = 0x67332667ffc00b31ULL;
4727a3f5d11SAllan Jude 	ctx->state[5] = 0x8eb44a8768581511ULL;
4737a3f5d11SAllan Jude 	ctx->state[6] = 0xdb0c2e0d64f98fa7ULL;
4747a3f5d11SAllan Jude 	ctx->state[7] = 0x47b5481dbefa4fa4ULL;
4757a3f5d11SAllan Jude }
4767a3f5d11SAllan Jude 
4777a3f5d11SAllan Jude /* Add bytes into the SHA-384 hash */
4787a3f5d11SAllan Jude void
SHA384_Update(SHA384_CTX * ctx,const void * in,size_t len)4797a3f5d11SAllan Jude SHA384_Update(SHA384_CTX * ctx, const void *in, size_t len)
4807a3f5d11SAllan Jude {
4817a3f5d11SAllan Jude 
4827a3f5d11SAllan Jude 	SHA512_Update((SHA512_CTX *)ctx, in, len);
4837a3f5d11SAllan Jude }
4847a3f5d11SAllan Jude 
4857a3f5d11SAllan Jude /*
4867a3f5d11SAllan Jude  * SHA-384 finalization.  Pads the input data, exports the hash value,
4877a3f5d11SAllan Jude  * and clears the context state.
4887a3f5d11SAllan Jude  */
4897a3f5d11SAllan Jude void
SHA384_Final(unsigned char digest[static SHA384_DIGEST_LENGTH],SHA384_CTX * ctx)490571ebf76SConrad Meyer SHA384_Final(unsigned char digest[static SHA384_DIGEST_LENGTH], SHA384_CTX *ctx)
4917a3f5d11SAllan Jude {
4927a3f5d11SAllan Jude 
4937a3f5d11SAllan Jude 	/* Add padding */
4947a3f5d11SAllan Jude 	SHA512_Pad((SHA512_CTX *)ctx);
4957a3f5d11SAllan Jude 
4967a3f5d11SAllan Jude 	/* Write the hash */
4977a3f5d11SAllan Jude 	be64enc_vect(digest, ctx->state, SHA384_DIGEST_LENGTH);
4987a3f5d11SAllan Jude 
4997a3f5d11SAllan Jude 	/* Clear the context state */
50066bdf50fSXin LI 	explicit_bzero(ctx, sizeof(*ctx));
5017a3f5d11SAllan Jude }
5027a3f5d11SAllan Jude 
5037a3f5d11SAllan Jude #ifdef WEAK_REFS
5047a3f5d11SAllan Jude /* When building libmd, provide weak references. Note: this is not
5057a3f5d11SAllan Jude    activated in the context of compiling these sources for internal
5067a3f5d11SAllan Jude    use in libcrypt.
5077a3f5d11SAllan Jude  */
5087a3f5d11SAllan Jude #undef SHA512_Init
5097a3f5d11SAllan Jude __weak_reference(_libmd_SHA512_Init, SHA512_Init);
5107a3f5d11SAllan Jude #undef SHA512_Update
5117a3f5d11SAllan Jude __weak_reference(_libmd_SHA512_Update, SHA512_Update);
5127a3f5d11SAllan Jude #undef SHA512_Final
5137a3f5d11SAllan Jude __weak_reference(_libmd_SHA512_Final, SHA512_Final);
5147a3f5d11SAllan Jude 
5151780e407SAllan Jude #undef SHA512_224_Init
5161780e407SAllan Jude __weak_reference(_libmd_SHA512_224_Init, SHA512_224_Init);
5171780e407SAllan Jude #undef SHA512_224_Update
5181780e407SAllan Jude __weak_reference(_libmd_SHA512_224_Update, SHA512_224_Update);
5191780e407SAllan Jude #undef SHA512_224_Final
5201780e407SAllan Jude __weak_reference(_libmd_SHA512_224_Final, SHA512_224_Final);
5211780e407SAllan Jude 
5221780e407SAllan Jude #undef SHA512_256_Init
5231780e407SAllan Jude __weak_reference(_libmd_SHA512_256_Init, SHA512_256_Init);
5241780e407SAllan Jude #undef SHA512_256_Update
5251780e407SAllan Jude __weak_reference(_libmd_SHA512_256_Update, SHA512_256_Update);
5261780e407SAllan Jude #undef SHA512_256_Final
5271780e407SAllan Jude __weak_reference(_libmd_SHA512_256_Final, SHA512_256_Final);
5281780e407SAllan Jude 
5297a3f5d11SAllan Jude #undef SHA384_Init
5307a3f5d11SAllan Jude __weak_reference(_libmd_SHA384_Init, SHA384_Init);
5317a3f5d11SAllan Jude #undef SHA384_Update
5327a3f5d11SAllan Jude __weak_reference(_libmd_SHA384_Update, SHA384_Update);
5337a3f5d11SAllan Jude #undef SHA384_Final
5347a3f5d11SAllan Jude __weak_reference(_libmd_SHA384_Final, SHA384_Final);
5357a3f5d11SAllan Jude #endif
536