1258945Sroberto/*
2280849Scy * Copyright (C) 2005-2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
3258945Sroberto *
4258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any
5258945Sroberto * purpose with or without fee is hereby granted, provided that the above
6258945Sroberto * copyright notice and this permission notice appear in all copies.
7258945Sroberto *
8258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10258945Sroberto * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14258945Sroberto * PERFORMANCE OF THIS SOFTWARE.
15258945Sroberto */
16258945Sroberto
17280849Scy/* $Id$ */
18258945Sroberto
19280849Scy/*	$FreeBSD:  258945 2013-12-04 21:33:17Z roberto $	*/
20258945Sroberto/*	$KAME: sha2.c,v 1.8 2001/11/08 01:07:52 itojun Exp $	*/
21258945Sroberto
22258945Sroberto/*
23258945Sroberto * sha2.c
24258945Sroberto *
25258945Sroberto * Version 1.0.0beta1
26258945Sroberto *
27258945Sroberto * Written by Aaron D. Gifford <me@aarongifford.com>
28258945Sroberto *
29258945Sroberto * Copyright 2000 Aaron D. Gifford.  All rights reserved.
30258945Sroberto *
31258945Sroberto * Redistribution and use in source and binary forms, with or without
32258945Sroberto * modification, are permitted provided that the following conditions
33258945Sroberto * are met:
34258945Sroberto * 1. Redistributions of source code must retain the above copyright
35258945Sroberto *    notice, this list of conditions and the following disclaimer.
36258945Sroberto * 2. Redistributions in binary form must reproduce the above copyright
37258945Sroberto *    notice, this list of conditions and the following disclaimer in the
38258945Sroberto *    documentation and/or other materials provided with the distribution.
39258945Sroberto * 3. Neither the name of the copyright holder nor the names of contributors
40258945Sroberto *    may be used to endorse or promote products derived from this software
41258945Sroberto *    without specific prior written permission.
42258945Sroberto *
43258945Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
44258945Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45258945Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46258945Sroberto * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
47258945Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48258945Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49258945Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50258945Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51258945Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52258945Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53258945Sroberto * SUCH DAMAGE.
54258945Sroberto *
55258945Sroberto */
56258945Sroberto
57258945Sroberto
58258945Sroberto#include <config.h>
59258945Sroberto
60258945Sroberto#include <isc/assertions.h>
61280849Scy#include <isc/platform.h>
62258945Sroberto#include <isc/sha2.h>
63258945Sroberto#include <isc/string.h>
64258945Sroberto#include <isc/util.h>
65258945Sroberto
66280849Scy#ifdef ISC_PLATFORM_OPENSSLHASH
67280849Scy
68280849Scyvoid
69280849Scyisc_sha224_init(isc_sha224_t *context) {
70280849Scy	if (context == (isc_sha224_t *)0) {
71280849Scy		return;
72280849Scy	}
73280849Scy	EVP_DigestInit(context, EVP_sha224());
74280849Scy}
75280849Scy
76280849Scyvoid
77280849Scyisc_sha224_invalidate(isc_sha224_t *context) {
78280849Scy	EVP_MD_CTX_cleanup(context);
79280849Scy}
80280849Scy
81280849Scyvoid
82280849Scyisc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) {
83280849Scy	if (len == 0U) {
84280849Scy		/* Calling with no data is valid - we do nothing */
85280849Scy		return;
86280849Scy	}
87280849Scy
88280849Scy	/* Sanity check: */
89280849Scy	REQUIRE(context != (isc_sha224_t *)0 && data != (isc_uint8_t*)0);
90280849Scy
91280849Scy	EVP_DigestUpdate(context, (const void *) data, len);
92280849Scy}
93280849Scy
94280849Scyvoid
95280849Scyisc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) {
96280849Scy	/* Sanity check: */
97280849Scy	REQUIRE(context != (isc_sha224_t *)0);
98280849Scy
99280849Scy	/* If no digest buffer is passed, we don't bother doing this: */
100280849Scy	if (digest != (isc_uint8_t*)0) {
101280849Scy		EVP_DigestFinal(context, digest, NULL);
102280849Scy	} else {
103280849Scy		EVP_MD_CTX_cleanup(context);
104280849Scy	}
105280849Scy}
106280849Scy
107280849Scyvoid
108280849Scyisc_sha256_init(isc_sha256_t *context) {
109280849Scy	if (context == (isc_sha256_t *)0) {
110280849Scy		return;
111280849Scy	}
112280849Scy	EVP_DigestInit(context, EVP_sha256());
113280849Scy}
114280849Scy
115280849Scyvoid
116280849Scyisc_sha256_invalidate(isc_sha256_t *context) {
117280849Scy	EVP_MD_CTX_cleanup(context);
118280849Scy}
119280849Scy
120280849Scyvoid
121280849Scyisc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) {
122280849Scy	if (len == 0U) {
123280849Scy		/* Calling with no data is valid - we do nothing */
124280849Scy		return;
125280849Scy	}
126280849Scy
127280849Scy	/* Sanity check: */
128280849Scy	REQUIRE(context != (isc_sha256_t *)0 && data != (isc_uint8_t*)0);
129280849Scy
130280849Scy	EVP_DigestUpdate(context, (const void *) data, len);
131280849Scy}
132280849Scy
133280849Scyvoid
134280849Scyisc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
135280849Scy	/* Sanity check: */
136280849Scy	REQUIRE(context != (isc_sha256_t *)0);
137280849Scy
138280849Scy	/* If no digest buffer is passed, we don't bother doing this: */
139280849Scy	if (digest != (isc_uint8_t*)0) {
140280849Scy		EVP_DigestFinal(context, digest, NULL);
141280849Scy	} else {
142280849Scy		EVP_MD_CTX_cleanup(context);
143280849Scy	}
144280849Scy}
145280849Scy
146280849Scyvoid
147280849Scyisc_sha512_init(isc_sha512_t *context) {
148280849Scy	if (context == (isc_sha512_t *)0) {
149280849Scy		return;
150280849Scy	}
151280849Scy	EVP_DigestInit(context, EVP_sha512());
152280849Scy}
153280849Scy
154280849Scyvoid
155280849Scyisc_sha512_invalidate(isc_sha512_t *context) {
156280849Scy	EVP_MD_CTX_cleanup(context);
157280849Scy}
158280849Scy
159280849Scyvoid isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) {
160280849Scy	if (len == 0U) {
161280849Scy		/* Calling with no data is valid - we do nothing */
162280849Scy		return;
163280849Scy	}
164280849Scy
165280849Scy	/* Sanity check: */
166280849Scy	REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
167280849Scy
168280849Scy	EVP_DigestUpdate(context, (const void *) data, len);
169280849Scy}
170280849Scy
171280849Scyvoid isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
172280849Scy	/* Sanity check: */
173280849Scy	REQUIRE(context != (isc_sha512_t *)0);
174280849Scy
175280849Scy	/* If no digest buffer is passed, we don't bother doing this: */
176280849Scy	if (digest != (isc_uint8_t*)0) {
177280849Scy		EVP_DigestFinal(context, digest, NULL);
178280849Scy	} else {
179280849Scy		EVP_MD_CTX_cleanup(context);
180280849Scy	}
181280849Scy}
182280849Scy
183280849Scyvoid
184280849Scyisc_sha384_init(isc_sha384_t *context) {
185280849Scy	if (context == (isc_sha384_t *)0) {
186280849Scy		return;
187280849Scy	}
188280849Scy	EVP_DigestInit(context, EVP_sha384());
189280849Scy}
190280849Scy
191280849Scyvoid
192280849Scyisc_sha384_invalidate(isc_sha384_t *context) {
193280849Scy	EVP_MD_CTX_cleanup(context);
194280849Scy}
195280849Scy
196280849Scyvoid
197280849Scyisc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) {
198280849Scy	if (len == 0U) {
199280849Scy		/* Calling with no data is valid - we do nothing */
200280849Scy		return;
201280849Scy	}
202280849Scy
203280849Scy	/* Sanity check: */
204280849Scy	REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
205280849Scy
206280849Scy	EVP_DigestUpdate(context, (const void *) data, len);
207280849Scy}
208280849Scy
209280849Scyvoid
210280849Scyisc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
211280849Scy	/* Sanity check: */
212280849Scy	REQUIRE(context != (isc_sha384_t *)0);
213280849Scy
214280849Scy	/* If no digest buffer is passed, we don't bother doing this: */
215280849Scy	if (digest != (isc_uint8_t*)0) {
216280849Scy		EVP_DigestFinal(context, digest, NULL);
217280849Scy	} else {
218280849Scy		EVP_MD_CTX_cleanup(context);
219280849Scy	}
220280849Scy}
221280849Scy
222280849Scy#else
223280849Scy
224258945Sroberto/*
225258945Sroberto * UNROLLED TRANSFORM LOOP NOTE:
226258945Sroberto * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
227258945Sroberto * loop version for the hash transform rounds (defined using macros
228258945Sroberto * later in this file).  Either define on the command line, for example:
229258945Sroberto *
230258945Sroberto *   cc -DISC_SHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
231258945Sroberto *
232258945Sroberto * or define below:
233258945Sroberto *
234258945Sroberto *   \#define ISC_SHA2_UNROLL_TRANSFORM
235258945Sroberto *
236258945Sroberto */
237258945Sroberto
238258945Sroberto/*** SHA-256/384/512 Machine Architecture Definitions *****************/
239258945Sroberto/*
240258945Sroberto * BYTE_ORDER NOTE:
241258945Sroberto *
242258945Sroberto * Please make sure that your system defines BYTE_ORDER.  If your
243258945Sroberto * architecture is little-endian, make sure it also defines
244258945Sroberto * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
245258945Sroberto * equivalent.
246258945Sroberto *
247258945Sroberto * If your system does not define the above, then you can do so by
248258945Sroberto * hand like this:
249258945Sroberto *
250258945Sroberto *   \#define LITTLE_ENDIAN 1234
251258945Sroberto *   \#define BIG_ENDIAN    4321
252258945Sroberto *
253258945Sroberto * And for little-endian machines, add:
254258945Sroberto *
255258945Sroberto *   \#define BYTE_ORDER LITTLE_ENDIAN
256258945Sroberto *
257258945Sroberto * Or for big-endian machines:
258258945Sroberto *
259258945Sroberto *   \#define BYTE_ORDER BIG_ENDIAN
260258945Sroberto *
261258945Sroberto * The FreeBSD machine this was written on defines BYTE_ORDER
262258945Sroberto * appropriately by including <sys/types.h> (which in turn includes
263258945Sroberto * <machine/endian.h> where the appropriate definitions are actually
264258945Sroberto * made).
265258945Sroberto */
266258945Sroberto#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
267258945Sroberto#ifndef BYTE_ORDER
268258945Sroberto#ifndef BIG_ENDIAN
269258945Sroberto#define BIG_ENDIAN 4321
270258945Sroberto#endif
271258945Sroberto#ifndef LITTLE_ENDIAN
272258945Sroberto#define LITTLE_ENDIAN 1234
273258945Sroberto#endif
274258945Sroberto#ifdef WORDS_BIGENDIAN
275258945Sroberto#define BYTE_ORDER BIG_ENDIAN
276258945Sroberto#else
277258945Sroberto#define BYTE_ORDER LITTLE_ENDIAN
278258945Sroberto#endif
279258945Sroberto#else
280258945Sroberto#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
281258945Sroberto#endif
282258945Sroberto#endif
283258945Sroberto
284258945Sroberto/*** SHA-256/384/512 Various Length Definitions ***********************/
285258945Sroberto/* NOTE: Most of these are in sha2.h */
286258945Sroberto#define ISC_SHA256_SHORT_BLOCK_LENGTH	(ISC_SHA256_BLOCK_LENGTH - 8)
287258945Sroberto#define ISC_SHA384_SHORT_BLOCK_LENGTH	(ISC_SHA384_BLOCK_LENGTH - 16)
288258945Sroberto#define ISC_SHA512_SHORT_BLOCK_LENGTH	(ISC_SHA512_BLOCK_LENGTH - 16)
289258945Sroberto
290258945Sroberto
291258945Sroberto/*** ENDIAN REVERSAL MACROS *******************************************/
292258945Sroberto#if BYTE_ORDER == LITTLE_ENDIAN
293258945Sroberto#define REVERSE32(w,x)	{ \
294258945Sroberto	isc_uint32_t tmp = (w); \
295258945Sroberto	tmp = (tmp >> 16) | (tmp << 16); \
296258945Sroberto	(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
297258945Sroberto}
298258945Sroberto#ifdef WIN32
299258945Sroberto#define REVERSE64(w,x)	{ \
300258945Sroberto	isc_uint64_t tmp = (w); \
301258945Sroberto	tmp = (tmp >> 32) | (tmp << 32); \
302258945Sroberto	tmp = ((tmp & 0xff00ff00ff00ff00UL) >> 8) | \
303258945Sroberto	      ((tmp & 0x00ff00ff00ff00ffUL) << 8); \
304258945Sroberto	(x) = ((tmp & 0xffff0000ffff0000UL) >> 16) | \
305258945Sroberto	      ((tmp & 0x0000ffff0000ffffUL) << 16); \
306258945Sroberto}
307258945Sroberto#else
308258945Sroberto#define REVERSE64(w,x)	{ \
309258945Sroberto	isc_uint64_t tmp = (w); \
310258945Sroberto	tmp = (tmp >> 32) | (tmp << 32); \
311258945Sroberto	tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
312258945Sroberto	      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
313258945Sroberto	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
314258945Sroberto	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
315258945Sroberto}
316258945Sroberto#endif
317258945Sroberto#endif /* BYTE_ORDER == LITTLE_ENDIAN */
318258945Sroberto
319258945Sroberto/*
320258945Sroberto * Macro for incrementally adding the unsigned 64-bit integer n to the
321258945Sroberto * unsigned 128-bit integer (represented using a two-element array of
322258945Sroberto * 64-bit words):
323258945Sroberto */
324258945Sroberto#define ADDINC128(w,n)	{ \
325258945Sroberto	(w)[0] += (isc_uint64_t)(n); \
326258945Sroberto	if ((w)[0] < (n)) { \
327258945Sroberto		(w)[1]++; \
328258945Sroberto	} \
329258945Sroberto}
330258945Sroberto
331258945Sroberto/*** THE SIX LOGICAL FUNCTIONS ****************************************/
332258945Sroberto/*
333258945Sroberto * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
334258945Sroberto *
335258945Sroberto *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
336258945Sroberto *   S is a ROTATION) because the SHA-256/384/512 description document
337258945Sroberto *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
338258945Sroberto *   same "backwards" definition.
339258945Sroberto */
340258945Sroberto/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
341258945Sroberto#define R(b,x) 		((x) >> (b))
342258945Sroberto/* 32-bit Rotate-right (used in SHA-256): */
343258945Sroberto#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
344258945Sroberto/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
345258945Sroberto#define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
346258945Sroberto
347258945Sroberto/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
348258945Sroberto#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
349258945Sroberto#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
350258945Sroberto
351258945Sroberto/* Four of six logical functions used in SHA-256: */
352258945Sroberto#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
353258945Sroberto#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
354258945Sroberto#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
355258945Sroberto#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
356258945Sroberto
357258945Sroberto/* Four of six logical functions used in SHA-384 and SHA-512: */
358258945Sroberto#define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
359258945Sroberto#define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
360258945Sroberto#define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
361258945Sroberto#define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
362258945Sroberto
363258945Sroberto/*** INTERNAL FUNCTION PROTOTYPES *************************************/
364258945Sroberto/* NOTE: These should not be accessed directly from outside this
365258945Sroberto * library -- they are intended for private internal visibility/use
366258945Sroberto * only.
367258945Sroberto */
368258945Srobertovoid isc_sha512_last(isc_sha512_t *);
369258945Srobertovoid isc_sha256_transform(isc_sha256_t *, const isc_uint32_t*);
370258945Srobertovoid isc_sha512_transform(isc_sha512_t *, const isc_uint64_t*);
371258945Sroberto
372258945Sroberto
373258945Sroberto/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
374258945Sroberto/* Hash constant words K for SHA-224 and SHA-256: */
375258945Srobertostatic const isc_uint32_t K256[64] = {
376258945Sroberto	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
377258945Sroberto	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
378258945Sroberto	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
379258945Sroberto	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
380258945Sroberto	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
381258945Sroberto	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
382258945Sroberto	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
383258945Sroberto	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
384258945Sroberto	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
385258945Sroberto	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
386258945Sroberto	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
387258945Sroberto	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
388258945Sroberto	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
389258945Sroberto	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
390258945Sroberto	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
391258945Sroberto	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
392258945Sroberto};
393258945Sroberto
394258945Sroberto/* Initial hash value H for SHA-224: */
395258945Srobertostatic const isc_uint32_t sha224_initial_hash_value[8] = {
396258945Sroberto	0xc1059ed8UL,
397258945Sroberto	0x367cd507UL,
398258945Sroberto	0x3070dd17UL,
399258945Sroberto	0xf70e5939UL,
400258945Sroberto	0xffc00b31UL,
401258945Sroberto	0x68581511UL,
402258945Sroberto	0x64f98fa7UL,
403258945Sroberto	0xbefa4fa4UL
404258945Sroberto};
405258945Sroberto
406258945Sroberto/* Initial hash value H for SHA-256: */
407258945Srobertostatic const isc_uint32_t sha256_initial_hash_value[8] = {
408258945Sroberto	0x6a09e667UL,
409258945Sroberto	0xbb67ae85UL,
410258945Sroberto	0x3c6ef372UL,
411258945Sroberto	0xa54ff53aUL,
412258945Sroberto	0x510e527fUL,
413258945Sroberto	0x9b05688cUL,
414258945Sroberto	0x1f83d9abUL,
415258945Sroberto	0x5be0cd19UL
416258945Sroberto};
417258945Sroberto
418258945Sroberto#ifdef WIN32
419258945Sroberto/* Hash constant words K for SHA-384 and SHA-512: */
420258945Srobertostatic const isc_uint64_t K512[80] = {
421258945Sroberto	0x428a2f98d728ae22UL, 0x7137449123ef65cdUL,
422258945Sroberto	0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
423258945Sroberto	0x3956c25bf348b538UL, 0x59f111f1b605d019UL,
424258945Sroberto	0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
425258945Sroberto	0xd807aa98a3030242UL, 0x12835b0145706fbeUL,
426258945Sroberto	0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
427258945Sroberto	0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL,
428258945Sroberto	0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
429258945Sroberto	0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL,
430258945Sroberto	0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
431258945Sroberto	0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL,
432258945Sroberto	0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
433258945Sroberto	0x983e5152ee66dfabUL, 0xa831c66d2db43210UL,
434258945Sroberto	0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
435258945Sroberto	0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL,
436258945Sroberto	0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
437258945Sroberto	0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL,
438258945Sroberto	0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
439258945Sroberto	0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL,
440258945Sroberto	0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
441258945Sroberto	0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL,
442258945Sroberto	0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
443258945Sroberto	0xd192e819d6ef5218UL, 0xd69906245565a910UL,
444258945Sroberto	0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
445258945Sroberto	0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL,
446258945Sroberto	0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
447258945Sroberto	0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL,
448258945Sroberto	0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
449258945Sroberto	0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL,
450258945Sroberto	0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
451258945Sroberto	0x90befffa23631e28UL, 0xa4506cebde82bde9UL,
452258945Sroberto	0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
453258945Sroberto	0xca273eceea26619cUL, 0xd186b8c721c0c207UL,
454258945Sroberto	0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
455258945Sroberto	0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL,
456258945Sroberto	0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
457258945Sroberto	0x28db77f523047d84UL, 0x32caab7b40c72493UL,
458258945Sroberto	0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
459258945Sroberto	0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL,
460258945Sroberto	0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL
461258945Sroberto};
462258945Sroberto
463258945Sroberto/* Initial hash value H for SHA-384: */
464258945Srobertostatic const isc_uint64_t sha384_initial_hash_value[8] = {
465258945Sroberto	0xcbbb9d5dc1059ed8UL,
466258945Sroberto	0x629a292a367cd507UL,
467258945Sroberto	0x9159015a3070dd17UL,
468258945Sroberto	0x152fecd8f70e5939UL,
469258945Sroberto	0x67332667ffc00b31UL,
470258945Sroberto	0x8eb44a8768581511UL,
471258945Sroberto	0xdb0c2e0d64f98fa7UL,
472258945Sroberto	0x47b5481dbefa4fa4UL
473258945Sroberto};
474258945Sroberto
475258945Sroberto/* Initial hash value H for SHA-512: */
476258945Srobertostatic const isc_uint64_t sha512_initial_hash_value[8] = {
477258945Sroberto	0x6a09e667f3bcc908U,
478258945Sroberto	0xbb67ae8584caa73bUL,
479258945Sroberto	0x3c6ef372fe94f82bUL,
480258945Sroberto	0xa54ff53a5f1d36f1UL,
481258945Sroberto	0x510e527fade682d1UL,
482258945Sroberto	0x9b05688c2b3e6c1fUL,
483258945Sroberto	0x1f83d9abfb41bd6bUL,
484258945Sroberto	0x5be0cd19137e2179UL
485258945Sroberto};
486258945Sroberto#else
487258945Sroberto/* Hash constant words K for SHA-384 and SHA-512: */
488258945Srobertostatic const isc_uint64_t K512[80] = {
489258945Sroberto	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
490258945Sroberto	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
491258945Sroberto	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
492258945Sroberto	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
493258945Sroberto	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
494258945Sroberto	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
495258945Sroberto	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
496258945Sroberto	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
497258945Sroberto	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
498258945Sroberto	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
499258945Sroberto	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
500258945Sroberto	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
501258945Sroberto	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
502258945Sroberto	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
503258945Sroberto	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
504258945Sroberto	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
505258945Sroberto	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
506258945Sroberto	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
507258945Sroberto	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
508258945Sroberto	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
509258945Sroberto	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
510258945Sroberto	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
511258945Sroberto	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
512258945Sroberto	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
513258945Sroberto	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
514258945Sroberto	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
515258945Sroberto	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
516258945Sroberto	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
517258945Sroberto	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
518258945Sroberto	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
519258945Sroberto	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
520258945Sroberto	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
521258945Sroberto	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
522258945Sroberto	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
523258945Sroberto	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
524258945Sroberto	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
525258945Sroberto	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
526258945Sroberto	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
527258945Sroberto	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
528258945Sroberto	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
529258945Sroberto};
530258945Sroberto
531258945Sroberto/* Initial hash value H for SHA-384: */
532258945Srobertostatic const isc_uint64_t sha384_initial_hash_value[8] = {
533258945Sroberto	0xcbbb9d5dc1059ed8ULL,
534258945Sroberto	0x629a292a367cd507ULL,
535258945Sroberto	0x9159015a3070dd17ULL,
536258945Sroberto	0x152fecd8f70e5939ULL,
537258945Sroberto	0x67332667ffc00b31ULL,
538258945Sroberto	0x8eb44a8768581511ULL,
539258945Sroberto	0xdb0c2e0d64f98fa7ULL,
540258945Sroberto	0x47b5481dbefa4fa4ULL
541258945Sroberto};
542258945Sroberto
543258945Sroberto/* Initial hash value H for SHA-512: */
544258945Srobertostatic const isc_uint64_t sha512_initial_hash_value[8] = {
545258945Sroberto	0x6a09e667f3bcc908ULL,
546258945Sroberto	0xbb67ae8584caa73bULL,
547258945Sroberto	0x3c6ef372fe94f82bULL,
548258945Sroberto	0xa54ff53a5f1d36f1ULL,
549258945Sroberto	0x510e527fade682d1ULL,
550258945Sroberto	0x9b05688c2b3e6c1fULL,
551258945Sroberto	0x1f83d9abfb41bd6bULL,
552258945Sroberto	0x5be0cd19137e2179ULL
553258945Sroberto};
554258945Sroberto#endif
555258945Sroberto
556258945Sroberto
557258945Sroberto/*** SHA-224: *********************************************************/
558258945Srobertovoid
559258945Srobertoisc_sha224_init(isc_sha224_t *context) {
560258945Sroberto	if (context == (isc_sha256_t *)0) {
561258945Sroberto		return;
562258945Sroberto	}
563258945Sroberto	memcpy(context->state, sha224_initial_hash_value,
564258945Sroberto	       ISC_SHA256_DIGESTLENGTH);
565258945Sroberto	memset(context->buffer, 0, ISC_SHA256_BLOCK_LENGTH);
566258945Sroberto	context->bitcount = 0;
567258945Sroberto}
568258945Sroberto
569258945Srobertovoid
570280849Scyisc_sha224_invalidate(isc_sha224_t *context) {
571280849Scy	memset(context, 0, sizeof(isc_sha224_t));
572280849Scy}
573280849Scy
574280849Scyvoid
575258945Srobertoisc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) {
576258945Sroberto	isc_sha256_update((isc_sha256_t *)context, data, len);
577258945Sroberto}
578258945Sroberto
579258945Srobertovoid
580258945Srobertoisc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) {
581258945Sroberto	isc_uint8_t sha256_digest[ISC_SHA256_DIGESTLENGTH];
582258945Sroberto	isc_sha256_final(sha256_digest, (isc_sha256_t *)context);
583258945Sroberto	memcpy(digest, sha256_digest, ISC_SHA224_DIGESTLENGTH);
584258945Sroberto	memset(sha256_digest, 0, ISC_SHA256_DIGESTLENGTH);
585258945Sroberto}
586258945Sroberto
587258945Sroberto/*** SHA-256: *********************************************************/
588258945Srobertovoid
589258945Srobertoisc_sha256_init(isc_sha256_t *context) {
590258945Sroberto	if (context == (isc_sha256_t *)0) {
591258945Sroberto		return;
592258945Sroberto	}
593258945Sroberto	memcpy(context->state, sha256_initial_hash_value,
594258945Sroberto	       ISC_SHA256_DIGESTLENGTH);
595258945Sroberto	memset(context->buffer, 0, ISC_SHA256_BLOCK_LENGTH);
596258945Sroberto	context->bitcount = 0;
597258945Sroberto}
598258945Sroberto
599280849Scyvoid
600280849Scyisc_sha256_invalidate(isc_sha256_t *context) {
601280849Scy	memset(context, 0, sizeof(isc_sha256_t));
602280849Scy}
603280849Scy
604258945Sroberto#ifdef ISC_SHA2_UNROLL_TRANSFORM
605258945Sroberto
606258945Sroberto/* Unrolled SHA-256 round macros: */
607258945Sroberto
608258945Sroberto#if BYTE_ORDER == LITTLE_ENDIAN
609258945Sroberto
610258945Sroberto#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
611258945Sroberto	REVERSE32(*data++, W256[j]); \
612258945Sroberto	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
613258945Sroberto	     K256[j] + W256[j]; \
614258945Sroberto	(d) += T1; \
615258945Sroberto	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
616258945Sroberto	j++
617258945Sroberto
618258945Sroberto
619258945Sroberto#else /* BYTE_ORDER == LITTLE_ENDIAN */
620258945Sroberto
621258945Sroberto#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
622258945Sroberto	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
623258945Sroberto	     K256[j] + (W256[j] = *data++); \
624258945Sroberto	(d) += T1; \
625258945Sroberto	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
626258945Sroberto	j++
627258945Sroberto
628258945Sroberto#endif /* BYTE_ORDER == LITTLE_ENDIAN */
629258945Sroberto
630258945Sroberto#define ROUND256(a,b,c,d,e,f,g,h)	\
631258945Sroberto	s0 = W256[(j+1)&0x0f]; \
632258945Sroberto	s0 = sigma0_256(s0); \
633258945Sroberto	s1 = W256[(j+14)&0x0f]; \
634258945Sroberto	s1 = sigma1_256(s1); \
635258945Sroberto	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
636258945Sroberto	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
637258945Sroberto	(d) += T1; \
638258945Sroberto	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
639258945Sroberto	j++
640258945Sroberto
641258945Srobertovoid isc_sha256_transform(isc_sha256_t *context, const isc_uint32_t* data) {
642258945Sroberto	isc_uint32_t	a, b, c, d, e, f, g, h, s0, s1;
643258945Sroberto	isc_uint32_t	T1, *W256;
644258945Sroberto	int		j;
645258945Sroberto
646258945Sroberto	W256 = (isc_uint32_t*)context->buffer;
647258945Sroberto
648258945Sroberto	/* Initialize registers with the prev. intermediate value */
649258945Sroberto	a = context->state[0];
650258945Sroberto	b = context->state[1];
651258945Sroberto	c = context->state[2];
652258945Sroberto	d = context->state[3];
653258945Sroberto	e = context->state[4];
654258945Sroberto	f = context->state[5];
655258945Sroberto	g = context->state[6];
656258945Sroberto	h = context->state[7];
657258945Sroberto
658258945Sroberto	j = 0;
659258945Sroberto	do {
660258945Sroberto		/* Rounds 0 to 15 (unrolled): */
661258945Sroberto		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
662258945Sroberto		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
663258945Sroberto		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
664258945Sroberto		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
665258945Sroberto		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
666258945Sroberto		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
667258945Sroberto		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
668258945Sroberto		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
669258945Sroberto	} while (j < 16);
670258945Sroberto
671258945Sroberto	/* Now for the remaining rounds to 64: */
672258945Sroberto	do {
673258945Sroberto		ROUND256(a,b,c,d,e,f,g,h);
674258945Sroberto		ROUND256(h,a,b,c,d,e,f,g);
675258945Sroberto		ROUND256(g,h,a,b,c,d,e,f);
676258945Sroberto		ROUND256(f,g,h,a,b,c,d,e);
677258945Sroberto		ROUND256(e,f,g,h,a,b,c,d);
678258945Sroberto		ROUND256(d,e,f,g,h,a,b,c);
679258945Sroberto		ROUND256(c,d,e,f,g,h,a,b);
680258945Sroberto		ROUND256(b,c,d,e,f,g,h,a);
681258945Sroberto	} while (j < 64);
682258945Sroberto
683258945Sroberto	/* Compute the current intermediate hash value */
684258945Sroberto	context->state[0] += a;
685258945Sroberto	context->state[1] += b;
686258945Sroberto	context->state[2] += c;
687258945Sroberto	context->state[3] += d;
688258945Sroberto	context->state[4] += e;
689258945Sroberto	context->state[5] += f;
690258945Sroberto	context->state[6] += g;
691258945Sroberto	context->state[7] += h;
692258945Sroberto
693258945Sroberto	/* Clean up */
694258945Sroberto	a = b = c = d = e = f = g = h = T1 = 0;
695280849Scy	/* Avoid compiler warnings */
696280849Scy	POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
697280849Scy	POST(g); POST(h); POST(T1);
698258945Sroberto}
699258945Sroberto
700258945Sroberto#else /* ISC_SHA2_UNROLL_TRANSFORM */
701258945Sroberto
702258945Srobertovoid
703258945Srobertoisc_sha256_transform(isc_sha256_t *context, const isc_uint32_t* data) {
704258945Sroberto	isc_uint32_t	a, b, c, d, e, f, g, h, s0, s1;
705258945Sroberto	isc_uint32_t	T1, T2, *W256;
706258945Sroberto	int		j;
707258945Sroberto
708258945Sroberto	W256 = (isc_uint32_t*)context->buffer;
709258945Sroberto
710258945Sroberto	/* Initialize registers with the prev. intermediate value */
711258945Sroberto	a = context->state[0];
712258945Sroberto	b = context->state[1];
713258945Sroberto	c = context->state[2];
714258945Sroberto	d = context->state[3];
715258945Sroberto	e = context->state[4];
716258945Sroberto	f = context->state[5];
717258945Sroberto	g = context->state[6];
718258945Sroberto	h = context->state[7];
719258945Sroberto
720258945Sroberto	j = 0;
721258945Sroberto	do {
722258945Sroberto#if BYTE_ORDER == LITTLE_ENDIAN
723258945Sroberto		/* Copy data while converting to host byte order */
724258945Sroberto		REVERSE32(*data++,W256[j]);
725258945Sroberto		/* Apply the SHA-256 compression function to update a..h */
726258945Sroberto		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
727258945Sroberto#else /* BYTE_ORDER == LITTLE_ENDIAN */
728258945Sroberto		/* Apply the SHA-256 compression function to update a..h with copy */
729258945Sroberto		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
730258945Sroberto#endif /* BYTE_ORDER == LITTLE_ENDIAN */
731258945Sroberto		T2 = Sigma0_256(a) + Maj(a, b, c);
732258945Sroberto		h = g;
733258945Sroberto		g = f;
734258945Sroberto		f = e;
735258945Sroberto		e = d + T1;
736258945Sroberto		d = c;
737258945Sroberto		c = b;
738258945Sroberto		b = a;
739258945Sroberto		a = T1 + T2;
740258945Sroberto
741258945Sroberto		j++;
742258945Sroberto	} while (j < 16);
743258945Sroberto
744258945Sroberto	do {
745258945Sroberto		/* Part of the message block expansion: */
746258945Sroberto		s0 = W256[(j+1)&0x0f];
747258945Sroberto		s0 = sigma0_256(s0);
748258945Sroberto		s1 = W256[(j+14)&0x0f];
749258945Sroberto		s1 = sigma1_256(s1);
750258945Sroberto
751258945Sroberto		/* Apply the SHA-256 compression function to update a..h */
752258945Sroberto		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
753258945Sroberto		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
754258945Sroberto		T2 = Sigma0_256(a) + Maj(a, b, c);
755258945Sroberto		h = g;
756258945Sroberto		g = f;
757258945Sroberto		f = e;
758258945Sroberto		e = d + T1;
759258945Sroberto		d = c;
760258945Sroberto		c = b;
761258945Sroberto		b = a;
762258945Sroberto		a = T1 + T2;
763258945Sroberto
764258945Sroberto		j++;
765258945Sroberto	} while (j < 64);
766258945Sroberto
767258945Sroberto	/* Compute the current intermediate hash value */
768258945Sroberto	context->state[0] += a;
769258945Sroberto	context->state[1] += b;
770258945Sroberto	context->state[2] += c;
771258945Sroberto	context->state[3] += d;
772258945Sroberto	context->state[4] += e;
773258945Sroberto	context->state[5] += f;
774258945Sroberto	context->state[6] += g;
775258945Sroberto	context->state[7] += h;
776258945Sroberto
777258945Sroberto	/* Clean up */
778258945Sroberto	a = b = c = d = e = f = g = h = T1 = T2 = 0;
779280849Scy	/* Avoid compiler warnings */
780280849Scy	POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
781280849Scy	POST(g); POST(h); POST(T1); POST(T2);
782258945Sroberto}
783258945Sroberto
784258945Sroberto#endif /* ISC_SHA2_UNROLL_TRANSFORM */
785258945Sroberto
786258945Srobertovoid
787258945Srobertoisc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) {
788258945Sroberto	unsigned int	freespace, usedspace;
789258945Sroberto
790258945Sroberto	if (len == 0U) {
791258945Sroberto		/* Calling with no data is valid - we do nothing */
792258945Sroberto		return;
793258945Sroberto	}
794258945Sroberto
795258945Sroberto	/* Sanity check: */
796258945Sroberto	REQUIRE(context != (isc_sha256_t *)0 && data != (isc_uint8_t*)0);
797258945Sroberto
798258945Sroberto	usedspace = (unsigned int)((context->bitcount >> 3) %
799258945Sroberto				   ISC_SHA256_BLOCK_LENGTH);
800258945Sroberto	if (usedspace > 0) {
801258945Sroberto		/* Calculate how much free space is available in the buffer */
802258945Sroberto		freespace = ISC_SHA256_BLOCK_LENGTH - usedspace;
803258945Sroberto
804258945Sroberto		if (len >= freespace) {
805258945Sroberto			/* Fill the buffer completely and process it */
806258945Sroberto			memcpy(&context->buffer[usedspace], data, freespace);
807258945Sroberto			context->bitcount += freespace << 3;
808258945Sroberto			len -= freespace;
809258945Sroberto			data += freespace;
810258945Sroberto			isc_sha256_transform(context,
811258945Sroberto					     (isc_uint32_t*)context->buffer);
812258945Sroberto		} else {
813258945Sroberto			/* The buffer is not yet full */
814258945Sroberto			memcpy(&context->buffer[usedspace], data, len);
815258945Sroberto			context->bitcount += len << 3;
816258945Sroberto			/* Clean up: */
817258945Sroberto			usedspace = freespace = 0;
818280849Scy			/* Avoid compiler warnings: */
819280849Scy			POST(usedspace); POST(freespace);
820258945Sroberto			return;
821258945Sroberto		}
822258945Sroberto	}
823258945Sroberto	while (len >= ISC_SHA256_BLOCK_LENGTH) {
824258945Sroberto		/* Process as many complete blocks as we can */
825258945Sroberto		memcpy(context->buffer, data, ISC_SHA256_BLOCK_LENGTH);
826258945Sroberto		isc_sha256_transform(context, (isc_uint32_t*)context->buffer);
827258945Sroberto		context->bitcount += ISC_SHA256_BLOCK_LENGTH << 3;
828258945Sroberto		len -= ISC_SHA256_BLOCK_LENGTH;
829258945Sroberto		data += ISC_SHA256_BLOCK_LENGTH;
830258945Sroberto	}
831258945Sroberto	if (len > 0U) {
832258945Sroberto		/* There's left-overs, so save 'em */
833258945Sroberto		memcpy(context->buffer, data, len);
834258945Sroberto		context->bitcount += len << 3;
835258945Sroberto	}
836258945Sroberto	/* Clean up: */
837258945Sroberto	usedspace = freespace = 0;
838280849Scy	/* Avoid compiler warnings: */
839280849Scy	POST(usedspace); POST(freespace);
840258945Sroberto}
841258945Sroberto
842258945Srobertovoid
843258945Srobertoisc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
844258945Sroberto	isc_uint32_t	*d = (isc_uint32_t*)digest;
845258945Sroberto	unsigned int	usedspace;
846258945Sroberto
847258945Sroberto	/* Sanity check: */
848258945Sroberto	REQUIRE(context != (isc_sha256_t *)0);
849258945Sroberto
850258945Sroberto	/* If no digest buffer is passed, we don't bother doing this: */
851258945Sroberto	if (digest != (isc_uint8_t*)0) {
852258945Sroberto		usedspace = (unsigned int)((context->bitcount >> 3) %
853258945Sroberto					   ISC_SHA256_BLOCK_LENGTH);
854258945Sroberto#if BYTE_ORDER == LITTLE_ENDIAN
855258945Sroberto		/* Convert FROM host byte order */
856258945Sroberto		REVERSE64(context->bitcount,context->bitcount);
857258945Sroberto#endif
858258945Sroberto		if (usedspace > 0) {
859258945Sroberto			/* Begin padding with a 1 bit: */
860258945Sroberto			context->buffer[usedspace++] = 0x80;
861258945Sroberto
862258945Sroberto			if (usedspace <= ISC_SHA256_SHORT_BLOCK_LENGTH) {
863258945Sroberto				/* Set-up for the last transform: */
864258945Sroberto				memset(&context->buffer[usedspace], 0,
865258945Sroberto				       ISC_SHA256_SHORT_BLOCK_LENGTH - usedspace);
866258945Sroberto			} else {
867258945Sroberto				if (usedspace < ISC_SHA256_BLOCK_LENGTH) {
868258945Sroberto					memset(&context->buffer[usedspace], 0,
869258945Sroberto					       ISC_SHA256_BLOCK_LENGTH -
870258945Sroberto					       usedspace);
871258945Sroberto				}
872258945Sroberto				/* Do second-to-last transform: */
873258945Sroberto				isc_sha256_transform(context,
874258945Sroberto					       (isc_uint32_t*)context->buffer);
875258945Sroberto
876258945Sroberto				/* And set-up for the last transform: */
877258945Sroberto				memset(context->buffer, 0,
878258945Sroberto				       ISC_SHA256_SHORT_BLOCK_LENGTH);
879258945Sroberto			}
880258945Sroberto		} else {
881258945Sroberto			/* Set-up for the last transform: */
882258945Sroberto			memset(context->buffer, 0, ISC_SHA256_SHORT_BLOCK_LENGTH);
883258945Sroberto
884258945Sroberto			/* Begin padding with a 1 bit: */
885258945Sroberto			*context->buffer = 0x80;
886258945Sroberto		}
887258945Sroberto		/* Set the bit count: */
888258945Sroberto		*(isc_uint64_t*)&context->buffer[ISC_SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
889258945Sroberto
890258945Sroberto		/* Final transform: */
891258945Sroberto		isc_sha256_transform(context, (isc_uint32_t*)context->buffer);
892258945Sroberto
893258945Sroberto#if BYTE_ORDER == LITTLE_ENDIAN
894258945Sroberto		{
895258945Sroberto			/* Convert TO host byte order */
896258945Sroberto			int	j;
897258945Sroberto			for (j = 0; j < 8; j++) {
898258945Sroberto				REVERSE32(context->state[j],context->state[j]);
899258945Sroberto				*d++ = context->state[j];
900258945Sroberto			}
901258945Sroberto		}
902258945Sroberto#else
903258945Sroberto		memcpy(d, context->state, ISC_SHA256_DIGESTLENGTH);
904258945Sroberto#endif
905258945Sroberto	}
906258945Sroberto
907258945Sroberto	/* Clean up state data: */
908280849Scy	memset(context, 0, sizeof(*context));
909258945Sroberto	usedspace = 0;
910280849Scy	POST(usedspace);
911258945Sroberto}
912258945Sroberto
913258945Sroberto/*** SHA-512: *********************************************************/
914258945Srobertovoid
915258945Srobertoisc_sha512_init(isc_sha512_t *context) {
916258945Sroberto	if (context == (isc_sha512_t *)0) {
917258945Sroberto		return;
918258945Sroberto	}
919258945Sroberto	memcpy(context->state, sha512_initial_hash_value,
920258945Sroberto	       ISC_SHA512_DIGESTLENGTH);
921258945Sroberto	memset(context->buffer, 0, ISC_SHA512_BLOCK_LENGTH);
922258945Sroberto	context->bitcount[0] = context->bitcount[1] =  0;
923258945Sroberto}
924258945Sroberto
925280849Scyvoid
926280849Scyisc_sha512_invalidate(isc_sha512_t *context) {
927280849Scy	memset(context, 0, sizeof(isc_sha512_t));
928280849Scy}
929280849Scy
930258945Sroberto#ifdef ISC_SHA2_UNROLL_TRANSFORM
931258945Sroberto
932258945Sroberto/* Unrolled SHA-512 round macros: */
933258945Sroberto#if BYTE_ORDER == LITTLE_ENDIAN
934258945Sroberto
935258945Sroberto#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
936258945Sroberto	REVERSE64(*data++, W512[j]); \
937258945Sroberto	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
938258945Sroberto	     K512[j] + W512[j]; \
939258945Sroberto	(d) += T1, \
940258945Sroberto	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
941258945Sroberto	j++
942258945Sroberto
943258945Sroberto
944258945Sroberto#else /* BYTE_ORDER == LITTLE_ENDIAN */
945258945Sroberto
946258945Sroberto#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
947258945Sroberto	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
948258945Sroberto	     K512[j] + (W512[j] = *data++); \
949258945Sroberto	(d) += T1; \
950258945Sroberto	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
951258945Sroberto	j++
952258945Sroberto
953258945Sroberto#endif /* BYTE_ORDER == LITTLE_ENDIAN */
954258945Sroberto
955258945Sroberto#define ROUND512(a,b,c,d,e,f,g,h)	\
956258945Sroberto	s0 = W512[(j+1)&0x0f]; \
957258945Sroberto	s0 = sigma0_512(s0); \
958258945Sroberto	s1 = W512[(j+14)&0x0f]; \
959258945Sroberto	s1 = sigma1_512(s1); \
960258945Sroberto	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
961258945Sroberto	     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
962258945Sroberto	(d) += T1; \
963258945Sroberto	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
964258945Sroberto	j++
965258945Sroberto
966258945Srobertovoid isc_sha512_transform(isc_sha512_t *context, const isc_uint64_t* data) {
967258945Sroberto	isc_uint64_t	a, b, c, d, e, f, g, h, s0, s1;
968258945Sroberto	isc_uint64_t	T1, *W512 = (isc_uint64_t*)context->buffer;
969258945Sroberto	int		j;
970258945Sroberto
971258945Sroberto	/* Initialize registers with the prev. intermediate value */
972258945Sroberto	a = context->state[0];
973258945Sroberto	b = context->state[1];
974258945Sroberto	c = context->state[2];
975258945Sroberto	d = context->state[3];
976258945Sroberto	e = context->state[4];
977258945Sroberto	f = context->state[5];
978258945Sroberto	g = context->state[6];
979258945Sroberto	h = context->state[7];
980258945Sroberto
981258945Sroberto	j = 0;
982258945Sroberto	do {
983258945Sroberto		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
984258945Sroberto		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
985258945Sroberto		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
986258945Sroberto		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
987258945Sroberto		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
988258945Sroberto		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
989258945Sroberto		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
990258945Sroberto		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
991258945Sroberto	} while (j < 16);
992258945Sroberto
993258945Sroberto	/* Now for the remaining rounds up to 79: */
994258945Sroberto	do {
995258945Sroberto		ROUND512(a,b,c,d,e,f,g,h);
996258945Sroberto		ROUND512(h,a,b,c,d,e,f,g);
997258945Sroberto		ROUND512(g,h,a,b,c,d,e,f);
998258945Sroberto		ROUND512(f,g,h,a,b,c,d,e);
999258945Sroberto		ROUND512(e,f,g,h,a,b,c,d);
1000258945Sroberto		ROUND512(d,e,f,g,h,a,b,c);
1001258945Sroberto		ROUND512(c,d,e,f,g,h,a,b);
1002258945Sroberto		ROUND512(b,c,d,e,f,g,h,a);
1003258945Sroberto	} while (j < 80);
1004258945Sroberto
1005258945Sroberto	/* Compute the current intermediate hash value */
1006258945Sroberto	context->state[0] += a;
1007258945Sroberto	context->state[1] += b;
1008258945Sroberto	context->state[2] += c;
1009258945Sroberto	context->state[3] += d;
1010258945Sroberto	context->state[4] += e;
1011258945Sroberto	context->state[5] += f;
1012258945Sroberto	context->state[6] += g;
1013258945Sroberto	context->state[7] += h;
1014258945Sroberto
1015258945Sroberto	/* Clean up */
1016258945Sroberto	a = b = c = d = e = f = g = h = T1 = 0;
1017280849Scy	/* Avoid compiler warnings */
1018280849Scy	POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
1019280849Scy	POST(g); POST(h); POST(T1);
1020258945Sroberto}
1021258945Sroberto
1022258945Sroberto#else /* ISC_SHA2_UNROLL_TRANSFORM */
1023258945Sroberto
1024258945Srobertovoid
1025258945Srobertoisc_sha512_transform(isc_sha512_t *context, const isc_uint64_t* data) {
1026258945Sroberto	isc_uint64_t	a, b, c, d, e, f, g, h, s0, s1;
1027258945Sroberto	isc_uint64_t	T1, T2, *W512 = (isc_uint64_t*)context->buffer;
1028258945Sroberto	int		j;
1029258945Sroberto
1030258945Sroberto	/* Initialize registers with the prev. intermediate value */
1031258945Sroberto	a = context->state[0];
1032258945Sroberto	b = context->state[1];
1033258945Sroberto	c = context->state[2];
1034258945Sroberto	d = context->state[3];
1035258945Sroberto	e = context->state[4];
1036258945Sroberto	f = context->state[5];
1037258945Sroberto	g = context->state[6];
1038258945Sroberto	h = context->state[7];
1039258945Sroberto
1040258945Sroberto	j = 0;
1041258945Sroberto	do {
1042258945Sroberto#if BYTE_ORDER == LITTLE_ENDIAN
1043258945Sroberto		/* Convert TO host byte order */
1044258945Sroberto		REVERSE64(*data++, W512[j]);
1045258945Sroberto		/* Apply the SHA-512 compression function to update a..h */
1046258945Sroberto		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
1047258945Sroberto#else /* BYTE_ORDER == LITTLE_ENDIAN */
1048258945Sroberto		/* Apply the SHA-512 compression function to update a..h with copy */
1049258945Sroberto		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
1050258945Sroberto#endif /* BYTE_ORDER == LITTLE_ENDIAN */
1051258945Sroberto		T2 = Sigma0_512(a) + Maj(a, b, c);
1052258945Sroberto		h = g;
1053258945Sroberto		g = f;
1054258945Sroberto		f = e;
1055258945Sroberto		e = d + T1;
1056258945Sroberto		d = c;
1057258945Sroberto		c = b;
1058258945Sroberto		b = a;
1059258945Sroberto		a = T1 + T2;
1060258945Sroberto
1061258945Sroberto		j++;
1062258945Sroberto	} while (j < 16);
1063258945Sroberto
1064258945Sroberto	do {
1065258945Sroberto		/* Part of the message block expansion: */
1066258945Sroberto		s0 = W512[(j+1)&0x0f];
1067258945Sroberto		s0 = sigma0_512(s0);
1068258945Sroberto		s1 = W512[(j+14)&0x0f];
1069258945Sroberto		s1 =  sigma1_512(s1);
1070258945Sroberto
1071258945Sroberto		/* Apply the SHA-512 compression function to update a..h */
1072258945Sroberto		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
1073258945Sroberto		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
1074258945Sroberto		T2 = Sigma0_512(a) + Maj(a, b, c);
1075258945Sroberto		h = g;
1076258945Sroberto		g = f;
1077258945Sroberto		f = e;
1078258945Sroberto		e = d + T1;
1079258945Sroberto		d = c;
1080258945Sroberto		c = b;
1081258945Sroberto		b = a;
1082258945Sroberto		a = T1 + T2;
1083258945Sroberto
1084258945Sroberto		j++;
1085258945Sroberto	} while (j < 80);
1086258945Sroberto
1087258945Sroberto	/* Compute the current intermediate hash value */
1088258945Sroberto	context->state[0] += a;
1089258945Sroberto	context->state[1] += b;
1090258945Sroberto	context->state[2] += c;
1091258945Sroberto	context->state[3] += d;
1092258945Sroberto	context->state[4] += e;
1093258945Sroberto	context->state[5] += f;
1094258945Sroberto	context->state[6] += g;
1095258945Sroberto	context->state[7] += h;
1096258945Sroberto
1097258945Sroberto	/* Clean up */
1098258945Sroberto	a = b = c = d = e = f = g = h = T1 = T2 = 0;
1099280849Scy	/* Avoid compiler warnings */
1100280849Scy	POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
1101280849Scy	POST(g); POST(h); POST(T1); POST(T2);
1102258945Sroberto}
1103258945Sroberto
1104258945Sroberto#endif /* ISC_SHA2_UNROLL_TRANSFORM */
1105258945Sroberto
1106258945Srobertovoid isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) {
1107258945Sroberto	unsigned int	freespace, usedspace;
1108258945Sroberto
1109258945Sroberto	if (len == 0U) {
1110258945Sroberto		/* Calling with no data is valid - we do nothing */
1111258945Sroberto		return;
1112258945Sroberto	}
1113258945Sroberto
1114258945Sroberto	/* Sanity check: */
1115258945Sroberto	REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
1116258945Sroberto
1117258945Sroberto	usedspace = (unsigned int)((context->bitcount[0] >> 3) %
1118258945Sroberto				   ISC_SHA512_BLOCK_LENGTH);
1119258945Sroberto	if (usedspace > 0) {
1120258945Sroberto		/* Calculate how much free space is available in the buffer */
1121258945Sroberto		freespace = ISC_SHA512_BLOCK_LENGTH - usedspace;
1122258945Sroberto
1123258945Sroberto		if (len >= freespace) {
1124258945Sroberto			/* Fill the buffer completely and process it */
1125258945Sroberto			memcpy(&context->buffer[usedspace], data, freespace);
1126258945Sroberto			ADDINC128(context->bitcount, freespace << 3);
1127258945Sroberto			len -= freespace;
1128258945Sroberto			data += freespace;
1129258945Sroberto			isc_sha512_transform(context,
1130258945Sroberto					     (isc_uint64_t*)context->buffer);
1131258945Sroberto		} else {
1132258945Sroberto			/* The buffer is not yet full */
1133258945Sroberto			memcpy(&context->buffer[usedspace], data, len);
1134258945Sroberto			ADDINC128(context->bitcount, len << 3);
1135258945Sroberto			/* Clean up: */
1136258945Sroberto			usedspace = freespace = 0;
1137280849Scy			/* Avoid compiler warnings: */
1138280849Scy			POST(usedspace); POST(freespace);
1139258945Sroberto			return;
1140258945Sroberto		}
1141258945Sroberto	}
1142258945Sroberto	while (len >= ISC_SHA512_BLOCK_LENGTH) {
1143258945Sroberto		/* Process as many complete blocks as we can */
1144258945Sroberto		memcpy(context->buffer, data, ISC_SHA512_BLOCK_LENGTH);
1145258945Sroberto		isc_sha512_transform(context, (isc_uint64_t*)context->buffer);
1146258945Sroberto		ADDINC128(context->bitcount, ISC_SHA512_BLOCK_LENGTH << 3);
1147258945Sroberto		len -= ISC_SHA512_BLOCK_LENGTH;
1148258945Sroberto		data += ISC_SHA512_BLOCK_LENGTH;
1149258945Sroberto	}
1150258945Sroberto	if (len > 0U) {
1151258945Sroberto		/* There's left-overs, so save 'em */
1152258945Sroberto		memcpy(context->buffer, data, len);
1153258945Sroberto		ADDINC128(context->bitcount, len << 3);
1154258945Sroberto	}
1155258945Sroberto	/* Clean up: */
1156258945Sroberto	usedspace = freespace = 0;
1157280849Scy	/* Avoid compiler warnings: */
1158280849Scy	POST(usedspace); POST(freespace);
1159258945Sroberto}
1160258945Sroberto
1161258945Srobertovoid isc_sha512_last(isc_sha512_t *context) {
1162258945Sroberto	unsigned int	usedspace;
1163258945Sroberto
1164258945Sroberto	usedspace = (unsigned int)((context->bitcount[0] >> 3) %
1165258945Sroberto				    ISC_SHA512_BLOCK_LENGTH);
1166258945Sroberto#if BYTE_ORDER == LITTLE_ENDIAN
1167258945Sroberto	/* Convert FROM host byte order */
1168258945Sroberto	REVERSE64(context->bitcount[0],context->bitcount[0]);
1169258945Sroberto	REVERSE64(context->bitcount[1],context->bitcount[1]);
1170258945Sroberto#endif
1171258945Sroberto	if (usedspace > 0) {
1172258945Sroberto		/* Begin padding with a 1 bit: */
1173258945Sroberto		context->buffer[usedspace++] = 0x80;
1174258945Sroberto
1175258945Sroberto		if (usedspace <= ISC_SHA512_SHORT_BLOCK_LENGTH) {
1176258945Sroberto			/* Set-up for the last transform: */
1177258945Sroberto			memset(&context->buffer[usedspace], 0,
1178258945Sroberto			       ISC_SHA512_SHORT_BLOCK_LENGTH - usedspace);
1179258945Sroberto		} else {
1180258945Sroberto			if (usedspace < ISC_SHA512_BLOCK_LENGTH) {
1181258945Sroberto				memset(&context->buffer[usedspace], 0,
1182258945Sroberto				       ISC_SHA512_BLOCK_LENGTH - usedspace);
1183258945Sroberto			}
1184258945Sroberto			/* Do second-to-last transform: */
1185258945Sroberto			isc_sha512_transform(context,
1186258945Sroberto					    (isc_uint64_t*)context->buffer);
1187258945Sroberto
1188258945Sroberto			/* And set-up for the last transform: */
1189258945Sroberto			memset(context->buffer, 0, ISC_SHA512_BLOCK_LENGTH - 2);
1190258945Sroberto		}
1191258945Sroberto	} else {
1192258945Sroberto		/* Prepare for final transform: */
1193258945Sroberto		memset(context->buffer, 0, ISC_SHA512_SHORT_BLOCK_LENGTH);
1194258945Sroberto
1195258945Sroberto		/* Begin padding with a 1 bit: */
1196258945Sroberto		*context->buffer = 0x80;
1197258945Sroberto	}
1198258945Sroberto	/* Store the length of input data (in bits): */
1199258945Sroberto	*(isc_uint64_t*)&context->buffer[ISC_SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
1200258945Sroberto	*(isc_uint64_t*)&context->buffer[ISC_SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
1201258945Sroberto
1202258945Sroberto	/* Final transform: */
1203258945Sroberto	isc_sha512_transform(context, (isc_uint64_t*)context->buffer);
1204258945Sroberto}
1205258945Sroberto
1206258945Srobertovoid isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
1207258945Sroberto	isc_uint64_t	*d = (isc_uint64_t*)digest;
1208258945Sroberto
1209258945Sroberto	/* Sanity check: */
1210258945Sroberto	REQUIRE(context != (isc_sha512_t *)0);
1211258945Sroberto
1212258945Sroberto	/* If no digest buffer is passed, we don't bother doing this: */
1213258945Sroberto	if (digest != (isc_uint8_t*)0) {
1214258945Sroberto		isc_sha512_last(context);
1215258945Sroberto
1216258945Sroberto		/* Save the hash data for output: */
1217258945Sroberto#if BYTE_ORDER == LITTLE_ENDIAN
1218258945Sroberto		{
1219258945Sroberto			/* Convert TO host byte order */
1220258945Sroberto			int	j;
1221258945Sroberto			for (j = 0; j < 8; j++) {
1222258945Sroberto				REVERSE64(context->state[j],context->state[j]);
1223258945Sroberto				*d++ = context->state[j];
1224258945Sroberto			}
1225258945Sroberto		}
1226258945Sroberto#else
1227258945Sroberto		memcpy(d, context->state, ISC_SHA512_DIGESTLENGTH);
1228258945Sroberto#endif
1229258945Sroberto	}
1230258945Sroberto
1231258945Sroberto	/* Zero out state data */
1232280849Scy	memset(context, 0, sizeof(*context));
1233258945Sroberto}
1234258945Sroberto
1235258945Sroberto
1236258945Sroberto/*** SHA-384: *********************************************************/
1237258945Srobertovoid
1238258945Srobertoisc_sha384_init(isc_sha384_t *context) {
1239258945Sroberto	if (context == (isc_sha384_t *)0) {
1240258945Sroberto		return;
1241258945Sroberto	}
1242258945Sroberto	memcpy(context->state, sha384_initial_hash_value,
1243258945Sroberto	       ISC_SHA512_DIGESTLENGTH);
1244258945Sroberto	memset(context->buffer, 0, ISC_SHA384_BLOCK_LENGTH);
1245258945Sroberto	context->bitcount[0] = context->bitcount[1] = 0;
1246258945Sroberto}
1247258945Sroberto
1248258945Srobertovoid
1249280849Scyisc_sha384_invalidate(isc_sha384_t *context) {
1250280849Scy	memset(context, 0, sizeof(isc_sha384_t));
1251280849Scy}
1252280849Scy
1253280849Scyvoid
1254258945Srobertoisc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) {
1255258945Sroberto	isc_sha512_update((isc_sha512_t *)context, data, len);
1256258945Sroberto}
1257258945Sroberto
1258258945Srobertovoid
1259258945Srobertoisc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
1260258945Sroberto	isc_uint64_t	*d = (isc_uint64_t*)digest;
1261258945Sroberto
1262258945Sroberto	/* Sanity check: */
1263258945Sroberto	REQUIRE(context != (isc_sha384_t *)0);
1264258945Sroberto
1265258945Sroberto	/* If no digest buffer is passed, we don't bother doing this: */
1266258945Sroberto	if (digest != (isc_uint8_t*)0) {
1267258945Sroberto		isc_sha512_last((isc_sha512_t *)context);
1268258945Sroberto
1269258945Sroberto		/* Save the hash data for output: */
1270258945Sroberto#if BYTE_ORDER == LITTLE_ENDIAN
1271258945Sroberto		{
1272258945Sroberto			/* Convert TO host byte order */
1273258945Sroberto			int	j;
1274258945Sroberto			for (j = 0; j < 6; j++) {
1275258945Sroberto				REVERSE64(context->state[j],context->state[j]);
1276258945Sroberto				*d++ = context->state[j];
1277258945Sroberto			}
1278258945Sroberto		}
1279258945Sroberto#else
1280258945Sroberto		memcpy(d, context->state, ISC_SHA384_DIGESTLENGTH);
1281258945Sroberto#endif
1282258945Sroberto	}
1283258945Sroberto
1284258945Sroberto	/* Zero out state data */
1285280849Scy	memset(context, 0, sizeof(*context));
1286258945Sroberto}
1287280849Scy#endif /* !ISC_PLATFORM_OPENSSLHASH */
1288258945Sroberto
1289280849Scy/*
1290280849Scy * Constant used by SHA256/384/512_End() functions for converting the
1291280849Scy * digest to a readable hexadecimal character string:
1292280849Scy */
1293280849Scystatic const char *sha2_hex_digits = "0123456789abcdef";
1294280849Scy
1295258945Srobertochar *
1296280849Scyisc_sha224_end(isc_sha224_t *context, char buffer[]) {
1297280849Scy	isc_uint8_t	digest[ISC_SHA224_DIGESTLENGTH], *d = digest;
1298280849Scy	unsigned int	i;
1299280849Scy
1300280849Scy	/* Sanity check: */
1301280849Scy	REQUIRE(context != (isc_sha224_t *)0);
1302280849Scy
1303280849Scy	if (buffer != (char*)0) {
1304280849Scy		isc_sha224_final(digest, context);
1305280849Scy
1306280849Scy		for (i = 0; i < ISC_SHA224_DIGESTLENGTH; i++) {
1307280849Scy			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
1308280849Scy			*buffer++ = sha2_hex_digits[*d & 0x0f];
1309280849Scy			d++;
1310280849Scy		}
1311280849Scy		*buffer = (char)0;
1312280849Scy	} else {
1313280849Scy#ifdef ISC_PLATFORM_OPENSSLHASH
1314280849Scy		EVP_MD_CTX_cleanup(context);
1315280849Scy#else
1316280849Scy		memset(context, 0, sizeof(*context));
1317280849Scy#endif
1318280849Scy	}
1319280849Scy	memset(digest, 0, ISC_SHA224_DIGESTLENGTH);
1320280849Scy	return buffer;
1321280849Scy}
1322280849Scy
1323280849Scychar *
1324280849Scyisc_sha224_data(const isc_uint8_t *data, size_t len,
1325280849Scy		char digest[ISC_SHA224_DIGESTSTRINGLENGTH])
1326280849Scy{
1327280849Scy	isc_sha224_t context;
1328280849Scy
1329280849Scy	isc_sha224_init(&context);
1330280849Scy	isc_sha224_update(&context, data, len);
1331280849Scy	return (isc_sha224_end(&context, digest));
1332280849Scy}
1333280849Scy
1334280849Scychar *
1335280849Scyisc_sha256_end(isc_sha256_t *context, char buffer[]) {
1336280849Scy	isc_uint8_t	digest[ISC_SHA256_DIGESTLENGTH], *d = digest;
1337280849Scy	unsigned int	i;
1338280849Scy
1339280849Scy	/* Sanity check: */
1340280849Scy	REQUIRE(context != (isc_sha256_t *)0);
1341280849Scy
1342280849Scy	if (buffer != (char*)0) {
1343280849Scy		isc_sha256_final(digest, context);
1344280849Scy
1345280849Scy		for (i = 0; i < ISC_SHA256_DIGESTLENGTH; i++) {
1346280849Scy			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
1347280849Scy			*buffer++ = sha2_hex_digits[*d & 0x0f];
1348280849Scy			d++;
1349280849Scy		}
1350280849Scy		*buffer = (char)0;
1351280849Scy	} else {
1352280849Scy#ifdef ISC_PLATFORM_OPENSSLHASH
1353280849Scy		EVP_MD_CTX_cleanup(context);
1354280849Scy#else
1355280849Scy		memset(context, 0, sizeof(*context));
1356280849Scy#endif
1357280849Scy	}
1358280849Scy	memset(digest, 0, ISC_SHA256_DIGESTLENGTH);
1359280849Scy	return buffer;
1360280849Scy}
1361280849Scy
1362280849Scychar *
1363280849Scyisc_sha256_data(const isc_uint8_t* data, size_t len,
1364280849Scy		char digest[ISC_SHA256_DIGESTSTRINGLENGTH])
1365280849Scy{
1366280849Scy	isc_sha256_t context;
1367280849Scy
1368280849Scy	isc_sha256_init(&context);
1369280849Scy	isc_sha256_update(&context, data, len);
1370280849Scy	return (isc_sha256_end(&context, digest));
1371280849Scy}
1372280849Scy
1373280849Scychar *
1374280849Scyisc_sha512_end(isc_sha512_t *context, char buffer[]) {
1375280849Scy	isc_uint8_t	digest[ISC_SHA512_DIGESTLENGTH], *d = digest;
1376280849Scy	unsigned int	i;
1377280849Scy
1378280849Scy	/* Sanity check: */
1379280849Scy	REQUIRE(context != (isc_sha512_t *)0);
1380280849Scy
1381280849Scy	if (buffer != (char*)0) {
1382280849Scy		isc_sha512_final(digest, context);
1383280849Scy
1384280849Scy		for (i = 0; i < ISC_SHA512_DIGESTLENGTH; i++) {
1385280849Scy			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
1386280849Scy			*buffer++ = sha2_hex_digits[*d & 0x0f];
1387280849Scy			d++;
1388280849Scy		}
1389280849Scy		*buffer = (char)0;
1390280849Scy	} else {
1391280849Scy#ifdef ISC_PLATFORM_OPENSSLHASH
1392280849Scy		EVP_MD_CTX_cleanup(context);
1393280849Scy#else
1394280849Scy		memset(context, 0, sizeof(*context));
1395280849Scy#endif
1396280849Scy	}
1397280849Scy	memset(digest, 0, ISC_SHA512_DIGESTLENGTH);
1398280849Scy	return buffer;
1399280849Scy}
1400280849Scy
1401280849Scychar *
1402280849Scyisc_sha512_data(const isc_uint8_t *data, size_t len,
1403280849Scy		char digest[ISC_SHA512_DIGESTSTRINGLENGTH])
1404280849Scy{
1405280849Scy	isc_sha512_t 	context;
1406280849Scy
1407280849Scy	isc_sha512_init(&context);
1408280849Scy	isc_sha512_update(&context, data, len);
1409280849Scy	return (isc_sha512_end(&context, digest));
1410280849Scy}
1411280849Scy
1412280849Scychar *
1413258945Srobertoisc_sha384_end(isc_sha384_t *context, char buffer[]) {
1414258945Sroberto	isc_uint8_t	digest[ISC_SHA384_DIGESTLENGTH], *d = digest;
1415258945Sroberto	unsigned int	i;
1416258945Sroberto
1417258945Sroberto	/* Sanity check: */
1418258945Sroberto	REQUIRE(context != (isc_sha384_t *)0);
1419258945Sroberto
1420258945Sroberto	if (buffer != (char*)0) {
1421258945Sroberto		isc_sha384_final(digest, context);
1422258945Sroberto
1423258945Sroberto		for (i = 0; i < ISC_SHA384_DIGESTLENGTH; i++) {
1424258945Sroberto			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
1425258945Sroberto			*buffer++ = sha2_hex_digits[*d & 0x0f];
1426258945Sroberto			d++;
1427258945Sroberto		}
1428258945Sroberto		*buffer = (char)0;
1429258945Sroberto	} else {
1430280849Scy#ifdef ISC_PLATFORM_OPENSSLHASH
1431280849Scy		EVP_MD_CTX_cleanup(context);
1432280849Scy#else
1433280849Scy		memset(context, 0, sizeof(*context));
1434280849Scy#endif
1435258945Sroberto	}
1436258945Sroberto	memset(digest, 0, ISC_SHA384_DIGESTLENGTH);
1437258945Sroberto	return buffer;
1438258945Sroberto}
1439258945Sroberto
1440280849Scychar *
1441258945Srobertoisc_sha384_data(const isc_uint8_t *data, size_t len,
1442258945Sroberto		char digest[ISC_SHA384_DIGESTSTRINGLENGTH])
1443258945Sroberto{
1444258945Sroberto	isc_sha384_t context;
1445258945Sroberto
1446258945Sroberto	isc_sha384_init(&context);
1447258945Sroberto	isc_sha384_update(&context, data, len);
1448258945Sroberto	return (isc_sha384_end(&context, digest));
1449258945Sroberto}
1450