135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev/*
235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * FIPS 180-2 SHA-224/256/384/512 implementation
335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * Last update: 02/02/2007
435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * Issue date:  04/30/2005
535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev *
635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * Since this code has been incorporated into a GPLv2 project, it is
735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * distributed under GPLv2 inside mmc-utils.  The original BSD license
835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * that the code was released under is included below for clarity.
935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev *
1035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
1135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * All rights reserved.
1235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev *
1335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * Redistribution and use in source and binary forms, with or without
1435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * modification, are permitted provided that the following conditions
1535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * are met:
1635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * 1. Redistributions of source code must retain the above copyright
1735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev *    notice, this list of conditions and the following disclaimer.
1835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * 2. Redistributions in binary form must reproduce the above copyright
1935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev *    notice, this list of conditions and the following disclaimer in the
2035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev *    documentation and/or other materials provided with the distribution.
2135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * 3. Neither the name of the project nor the names of its contributors
2235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev *    may be used to endorse or promote products derived from this software
2335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev *    without specific prior written permission.
2435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev *
2535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev * SUCH DAMAGE.
3635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev */
3735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
3835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#if 0
3935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define UNROLL_LOOPS /* Enable loops unrolling */
4035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif
4135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
4235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#include <string.h>
4335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
4435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#include "sha2.h"
4535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
4635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHFR(x, n)    (x >> n)
4735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define ROTR(x, n)   ((x >> n) | (x << ((sizeof(x) << 3) - n)))
4835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define ROTL(x, n)   ((x << n) | (x >> ((sizeof(x) << 3) - n)))
4935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define CH(x, y, z)  ((x & y) ^ (~x & z))
5035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
5135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
5235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA256_F1(x) (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
5335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA256_F2(x) (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
5435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA256_F3(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))
5535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
5635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
5735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
5835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
5935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA512_F3(x) (ROTR(x,  1) ^ ROTR(x,  8) ^ SHFR(x,  7))
6035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x,  6))
6135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
6235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define UNPACK32(x, str)                      \
6335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{                                             \
6435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 3) = (uint8) ((x)      );       \
6535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 2) = (uint8) ((x) >>  8);       \
6635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 1) = (uint8) ((x) >> 16);       \
6735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 0) = (uint8) ((x) >> 24);       \
6835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
6935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
7035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define PACK32(str, x)                        \
7135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{                                             \
7235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *(x) =   ((uint32) *((str) + 3)      )    \
7335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           | ((uint32) *((str) + 2) <<  8)    \
7435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           | ((uint32) *((str) + 1) << 16)    \
7535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           | ((uint32) *((str) + 0) << 24);   \
7635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
7735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
7835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define UNPACK64(x, str)                      \
7935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{                                             \
8035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 7) = (uint8) ((x)      );       \
8135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 6) = (uint8) ((x) >>  8);       \
8235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 5) = (uint8) ((x) >> 16);       \
8335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 4) = (uint8) ((x) >> 24);       \
8435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 3) = (uint8) ((x) >> 32);       \
8535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 2) = (uint8) ((x) >> 40);       \
8635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 1) = (uint8) ((x) >> 48);       \
8735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *((str) + 0) = (uint8) ((x) >> 56);       \
8835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
8935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
9035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define PACK64(str, x)                        \
9135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{                                             \
9235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    *(x) =   ((uint64) *((str) + 7)      )    \
9335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           | ((uint64) *((str) + 6) <<  8)    \
9435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           | ((uint64) *((str) + 5) << 16)    \
9535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           | ((uint64) *((str) + 4) << 24)    \
9635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           | ((uint64) *((str) + 3) << 32)    \
9735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           | ((uint64) *((str) + 2) << 40)    \
9835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           | ((uint64) *((str) + 1) << 48)    \
9935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           | ((uint64) *((str) + 0) << 56);   \
10035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
10135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
10235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev/* Macros used for loops unrolling */
10335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
10435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA256_SCR(i)                         \
10535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{                                             \
10635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    w[i] =  SHA256_F4(w[i -  2]) + w[i -  7]  \
10735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev          + SHA256_F3(w[i - 15]) + w[i - 16]; \
10835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
10935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
11035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA512_SCR(i)                         \
11135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{                                             \
11235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    w[i] =  SHA512_F4(w[i -  2]) + w[i -  7]  \
11335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev          + SHA512_F3(w[i - 15]) + w[i - 16]; \
11435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
11535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
11635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA256_EXP(a, b, c, d, e, f, g, h, j)               \
11735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{                                                           \
11835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
11935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev         + sha256_k[j] + w[j];                              \
12035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]);       \
12135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    wv[d] += t1;                                            \
12235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    wv[h] = t1 + t2;                                        \
12335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
12435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
12535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#define SHA512_EXP(a, b, c, d, e, f, g ,h, j)               \
12635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{                                                           \
12735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
12835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev         + sha512_k[j] + w[j];                              \
12935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]);       \
13035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    wv[d] += t1;                                            \
13135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    wv[h] = t1 + t2;                                        \
13235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
13335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
13435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevuint32 sha224_h0[8] =
13535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
13635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
13735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
13835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevuint32 sha256_h0[8] =
13935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
14035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
14135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
14235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevuint64 sha384_h0[8] =
14335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            {0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
14435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
14535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
14635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL};
14735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
14835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevuint64 sha512_h0[8] =
14935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            {0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
15035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
15135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
15235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
15335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
15435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevuint32 sha256_k[64] =
15535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
15635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
15735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
15835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
15935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
16035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
16135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
16235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
16335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
16435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
16535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
16635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
16735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
16835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
16935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
17035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
17135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
17235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevuint64 sha512_k[80] =
17335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            {0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
17435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
17535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
17635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
17735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
17835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
17935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
18035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
18135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
18235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
18335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
18435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
18535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
18635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
18735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
18835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
18935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
19035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
19135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
19235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
19335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
19435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
19535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
19635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
19735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
19835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
19935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
20035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
20135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
20235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
20335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
20435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
20535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
20635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
20735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
20835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
20935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
21035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
21135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
21235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev             0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
21335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
21435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev/* SHA-256 functions */
21535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
21635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha256_transf(sha256_ctx *ctx, const unsigned char *message,
21735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                   unsigned int block_nb)
21835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
21935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    uint32 w[64];
22035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    uint32 wv[8];
22135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    uint32 t1, t2;
22235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    const unsigned char *sub_block;
22335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i;
22435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
22535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
22635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int j;
22735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif
22835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
22935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0; i < (int) block_nb; i++) {
23035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        sub_block = message + (i << 6);
23135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
23235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
23335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        for (j = 0; j < 16; j++) {
23435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            PACK32(&sub_block[j << 2], &w[j]);
23535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
23635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
23735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        for (j = 16; j < 64; j++) {
23835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            SHA256_SCR(j);
23935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
24035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
24135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        for (j = 0; j < 8; j++) {
24235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[j] = ctx->h[j];
24335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
24435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
24535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        for (j = 0; j < 64; j++) {
24635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
24735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                + sha256_k[j] + w[j];
24835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
24935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[7] = wv[6];
25035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[6] = wv[5];
25135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[5] = wv[4];
25235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[4] = wv[3] + t1;
25335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[3] = wv[2];
25435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[2] = wv[1];
25535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[1] = wv[0];
25635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[0] = t1 + t2;
25735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
25835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
25935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        for (j = 0; j < 8; j++) {
26035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            ctx->h[j] += wv[j];
26135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
26235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#else
26335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
26435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
26535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
26635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
26735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
26835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
26935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
27035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
27135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
27235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
27335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
27435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
27535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
27635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
27735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
27835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
27935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
28035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
28135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
28235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
28335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
28435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
28535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
28635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
28735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
28835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
28935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
29035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
29135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
29235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
29335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
29435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
29535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
29635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
29735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
29835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
29935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
30035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
30135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
30235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
30335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
30435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
30535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
30635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
30735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
30835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
30935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
31035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
31135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
31235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
31335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
31435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
31535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
31635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
31735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
31835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
31935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
32035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
32135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
32235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
32335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
32435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
32535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
32635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
32735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* !UNROLL_LOOPS */
32835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
32935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
33035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
33135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
33235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
33335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256_ctx ctx;
33435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
33535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256_init(&ctx);
33635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256_update(&ctx, message, len);
33735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256_final(&ctx, digest);
33835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
33935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
34035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha256_init(sha256_ctx *ctx)
34135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
34235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
34335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i;
34435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0; i < 8; i++) {
34535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[i] = sha256_h0[i];
34635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
34735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#else
34835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
34935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
35035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
35135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
35235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* !UNROLL_LOOPS */
35335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
35435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->len = 0;
35535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->tot_len = 0;
35635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
35735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
35835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha256_update(sha256_ctx *ctx, const unsigned char *message,
35935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                   unsigned int len)
36035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
36135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int block_nb;
36235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int new_len, rem_len, tmp_len;
36335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    const unsigned char *shifted_message;
36435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
36535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    tmp_len = SHA256_BLOCK_SIZE - ctx->len;
36635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    rem_len = len < tmp_len ? len : tmp_len;
36735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
36835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memcpy(&ctx->block[ctx->len], message, rem_len);
36935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
37035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    if (ctx->len + len < SHA256_BLOCK_SIZE) {
37135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->len += len;
37235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        return;
37335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
37435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
37535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    new_len = len - rem_len;
37635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    block_nb = new_len / SHA256_BLOCK_SIZE;
37735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
37835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    shifted_message = message + rem_len;
37935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
38035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256_transf(ctx, ctx->block, 1);
38135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256_transf(ctx, shifted_message, block_nb);
38235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
38335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    rem_len = new_len % SHA256_BLOCK_SIZE;
38435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
38535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memcpy(ctx->block, &shifted_message[block_nb << 6],
38635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           rem_len);
38735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
38835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->len = rem_len;
38935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->tot_len += (block_nb + 1) << 6;
39035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
39135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
39235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha256_final(sha256_ctx *ctx, unsigned char *digest)
39335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
39435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int block_nb;
39535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int pm_len;
39635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int len_b;
39735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
39835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
39935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i;
40035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif
40135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
40235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
40335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                     < (ctx->len % SHA256_BLOCK_SIZE)));
40435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
40535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    len_b = (ctx->tot_len + ctx->len) << 3;
40635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    pm_len = block_nb << 6;
40735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
40835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
40935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->block[ctx->len] = 0x80;
41035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK32(len_b, ctx->block + pm_len - 4);
41135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
41235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256_transf(ctx, ctx->block, block_nb);
41335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
41435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
41535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0 ; i < 8; i++) {
41635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        UNPACK32(ctx->h[i], &digest[i << 2]);
41735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
41835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#else
41935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[0], &digest[ 0]);
42035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[1], &digest[ 4]);
42135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[2], &digest[ 8]);
42235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[3], &digest[12]);
42335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[4], &digest[16]);
42435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[5], &digest[20]);
42535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[6], &digest[24]);
42635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[7], &digest[28]);
42735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* !UNROLL_LOOPS */
42835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
42935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
43035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev/* SHA-512 functions */
43135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
43235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha512_transf(sha512_ctx *ctx, const unsigned char *message,
43335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                   unsigned int block_nb)
43435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
43535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    uint64 w[80];
43635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    uint64 wv[8];
43735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    uint64 t1, t2;
43835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    const unsigned char *sub_block;
43935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i, j;
44035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
44135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0; i < (int) block_nb; i++) {
44235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        sub_block = message + (i << 7);
44335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
44435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
44535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        for (j = 0; j < 16; j++) {
44635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            PACK64(&sub_block[j << 3], &w[j]);
44735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
44835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
44935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        for (j = 16; j < 80; j++) {
45035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            SHA512_SCR(j);
45135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
45235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
45335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        for (j = 0; j < 8; j++) {
45435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[j] = ctx->h[j];
45535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
45635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
45735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        for (j = 0; j < 80; j++) {
45835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
45935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                + sha512_k[j] + w[j];
46035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
46135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[7] = wv[6];
46235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[6] = wv[5];
46335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[5] = wv[4];
46435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[4] = wv[3] + t1;
46535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[3] = wv[2];
46635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[2] = wv[1];
46735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[1] = wv[0];
46835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            wv[0] = t1 + t2;
46935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
47035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
47135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        for (j = 0; j < 8; j++) {
47235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            ctx->h[j] += wv[j];
47335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
47435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#else
47535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK64(&sub_block[  0], &w[ 0]); PACK64(&sub_block[  8], &w[ 1]);
47635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]);
47735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]);
47835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]);
47935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]);
48035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]);
48135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]);
48235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]);
48335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
48435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
48535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
48635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
48735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
48835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
48935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
49035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
49135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
49235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
49335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
49435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
49535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
49635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
49735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
49835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
49935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
50035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
50135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
50235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
50335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
50435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
50535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
50635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        j = 0;
50735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
50835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        do {
50935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
51035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
51135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
51235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
51335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
51435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
51535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
51635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
51735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        } while (j < 80);
51835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
51935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
52035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
52135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
52235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
52335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* !UNROLL_LOOPS */
52435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
52535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
52635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
52735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha512(const unsigned char *message, unsigned int len,
52835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            unsigned char *digest)
52935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
53035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512_ctx ctx;
53135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
53235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512_init(&ctx);
53335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512_update(&ctx, message, len);
53435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512_final(&ctx, digest);
53535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
53635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
53735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha512_init(sha512_ctx *ctx)
53835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
53935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
54035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i;
54135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0; i < 8; i++) {
54235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[i] = sha512_h0[i];
54335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
54435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#else
54535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
54635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
54735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
54835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
54935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* !UNROLL_LOOPS */
55035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
55135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->len = 0;
55235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->tot_len = 0;
55335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
55435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
55535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha512_update(sha512_ctx *ctx, const unsigned char *message,
55635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                   unsigned int len)
55735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
55835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int block_nb;
55935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int new_len, rem_len, tmp_len;
56035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    const unsigned char *shifted_message;
56135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
56235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    tmp_len = SHA512_BLOCK_SIZE - ctx->len;
56335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    rem_len = len < tmp_len ? len : tmp_len;
56435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
56535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memcpy(&ctx->block[ctx->len], message, rem_len);
56635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
56735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    if (ctx->len + len < SHA512_BLOCK_SIZE) {
56835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->len += len;
56935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        return;
57035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
57135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
57235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    new_len = len - rem_len;
57335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    block_nb = new_len / SHA512_BLOCK_SIZE;
57435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
57535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    shifted_message = message + rem_len;
57635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
57735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512_transf(ctx, ctx->block, 1);
57835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512_transf(ctx, shifted_message, block_nb);
57935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
58035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    rem_len = new_len % SHA512_BLOCK_SIZE;
58135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
58235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memcpy(ctx->block, &shifted_message[block_nb << 7],
58335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           rem_len);
58435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
58535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->len = rem_len;
58635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->tot_len += (block_nb + 1) << 7;
58735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
58835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
58935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha512_final(sha512_ctx *ctx, unsigned char *digest)
59035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
59135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int block_nb;
59235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int pm_len;
59335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int len_b;
59435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
59535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
59635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i;
59735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif
59835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
59935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
60035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                     < (ctx->len % SHA512_BLOCK_SIZE));
60135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
60235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    len_b = (ctx->tot_len + ctx->len) << 3;
60335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    pm_len = block_nb << 7;
60435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
60535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
60635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->block[ctx->len] = 0x80;
60735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK32(len_b, ctx->block + pm_len - 4);
60835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
60935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512_transf(ctx, ctx->block, block_nb);
61035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
61135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
61235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0 ; i < 8; i++) {
61335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        UNPACK64(ctx->h[i], &digest[i << 3]);
61435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
61535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#else
61635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[0], &digest[ 0]);
61735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[1], &digest[ 8]);
61835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[2], &digest[16]);
61935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[3], &digest[24]);
62035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[4], &digest[32]);
62135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[5], &digest[40]);
62235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[6], &digest[48]);
62335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[7], &digest[56]);
62435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* !UNROLL_LOOPS */
62535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
62635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
62735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev/* SHA-384 functions */
62835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
62935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha384(const unsigned char *message, unsigned int len,
63035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            unsigned char *digest)
63135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
63235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha384_ctx ctx;
63335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
63435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha384_init(&ctx);
63535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha384_update(&ctx, message, len);
63635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha384_final(&ctx, digest);
63735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
63835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
63935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha384_init(sha384_ctx *ctx)
64035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
64135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
64235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i;
64335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0; i < 8; i++) {
64435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[i] = sha384_h0[i];
64535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
64635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#else
64735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[0] = sha384_h0[0]; ctx->h[1] = sha384_h0[1];
64835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[2] = sha384_h0[2]; ctx->h[3] = sha384_h0[3];
64935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[4] = sha384_h0[4]; ctx->h[5] = sha384_h0[5];
65035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[6] = sha384_h0[6]; ctx->h[7] = sha384_h0[7];
65135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* !UNROLL_LOOPS */
65235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
65335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->len = 0;
65435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->tot_len = 0;
65535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
65635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
65735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha384_update(sha384_ctx *ctx, const unsigned char *message,
65835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                   unsigned int len)
65935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
66035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int block_nb;
66135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int new_len, rem_len, tmp_len;
66235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    const unsigned char *shifted_message;
66335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
66435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    tmp_len = SHA384_BLOCK_SIZE - ctx->len;
66535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    rem_len = len < tmp_len ? len : tmp_len;
66635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
66735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memcpy(&ctx->block[ctx->len], message, rem_len);
66835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
66935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    if (ctx->len + len < SHA384_BLOCK_SIZE) {
67035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->len += len;
67135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        return;
67235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
67335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
67435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    new_len = len - rem_len;
67535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    block_nb = new_len / SHA384_BLOCK_SIZE;
67635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
67735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    shifted_message = message + rem_len;
67835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
67935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512_transf(ctx, ctx->block, 1);
68035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512_transf(ctx, shifted_message, block_nb);
68135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
68235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    rem_len = new_len % SHA384_BLOCK_SIZE;
68335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
68435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memcpy(ctx->block, &shifted_message[block_nb << 7],
68535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           rem_len);
68635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
68735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->len = rem_len;
68835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->tot_len += (block_nb + 1) << 7;
68935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
69035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
69135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha384_final(sha384_ctx *ctx, unsigned char *digest)
69235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
69335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int block_nb;
69435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int pm_len;
69535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int len_b;
69635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
69735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
69835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i;
69935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif
70035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
70135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    block_nb = (1 + ((SHA384_BLOCK_SIZE - 17)
70235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                     < (ctx->len % SHA384_BLOCK_SIZE)));
70335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
70435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    len_b = (ctx->tot_len + ctx->len) << 3;
70535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    pm_len = block_nb << 7;
70635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
70735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
70835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->block[ctx->len] = 0x80;
70935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK32(len_b, ctx->block + pm_len - 4);
71035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
71135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512_transf(ctx, ctx->block, block_nb);
71235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
71335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
71435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0 ; i < 6; i++) {
71535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        UNPACK64(ctx->h[i], &digest[i << 3]);
71635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
71735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#else
71835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[0], &digest[ 0]);
71935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[1], &digest[ 8]);
72035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[2], &digest[16]);
72135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[3], &digest[24]);
72235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[4], &digest[32]);
72335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK64(ctx->h[5], &digest[40]);
72435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* !UNROLL_LOOPS */
72535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
72635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
72735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev/* SHA-224 functions */
72835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
72935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha224(const unsigned char *message, unsigned int len,
73035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev            unsigned char *digest)
73135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
73235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha224_ctx ctx;
73335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
73435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha224_init(&ctx);
73535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha224_update(&ctx, message, len);
73635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha224_final(&ctx, digest);
73735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
73835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
73935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha224_init(sha224_ctx *ctx)
74035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
74135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
74235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i;
74335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0; i < 8; i++) {
74435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->h[i] = sha224_h0[i];
74535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
74635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#else
74735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[0] = sha224_h0[0]; ctx->h[1] = sha224_h0[1];
74835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[2] = sha224_h0[2]; ctx->h[3] = sha224_h0[3];
74935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[4] = sha224_h0[4]; ctx->h[5] = sha224_h0[5];
75035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->h[6] = sha224_h0[6]; ctx->h[7] = sha224_h0[7];
75135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* !UNROLL_LOOPS */
75235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
75335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->len = 0;
75435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->tot_len = 0;
75535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
75635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
75735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha224_update(sha224_ctx *ctx, const unsigned char *message,
75835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                   unsigned int len)
75935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
76035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int block_nb;
76135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int new_len, rem_len, tmp_len;
76235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    const unsigned char *shifted_message;
76335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
76435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    tmp_len = SHA224_BLOCK_SIZE - ctx->len;
76535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    rem_len = len < tmp_len ? len : tmp_len;
76635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
76735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memcpy(&ctx->block[ctx->len], message, rem_len);
76835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
76935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    if (ctx->len + len < SHA224_BLOCK_SIZE) {
77035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        ctx->len += len;
77135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        return;
77235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
77335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
77435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    new_len = len - rem_len;
77535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    block_nb = new_len / SHA224_BLOCK_SIZE;
77635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
77735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    shifted_message = message + rem_len;
77835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
77935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256_transf(ctx, ctx->block, 1);
78035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256_transf(ctx, shifted_message, block_nb);
78135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
78235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    rem_len = new_len % SHA224_BLOCK_SIZE;
78335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
78435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memcpy(ctx->block, &shifted_message[block_nb << 6],
78535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev           rem_len);
78635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
78735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->len = rem_len;
78835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->tot_len += (block_nb + 1) << 6;
78935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
79035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
79135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid sha224_final(sha224_ctx *ctx, unsigned char *digest)
79235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
79335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int block_nb;
79435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int pm_len;
79535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int len_b;
79635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
79735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
79835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i;
79935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif
80035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
80135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    block_nb = (1 + ((SHA224_BLOCK_SIZE - 9)
80235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                     < (ctx->len % SHA224_BLOCK_SIZE)));
80335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
80435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    len_b = (ctx->tot_len + ctx->len) << 3;
80535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    pm_len = block_nb << 6;
80635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
80735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
80835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    ctx->block[ctx->len] = 0x80;
80935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    UNPACK32(len_b, ctx->block + pm_len - 4);
81035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
81135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256_transf(ctx, ctx->block, block_nb);
81235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
81335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifndef UNROLL_LOOPS
81435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0 ; i < 7; i++) {
81535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        UNPACK32(ctx->h[i], &digest[i << 2]);
81635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
81735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#else
81835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[0], &digest[ 0]);
81935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[1], &digest[ 4]);
82035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[2], &digest[ 8]);
82135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[3], &digest[12]);
82235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[4], &digest[16]);
82335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[5], &digest[20]);
82435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev   UNPACK32(ctx->h[6], &digest[24]);
82535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* !UNROLL_LOOPS */
82635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
82735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
82835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#ifdef TEST_VECTORS
82935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
83035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev/* FIPS 180-2 Validation tests */
83135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
83235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#include <stdio.h>
83335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#include <stdlib.h>
83435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
83535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevvoid test(const char *vector, unsigned char *digest,
83635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev          unsigned int digest_size)
83735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
83835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    char output[2 * SHA512_DIGEST_SIZE + 1];
83935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    int i;
84035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
84135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    output[2 * digest_size] = '\0';
84235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
84335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    for (i = 0; i < (int) digest_size ; i++) {
84435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev       sprintf(output + 2 * i, "%02x", digest[i]);
84535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
84635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
84735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("H: %s\n", output);
84835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    if (strcmp(vector, output)) {
84935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        fprintf(stderr, "Test failed.\n");
85035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        exit(EXIT_FAILURE);
85135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
85235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
85335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
85435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaevint main(void)
85535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev{
85635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    static const char *vectors[4][3] =
85735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    {   /* SHA-224 */
85835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        {
85935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
86035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525",
86135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67",
86235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        },
86335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        /* SHA-256 */
86435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        {
86535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
86635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
86735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0",
86835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        },
86935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        /* SHA-384 */
87035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        {
87135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
87235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "8086072ba1e7cc2358baeca134c825a7",
87335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
87435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "fcc7c71a557e2db966c3e9fa91746039",
87535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"
87635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "07b8b3dc38ecc4ebae97ddd87f3d8985",
87735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        },
87835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        /* SHA-512 */
87935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        {
88035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
88135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
88235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
88335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909",
88435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
88535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
88635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        }
88735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    };
88835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
88935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    static const char message1[] = "abc";
89035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    static const char message2a[] = "abcdbcdecdefdefgefghfghighijhi"
89135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                                    "jkijkljklmklmnlmnomnopnopq";
89235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    static const char message2b[] = "abcdefghbcdefghicdefghijdefghijkefghij"
89335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                                    "klfghijklmghijklmnhijklmnoijklmnopjklm"
89435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev                                    "nopqklmnopqrlmnopqrsmnopqrstnopqrstu";
89535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned char *message3;
89635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned int message3_len = 1000000;
89735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    unsigned char digest[SHA512_DIGEST_SIZE];
89835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
89935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    message3 = malloc(message3_len);
90035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    if (message3 == NULL) {
90135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        fprintf(stderr, "Can't allocate memory\n");
90235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev        return -1;
90335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    }
90435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    memset(message3, 'a', message3_len);
90535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
90635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("SHA-2 FIPS 180-2 Validation tests\n\n");
90735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("SHA-224 Test vectors\n");
90835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
90935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha224((const unsigned char *) message1, strlen(message1), digest);
91035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[0][0], digest, SHA224_DIGEST_SIZE);
91135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha224((const unsigned char *) message2a, strlen(message2a), digest);
91235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[0][1], digest, SHA224_DIGEST_SIZE);
91335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha224(message3, message3_len, digest);
91435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[0][2], digest, SHA224_DIGEST_SIZE);
91535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("\n");
91635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
91735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("SHA-256 Test vectors\n");
91835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
91935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256((const unsigned char *) message1, strlen(message1), digest);
92035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[1][0], digest, SHA256_DIGEST_SIZE);
92135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256((const unsigned char *) message2a, strlen(message2a), digest);
92235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[1][1], digest, SHA256_DIGEST_SIZE);
92335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha256(message3, message3_len, digest);
92435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[1][2], digest, SHA256_DIGEST_SIZE);
92535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("\n");
92635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
92735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("SHA-384 Test vectors\n");
92835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
92935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha384((const unsigned char *) message1, strlen(message1), digest);
93035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[2][0], digest, SHA384_DIGEST_SIZE);
93135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha384((const unsigned char *)message2b, strlen(message2b), digest);
93235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[2][1], digest, SHA384_DIGEST_SIZE);
93335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha384(message3, message3_len, digest);
93435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[2][2], digest, SHA384_DIGEST_SIZE);
93535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("\n");
93635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
93735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("SHA-512 Test vectors\n");
93835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
93935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512((const unsigned char *) message1, strlen(message1), digest);
94035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[3][0], digest, SHA512_DIGEST_SIZE);
94135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512((const unsigned char *) message2b, strlen(message2b), digest);
94235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[3][1], digest, SHA512_DIGEST_SIZE);
94335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    sha512(message3, message3_len, digest);
94435c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    test(vectors[3][2], digest, SHA512_DIGEST_SIZE);
94535c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("\n");
94635c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
94735c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    printf("All tests passed.\n");
94835c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
94935c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev    return 0;
95035c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev}
95135c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
95235c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev#endif /* TEST_VECTORS */
95335c31feacf9be6a76732910f564cedbd872512f8Roman Peniaev
954