xref: /minix3/common/lib/libc/hash/sha2/sha2.c (revision 44707c1900f2a0f1cb5c20e60477b0c2c9ceb595)
184d9c625SLionel Sambuc /* $NetBSD: sha2.c,v 1.24 2013/06/09 19:46:56 christos Exp $ */
2b6cbf720SGianluca Guida /*	$KAME: sha2.c,v 1.9 2003/07/20 00:28:38 itojun Exp $	*/
3b6cbf720SGianluca Guida 
4b6cbf720SGianluca Guida /*
5b6cbf720SGianluca Guida  * sha2.c
6b6cbf720SGianluca Guida  *
7b6cbf720SGianluca Guida  * Version 1.0.0beta1
8b6cbf720SGianluca Guida  *
9b6cbf720SGianluca Guida  * Written by Aaron D. Gifford <me@aarongifford.com>
10b6cbf720SGianluca Guida  *
11b6cbf720SGianluca Guida  * Copyright 2000 Aaron D. Gifford.  All rights reserved.
12b6cbf720SGianluca Guida  *
13b6cbf720SGianluca Guida  * Redistribution and use in source and binary forms, with or without
14b6cbf720SGianluca Guida  * modification, are permitted provided that the following conditions
15b6cbf720SGianluca Guida  * are met:
16b6cbf720SGianluca Guida  * 1. Redistributions of source code must retain the above copyright
17b6cbf720SGianluca Guida  *    notice, this list of conditions and the following disclaimer.
18b6cbf720SGianluca Guida  * 2. Redistributions in binary form must reproduce the above copyright
19b6cbf720SGianluca Guida  *    notice, this list of conditions and the following disclaimer in the
20b6cbf720SGianluca Guida  *    documentation and/or other materials provided with the distribution.
21b6cbf720SGianluca Guida  * 3. Neither the name of the copyright holder nor the names of contributors
22b6cbf720SGianluca Guida  *    may be used to endorse or promote products derived from this software
23b6cbf720SGianluca Guida  *    without specific prior written permission.
24b6cbf720SGianluca Guida  *
25b6cbf720SGianluca Guida  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
26b6cbf720SGianluca Guida  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27b6cbf720SGianluca Guida  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28b6cbf720SGianluca Guida  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
29b6cbf720SGianluca Guida  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30b6cbf720SGianluca Guida  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31b6cbf720SGianluca Guida  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32b6cbf720SGianluca Guida  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33b6cbf720SGianluca Guida  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34b6cbf720SGianluca Guida  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35b6cbf720SGianluca Guida  * SUCH DAMAGE.
36b6cbf720SGianluca Guida  *
37b6cbf720SGianluca Guida  */
38b6cbf720SGianluca Guida 
39b6cbf720SGianluca Guida #if HAVE_NBTOOL_CONFIG_H
40b6cbf720SGianluca Guida #include "nbtool_config.h"
41b6cbf720SGianluca Guida #endif
42b6cbf720SGianluca Guida 
43b6cbf720SGianluca Guida #include <sys/cdefs.h>
44b6cbf720SGianluca Guida 
45b6cbf720SGianluca Guida #if defined(_KERNEL) || defined(_STANDALONE)
4684d9c625SLionel Sambuc __KERNEL_RCSID(0, "$NetBSD: sha2.c,v 1.24 2013/06/09 19:46:56 christos Exp $");
47b6cbf720SGianluca Guida 
48b6cbf720SGianluca Guida #include <sys/param.h>	/* XXX: to pull <machine/macros.h> for vax memset(9) */
49b6cbf720SGianluca Guida #include <lib/libkern/libkern.h>
50b6cbf720SGianluca Guida 
51b6cbf720SGianluca Guida #else
52b6cbf720SGianluca Guida 
53b6cbf720SGianluca Guida #if defined(LIBC_SCCS) && !defined(lint)
5484d9c625SLionel Sambuc __RCSID("$NetBSD: sha2.c,v 1.24 2013/06/09 19:46:56 christos Exp $");
55b6cbf720SGianluca Guida #endif /* LIBC_SCCS and not lint */
56b6cbf720SGianluca Guida 
57b6cbf720SGianluca Guida #include "namespace.h"
58b6cbf720SGianluca Guida #include <string.h>
59b6cbf720SGianluca Guida 
60*44707c19SDavid van Moolenbroek #if defined(__minix) && defined(_LIBMINC)
61*44707c19SDavid van Moolenbroek #include <stdint.h> /* for uintptr_t */
62*44707c19SDavid van Moolenbroek #endif /* defined(__minix) && defined(_LIBMINC) */
63*44707c19SDavid van Moolenbroek 
64b6cbf720SGianluca Guida #endif
65b6cbf720SGianluca Guida 
66b6cbf720SGianluca Guida #include <sys/types.h>
67b6cbf720SGianluca Guida #include <sys/sha2.h>
68b6cbf720SGianluca Guida 
69b6cbf720SGianluca Guida #if HAVE_SYS_ENDIAN_H
70b6cbf720SGianluca Guida # include <sys/endian.h>
71b6cbf720SGianluca Guida #endif
72b6cbf720SGianluca Guida 
73b6cbf720SGianluca Guida /*** SHA-256/384/512 Various Length Definitions ***********************/
74b6cbf720SGianluca Guida /* NOTE: Most of these are in sha2.h */
75b6cbf720SGianluca Guida #define SHA256_SHORT_BLOCK_LENGTH	(SHA256_BLOCK_LENGTH - 8)
76b6cbf720SGianluca Guida #define SHA384_SHORT_BLOCK_LENGTH	(SHA384_BLOCK_LENGTH - 16)
77b6cbf720SGianluca Guida #define SHA512_SHORT_BLOCK_LENGTH	(SHA512_BLOCK_LENGTH - 16)
78b6cbf720SGianluca Guida 
79b6cbf720SGianluca Guida /*
80b6cbf720SGianluca Guida  * Macro for incrementally adding the unsigned 64-bit integer n to the
81b6cbf720SGianluca Guida  * unsigned 128-bit integer (represented using a two-element array of
82b6cbf720SGianluca Guida  * 64-bit words):
83b6cbf720SGianluca Guida  */
84b6cbf720SGianluca Guida #define ADDINC128(w,n)	{ \
85b6cbf720SGianluca Guida 	(w)[0] += (uint64_t)(n); \
86b6cbf720SGianluca Guida 	if ((w)[0] < (n)) { \
87b6cbf720SGianluca Guida 		(w)[1]++; \
88b6cbf720SGianluca Guida 	} \
89b6cbf720SGianluca Guida }
90b6cbf720SGianluca Guida 
91b6cbf720SGianluca Guida /*** THE SIX LOGICAL FUNCTIONS ****************************************/
92b6cbf720SGianluca Guida /*
93b6cbf720SGianluca Guida  * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
94b6cbf720SGianluca Guida  *
95b6cbf720SGianluca Guida  *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
96b6cbf720SGianluca Guida  *   S is a ROTATION) because the SHA-256/384/512 description document
97b6cbf720SGianluca Guida  *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
98b6cbf720SGianluca Guida  *   same "backwards" definition.
99b6cbf720SGianluca Guida  */
100b6cbf720SGianluca Guida /* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
101b6cbf720SGianluca Guida #define R(b,x) 		((x) >> (b))
102b6cbf720SGianluca Guida /* 32-bit Rotate-right (used in SHA-256): */
103b6cbf720SGianluca Guida #define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
104b6cbf720SGianluca Guida /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
105b6cbf720SGianluca Guida #define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
106b6cbf720SGianluca Guida 
107b6cbf720SGianluca Guida /* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
108b6cbf720SGianluca Guida #define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
109b6cbf720SGianluca Guida #define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
110b6cbf720SGianluca Guida 
111b6cbf720SGianluca Guida /* Four of six logical functions used in SHA-256: */
112b6cbf720SGianluca Guida #define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
113b6cbf720SGianluca Guida #define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
114b6cbf720SGianluca Guida #define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
115b6cbf720SGianluca Guida #define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
116b6cbf720SGianluca Guida 
117b6cbf720SGianluca Guida /* Four of six logical functions used in SHA-384 and SHA-512: */
118b6cbf720SGianluca Guida #define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
119b6cbf720SGianluca Guida #define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
120b6cbf720SGianluca Guida #define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
121b6cbf720SGianluca Guida #define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
122b6cbf720SGianluca Guida 
123b6cbf720SGianluca Guida /*** INTERNAL FUNCTION PROTOTYPES *************************************/
124b6cbf720SGianluca Guida /* NOTE: These should not be accessed directly from outside this
125b6cbf720SGianluca Guida  * library -- they are intended for private internal visibility/use
126b6cbf720SGianluca Guida  * only.
127b6cbf720SGianluca Guida  */
128b6cbf720SGianluca Guida static void SHA512_Last(SHA512_CTX *);
129b6cbf720SGianluca Guida void SHA224_Transform(SHA224_CTX *, const uint32_t*);
130b6cbf720SGianluca Guida void SHA256_Transform(SHA256_CTX *, const uint32_t*);
131b6cbf720SGianluca Guida void SHA384_Transform(SHA384_CTX *, const uint64_t*);
132b6cbf720SGianluca Guida void SHA512_Transform(SHA512_CTX *, const uint64_t*);
133b6cbf720SGianluca Guida 
134b6cbf720SGianluca Guida 
135b6cbf720SGianluca Guida /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
136b6cbf720SGianluca Guida /* Hash constant words K for SHA-256: */
137b6cbf720SGianluca Guida static const uint32_t K256[64] = {
138b6cbf720SGianluca Guida 	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
139b6cbf720SGianluca Guida 	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
140b6cbf720SGianluca Guida 	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
141b6cbf720SGianluca Guida 	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
142b6cbf720SGianluca Guida 	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
143b6cbf720SGianluca Guida 	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
144b6cbf720SGianluca Guida 	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
145b6cbf720SGianluca Guida 	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
146b6cbf720SGianluca Guida 	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
147b6cbf720SGianluca Guida 	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
148b6cbf720SGianluca Guida 	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
149b6cbf720SGianluca Guida 	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
150b6cbf720SGianluca Guida 	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
151b6cbf720SGianluca Guida 	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
152b6cbf720SGianluca Guida 	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
153b6cbf720SGianluca Guida 	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
154b6cbf720SGianluca Guida };
155b6cbf720SGianluca Guida 
156b6cbf720SGianluca Guida /* Initial hash value H for SHA-224: */
157b6cbf720SGianluca Guida static const uint32_t sha224_initial_hash_value[8] = {
158b6cbf720SGianluca Guida 	0xc1059ed8UL,
159b6cbf720SGianluca Guida 	0x367cd507UL,
160b6cbf720SGianluca Guida 	0x3070dd17UL,
161b6cbf720SGianluca Guida 	0xf70e5939UL,
162b6cbf720SGianluca Guida 	0xffc00b31UL,
163b6cbf720SGianluca Guida 	0x68581511UL,
164b6cbf720SGianluca Guida 	0x64f98fa7UL,
165b6cbf720SGianluca Guida 	0xbefa4fa4UL
166b6cbf720SGianluca Guida };
167b6cbf720SGianluca Guida 
168b6cbf720SGianluca Guida /* Initial hash value H for SHA-256: */
169b6cbf720SGianluca Guida static const uint32_t sha256_initial_hash_value[8] = {
170b6cbf720SGianluca Guida 	0x6a09e667UL,
171b6cbf720SGianluca Guida 	0xbb67ae85UL,
172b6cbf720SGianluca Guida 	0x3c6ef372UL,
173b6cbf720SGianluca Guida 	0xa54ff53aUL,
174b6cbf720SGianluca Guida 	0x510e527fUL,
175b6cbf720SGianluca Guida 	0x9b05688cUL,
176b6cbf720SGianluca Guida 	0x1f83d9abUL,
177b6cbf720SGianluca Guida 	0x5be0cd19UL
178b6cbf720SGianluca Guida };
179b6cbf720SGianluca Guida 
180b6cbf720SGianluca Guida /* Hash constant words K for SHA-384 and SHA-512: */
181b6cbf720SGianluca Guida static const uint64_t K512[80] = {
182b6cbf720SGianluca Guida 	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
183b6cbf720SGianluca Guida 	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
184b6cbf720SGianluca Guida 	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
185b6cbf720SGianluca Guida 	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
186b6cbf720SGianluca Guida 	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
187b6cbf720SGianluca Guida 	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
188b6cbf720SGianluca Guida 	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
189b6cbf720SGianluca Guida 	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
190b6cbf720SGianluca Guida 	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
191b6cbf720SGianluca Guida 	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
192b6cbf720SGianluca Guida 	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
193b6cbf720SGianluca Guida 	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
194b6cbf720SGianluca Guida 	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
195b6cbf720SGianluca Guida 	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
196b6cbf720SGianluca Guida 	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
197b6cbf720SGianluca Guida 	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
198b6cbf720SGianluca Guida 	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
199b6cbf720SGianluca Guida 	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
200b6cbf720SGianluca Guida 	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
201b6cbf720SGianluca Guida 	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
202b6cbf720SGianluca Guida 	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
203b6cbf720SGianluca Guida 	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
204b6cbf720SGianluca Guida 	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
205b6cbf720SGianluca Guida 	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
206b6cbf720SGianluca Guida 	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
207b6cbf720SGianluca Guida 	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
208b6cbf720SGianluca Guida 	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
209b6cbf720SGianluca Guida 	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
210b6cbf720SGianluca Guida 	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
211b6cbf720SGianluca Guida 	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
212b6cbf720SGianluca Guida 	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
213b6cbf720SGianluca Guida 	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
214b6cbf720SGianluca Guida 	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
215b6cbf720SGianluca Guida 	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
216b6cbf720SGianluca Guida 	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
217b6cbf720SGianluca Guida 	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
218b6cbf720SGianluca Guida 	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
219b6cbf720SGianluca Guida 	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
220b6cbf720SGianluca Guida 	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
221b6cbf720SGianluca Guida 	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
222b6cbf720SGianluca Guida };
223b6cbf720SGianluca Guida 
224b6cbf720SGianluca Guida /* Initial hash value H for SHA-384 */
225b6cbf720SGianluca Guida static const uint64_t sha384_initial_hash_value[8] = {
226b6cbf720SGianluca Guida 	0xcbbb9d5dc1059ed8ULL,
227b6cbf720SGianluca Guida 	0x629a292a367cd507ULL,
228b6cbf720SGianluca Guida 	0x9159015a3070dd17ULL,
229b6cbf720SGianluca Guida 	0x152fecd8f70e5939ULL,
230b6cbf720SGianluca Guida 	0x67332667ffc00b31ULL,
231b6cbf720SGianluca Guida 	0x8eb44a8768581511ULL,
232b6cbf720SGianluca Guida 	0xdb0c2e0d64f98fa7ULL,
233b6cbf720SGianluca Guida 	0x47b5481dbefa4fa4ULL
234b6cbf720SGianluca Guida };
235b6cbf720SGianluca Guida 
236b6cbf720SGianluca Guida /* Initial hash value H for SHA-512 */
237b6cbf720SGianluca Guida static const uint64_t sha512_initial_hash_value[8] = {
238b6cbf720SGianluca Guida 	0x6a09e667f3bcc908ULL,
239b6cbf720SGianluca Guida 	0xbb67ae8584caa73bULL,
240b6cbf720SGianluca Guida 	0x3c6ef372fe94f82bULL,
241b6cbf720SGianluca Guida 	0xa54ff53a5f1d36f1ULL,
242b6cbf720SGianluca Guida 	0x510e527fade682d1ULL,
243b6cbf720SGianluca Guida 	0x9b05688c2b3e6c1fULL,
244b6cbf720SGianluca Guida 	0x1f83d9abfb41bd6bULL,
245b6cbf720SGianluca Guida 	0x5be0cd19137e2179ULL
246b6cbf720SGianluca Guida };
247b6cbf720SGianluca Guida 
248b6cbf720SGianluca Guida #if !defined(_KERNEL) && !defined(_STANDALONE)
249b6cbf720SGianluca Guida #if defined(__weak_alias)
__weak_alias(SHA224_Init,_SHA224_Init)250b6cbf720SGianluca Guida __weak_alias(SHA224_Init,_SHA224_Init)
251b6cbf720SGianluca Guida __weak_alias(SHA224_Update,_SHA224_Update)
252b6cbf720SGianluca Guida __weak_alias(SHA224_Final,_SHA224_Final)
253b6cbf720SGianluca Guida __weak_alias(SHA224_Transform,_SHA224_Transform)
254b6cbf720SGianluca Guida 
255b6cbf720SGianluca Guida __weak_alias(SHA256_Init,_SHA256_Init)
256b6cbf720SGianluca Guida __weak_alias(SHA256_Update,_SHA256_Update)
257b6cbf720SGianluca Guida __weak_alias(SHA256_Final,_SHA256_Final)
258b6cbf720SGianluca Guida __weak_alias(SHA256_Transform,_SHA256_Transform)
259b6cbf720SGianluca Guida 
260b6cbf720SGianluca Guida __weak_alias(SHA384_Init,_SHA384_Init)
261b6cbf720SGianluca Guida __weak_alias(SHA384_Update,_SHA384_Update)
262b6cbf720SGianluca Guida __weak_alias(SHA384_Final,_SHA384_Final)
263b6cbf720SGianluca Guida __weak_alias(SHA384_Transform,_SHA384_Transform)
264b6cbf720SGianluca Guida 
265b6cbf720SGianluca Guida __weak_alias(SHA512_Init,_SHA512_Init)
266b6cbf720SGianluca Guida __weak_alias(SHA512_Update,_SHA512_Update)
267b6cbf720SGianluca Guida __weak_alias(SHA512_Final,_SHA512_Final)
268b6cbf720SGianluca Guida __weak_alias(SHA512_Transform,_SHA512_Transform)
269b6cbf720SGianluca Guida #endif
270b6cbf720SGianluca Guida #endif
271b6cbf720SGianluca Guida 
272b6cbf720SGianluca Guida /*** SHA-256: *********************************************************/
273b6cbf720SGianluca Guida int
274b6cbf720SGianluca Guida SHA256_Init(SHA256_CTX *context)
275b6cbf720SGianluca Guida {
276b6cbf720SGianluca Guida 	if (context == NULL)
277b6cbf720SGianluca Guida 		return 1;
278b6cbf720SGianluca Guida 
279b6cbf720SGianluca Guida 	memcpy(context->state, sha256_initial_hash_value,
280b6cbf720SGianluca Guida 	    (size_t)(SHA256_DIGEST_LENGTH));
281b6cbf720SGianluca Guida 	memset(context->buffer, 0, (size_t)(SHA256_BLOCK_LENGTH));
282b6cbf720SGianluca Guida 	context->bitcount = 0;
283b6cbf720SGianluca Guida 
284b6cbf720SGianluca Guida 	return 1;
285b6cbf720SGianluca Guida }
286b6cbf720SGianluca Guida 
287b6cbf720SGianluca Guida #ifdef SHA2_UNROLL_TRANSFORM
288b6cbf720SGianluca Guida 
289b6cbf720SGianluca Guida /* Unrolled SHA-256 round macros: */
290b6cbf720SGianluca Guida 
291b6cbf720SGianluca Guida #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
29284d9c625SLionel Sambuc 	W256[j] = be32dec(data);		\
293b6cbf720SGianluca Guida 	++data;					\
294b6cbf720SGianluca Guida 	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
295b6cbf720SGianluca Guida              K256[j] + W256[j]; \
296b6cbf720SGianluca Guida 	(d) += T1; \
297b6cbf720SGianluca Guida 	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
298b6cbf720SGianluca Guida 	j++
299b6cbf720SGianluca Guida 
300b6cbf720SGianluca Guida #define ROUND256(a,b,c,d,e,f,g,h)	\
301b6cbf720SGianluca Guida 	s0 = W256[(j+1)&0x0f]; \
302b6cbf720SGianluca Guida 	s0 = sigma0_256(s0); \
303b6cbf720SGianluca Guida 	s1 = W256[(j+14)&0x0f]; \
304b6cbf720SGianluca Guida 	s1 = sigma1_256(s1); \
305b6cbf720SGianluca Guida 	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
306b6cbf720SGianluca Guida 	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
307b6cbf720SGianluca Guida 	(d) += T1; \
308b6cbf720SGianluca Guida 	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
309b6cbf720SGianluca Guida 	j++
310b6cbf720SGianluca Guida 
311b6cbf720SGianluca Guida void
SHA256_Transform(SHA256_CTX * context,const uint32_t * data)312b6cbf720SGianluca Guida SHA256_Transform(SHA256_CTX *context, const uint32_t *data)
313b6cbf720SGianluca Guida {
314b6cbf720SGianluca Guida 	uint32_t	a, b, c, d, e, f, g, h, s0, s1;
315b6cbf720SGianluca Guida 	uint32_t	T1, *W256;
316b6cbf720SGianluca Guida 	int		j;
317b6cbf720SGianluca Guida 
318b6cbf720SGianluca Guida 	W256 = (uint32_t *)context->buffer;
319b6cbf720SGianluca Guida 
320b6cbf720SGianluca Guida 	/* Initialize registers with the prev. intermediate value */
321b6cbf720SGianluca Guida 	a = context->state[0];
322b6cbf720SGianluca Guida 	b = context->state[1];
323b6cbf720SGianluca Guida 	c = context->state[2];
324b6cbf720SGianluca Guida 	d = context->state[3];
325b6cbf720SGianluca Guida 	e = context->state[4];
326b6cbf720SGianluca Guida 	f = context->state[5];
327b6cbf720SGianluca Guida 	g = context->state[6];
328b6cbf720SGianluca Guida 	h = context->state[7];
329b6cbf720SGianluca Guida 
330b6cbf720SGianluca Guida 	j = 0;
331b6cbf720SGianluca Guida 	do {
332b6cbf720SGianluca Guida 		/* Rounds 0 to 15 (unrolled): */
333b6cbf720SGianluca Guida 		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
334b6cbf720SGianluca Guida 		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
335b6cbf720SGianluca Guida 		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
336b6cbf720SGianluca Guida 		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
337b6cbf720SGianluca Guida 		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
338b6cbf720SGianluca Guida 		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
339b6cbf720SGianluca Guida 		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
340b6cbf720SGianluca Guida 		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
341b6cbf720SGianluca Guida 	} while (j < 16);
342b6cbf720SGianluca Guida 
343b6cbf720SGianluca Guida 	/* Now for the remaining rounds to 64: */
344b6cbf720SGianluca Guida 	do {
345b6cbf720SGianluca Guida 		ROUND256(a,b,c,d,e,f,g,h);
346b6cbf720SGianluca Guida 		ROUND256(h,a,b,c,d,e,f,g);
347b6cbf720SGianluca Guida 		ROUND256(g,h,a,b,c,d,e,f);
348b6cbf720SGianluca Guida 		ROUND256(f,g,h,a,b,c,d,e);
349b6cbf720SGianluca Guida 		ROUND256(e,f,g,h,a,b,c,d);
350b6cbf720SGianluca Guida 		ROUND256(d,e,f,g,h,a,b,c);
351b6cbf720SGianluca Guida 		ROUND256(c,d,e,f,g,h,a,b);
352b6cbf720SGianluca Guida 		ROUND256(b,c,d,e,f,g,h,a);
353b6cbf720SGianluca Guida 	} while (j < 64);
354b6cbf720SGianluca Guida 
355b6cbf720SGianluca Guida 	/* Compute the current intermediate hash value */
356b6cbf720SGianluca Guida 	context->state[0] += a;
357b6cbf720SGianluca Guida 	context->state[1] += b;
358b6cbf720SGianluca Guida 	context->state[2] += c;
359b6cbf720SGianluca Guida 	context->state[3] += d;
360b6cbf720SGianluca Guida 	context->state[4] += e;
361b6cbf720SGianluca Guida 	context->state[5] += f;
362b6cbf720SGianluca Guida 	context->state[6] += g;
363b6cbf720SGianluca Guida 	context->state[7] += h;
364b6cbf720SGianluca Guida 
365b6cbf720SGianluca Guida 	/* Clean up */
366b6cbf720SGianluca Guida 	a = b = c = d = e = f = g = h = T1 = 0;
367b6cbf720SGianluca Guida }
368b6cbf720SGianluca Guida 
369b6cbf720SGianluca Guida #else /* SHA2_UNROLL_TRANSFORM */
370b6cbf720SGianluca Guida 
371b6cbf720SGianluca Guida void
SHA256_Transform(SHA256_CTX * context,const uint32_t * data)372b6cbf720SGianluca Guida SHA256_Transform(SHA256_CTX *context, const uint32_t *data)
373b6cbf720SGianluca Guida {
374b6cbf720SGianluca Guida 	uint32_t	a, b, c, d, e, f, g, h, s0, s1;
375b6cbf720SGianluca Guida 	uint32_t	T1, T2, *W256;
376b6cbf720SGianluca Guida 	int		j;
377b6cbf720SGianluca Guida 
378b6cbf720SGianluca Guida 	W256 = (uint32_t *)(void *)context->buffer;
379b6cbf720SGianluca Guida 
380b6cbf720SGianluca Guida 	/* Initialize registers with the prev. intermediate value */
381b6cbf720SGianluca Guida 	a = context->state[0];
382b6cbf720SGianluca Guida 	b = context->state[1];
383b6cbf720SGianluca Guida 	c = context->state[2];
384b6cbf720SGianluca Guida 	d = context->state[3];
385b6cbf720SGianluca Guida 	e = context->state[4];
386b6cbf720SGianluca Guida 	f = context->state[5];
387b6cbf720SGianluca Guida 	g = context->state[6];
388b6cbf720SGianluca Guida 	h = context->state[7];
389b6cbf720SGianluca Guida 
390b6cbf720SGianluca Guida 	j = 0;
391b6cbf720SGianluca Guida 	do {
39284d9c625SLionel Sambuc 		W256[j] = be32dec(data);
393b6cbf720SGianluca Guida 		++data;
394b6cbf720SGianluca Guida 		/* Apply the SHA-256 compression function to update a..h */
395b6cbf720SGianluca Guida 		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
396b6cbf720SGianluca Guida 		T2 = Sigma0_256(a) + Maj(a, b, c);
397b6cbf720SGianluca Guida 		h = g;
398b6cbf720SGianluca Guida 		g = f;
399b6cbf720SGianluca Guida 		f = e;
400b6cbf720SGianluca Guida 		e = d + T1;
401b6cbf720SGianluca Guida 		d = c;
402b6cbf720SGianluca Guida 		c = b;
403b6cbf720SGianluca Guida 		b = a;
404b6cbf720SGianluca Guida 		a = T1 + T2;
405b6cbf720SGianluca Guida 
406b6cbf720SGianluca Guida 		j++;
407b6cbf720SGianluca Guida 	} while (j < 16);
408b6cbf720SGianluca Guida 
409b6cbf720SGianluca Guida 	do {
410b6cbf720SGianluca Guida 		/* Part of the message block expansion: */
411b6cbf720SGianluca Guida 		s0 = W256[(j+1)&0x0f];
412b6cbf720SGianluca Guida 		s0 = sigma0_256(s0);
413b6cbf720SGianluca Guida 		s1 = W256[(j+14)&0x0f];
414b6cbf720SGianluca Guida 		s1 = sigma1_256(s1);
415b6cbf720SGianluca Guida 
416b6cbf720SGianluca Guida 		/* Apply the SHA-256 compression function to update a..h */
417b6cbf720SGianluca Guida 		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
418b6cbf720SGianluca Guida 		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
419b6cbf720SGianluca Guida 		T2 = Sigma0_256(a) + Maj(a, b, c);
420b6cbf720SGianluca Guida 		h = g;
421b6cbf720SGianluca Guida 		g = f;
422b6cbf720SGianluca Guida 		f = e;
423b6cbf720SGianluca Guida 		e = d + T1;
424b6cbf720SGianluca Guida 		d = c;
425b6cbf720SGianluca Guida 		c = b;
426b6cbf720SGianluca Guida 		b = a;
427b6cbf720SGianluca Guida 		a = T1 + T2;
428b6cbf720SGianluca Guida 
429b6cbf720SGianluca Guida 		j++;
430b6cbf720SGianluca Guida 	} while (j < 64);
431b6cbf720SGianluca Guida 
432b6cbf720SGianluca Guida 	/* Compute the current intermediate hash value */
433b6cbf720SGianluca Guida 	context->state[0] += a;
434b6cbf720SGianluca Guida 	context->state[1] += b;
435b6cbf720SGianluca Guida 	context->state[2] += c;
436b6cbf720SGianluca Guida 	context->state[3] += d;
437b6cbf720SGianluca Guida 	context->state[4] += e;
438b6cbf720SGianluca Guida 	context->state[5] += f;
439b6cbf720SGianluca Guida 	context->state[6] += g;
440b6cbf720SGianluca Guida 	context->state[7] += h;
441b6cbf720SGianluca Guida 
442b6cbf720SGianluca Guida 	/* Clean up */
443b6cbf720SGianluca Guida 	a = b = c = d = e = f = g = h = T1 = T2 = 0;
444b6cbf720SGianluca Guida }
445b6cbf720SGianluca Guida 
446b6cbf720SGianluca Guida #endif /* SHA2_UNROLL_TRANSFORM */
447b6cbf720SGianluca Guida 
448b6cbf720SGianluca Guida int
SHA256_Update(SHA256_CTX * context,const uint8_t * data,size_t len)449b6cbf720SGianluca Guida SHA256_Update(SHA256_CTX *context, const uint8_t *data, size_t len)
450b6cbf720SGianluca Guida {
451b6cbf720SGianluca Guida 	unsigned int	freespace, usedspace;
452b6cbf720SGianluca Guida 
453b6cbf720SGianluca Guida 	if (len == 0) {
454b6cbf720SGianluca Guida 		/* Calling with no data is valid - we do nothing */
455b6cbf720SGianluca Guida 		return 1;
456b6cbf720SGianluca Guida 	}
457b6cbf720SGianluca Guida 
458b6cbf720SGianluca Guida 	usedspace = (unsigned int)((context->bitcount >> 3) %
459b6cbf720SGianluca Guida 				    SHA256_BLOCK_LENGTH);
460b6cbf720SGianluca Guida 	if (usedspace > 0) {
461b6cbf720SGianluca Guida 		/* Calculate how much free space is available in the buffer */
462b6cbf720SGianluca Guida 		freespace = SHA256_BLOCK_LENGTH - usedspace;
463b6cbf720SGianluca Guida 
464b6cbf720SGianluca Guida 		if (len >= freespace) {
465b6cbf720SGianluca Guida 			/* Fill the buffer completely and process it */
466b6cbf720SGianluca Guida 			memcpy(&context->buffer[usedspace], data,
467b6cbf720SGianluca Guida 			    (size_t)(freespace));
468b6cbf720SGianluca Guida 			context->bitcount += freespace << 3;
469b6cbf720SGianluca Guida 			len -= freespace;
470b6cbf720SGianluca Guida 			data += freespace;
471b6cbf720SGianluca Guida 			SHA256_Transform(context,
472b6cbf720SGianluca Guida 			    (uint32_t *)(void *)context->buffer);
473b6cbf720SGianluca Guida 		} else {
474b6cbf720SGianluca Guida 			/* The buffer is not yet full */
475b6cbf720SGianluca Guida 			memcpy(&context->buffer[usedspace], data, len);
476b6cbf720SGianluca Guida 			context->bitcount += len << 3;
477b6cbf720SGianluca Guida 			/* Clean up: */
478b6cbf720SGianluca Guida 			usedspace = freespace = 0;
479b6cbf720SGianluca Guida 			return 1;
480b6cbf720SGianluca Guida 		}
481b6cbf720SGianluca Guida 	}
482b6cbf720SGianluca Guida 	/*
483b6cbf720SGianluca Guida 	 * Process as many complete blocks as possible.
484b6cbf720SGianluca Guida 	 *
485b6cbf720SGianluca Guida 	 * Check alignment of the data pointer. If it is 32bit aligned,
486b6cbf720SGianluca Guida 	 * SHA256_Transform can be called directly on the data stream,
487b6cbf720SGianluca Guida 	 * otherwise enforce the alignment by copy into the buffer.
488b6cbf720SGianluca Guida 	 */
489b6cbf720SGianluca Guida 	if ((uintptr_t)data % 4 == 0) {
490b6cbf720SGianluca Guida 		while (len >= SHA256_BLOCK_LENGTH) {
491b6cbf720SGianluca Guida 			SHA256_Transform(context,
492b6cbf720SGianluca Guida 			    (const uint32_t *)(const void *)data);
493b6cbf720SGianluca Guida 			context->bitcount += SHA256_BLOCK_LENGTH << 3;
494b6cbf720SGianluca Guida 			len -= SHA256_BLOCK_LENGTH;
495b6cbf720SGianluca Guida 			data += SHA256_BLOCK_LENGTH;
496b6cbf720SGianluca Guida 		}
497b6cbf720SGianluca Guida 	} else {
498b6cbf720SGianluca Guida 		while (len >= SHA256_BLOCK_LENGTH) {
499b6cbf720SGianluca Guida 			memcpy(context->buffer, data, SHA256_BLOCK_LENGTH);
500b6cbf720SGianluca Guida 			SHA256_Transform(context,
501b6cbf720SGianluca Guida 			    (const uint32_t *)(const void *)context->buffer);
502b6cbf720SGianluca Guida 			context->bitcount += SHA256_BLOCK_LENGTH << 3;
503b6cbf720SGianluca Guida 			len -= SHA256_BLOCK_LENGTH;
504b6cbf720SGianluca Guida 			data += SHA256_BLOCK_LENGTH;
505b6cbf720SGianluca Guida 		}
506b6cbf720SGianluca Guida 	}
507b6cbf720SGianluca Guida 	if (len > 0) {
508b6cbf720SGianluca Guida 		/* There's left-overs, so save 'em */
509b6cbf720SGianluca Guida 		memcpy(context->buffer, data, len);
510b6cbf720SGianluca Guida 		context->bitcount += len << 3;
511b6cbf720SGianluca Guida 	}
512b6cbf720SGianluca Guida 	/* Clean up: */
513b6cbf720SGianluca Guida 	usedspace = freespace = 0;
514b6cbf720SGianluca Guida 
515b6cbf720SGianluca Guida 	return 1;
516b6cbf720SGianluca Guida }
517b6cbf720SGianluca Guida 
518b6cbf720SGianluca Guida static int
SHA224_256_Final(uint8_t digest[],SHA256_CTX * context,size_t len)519b6cbf720SGianluca Guida SHA224_256_Final(uint8_t digest[], SHA256_CTX *context, size_t len)
520b6cbf720SGianluca Guida {
521b6cbf720SGianluca Guida 	unsigned int	usedspace;
522b6cbf720SGianluca Guida 	size_t i;
523b6cbf720SGianluca Guida 
524b6cbf720SGianluca Guida 	/* If no digest buffer is passed, we don't bother doing this: */
525b6cbf720SGianluca Guida 	if (digest != NULL) {
526b6cbf720SGianluca Guida 		usedspace = (unsigned int)((context->bitcount >> 3) %
527b6cbf720SGianluca Guida 		    SHA256_BLOCK_LENGTH);
528b6cbf720SGianluca Guida 		context->bitcount = htobe64(context->bitcount);
529b6cbf720SGianluca Guida 		if (usedspace > 0) {
530b6cbf720SGianluca Guida 			/* Begin padding with a 1 bit: */
531b6cbf720SGianluca Guida 			context->buffer[usedspace++] = 0x80;
532b6cbf720SGianluca Guida 
533b6cbf720SGianluca Guida 			if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
534b6cbf720SGianluca Guida 				/* Set-up for the last transform: */
535b6cbf720SGianluca Guida 				memset(&context->buffer[usedspace], 0,
536b6cbf720SGianluca Guida 				    (size_t)(SHA256_SHORT_BLOCK_LENGTH -
537b6cbf720SGianluca Guida 				    usedspace));
538b6cbf720SGianluca Guida 			} else {
539b6cbf720SGianluca Guida 				if (usedspace < SHA256_BLOCK_LENGTH) {
540b6cbf720SGianluca Guida 					memset(&context->buffer[usedspace], 0,
541b6cbf720SGianluca Guida 					    (size_t)(SHA256_BLOCK_LENGTH -
542b6cbf720SGianluca Guida 					    usedspace));
543b6cbf720SGianluca Guida 				}
544b6cbf720SGianluca Guida 				/* Do second-to-last transform: */
545b6cbf720SGianluca Guida 				SHA256_Transform(context,
546b6cbf720SGianluca Guida 				    (uint32_t *)(void *)context->buffer);
547b6cbf720SGianluca Guida 
548b6cbf720SGianluca Guida 				/* And set-up for the last transform: */
549b6cbf720SGianluca Guida 				memset(context->buffer, 0,
550b6cbf720SGianluca Guida 				    (size_t)(SHA256_SHORT_BLOCK_LENGTH));
551b6cbf720SGianluca Guida 			}
552b6cbf720SGianluca Guida 		} else {
553b6cbf720SGianluca Guida 			/* Set-up for the last transform: */
554b6cbf720SGianluca Guida 			memset(context->buffer, 0,
555b6cbf720SGianluca Guida 			    (size_t)(SHA256_SHORT_BLOCK_LENGTH));
556b6cbf720SGianluca Guida 
557b6cbf720SGianluca Guida 			/* Begin padding with a 1 bit: */
558b6cbf720SGianluca Guida 			*context->buffer = 0x80;
559b6cbf720SGianluca Guida 		}
560b6cbf720SGianluca Guida 		/* Set the bit count: */
561b6cbf720SGianluca Guida 		memcpy(&context->buffer[SHA256_SHORT_BLOCK_LENGTH],
562b6cbf720SGianluca Guida 		    &context->bitcount, sizeof(context->bitcount));
563b6cbf720SGianluca Guida 
564b6cbf720SGianluca Guida 		/* Final transform: */
565b6cbf720SGianluca Guida 		SHA256_Transform(context, (uint32_t *)(void *)context->buffer);
566b6cbf720SGianluca Guida 
567b6cbf720SGianluca Guida 		for (i = 0; i < len / 4; i++)
568b6cbf720SGianluca Guida 			be32enc(digest + 4 * i, context->state[i]);
569b6cbf720SGianluca Guida 	}
570b6cbf720SGianluca Guida 
571b6cbf720SGianluca Guida 	/* Clean up state data: */
572b6cbf720SGianluca Guida 	memset(context, 0, sizeof(*context));
573b6cbf720SGianluca Guida 	usedspace = 0;
574b6cbf720SGianluca Guida 
575b6cbf720SGianluca Guida 	return 1;
576b6cbf720SGianluca Guida }
577b6cbf720SGianluca Guida 
578b6cbf720SGianluca Guida int
SHA256_Final(uint8_t digest[],SHA256_CTX * context)579b6cbf720SGianluca Guida SHA256_Final(uint8_t digest[], SHA256_CTX *context)
580b6cbf720SGianluca Guida {
581b6cbf720SGianluca Guida 	return SHA224_256_Final(digest, context, SHA256_DIGEST_LENGTH);
582b6cbf720SGianluca Guida }
583b6cbf720SGianluca Guida 
584b6cbf720SGianluca Guida /*** SHA-224: *********************************************************/
585b6cbf720SGianluca Guida int
SHA224_Init(SHA224_CTX * context)586b6cbf720SGianluca Guida SHA224_Init(SHA224_CTX *context)
587b6cbf720SGianluca Guida {
588b6cbf720SGianluca Guida 	if (context == NULL)
589b6cbf720SGianluca Guida 		return 1;
590b6cbf720SGianluca Guida 
591b6cbf720SGianluca Guida 	/* The state and buffer size are driven by SHA256, not by SHA224. */
592b6cbf720SGianluca Guida 	memcpy(context->state, sha224_initial_hash_value,
593b6cbf720SGianluca Guida 	    (size_t)(SHA256_DIGEST_LENGTH));
594b6cbf720SGianluca Guida 	memset(context->buffer, 0, (size_t)(SHA256_BLOCK_LENGTH));
595b6cbf720SGianluca Guida 	context->bitcount = 0;
596b6cbf720SGianluca Guida 
597b6cbf720SGianluca Guida 	return 1;
598b6cbf720SGianluca Guida }
599b6cbf720SGianluca Guida 
600b6cbf720SGianluca Guida int
SHA224_Update(SHA224_CTX * context,const uint8_t * data,size_t len)601b6cbf720SGianluca Guida SHA224_Update(SHA224_CTX *context, const uint8_t *data, size_t len)
602b6cbf720SGianluca Guida {
603b6cbf720SGianluca Guida 	return SHA256_Update((SHA256_CTX *)context, data, len);
604b6cbf720SGianluca Guida }
605b6cbf720SGianluca Guida 
606b6cbf720SGianluca Guida void
SHA224_Transform(SHA224_CTX * context,const uint32_t * data)607b6cbf720SGianluca Guida SHA224_Transform(SHA224_CTX *context, const uint32_t *data)
608b6cbf720SGianluca Guida {
609b6cbf720SGianluca Guida 	SHA256_Transform((SHA256_CTX *)context, data);
610b6cbf720SGianluca Guida }
611b6cbf720SGianluca Guida 
612b6cbf720SGianluca Guida int
SHA224_Final(uint8_t digest[],SHA224_CTX * context)613b6cbf720SGianluca Guida SHA224_Final(uint8_t digest[], SHA224_CTX *context)
614b6cbf720SGianluca Guida {
615b6cbf720SGianluca Guida 	return SHA224_256_Final(digest, (SHA256_CTX *)context,
616b6cbf720SGianluca Guida 	    SHA224_DIGEST_LENGTH);
617b6cbf720SGianluca Guida }
618b6cbf720SGianluca Guida 
619b6cbf720SGianluca Guida /*** SHA-512: *********************************************************/
620b6cbf720SGianluca Guida int
SHA512_Init(SHA512_CTX * context)621b6cbf720SGianluca Guida SHA512_Init(SHA512_CTX *context)
622b6cbf720SGianluca Guida {
623b6cbf720SGianluca Guida 	if (context == NULL)
624b6cbf720SGianluca Guida 		return 1;
625b6cbf720SGianluca Guida 
626b6cbf720SGianluca Guida 	memcpy(context->state, sha512_initial_hash_value,
627b6cbf720SGianluca Guida 	    (size_t)(SHA512_DIGEST_LENGTH));
628b6cbf720SGianluca Guida 	memset(context->buffer, 0, (size_t)(SHA512_BLOCK_LENGTH));
629b6cbf720SGianluca Guida 	context->bitcount[0] = context->bitcount[1] =  0;
630b6cbf720SGianluca Guida 
631b6cbf720SGianluca Guida 	return 1;
632b6cbf720SGianluca Guida }
633b6cbf720SGianluca Guida 
634b6cbf720SGianluca Guida #ifdef SHA2_UNROLL_TRANSFORM
635b6cbf720SGianluca Guida 
636b6cbf720SGianluca Guida /* Unrolled SHA-512 round macros: */
637b6cbf720SGianluca Guida #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
63884d9c625SLionel Sambuc 	W512[j] = be64dec(data);		\
639b6cbf720SGianluca Guida 	++data;					\
640b6cbf720SGianluca Guida 	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
641b6cbf720SGianluca Guida              K512[j] + W512[j]; \
642b6cbf720SGianluca Guida 	(d) += T1, \
643b6cbf720SGianluca Guida 	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
644b6cbf720SGianluca Guida 	j++
645b6cbf720SGianluca Guida 
646b6cbf720SGianluca Guida #define ROUND512(a,b,c,d,e,f,g,h)	\
647b6cbf720SGianluca Guida 	s0 = W512[(j+1)&0x0f]; \
648b6cbf720SGianluca Guida 	s0 = sigma0_512(s0); \
649b6cbf720SGianluca Guida 	s1 = W512[(j+14)&0x0f]; \
650b6cbf720SGianluca Guida 	s1 = sigma1_512(s1); \
651b6cbf720SGianluca Guida 	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
652b6cbf720SGianluca Guida              (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
653b6cbf720SGianluca Guida 	(d) += T1; \
654b6cbf720SGianluca Guida 	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
655b6cbf720SGianluca Guida 	j++
656b6cbf720SGianluca Guida 
657b6cbf720SGianluca Guida void
SHA512_Transform(SHA512_CTX * context,const uint64_t * data)658b6cbf720SGianluca Guida SHA512_Transform(SHA512_CTX *context, const uint64_t *data)
659b6cbf720SGianluca Guida {
660b6cbf720SGianluca Guida 	uint64_t	a, b, c, d, e, f, g, h, s0, s1;
661b6cbf720SGianluca Guida 	uint64_t	T1, *W512 = (uint64_t *)context->buffer;
662b6cbf720SGianluca Guida 	int		j;
663b6cbf720SGianluca Guida 
664b6cbf720SGianluca Guida 	/* Initialize registers with the prev. intermediate value */
665b6cbf720SGianluca Guida 	a = context->state[0];
666b6cbf720SGianluca Guida 	b = context->state[1];
667b6cbf720SGianluca Guida 	c = context->state[2];
668b6cbf720SGianluca Guida 	d = context->state[3];
669b6cbf720SGianluca Guida 	e = context->state[4];
670b6cbf720SGianluca Guida 	f = context->state[5];
671b6cbf720SGianluca Guida 	g = context->state[6];
672b6cbf720SGianluca Guida 	h = context->state[7];
673b6cbf720SGianluca Guida 
674b6cbf720SGianluca Guida 	j = 0;
675b6cbf720SGianluca Guida 	do {
676b6cbf720SGianluca Guida 		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
677b6cbf720SGianluca Guida 		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
678b6cbf720SGianluca Guida 		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
679b6cbf720SGianluca Guida 		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
680b6cbf720SGianluca Guida 		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
681b6cbf720SGianluca Guida 		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
682b6cbf720SGianluca Guida 		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
683b6cbf720SGianluca Guida 		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
684b6cbf720SGianluca Guida 	} while (j < 16);
685b6cbf720SGianluca Guida 
686b6cbf720SGianluca Guida 	/* Now for the remaining rounds up to 79: */
687b6cbf720SGianluca Guida 	do {
688b6cbf720SGianluca Guida 		ROUND512(a,b,c,d,e,f,g,h);
689b6cbf720SGianluca Guida 		ROUND512(h,a,b,c,d,e,f,g);
690b6cbf720SGianluca Guida 		ROUND512(g,h,a,b,c,d,e,f);
691b6cbf720SGianluca Guida 		ROUND512(f,g,h,a,b,c,d,e);
692b6cbf720SGianluca Guida 		ROUND512(e,f,g,h,a,b,c,d);
693b6cbf720SGianluca Guida 		ROUND512(d,e,f,g,h,a,b,c);
694b6cbf720SGianluca Guida 		ROUND512(c,d,e,f,g,h,a,b);
695b6cbf720SGianluca Guida 		ROUND512(b,c,d,e,f,g,h,a);
696b6cbf720SGianluca Guida 	} while (j < 80);
697b6cbf720SGianluca Guida 
698b6cbf720SGianluca Guida 	/* Compute the current intermediate hash value */
699b6cbf720SGianluca Guida 	context->state[0] += a;
700b6cbf720SGianluca Guida 	context->state[1] += b;
701b6cbf720SGianluca Guida 	context->state[2] += c;
702b6cbf720SGianluca Guida 	context->state[3] += d;
703b6cbf720SGianluca Guida 	context->state[4] += e;
704b6cbf720SGianluca Guida 	context->state[5] += f;
705b6cbf720SGianluca Guida 	context->state[6] += g;
706b6cbf720SGianluca Guida 	context->state[7] += h;
707b6cbf720SGianluca Guida 
708b6cbf720SGianluca Guida 	/* Clean up */
709b6cbf720SGianluca Guida 	a = b = c = d = e = f = g = h = T1 = 0;
710b6cbf720SGianluca Guida }
711b6cbf720SGianluca Guida 
712b6cbf720SGianluca Guida #else /* SHA2_UNROLL_TRANSFORM */
713b6cbf720SGianluca Guida 
714b6cbf720SGianluca Guida void
SHA512_Transform(SHA512_CTX * context,const uint64_t * data)715b6cbf720SGianluca Guida SHA512_Transform(SHA512_CTX *context, const uint64_t *data)
716b6cbf720SGianluca Guida {
717b6cbf720SGianluca Guida 	uint64_t	a, b, c, d, e, f, g, h, s0, s1;
718b6cbf720SGianluca Guida 	uint64_t	T1, T2, *W512 = (void *)context->buffer;
719b6cbf720SGianluca Guida 	int		j;
720b6cbf720SGianluca Guida 
721b6cbf720SGianluca Guida 	/* Initialize registers with the prev. intermediate value */
722b6cbf720SGianluca Guida 	a = context->state[0];
723b6cbf720SGianluca Guida 	b = context->state[1];
724b6cbf720SGianluca Guida 	c = context->state[2];
725b6cbf720SGianluca Guida 	d = context->state[3];
726b6cbf720SGianluca Guida 	e = context->state[4];
727b6cbf720SGianluca Guida 	f = context->state[5];
728b6cbf720SGianluca Guida 	g = context->state[6];
729b6cbf720SGianluca Guida 	h = context->state[7];
730b6cbf720SGianluca Guida 
731b6cbf720SGianluca Guida 	j = 0;
732b6cbf720SGianluca Guida 	do {
73384d9c625SLionel Sambuc 		W512[j] = be64dec(data);
734b6cbf720SGianluca Guida 		++data;
735b6cbf720SGianluca Guida 		/* Apply the SHA-512 compression function to update a..h */
736b6cbf720SGianluca Guida 		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
737b6cbf720SGianluca Guida 		T2 = Sigma0_512(a) + Maj(a, b, c);
738b6cbf720SGianluca Guida 		h = g;
739b6cbf720SGianluca Guida 		g = f;
740b6cbf720SGianluca Guida 		f = e;
741b6cbf720SGianluca Guida 		e = d + T1;
742b6cbf720SGianluca Guida 		d = c;
743b6cbf720SGianluca Guida 		c = b;
744b6cbf720SGianluca Guida 		b = a;
745b6cbf720SGianluca Guida 		a = T1 + T2;
746b6cbf720SGianluca Guida 
747b6cbf720SGianluca Guida 		j++;
748b6cbf720SGianluca Guida 	} while (j < 16);
749b6cbf720SGianluca Guida 
750b6cbf720SGianluca Guida 	do {
751b6cbf720SGianluca Guida 		/* Part of the message block expansion: */
752b6cbf720SGianluca Guida 		s0 = W512[(j+1)&0x0f];
753b6cbf720SGianluca Guida 		s0 = sigma0_512(s0);
754b6cbf720SGianluca Guida 		s1 = W512[(j+14)&0x0f];
755b6cbf720SGianluca Guida 		s1 =  sigma1_512(s1);
756b6cbf720SGianluca Guida 
757b6cbf720SGianluca Guida 		/* Apply the SHA-512 compression function to update a..h */
758b6cbf720SGianluca Guida 		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
759b6cbf720SGianluca Guida 		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
760b6cbf720SGianluca Guida 		T2 = Sigma0_512(a) + Maj(a, b, c);
761b6cbf720SGianluca Guida 		h = g;
762b6cbf720SGianluca Guida 		g = f;
763b6cbf720SGianluca Guida 		f = e;
764b6cbf720SGianluca Guida 		e = d + T1;
765b6cbf720SGianluca Guida 		d = c;
766b6cbf720SGianluca Guida 		c = b;
767b6cbf720SGianluca Guida 		b = a;
768b6cbf720SGianluca Guida 		a = T1 + T2;
769b6cbf720SGianluca Guida 
770b6cbf720SGianluca Guida 		j++;
771b6cbf720SGianluca Guida 	} while (j < 80);
772b6cbf720SGianluca Guida 
773b6cbf720SGianluca Guida 	/* Compute the current intermediate hash value */
774b6cbf720SGianluca Guida 	context->state[0] += a;
775b6cbf720SGianluca Guida 	context->state[1] += b;
776b6cbf720SGianluca Guida 	context->state[2] += c;
777b6cbf720SGianluca Guida 	context->state[3] += d;
778b6cbf720SGianluca Guida 	context->state[4] += e;
779b6cbf720SGianluca Guida 	context->state[5] += f;
780b6cbf720SGianluca Guida 	context->state[6] += g;
781b6cbf720SGianluca Guida 	context->state[7] += h;
782b6cbf720SGianluca Guida 
783b6cbf720SGianluca Guida 	/* Clean up */
784b6cbf720SGianluca Guida 	a = b = c = d = e = f = g = h = T1 = T2 = 0;
785b6cbf720SGianluca Guida }
786b6cbf720SGianluca Guida 
787b6cbf720SGianluca Guida #endif /* SHA2_UNROLL_TRANSFORM */
788b6cbf720SGianluca Guida 
789b6cbf720SGianluca Guida int
SHA512_Update(SHA512_CTX * context,const uint8_t * data,size_t len)790b6cbf720SGianluca Guida SHA512_Update(SHA512_CTX *context, const uint8_t *data, size_t len)
791b6cbf720SGianluca Guida {
792b6cbf720SGianluca Guida 	unsigned int	freespace, usedspace;
793b6cbf720SGianluca Guida 
794b6cbf720SGianluca Guida 	if (len == 0) {
795b6cbf720SGianluca Guida 		/* Calling with no data is valid - we do nothing */
796b6cbf720SGianluca Guida 		return 1;
797b6cbf720SGianluca Guida 	}
798b6cbf720SGianluca Guida 
799b6cbf720SGianluca Guida 	usedspace = (unsigned int)((context->bitcount[0] >> 3) %
800b6cbf720SGianluca Guida 	    SHA512_BLOCK_LENGTH);
801b6cbf720SGianluca Guida 	if (usedspace > 0) {
802b6cbf720SGianluca Guida 		/* Calculate how much free space is available in the buffer */
803b6cbf720SGianluca Guida 		freespace = SHA512_BLOCK_LENGTH - usedspace;
804b6cbf720SGianluca Guida 
805b6cbf720SGianluca Guida 		if (len >= freespace) {
806b6cbf720SGianluca Guida 			/* Fill the buffer completely and process it */
807b6cbf720SGianluca Guida 			memcpy(&context->buffer[usedspace], data,
808b6cbf720SGianluca Guida 			    (size_t)(freespace));
809b6cbf720SGianluca Guida 			ADDINC128(context->bitcount, freespace << 3);
810b6cbf720SGianluca Guida 			len -= freespace;
811b6cbf720SGianluca Guida 			data += freespace;
812b6cbf720SGianluca Guida 			SHA512_Transform(context,
813b6cbf720SGianluca Guida 			    (uint64_t *)(void *)context->buffer);
814b6cbf720SGianluca Guida 		} else {
815b6cbf720SGianluca Guida 			/* The buffer is not yet full */
816b6cbf720SGianluca Guida 			memcpy(&context->buffer[usedspace], data, len);
817b6cbf720SGianluca Guida 			ADDINC128(context->bitcount, len << 3);
818b6cbf720SGianluca Guida 			/* Clean up: */
819b6cbf720SGianluca Guida 			usedspace = freespace = 0;
820b6cbf720SGianluca Guida 			return 1;
821b6cbf720SGianluca Guida 		}
822b6cbf720SGianluca Guida 	}
823b6cbf720SGianluca Guida 	/*
824b6cbf720SGianluca Guida 	 * Process as many complete blocks as possible.
825b6cbf720SGianluca Guida 	 *
826b6cbf720SGianluca Guida 	 * Check alignment of the data pointer. If it is 64bit aligned,
827b6cbf720SGianluca Guida 	 * SHA512_Transform can be called directly on the data stream,
828b6cbf720SGianluca Guida 	 * otherwise enforce the alignment by copy into the buffer.
829b6cbf720SGianluca Guida 	 */
830b6cbf720SGianluca Guida 	if ((uintptr_t)data % 8 == 0) {
831b6cbf720SGianluca Guida 		while (len >= SHA512_BLOCK_LENGTH) {
832b6cbf720SGianluca Guida 			SHA512_Transform(context,
833b6cbf720SGianluca Guida 			    (const uint64_t*)(const void *)data);
834b6cbf720SGianluca Guida 			ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
835b6cbf720SGianluca Guida 			len -= SHA512_BLOCK_LENGTH;
836b6cbf720SGianluca Guida 			data += SHA512_BLOCK_LENGTH;
837b6cbf720SGianluca Guida 		}
838b6cbf720SGianluca Guida 	} else {
839b6cbf720SGianluca Guida 		while (len >= SHA512_BLOCK_LENGTH) {
840b6cbf720SGianluca Guida 			memcpy(context->buffer, data, SHA512_BLOCK_LENGTH);
841b6cbf720SGianluca Guida 			SHA512_Transform(context,
842b6cbf720SGianluca Guida 			    (const void *)context->buffer);
843b6cbf720SGianluca Guida 			ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
844b6cbf720SGianluca Guida 			len -= SHA512_BLOCK_LENGTH;
845b6cbf720SGianluca Guida 			data += SHA512_BLOCK_LENGTH;
846b6cbf720SGianluca Guida 		}
847b6cbf720SGianluca Guida 	}
848b6cbf720SGianluca Guida 	if (len > 0) {
849b6cbf720SGianluca Guida 		/* There's left-overs, so save 'em */
850b6cbf720SGianluca Guida 		memcpy(context->buffer, data, len);
851b6cbf720SGianluca Guida 		ADDINC128(context->bitcount, len << 3);
852b6cbf720SGianluca Guida 	}
853b6cbf720SGianluca Guida 	/* Clean up: */
854b6cbf720SGianluca Guida 	usedspace = freespace = 0;
855b6cbf720SGianluca Guida 
856b6cbf720SGianluca Guida 	return 1;
857b6cbf720SGianluca Guida }
858b6cbf720SGianluca Guida 
859b6cbf720SGianluca Guida static void
SHA512_Last(SHA512_CTX * context)860b6cbf720SGianluca Guida SHA512_Last(SHA512_CTX *context)
861b6cbf720SGianluca Guida {
862b6cbf720SGianluca Guida 	unsigned int	usedspace;
863b6cbf720SGianluca Guida 
864b6cbf720SGianluca Guida 	usedspace = (unsigned int)((context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH);
865b6cbf720SGianluca Guida 	context->bitcount[0] = htobe64(context->bitcount[0]);
866b6cbf720SGianluca Guida 	context->bitcount[1] = htobe64(context->bitcount[1]);
867b6cbf720SGianluca Guida 	if (usedspace > 0) {
868b6cbf720SGianluca Guida 		/* Begin padding with a 1 bit: */
869b6cbf720SGianluca Guida 		context->buffer[usedspace++] = 0x80;
870b6cbf720SGianluca Guida 
871b6cbf720SGianluca Guida 		if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
872b6cbf720SGianluca Guida 			/* Set-up for the last transform: */
873b6cbf720SGianluca Guida 			memset(&context->buffer[usedspace], 0,
874b6cbf720SGianluca Guida 			    (size_t)(SHA512_SHORT_BLOCK_LENGTH - usedspace));
875b6cbf720SGianluca Guida 		} else {
876b6cbf720SGianluca Guida 			if (usedspace < SHA512_BLOCK_LENGTH) {
877b6cbf720SGianluca Guida 				memset(&context->buffer[usedspace], 0,
878b6cbf720SGianluca Guida 				    (size_t)(SHA512_BLOCK_LENGTH - usedspace));
879b6cbf720SGianluca Guida 			}
880b6cbf720SGianluca Guida 			/* Do second-to-last transform: */
881b6cbf720SGianluca Guida 			SHA512_Transform(context,
882b6cbf720SGianluca Guida 			    (uint64_t *)(void *)context->buffer);
883b6cbf720SGianluca Guida 
884b6cbf720SGianluca Guida 			/* And set-up for the last transform: */
885b6cbf720SGianluca Guida 			memset(context->buffer, 0,
886b6cbf720SGianluca Guida 			    (size_t)(SHA512_BLOCK_LENGTH - 2));
887b6cbf720SGianluca Guida 		}
888b6cbf720SGianluca Guida 	} else {
889b6cbf720SGianluca Guida 		/* Prepare for final transform: */
890b6cbf720SGianluca Guida 		memset(context->buffer, 0, (size_t)(SHA512_SHORT_BLOCK_LENGTH));
891b6cbf720SGianluca Guida 
892b6cbf720SGianluca Guida 		/* Begin padding with a 1 bit: */
893b6cbf720SGianluca Guida 		*context->buffer = 0x80;
894b6cbf720SGianluca Guida 	}
895b6cbf720SGianluca Guida 	/* Store the length of input data (in bits): */
896b6cbf720SGianluca Guida 	memcpy(&context->buffer[SHA512_SHORT_BLOCK_LENGTH],
897b6cbf720SGianluca Guida 	    &context->bitcount[1], sizeof(context->bitcount[1]));
898b6cbf720SGianluca Guida 	memcpy(&context->buffer[SHA512_SHORT_BLOCK_LENGTH + 8],
899b6cbf720SGianluca Guida 	    &context->bitcount[0], sizeof(context->bitcount[0]));
900b6cbf720SGianluca Guida 
901b6cbf720SGianluca Guida 	/* Final transform: */
902b6cbf720SGianluca Guida 	SHA512_Transform(context, (uint64_t *)(void *)context->buffer);
903b6cbf720SGianluca Guida }
904b6cbf720SGianluca Guida 
905b6cbf720SGianluca Guida int
SHA512_Final(uint8_t digest[],SHA512_CTX * context)906b6cbf720SGianluca Guida SHA512_Final(uint8_t digest[], SHA512_CTX *context)
907b6cbf720SGianluca Guida {
908b6cbf720SGianluca Guida 	size_t i;
909b6cbf720SGianluca Guida 
910b6cbf720SGianluca Guida 	/* If no digest buffer is passed, we don't bother doing this: */
911b6cbf720SGianluca Guida 	if (digest != NULL) {
912b6cbf720SGianluca Guida 		SHA512_Last(context);
913b6cbf720SGianluca Guida 
914b6cbf720SGianluca Guida 		/* Save the hash data for output: */
915b6cbf720SGianluca Guida 		for (i = 0; i < 8; ++i)
916b6cbf720SGianluca Guida 			be64enc(digest + 8 * i, context->state[i]);
917b6cbf720SGianluca Guida 	}
918b6cbf720SGianluca Guida 
919b6cbf720SGianluca Guida 	/* Zero out state data */
920b6cbf720SGianluca Guida 	memset(context, 0, sizeof(*context));
921b6cbf720SGianluca Guida 
922b6cbf720SGianluca Guida 	return 1;
923b6cbf720SGianluca Guida }
924b6cbf720SGianluca Guida 
925b6cbf720SGianluca Guida /*** SHA-384: *********************************************************/
926b6cbf720SGianluca Guida int
SHA384_Init(SHA384_CTX * context)927b6cbf720SGianluca Guida SHA384_Init(SHA384_CTX *context)
928b6cbf720SGianluca Guida {
929b6cbf720SGianluca Guida 	if (context == NULL)
930b6cbf720SGianluca Guida 		return 1;
931b6cbf720SGianluca Guida 
932b6cbf720SGianluca Guida 	memcpy(context->state, sha384_initial_hash_value,
933b6cbf720SGianluca Guida 	    (size_t)(SHA512_DIGEST_LENGTH));
934b6cbf720SGianluca Guida 	memset(context->buffer, 0, (size_t)(SHA384_BLOCK_LENGTH));
935b6cbf720SGianluca Guida 	context->bitcount[0] = context->bitcount[1] = 0;
936b6cbf720SGianluca Guida 
937b6cbf720SGianluca Guida 	return 1;
938b6cbf720SGianluca Guida }
939b6cbf720SGianluca Guida 
940b6cbf720SGianluca Guida int
SHA384_Update(SHA384_CTX * context,const uint8_t * data,size_t len)941b6cbf720SGianluca Guida SHA384_Update(SHA384_CTX *context, const uint8_t *data, size_t len)
942b6cbf720SGianluca Guida {
943b6cbf720SGianluca Guida 	return SHA512_Update((SHA512_CTX *)context, data, len);
944b6cbf720SGianluca Guida }
945b6cbf720SGianluca Guida 
946b6cbf720SGianluca Guida void
SHA384_Transform(SHA512_CTX * context,const uint64_t * data)947b6cbf720SGianluca Guida SHA384_Transform(SHA512_CTX *context, const uint64_t *data)
948b6cbf720SGianluca Guida {
949b6cbf720SGianluca Guida 	SHA512_Transform((SHA512_CTX *)context, data);
950b6cbf720SGianluca Guida }
951b6cbf720SGianluca Guida 
952b6cbf720SGianluca Guida int
SHA384_Final(uint8_t digest[],SHA384_CTX * context)953b6cbf720SGianluca Guida SHA384_Final(uint8_t digest[], SHA384_CTX *context)
954b6cbf720SGianluca Guida {
955b6cbf720SGianluca Guida 	size_t i;
956b6cbf720SGianluca Guida 
957b6cbf720SGianluca Guida 	/* If no digest buffer is passed, we don't bother doing this: */
958b6cbf720SGianluca Guida 	if (digest != NULL) {
959b6cbf720SGianluca Guida 		SHA512_Last((SHA512_CTX *)context);
960b6cbf720SGianluca Guida 
961b6cbf720SGianluca Guida 		/* Save the hash data for output: */
962b6cbf720SGianluca Guida 		for (i = 0; i < 6; ++i)
963b6cbf720SGianluca Guida 			be64enc(digest + 8 * i, context->state[i]);
964b6cbf720SGianluca Guida 	}
965b6cbf720SGianluca Guida 
966b6cbf720SGianluca Guida 	/* Zero out state data */
967b6cbf720SGianluca Guida 	memset(context, 0, sizeof(*context));
968b6cbf720SGianluca Guida 
969b6cbf720SGianluca Guida 	return 1;
970b6cbf720SGianluca Guida }
971