1*f8570f8aSmrg /* $NetBSD: sha2.c,v 1.5 2023/08/01 07:04:14 mrg Exp $ */
225f78d91Sagc /* $KAME: sha2.c,v 1.9 2003/07/20 00:28:38 itojun Exp $ */
325f78d91Sagc
425f78d91Sagc /*
525f78d91Sagc * sha2.c
625f78d91Sagc *
725f78d91Sagc * Version 1.0.0beta1
825f78d91Sagc *
925f78d91Sagc * Written by Aaron D. Gifford <me@aarongifford.com>
1025f78d91Sagc *
1125f78d91Sagc * Copyright 2000 Aaron D. Gifford. All rights reserved.
1225f78d91Sagc *
1325f78d91Sagc * Redistribution and use in source and binary forms, with or without
1425f78d91Sagc * modification, are permitted provided that the following conditions
1525f78d91Sagc * are met:
1625f78d91Sagc * 1. Redistributions of source code must retain the above copyright
1725f78d91Sagc * notice, this list of conditions and the following disclaimer.
1825f78d91Sagc * 2. Redistributions in binary form must reproduce the above copyright
1925f78d91Sagc * notice, this list of conditions and the following disclaimer in the
2025f78d91Sagc * documentation and/or other materials provided with the distribution.
2125f78d91Sagc * 3. Neither the name of the copyright holder nor the names of contributors
2225f78d91Sagc * may be used to endorse or promote products derived from this software
2325f78d91Sagc * without specific prior written permission.
2425f78d91Sagc *
2525f78d91Sagc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
2625f78d91Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2725f78d91Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2825f78d91Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
2925f78d91Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3025f78d91Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3125f78d91Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3225f78d91Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3325f78d91Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3425f78d91Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3525f78d91Sagc * SUCH DAMAGE.
3625f78d91Sagc *
3725f78d91Sagc */
3825f78d91Sagc
3925f78d91Sagc #include <sys/types.h>
4025f78d91Sagc
4125f78d91Sagc #include <inttypes.h>
4225f78d91Sagc #include <string.h>
4325f78d91Sagc
4425f78d91Sagc #include "sha2.h"
4525f78d91Sagc
4625f78d91Sagc # undef htobe32
4725f78d91Sagc # undef htobe64
4825f78d91Sagc # undef be32toh
4925f78d91Sagc # undef be64toh
5025f78d91Sagc
51fd2346d6Schristos #ifndef __CAST
5225f78d91Sagc #define __CAST(__dt, __st) ((__dt)(__st)) /* srsly? */
53fd2346d6Schristos #endif
5425f78d91Sagc
5525f78d91Sagc static __inline void
be32encode(void * buf,uint32_t u)5625f78d91Sagc be32encode(void *buf, uint32_t u)
5725f78d91Sagc {
5825f78d91Sagc uint8_t *p = __CAST(uint8_t *, buf);
5925f78d91Sagc
6025f78d91Sagc p[0] = __CAST(uint8_t, ((u >> 24) & 0xff));
6125f78d91Sagc p[1] = __CAST(uint8_t, ((u >> 16) & 0xff));
6225f78d91Sagc p[2] = __CAST(uint8_t, ((u >> 8) & 0xff));
6325f78d91Sagc p[3] = __CAST(uint8_t, (u & 0xff));
6425f78d91Sagc }
6525f78d91Sagc
6625f78d91Sagc static __inline void
be64encode(void * buf,uint64_t u)6725f78d91Sagc be64encode(void *buf, uint64_t u)
6825f78d91Sagc {
6925f78d91Sagc uint8_t *p = __CAST(uint8_t *, buf);
7025f78d91Sagc
7125f78d91Sagc be32encode(p, __CAST(uint32_t, (u >> 32)));
7225f78d91Sagc be32encode(p + 4, __CAST(uint32_t, (u & 0xffffffffULL)));
7325f78d91Sagc }
7425f78d91Sagc
7525f78d91Sagc static uint32_t
htobe32(uint32_t x)7625f78d91Sagc htobe32(uint32_t x)
7725f78d91Sagc {
7825f78d91Sagc uint8_t p[4];
7925f78d91Sagc memcpy(p, &x, 4);
8025f78d91Sagc
81f57bc4a2Skamil return (((uint32_t)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
8225f78d91Sagc }
8325f78d91Sagc
8425f78d91Sagc static uint64_t
htobe64(uint64_t x)8525f78d91Sagc htobe64(uint64_t x)
8625f78d91Sagc {
8725f78d91Sagc uint8_t p[8];
8825f78d91Sagc uint32_t u, v;
8925f78d91Sagc memcpy(p, &x, 8);
9025f78d91Sagc
91f57bc4a2Skamil u = (((uint32_t)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
92f57bc4a2Skamil v = (((uint32_t)p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]);
9325f78d91Sagc
9425f78d91Sagc return ((((uint64_t)u) << 32) | v);
9525f78d91Sagc }
9625f78d91Sagc
9725f78d91Sagc static uint32_t
be32toh(uint32_t x)9825f78d91Sagc be32toh(uint32_t x)
9925f78d91Sagc {
10025f78d91Sagc return htobe32(x);
10125f78d91Sagc }
10225f78d91Sagc
10325f78d91Sagc static uint64_t
be64toh(uint64_t x)10425f78d91Sagc be64toh(uint64_t x)
10525f78d91Sagc {
10625f78d91Sagc return htobe64(x);
10725f78d91Sagc }
10825f78d91Sagc
10925f78d91Sagc /*** SHA-256/384/512 Various Length Definitions ***********************/
11025f78d91Sagc /* NOTE: Most of these are in sha2.h */
11125f78d91Sagc #define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
11225f78d91Sagc #define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16)
11325f78d91Sagc #define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
11425f78d91Sagc
11525f78d91Sagc /*
11625f78d91Sagc * Macro for incrementally adding the unsigned 64-bit integer n to the
11725f78d91Sagc * unsigned 128-bit integer (represented using a two-element array of
11825f78d91Sagc * 64-bit words):
11925f78d91Sagc */
12025f78d91Sagc #define ADDINC128(w,n) { \
12125f78d91Sagc (w)[0] += (uint64_t)(n); \
12225f78d91Sagc if ((w)[0] < (n)) { \
12325f78d91Sagc (w)[1]++; \
12425f78d91Sagc } \
12525f78d91Sagc }
12625f78d91Sagc
12725f78d91Sagc /*** THE SIX LOGICAL FUNCTIONS ****************************************/
12825f78d91Sagc /*
12925f78d91Sagc * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
13025f78d91Sagc *
13125f78d91Sagc * NOTE: The naming of R and S appears backwards here (R is a SHIFT and
13225f78d91Sagc * S is a ROTATION) because the SHA-256/384/512 description document
13325f78d91Sagc * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
13425f78d91Sagc * same "backwards" definition.
13525f78d91Sagc */
13625f78d91Sagc /* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
13725f78d91Sagc #define R(b,x) ((x) >> (b))
13825f78d91Sagc /* 32-bit Rotate-right (used in SHA-256): */
13925f78d91Sagc #define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
14025f78d91Sagc /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
14125f78d91Sagc #define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
14225f78d91Sagc
14325f78d91Sagc /* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
14425f78d91Sagc #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
14525f78d91Sagc #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
14625f78d91Sagc
14725f78d91Sagc /* Four of six logical functions used in SHA-256: */
14825f78d91Sagc #define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x)))
14925f78d91Sagc #define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x)))
15025f78d91Sagc #define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x)))
15125f78d91Sagc #define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
15225f78d91Sagc
15325f78d91Sagc /* Four of six logical functions used in SHA-384 and SHA-512: */
15425f78d91Sagc #define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
15525f78d91Sagc #define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
15625f78d91Sagc #define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x)))
15725f78d91Sagc #define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x)))
15825f78d91Sagc
15925f78d91Sagc /*** INTERNAL FUNCTION PROTOTYPES *************************************/
16025f78d91Sagc /* NOTE: These should not be accessed directly from outside this
16125f78d91Sagc * library -- they are intended for private internal visibility/use
16225f78d91Sagc * only.
16325f78d91Sagc */
164dd98b26dSagc static void netpgpv_SHA512_Last(NETPGPV_SHA512_CTX *);
165dd98b26dSagc void netpgpv_SHA224_Transform(NETPGPV_SHA224_CTX *, const uint32_t*);
166dd98b26dSagc void netpgpv_SHA256_Transform(NETPGPV_SHA256_CTX *, const uint32_t*);
167dd98b26dSagc void netpgpv_SHA384_Transform(NETPGPV_SHA384_CTX *, const uint64_t*);
168dd98b26dSagc void netpgpv_SHA512_Transform(NETPGPV_SHA512_CTX *, const uint64_t*);
16925f78d91Sagc
17025f78d91Sagc
17125f78d91Sagc /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
17225f78d91Sagc /* Hash constant words K for SHA-256: */
17325f78d91Sagc static const uint32_t K256[64] = {
17425f78d91Sagc 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
17525f78d91Sagc 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
17625f78d91Sagc 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
17725f78d91Sagc 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
17825f78d91Sagc 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
17925f78d91Sagc 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
18025f78d91Sagc 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
18125f78d91Sagc 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
18225f78d91Sagc 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
18325f78d91Sagc 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
18425f78d91Sagc 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
18525f78d91Sagc 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
18625f78d91Sagc 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
18725f78d91Sagc 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
18825f78d91Sagc 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
18925f78d91Sagc 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
19025f78d91Sagc };
19125f78d91Sagc
19225f78d91Sagc /* Initial hash value H for SHA-224: */
19325f78d91Sagc static const uint32_t sha224_initial_hash_value[8] = {
19425f78d91Sagc 0xc1059ed8UL,
19525f78d91Sagc 0x367cd507UL,
19625f78d91Sagc 0x3070dd17UL,
19725f78d91Sagc 0xf70e5939UL,
19825f78d91Sagc 0xffc00b31UL,
19925f78d91Sagc 0x68581511UL,
20025f78d91Sagc 0x64f98fa7UL,
20125f78d91Sagc 0xbefa4fa4UL
20225f78d91Sagc };
20325f78d91Sagc
20425f78d91Sagc /* Initial hash value H for SHA-256: */
20525f78d91Sagc static const uint32_t sha256_initial_hash_value[8] = {
20625f78d91Sagc 0x6a09e667UL,
20725f78d91Sagc 0xbb67ae85UL,
20825f78d91Sagc 0x3c6ef372UL,
20925f78d91Sagc 0xa54ff53aUL,
21025f78d91Sagc 0x510e527fUL,
21125f78d91Sagc 0x9b05688cUL,
21225f78d91Sagc 0x1f83d9abUL,
21325f78d91Sagc 0x5be0cd19UL
21425f78d91Sagc };
21525f78d91Sagc
21625f78d91Sagc /* Hash constant words K for SHA-384 and SHA-512: */
21725f78d91Sagc static const uint64_t K512[80] = {
21825f78d91Sagc 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
21925f78d91Sagc 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
22025f78d91Sagc 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
22125f78d91Sagc 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
22225f78d91Sagc 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
22325f78d91Sagc 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
22425f78d91Sagc 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
22525f78d91Sagc 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
22625f78d91Sagc 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
22725f78d91Sagc 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
22825f78d91Sagc 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
22925f78d91Sagc 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
23025f78d91Sagc 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
23125f78d91Sagc 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
23225f78d91Sagc 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
23325f78d91Sagc 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
23425f78d91Sagc 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
23525f78d91Sagc 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
23625f78d91Sagc 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
23725f78d91Sagc 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
23825f78d91Sagc 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
23925f78d91Sagc 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
24025f78d91Sagc 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
24125f78d91Sagc 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
24225f78d91Sagc 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
24325f78d91Sagc 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
24425f78d91Sagc 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
24525f78d91Sagc 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
24625f78d91Sagc 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
24725f78d91Sagc 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
24825f78d91Sagc 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
24925f78d91Sagc 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
25025f78d91Sagc 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
25125f78d91Sagc 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
25225f78d91Sagc 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
25325f78d91Sagc 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
25425f78d91Sagc 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
25525f78d91Sagc 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
25625f78d91Sagc 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
25725f78d91Sagc 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
25825f78d91Sagc };
25925f78d91Sagc
26025f78d91Sagc /* Initial hash value H for SHA-384 */
26125f78d91Sagc static const uint64_t sha384_initial_hash_value[8] = {
26225f78d91Sagc 0xcbbb9d5dc1059ed8ULL,
26325f78d91Sagc 0x629a292a367cd507ULL,
26425f78d91Sagc 0x9159015a3070dd17ULL,
26525f78d91Sagc 0x152fecd8f70e5939ULL,
26625f78d91Sagc 0x67332667ffc00b31ULL,
26725f78d91Sagc 0x8eb44a8768581511ULL,
26825f78d91Sagc 0xdb0c2e0d64f98fa7ULL,
26925f78d91Sagc 0x47b5481dbefa4fa4ULL
27025f78d91Sagc };
27125f78d91Sagc
27225f78d91Sagc /* Initial hash value H for SHA-512 */
27325f78d91Sagc static const uint64_t sha512_initial_hash_value[8] = {
27425f78d91Sagc 0x6a09e667f3bcc908ULL,
27525f78d91Sagc 0xbb67ae8584caa73bULL,
27625f78d91Sagc 0x3c6ef372fe94f82bULL,
27725f78d91Sagc 0xa54ff53a5f1d36f1ULL,
27825f78d91Sagc 0x510e527fade682d1ULL,
27925f78d91Sagc 0x9b05688c2b3e6c1fULL,
28025f78d91Sagc 0x1f83d9abfb41bd6bULL,
28125f78d91Sagc 0x5be0cd19137e2179ULL
28225f78d91Sagc };
28325f78d91Sagc
28425f78d91Sagc /*** SHA-256: *********************************************************/
28525f78d91Sagc int
netpgpv_SHA256_Init(NETPGPV_SHA256_CTX * context)286dd98b26dSagc netpgpv_SHA256_Init(NETPGPV_SHA256_CTX *context)
28725f78d91Sagc {
28825f78d91Sagc if (context == NULL)
28925f78d91Sagc return 1;
29025f78d91Sagc
29125f78d91Sagc memcpy(context->state, sha256_initial_hash_value,
29225f78d91Sagc (size_t)(SHA256_DIGEST_LENGTH));
29325f78d91Sagc memset(context->buffer, 0, (size_t)(SHA256_BLOCK_LENGTH));
29425f78d91Sagc context->bitcount = 0;
29525f78d91Sagc
29625f78d91Sagc return 1;
29725f78d91Sagc }
29825f78d91Sagc
29925f78d91Sagc #ifdef SHA2_UNROLL_TRANSFORM
30025f78d91Sagc
30125f78d91Sagc /* Unrolled SHA-256 round macros: */
30225f78d91Sagc
30325f78d91Sagc #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
30425f78d91Sagc W256[j] = be32toh(*data); \
30525f78d91Sagc ++data; \
30625f78d91Sagc T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
30725f78d91Sagc K256[j] + W256[j]; \
30825f78d91Sagc (d) += T1; \
30925f78d91Sagc (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
31025f78d91Sagc j++
31125f78d91Sagc
31225f78d91Sagc #define ROUND256(a,b,c,d,e,f,g,h) \
31325f78d91Sagc s0 = W256[(j+1)&0x0f]; \
31425f78d91Sagc s0 = sigma0_256(s0); \
31525f78d91Sagc s1 = W256[(j+14)&0x0f]; \
31625f78d91Sagc s1 = sigma1_256(s1); \
31725f78d91Sagc T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
31825f78d91Sagc (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
31925f78d91Sagc (d) += T1; \
32025f78d91Sagc (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
32125f78d91Sagc j++
32225f78d91Sagc
32325f78d91Sagc void
netpgpv_SHA256_Transform(NETPGPV_SHA256_CTX * context,const uint32_t * data)324dd98b26dSagc netpgpv_SHA256_Transform(NETPGPV_SHA256_CTX *context, const uint32_t *data)
32525f78d91Sagc {
32625f78d91Sagc uint32_t a, b, c, d, e, f, g, h, s0, s1;
32725f78d91Sagc uint32_t T1, *W256;
32825f78d91Sagc int j;
32925f78d91Sagc
33025f78d91Sagc W256 = (uint32_t *)context->buffer;
33125f78d91Sagc
33225f78d91Sagc /* Initialize registers with the prev. intermediate value */
33325f78d91Sagc a = context->state[0];
33425f78d91Sagc b = context->state[1];
33525f78d91Sagc c = context->state[2];
33625f78d91Sagc d = context->state[3];
33725f78d91Sagc e = context->state[4];
33825f78d91Sagc f = context->state[5];
33925f78d91Sagc g = context->state[6];
34025f78d91Sagc h = context->state[7];
34125f78d91Sagc
34225f78d91Sagc j = 0;
34325f78d91Sagc do {
34425f78d91Sagc /* Rounds 0 to 15 (unrolled): */
34525f78d91Sagc ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
34625f78d91Sagc ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
34725f78d91Sagc ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
34825f78d91Sagc ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
34925f78d91Sagc ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
35025f78d91Sagc ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
35125f78d91Sagc ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
35225f78d91Sagc ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
35325f78d91Sagc } while (j < 16);
35425f78d91Sagc
35525f78d91Sagc /* Now for the remaining rounds to 64: */
35625f78d91Sagc do {
35725f78d91Sagc ROUND256(a,b,c,d,e,f,g,h);
35825f78d91Sagc ROUND256(h,a,b,c,d,e,f,g);
35925f78d91Sagc ROUND256(g,h,a,b,c,d,e,f);
36025f78d91Sagc ROUND256(f,g,h,a,b,c,d,e);
36125f78d91Sagc ROUND256(e,f,g,h,a,b,c,d);
36225f78d91Sagc ROUND256(d,e,f,g,h,a,b,c);
36325f78d91Sagc ROUND256(c,d,e,f,g,h,a,b);
36425f78d91Sagc ROUND256(b,c,d,e,f,g,h,a);
36525f78d91Sagc } while (j < 64);
36625f78d91Sagc
36725f78d91Sagc /* Compute the current intermediate hash value */
36825f78d91Sagc context->state[0] += a;
36925f78d91Sagc context->state[1] += b;
37025f78d91Sagc context->state[2] += c;
37125f78d91Sagc context->state[3] += d;
37225f78d91Sagc context->state[4] += e;
37325f78d91Sagc context->state[5] += f;
37425f78d91Sagc context->state[6] += g;
37525f78d91Sagc context->state[7] += h;
37625f78d91Sagc
37725f78d91Sagc /* Clean up */
37825f78d91Sagc a = b = c = d = e = f = g = h = T1 = 0;
37925f78d91Sagc }
38025f78d91Sagc
38125f78d91Sagc #else /* SHA2_UNROLL_TRANSFORM */
38225f78d91Sagc
38325f78d91Sagc void
netpgpv_SHA256_Transform(NETPGPV_SHA256_CTX * context,const uint32_t * data)384dd98b26dSagc netpgpv_SHA256_Transform(NETPGPV_SHA256_CTX *context, const uint32_t *data)
38525f78d91Sagc {
38625f78d91Sagc uint32_t a, b, c, d, e, f, g, h, s0, s1;
38725f78d91Sagc uint32_t T1, T2, *W256;
38825f78d91Sagc int j;
38925f78d91Sagc
39025f78d91Sagc W256 = (uint32_t *)(void *)context->buffer;
39125f78d91Sagc
39225f78d91Sagc /* Initialize registers with the prev. intermediate value */
39325f78d91Sagc a = context->state[0];
39425f78d91Sagc b = context->state[1];
39525f78d91Sagc c = context->state[2];
39625f78d91Sagc d = context->state[3];
39725f78d91Sagc e = context->state[4];
39825f78d91Sagc f = context->state[5];
39925f78d91Sagc g = context->state[6];
40025f78d91Sagc h = context->state[7];
40125f78d91Sagc
40225f78d91Sagc j = 0;
40325f78d91Sagc do {
40425f78d91Sagc W256[j] = be32toh(*data);
40525f78d91Sagc ++data;
40625f78d91Sagc /* Apply the SHA-256 compression function to update a..h */
40725f78d91Sagc T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
40825f78d91Sagc T2 = Sigma0_256(a) + Maj(a, b, c);
40925f78d91Sagc h = g;
41025f78d91Sagc g = f;
41125f78d91Sagc f = e;
41225f78d91Sagc e = d + T1;
41325f78d91Sagc d = c;
41425f78d91Sagc c = b;
41525f78d91Sagc b = a;
41625f78d91Sagc a = T1 + T2;
41725f78d91Sagc
41825f78d91Sagc j++;
41925f78d91Sagc } while (j < 16);
42025f78d91Sagc
42125f78d91Sagc do {
42225f78d91Sagc /* Part of the message block expansion: */
42325f78d91Sagc s0 = W256[(j+1)&0x0f];
42425f78d91Sagc s0 = sigma0_256(s0);
42525f78d91Sagc s1 = W256[(j+14)&0x0f];
42625f78d91Sagc s1 = sigma1_256(s1);
42725f78d91Sagc
42825f78d91Sagc /* Apply the SHA-256 compression function to update a..h */
42925f78d91Sagc T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
43025f78d91Sagc (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
43125f78d91Sagc T2 = Sigma0_256(a) + Maj(a, b, c);
43225f78d91Sagc h = g;
43325f78d91Sagc g = f;
43425f78d91Sagc f = e;
43525f78d91Sagc e = d + T1;
43625f78d91Sagc d = c;
43725f78d91Sagc c = b;
43825f78d91Sagc b = a;
43925f78d91Sagc a = T1 + T2;
44025f78d91Sagc
44125f78d91Sagc j++;
44225f78d91Sagc } while (j < 64);
44325f78d91Sagc
44425f78d91Sagc /* Compute the current intermediate hash value */
44525f78d91Sagc context->state[0] += a;
44625f78d91Sagc context->state[1] += b;
44725f78d91Sagc context->state[2] += c;
44825f78d91Sagc context->state[3] += d;
44925f78d91Sagc context->state[4] += e;
45025f78d91Sagc context->state[5] += f;
45125f78d91Sagc context->state[6] += g;
45225f78d91Sagc context->state[7] += h;
45325f78d91Sagc
45425f78d91Sagc /* Clean up */
45525f78d91Sagc a = b = c = d = e = f = g = h = T1 = T2 = 0;
45625f78d91Sagc }
45725f78d91Sagc
45825f78d91Sagc #endif /* SHA2_UNROLL_TRANSFORM */
45925f78d91Sagc
46025f78d91Sagc int
netpgpv_SHA256_Update(NETPGPV_SHA256_CTX * context,const uint8_t * data,size_t len)461dd98b26dSagc netpgpv_SHA256_Update(NETPGPV_SHA256_CTX *context, const uint8_t *data, size_t len)
46225f78d91Sagc {
46325f78d91Sagc unsigned int freespace, usedspace;
46425f78d91Sagc
46525f78d91Sagc if (len == 0) {
46625f78d91Sagc /* Calling with no data is valid - we do nothing */
46725f78d91Sagc return 1;
46825f78d91Sagc }
46925f78d91Sagc
47025f78d91Sagc usedspace = (unsigned int)((context->bitcount >> 3) %
47125f78d91Sagc SHA256_BLOCK_LENGTH);
47225f78d91Sagc if (usedspace > 0) {
47325f78d91Sagc /* Calculate how much free space is available in the buffer */
47425f78d91Sagc freespace = SHA256_BLOCK_LENGTH - usedspace;
47525f78d91Sagc
47625f78d91Sagc if (len >= freespace) {
47725f78d91Sagc /* Fill the buffer completely and process it */
47825f78d91Sagc memcpy(&context->buffer[usedspace], data,
47925f78d91Sagc (size_t)(freespace));
48025f78d91Sagc context->bitcount += freespace << 3;
48125f78d91Sagc len -= freespace;
48225f78d91Sagc data += freespace;
483dd98b26dSagc netpgpv_SHA256_Transform(context,
48425f78d91Sagc (uint32_t *)(void *)context->buffer);
48525f78d91Sagc } else {
48625f78d91Sagc /* The buffer is not yet full */
48725f78d91Sagc memcpy(&context->buffer[usedspace], data, len);
48825f78d91Sagc context->bitcount += len << 3;
48925f78d91Sagc /* Clean up: */
49025f78d91Sagc usedspace = freespace = 0;
49125f78d91Sagc return 1;
49225f78d91Sagc }
49325f78d91Sagc }
49425f78d91Sagc /*
49525f78d91Sagc * Process as many complete blocks as possible.
49625f78d91Sagc *
49725f78d91Sagc * Check alignment of the data pointer. If it is 32bit aligned,
49825f78d91Sagc * SHA256_Transform can be called directly on the data stream,
49925f78d91Sagc * otherwise enforce the alignment by copy into the buffer.
50025f78d91Sagc */
50125f78d91Sagc if ((uintptr_t)data % 4 == 0) {
50225f78d91Sagc while (len >= SHA256_BLOCK_LENGTH) {
503dd98b26dSagc netpgpv_SHA256_Transform(context,
50425f78d91Sagc (const uint32_t *)(const void *)data);
50525f78d91Sagc context->bitcount += SHA256_BLOCK_LENGTH << 3;
50625f78d91Sagc len -= SHA256_BLOCK_LENGTH;
50725f78d91Sagc data += SHA256_BLOCK_LENGTH;
50825f78d91Sagc }
50925f78d91Sagc } else {
51025f78d91Sagc while (len >= SHA256_BLOCK_LENGTH) {
51125f78d91Sagc memcpy(context->buffer, data, SHA256_BLOCK_LENGTH);
512dd98b26dSagc netpgpv_SHA256_Transform(context,
51325f78d91Sagc (const uint32_t *)(const void *)context->buffer);
51425f78d91Sagc context->bitcount += SHA256_BLOCK_LENGTH << 3;
51525f78d91Sagc len -= SHA256_BLOCK_LENGTH;
51625f78d91Sagc data += SHA256_BLOCK_LENGTH;
51725f78d91Sagc }
51825f78d91Sagc }
51925f78d91Sagc if (len > 0) {
52025f78d91Sagc /* There's left-overs, so save 'em */
52125f78d91Sagc memcpy(context->buffer, data, len);
52225f78d91Sagc context->bitcount += len << 3;
52325f78d91Sagc }
52425f78d91Sagc /* Clean up: */
52525f78d91Sagc usedspace = freespace = 0;
52625f78d91Sagc
52725f78d91Sagc return 1;
52825f78d91Sagc }
52925f78d91Sagc
53025f78d91Sagc static int
netpgpv_SHA224_256_Final(uint8_t digest[],NETPGPV_SHA256_CTX * context,size_t len)531dd98b26dSagc netpgpv_SHA224_256_Final(uint8_t digest[], NETPGPV_SHA256_CTX *context, size_t len)
53225f78d91Sagc {
53325f78d91Sagc unsigned int usedspace;
53425f78d91Sagc size_t i;
53525f78d91Sagc
53625f78d91Sagc /* If no digest buffer is passed, we don't bother doing this: */
53725f78d91Sagc if (digest != NULL) {
53825f78d91Sagc usedspace = (unsigned int)((context->bitcount >> 3) %
53925f78d91Sagc SHA256_BLOCK_LENGTH);
54025f78d91Sagc context->bitcount = htobe64(context->bitcount);
54125f78d91Sagc if (usedspace > 0) {
54225f78d91Sagc /* Begin padding with a 1 bit: */
54325f78d91Sagc context->buffer[usedspace++] = 0x80;
54425f78d91Sagc
54525f78d91Sagc if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
54625f78d91Sagc /* Set-up for the last transform: */
54725f78d91Sagc memset(&context->buffer[usedspace], 0,
54825f78d91Sagc (size_t)(SHA256_SHORT_BLOCK_LENGTH -
54925f78d91Sagc usedspace));
55025f78d91Sagc } else {
55125f78d91Sagc if (usedspace < SHA256_BLOCK_LENGTH) {
55225f78d91Sagc memset(&context->buffer[usedspace], 0,
55325f78d91Sagc (size_t)(SHA256_BLOCK_LENGTH -
55425f78d91Sagc usedspace));
55525f78d91Sagc }
55625f78d91Sagc /* Do second-to-last transform: */
557dd98b26dSagc netpgpv_SHA256_Transform(context,
55825f78d91Sagc (uint32_t *)(void *)context->buffer);
55925f78d91Sagc
56025f78d91Sagc /* And set-up for the last transform: */
56125f78d91Sagc memset(context->buffer, 0,
56225f78d91Sagc (size_t)(SHA256_SHORT_BLOCK_LENGTH));
56325f78d91Sagc }
56425f78d91Sagc } else {
56525f78d91Sagc /* Set-up for the last transform: */
56625f78d91Sagc memset(context->buffer, 0,
56725f78d91Sagc (size_t)(SHA256_SHORT_BLOCK_LENGTH));
56825f78d91Sagc
56925f78d91Sagc /* Begin padding with a 1 bit: */
57025f78d91Sagc *context->buffer = 0x80;
57125f78d91Sagc }
57225f78d91Sagc /* Set the bit count: */
57325f78d91Sagc memcpy(&context->buffer[SHA256_SHORT_BLOCK_LENGTH],
57425f78d91Sagc &context->bitcount, sizeof(context->bitcount));
57525f78d91Sagc
57625f78d91Sagc /* Final transform: */
577dd98b26dSagc netpgpv_SHA256_Transform(context, (uint32_t *)(void *)context->buffer);
57825f78d91Sagc
57925f78d91Sagc for (i = 0; i < len / 4; i++)
58025f78d91Sagc be32encode(digest + 4 * i, context->state[i]);
58125f78d91Sagc }
58225f78d91Sagc
58325f78d91Sagc /* Clean up state data: */
58425f78d91Sagc memset(context, 0, sizeof(*context));
58525f78d91Sagc usedspace = 0;
58625f78d91Sagc
58725f78d91Sagc return 1;
58825f78d91Sagc }
58925f78d91Sagc
59025f78d91Sagc int
netpgpv_SHA256_Final(uint8_t digest[32],NETPGPV_SHA256_CTX * context)591*f8570f8aSmrg netpgpv_SHA256_Final(uint8_t digest[32], NETPGPV_SHA256_CTX *context)
59225f78d91Sagc {
593dd98b26dSagc return netpgpv_SHA224_256_Final(digest, context, SHA256_DIGEST_LENGTH);
59425f78d91Sagc }
59525f78d91Sagc
59625f78d91Sagc /*** SHA-224: *********************************************************/
59725f78d91Sagc int
netpgpv_SHA224_Init(NETPGPV_SHA224_CTX * context)598dd98b26dSagc netpgpv_SHA224_Init(NETPGPV_SHA224_CTX *context)
59925f78d91Sagc {
60025f78d91Sagc if (context == NULL)
60125f78d91Sagc return 1;
60225f78d91Sagc
60325f78d91Sagc /* The state and buffer size are driven by SHA256, not by SHA224. */
60425f78d91Sagc memcpy(context->state, sha224_initial_hash_value,
60525f78d91Sagc (size_t)(SHA256_DIGEST_LENGTH));
60625f78d91Sagc memset(context->buffer, 0, (size_t)(SHA256_BLOCK_LENGTH));
60725f78d91Sagc context->bitcount = 0;
60825f78d91Sagc
60925f78d91Sagc return 1;
61025f78d91Sagc }
61125f78d91Sagc
61225f78d91Sagc int
netpgpv_SHA224_Update(NETPGPV_SHA224_CTX * context,const uint8_t * data,size_t len)613dd98b26dSagc netpgpv_SHA224_Update(NETPGPV_SHA224_CTX *context, const uint8_t *data, size_t len)
61425f78d91Sagc {
615dd98b26dSagc return netpgpv_SHA256_Update((NETPGPV_SHA256_CTX *)context, data, len);
61625f78d91Sagc }
61725f78d91Sagc
61825f78d91Sagc void
netpgpv_SHA224_Transform(NETPGPV_SHA224_CTX * context,const uint32_t * data)619dd98b26dSagc netpgpv_SHA224_Transform(NETPGPV_SHA224_CTX *context, const uint32_t *data)
62025f78d91Sagc {
621dd98b26dSagc netpgpv_SHA256_Transform((NETPGPV_SHA256_CTX *)context, data);
62225f78d91Sagc }
62325f78d91Sagc
62425f78d91Sagc int
netpgpv_SHA224_Final(uint8_t digest[28],NETPGPV_SHA224_CTX * context)625*f8570f8aSmrg netpgpv_SHA224_Final(uint8_t digest[28], NETPGPV_SHA224_CTX *context)
62625f78d91Sagc {
627dd98b26dSagc return netpgpv_SHA224_256_Final(digest, (NETPGPV_SHA256_CTX *)context,
62825f78d91Sagc SHA224_DIGEST_LENGTH);
62925f78d91Sagc }
63025f78d91Sagc
63125f78d91Sagc /*** SHA-512: *********************************************************/
63225f78d91Sagc int
netpgpv_SHA512_Init(NETPGPV_SHA512_CTX * context)633dd98b26dSagc netpgpv_SHA512_Init(NETPGPV_SHA512_CTX *context)
63425f78d91Sagc {
63525f78d91Sagc if (context == NULL)
63625f78d91Sagc return 1;
63725f78d91Sagc
63825f78d91Sagc memcpy(context->state, sha512_initial_hash_value,
63925f78d91Sagc (size_t)(SHA512_DIGEST_LENGTH));
64025f78d91Sagc memset(context->buffer, 0, (size_t)(SHA512_BLOCK_LENGTH));
64125f78d91Sagc context->bitcount[0] = context->bitcount[1] = 0;
64225f78d91Sagc
64325f78d91Sagc return 1;
64425f78d91Sagc }
64525f78d91Sagc
64625f78d91Sagc #ifdef SHA2_UNROLL_TRANSFORM
64725f78d91Sagc
64825f78d91Sagc /* Unrolled SHA-512 round macros: */
64925f78d91Sagc #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
65025f78d91Sagc W512[j] = be64toh(*data); \
65125f78d91Sagc ++data; \
65225f78d91Sagc T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
65325f78d91Sagc K512[j] + W512[j]; \
65425f78d91Sagc (d) += T1, \
65525f78d91Sagc (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
65625f78d91Sagc j++
65725f78d91Sagc
65825f78d91Sagc #define ROUND512(a,b,c,d,e,f,g,h) \
65925f78d91Sagc s0 = W512[(j+1)&0x0f]; \
66025f78d91Sagc s0 = sigma0_512(s0); \
66125f78d91Sagc s1 = W512[(j+14)&0x0f]; \
66225f78d91Sagc s1 = sigma1_512(s1); \
66325f78d91Sagc T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
66425f78d91Sagc (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
66525f78d91Sagc (d) += T1; \
66625f78d91Sagc (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
66725f78d91Sagc j++
66825f78d91Sagc
66925f78d91Sagc void
netpgpv_SHA512_Transform(NETPGPV_SHA512_CTX * context,const uint64_t * data)670dd98b26dSagc netpgpv_SHA512_Transform(NETPGPV_SHA512_CTX *context, const uint64_t *data)
67125f78d91Sagc {
67225f78d91Sagc uint64_t a, b, c, d, e, f, g, h, s0, s1;
67325f78d91Sagc uint64_t T1, *W512 = (uint64_t *)context->buffer;
67425f78d91Sagc int j;
67525f78d91Sagc
67625f78d91Sagc /* Initialize registers with the prev. intermediate value */
67725f78d91Sagc a = context->state[0];
67825f78d91Sagc b = context->state[1];
67925f78d91Sagc c = context->state[2];
68025f78d91Sagc d = context->state[3];
68125f78d91Sagc e = context->state[4];
68225f78d91Sagc f = context->state[5];
68325f78d91Sagc g = context->state[6];
68425f78d91Sagc h = context->state[7];
68525f78d91Sagc
68625f78d91Sagc j = 0;
68725f78d91Sagc do {
68825f78d91Sagc ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
68925f78d91Sagc ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
69025f78d91Sagc ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
69125f78d91Sagc ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
69225f78d91Sagc ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
69325f78d91Sagc ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
69425f78d91Sagc ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
69525f78d91Sagc ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
69625f78d91Sagc } while (j < 16);
69725f78d91Sagc
69825f78d91Sagc /* Now for the remaining rounds up to 79: */
69925f78d91Sagc do {
70025f78d91Sagc ROUND512(a,b,c,d,e,f,g,h);
70125f78d91Sagc ROUND512(h,a,b,c,d,e,f,g);
70225f78d91Sagc ROUND512(g,h,a,b,c,d,e,f);
70325f78d91Sagc ROUND512(f,g,h,a,b,c,d,e);
70425f78d91Sagc ROUND512(e,f,g,h,a,b,c,d);
70525f78d91Sagc ROUND512(d,e,f,g,h,a,b,c);
70625f78d91Sagc ROUND512(c,d,e,f,g,h,a,b);
70725f78d91Sagc ROUND512(b,c,d,e,f,g,h,a);
70825f78d91Sagc } while (j < 80);
70925f78d91Sagc
71025f78d91Sagc /* Compute the current intermediate hash value */
71125f78d91Sagc context->state[0] += a;
71225f78d91Sagc context->state[1] += b;
71325f78d91Sagc context->state[2] += c;
71425f78d91Sagc context->state[3] += d;
71525f78d91Sagc context->state[4] += e;
71625f78d91Sagc context->state[5] += f;
71725f78d91Sagc context->state[6] += g;
71825f78d91Sagc context->state[7] += h;
71925f78d91Sagc
72025f78d91Sagc /* Clean up */
72125f78d91Sagc a = b = c = d = e = f = g = h = T1 = 0;
72225f78d91Sagc }
72325f78d91Sagc
72425f78d91Sagc #else /* SHA2_UNROLL_TRANSFORM */
72525f78d91Sagc
72625f78d91Sagc void
netpgpv_SHA512_Transform(NETPGPV_SHA512_CTX * context,const uint64_t * data)727dd98b26dSagc netpgpv_SHA512_Transform(NETPGPV_SHA512_CTX *context, const uint64_t *data)
72825f78d91Sagc {
72925f78d91Sagc uint64_t a, b, c, d, e, f, g, h, s0, s1;
73025f78d91Sagc uint64_t T1, T2, *W512 = (void *)context->buffer;
73125f78d91Sagc int j;
73225f78d91Sagc
73325f78d91Sagc /* Initialize registers with the prev. intermediate value */
73425f78d91Sagc a = context->state[0];
73525f78d91Sagc b = context->state[1];
73625f78d91Sagc c = context->state[2];
73725f78d91Sagc d = context->state[3];
73825f78d91Sagc e = context->state[4];
73925f78d91Sagc f = context->state[5];
74025f78d91Sagc g = context->state[6];
74125f78d91Sagc h = context->state[7];
74225f78d91Sagc
74325f78d91Sagc j = 0;
74425f78d91Sagc do {
74525f78d91Sagc W512[j] = be64toh(*data);
74625f78d91Sagc ++data;
74725f78d91Sagc /* Apply the SHA-512 compression function to update a..h */
74825f78d91Sagc T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
74925f78d91Sagc T2 = Sigma0_512(a) + Maj(a, b, c);
75025f78d91Sagc h = g;
75125f78d91Sagc g = f;
75225f78d91Sagc f = e;
75325f78d91Sagc e = d + T1;
75425f78d91Sagc d = c;
75525f78d91Sagc c = b;
75625f78d91Sagc b = a;
75725f78d91Sagc a = T1 + T2;
75825f78d91Sagc
75925f78d91Sagc j++;
76025f78d91Sagc } while (j < 16);
76125f78d91Sagc
76225f78d91Sagc do {
76325f78d91Sagc /* Part of the message block expansion: */
76425f78d91Sagc s0 = W512[(j+1)&0x0f];
76525f78d91Sagc s0 = sigma0_512(s0);
76625f78d91Sagc s1 = W512[(j+14)&0x0f];
76725f78d91Sagc s1 = sigma1_512(s1);
76825f78d91Sagc
76925f78d91Sagc /* Apply the SHA-512 compression function to update a..h */
77025f78d91Sagc T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
77125f78d91Sagc (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
77225f78d91Sagc T2 = Sigma0_512(a) + Maj(a, b, c);
77325f78d91Sagc h = g;
77425f78d91Sagc g = f;
77525f78d91Sagc f = e;
77625f78d91Sagc e = d + T1;
77725f78d91Sagc d = c;
77825f78d91Sagc c = b;
77925f78d91Sagc b = a;
78025f78d91Sagc a = T1 + T2;
78125f78d91Sagc
78225f78d91Sagc j++;
78325f78d91Sagc } while (j < 80);
78425f78d91Sagc
78525f78d91Sagc /* Compute the current intermediate hash value */
78625f78d91Sagc context->state[0] += a;
78725f78d91Sagc context->state[1] += b;
78825f78d91Sagc context->state[2] += c;
78925f78d91Sagc context->state[3] += d;
79025f78d91Sagc context->state[4] += e;
79125f78d91Sagc context->state[5] += f;
79225f78d91Sagc context->state[6] += g;
79325f78d91Sagc context->state[7] += h;
79425f78d91Sagc
79525f78d91Sagc /* Clean up */
79625f78d91Sagc a = b = c = d = e = f = g = h = T1 = T2 = 0;
79725f78d91Sagc }
79825f78d91Sagc
79925f78d91Sagc #endif /* SHA2_UNROLL_TRANSFORM */
80025f78d91Sagc
80125f78d91Sagc int
netpgpv_SHA512_Update(NETPGPV_SHA512_CTX * context,const uint8_t * data,size_t len)802dd98b26dSagc netpgpv_SHA512_Update(NETPGPV_SHA512_CTX *context, const uint8_t *data, size_t len)
80325f78d91Sagc {
80425f78d91Sagc unsigned int freespace, usedspace;
80525f78d91Sagc
80625f78d91Sagc if (len == 0) {
80725f78d91Sagc /* Calling with no data is valid - we do nothing */
80825f78d91Sagc return 1;
80925f78d91Sagc }
81025f78d91Sagc
81125f78d91Sagc usedspace = (unsigned int)((context->bitcount[0] >> 3) %
81225f78d91Sagc SHA512_BLOCK_LENGTH);
81325f78d91Sagc if (usedspace > 0) {
81425f78d91Sagc /* Calculate how much free space is available in the buffer */
81525f78d91Sagc freespace = SHA512_BLOCK_LENGTH - usedspace;
81625f78d91Sagc
81725f78d91Sagc if (len >= freespace) {
81825f78d91Sagc /* Fill the buffer completely and process it */
81925f78d91Sagc memcpy(&context->buffer[usedspace], data,
82025f78d91Sagc (size_t)(freespace));
82125f78d91Sagc ADDINC128(context->bitcount, freespace << 3);
82225f78d91Sagc len -= freespace;
82325f78d91Sagc data += freespace;
824dd98b26dSagc netpgpv_SHA512_Transform(context,
82525f78d91Sagc (uint64_t *)(void *)context->buffer);
82625f78d91Sagc } else {
82725f78d91Sagc /* The buffer is not yet full */
82825f78d91Sagc memcpy(&context->buffer[usedspace], data, len);
82925f78d91Sagc ADDINC128(context->bitcount, len << 3);
83025f78d91Sagc /* Clean up: */
83125f78d91Sagc usedspace = freespace = 0;
83225f78d91Sagc return 1;
83325f78d91Sagc }
83425f78d91Sagc }
83525f78d91Sagc /*
83625f78d91Sagc * Process as many complete blocks as possible.
83725f78d91Sagc *
83825f78d91Sagc * Check alignment of the data pointer. If it is 64bit aligned,
83925f78d91Sagc * SHA512_Transform can be called directly on the data stream,
84025f78d91Sagc * otherwise enforce the alignment by copy into the buffer.
84125f78d91Sagc */
84225f78d91Sagc if ((uintptr_t)data % 8 == 0) {
84325f78d91Sagc while (len >= SHA512_BLOCK_LENGTH) {
844dd98b26dSagc netpgpv_SHA512_Transform(context,
84525f78d91Sagc (const uint64_t*)(const void *)data);
84625f78d91Sagc ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
84725f78d91Sagc len -= SHA512_BLOCK_LENGTH;
84825f78d91Sagc data += SHA512_BLOCK_LENGTH;
84925f78d91Sagc }
85025f78d91Sagc } else {
85125f78d91Sagc while (len >= SHA512_BLOCK_LENGTH) {
85225f78d91Sagc memcpy(context->buffer, data, SHA512_BLOCK_LENGTH);
853dd98b26dSagc netpgpv_SHA512_Transform(context,
85425f78d91Sagc (const void *)context->buffer);
85525f78d91Sagc ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
85625f78d91Sagc len -= SHA512_BLOCK_LENGTH;
85725f78d91Sagc data += SHA512_BLOCK_LENGTH;
85825f78d91Sagc }
85925f78d91Sagc }
86025f78d91Sagc if (len > 0) {
86125f78d91Sagc /* There's left-overs, so save 'em */
86225f78d91Sagc memcpy(context->buffer, data, len);
86325f78d91Sagc ADDINC128(context->bitcount, len << 3);
86425f78d91Sagc }
86525f78d91Sagc /* Clean up: */
86625f78d91Sagc usedspace = freespace = 0;
86725f78d91Sagc
86825f78d91Sagc return 1;
86925f78d91Sagc }
87025f78d91Sagc
87125f78d91Sagc static void
netpgpv_SHA512_Last(NETPGPV_SHA512_CTX * context)872dd98b26dSagc netpgpv_SHA512_Last(NETPGPV_SHA512_CTX *context)
87325f78d91Sagc {
87425f78d91Sagc unsigned int usedspace;
87525f78d91Sagc
87625f78d91Sagc usedspace = (unsigned int)((context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH);
87725f78d91Sagc context->bitcount[0] = htobe64(context->bitcount[0]);
87825f78d91Sagc context->bitcount[1] = htobe64(context->bitcount[1]);
87925f78d91Sagc if (usedspace > 0) {
88025f78d91Sagc /* Begin padding with a 1 bit: */
88125f78d91Sagc context->buffer[usedspace++] = 0x80;
88225f78d91Sagc
88325f78d91Sagc if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
88425f78d91Sagc /* Set-up for the last transform: */
88525f78d91Sagc memset(&context->buffer[usedspace], 0,
88625f78d91Sagc (size_t)(SHA512_SHORT_BLOCK_LENGTH - usedspace));
88725f78d91Sagc } else {
88825f78d91Sagc if (usedspace < SHA512_BLOCK_LENGTH) {
88925f78d91Sagc memset(&context->buffer[usedspace], 0,
89025f78d91Sagc (size_t)(SHA512_BLOCK_LENGTH - usedspace));
89125f78d91Sagc }
89225f78d91Sagc /* Do second-to-last transform: */
893dd98b26dSagc netpgpv_SHA512_Transform(context,
89425f78d91Sagc (uint64_t *)(void *)context->buffer);
89525f78d91Sagc
89625f78d91Sagc /* And set-up for the last transform: */
89725f78d91Sagc memset(context->buffer, 0,
89825f78d91Sagc (size_t)(SHA512_BLOCK_LENGTH - 2));
89925f78d91Sagc }
90025f78d91Sagc } else {
90125f78d91Sagc /* Prepare for final transform: */
90225f78d91Sagc memset(context->buffer, 0, (size_t)(SHA512_SHORT_BLOCK_LENGTH));
90325f78d91Sagc
90425f78d91Sagc /* Begin padding with a 1 bit: */
90525f78d91Sagc *context->buffer = 0x80;
90625f78d91Sagc }
90725f78d91Sagc /* Store the length of input data (in bits): */
90825f78d91Sagc memcpy(&context->buffer[SHA512_SHORT_BLOCK_LENGTH],
90925f78d91Sagc &context->bitcount[1], sizeof(context->bitcount[1]));
91025f78d91Sagc memcpy(&context->buffer[SHA512_SHORT_BLOCK_LENGTH + 8],
91125f78d91Sagc &context->bitcount[0], sizeof(context->bitcount[0]));
91225f78d91Sagc
91325f78d91Sagc /* Final transform: */
914dd98b26dSagc netpgpv_SHA512_Transform(context, (uint64_t *)(void *)context->buffer);
91525f78d91Sagc }
91625f78d91Sagc
91725f78d91Sagc int
netpgpv_SHA512_Final(uint8_t digest[64],NETPGPV_SHA512_CTX * context)918*f8570f8aSmrg netpgpv_SHA512_Final(uint8_t digest[64], NETPGPV_SHA512_CTX *context)
91925f78d91Sagc {
92025f78d91Sagc size_t i;
92125f78d91Sagc
92225f78d91Sagc /* If no digest buffer is passed, we don't bother doing this: */
92325f78d91Sagc if (digest != NULL) {
924dd98b26dSagc netpgpv_SHA512_Last(context);
92525f78d91Sagc
92625f78d91Sagc /* Save the hash data for output: */
92725f78d91Sagc for (i = 0; i < 8; ++i)
92825f78d91Sagc be64encode(digest + 8 * i, context->state[i]);
92925f78d91Sagc }
93025f78d91Sagc
93125f78d91Sagc /* Zero out state data */
93225f78d91Sagc memset(context, 0, sizeof(*context));
93325f78d91Sagc
93425f78d91Sagc return 1;
93525f78d91Sagc }
93625f78d91Sagc
93725f78d91Sagc /*** SHA-384: *********************************************************/
93825f78d91Sagc int
netpgpv_SHA384_Init(NETPGPV_SHA384_CTX * context)939dd98b26dSagc netpgpv_SHA384_Init(NETPGPV_SHA384_CTX *context)
94025f78d91Sagc {
94125f78d91Sagc if (context == NULL)
94225f78d91Sagc return 1;
94325f78d91Sagc
94425f78d91Sagc memcpy(context->state, sha384_initial_hash_value,
94525f78d91Sagc (size_t)(SHA512_DIGEST_LENGTH));
94625f78d91Sagc memset(context->buffer, 0, (size_t)(SHA384_BLOCK_LENGTH));
94725f78d91Sagc context->bitcount[0] = context->bitcount[1] = 0;
94825f78d91Sagc
94925f78d91Sagc return 1;
95025f78d91Sagc }
95125f78d91Sagc
95225f78d91Sagc int
netpgpv_SHA384_Update(NETPGPV_SHA384_CTX * context,const uint8_t * data,size_t len)953dd98b26dSagc netpgpv_SHA384_Update(NETPGPV_SHA384_CTX *context, const uint8_t *data, size_t len)
95425f78d91Sagc {
955dd98b26dSagc return netpgpv_SHA512_Update((NETPGPV_SHA512_CTX *)context, data, len);
95625f78d91Sagc }
95725f78d91Sagc
95825f78d91Sagc void
netpgpv_SHA384_Transform(NETPGPV_SHA512_CTX * context,const uint64_t * data)959dd98b26dSagc netpgpv_SHA384_Transform(NETPGPV_SHA512_CTX *context, const uint64_t *data)
96025f78d91Sagc {
961dd98b26dSagc netpgpv_SHA512_Transform((NETPGPV_SHA512_CTX *)context, data);
96225f78d91Sagc }
96325f78d91Sagc
96425f78d91Sagc int
netpgpv_SHA384_Final(uint8_t digest[48],NETPGPV_SHA384_CTX * context)965*f8570f8aSmrg netpgpv_SHA384_Final(uint8_t digest[48], NETPGPV_SHA384_CTX *context)
96625f78d91Sagc {
96725f78d91Sagc size_t i;
96825f78d91Sagc
96925f78d91Sagc /* If no digest buffer is passed, we don't bother doing this: */
97025f78d91Sagc if (digest != NULL) {
971dd98b26dSagc netpgpv_SHA512_Last((NETPGPV_SHA512_CTX *)context);
97225f78d91Sagc
97325f78d91Sagc /* Save the hash data for output: */
97425f78d91Sagc for (i = 0; i < 6; ++i)
97525f78d91Sagc be64encode(digest + 8 * i, context->state[i]);
97625f78d91Sagc }
97725f78d91Sagc
97825f78d91Sagc /* Zero out state data */
97925f78d91Sagc memset(context, 0, sizeof(*context));
98025f78d91Sagc
98125f78d91Sagc return 1;
98225f78d91Sagc }
983