* *
* partial sync with the 3.4 fork codebase. These are the things
synces for the most part:
- copyright headers
- grammar/typos in comments and some readmes
- comment/whitespace/decorations
- variable scoping in C files
- DO CASE/SWITCH and some other alternate syntax usage
- minimal amount of human readable text in strings
- minor code updates
- HB_TRACE() void * casts for pointers and few other changes to
avoid C compiler warnings
- various other, minor code cleanups
- only Harbour/C code/headers were touched in src, utils, contrib,
include. No 3rd party code, no make files, and with just a few
exceptions, no 'tests' code was touched.
- certain components were not touched were 3.4 diverged too much
already, like f.e. hbmk2, hbssl, hbcurl, hbexpat
- the goal was that no actual program logic should be altered by
these changes. Except some possible minor exceptions, any such
change is probably a bug in this patch.
It's a massive patch, if you find anything broken after it, please
open an Issue with the details. Build test was done on macOS.
The goal is make it easier to see what actual code/logic was changed
in 3.4 compared to 3.2 and to make patches easier to apply in both
ways.
828 lines
29 KiB
C
828 lines
29 KiB
C
/*
|
|
* FIPS 180-2 SHA-224/256/384/512 implementation
|
|
* Last update: 2007-02-02
|
|
* Issue date: 2005-04-30
|
|
*
|
|
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the project nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#if ( defined( __POCC__ ) && __POCC__ >= 600 ) /* Trick to avoid Pelles C 6.00.6 compiler internal error. [vszakats] */
|
|
#define UNROLL_LOOPS /* Enable loops unrolling */
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include "sha2.h"
|
|
#include "hbdefs.h"
|
|
|
|
#define SHFR(x, n) (x >> n)
|
|
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
|
#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
|
|
#define CH(x, y, z) ((x & y) ^ (~x & z))
|
|
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
|
|
|
#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
|
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
|
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
|
|
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
|
|
|
|
#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
|
|
#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
|
|
#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
|
|
#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
|
|
|
|
#define UNPACK32(x, str) \
|
|
{ \
|
|
*((str) + 3) = (uint8) ((x) ); \
|
|
*((str) + 2) = (uint8) ((x) >> 8); \
|
|
*((str) + 1) = (uint8) ((x) >> 16); \
|
|
*((str) + 0) = (uint8) ((x) >> 24); \
|
|
}
|
|
|
|
#define PACK32(str, x) \
|
|
{ \
|
|
*(x) = ((uint32) *((str) + 3) ) \
|
|
| ((uint32) *((str) + 2) << 8) \
|
|
| ((uint32) *((str) + 1) << 16) \
|
|
| ((uint32) *((str) + 0) << 24); \
|
|
}
|
|
|
|
#define UNPACK64(x, str) \
|
|
{ \
|
|
*((str) + 7) = (uint8) ((x) ); \
|
|
*((str) + 6) = (uint8) ((x) >> 8); \
|
|
*((str) + 5) = (uint8) ((x) >> 16); \
|
|
*((str) + 4) = (uint8) ((x) >> 24); \
|
|
*((str) + 3) = (uint8) ((x) >> 32); \
|
|
*((str) + 2) = (uint8) ((x) >> 40); \
|
|
*((str) + 1) = (uint8) ((x) >> 48); \
|
|
*((str) + 0) = (uint8) ((x) >> 56); \
|
|
}
|
|
|
|
#define PACK64(str, x) \
|
|
{ \
|
|
*(x) = ((uint64) *((str) + 7) ) \
|
|
| ((uint64) *((str) + 6) << 8) \
|
|
| ((uint64) *((str) + 5) << 16) \
|
|
| ((uint64) *((str) + 4) << 24) \
|
|
| ((uint64) *((str) + 3) << 32) \
|
|
| ((uint64) *((str) + 2) << 40) \
|
|
| ((uint64) *((str) + 1) << 48) \
|
|
| ((uint64) *((str) + 0) << 56); \
|
|
}
|
|
|
|
/* Macros used for loops unrolling */
|
|
|
|
#define SHA256_SCR(i) \
|
|
{ \
|
|
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
|
|
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
|
|
}
|
|
|
|
#define SHA512_SCR(i) \
|
|
{ \
|
|
w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \
|
|
+ SHA512_F3(w[i - 15]) + w[i - 16]; \
|
|
}
|
|
|
|
#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
|
|
{ \
|
|
t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
|
|
+ sha256_k[j] + w[j]; \
|
|
t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
|
wv[d] += t1; \
|
|
wv[h] = t1 + t2; \
|
|
}
|
|
|
|
#define SHA512_EXP(a, b, c, d, e, f, g, h, j) \
|
|
{ \
|
|
t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
|
|
+ sha512_k[j] + w[j]; \
|
|
t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
|
wv[d] += t1; \
|
|
wv[h] = t1 + t2; \
|
|
}
|
|
|
|
static const uint32 sha224_h0[8] =
|
|
{0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
|
|
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
|
|
|
|
static const uint32 sha256_h0[8] =
|
|
{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
|
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
|
|
|
|
static const uint64 sha384_h0[8] =
|
|
{HB_ULL( 0xcbbb9d5dc1059ed8 ), HB_ULL( 0x629a292a367cd507 ),
|
|
HB_ULL( 0x9159015a3070dd17 ), HB_ULL( 0x152fecd8f70e5939 ),
|
|
HB_ULL( 0x67332667ffc00b31 ), HB_ULL( 0x8eb44a8768581511 ),
|
|
HB_ULL( 0xdb0c2e0d64f98fa7 ), HB_ULL( 0x47b5481dbefa4fa4 )};
|
|
|
|
static const uint64 sha512_h0[8] =
|
|
{HB_ULL( 0x6a09e667f3bcc908 ), HB_ULL( 0xbb67ae8584caa73b ),
|
|
HB_ULL( 0x3c6ef372fe94f82b ), HB_ULL( 0xa54ff53a5f1d36f1 ),
|
|
HB_ULL( 0x510e527fade682d1 ), HB_ULL( 0x9b05688c2b3e6c1f ),
|
|
HB_ULL( 0x1f83d9abfb41bd6b ), HB_ULL( 0x5be0cd19137e2179 )};
|
|
|
|
static const uint32 sha256_k[64] =
|
|
{0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
|
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
|
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
|
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
|
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
|
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
|
|
|
|
static const uint64 sha512_k[80] =
|
|
{HB_ULL( 0x428a2f98d728ae22 ), HB_ULL( 0x7137449123ef65cd ),
|
|
HB_ULL( 0xb5c0fbcfec4d3b2f ), HB_ULL( 0xe9b5dba58189dbbc ),
|
|
HB_ULL( 0x3956c25bf348b538 ), HB_ULL( 0x59f111f1b605d019 ),
|
|
HB_ULL( 0x923f82a4af194f9b ), HB_ULL( 0xab1c5ed5da6d8118 ),
|
|
HB_ULL( 0xd807aa98a3030242 ), HB_ULL( 0x12835b0145706fbe ),
|
|
HB_ULL( 0x243185be4ee4b28c ), HB_ULL( 0x550c7dc3d5ffb4e2 ),
|
|
HB_ULL( 0x72be5d74f27b896f ), HB_ULL( 0x80deb1fe3b1696b1 ),
|
|
HB_ULL( 0x9bdc06a725c71235 ), HB_ULL( 0xc19bf174cf692694 ),
|
|
HB_ULL( 0xe49b69c19ef14ad2 ), HB_ULL( 0xefbe4786384f25e3 ),
|
|
HB_ULL( 0x0fc19dc68b8cd5b5 ), HB_ULL( 0x240ca1cc77ac9c65 ),
|
|
HB_ULL( 0x2de92c6f592b0275 ), HB_ULL( 0x4a7484aa6ea6e483 ),
|
|
HB_ULL( 0x5cb0a9dcbd41fbd4 ), HB_ULL( 0x76f988da831153b5 ),
|
|
HB_ULL( 0x983e5152ee66dfab ), HB_ULL( 0xa831c66d2db43210 ),
|
|
HB_ULL( 0xb00327c898fb213f ), HB_ULL( 0xbf597fc7beef0ee4 ),
|
|
HB_ULL( 0xc6e00bf33da88fc2 ), HB_ULL( 0xd5a79147930aa725 ),
|
|
HB_ULL( 0x06ca6351e003826f ), HB_ULL( 0x142929670a0e6e70 ),
|
|
HB_ULL( 0x27b70a8546d22ffc ), HB_ULL( 0x2e1b21385c26c926 ),
|
|
HB_ULL( 0x4d2c6dfc5ac42aed ), HB_ULL( 0x53380d139d95b3df ),
|
|
HB_ULL( 0x650a73548baf63de ), HB_ULL( 0x766a0abb3c77b2a8 ),
|
|
HB_ULL( 0x81c2c92e47edaee6 ), HB_ULL( 0x92722c851482353b ),
|
|
HB_ULL( 0xa2bfe8a14cf10364 ), HB_ULL( 0xa81a664bbc423001 ),
|
|
HB_ULL( 0xc24b8b70d0f89791 ), HB_ULL( 0xc76c51a30654be30 ),
|
|
HB_ULL( 0xd192e819d6ef5218 ), HB_ULL( 0xd69906245565a910 ),
|
|
HB_ULL( 0xf40e35855771202a ), HB_ULL( 0x106aa07032bbd1b8 ),
|
|
HB_ULL( 0x19a4c116b8d2d0c8 ), HB_ULL( 0x1e376c085141ab53 ),
|
|
HB_ULL( 0x2748774cdf8eeb99 ), HB_ULL( 0x34b0bcb5e19b48a8 ),
|
|
HB_ULL( 0x391c0cb3c5c95a63 ), HB_ULL( 0x4ed8aa4ae3418acb ),
|
|
HB_ULL( 0x5b9cca4f7763e373 ), HB_ULL( 0x682e6ff3d6b2b8a3 ),
|
|
HB_ULL( 0x748f82ee5defb2fc ), HB_ULL( 0x78a5636f43172f60 ),
|
|
HB_ULL( 0x84c87814a1f0ab72 ), HB_ULL( 0x8cc702081a6439ec ),
|
|
HB_ULL( 0x90befffa23631e28 ), HB_ULL( 0xa4506cebde82bde9 ),
|
|
HB_ULL( 0xbef9a3f7b2c67915 ), HB_ULL( 0xc67178f2e372532b ),
|
|
HB_ULL( 0xca273eceea26619c ), HB_ULL( 0xd186b8c721c0c207 ),
|
|
HB_ULL( 0xeada7dd6cde0eb1e ), HB_ULL( 0xf57d4f7fee6ed178 ),
|
|
HB_ULL( 0x06f067aa72176fba ), HB_ULL( 0x0a637dc5a2c898a6 ),
|
|
HB_ULL( 0x113f9804bef90dae ), HB_ULL( 0x1b710b35131c471b ),
|
|
HB_ULL( 0x28db77f523047d84 ), HB_ULL( 0x32caab7b40c72493 ),
|
|
HB_ULL( 0x3c9ebe0a15c9bebc ), HB_ULL( 0x431d67c49c100d4c ),
|
|
HB_ULL( 0x4cc5d4becb3e42b6 ), HB_ULL( 0x597f299cfc657e2a ),
|
|
HB_ULL( 0x5fcb6fab3ad6faec ), HB_ULL( 0x6c44198c4a475817 )};
|
|
|
|
/* SHA-256 functions */
|
|
|
|
static void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
|
|
unsigned int block_nb)
|
|
{
|
|
uint32 w[64];
|
|
uint32 wv[8];
|
|
uint32 t1, t2;
|
|
const unsigned char *sub_block;
|
|
int i;
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
int j;
|
|
#endif
|
|
|
|
for (i = 0; i < (int) block_nb; i++) {
|
|
sub_block = message + (i << 6);
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
for (j = 0; j < 16; j++) {
|
|
PACK32(&sub_block[j << 2], &w[j]);
|
|
}
|
|
|
|
for (j = 16; j < 64; j++) {
|
|
SHA256_SCR(j);
|
|
}
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
wv[j] = ctx->h[j];
|
|
}
|
|
|
|
for (j = 0; j < 64; j++) {
|
|
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
|
+ sha256_k[j] + w[j];
|
|
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
|
wv[7] = wv[6];
|
|
wv[6] = wv[5];
|
|
wv[5] = wv[4];
|
|
wv[4] = wv[3] + t1;
|
|
wv[3] = wv[2];
|
|
wv[2] = wv[1];
|
|
wv[1] = wv[0];
|
|
wv[0] = t1 + t2;
|
|
}
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
ctx->h[j] += wv[j];
|
|
}
|
|
#else
|
|
PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
|
|
PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
|
|
PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
|
|
PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
|
|
PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
|
|
PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
|
|
PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
|
|
PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
|
|
|
|
SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
|
|
SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
|
|
SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
|
|
SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
|
|
SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
|
|
SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
|
|
SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
|
|
SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
|
|
SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
|
|
SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
|
|
SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
|
|
SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
|
|
|
|
wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
|
|
wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
|
|
wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
|
|
wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
|
|
|
|
SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
|
|
SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
|
|
SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
|
|
SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
|
|
SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
|
|
SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
|
|
SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
|
|
SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
|
|
SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
|
|
SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
|
|
SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
|
|
SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
|
|
SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
|
|
SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
|
|
SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
|
|
SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
|
|
SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
|
|
SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
|
|
SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
|
|
SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
|
|
SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
|
|
SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
|
|
SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
|
|
SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
|
|
SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
|
|
SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
|
|
SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
|
|
SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
|
|
SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
|
|
SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
|
|
SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
|
|
SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
|
|
|
|
ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
|
|
ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
|
|
ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
|
|
ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
|
|
#endif /* !UNROLL_LOOPS */
|
|
}
|
|
}
|
|
|
|
void hb_sha256(const void *message, unsigned int len, unsigned char *digest)
|
|
{
|
|
sha256_ctx ctx;
|
|
|
|
hb_sha256_init(&ctx);
|
|
hb_sha256_update(&ctx, message, len);
|
|
hb_sha256_final(&ctx, digest);
|
|
}
|
|
|
|
void hb_sha256_init(sha256_ctx *ctx)
|
|
{
|
|
#ifndef UNROLL_LOOPS
|
|
int i;
|
|
for (i = 0; i < 8; i++) {
|
|
ctx->h[i] = sha256_h0[i];
|
|
}
|
|
#else
|
|
ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
|
|
ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
|
|
ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
|
|
ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
|
|
#endif /* !UNROLL_LOOPS */
|
|
|
|
ctx->len = 0;
|
|
ctx->tot_len = 0;
|
|
}
|
|
|
|
void hb_sha256_update(sha256_ctx *ctx, const void *messagev,
|
|
unsigned int len)
|
|
{
|
|
const unsigned char * message = ( const unsigned char * ) messagev;
|
|
unsigned int block_nb;
|
|
unsigned int new_len, rem_len, tmp_len;
|
|
const unsigned char *shifted_message;
|
|
|
|
tmp_len = SHA256_BLOCK_SIZE - ctx->len;
|
|
rem_len = len < tmp_len ? len : tmp_len;
|
|
|
|
memcpy(&ctx->block[ctx->len], message, rem_len);
|
|
|
|
if (ctx->len + len < SHA256_BLOCK_SIZE) {
|
|
ctx->len += len;
|
|
return;
|
|
}
|
|
|
|
new_len = len - rem_len;
|
|
block_nb = new_len / SHA256_BLOCK_SIZE;
|
|
|
|
shifted_message = message + rem_len;
|
|
|
|
sha256_transf(ctx, ctx->block, 1);
|
|
sha256_transf(ctx, shifted_message, block_nb);
|
|
|
|
rem_len = new_len % SHA256_BLOCK_SIZE;
|
|
|
|
memcpy(ctx->block, &shifted_message[block_nb << 6],
|
|
rem_len);
|
|
|
|
ctx->len = rem_len;
|
|
ctx->tot_len += (block_nb + 1) << 6;
|
|
}
|
|
|
|
void hb_sha256_final(sha256_ctx *ctx, unsigned char *digest)
|
|
{
|
|
unsigned int block_nb;
|
|
unsigned int pm_len;
|
|
unsigned int len_b;
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
int i;
|
|
#endif
|
|
|
|
block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
|
|
< (ctx->len % SHA256_BLOCK_SIZE)));
|
|
|
|
len_b = (ctx->tot_len + ctx->len) << 3;
|
|
pm_len = block_nb << 6;
|
|
|
|
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
|
ctx->block[ctx->len] = 0x80;
|
|
UNPACK32(len_b, ctx->block + pm_len - 4);
|
|
|
|
sha256_transf(ctx, ctx->block, block_nb);
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
for (i = 0 ; i < 8; i++) {
|
|
UNPACK32(ctx->h[i], &digest[i << 2]);
|
|
}
|
|
#else
|
|
UNPACK32(ctx->h[0], &digest[ 0]);
|
|
UNPACK32(ctx->h[1], &digest[ 4]);
|
|
UNPACK32(ctx->h[2], &digest[ 8]);
|
|
UNPACK32(ctx->h[3], &digest[12]);
|
|
UNPACK32(ctx->h[4], &digest[16]);
|
|
UNPACK32(ctx->h[5], &digest[20]);
|
|
UNPACK32(ctx->h[6], &digest[24]);
|
|
UNPACK32(ctx->h[7], &digest[28]);
|
|
#endif /* !UNROLL_LOOPS */
|
|
}
|
|
|
|
/* SHA-512 functions */
|
|
|
|
static void sha512_transf(sha512_ctx *ctx, const unsigned char *message,
|
|
unsigned int block_nb)
|
|
{
|
|
uint64 w[80];
|
|
uint64 wv[8];
|
|
uint64 t1, t2;
|
|
const unsigned char *sub_block;
|
|
int i, j;
|
|
|
|
for (i = 0; i < (int) block_nb; i++) {
|
|
sub_block = message + (i << 7);
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
for (j = 0; j < 16; j++) {
|
|
PACK64(&sub_block[j << 3], &w[j]);
|
|
}
|
|
|
|
for (j = 16; j < 80; j++) {
|
|
SHA512_SCR(j);
|
|
}
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
wv[j] = ctx->h[j];
|
|
}
|
|
|
|
for (j = 0; j < 80; j++) {
|
|
t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
|
+ sha512_k[j] + w[j];
|
|
t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
|
wv[7] = wv[6];
|
|
wv[6] = wv[5];
|
|
wv[5] = wv[4];
|
|
wv[4] = wv[3] + t1;
|
|
wv[3] = wv[2];
|
|
wv[2] = wv[1];
|
|
wv[1] = wv[0];
|
|
wv[0] = t1 + t2;
|
|
}
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
ctx->h[j] += wv[j];
|
|
}
|
|
#else
|
|
PACK64(&sub_block[ 0], &w[ 0]); PACK64(&sub_block[ 8], &w[ 1]);
|
|
PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]);
|
|
PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]);
|
|
PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]);
|
|
PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]);
|
|
PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]);
|
|
PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]);
|
|
PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]);
|
|
|
|
SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
|
|
SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
|
|
SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
|
|
SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
|
|
SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
|
|
SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
|
|
SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
|
|
SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
|
|
SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
|
|
SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
|
|
SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
|
|
SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
|
|
SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
|
|
SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
|
|
SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
|
|
SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
|
|
|
|
wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
|
|
wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
|
|
wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
|
|
wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
|
|
|
|
j = 0;
|
|
|
|
do {
|
|
SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
|
|
SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
|
|
SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
|
|
SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
|
|
SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
|
|
SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
|
|
SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
|
|
SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
|
|
} while (j < 80);
|
|
|
|
ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
|
|
ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
|
|
ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
|
|
ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
|
|
#endif /* !UNROLL_LOOPS */
|
|
}
|
|
}
|
|
|
|
void hb_sha512(const void *message, unsigned int len,
|
|
unsigned char *digest)
|
|
{
|
|
sha512_ctx ctx;
|
|
|
|
hb_sha512_init(&ctx);
|
|
hb_sha512_update(&ctx, message, len);
|
|
hb_sha512_final(&ctx, digest);
|
|
}
|
|
|
|
void hb_sha512_init(sha512_ctx *ctx)
|
|
{
|
|
#ifndef UNROLL_LOOPS
|
|
int i;
|
|
for (i = 0; i < 8; i++) {
|
|
ctx->h[i] = sha512_h0[i];
|
|
}
|
|
#else
|
|
ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
|
|
ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
|
|
ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
|
|
ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
|
|
#endif /* !UNROLL_LOOPS */
|
|
|
|
ctx->len = 0;
|
|
ctx->tot_len = 0;
|
|
}
|
|
|
|
void hb_sha512_update(sha512_ctx *ctx, const void *messagev,
|
|
unsigned int len)
|
|
{
|
|
const unsigned char * message = ( const unsigned char * ) messagev;
|
|
unsigned int block_nb;
|
|
unsigned int new_len, rem_len, tmp_len;
|
|
const unsigned char *shifted_message;
|
|
|
|
tmp_len = SHA512_BLOCK_SIZE - ctx->len;
|
|
rem_len = len < tmp_len ? len : tmp_len;
|
|
|
|
memcpy(&ctx->block[ctx->len], message, rem_len);
|
|
|
|
if (ctx->len + len < SHA512_BLOCK_SIZE) {
|
|
ctx->len += len;
|
|
return;
|
|
}
|
|
|
|
new_len = len - rem_len;
|
|
block_nb = new_len / SHA512_BLOCK_SIZE;
|
|
|
|
shifted_message = message + rem_len;
|
|
|
|
sha512_transf(ctx, ctx->block, 1);
|
|
sha512_transf(ctx, shifted_message, block_nb);
|
|
|
|
rem_len = new_len % SHA512_BLOCK_SIZE;
|
|
|
|
memcpy(ctx->block, &shifted_message[block_nb << 7],
|
|
rem_len);
|
|
|
|
ctx->len = rem_len;
|
|
ctx->tot_len += (block_nb + 1) << 7;
|
|
}
|
|
|
|
void hb_sha512_final(sha512_ctx *ctx, unsigned char *digest)
|
|
{
|
|
unsigned int block_nb;
|
|
unsigned int pm_len;
|
|
unsigned int len_b;
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
int i;
|
|
#endif
|
|
|
|
block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
|
|
< (ctx->len % SHA512_BLOCK_SIZE));
|
|
|
|
len_b = (ctx->tot_len + ctx->len) << 3;
|
|
pm_len = block_nb << 7;
|
|
|
|
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
|
ctx->block[ctx->len] = 0x80;
|
|
UNPACK32(len_b, ctx->block + pm_len - 4);
|
|
|
|
sha512_transf(ctx, ctx->block, block_nb);
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
for (i = 0 ; i < 8; i++) {
|
|
UNPACK64(ctx->h[i], &digest[i << 3]);
|
|
}
|
|
#else
|
|
UNPACK64(ctx->h[0], &digest[ 0]);
|
|
UNPACK64(ctx->h[1], &digest[ 8]);
|
|
UNPACK64(ctx->h[2], &digest[16]);
|
|
UNPACK64(ctx->h[3], &digest[24]);
|
|
UNPACK64(ctx->h[4], &digest[32]);
|
|
UNPACK64(ctx->h[5], &digest[40]);
|
|
UNPACK64(ctx->h[6], &digest[48]);
|
|
UNPACK64(ctx->h[7], &digest[56]);
|
|
#endif /* !UNROLL_LOOPS */
|
|
}
|
|
|
|
/* SHA-384 functions */
|
|
|
|
void hb_sha384(const void *message, unsigned int len,
|
|
unsigned char *digest)
|
|
{
|
|
sha384_ctx ctx;
|
|
|
|
hb_sha384_init(&ctx);
|
|
hb_sha384_update(&ctx, message, len);
|
|
hb_sha384_final(&ctx, digest);
|
|
}
|
|
|
|
void hb_sha384_init(sha384_ctx *ctx)
|
|
{
|
|
#ifndef UNROLL_LOOPS
|
|
int i;
|
|
for (i = 0; i < 8; i++) {
|
|
ctx->h[i] = sha384_h0[i];
|
|
}
|
|
#else
|
|
ctx->h[0] = sha384_h0[0]; ctx->h[1] = sha384_h0[1];
|
|
ctx->h[2] = sha384_h0[2]; ctx->h[3] = sha384_h0[3];
|
|
ctx->h[4] = sha384_h0[4]; ctx->h[5] = sha384_h0[5];
|
|
ctx->h[6] = sha384_h0[6]; ctx->h[7] = sha384_h0[7];
|
|
#endif /* !UNROLL_LOOPS */
|
|
|
|
ctx->len = 0;
|
|
ctx->tot_len = 0;
|
|
}
|
|
|
|
void hb_sha384_update(sha384_ctx *ctx, const void *messagev,
|
|
unsigned int len)
|
|
{
|
|
const unsigned char * message = ( const unsigned char * ) messagev;
|
|
unsigned int block_nb;
|
|
unsigned int new_len, rem_len, tmp_len;
|
|
const unsigned char *shifted_message;
|
|
|
|
tmp_len = SHA384_BLOCK_SIZE - ctx->len;
|
|
rem_len = len < tmp_len ? len : tmp_len;
|
|
|
|
memcpy(&ctx->block[ctx->len], message, rem_len);
|
|
|
|
if (ctx->len + len < SHA384_BLOCK_SIZE) {
|
|
ctx->len += len;
|
|
return;
|
|
}
|
|
|
|
new_len = len - rem_len;
|
|
block_nb = new_len / SHA384_BLOCK_SIZE;
|
|
|
|
shifted_message = message + rem_len;
|
|
|
|
sha512_transf(ctx, ctx->block, 1);
|
|
sha512_transf(ctx, shifted_message, block_nb);
|
|
|
|
rem_len = new_len % SHA384_BLOCK_SIZE;
|
|
|
|
memcpy(ctx->block, &shifted_message[block_nb << 7],
|
|
rem_len);
|
|
|
|
ctx->len = rem_len;
|
|
ctx->tot_len += (block_nb + 1) << 7;
|
|
}
|
|
|
|
void hb_sha384_final(sha384_ctx *ctx, unsigned char *digest)
|
|
{
|
|
unsigned int block_nb;
|
|
unsigned int pm_len;
|
|
unsigned int len_b;
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
int i;
|
|
#endif
|
|
|
|
block_nb = (1 + ((SHA384_BLOCK_SIZE - 17)
|
|
< (ctx->len % SHA384_BLOCK_SIZE)));
|
|
|
|
len_b = (ctx->tot_len + ctx->len) << 3;
|
|
pm_len = block_nb << 7;
|
|
|
|
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
|
ctx->block[ctx->len] = 0x80;
|
|
UNPACK32(len_b, ctx->block + pm_len - 4);
|
|
|
|
sha512_transf(ctx, ctx->block, block_nb);
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
for (i = 0 ; i < 6; i++) {
|
|
UNPACK64(ctx->h[i], &digest[i << 3]);
|
|
}
|
|
#else
|
|
UNPACK64(ctx->h[0], &digest[ 0]);
|
|
UNPACK64(ctx->h[1], &digest[ 8]);
|
|
UNPACK64(ctx->h[2], &digest[16]);
|
|
UNPACK64(ctx->h[3], &digest[24]);
|
|
UNPACK64(ctx->h[4], &digest[32]);
|
|
UNPACK64(ctx->h[5], &digest[40]);
|
|
#endif /* !UNROLL_LOOPS */
|
|
}
|
|
|
|
/* SHA-224 functions */
|
|
|
|
void hb_sha224(const void *message, unsigned int len,
|
|
unsigned char *digest)
|
|
{
|
|
sha224_ctx ctx;
|
|
|
|
hb_sha224_init(&ctx);
|
|
hb_sha224_update(&ctx, message, len);
|
|
hb_sha224_final(&ctx, digest);
|
|
}
|
|
|
|
void hb_sha224_init(sha224_ctx *ctx)
|
|
{
|
|
#ifndef UNROLL_LOOPS
|
|
int i;
|
|
for (i = 0; i < 8; i++) {
|
|
ctx->h[i] = sha224_h0[i];
|
|
}
|
|
#else
|
|
ctx->h[0] = sha224_h0[0]; ctx->h[1] = sha224_h0[1];
|
|
ctx->h[2] = sha224_h0[2]; ctx->h[3] = sha224_h0[3];
|
|
ctx->h[4] = sha224_h0[4]; ctx->h[5] = sha224_h0[5];
|
|
ctx->h[6] = sha224_h0[6]; ctx->h[7] = sha224_h0[7];
|
|
#endif /* !UNROLL_LOOPS */
|
|
|
|
ctx->len = 0;
|
|
ctx->tot_len = 0;
|
|
}
|
|
|
|
void hb_sha224_update(sha224_ctx *ctx, const void *messagev,
|
|
unsigned int len)
|
|
{
|
|
const unsigned char * message = ( const unsigned char * ) messagev;
|
|
unsigned int block_nb;
|
|
unsigned int new_len, rem_len, tmp_len;
|
|
const unsigned char *shifted_message;
|
|
|
|
tmp_len = SHA224_BLOCK_SIZE - ctx->len;
|
|
rem_len = len < tmp_len ? len : tmp_len;
|
|
|
|
memcpy(&ctx->block[ctx->len], message, rem_len);
|
|
|
|
if (ctx->len + len < SHA224_BLOCK_SIZE) {
|
|
ctx->len += len;
|
|
return;
|
|
}
|
|
|
|
new_len = len - rem_len;
|
|
block_nb = new_len / SHA224_BLOCK_SIZE;
|
|
|
|
shifted_message = message + rem_len;
|
|
|
|
sha256_transf(ctx, ctx->block, 1);
|
|
sha256_transf(ctx, shifted_message, block_nb);
|
|
|
|
rem_len = new_len % SHA224_BLOCK_SIZE;
|
|
|
|
memcpy(ctx->block, &shifted_message[block_nb << 6],
|
|
rem_len);
|
|
|
|
ctx->len = rem_len;
|
|
ctx->tot_len += (block_nb + 1) << 6;
|
|
}
|
|
|
|
void hb_sha224_final(sha224_ctx *ctx, unsigned char *digest)
|
|
{
|
|
unsigned int block_nb;
|
|
unsigned int pm_len;
|
|
unsigned int len_b;
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
int i;
|
|
#endif
|
|
|
|
block_nb = (1 + ((SHA224_BLOCK_SIZE - 9)
|
|
< (ctx->len % SHA224_BLOCK_SIZE)));
|
|
|
|
len_b = (ctx->tot_len + ctx->len) << 3;
|
|
pm_len = block_nb << 6;
|
|
|
|
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
|
ctx->block[ctx->len] = 0x80;
|
|
UNPACK32(len_b, ctx->block + pm_len - 4);
|
|
|
|
sha256_transf(ctx, ctx->block, block_nb);
|
|
|
|
#ifndef UNROLL_LOOPS
|
|
for (i = 0 ; i < 7; i++) {
|
|
UNPACK32(ctx->h[i], &digest[i << 2]);
|
|
}
|
|
#else
|
|
UNPACK32(ctx->h[0], &digest[ 0]);
|
|
UNPACK32(ctx->h[1], &digest[ 4]);
|
|
UNPACK32(ctx->h[2], &digest[ 8]);
|
|
UNPACK32(ctx->h[3], &digest[12]);
|
|
UNPACK32(ctx->h[4], &digest[16]);
|
|
UNPACK32(ctx->h[5], &digest[20]);
|
|
UNPACK32(ctx->h[6], &digest[24]);
|
|
#endif /* !UNROLL_LOOPS */
|
|
}
|