xref: /freebsd/sys/crypto/sha2/sha256c.c (revision 69d8dc20be6ca10cf87c98223121c4121aff42cc)
197447ea4SJohn-Mark Gurney /*-
297447ea4SJohn-Mark Gurney  * Copyright 2005 Colin Percival
397447ea4SJohn-Mark Gurney  * All rights reserved.
497447ea4SJohn-Mark Gurney  *
597447ea4SJohn-Mark Gurney  * Redistribution and use in source and binary forms, with or without
697447ea4SJohn-Mark Gurney  * modification, are permitted provided that the following conditions
797447ea4SJohn-Mark Gurney  * are met:
897447ea4SJohn-Mark Gurney  * 1. Redistributions of source code must retain the above copyright
997447ea4SJohn-Mark Gurney  *    notice, this list of conditions and the following disclaimer.
1097447ea4SJohn-Mark Gurney  * 2. Redistributions in binary form must reproduce the above copyright
1197447ea4SJohn-Mark Gurney  *    notice, this list of conditions and the following disclaimer in the
1297447ea4SJohn-Mark Gurney  *    documentation and/or other materials provided with the distribution.
1397447ea4SJohn-Mark Gurney  *
1497447ea4SJohn-Mark Gurney  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1597447ea4SJohn-Mark Gurney  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1697447ea4SJohn-Mark Gurney  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1797447ea4SJohn-Mark Gurney  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1897447ea4SJohn-Mark Gurney  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1997447ea4SJohn-Mark Gurney  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2097447ea4SJohn-Mark Gurney  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2197447ea4SJohn-Mark Gurney  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2297447ea4SJohn-Mark Gurney  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2397447ea4SJohn-Mark Gurney  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2497447ea4SJohn-Mark Gurney  * SUCH DAMAGE.
2597447ea4SJohn-Mark Gurney  */
2697447ea4SJohn-Mark Gurney 
2797447ea4SJohn-Mark Gurney #include <sys/cdefs.h>
2897447ea4SJohn-Mark Gurney __FBSDID("$FreeBSD$");
2997447ea4SJohn-Mark Gurney 
3097447ea4SJohn-Mark Gurney #include <sys/endian.h>
3197447ea4SJohn-Mark Gurney #include <sys/types.h>
3297447ea4SJohn-Mark Gurney 
338083f14fSJohn-Mark Gurney #ifdef _KERNEL
348083f14fSJohn-Mark Gurney #include <sys/systm.h>
358083f14fSJohn-Mark Gurney #else
3697447ea4SJohn-Mark Gurney #include <string.h>
378083f14fSJohn-Mark Gurney #endif
3897447ea4SJohn-Mark Gurney 
391245c6d1SConrad Meyer #include "sha224.h"
4097447ea4SJohn-Mark Gurney #include "sha256.h"
41*69d8dc20SAndrew Turner #include "sha256c_impl.h"
42*69d8dc20SAndrew Turner 
43*69d8dc20SAndrew Turner #if defined(ARM64_SHA2)
44*69d8dc20SAndrew Turner #include <sys/auxv.h>
45*69d8dc20SAndrew Turner #include <machine/ifunc.h>
46*69d8dc20SAndrew Turner #endif
4797447ea4SJohn-Mark Gurney 
4897447ea4SJohn-Mark Gurney #if BYTE_ORDER == BIG_ENDIAN
4997447ea4SJohn-Mark Gurney 
5097447ea4SJohn-Mark Gurney /* Copy a vector of big-endian uint32_t into a vector of bytes */
5197447ea4SJohn-Mark Gurney #define be32enc_vect(dst, src, len)	\
5297447ea4SJohn-Mark Gurney 	memcpy((void *)dst, (const void *)src, (size_t)len)
5397447ea4SJohn-Mark Gurney 
5497447ea4SJohn-Mark Gurney /* Copy a vector of bytes into a vector of big-endian uint32_t */
5597447ea4SJohn-Mark Gurney #define be32dec_vect(dst, src, len)	\
5697447ea4SJohn-Mark Gurney 	memcpy((void *)dst, (const void *)src, (size_t)len)
5797447ea4SJohn-Mark Gurney 
5897447ea4SJohn-Mark Gurney #else /* BYTE_ORDER != BIG_ENDIAN */
5997447ea4SJohn-Mark Gurney 
6097447ea4SJohn-Mark Gurney /*
6197447ea4SJohn-Mark Gurney  * Encode a length len/4 vector of (uint32_t) into a length len vector of
6297447ea4SJohn-Mark Gurney  * (unsigned char) in big-endian form.  Assumes len is a multiple of 4.
6397447ea4SJohn-Mark Gurney  */
6497447ea4SJohn-Mark Gurney static void
6597447ea4SJohn-Mark Gurney be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
6697447ea4SJohn-Mark Gurney {
6797447ea4SJohn-Mark Gurney 	size_t i;
6897447ea4SJohn-Mark Gurney 
6997447ea4SJohn-Mark Gurney 	for (i = 0; i < len / 4; i++)
7097447ea4SJohn-Mark Gurney 		be32enc(dst + i * 4, src[i]);
7197447ea4SJohn-Mark Gurney }
7297447ea4SJohn-Mark Gurney 
7397447ea4SJohn-Mark Gurney /*
7497447ea4SJohn-Mark Gurney  * Decode a big-endian length len vector of (unsigned char) into a length
7597447ea4SJohn-Mark Gurney  * len/4 vector of (uint32_t).  Assumes len is a multiple of 4.
7697447ea4SJohn-Mark Gurney  */
7797447ea4SJohn-Mark Gurney static void
7897447ea4SJohn-Mark Gurney be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
7997447ea4SJohn-Mark Gurney {
8097447ea4SJohn-Mark Gurney 	size_t i;
8197447ea4SJohn-Mark Gurney 
8297447ea4SJohn-Mark Gurney 	for (i = 0; i < len / 4; i++)
8397447ea4SJohn-Mark Gurney 		dst[i] = be32dec(src + i * 4);
8497447ea4SJohn-Mark Gurney }
8597447ea4SJohn-Mark Gurney 
8697447ea4SJohn-Mark Gurney #endif /* BYTE_ORDER != BIG_ENDIAN */
8797447ea4SJohn-Mark Gurney 
88696c3895SColin Percival /* SHA256 round constants. */
89696c3895SColin Percival static const uint32_t K[64] = {
90696c3895SColin Percival 	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
91696c3895SColin Percival 	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
92696c3895SColin Percival 	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
93696c3895SColin Percival 	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
94696c3895SColin Percival 	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
95696c3895SColin Percival 	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
96696c3895SColin Percival 	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
97696c3895SColin Percival 	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
98696c3895SColin Percival 	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
99696c3895SColin Percival 	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
100696c3895SColin Percival 	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
101696c3895SColin Percival 	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
102696c3895SColin Percival 	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
103696c3895SColin Percival 	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
104696c3895SColin Percival 	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
105696c3895SColin Percival 	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
106696c3895SColin Percival };
107696c3895SColin Percival 
10897447ea4SJohn-Mark Gurney /* Elementary functions used by SHA256 */
10997447ea4SJohn-Mark Gurney #define Ch(x, y, z)	((x & (y ^ z)) ^ z)
11097447ea4SJohn-Mark Gurney #define Maj(x, y, z)	((x & (y | z)) | (y & z))
11197447ea4SJohn-Mark Gurney #define SHR(x, n)	(x >> n)
11297447ea4SJohn-Mark Gurney #define ROTR(x, n)	((x >> n) | (x << (32 - n)))
11397447ea4SJohn-Mark Gurney #define S0(x)		(ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
11497447ea4SJohn-Mark Gurney #define S1(x)		(ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
11597447ea4SJohn-Mark Gurney #define s0(x)		(ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
11697447ea4SJohn-Mark Gurney #define s1(x)		(ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
11797447ea4SJohn-Mark Gurney 
11897447ea4SJohn-Mark Gurney /* SHA256 round function */
11997447ea4SJohn-Mark Gurney #define RND(a, b, c, d, e, f, g, h, k)			\
120696c3895SColin Percival 	h += S1(e) + Ch(e, f, g) + k;			\
121696c3895SColin Percival 	d += h;						\
122696c3895SColin Percival 	h += S0(a) + Maj(a, b, c);
12397447ea4SJohn-Mark Gurney 
12497447ea4SJohn-Mark Gurney /* Adjusted round function for rotating state */
125696c3895SColin Percival #define RNDr(S, W, i, ii)			\
12697447ea4SJohn-Mark Gurney 	RND(S[(64 - i) % 8], S[(65 - i) % 8],	\
12797447ea4SJohn-Mark Gurney 	    S[(66 - i) % 8], S[(67 - i) % 8],	\
12897447ea4SJohn-Mark Gurney 	    S[(68 - i) % 8], S[(69 - i) % 8],	\
12997447ea4SJohn-Mark Gurney 	    S[(70 - i) % 8], S[(71 - i) % 8],	\
130696c3895SColin Percival 	    W[i + ii] + K[i + ii])
131696c3895SColin Percival 
132696c3895SColin Percival /* Message schedule computation */
133696c3895SColin Percival #define MSCH(W, ii, i)				\
134696c3895SColin Percival 	W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
13597447ea4SJohn-Mark Gurney 
13697447ea4SJohn-Mark Gurney /*
13797447ea4SJohn-Mark Gurney  * SHA256 block compression function.  The 256-bit state is transformed via
13897447ea4SJohn-Mark Gurney  * the 512-bit input block to produce a new state.
13997447ea4SJohn-Mark Gurney  */
14097447ea4SJohn-Mark Gurney static void
141*69d8dc20SAndrew Turner SHA256_Transform_c(uint32_t * state, const unsigned char block[64])
14297447ea4SJohn-Mark Gurney {
14397447ea4SJohn-Mark Gurney 	uint32_t W[64];
14497447ea4SJohn-Mark Gurney 	uint32_t S[8];
14597447ea4SJohn-Mark Gurney 	int i;
14697447ea4SJohn-Mark Gurney 
147696c3895SColin Percival 	/* 1. Prepare the first part of the message schedule W. */
14897447ea4SJohn-Mark Gurney 	be32dec_vect(W, block, 64);
14997447ea4SJohn-Mark Gurney 
15097447ea4SJohn-Mark Gurney 	/* 2. Initialize working variables. */
15197447ea4SJohn-Mark Gurney 	memcpy(S, state, 32);
15297447ea4SJohn-Mark Gurney 
15397447ea4SJohn-Mark Gurney 	/* 3. Mix. */
154696c3895SColin Percival 	for (i = 0; i < 64; i += 16) {
155696c3895SColin Percival 		RNDr(S, W, 0, i);
156696c3895SColin Percival 		RNDr(S, W, 1, i);
157696c3895SColin Percival 		RNDr(S, W, 2, i);
158696c3895SColin Percival 		RNDr(S, W, 3, i);
159696c3895SColin Percival 		RNDr(S, W, 4, i);
160696c3895SColin Percival 		RNDr(S, W, 5, i);
161696c3895SColin Percival 		RNDr(S, W, 6, i);
162696c3895SColin Percival 		RNDr(S, W, 7, i);
163696c3895SColin Percival 		RNDr(S, W, 8, i);
164696c3895SColin Percival 		RNDr(S, W, 9, i);
165696c3895SColin Percival 		RNDr(S, W, 10, i);
166696c3895SColin Percival 		RNDr(S, W, 11, i);
167696c3895SColin Percival 		RNDr(S, W, 12, i);
168696c3895SColin Percival 		RNDr(S, W, 13, i);
169696c3895SColin Percival 		RNDr(S, W, 14, i);
170696c3895SColin Percival 		RNDr(S, W, 15, i);
171696c3895SColin Percival 
172696c3895SColin Percival 		if (i == 48)
173696c3895SColin Percival 			break;
174696c3895SColin Percival 		MSCH(W, 0, i);
175696c3895SColin Percival 		MSCH(W, 1, i);
176696c3895SColin Percival 		MSCH(W, 2, i);
177696c3895SColin Percival 		MSCH(W, 3, i);
178696c3895SColin Percival 		MSCH(W, 4, i);
179696c3895SColin Percival 		MSCH(W, 5, i);
180696c3895SColin Percival 		MSCH(W, 6, i);
181696c3895SColin Percival 		MSCH(W, 7, i);
182696c3895SColin Percival 		MSCH(W, 8, i);
183696c3895SColin Percival 		MSCH(W, 9, i);
184696c3895SColin Percival 		MSCH(W, 10, i);
185696c3895SColin Percival 		MSCH(W, 11, i);
186696c3895SColin Percival 		MSCH(W, 12, i);
187696c3895SColin Percival 		MSCH(W, 13, i);
188696c3895SColin Percival 		MSCH(W, 14, i);
189696c3895SColin Percival 		MSCH(W, 15, i);
190696c3895SColin Percival 	}
19197447ea4SJohn-Mark Gurney 
19297447ea4SJohn-Mark Gurney 	/* 4. Mix local working variables into global state */
19397447ea4SJohn-Mark Gurney 	for (i = 0; i < 8; i++)
19497447ea4SJohn-Mark Gurney 		state[i] += S[i];
19597447ea4SJohn-Mark Gurney }
19697447ea4SJohn-Mark Gurney 
197*69d8dc20SAndrew Turner #if defined(ARM64_SHA2)
198*69d8dc20SAndrew Turner static void
199*69d8dc20SAndrew Turner SHA256_Transform_arm64(uint32_t * state, const unsigned char block[64])
200*69d8dc20SAndrew Turner {
201*69d8dc20SAndrew Turner 	SHA256_Transform_arm64_impl(state, block, K);
202*69d8dc20SAndrew Turner }
203*69d8dc20SAndrew Turner 
204*69d8dc20SAndrew Turner DEFINE_UIFUNC(static, void, SHA256_Transform,
205*69d8dc20SAndrew Turner     (uint32_t * state, const unsigned char block[64]))
206*69d8dc20SAndrew Turner {
207*69d8dc20SAndrew Turner 	u_long hwcap;
208*69d8dc20SAndrew Turner 
209*69d8dc20SAndrew Turner 	if (elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)) == 0) {
210*69d8dc20SAndrew Turner 		if ((hwcap & HWCAP_SHA2) != 0)
211*69d8dc20SAndrew Turner 			return (SHA256_Transform_arm64);
212*69d8dc20SAndrew Turner 	}
213*69d8dc20SAndrew Turner 
214*69d8dc20SAndrew Turner 	return (SHA256_Transform_c);
215*69d8dc20SAndrew Turner }
216*69d8dc20SAndrew Turner #else
217*69d8dc20SAndrew Turner static void
218*69d8dc20SAndrew Turner SHA256_Transform(uint32_t * state, const unsigned char block[64])
219*69d8dc20SAndrew Turner {
220*69d8dc20SAndrew Turner 	SHA256_Transform_c(state, block);
221*69d8dc20SAndrew Turner }
222*69d8dc20SAndrew Turner #endif
223*69d8dc20SAndrew Turner 
22497447ea4SJohn-Mark Gurney static unsigned char PAD[64] = {
22597447ea4SJohn-Mark Gurney 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22697447ea4SJohn-Mark Gurney 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22797447ea4SJohn-Mark Gurney 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22897447ea4SJohn-Mark Gurney 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
22997447ea4SJohn-Mark Gurney };
23097447ea4SJohn-Mark Gurney 
23197447ea4SJohn-Mark Gurney /* Add padding and terminating bit-count. */
23297447ea4SJohn-Mark Gurney static void
23397447ea4SJohn-Mark Gurney SHA256_Pad(SHA256_CTX * ctx)
23497447ea4SJohn-Mark Gurney {
235696c3895SColin Percival 	size_t r;
23697447ea4SJohn-Mark Gurney 
237696c3895SColin Percival 	/* Figure out how many bytes we have buffered. */
23897447ea4SJohn-Mark Gurney 	r = (ctx->count >> 3) & 0x3f;
23997447ea4SJohn-Mark Gurney 
240696c3895SColin Percival 	/* Pad to 56 mod 64, transforming if we finish a block en route. */
241696c3895SColin Percival 	if (r < 56) {
242696c3895SColin Percival 		/* Pad to 56 mod 64. */
243696c3895SColin Percival 		memcpy(&ctx->buf[r], PAD, 56 - r);
244696c3895SColin Percival 	} else {
245696c3895SColin Percival 		/* Finish the current block and mix. */
246696c3895SColin Percival 		memcpy(&ctx->buf[r], PAD, 64 - r);
247696c3895SColin Percival 		SHA256_Transform(ctx->state, ctx->buf);
248696c3895SColin Percival 
249696c3895SColin Percival 		/* The start of the final block is all zeroes. */
250696c3895SColin Percival 		memset(&ctx->buf[0], 0, 56);
251696c3895SColin Percival 	}
252696c3895SColin Percival 
253696c3895SColin Percival 	/* Add the terminating bit-count. */
254696c3895SColin Percival 	be64enc(&ctx->buf[56], ctx->count);
255696c3895SColin Percival 
256696c3895SColin Percival 	/* Mix in the final block. */
257696c3895SColin Percival 	SHA256_Transform(ctx->state, ctx->buf);
25897447ea4SJohn-Mark Gurney }
25997447ea4SJohn-Mark Gurney 
26097447ea4SJohn-Mark Gurney /* SHA-256 initialization.  Begins a SHA-256 operation. */
26197447ea4SJohn-Mark Gurney void
26297447ea4SJohn-Mark Gurney SHA256_Init(SHA256_CTX * ctx)
26397447ea4SJohn-Mark Gurney {
26497447ea4SJohn-Mark Gurney 
26597447ea4SJohn-Mark Gurney 	/* Zero bits processed so far */
26697447ea4SJohn-Mark Gurney 	ctx->count = 0;
26797447ea4SJohn-Mark Gurney 
26897447ea4SJohn-Mark Gurney 	/* Magic initialization constants */
26997447ea4SJohn-Mark Gurney 	ctx->state[0] = 0x6A09E667;
27097447ea4SJohn-Mark Gurney 	ctx->state[1] = 0xBB67AE85;
27197447ea4SJohn-Mark Gurney 	ctx->state[2] = 0x3C6EF372;
27297447ea4SJohn-Mark Gurney 	ctx->state[3] = 0xA54FF53A;
27397447ea4SJohn-Mark Gurney 	ctx->state[4] = 0x510E527F;
27497447ea4SJohn-Mark Gurney 	ctx->state[5] = 0x9B05688C;
27597447ea4SJohn-Mark Gurney 	ctx->state[6] = 0x1F83D9AB;
27697447ea4SJohn-Mark Gurney 	ctx->state[7] = 0x5BE0CD19;
27797447ea4SJohn-Mark Gurney }
27897447ea4SJohn-Mark Gurney 
27997447ea4SJohn-Mark Gurney /* Add bytes into the hash */
28097447ea4SJohn-Mark Gurney void
28197447ea4SJohn-Mark Gurney SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len)
28297447ea4SJohn-Mark Gurney {
28397447ea4SJohn-Mark Gurney 	uint64_t bitlen;
28497447ea4SJohn-Mark Gurney 	uint32_t r;
28597447ea4SJohn-Mark Gurney 	const unsigned char *src = in;
28697447ea4SJohn-Mark Gurney 
28797447ea4SJohn-Mark Gurney 	/* Number of bytes left in the buffer from previous updates */
28897447ea4SJohn-Mark Gurney 	r = (ctx->count >> 3) & 0x3f;
28997447ea4SJohn-Mark Gurney 
29097447ea4SJohn-Mark Gurney 	/* Convert the length into a number of bits */
29197447ea4SJohn-Mark Gurney 	bitlen = len << 3;
29297447ea4SJohn-Mark Gurney 
29397447ea4SJohn-Mark Gurney 	/* Update number of bits */
29497447ea4SJohn-Mark Gurney 	ctx->count += bitlen;
29597447ea4SJohn-Mark Gurney 
29697447ea4SJohn-Mark Gurney 	/* Handle the case where we don't need to perform any transforms */
29797447ea4SJohn-Mark Gurney 	if (len < 64 - r) {
29897447ea4SJohn-Mark Gurney 		memcpy(&ctx->buf[r], src, len);
29997447ea4SJohn-Mark Gurney 		return;
30097447ea4SJohn-Mark Gurney 	}
30197447ea4SJohn-Mark Gurney 
30297447ea4SJohn-Mark Gurney 	/* Finish the current block */
30397447ea4SJohn-Mark Gurney 	memcpy(&ctx->buf[r], src, 64 - r);
30497447ea4SJohn-Mark Gurney 	SHA256_Transform(ctx->state, ctx->buf);
30597447ea4SJohn-Mark Gurney 	src += 64 - r;
30697447ea4SJohn-Mark Gurney 	len -= 64 - r;
30797447ea4SJohn-Mark Gurney 
30897447ea4SJohn-Mark Gurney 	/* Perform complete blocks */
30997447ea4SJohn-Mark Gurney 	while (len >= 64) {
31097447ea4SJohn-Mark Gurney 		SHA256_Transform(ctx->state, src);
31197447ea4SJohn-Mark Gurney 		src += 64;
31297447ea4SJohn-Mark Gurney 		len -= 64;
31397447ea4SJohn-Mark Gurney 	}
31497447ea4SJohn-Mark Gurney 
31597447ea4SJohn-Mark Gurney 	/* Copy left over data into buffer */
31697447ea4SJohn-Mark Gurney 	memcpy(ctx->buf, src, len);
31797447ea4SJohn-Mark Gurney }
31897447ea4SJohn-Mark Gurney 
31997447ea4SJohn-Mark Gurney /*
32097447ea4SJohn-Mark Gurney  * SHA-256 finalization.  Pads the input data, exports the hash value,
32197447ea4SJohn-Mark Gurney  * and clears the context state.
32297447ea4SJohn-Mark Gurney  */
32397447ea4SJohn-Mark Gurney void
324571ebf76SConrad Meyer SHA256_Final(unsigned char digest[static SHA256_DIGEST_LENGTH], SHA256_CTX *ctx)
32597447ea4SJohn-Mark Gurney {
32697447ea4SJohn-Mark Gurney 
32797447ea4SJohn-Mark Gurney 	/* Add padding */
32897447ea4SJohn-Mark Gurney 	SHA256_Pad(ctx);
32997447ea4SJohn-Mark Gurney 
33097447ea4SJohn-Mark Gurney 	/* Write the hash */
331571ebf76SConrad Meyer 	be32enc_vect(digest, ctx->state, SHA256_DIGEST_LENGTH);
33297447ea4SJohn-Mark Gurney 
33397447ea4SJohn-Mark Gurney 	/* Clear the context state */
33466bdf50fSXin LI 	explicit_bzero(ctx, sizeof(*ctx));
33597447ea4SJohn-Mark Gurney }
3362ff9c4f9SJohn-Mark Gurney 
3371245c6d1SConrad Meyer /*** SHA-224: *********************************************************/
3381245c6d1SConrad Meyer /*
3391245c6d1SConrad Meyer  * the SHA224 and SHA256 transforms are identical
3401245c6d1SConrad Meyer  */
3411245c6d1SConrad Meyer 
3421245c6d1SConrad Meyer /* SHA-224 initialization.  Begins a SHA-224 operation. */
3431245c6d1SConrad Meyer void
3441245c6d1SConrad Meyer SHA224_Init(SHA224_CTX * ctx)
3451245c6d1SConrad Meyer {
3461245c6d1SConrad Meyer 
3471245c6d1SConrad Meyer 	/* Zero bits processed so far */
3481245c6d1SConrad Meyer 	ctx->count = 0;
3491245c6d1SConrad Meyer 
3501245c6d1SConrad Meyer 	/* Magic initialization constants */
3511245c6d1SConrad Meyer 	ctx->state[0] = 0xC1059ED8;
3521245c6d1SConrad Meyer 	ctx->state[1] = 0x367CD507;
3531245c6d1SConrad Meyer 	ctx->state[2] = 0x3070DD17;
3541245c6d1SConrad Meyer 	ctx->state[3] = 0xF70E5939;
3551245c6d1SConrad Meyer 	ctx->state[4] = 0xFFC00B31;
3561245c6d1SConrad Meyer 	ctx->state[5] = 0x68581511;
3571245c6d1SConrad Meyer 	ctx->state[6] = 0x64f98FA7;
3581245c6d1SConrad Meyer 	ctx->state[7] = 0xBEFA4FA4;
3591245c6d1SConrad Meyer }
3601245c6d1SConrad Meyer 
3611245c6d1SConrad Meyer /* Add bytes into the SHA-224 hash */
3621245c6d1SConrad Meyer void
3631245c6d1SConrad Meyer SHA224_Update(SHA224_CTX * ctx, const void *in, size_t len)
3641245c6d1SConrad Meyer {
3651245c6d1SConrad Meyer 
3661245c6d1SConrad Meyer 	SHA256_Update((SHA256_CTX *)ctx, in, len);
3671245c6d1SConrad Meyer }
3681245c6d1SConrad Meyer 
3691245c6d1SConrad Meyer /*
3701245c6d1SConrad Meyer  * SHA-224 finalization.  Pads the input data, exports the hash value,
3711245c6d1SConrad Meyer  * and clears the context state.
3721245c6d1SConrad Meyer  */
3731245c6d1SConrad Meyer void
3741245c6d1SConrad Meyer SHA224_Final(unsigned char digest[static SHA224_DIGEST_LENGTH], SHA224_CTX *ctx)
3751245c6d1SConrad Meyer {
3761245c6d1SConrad Meyer 
3771245c6d1SConrad Meyer 	/* Add padding */
3781245c6d1SConrad Meyer 	SHA256_Pad((SHA256_CTX *)ctx);
3791245c6d1SConrad Meyer 
3801245c6d1SConrad Meyer 	/* Write the hash */
3811245c6d1SConrad Meyer 	be32enc_vect(digest, ctx->state, SHA224_DIGEST_LENGTH);
3821245c6d1SConrad Meyer 
3831245c6d1SConrad Meyer 	/* Clear the context state */
3841245c6d1SConrad Meyer 	explicit_bzero(ctx, sizeof(*ctx));
3851245c6d1SConrad Meyer }
3861245c6d1SConrad Meyer 
3872ff9c4f9SJohn-Mark Gurney #ifdef WEAK_REFS
3882ff9c4f9SJohn-Mark Gurney /* When building libmd, provide weak references. Note: this is not
3892ff9c4f9SJohn-Mark Gurney    activated in the context of compiling these sources for internal
3902ff9c4f9SJohn-Mark Gurney    use in libcrypt.
3912ff9c4f9SJohn-Mark Gurney  */
3922ff9c4f9SJohn-Mark Gurney #undef SHA256_Init
3932ff9c4f9SJohn-Mark Gurney __weak_reference(_libmd_SHA256_Init, SHA256_Init);
3942ff9c4f9SJohn-Mark Gurney #undef SHA256_Update
3952ff9c4f9SJohn-Mark Gurney __weak_reference(_libmd_SHA256_Update, SHA256_Update);
3962ff9c4f9SJohn-Mark Gurney #undef SHA256_Final
3972ff9c4f9SJohn-Mark Gurney __weak_reference(_libmd_SHA256_Final, SHA256_Final);
3982ff9c4f9SJohn-Mark Gurney #undef SHA256_Transform
3992ff9c4f9SJohn-Mark Gurney __weak_reference(_libmd_SHA256_Transform, SHA256_Transform);
4001245c6d1SConrad Meyer 
4011245c6d1SConrad Meyer #undef SHA224_Init
4021245c6d1SConrad Meyer __weak_reference(_libmd_SHA224_Init, SHA224_Init);
4031245c6d1SConrad Meyer #undef SHA224_Update
4041245c6d1SConrad Meyer __weak_reference(_libmd_SHA224_Update, SHA224_Update);
4051245c6d1SConrad Meyer #undef SHA224_Final
4061245c6d1SConrad Meyer __weak_reference(_libmd_SHA224_Final, SHA224_Final);
4072ff9c4f9SJohn-Mark Gurney #endif
408