Add support for lbry mining algorithm.

This commit is contained in:
lbrynaut 2019-07-01 08:18:01 -05:00 committed by Brannon King
parent 5f02105940
commit a4bb8de94a
11 changed files with 4966 additions and 105 deletions

View file

@ -5,6 +5,8 @@ else
JANSSON_INCLUDES=
endif
SHA3_INCLUDES= -I$(top_srcdir)/sha3
EXTRA_DIST = example-cfg.json nomacro.pl
SUBDIRS = compat
@ -15,7 +17,8 @@ dist_man_MANS = minerd.1
minerd_SOURCES = elist.h miner.h compat.h \
cpu-miner.c util.c \
sha2.c scrypt.c
sha2.c scrypt.c \
sph_sha2.c sph_sha2big.c sph_ripemd.c lbry.c
if USE_ASM
if ARCH_x86
minerd_SOURCES += sha2-x86.S scrypt-x86.S
@ -33,5 +36,4 @@ endif
minerd_LDFLAGS = $(PTHREAD_FLAGS)
minerd_LDADD = @LIBCURL@ @JANSSON_LIBS@ @PTHREAD_LIBS@ @WS2_LIBS@
minerd_CFLAGS = -fno-strict-aliasing
minerd_CPPFLAGS = @LIBCURL_CPPFLAGS@ $(JANSSON_INCLUDES) $(PTHREAD_FLAGS)
minerd_CPPFLAGS = @LIBCURL_CPPFLAGS@ $(JANSSON_INCLUDES) $(SHA3_INCLUDES) $(PTHREAD_FLAGS)

View file

@ -101,13 +101,11 @@ struct workio_cmd {
};
enum algos {
ALGO_SCRYPT, /* scrypt(1024,1,1) */
ALGO_SHA256D, /* SHA-256d */
ALGO_LBRY, /* lbry */
};
static const char *algo_names[] = {
[ALGO_SCRYPT] = "scrypt",
[ALGO_SHA256D] = "sha256d",
[ALGO_LBRY] = "lbry",
};
bool opt_debug = false;
@ -117,8 +115,8 @@ bool opt_redirect = true;
bool want_longpoll = true;
bool have_longpoll = false;
bool have_gbt = true;
bool allow_getwork = true;
bool want_stratum = true;
bool allow_getwork = false;
bool want_stratum = false;
bool have_stratum = false;
bool use_syslog = false;
static bool opt_background = false;
@ -127,7 +125,7 @@ static int opt_retries = -1;
static int opt_fail_pause = 30;
int opt_timeout = 0;
static int opt_scantime = 5;
static enum algos opt_algo = ALGO_SCRYPT;
static enum algos opt_algo = ALGO_LBRY;
static int opt_scrypt_n = 1024;
static int opt_n_threads;
static int num_processors;
@ -169,6 +167,7 @@ static char const usage[] = "\
Usage: " PROGRAM_NAME " [OPTIONS]\n\
Options:\n\
-a, --algo=ALGO specify the algorithm to use\n\
lbry (default)\n\
scrypt scrypt(1024, 1, 1) (default)\n\
scrypt:N scrypt(N, 1, 1)\n\
sha256d SHA-256d\n\
@ -188,9 +187,7 @@ Options:\n\
--coinbase-addr=ADDR payout address for solo mining\n\
--coinbase-sig=TEXT data to insert in the coinbase when possible\n\
--no-longpoll disable long polling support\n\
--no-getwork disable getwork support\n\
--no-gbt disable getblocktemplate support\n\
--no-stratum disable X-Stratum support\n\
--no-redirect ignore requests to change the URL of the mining server\n\
-q, --quiet disable per-thread hashmeter output\n\
-D, --debug enable debug output\n\
@ -232,10 +229,8 @@ static struct option const options[] = {
{ "debug", 0, NULL, 'D' },
{ "help", 0, NULL, 'h' },
{ "no-gbt", 0, NULL, 1011 },
{ "no-getwork", 0, NULL, 1010 },
{ "no-longpoll", 0, NULL, 1003 },
{ "no-redirect", 0, NULL, 1009 },
{ "no-stratum", 0, NULL, 1007 },
{ "pass", 1, NULL, 'p' },
{ "protocol-dump", 0, NULL, 'P' },
{ "proxy", 1, NULL, 'x' },
@ -256,7 +251,7 @@ static struct option const options[] = {
};
struct work {
uint32_t data[32];
uint32_t data[40];
uint32_t target[8];
int height;
@ -319,36 +314,13 @@ static bool jobj_binary(const json_t *obj, const char *key,
return true;
}
static bool work_decode(const json_t *val, struct work *work)
{
int i;
if (unlikely(!jobj_binary(val, "data", work->data, sizeof(work->data)))) {
applog(LOG_ERR, "JSON invalid data");
goto err_out;
}
if (unlikely(!jobj_binary(val, "target", work->target, sizeof(work->target)))) {
applog(LOG_ERR, "JSON invalid target");
goto err_out;
}
for (i = 0; i < ARRAY_SIZE(work->data); i++)
work->data[i] = le32dec(work->data + i);
for (i = 0; i < ARRAY_SIZE(work->target); i++)
work->target[i] = le32dec(work->target + i);
return true;
err_out:
return false;
}
static bool gbt_work_decode(const json_t *val, struct work *work)
{
int i, n;
uint32_t version, curtime, bits;
uint32_t prevhash[8];
uint32_t target[8];
uint32_t claimtrie[8];
int cbtx_size;
unsigned char *cbtx = NULL;
unsigned char *tx = NULL;
@ -401,6 +373,11 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
}
version = json_integer_value(tmp);
if (unlikely(!jobj_binary(val, "claimtrie", claimtrie, sizeof(claimtrie)))) {
applog(LOG_ERR, "JSON invalid claimtrie");
goto out;
}
if (unlikely(!jobj_binary(val, "previousblockhash", prevhash, sizeof(prevhash)))) {
applog(LOG_ERR, "JSON invalid previousblockhash");
goto out;
@ -438,6 +415,7 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
/* build coinbase transaction */
tmp = json_object_get(val, "coinbasetxn");
if (tmp) {
const char *cbtx_hex = json_string_value(json_object_get(tmp, "data"));
cbtx_size = cbtx_hex ? strlen(cbtx_hex) / 2 : 0;
@ -628,18 +606,20 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
}
/* assemble block header */
memset(work->data, 0x00, sizeof(work->data));
work->data[0] = swab32(version);
for (i = 0; i < 8; i++)
work->data[8 - i] = le32dec(prevhash + i);
for (i = 0; i < 8; i++)
work->data[9 + i] = be32dec((uint32_t *)merkle_tree[0] + i);
work->data[17] = swab32(curtime);
work->data[18] = le32dec(&bits);
memset(work->data + 19, 0x00, 52);
work->data[20] = 0x80000000;
work->data[31] = 0x00000280;
for (i = 0; i < 8; i++)
work->data[24 - i] = le32dec(claimtrie + i);
work->data[25] = swab32(curtime);
work->data[26] = le32dec(&bits);
work->data[28] = 0x80000000;
work->data[39] = 0x00000280;
if (unlikely(!jobj_binary(val, "target", target, sizeof(target)))) {
if (unlikely(!jobj_binary(val, "target", target, sizeof(target)))) {
applog(LOG_ERR, "JSON invalid target");
goto out;
}
@ -744,20 +724,20 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
for (i = 0; i < ARRAY_SIZE(work->data); i++)
be32enc(work->data + i, work->data[i]);
bin2hex(data_str, (unsigned char *)work->data, 80);
bin2hex(data_str, (unsigned char *)work->data, 112);
if (work->workid) {
char *params;
val = json_object();
json_object_set_new(val, "workid", json_string(work->workid));
params = json_dumps(val, 0);
json_decref(val);
req = malloc(128 + 2*80 + strlen(work->txs) + strlen(params));
req = malloc(160 + 2*112 + strlen(work->txs) + strlen(params));
sprintf(req,
"{\"method\": \"submitblock\", \"params\": [\"%s%s\", %s], \"id\":1}\r\n",
data_str, work->txs, params);
free(params);
} else {
req = malloc(128 + 2*80 + strlen(work->txs));
req = malloc(160 + 2*112 + strlen(work->txs));
sprintf(req,
"{\"method\": \"submitblock\", \"params\": [\"%s%s\"], \"id\":1}\r\n",
data_str, work->txs);
@ -823,14 +803,14 @@ static const char *getwork_req =
"{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
#define GBT_CAPABILITIES "[\"coinbasetxn\", \"coinbasevalue\", \"longpoll\", \"workid\"]"
#define GBT_RULES "[\"segwit\"]"
static const char *gbt_req =
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
GBT_CAPABILITIES ", \"rules\": " GBT_RULES "}], \"id\":0}\r\n";
GBT_CAPABILITIES "}], \"id\":0}\r\n";
static const char *gbt_lp_req =
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
GBT_CAPABILITIES ", \"rules\": " GBT_RULES ", \"longpollid\": \"%s\"}], \"id\":0}\r\n";
GBT_CAPABILITIES "}], \"id\":0}\r\n";
static bool get_upstream_work(CURL *curl, struct work *work)
{
@ -868,14 +848,11 @@ start:
if (!val)
return false;
if (have_gbt) {
rc = gbt_work_decode(json_object_get(val, "result"), work);
if (!have_gbt) {
json_decref(val);
goto start;
}
} else
rc = work_decode(json_object_get(val, "result"), work);
rc = gbt_work_decode(json_object_get(val, "result"), work);
if (!rc) {
json_decref(val);
goto start;
}
if (opt_debug && rc) {
timeval_subtract(&diff, &tv_end, &tv_start);
@ -1114,10 +1091,7 @@ static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
free(xnonce2str);
}
if (opt_algo == ALGO_SCRYPT)
diff_to_target(work->target, sctx->job.diff / 65536.0);
else
diff_to_target(work->target, sctx->job.diff);
diff_to_target(work->target, sctx->job.diff);
}
static void *miner_thread(void *userdata)
@ -1148,15 +1122,6 @@ static void *miner_thread(void *userdata)
affine_to_cpu(thr_id, thr_id % num_processors);
}
if (opt_algo == ALGO_SCRYPT) {
scratchbuf = scrypt_buffer_alloc(opt_scrypt_n);
if (!scratchbuf) {
applog(LOG_ERR, "scrypt buffer allocation failed");
pthread_mutex_lock(&applog_lock);
exit(1);
}
}
while (1) {
unsigned long hashes_done;
struct timeval tv_start, tv_end, diff;
@ -1175,7 +1140,7 @@ static void *miner_thread(void *userdata)
pthread_mutex_lock(&g_work_lock);
if (!have_stratum &&
(time(NULL) - g_work_time >= min_scantime ||
work.data[19] >= end_nonce)) {
work.data[27] >= end_nonce)) {
work_free(&g_work);
if (unlikely(!get_work(mythr, &g_work))) {
applog(LOG_ERR, "work retrieval failed, exiting "
@ -1190,12 +1155,13 @@ static void *miner_thread(void *userdata)
continue;
}
}
if (memcmp(work.data, g_work.data, 76)) {
/* if (memcmp(work.data, g_work.data, 76)) { */
if (memcmp(work.data, g_work.data, 108)) {
work_free(&work);
work_copy(&work, &g_work);
work.data[19] = 0xffffffffU / opt_n_threads * thr_id;
work.data[27] = 0xffffffffU / opt_n_threads * thr_id;
} else
work.data[19]++;
work.data[27]++;
pthread_mutex_unlock(&g_work_lock);
work_restart[thr_id].restart = 0;
@ -1208,11 +1174,8 @@ static void *miner_thread(void *userdata)
max64 *= thr_hashrates[thr_id];
if (max64 <= 0) {
switch (opt_algo) {
case ALGO_SCRYPT:
max64 = opt_scrypt_n < 16 ? 0x3ffff : 0x3fffff / opt_scrypt_n;
break;
case ALGO_SHA256D:
max64 = 0x1fffff;
case ALGO_LBRY:
max64 = 0x1fffff;
break;
}
}
@ -1226,17 +1189,12 @@ static void *miner_thread(void *userdata)
/* scan nonces for a proof-of-work hash */
switch (opt_algo) {
case ALGO_SCRYPT:
rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target,
max_nonce, &hashes_done, opt_scrypt_n);
case ALGO_LBRY:
rc = scanhash_lbry(thr_id, work.data, work.target,
max_nonce, &hashes_done);
break;
case ALGO_SHA256D:
rc = scanhash_sha256d(thr_id, work.data, work.target,
max_nonce, &hashes_done);
break;
default:
default:
/* should never happen */
goto out;
}
@ -1344,16 +1302,13 @@ start:
}
if (likely(val)) {
bool rc;
applog(LOG_INFO, "LONGPOLL pushed new work");
//applog(LOG_INFO, "LONGPOLL pushed new work");
res = json_object_get(val, "result");
soval = json_object_get(res, "submitold");
submit_old = soval ? json_is_true(soval) : false;
pthread_mutex_lock(&g_work_lock);
work_free(&g_work);
if (have_gbt)
rc = gbt_work_decode(res, &g_work);
else
rc = work_decode(res, &g_work);
rc = gbt_work_decode(res, &g_work);
if (rc) {
time(&g_work_time);
restart_threads();
@ -1566,15 +1521,6 @@ static void parse_arg(int key, char *arg, char *pname)
opt_algo = i;
break;
}
if (arg[v] == ':' && i == ALGO_SCRYPT) {
char *ep;
v = strtol(arg+v+1, &ep, 10);
if (*ep || v & (v-1) || v < 2)
continue;
opt_algo = i;
opt_scrypt_n = v;
break;
}
}
}
if (i == ARRAY_SIZE(algo_names)) {

128
lbry.c Normal file
View file

@ -0,0 +1,128 @@
#include "miner.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "sha3/sph_sha2.h"
#include "sha3/sph_ripemd.h"
//#define DEBUG_ALGO
/* Move init out of loop, so init once externally, and then use one single memcpy with that bigger memory block */
typedef struct {
sph_sha256_context sha256;
sph_sha512_context sha512;
sph_ripemd160_context ripemd;
} lbryhash_context_holder;
/* no need to copy, because close reinit the context */
static THREADLOCAL lbryhash_context_holder ctx;
void init_lbry_contexts(void *dummy)
{
sph_sha256_init(&ctx.sha256);
sph_sha512_init(&ctx.sha512);
sph_ripemd160_init(&ctx.ripemd);
}
void lbryhash(void* output, const void* input)
{
uint32_t hashA[16], hashB[16], hashC[16];
memset(hashA, 0, 16 * sizeof(uint32_t));
memset(hashB, 0, 16 * sizeof(uint32_t));
memset(hashC, 0, 16 * sizeof(uint32_t));
sph_sha256 (&ctx.sha256, input, 112);
sph_sha256_close(&ctx.sha256, hashA);
sph_sha256 (&ctx.sha256, hashA, 32);
sph_sha256_close(&ctx.sha256, hashA);
sph_sha512 (&ctx.sha512, hashA, 32);
sph_sha512_close(&ctx.sha512, hashA);
sph_ripemd160 (&ctx.ripemd, hashA, 32);
sph_ripemd160_close(&ctx.ripemd, hashB);
sph_ripemd160 (&ctx.ripemd, hashA+8, 32);
sph_ripemd160_close(&ctx.ripemd, hashC);
sph_sha256 (&ctx.sha256, hashB, 20);
sph_sha256 (&ctx.sha256, hashC, 20);
sph_sha256_close(&ctx.sha256, hashA);
sph_sha256 (&ctx.sha256, hashA, 32);
sph_sha256_close(&ctx.sha256, hashA);
memcpy(output, hashA, 32);
}
int scanhash_lbry(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, uint64_t *hashes_done)
{
uint32_t n = pdata[27] - 1;
const uint32_t first_nonce = pdata[27];
const uint32_t Htarg = ptarget[7];
uint32_t hash64[8] __attribute__((aligned(32)));
uint32_t endiandata[32];
uint64_t htmax[] = {
0,
0xF,
0xFF,
0xFFF,
0xFFFF,
0x10000000
};
uint32_t masks[] = {
0xFFFFFFFF,
0xFFFFFFF0,
0xFFFFFF00,
0xFFFFF000,
0xFFFF0000,
0
};
// we need bigendian data...
for (int kk=0; kk < 32; kk++) {
be32enc(&endiandata[kk], ((uint32_t*)pdata)[kk]);
};
#ifdef DEBUG_ALGO
printf("[%d] Htarg=%X\n", thr_id, Htarg);
#endif
for (int m=0; m < sizeof(masks); m++) {
if (Htarg <= htmax[m]) {
uint32_t mask = masks[m];
do {
pdata[27] = ++n;
be32enc(&endiandata[27], n);
lbryhash(hash64, &endiandata);
#ifndef DEBUG_ALGO
if ((!(hash64[7] & mask)) && fulltest(hash64, ptarget)) {
*hashes_done = n - first_nonce + 1;
return true;
}
#else
if (!(n % 0x1000) && !thr_id) printf(".");
if (!(hash64[7] & mask)) {
printf("[%d]",thr_id);
if (fulltest(hash64, ptarget)) {
*hashes_done = n - first_nonce + 1;
return true;
}
}
#endif
} while (n < max_nonce && !work_restart[thr_id].restart);
// see blake.c if else to understand the loop on htmax => mask
break;
}
}
*hashes_done = n - first_nonce + 1;
pdata[27] = n;
return 0;
}

View file

@ -58,6 +58,14 @@ enum {
#define likely(expr) (expr)
#endif
#if defined(_MSC_VER)
#define THREADLOCAL __declspec(thread)
#elif defined(__GNUC__)
#define THREADLOCAL __thread
#else
#define THREADLOCAL
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif

348
sha3/md_helper.c Normal file
View file

@ -0,0 +1,348 @@
/* $Id: md_helper.c 216 2010-06-08 09:46:57Z tp $ */
/*
* This file contains some functions which implement the external data
* handling and padding for Merkle-Damgard hash functions which follow
* the conventions set out by MD4 (little-endian) or SHA-1 (big-endian).
*
* API: this file is meant to be included, not compiled as a stand-alone
* file. Some macros must be defined:
* RFUN name for the round function
* HASH "short name" for the hash function
* BE32 defined for big-endian, 32-bit based (e.g. SHA-1)
* LE32 defined for little-endian, 32-bit based (e.g. MD5)
* BE64 defined for big-endian, 64-bit based (e.g. SHA-512)
* LE64 defined for little-endian, 64-bit based (no example yet)
* PW01 if defined, append 0x01 instead of 0x80 (for Tiger)
* BLEN if defined, length of a message block (in bytes)
* PLW1 if defined, length is defined on one 64-bit word only (for Tiger)
* PLW4 if defined, length is defined on four 64-bit words (for WHIRLPOOL)
* SVAL if defined, reference to the context state information
*
* BLEN is used when a message block is not 16 (32-bit or 64-bit) words:
* this is used for instance for Tiger, which works on 64-bit words but
* uses 512-bit message blocks (eight 64-bit words). PLW1 and PLW4 are
* ignored if 32-bit words are used; if 64-bit words are used and PLW1 is
* set, then only one word (64 bits) will be used to encode the input
* message length (in bits), otherwise two words will be used (as in
* SHA-384 and SHA-512). If 64-bit words are used and PLW4 is defined (but
* not PLW1), four 64-bit words will be used to encode the message length
* (in bits). Note that regardless of those settings, only 64-bit message
* lengths are supported (in bits): messages longer than 2 Exabytes will be
* improperly hashed (this is unlikely to happen soon: 2 Exabytes is about
* 2 millions Terabytes, which is huge).
*
* If CLOSE_ONLY is defined, then this file defines only the sph_XXX_close()
* function. This is used for Tiger2, which is identical to Tiger except
* when it comes to the padding (Tiger2 uses the standard 0x80 byte instead
* of the 0x01 from original Tiger).
*
* The RFUN function is invoked with two arguments, the first pointing to
* aligned data (as a "const void *"), the second being state information
* from the context structure. By default, this state information is the
* "val" field from the context, and this field is assumed to be an array
* of words ("sph_u32" or "sph_u64", depending on BE32/LE32/BE64/LE64).
* from the context structure. The "val" field can have any type, except
* for the output encoding which assumes that it is an array of "sph_u32"
* values. By defining NO_OUTPUT, this last step is deactivated; the
* includer code is then responsible for writing out the hash result. When
* NO_OUTPUT is defined, the third parameter to the "close()" function is
* ignored.
*
* ==========================(LICENSE BEGIN)============================
*
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ===========================(LICENSE END)=============================
*
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
*/
#include <sys/types.h>
#include <sha3/sph_types.h>
#ifdef _MSC_VER
#pragma warning (disable: 4146)
#endif
#undef SPH_XCAT
#define SPH_XCAT(a, b) SPH_XCAT_(a, b)
#undef SPH_XCAT_
#define SPH_XCAT_(a, b) a ## b
#undef SPH_BLEN
#undef SPH_WLEN
#if defined BE64 || defined LE64
#define SPH_BLEN 128U
#define SPH_WLEN 8U
#else
#define SPH_BLEN 64U
#define SPH_WLEN 4U
#endif
#ifdef BLEN
#undef SPH_BLEN
#define SPH_BLEN BLEN
#endif
#undef SPH_MAXPAD
#if defined PLW1
#define SPH_MAXPAD (SPH_BLEN - SPH_WLEN)
#elif defined PLW4
#define SPH_MAXPAD (SPH_BLEN - (SPH_WLEN << 2))
#else
#define SPH_MAXPAD (SPH_BLEN - (SPH_WLEN << 1))
#endif
#undef SPH_VAL
#undef SPH_NO_OUTPUT
#ifdef SVAL
#define SPH_VAL SVAL
#define SPH_NO_OUTPUT 1
#else
#define SPH_VAL sc->val
#endif
#ifndef CLOSE_ONLY
#ifdef SPH_UPTR
static void
SPH_XCAT(HASH, _short)(void *cc, const void *data, size_t len)
#else
void
SPH_XCAT(sph_, HASH)(void *cc, const void *data, size_t len)
#endif
{
SPH_XCAT(sph_, SPH_XCAT(HASH, _context)) *sc;
unsigned current;
sc = cc;
#if SPH_64
current = (unsigned)sc->count & (SPH_BLEN - 1U);
#else
current = (unsigned)sc->count_low & (SPH_BLEN - 1U);
#endif
while (len > 0) {
unsigned clen;
#if !SPH_64
sph_u32 clow, clow2;
#endif
clen = SPH_BLEN - current;
if (clen > len)
clen = len;
memcpy(sc->buf + current, data, clen);
data = (const unsigned char *)data + clen;
current += clen;
len -= clen;
if (current == SPH_BLEN) {
RFUN(sc->buf, SPH_VAL);
current = 0;
}
#if SPH_64
sc->count += clen;
#else
clow = sc->count_low;
clow2 = SPH_T32(clow + clen);
sc->count_low = clow2;
if (clow2 < clow)
sc->count_high ++;
#endif
}
}
#ifdef SPH_UPTR
void
SPH_XCAT(sph_, HASH)(void *cc, const void *data, size_t len)
{
SPH_XCAT(sph_, SPH_XCAT(HASH, _context)) *sc;
unsigned current;
size_t orig_len;
#if !SPH_64
sph_u32 clow, clow2;
#endif
if (len < (2 * SPH_BLEN)) {
SPH_XCAT(HASH, _short)(cc, data, len);
return;
}
sc = cc;
#if SPH_64
current = (unsigned)sc->count & (SPH_BLEN - 1U);
#else
current = (unsigned)sc->count_low & (SPH_BLEN - 1U);
#endif
if (current > 0) {
unsigned t;
t = SPH_BLEN - current;
SPH_XCAT(HASH, _short)(cc, data, t);
data = (const unsigned char *)data + t;
len -= t;
}
#if !SPH_UNALIGNED
if (((SPH_UPTR)data & (SPH_WLEN - 1U)) != 0) {
SPH_XCAT(HASH, _short)(cc, data, len);
return;
}
#endif
orig_len = len;
while (len >= SPH_BLEN) {
RFUN(data, SPH_VAL);
len -= SPH_BLEN;
data = (const unsigned char *)data + SPH_BLEN;
}
if (len > 0)
memcpy(sc->buf, data, len);
#if SPH_64
sc->count += (sph_u64)orig_len;
#else
clow = sc->count_low;
clow2 = SPH_T32(clow + orig_len);
sc->count_low = clow2;
if (clow2 < clow)
sc->count_high ++;
/*
* This code handles the improbable situation where "size_t" is
* greater than 32 bits, and yet we do not have a 64-bit type.
*/
orig_len >>= 12;
orig_len >>= 10;
orig_len >>= 10;
sc->count_high += orig_len;
#endif
}
#endif
#endif
/*
* Perform padding and produce result. The context is NOT reinitialized
* by this function.
*/
static void
SPH_XCAT(HASH, _addbits_and_close)(void *cc,
unsigned ub, unsigned n, void *dst, unsigned rnum)
{
SPH_XCAT(sph_, SPH_XCAT(HASH, _context)) *sc;
unsigned current, u;
#if !SPH_64
sph_u32 low, high;
#endif
sc = cc;
#if SPH_64
current = (unsigned)sc->count & (SPH_BLEN - 1U);
#else
current = (unsigned)sc->count_low & (SPH_BLEN - 1U);
#endif
#ifdef PW01
sc->buf[current ++] = (0x100 | (ub & 0xFF)) >> (8 - n);
#else
{
unsigned z;
z = 0x80 >> n;
sc->buf[current ++] = ((ub & -z) | z) & 0xFF;
}
#endif
if (current > SPH_MAXPAD) {
memset(sc->buf + current, 0, SPH_BLEN - current);
RFUN(sc->buf, SPH_VAL);
memset(sc->buf, 0, SPH_MAXPAD);
} else {
memset(sc->buf + current, 0, SPH_MAXPAD - current);
}
#if defined BE64
#if defined PLW1
sph_enc64be_aligned(sc->buf + SPH_MAXPAD,
SPH_T64(sc->count << 3) + (sph_u64)n);
#elif defined PLW4
memset(sc->buf + SPH_MAXPAD, 0, 2 * SPH_WLEN);
sph_enc64be_aligned(sc->buf + SPH_MAXPAD + 2 * SPH_WLEN,
sc->count >> 61);
sph_enc64be_aligned(sc->buf + SPH_MAXPAD + 3 * SPH_WLEN,
SPH_T64(sc->count << 3) + (sph_u64)n);
#else
sph_enc64be_aligned(sc->buf + SPH_MAXPAD, sc->count >> 61);
sph_enc64be_aligned(sc->buf + SPH_MAXPAD + SPH_WLEN,
SPH_T64(sc->count << 3) + (sph_u64)n);
#endif
#elif defined LE64
#if defined PLW1
sph_enc64le_aligned(sc->buf + SPH_MAXPAD,
SPH_T64(sc->count << 3) + (sph_u64)n);
#elif defined PLW1
sph_enc64le_aligned(sc->buf + SPH_MAXPAD,
SPH_T64(sc->count << 3) + (sph_u64)n);
sph_enc64le_aligned(sc->buf + SPH_MAXPAD + SPH_WLEN, sc->count >> 61);
memset(sc->buf + SPH_MAXPAD + 2 * SPH_WLEN, 0, 2 * SPH_WLEN);
#else
sph_enc64le_aligned(sc->buf + SPH_MAXPAD,
SPH_T64(sc->count << 3) + (sph_u64)n);
sph_enc64le_aligned(sc->buf + SPH_MAXPAD + SPH_WLEN, sc->count >> 61);
#endif
#else
#if SPH_64
#ifdef BE32
sph_enc64be_aligned(sc->buf + SPH_MAXPAD,
SPH_T64(sc->count << 3) + (sph_u64)n);
#else
sph_enc64le_aligned(sc->buf + SPH_MAXPAD,
SPH_T64(sc->count << 3) + (sph_u64)n);
#endif
#else
low = sc->count_low;
high = SPH_T32((sc->count_high << 3) | (low >> 29));
low = SPH_T32(low << 3) + (sph_u32)n;
#ifdef BE32
sph_enc32be(sc->buf + SPH_MAXPAD, high);
sph_enc32be(sc->buf + SPH_MAXPAD + SPH_WLEN, low);
#else
sph_enc32le(sc->buf + SPH_MAXPAD, low);
sph_enc32le(sc->buf + SPH_MAXPAD + SPH_WLEN, high);
#endif
#endif
#endif
RFUN(sc->buf, SPH_VAL);
#ifdef SPH_NO_OUTPUT
(void)dst;
(void)rnum;
(void)u;
#else
for (u = 0; u < rnum; u ++) {
#if defined BE64
sph_enc64be((unsigned char *)dst + 8 * u, sc->val[u]);
#elif defined LE64
sph_enc64le((unsigned char *)dst + 8 * u, sc->val[u]);
#elif defined BE32
sph_enc32be((unsigned char *)dst + 4 * u, sc->val[u]);
#else
sph_enc32le((unsigned char *)dst + 4 * u, sc->val[u]);
#endif
}
#endif
}
static void
SPH_XCAT(HASH, _close)(void *cc, void *dst, unsigned rnum)
{
SPH_XCAT(HASH, _addbits_and_close)(cc, 0, 0, dst, rnum);
}

281
sha3/sph_ripemd.h Normal file
View file

@ -0,0 +1,281 @@
/* $Id: sph_ripemd.h 216 2010-06-08 09:46:57Z tp $ */
/**
* RIPEMD, RIPEMD-128 and RIPEMD-160 interface.
*
* RIPEMD was first described in: Research and Development in Advanced
* Communication Technologies in Europe, "RIPE Integrity Primitives:
* Final Report of RACE Integrity Primitives Evaluation (R1040)", RACE,
* June 1992.
*
* A new, strengthened version, dubbed RIPEMD-160, was published in: H.
* Dobbertin, A. Bosselaers, and B. Preneel, "RIPEMD-160, a strengthened
* version of RIPEMD", Fast Software Encryption - FSE'96, LNCS 1039,
* Springer (1996), pp. 71--82.
*
* This article describes both RIPEMD-160, with a 160-bit output, and a
* reduced version called RIPEMD-128, which has a 128-bit output. RIPEMD-128
* was meant as a "drop-in" replacement for any hash function with 128-bit
* output, especially the original RIPEMD.
*
* @warning Collisions, and an efficient method to build other collisions,
* have been published for the original RIPEMD, which is thus considered as
* cryptographically broken. It is also very rarely encountered, and there
* seems to exist no free description or implementation of RIPEMD (except
* the sphlib code, of course). As of january 2007, RIPEMD-128 and RIPEMD-160
* seem as secure as their output length allows.
*
* ==========================(LICENSE BEGIN)============================
*
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ===========================(LICENSE END)=============================
*
* @file sph_ripemd.h
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
*/
#ifndef SPH_RIPEMD_H__
#define SPH_RIPEMD_H__
#include <stddef.h>
#include "sph_types.h"
#ifdef __cplusplus
extern "C"{
#endif
/**
* Output size (in bits) for RIPEMD.
*/
#define SPH_SIZE_ripemd 128
/**
* Output size (in bits) for RIPEMD-128.
*/
#define SPH_SIZE_ripemd128 128
/**
* Output size (in bits) for RIPEMD-160.
*/
#define SPH_SIZE_ripemd160 160
/**
* This structure is a context for RIPEMD computations: it contains the
* intermediate values and some data from the last entered block. Once
* a RIPEMD computation has been performed, the context can be reused for
* another computation.
*
* The contents of this structure are private. A running RIPEMD computation
* can be cloned by copying the context (e.g. with a simple
* <code>memcpy()</code>).
*/
typedef struct {
#ifndef DOXYGEN_IGNORE
unsigned char buf[64]; /* first field, for alignment */
sph_u32 val[4];
#if SPH_64
sph_u64 count;
#else
sph_u32 count_high, count_low;
#endif
#endif
} sph_ripemd_context;
/**
* Initialize a RIPEMD context. This process performs no memory allocation.
*
* @param cc the RIPEMD context (pointer to
* a <code>sph_ripemd_context</code>)
*/
void sph_ripemd_init(void *cc);
/**
* Process some data bytes. It is acceptable that <code>len</code> is zero
* (in which case this function does nothing).
*
* @param cc the RIPEMD context
* @param data the input data
* @param len the input data length (in bytes)
*/
void sph_ripemd(void *cc, const void *data, size_t len);
/**
* Terminate the current RIPEMD computation and output the result into the
* provided buffer. The destination buffer must be wide enough to
* accomodate the result (16 bytes). The context is automatically
* reinitialized.
*
* @param cc the RIPEMD context
* @param dst the destination buffer
*/
void sph_ripemd_close(void *cc, void *dst);
/**
* Apply the RIPEMD compression function on the provided data. The
* <code>msg</code> parameter contains the 16 32-bit input blocks,
* as numerical values (hence after the little-endian decoding). The
* <code>val</code> parameter contains the 5 32-bit input blocks for
* the compression function; the output is written in place in this
* array.
*
* @param msg the message block (16 values)
* @param val the function 128-bit input and output
*/
void sph_ripemd_comp(const sph_u32 msg[16], sph_u32 val[4]);
/* ===================================================================== */
/**
* This structure is a context for RIPEMD-128 computations: it contains the
* intermediate values and some data from the last entered block. Once
* a RIPEMD-128 computation has been performed, the context can be reused for
* another computation.
*
* The contents of this structure are private. A running RIPEMD-128 computation
* can be cloned by copying the context (e.g. with a simple
* <code>memcpy()</code>).
*/
typedef struct {
#ifndef DOXYGEN_IGNORE
unsigned char buf[64]; /* first field, for alignment */
sph_u32 val[4];
#if SPH_64
sph_u64 count;
#else
sph_u32 count_high, count_low;
#endif
#endif
} sph_ripemd128_context;
/**
* Initialize a RIPEMD-128 context. This process performs no memory allocation.
*
* @param cc the RIPEMD-128 context (pointer to
* a <code>sph_ripemd128_context</code>)
*/
void sph_ripemd128_init(void *cc);
/**
* Process some data bytes. It is acceptable that <code>len</code> is zero
* (in which case this function does nothing).
*
* @param cc the RIPEMD-128 context
* @param data the input data
* @param len the input data length (in bytes)
*/
void sph_ripemd128(void *cc, const void *data, size_t len);
/**
* Terminate the current RIPEMD-128 computation and output the result into the
* provided buffer. The destination buffer must be wide enough to
* accomodate the result (16 bytes). The context is automatically
* reinitialized.
*
* @param cc the RIPEMD-128 context
* @param dst the destination buffer
*/
void sph_ripemd128_close(void *cc, void *dst);
/**
* Apply the RIPEMD-128 compression function on the provided data. The
* <code>msg</code> parameter contains the 16 32-bit input blocks,
* as numerical values (hence after the little-endian decoding). The
* <code>val</code> parameter contains the 5 32-bit input blocks for
* the compression function; the output is written in place in this
* array.
*
* @param msg the message block (16 values)
* @param val the function 128-bit input and output
*/
void sph_ripemd128_comp(const sph_u32 msg[16], sph_u32 val[4]);
/* ===================================================================== */
/**
* This structure is a context for RIPEMD-160 computations: it contains the
* intermediate values and some data from the last entered block. Once
* a RIPEMD-160 computation has been performed, the context can be reused for
* another computation.
*
* The contents of this structure are private. A running RIPEMD-160 computation
* can be cloned by copying the context (e.g. with a simple
* <code>memcpy()</code>).
*/
typedef struct {
#ifndef DOXYGEN_IGNORE
unsigned char buf[64]; /* first field, for alignment */
sph_u32 val[5];
#if SPH_64
sph_u64 count;
#else
sph_u32 count_high, count_low;
#endif
#endif
} sph_ripemd160_context;
/**
* Initialize a RIPEMD-160 context. This process performs no memory allocation.
*
* @param cc the RIPEMD-160 context (pointer to
* a <code>sph_ripemd160_context</code>)
*/
void sph_ripemd160_init(void *cc);
/**
* Process some data bytes. It is acceptable that <code>len</code> is zero
* (in which case this function does nothing).
*
* @param cc the RIPEMD-160 context
* @param data the input data
* @param len the input data length (in bytes)
*/
void sph_ripemd160(void *cc, const void *data, size_t len);
/**
* Terminate the current RIPEMD-160 computation and output the result into the
* provided buffer. The destination buffer must be wide enough to
* accomodate the result (20 bytes). The context is automatically
* reinitialized.
*
* @param cc the RIPEMD-160 context
* @param dst the destination buffer
*/
void sph_ripemd160_close(void *cc, void *dst);
/**
* Apply the RIPEMD-160 compression function on the provided data. The
* <code>msg</code> parameter contains the 16 32-bit input blocks,
* as numerical values (hence after the little-endian decoding). The
* <code>val</code> parameter contains the 5 32-bit input blocks for
* the compression function; the output is written in place in this
* array.
*
* @param msg the message block (16 values)
* @param val the function 160-bit input and output
*/
void sph_ripemd160_comp(const sph_u32 msg[16], sph_u32 val[5]);
#ifdef __cplusplus
}
#endif
#endif

378
sha3/sph_sha2.h Normal file
View file

@ -0,0 +1,378 @@
/* $Id: sph_sha2.h 216 2010-06-08 09:46:57Z tp $ */
/**
* SHA-224, SHA-256, SHA-384 and SHA-512 interface.
*
* SHA-256 has been published in FIPS 180-2, now amended with a change
* notice to include SHA-224 as well (which is a simple variation on
* SHA-256). SHA-384 and SHA-512 are also defined in FIPS 180-2. FIPS
* standards can be found at:
* http://csrc.nist.gov/publications/fips/
*
* ==========================(LICENSE BEGIN)============================
*
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ===========================(LICENSE END)=============================
*
* @file sph_sha2.h
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
*/
#ifndef SPH_SHA2_H__
#define SPH_SHA2_H__
#include <stddef.h>
#include "sph_types.h"
#ifdef __cplusplus
extern "C"{
#endif
/**
* Output size (in bits) for SHA-224.
*/
#define SPH_SIZE_sha224 224
/**
* Output size (in bits) for SHA-256.
*/
#define SPH_SIZE_sha256 256
/**
* This structure is a context for SHA-224 computations: it contains the
* intermediate values and some data from the last entered block. Once
* a SHA-224 computation has been performed, the context can be reused for
* another computation.
*
* The contents of this structure are private. A running SHA-224 computation
* can be cloned by copying the context (e.g. with a simple
* <code>memcpy()</code>).
*/
typedef struct {
#ifndef DOXYGEN_IGNORE
unsigned char buf[64]; /* first field, for alignment */
sph_u32 val[8];
#if SPH_64
sph_u64 count;
#else
sph_u32 count_high, count_low;
#endif
#endif
} sph_sha224_context;
/**
* This structure is a context for SHA-256 computations. It is identical
* to the SHA-224 context. However, a context is initialized for SHA-224
* <strong>or</strong> SHA-256, but not both (the internal IV is not the
* same).
*/
typedef sph_sha224_context sph_sha256_context;
/**
* Initialize a SHA-224 context. This process performs no memory allocation.
*
* @param cc the SHA-224 context (pointer to
* a <code>sph_sha224_context</code>)
*/
void sph_sha224_init(void *cc);
/**
* Process some data bytes. It is acceptable that <code>len</code> is zero
* (in which case this function does nothing).
*
* @param cc the SHA-224 context
* @param data the input data
* @param len the input data length (in bytes)
*/
void sph_sha224(void *cc, const void *data, size_t len);
/**
* Terminate the current SHA-224 computation and output the result into the
* provided buffer. The destination buffer must be wide enough to
* accomodate the result (28 bytes). The context is automatically
* reinitialized.
*
* @param cc the SHA-224 context
* @param dst the destination buffer
*/
void sph_sha224_close(void *cc, void *dst);
/**
* Add a few additional bits (0 to 7) to the current computation, then
* terminate it and output the result in the provided buffer, which must
* be wide enough to accomodate the result (28 bytes). If bit number i
* in <code>ub</code> has value 2^i, then the extra bits are those
* numbered 7 downto 8-n (this is the big-endian convention at the byte
* level). The context is automatically reinitialized.
*
* @param cc the SHA-224 context
* @param ub the extra bits
* @param n the number of extra bits (0 to 7)
* @param dst the destination buffer
*/
void sph_sha224_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst);
/**
* Apply the SHA-224 compression function on the provided data. The
* <code>msg</code> parameter contains the 16 32-bit input blocks,
* as numerical values (hence after the big-endian decoding). The
* <code>val</code> parameter contains the 8 32-bit input blocks for
* the compression function; the output is written in place in this
* array.
*
* @param msg the message block (16 values)
* @param val the function 256-bit input and output
*/
void sph_sha224_comp(const sph_u32 msg[16], sph_u32 val[8]);
/**
* Initialize a SHA-256 context. This process performs no memory allocation.
*
* @param cc the SHA-256 context (pointer to
* a <code>sph_sha256_context</code>)
*/
void sph_sha256_init(void *cc);
#ifdef DOXYGEN_IGNORE
/**
* Process some data bytes, for SHA-256. This function is identical to
* <code>sha_224()</code>
*
* @param cc the SHA-224 context
* @param data the input data
* @param len the input data length (in bytes)
*/
void sph_sha256(void *cc, const void *data, size_t len);
#endif
#ifndef DOXYGEN_IGNORE
#define sph_sha256 sph_sha224
#endif
/**
* Terminate the current SHA-256 computation and output the result into the
* provided buffer. The destination buffer must be wide enough to
* accomodate the result (32 bytes). The context is automatically
* reinitialized.
*
* @param cc the SHA-256 context
* @param dst the destination buffer
*/
void sph_sha256_close(void *cc, void *dst);
/**
* Add a few additional bits (0 to 7) to the current computation, then
* terminate it and output the result in the provided buffer, which must
* be wide enough to accomodate the result (32 bytes). If bit number i
* in <code>ub</code> has value 2^i, then the extra bits are those
* numbered 7 downto 8-n (this is the big-endian convention at the byte
* level). The context is automatically reinitialized.
*
* @param cc the SHA-256 context
* @param ub the extra bits
* @param n the number of extra bits (0 to 7)
* @param dst the destination buffer
*/
void sph_sha256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst);
#ifdef DOXYGEN_IGNORE
/**
* Apply the SHA-256 compression function on the provided data. This
* function is identical to <code>sha224_comp()</code>.
*
* @param msg the message block (16 values)
* @param val the function 256-bit input and output
*/
void sph_sha256_comp(const sph_u32 msg[16], sph_u32 val[8]);
#endif
#ifndef DOXYGEN_IGNORE
#define sph_sha256_comp sph_sha224_comp
#endif
#if SPH_64
/**
* Output size (in bits) for SHA-384.
*/
#define SPH_SIZE_sha384 384
/**
* Output size (in bits) for SHA-512.
*/
#define SPH_SIZE_sha512 512
/**
* This structure is a context for SHA-384 computations: it contains the
* intermediate values and some data from the last entered block. Once
* a SHA-384 computation has been performed, the context can be reused for
* another computation.
*
* The contents of this structure are private. A running SHA-384 computation
* can be cloned by copying the context (e.g. with a simple
* <code>memcpy()</code>).
*/
typedef struct {
#ifndef DOXYGEN_IGNORE
unsigned char buf[128]; /* first field, for alignment */
sph_u64 val[8];
sph_u64 count;
#endif
} sph_sha384_context;
/**
* Initialize a SHA-384 context. This process performs no memory allocation.
*
* @param cc the SHA-384 context (pointer to
* a <code>sph_sha384_context</code>)
*/
void sph_sha384_init(void *cc);
/**
* Process some data bytes. It is acceptable that <code>len</code> is zero
* (in which case this function does nothing).
*
* @param cc the SHA-384 context
* @param data the input data
* @param len the input data length (in bytes)
*/
void sph_sha384(void *cc, const void *data, size_t len);
/**
* Terminate the current SHA-384 computation and output the result into the
* provided buffer. The destination buffer must be wide enough to
* accomodate the result (48 bytes). The context is automatically
* reinitialized.
*
* @param cc the SHA-384 context
* @param dst the destination buffer
*/
void sph_sha384_close(void *cc, void *dst);
/**
* Add a few additional bits (0 to 7) to the current computation, then
* terminate it and output the result in the provided buffer, which must
* be wide enough to accomodate the result (48 bytes). If bit number i
* in <code>ub</code> has value 2^i, then the extra bits are those
* numbered 7 downto 8-n (this is the big-endian convention at the byte
* level). The context is automatically reinitialized.
*
* @param cc the SHA-384 context
* @param ub the extra bits
* @param n the number of extra bits (0 to 7)
* @param dst the destination buffer
*/
void sph_sha384_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst);
/**
* Apply the SHA-384 compression function on the provided data. The
* <code>msg</code> parameter contains the 16 64-bit input blocks,
* as numerical values (hence after the big-endian decoding). The
* <code>val</code> parameter contains the 8 64-bit input blocks for
* the compression function; the output is written in place in this
* array.
*
* @param msg the message block (16 values)
* @param val the function 512-bit input and output
*/
void sph_sha384_comp(const sph_u64 msg[16], sph_u64 val[8]);
/**
* This structure is a context for SHA-512 computations. It is identical
* to the SHA-384 context. However, a context is initialized for SHA-384
* <strong>or</strong> SHA-512, but not both (the internal IV is not the
* same).
*/
typedef sph_sha384_context sph_sha512_context;
/**
* Initialize a SHA-512 context. This process performs no memory allocation.
*
* @param cc the SHA-512 context (pointer to
* a <code>sph_sha512_context</code>)
*/
void sph_sha512_init(void *cc);
#ifdef DOXYGEN_IGNORE
/**
* Process some data bytes, for SHA-512. This function is identical to
* <code>sph_sha384()</code>.
*
* @param cc the SHA-384 context
* @param data the input data
* @param len the input data length (in bytes)
*/
void sph_sha512(void *cc, const void *data, size_t len);
#endif
#ifndef DOXYGEN_IGNORE
#define sph_sha512 sph_sha384
#endif
/**
* Terminate the current SHA-512 computation and output the result into the
* provided buffer. The destination buffer must be wide enough to
* accomodate the result (64 bytes). The context is automatically
* reinitialized.
*
* @param cc the SHA-512 context
* @param dst the destination buffer
*/
void sph_sha512_close(void *cc, void *dst);
/**
* Add a few additional bits (0 to 7) to the current computation, then
* terminate it and output the result in the provided buffer, which must
* be wide enough to accomodate the result (64 bytes). If bit number i
* in <code>ub</code> has value 2^i, then the extra bits are those
* numbered 7 downto 8-n (this is the big-endian convention at the byte
* level). The context is automatically reinitialized.
*
* @param cc the SHA-512 context
* @param ub the extra bits
* @param n the number of extra bits (0 to 7)
* @param dst the destination buffer
*/
void sph_sha512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst);
#ifdef DOXYGEN_IGNORE
/**
* Apply the SHA-512 compression function. This function is identical to
* <code>sph_sha384_comp()</code>.
*
* @param msg the message block (16 values)
* @param val the function 512-bit input and output
*/
void sph_sha512_comp(const sph_u64 msg[16], sph_u64 val[8]);
#endif
#ifndef DOXYGEN_IGNORE
#define sph_sha512_comp sph_sha384_comp
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif

1976
sha3/sph_types.h Normal file

File diff suppressed because it is too large Load diff

841
sph_ripemd.c Normal file
View file

@ -0,0 +1,841 @@
/* $Id: ripemd.c 216 2010-06-08 09:46:57Z tp $ */
/*
* RIPEMD-160 implementation.
*
* ==========================(LICENSE BEGIN)============================
*
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ===========================(LICENSE END)=============================
*
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
*/
#include <stddef.h>
#include <string.h>
#include "sph_ripemd.h"
#ifdef __cplusplus
extern "C"{
#endif
/*
* Round functions for RIPEMD (original).
*/
#define F(x, y, z) ((((y) ^ (z)) & (x)) ^ (z))
#define G(x, y, z) (((x) & (y)) | (((x) | (y)) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
static const sph_u32 oIV[5] = {
SPH_C32(0x67452301), SPH_C32(0xEFCDAB89),
SPH_C32(0x98BADCFE), SPH_C32(0x10325476)
};
/*
* Round functions for RIPEMD-128 and RIPEMD-160.
*/
#define F1(x, y, z) ((x) ^ (y) ^ (z))
#define F2(x, y, z) ((((y) ^ (z)) & (x)) ^ (z))
#define F3(x, y, z) (((x) | ~(y)) ^ (z))
#define F4(x, y, z) ((((x) ^ (y)) & (z)) ^ (y))
#define F5(x, y, z) ((x) ^ ((y) | ~(z)))
static const sph_u32 IV[5] = {
SPH_C32(0x67452301), SPH_C32(0xEFCDAB89), SPH_C32(0x98BADCFE),
SPH_C32(0x10325476), SPH_C32(0xC3D2E1F0)
};
#define ROTL SPH_ROTL32
/* ===================================================================== */
/*
* RIPEMD (original hash, deprecated).
*/
#define FF1(A, B, C, D, X, s) do { \
sph_u32 tmp = SPH_T32((A) + F(B, C, D) + (X)); \
(A) = ROTL(tmp, (s)); \
} while (0)
#define GG1(A, B, C, D, X, s) do { \
sph_u32 tmp = SPH_T32((A) + G(B, C, D) \
+ (X) + SPH_C32(0x5A827999)); \
(A) = ROTL(tmp, (s)); \
} while (0)
#define HH1(A, B, C, D, X, s) do { \
sph_u32 tmp = SPH_T32((A) + H(B, C, D) \
+ (X) + SPH_C32(0x6ED9EBA1)); \
(A) = ROTL(tmp, (s)); \
} while (0)
#define FF2(A, B, C, D, X, s) do { \
sph_u32 tmp = SPH_T32((A) + F(B, C, D) \
+ (X) + SPH_C32(0x50A28BE6)); \
(A) = ROTL(tmp, (s)); \
} while (0)
#define GG2(A, B, C, D, X, s) do { \
sph_u32 tmp = SPH_T32((A) + G(B, C, D) + (X)); \
(A) = ROTL(tmp, (s)); \
} while (0)
#define HH2(A, B, C, D, X, s) do { \
sph_u32 tmp = SPH_T32((A) + H(B, C, D) \
+ (X) + SPH_C32(0x5C4DD124)); \
(A) = ROTL(tmp, (s)); \
} while (0)
#define RIPEMD_ROUND_BODY(in, h) do { \
sph_u32 A1, B1, C1, D1; \
sph_u32 A2, B2, C2, D2; \
sph_u32 tmp; \
\
A1 = A2 = (h)[0]; \
B1 = B2 = (h)[1]; \
C1 = C2 = (h)[2]; \
D1 = D2 = (h)[3]; \
\
FF1(A1, B1, C1, D1, in( 0), 11); \
FF1(D1, A1, B1, C1, in( 1), 14); \
FF1(C1, D1, A1, B1, in( 2), 15); \
FF1(B1, C1, D1, A1, in( 3), 12); \
FF1(A1, B1, C1, D1, in( 4), 5); \
FF1(D1, A1, B1, C1, in( 5), 8); \
FF1(C1, D1, A1, B1, in( 6), 7); \
FF1(B1, C1, D1, A1, in( 7), 9); \
FF1(A1, B1, C1, D1, in( 8), 11); \
FF1(D1, A1, B1, C1, in( 9), 13); \
FF1(C1, D1, A1, B1, in(10), 14); \
FF1(B1, C1, D1, A1, in(11), 15); \
FF1(A1, B1, C1, D1, in(12), 6); \
FF1(D1, A1, B1, C1, in(13), 7); \
FF1(C1, D1, A1, B1, in(14), 9); \
FF1(B1, C1, D1, A1, in(15), 8); \
\
GG1(A1, B1, C1, D1, in( 7), 7); \
GG1(D1, A1, B1, C1, in( 4), 6); \
GG1(C1, D1, A1, B1, in(13), 8); \
GG1(B1, C1, D1, A1, in( 1), 13); \
GG1(A1, B1, C1, D1, in(10), 11); \
GG1(D1, A1, B1, C1, in( 6), 9); \
GG1(C1, D1, A1, B1, in(15), 7); \
GG1(B1, C1, D1, A1, in( 3), 15); \
GG1(A1, B1, C1, D1, in(12), 7); \
GG1(D1, A1, B1, C1, in( 0), 12); \
GG1(C1, D1, A1, B1, in( 9), 15); \
GG1(B1, C1, D1, A1, in( 5), 9); \
GG1(A1, B1, C1, D1, in(14), 7); \
GG1(D1, A1, B1, C1, in( 2), 11); \
GG1(C1, D1, A1, B1, in(11), 13); \
GG1(B1, C1, D1, A1, in( 8), 12); \
\
HH1(A1, B1, C1, D1, in( 3), 11); \
HH1(D1, A1, B1, C1, in(10), 13); \
HH1(C1, D1, A1, B1, in( 2), 14); \
HH1(B1, C1, D1, A1, in( 4), 7); \
HH1(A1, B1, C1, D1, in( 9), 14); \
HH1(D1, A1, B1, C1, in(15), 9); \
HH1(C1, D1, A1, B1, in( 8), 13); \
HH1(B1, C1, D1, A1, in( 1), 15); \
HH1(A1, B1, C1, D1, in(14), 6); \
HH1(D1, A1, B1, C1, in( 7), 8); \
HH1(C1, D1, A1, B1, in( 0), 13); \
HH1(B1, C1, D1, A1, in( 6), 6); \
HH1(A1, B1, C1, D1, in(11), 12); \
HH1(D1, A1, B1, C1, in(13), 5); \
HH1(C1, D1, A1, B1, in( 5), 7); \
HH1(B1, C1, D1, A1, in(12), 5); \
\
FF2(A2, B2, C2, D2, in( 0), 11); \
FF2(D2, A2, B2, C2, in( 1), 14); \
FF2(C2, D2, A2, B2, in( 2), 15); \
FF2(B2, C2, D2, A2, in( 3), 12); \
FF2(A2, B2, C2, D2, in( 4), 5); \
FF2(D2, A2, B2, C2, in( 5), 8); \
FF2(C2, D2, A2, B2, in( 6), 7); \
FF2(B2, C2, D2, A2, in( 7), 9); \
FF2(A2, B2, C2, D2, in( 8), 11); \
FF2(D2, A2, B2, C2, in( 9), 13); \
FF2(C2, D2, A2, B2, in(10), 14); \
FF2(B2, C2, D2, A2, in(11), 15); \
FF2(A2, B2, C2, D2, in(12), 6); \
FF2(D2, A2, B2, C2, in(13), 7); \
FF2(C2, D2, A2, B2, in(14), 9); \
FF2(B2, C2, D2, A2, in(15), 8); \
\
GG2(A2, B2, C2, D2, in( 7), 7); \
GG2(D2, A2, B2, C2, in( 4), 6); \
GG2(C2, D2, A2, B2, in(13), 8); \
GG2(B2, C2, D2, A2, in( 1), 13); \
GG2(A2, B2, C2, D2, in(10), 11); \
GG2(D2, A2, B2, C2, in( 6), 9); \
GG2(C2, D2, A2, B2, in(15), 7); \
GG2(B2, C2, D2, A2, in( 3), 15); \
GG2(A2, B2, C2, D2, in(12), 7); \
GG2(D2, A2, B2, C2, in( 0), 12); \
GG2(C2, D2, A2, B2, in( 9), 15); \
GG2(B2, C2, D2, A2, in( 5), 9); \
GG2(A2, B2, C2, D2, in(14), 7); \
GG2(D2, A2, B2, C2, in( 2), 11); \
GG2(C2, D2, A2, B2, in(11), 13); \
GG2(B2, C2, D2, A2, in( 8), 12); \
\
HH2(A2, B2, C2, D2, in( 3), 11); \
HH2(D2, A2, B2, C2, in(10), 13); \
HH2(C2, D2, A2, B2, in( 2), 14); \
HH2(B2, C2, D2, A2, in( 4), 7); \
HH2(A2, B2, C2, D2, in( 9), 14); \
HH2(D2, A2, B2, C2, in(15), 9); \
HH2(C2, D2, A2, B2, in( 8), 13); \
HH2(B2, C2, D2, A2, in( 1), 15); \
HH2(A2, B2, C2, D2, in(14), 6); \
HH2(D2, A2, B2, C2, in( 7), 8); \
HH2(C2, D2, A2, B2, in( 0), 13); \
HH2(B2, C2, D2, A2, in( 6), 6); \
HH2(A2, B2, C2, D2, in(11), 12); \
HH2(D2, A2, B2, C2, in(13), 5); \
HH2(C2, D2, A2, B2, in( 5), 7); \
HH2(B2, C2, D2, A2, in(12), 5); \
\
tmp = SPH_T32((h)[1] + C1 + D2); \
(h)[1] = SPH_T32((h)[2] + D1 + A2); \
(h)[2] = SPH_T32((h)[3] + A1 + B2); \
(h)[3] = SPH_T32((h)[0] + B1 + C2); \
(h)[0] = tmp; \
} while (0)
/*
* One round of RIPEMD. The data must be aligned for 32-bit access.
*/
static void
ripemd_round(const unsigned char *data, sph_u32 r[5])
{
#if SPH_LITTLE_FAST
#define RIPEMD_IN(x) sph_dec32le_aligned(data + (4 * (x)))
#else
sph_u32 X_var[16];
int i;
for (i = 0; i < 16; i ++)
X_var[i] = sph_dec32le_aligned(data + 4 * i);
#define RIPEMD_IN(x) X_var[x]
#endif
RIPEMD_ROUND_BODY(RIPEMD_IN, r);
#undef RIPEMD_IN
}
/* see sph_ripemd.h */
void
sph_ripemd_init(void *cc)
{
sph_ripemd_context *sc;
sc = cc;
memcpy(sc->val, oIV, sizeof sc->val);
#if SPH_64
sc->count = 0;
#else
sc->count_high = sc->count_low = 0;
#endif
}
#define RFUN ripemd_round
#define HASH ripemd
#define LE32 1
#include "md_helper.c"
#undef RFUN
#undef HASH
#undef LE32
/* see sph_ripemd.h */
void
sph_ripemd_close(void *cc, void *dst)
{
ripemd_close(cc, dst, 4);
sph_ripemd_init(cc);
}
/* see sph_ripemd.h */
void
sph_ripemd_comp(const sph_u32 msg[16], sph_u32 val[4])
{
#define RIPEMD_IN(x) msg[x]
RIPEMD_ROUND_BODY(RIPEMD_IN, val);
#undef RIPEMD_IN
}
/* ===================================================================== */
/*
* RIPEMD-128.
*/
/*
* Round constants for RIPEMD-128.
*/
#define sK11 SPH_C32(0x00000000)
#define sK12 SPH_C32(0x5A827999)
#define sK13 SPH_C32(0x6ED9EBA1)
#define sK14 SPH_C32(0x8F1BBCDC)
#define sK21 SPH_C32(0x50A28BE6)
#define sK22 SPH_C32(0x5C4DD124)
#define sK23 SPH_C32(0x6D703EF3)
#define sK24 SPH_C32(0x00000000)
#define sRR(a, b, c, d, f, s, r, k) do { \
a = ROTL(SPH_T32(a + f(b, c, d) + r + k), s); \
} while (0)
#define sROUND1(a, b, c, d, f, s, r, k) \
sRR(a ## 1, b ## 1, c ## 1, d ## 1, f, s, r, sK1 ## k)
#define sROUND2(a, b, c, d, f, s, r, k) \
sRR(a ## 2, b ## 2, c ## 2, d ## 2, f, s, r, sK2 ## k)
/*
* This macro defines the body for a RIPEMD-128 compression function
* implementation. The "in" parameter should evaluate, when applied to a
* numerical input parameter from 0 to 15, to an expression which yields
* the corresponding input block. The "h" parameter should evaluate to
* an array or pointer expression designating the array of 4 words which
* contains the input and output of the compression function.
*/
#define RIPEMD128_ROUND_BODY(in, h) do { \
sph_u32 A1, B1, C1, D1; \
sph_u32 A2, B2, C2, D2; \
sph_u32 tmp; \
\
A1 = A2 = (h)[0]; \
B1 = B2 = (h)[1]; \
C1 = C2 = (h)[2]; \
D1 = D2 = (h)[3]; \
\
sROUND1(A, B, C, D, F1, 11, in( 0), 1); \
sROUND1(D, A, B, C, F1, 14, in( 1), 1); \
sROUND1(C, D, A, B, F1, 15, in( 2), 1); \
sROUND1(B, C, D, A, F1, 12, in( 3), 1); \
sROUND1(A, B, C, D, F1, 5, in( 4), 1); \
sROUND1(D, A, B, C, F1, 8, in( 5), 1); \
sROUND1(C, D, A, B, F1, 7, in( 6), 1); \
sROUND1(B, C, D, A, F1, 9, in( 7), 1); \
sROUND1(A, B, C, D, F1, 11, in( 8), 1); \
sROUND1(D, A, B, C, F1, 13, in( 9), 1); \
sROUND1(C, D, A, B, F1, 14, in(10), 1); \
sROUND1(B, C, D, A, F1, 15, in(11), 1); \
sROUND1(A, B, C, D, F1, 6, in(12), 1); \
sROUND1(D, A, B, C, F1, 7, in(13), 1); \
sROUND1(C, D, A, B, F1, 9, in(14), 1); \
sROUND1(B, C, D, A, F1, 8, in(15), 1); \
\
sROUND1(A, B, C, D, F2, 7, in( 7), 2); \
sROUND1(D, A, B, C, F2, 6, in( 4), 2); \
sROUND1(C, D, A, B, F2, 8, in(13), 2); \
sROUND1(B, C, D, A, F2, 13, in( 1), 2); \
sROUND1(A, B, C, D, F2, 11, in(10), 2); \
sROUND1(D, A, B, C, F2, 9, in( 6), 2); \
sROUND1(C, D, A, B, F2, 7, in(15), 2); \
sROUND1(B, C, D, A, F2, 15, in( 3), 2); \
sROUND1(A, B, C, D, F2, 7, in(12), 2); \
sROUND1(D, A, B, C, F2, 12, in( 0), 2); \
sROUND1(C, D, A, B, F2, 15, in( 9), 2); \
sROUND1(B, C, D, A, F2, 9, in( 5), 2); \
sROUND1(A, B, C, D, F2, 11, in( 2), 2); \
sROUND1(D, A, B, C, F2, 7, in(14), 2); \
sROUND1(C, D, A, B, F2, 13, in(11), 2); \
sROUND1(B, C, D, A, F2, 12, in( 8), 2); \
\
sROUND1(A, B, C, D, F3, 11, in( 3), 3); \
sROUND1(D, A, B, C, F3, 13, in(10), 3); \
sROUND1(C, D, A, B, F3, 6, in(14), 3); \
sROUND1(B, C, D, A, F3, 7, in( 4), 3); \
sROUND1(A, B, C, D, F3, 14, in( 9), 3); \
sROUND1(D, A, B, C, F3, 9, in(15), 3); \
sROUND1(C, D, A, B, F3, 13, in( 8), 3); \
sROUND1(B, C, D, A, F3, 15, in( 1), 3); \
sROUND1(A, B, C, D, F3, 14, in( 2), 3); \
sROUND1(D, A, B, C, F3, 8, in( 7), 3); \
sROUND1(C, D, A, B, F3, 13, in( 0), 3); \
sROUND1(B, C, D, A, F3, 6, in( 6), 3); \
sROUND1(A, B, C, D, F3, 5, in(13), 3); \
sROUND1(D, A, B, C, F3, 12, in(11), 3); \
sROUND1(C, D, A, B, F3, 7, in( 5), 3); \
sROUND1(B, C, D, A, F3, 5, in(12), 3); \
\
sROUND1(A, B, C, D, F4, 11, in( 1), 4); \
sROUND1(D, A, B, C, F4, 12, in( 9), 4); \
sROUND1(C, D, A, B, F4, 14, in(11), 4); \
sROUND1(B, C, D, A, F4, 15, in(10), 4); \
sROUND1(A, B, C, D, F4, 14, in( 0), 4); \
sROUND1(D, A, B, C, F4, 15, in( 8), 4); \
sROUND1(C, D, A, B, F4, 9, in(12), 4); \
sROUND1(B, C, D, A, F4, 8, in( 4), 4); \
sROUND1(A, B, C, D, F4, 9, in(13), 4); \
sROUND1(D, A, B, C, F4, 14, in( 3), 4); \
sROUND1(C, D, A, B, F4, 5, in( 7), 4); \
sROUND1(B, C, D, A, F4, 6, in(15), 4); \
sROUND1(A, B, C, D, F4, 8, in(14), 4); \
sROUND1(D, A, B, C, F4, 6, in( 5), 4); \
sROUND1(C, D, A, B, F4, 5, in( 6), 4); \
sROUND1(B, C, D, A, F4, 12, in( 2), 4); \
\
sROUND2(A, B, C, D, F4, 8, in( 5), 1); \
sROUND2(D, A, B, C, F4, 9, in(14), 1); \
sROUND2(C, D, A, B, F4, 9, in( 7), 1); \
sROUND2(B, C, D, A, F4, 11, in( 0), 1); \
sROUND2(A, B, C, D, F4, 13, in( 9), 1); \
sROUND2(D, A, B, C, F4, 15, in( 2), 1); \
sROUND2(C, D, A, B, F4, 15, in(11), 1); \
sROUND2(B, C, D, A, F4, 5, in( 4), 1); \
sROUND2(A, B, C, D, F4, 7, in(13), 1); \
sROUND2(D, A, B, C, F4, 7, in( 6), 1); \
sROUND2(C, D, A, B, F4, 8, in(15), 1); \
sROUND2(B, C, D, A, F4, 11, in( 8), 1); \
sROUND2(A, B, C, D, F4, 14, in( 1), 1); \
sROUND2(D, A, B, C, F4, 14, in(10), 1); \
sROUND2(C, D, A, B, F4, 12, in( 3), 1); \
sROUND2(B, C, D, A, F4, 6, in(12), 1); \
\
sROUND2(A, B, C, D, F3, 9, in( 6), 2); \
sROUND2(D, A, B, C, F3, 13, in(11), 2); \
sROUND2(C, D, A, B, F3, 15, in( 3), 2); \
sROUND2(B, C, D, A, F3, 7, in( 7), 2); \
sROUND2(A, B, C, D, F3, 12, in( 0), 2); \
sROUND2(D, A, B, C, F3, 8, in(13), 2); \
sROUND2(C, D, A, B, F3, 9, in( 5), 2); \
sROUND2(B, C, D, A, F3, 11, in(10), 2); \
sROUND2(A, B, C, D, F3, 7, in(14), 2); \
sROUND2(D, A, B, C, F3, 7, in(15), 2); \
sROUND2(C, D, A, B, F3, 12, in( 8), 2); \
sROUND2(B, C, D, A, F3, 7, in(12), 2); \
sROUND2(A, B, C, D, F3, 6, in( 4), 2); \
sROUND2(D, A, B, C, F3, 15, in( 9), 2); \
sROUND2(C, D, A, B, F3, 13, in( 1), 2); \
sROUND2(B, C, D, A, F3, 11, in( 2), 2); \
\
sROUND2(A, B, C, D, F2, 9, in(15), 3); \
sROUND2(D, A, B, C, F2, 7, in( 5), 3); \
sROUND2(C, D, A, B, F2, 15, in( 1), 3); \
sROUND2(B, C, D, A, F2, 11, in( 3), 3); \
sROUND2(A, B, C, D, F2, 8, in( 7), 3); \
sROUND2(D, A, B, C, F2, 6, in(14), 3); \
sROUND2(C, D, A, B, F2, 6, in( 6), 3); \
sROUND2(B, C, D, A, F2, 14, in( 9), 3); \
sROUND2(A, B, C, D, F2, 12, in(11), 3); \
sROUND2(D, A, B, C, F2, 13, in( 8), 3); \
sROUND2(C, D, A, B, F2, 5, in(12), 3); \
sROUND2(B, C, D, A, F2, 14, in( 2), 3); \
sROUND2(A, B, C, D, F2, 13, in(10), 3); \
sROUND2(D, A, B, C, F2, 13, in( 0), 3); \
sROUND2(C, D, A, B, F2, 7, in( 4), 3); \
sROUND2(B, C, D, A, F2, 5, in(13), 3); \
\
sROUND2(A, B, C, D, F1, 15, in( 8), 4); \
sROUND2(D, A, B, C, F1, 5, in( 6), 4); \
sROUND2(C, D, A, B, F1, 8, in( 4), 4); \
sROUND2(B, C, D, A, F1, 11, in( 1), 4); \
sROUND2(A, B, C, D, F1, 14, in( 3), 4); \
sROUND2(D, A, B, C, F1, 14, in(11), 4); \
sROUND2(C, D, A, B, F1, 6, in(15), 4); \
sROUND2(B, C, D, A, F1, 14, in( 0), 4); \
sROUND2(A, B, C, D, F1, 6, in( 5), 4); \
sROUND2(D, A, B, C, F1, 9, in(12), 4); \
sROUND2(C, D, A, B, F1, 12, in( 2), 4); \
sROUND2(B, C, D, A, F1, 9, in(13), 4); \
sROUND2(A, B, C, D, F1, 12, in( 9), 4); \
sROUND2(D, A, B, C, F1, 5, in( 7), 4); \
sROUND2(C, D, A, B, F1, 15, in(10), 4); \
sROUND2(B, C, D, A, F1, 8, in(14), 4); \
\
tmp = SPH_T32((h)[1] + C1 + D2); \
(h)[1] = SPH_T32((h)[2] + D1 + A2); \
(h)[2] = SPH_T32((h)[3] + A1 + B2); \
(h)[3] = SPH_T32((h)[0] + B1 + C2); \
(h)[0] = tmp; \
} while (0)
/*
* One round of RIPEMD-128. The data must be aligned for 32-bit access.
*/
static void
ripemd128_round(const unsigned char *data, sph_u32 r[5])
{
#if SPH_LITTLE_FAST
#define RIPEMD128_IN(x) sph_dec32le_aligned(data + (4 * (x)))
#else
sph_u32 X_var[16];
int i;
for (i = 0; i < 16; i ++)
X_var[i] = sph_dec32le_aligned(data + 4 * i);
#define RIPEMD128_IN(x) X_var[x]
#endif
RIPEMD128_ROUND_BODY(RIPEMD128_IN, r);
#undef RIPEMD128_IN
}
/* see sph_ripemd.h */
void
sph_ripemd128_init(void *cc)
{
sph_ripemd128_context *sc;
sc = cc;
memcpy(sc->val, IV, sizeof sc->val);
#if SPH_64
sc->count = 0;
#else
sc->count_high = sc->count_low = 0;
#endif
}
#define RFUN ripemd128_round
#define HASH ripemd128
#define LE32 1
#include "md_helper.c"
#undef RFUN
#undef HASH
#undef LE32
/* see sph_ripemd.h */
void
sph_ripemd128_close(void *cc, void *dst)
{
ripemd128_close(cc, dst, 4);
sph_ripemd128_init(cc);
}
/* see sph_ripemd.h */
void
sph_ripemd128_comp(const sph_u32 msg[16], sph_u32 val[4])
{
#define RIPEMD128_IN(x) msg[x]
RIPEMD128_ROUND_BODY(RIPEMD128_IN, val);
#undef RIPEMD128_IN
}
/* ===================================================================== */
/*
* RIPEMD-160.
*/
/*
* Round constants for RIPEMD-160.
*/
#define K11 SPH_C32(0x00000000)
#define K12 SPH_C32(0x5A827999)
#define K13 SPH_C32(0x6ED9EBA1)
#define K14 SPH_C32(0x8F1BBCDC)
#define K15 SPH_C32(0xA953FD4E)
#define K21 SPH_C32(0x50A28BE6)
#define K22 SPH_C32(0x5C4DD124)
#define K23 SPH_C32(0x6D703EF3)
#define K24 SPH_C32(0x7A6D76E9)
#define K25 SPH_C32(0x00000000)
#define RR(a, b, c, d, e, f, s, r, k) do { \
a = SPH_T32(ROTL(SPH_T32(a + f(b, c, d) + r + k), s) + e); \
c = ROTL(c, 10); \
} while (0)
#define ROUND1(a, b, c, d, e, f, s, r, k) \
RR(a ## 1, b ## 1, c ## 1, d ## 1, e ## 1, f, s, r, K1 ## k)
#define ROUND2(a, b, c, d, e, f, s, r, k) \
RR(a ## 2, b ## 2, c ## 2, d ## 2, e ## 2, f, s, r, K2 ## k)
/*
* This macro defines the body for a RIPEMD-160 compression function
* implementation. The "in" parameter should evaluate, when applied to a
* numerical input parameter from 0 to 15, to an expression which yields
* the corresponding input block. The "h" parameter should evaluate to
* an array or pointer expression designating the array of 5 words which
* contains the input and output of the compression function.
*/
#define RIPEMD160_ROUND_BODY(in, h) do { \
sph_u32 A1, B1, C1, D1, E1; \
sph_u32 A2, B2, C2, D2, E2; \
sph_u32 tmp; \
\
A1 = A2 = (h)[0]; \
B1 = B2 = (h)[1]; \
C1 = C2 = (h)[2]; \
D1 = D2 = (h)[3]; \
E1 = E2 = (h)[4]; \
\
ROUND1(A, B, C, D, E, F1, 11, in( 0), 1); \
ROUND1(E, A, B, C, D, F1, 14, in( 1), 1); \
ROUND1(D, E, A, B, C, F1, 15, in( 2), 1); \
ROUND1(C, D, E, A, B, F1, 12, in( 3), 1); \
ROUND1(B, C, D, E, A, F1, 5, in( 4), 1); \
ROUND1(A, B, C, D, E, F1, 8, in( 5), 1); \
ROUND1(E, A, B, C, D, F1, 7, in( 6), 1); \
ROUND1(D, E, A, B, C, F1, 9, in( 7), 1); \
ROUND1(C, D, E, A, B, F1, 11, in( 8), 1); \
ROUND1(B, C, D, E, A, F1, 13, in( 9), 1); \
ROUND1(A, B, C, D, E, F1, 14, in(10), 1); \
ROUND1(E, A, B, C, D, F1, 15, in(11), 1); \
ROUND1(D, E, A, B, C, F1, 6, in(12), 1); \
ROUND1(C, D, E, A, B, F1, 7, in(13), 1); \
ROUND1(B, C, D, E, A, F1, 9, in(14), 1); \
ROUND1(A, B, C, D, E, F1, 8, in(15), 1); \
\
ROUND1(E, A, B, C, D, F2, 7, in( 7), 2); \
ROUND1(D, E, A, B, C, F2, 6, in( 4), 2); \
ROUND1(C, D, E, A, B, F2, 8, in(13), 2); \
ROUND1(B, C, D, E, A, F2, 13, in( 1), 2); \
ROUND1(A, B, C, D, E, F2, 11, in(10), 2); \
ROUND1(E, A, B, C, D, F2, 9, in( 6), 2); \
ROUND1(D, E, A, B, C, F2, 7, in(15), 2); \
ROUND1(C, D, E, A, B, F2, 15, in( 3), 2); \
ROUND1(B, C, D, E, A, F2, 7, in(12), 2); \
ROUND1(A, B, C, D, E, F2, 12, in( 0), 2); \
ROUND1(E, A, B, C, D, F2, 15, in( 9), 2); \
ROUND1(D, E, A, B, C, F2, 9, in( 5), 2); \
ROUND1(C, D, E, A, B, F2, 11, in( 2), 2); \
ROUND1(B, C, D, E, A, F2, 7, in(14), 2); \
ROUND1(A, B, C, D, E, F2, 13, in(11), 2); \
ROUND1(E, A, B, C, D, F2, 12, in( 8), 2); \
\
ROUND1(D, E, A, B, C, F3, 11, in( 3), 3); \
ROUND1(C, D, E, A, B, F3, 13, in(10), 3); \
ROUND1(B, C, D, E, A, F3, 6, in(14), 3); \
ROUND1(A, B, C, D, E, F3, 7, in( 4), 3); \
ROUND1(E, A, B, C, D, F3, 14, in( 9), 3); \
ROUND1(D, E, A, B, C, F3, 9, in(15), 3); \
ROUND1(C, D, E, A, B, F3, 13, in( 8), 3); \
ROUND1(B, C, D, E, A, F3, 15, in( 1), 3); \
ROUND1(A, B, C, D, E, F3, 14, in( 2), 3); \
ROUND1(E, A, B, C, D, F3, 8, in( 7), 3); \
ROUND1(D, E, A, B, C, F3, 13, in( 0), 3); \
ROUND1(C, D, E, A, B, F3, 6, in( 6), 3); \
ROUND1(B, C, D, E, A, F3, 5, in(13), 3); \
ROUND1(A, B, C, D, E, F3, 12, in(11), 3); \
ROUND1(E, A, B, C, D, F3, 7, in( 5), 3); \
ROUND1(D, E, A, B, C, F3, 5, in(12), 3); \
\
ROUND1(C, D, E, A, B, F4, 11, in( 1), 4); \
ROUND1(B, C, D, E, A, F4, 12, in( 9), 4); \
ROUND1(A, B, C, D, E, F4, 14, in(11), 4); \
ROUND1(E, A, B, C, D, F4, 15, in(10), 4); \
ROUND1(D, E, A, B, C, F4, 14, in( 0), 4); \
ROUND1(C, D, E, A, B, F4, 15, in( 8), 4); \
ROUND1(B, C, D, E, A, F4, 9, in(12), 4); \
ROUND1(A, B, C, D, E, F4, 8, in( 4), 4); \
ROUND1(E, A, B, C, D, F4, 9, in(13), 4); \
ROUND1(D, E, A, B, C, F4, 14, in( 3), 4); \
ROUND1(C, D, E, A, B, F4, 5, in( 7), 4); \
ROUND1(B, C, D, E, A, F4, 6, in(15), 4); \
ROUND1(A, B, C, D, E, F4, 8, in(14), 4); \
ROUND1(E, A, B, C, D, F4, 6, in( 5), 4); \
ROUND1(D, E, A, B, C, F4, 5, in( 6), 4); \
ROUND1(C, D, E, A, B, F4, 12, in( 2), 4); \
\
ROUND1(B, C, D, E, A, F5, 9, in( 4), 5); \
ROUND1(A, B, C, D, E, F5, 15, in( 0), 5); \
ROUND1(E, A, B, C, D, F5, 5, in( 5), 5); \
ROUND1(D, E, A, B, C, F5, 11, in( 9), 5); \
ROUND1(C, D, E, A, B, F5, 6, in( 7), 5); \
ROUND1(B, C, D, E, A, F5, 8, in(12), 5); \
ROUND1(A, B, C, D, E, F5, 13, in( 2), 5); \
ROUND1(E, A, B, C, D, F5, 12, in(10), 5); \
ROUND1(D, E, A, B, C, F5, 5, in(14), 5); \
ROUND1(C, D, E, A, B, F5, 12, in( 1), 5); \
ROUND1(B, C, D, E, A, F5, 13, in( 3), 5); \
ROUND1(A, B, C, D, E, F5, 14, in( 8), 5); \
ROUND1(E, A, B, C, D, F5, 11, in(11), 5); \
ROUND1(D, E, A, B, C, F5, 8, in( 6), 5); \
ROUND1(C, D, E, A, B, F5, 5, in(15), 5); \
ROUND1(B, C, D, E, A, F5, 6, in(13), 5); \
\
ROUND2(A, B, C, D, E, F5, 8, in( 5), 1); \
ROUND2(E, A, B, C, D, F5, 9, in(14), 1); \
ROUND2(D, E, A, B, C, F5, 9, in( 7), 1); \
ROUND2(C, D, E, A, B, F5, 11, in( 0), 1); \
ROUND2(B, C, D, E, A, F5, 13, in( 9), 1); \
ROUND2(A, B, C, D, E, F5, 15, in( 2), 1); \
ROUND2(E, A, B, C, D, F5, 15, in(11), 1); \
ROUND2(D, E, A, B, C, F5, 5, in( 4), 1); \
ROUND2(C, D, E, A, B, F5, 7, in(13), 1); \
ROUND2(B, C, D, E, A, F5, 7, in( 6), 1); \
ROUND2(A, B, C, D, E, F5, 8, in(15), 1); \
ROUND2(E, A, B, C, D, F5, 11, in( 8), 1); \
ROUND2(D, E, A, B, C, F5, 14, in( 1), 1); \
ROUND2(C, D, E, A, B, F5, 14, in(10), 1); \
ROUND2(B, C, D, E, A, F5, 12, in( 3), 1); \
ROUND2(A, B, C, D, E, F5, 6, in(12), 1); \
\
ROUND2(E, A, B, C, D, F4, 9, in( 6), 2); \
ROUND2(D, E, A, B, C, F4, 13, in(11), 2); \
ROUND2(C, D, E, A, B, F4, 15, in( 3), 2); \
ROUND2(B, C, D, E, A, F4, 7, in( 7), 2); \
ROUND2(A, B, C, D, E, F4, 12, in( 0), 2); \
ROUND2(E, A, B, C, D, F4, 8, in(13), 2); \
ROUND2(D, E, A, B, C, F4, 9, in( 5), 2); \
ROUND2(C, D, E, A, B, F4, 11, in(10), 2); \
ROUND2(B, C, D, E, A, F4, 7, in(14), 2); \
ROUND2(A, B, C, D, E, F4, 7, in(15), 2); \
ROUND2(E, A, B, C, D, F4, 12, in( 8), 2); \
ROUND2(D, E, A, B, C, F4, 7, in(12), 2); \
ROUND2(C, D, E, A, B, F4, 6, in( 4), 2); \
ROUND2(B, C, D, E, A, F4, 15, in( 9), 2); \
ROUND2(A, B, C, D, E, F4, 13, in( 1), 2); \
ROUND2(E, A, B, C, D, F4, 11, in( 2), 2); \
\
ROUND2(D, E, A, B, C, F3, 9, in(15), 3); \
ROUND2(C, D, E, A, B, F3, 7, in( 5), 3); \
ROUND2(B, C, D, E, A, F3, 15, in( 1), 3); \
ROUND2(A, B, C, D, E, F3, 11, in( 3), 3); \
ROUND2(E, A, B, C, D, F3, 8, in( 7), 3); \
ROUND2(D, E, A, B, C, F3, 6, in(14), 3); \
ROUND2(C, D, E, A, B, F3, 6, in( 6), 3); \
ROUND2(B, C, D, E, A, F3, 14, in( 9), 3); \
ROUND2(A, B, C, D, E, F3, 12, in(11), 3); \
ROUND2(E, A, B, C, D, F3, 13, in( 8), 3); \
ROUND2(D, E, A, B, C, F3, 5, in(12), 3); \
ROUND2(C, D, E, A, B, F3, 14, in( 2), 3); \
ROUND2(B, C, D, E, A, F3, 13, in(10), 3); \
ROUND2(A, B, C, D, E, F3, 13, in( 0), 3); \
ROUND2(E, A, B, C, D, F3, 7, in( 4), 3); \
ROUND2(D, E, A, B, C, F3, 5, in(13), 3); \
\
ROUND2(C, D, E, A, B, F2, 15, in( 8), 4); \
ROUND2(B, C, D, E, A, F2, 5, in( 6), 4); \
ROUND2(A, B, C, D, E, F2, 8, in( 4), 4); \
ROUND2(E, A, B, C, D, F2, 11, in( 1), 4); \
ROUND2(D, E, A, B, C, F2, 14, in( 3), 4); \
ROUND2(C, D, E, A, B, F2, 14, in(11), 4); \
ROUND2(B, C, D, E, A, F2, 6, in(15), 4); \
ROUND2(A, B, C, D, E, F2, 14, in( 0), 4); \
ROUND2(E, A, B, C, D, F2, 6, in( 5), 4); \
ROUND2(D, E, A, B, C, F2, 9, in(12), 4); \
ROUND2(C, D, E, A, B, F2, 12, in( 2), 4); \
ROUND2(B, C, D, E, A, F2, 9, in(13), 4); \
ROUND2(A, B, C, D, E, F2, 12, in( 9), 4); \
ROUND2(E, A, B, C, D, F2, 5, in( 7), 4); \
ROUND2(D, E, A, B, C, F2, 15, in(10), 4); \
ROUND2(C, D, E, A, B, F2, 8, in(14), 4); \
\
ROUND2(B, C, D, E, A, F1, 8, in(12), 5); \
ROUND2(A, B, C, D, E, F1, 5, in(15), 5); \
ROUND2(E, A, B, C, D, F1, 12, in(10), 5); \
ROUND2(D, E, A, B, C, F1, 9, in( 4), 5); \
ROUND2(C, D, E, A, B, F1, 12, in( 1), 5); \
ROUND2(B, C, D, E, A, F1, 5, in( 5), 5); \
ROUND2(A, B, C, D, E, F1, 14, in( 8), 5); \
ROUND2(E, A, B, C, D, F1, 6, in( 7), 5); \
ROUND2(D, E, A, B, C, F1, 8, in( 6), 5); \
ROUND2(C, D, E, A, B, F1, 13, in( 2), 5); \
ROUND2(B, C, D, E, A, F1, 6, in(13), 5); \
ROUND2(A, B, C, D, E, F1, 5, in(14), 5); \
ROUND2(E, A, B, C, D, F1, 15, in( 0), 5); \
ROUND2(D, E, A, B, C, F1, 13, in( 3), 5); \
ROUND2(C, D, E, A, B, F1, 11, in( 9), 5); \
ROUND2(B, C, D, E, A, F1, 11, in(11), 5); \
\
tmp = SPH_T32((h)[1] + C1 + D2); \
(h)[1] = SPH_T32((h)[2] + D1 + E2); \
(h)[2] = SPH_T32((h)[3] + E1 + A2); \
(h)[3] = SPH_T32((h)[4] + A1 + B2); \
(h)[4] = SPH_T32((h)[0] + B1 + C2); \
(h)[0] = tmp; \
} while (0)
/*
* One round of RIPEMD-160. The data must be aligned for 32-bit access.
*/
static void
ripemd160_round(const unsigned char *data, sph_u32 r[5])
{
#if SPH_LITTLE_FAST
#define RIPEMD160_IN(x) sph_dec32le_aligned(data + (4 * (x)))
#else
sph_u32 X_var[16];
int i;
for (i = 0; i < 16; i ++)
X_var[i] = sph_dec32le_aligned(data + 4 * i);
#define RIPEMD160_IN(x) X_var[x]
#endif
RIPEMD160_ROUND_BODY(RIPEMD160_IN, r);
#undef RIPEMD160_IN
}
/* see sph_ripemd.h */
void
sph_ripemd160_init(void *cc)
{
sph_ripemd160_context *sc;
sc = cc;
memcpy(sc->val, IV, sizeof sc->val);
#if SPH_64
sc->count = 0;
#else
sc->count_high = sc->count_low = 0;
#endif
}
#define RFUN ripemd160_round
#define HASH ripemd160
#define LE32 1
#include "md_helper.c"
#undef RFUN
#undef HASH
#undef LE32
/* see sph_ripemd.h */
void
sph_ripemd160_close(void *cc, void *dst)
{
ripemd160_close(cc, dst, 5);
sph_ripemd160_init(cc);
}
/* see sph_ripemd.h */
void
sph_ripemd160_comp(const sph_u32 msg[16], sph_u32 val[5])
{
#define RIPEMD160_IN(x) msg[x]
RIPEMD160_ROUND_BODY(RIPEMD160_IN, val);
#undef RIPEMD160_IN
}
#ifdef __cplusplus
}
#endif

698
sph_sha2.c Normal file
View file

@ -0,0 +1,698 @@
/* $Id: sha2.c 227 2010-06-16 17:28:38Z tp $ */
/*
* SHA-224 / SHA-256 implementation.
*
* ==========================(LICENSE BEGIN)============================
*
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ===========================(LICENSE END)=============================
*
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
*/
#include <stddef.h>
#include <string.h>
#include "sph_sha2.h"
#ifdef __cplusplus
extern "C"{
#endif
#if SPH_SMALL_FOOTPRINT && !defined SPH_SMALL_FOOTPRINT_SHA2
#define SPH_SMALL_FOOTPRINT_SHA2 1
#endif
#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X)))
#define ROTR SPH_ROTR32
#define BSG2_0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define BSG2_1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define SSG2_0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SPH_T32((x) >> 3))
#define SSG2_1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SPH_T32((x) >> 10))
static const sph_u32 H224[8] = {
SPH_C32(0xC1059ED8), SPH_C32(0x367CD507), SPH_C32(0x3070DD17),
SPH_C32(0xF70E5939), SPH_C32(0xFFC00B31), SPH_C32(0x68581511),
SPH_C32(0x64F98FA7), SPH_C32(0xBEFA4FA4)
};
static const sph_u32 H256[8] = {
SPH_C32(0x6A09E667), SPH_C32(0xBB67AE85), SPH_C32(0x3C6EF372),
SPH_C32(0xA54FF53A), SPH_C32(0x510E527F), SPH_C32(0x9B05688C),
SPH_C32(0x1F83D9AB), SPH_C32(0x5BE0CD19)
};
/*
* The SHA2_ROUND_BODY defines the body for a SHA-224 / SHA-256
* compression function implementation. The "in" parameter should
* evaluate, when applied to a numerical input parameter from 0 to 15,
* to an expression which yields the corresponding input block. The "r"
* parameter should evaluate to an array or pointer expression
* designating the array of 8 words which contains the input and output
* of the compression function.
*/
#if SPH_SMALL_FOOTPRINT_SHA2
static const sph_u32 K[64] = {
SPH_C32(0x428A2F98), SPH_C32(0x71374491),
SPH_C32(0xB5C0FBCF), SPH_C32(0xE9B5DBA5),
SPH_C32(0x3956C25B), SPH_C32(0x59F111F1),
SPH_C32(0x923F82A4), SPH_C32(0xAB1C5ED5),
SPH_C32(0xD807AA98), SPH_C32(0x12835B01),
SPH_C32(0x243185BE), SPH_C32(0x550C7DC3),
SPH_C32(0x72BE5D74), SPH_C32(0x80DEB1FE),
SPH_C32(0x9BDC06A7), SPH_C32(0xC19BF174),
SPH_C32(0xE49B69C1), SPH_C32(0xEFBE4786),
SPH_C32(0x0FC19DC6), SPH_C32(0x240CA1CC),
SPH_C32(0x2DE92C6F), SPH_C32(0x4A7484AA),
SPH_C32(0x5CB0A9DC), SPH_C32(0x76F988DA),
SPH_C32(0x983E5152), SPH_C32(0xA831C66D),
SPH_C32(0xB00327C8), SPH_C32(0xBF597FC7),
SPH_C32(0xC6E00BF3), SPH_C32(0xD5A79147),
SPH_C32(0x06CA6351), SPH_C32(0x14292967),
SPH_C32(0x27B70A85), SPH_C32(0x2E1B2138),
SPH_C32(0x4D2C6DFC), SPH_C32(0x53380D13),
SPH_C32(0x650A7354), SPH_C32(0x766A0ABB),
SPH_C32(0x81C2C92E), SPH_C32(0x92722C85),
SPH_C32(0xA2BFE8A1), SPH_C32(0xA81A664B),
SPH_C32(0xC24B8B70), SPH_C32(0xC76C51A3),
SPH_C32(0xD192E819), SPH_C32(0xD6990624),
SPH_C32(0xF40E3585), SPH_C32(0x106AA070),
SPH_C32(0x19A4C116), SPH_C32(0x1E376C08),
SPH_C32(0x2748774C), SPH_C32(0x34B0BCB5),
SPH_C32(0x391C0CB3), SPH_C32(0x4ED8AA4A),
SPH_C32(0x5B9CCA4F), SPH_C32(0x682E6FF3),
SPH_C32(0x748F82EE), SPH_C32(0x78A5636F),
SPH_C32(0x84C87814), SPH_C32(0x8CC70208),
SPH_C32(0x90BEFFFA), SPH_C32(0xA4506CEB),
SPH_C32(0xBEF9A3F7), SPH_C32(0xC67178F2)
};
#define SHA2_MEXP1(in, pc) do { \
W[pc] = in(pc); \
} while (0)
#define SHA2_MEXP2(in, pc) do { \
W[(pc) & 0x0F] = SPH_T32(SSG2_1(W[((pc) - 2) & 0x0F]) \
+ W[((pc) - 7) & 0x0F] \
+ SSG2_0(W[((pc) - 15) & 0x0F]) + W[(pc) & 0x0F]); \
} while (0)
#define SHA2_STEPn(n, a, b, c, d, e, f, g, h, in, pc) do { \
sph_u32 t1, t2; \
SHA2_MEXP ## n(in, pc); \
t1 = SPH_T32(h + BSG2_1(e) + CH(e, f, g) \
+ K[pcount + (pc)] + W[(pc) & 0x0F]); \
t2 = SPH_T32(BSG2_0(a) + MAJ(a, b, c)); \
d = SPH_T32(d + t1); \
h = SPH_T32(t1 + t2); \
} while (0)
#define SHA2_STEP1(a, b, c, d, e, f, g, h, in, pc) \
SHA2_STEPn(1, a, b, c, d, e, f, g, h, in, pc)
#define SHA2_STEP2(a, b, c, d, e, f, g, h, in, pc) \
SHA2_STEPn(2, a, b, c, d, e, f, g, h, in, pc)
#define SHA2_ROUND_BODY(in, r) do { \
sph_u32 A, B, C, D, E, F, G, H; \
sph_u32 W[16]; \
unsigned pcount; \
\
A = (r)[0]; \
B = (r)[1]; \
C = (r)[2]; \
D = (r)[3]; \
E = (r)[4]; \
F = (r)[5]; \
G = (r)[6]; \
H = (r)[7]; \
pcount = 0; \
SHA2_STEP1(A, B, C, D, E, F, G, H, in, 0); \
SHA2_STEP1(H, A, B, C, D, E, F, G, in, 1); \
SHA2_STEP1(G, H, A, B, C, D, E, F, in, 2); \
SHA2_STEP1(F, G, H, A, B, C, D, E, in, 3); \
SHA2_STEP1(E, F, G, H, A, B, C, D, in, 4); \
SHA2_STEP1(D, E, F, G, H, A, B, C, in, 5); \
SHA2_STEP1(C, D, E, F, G, H, A, B, in, 6); \
SHA2_STEP1(B, C, D, E, F, G, H, A, in, 7); \
SHA2_STEP1(A, B, C, D, E, F, G, H, in, 8); \
SHA2_STEP1(H, A, B, C, D, E, F, G, in, 9); \
SHA2_STEP1(G, H, A, B, C, D, E, F, in, 10); \
SHA2_STEP1(F, G, H, A, B, C, D, E, in, 11); \
SHA2_STEP1(E, F, G, H, A, B, C, D, in, 12); \
SHA2_STEP1(D, E, F, G, H, A, B, C, in, 13); \
SHA2_STEP1(C, D, E, F, G, H, A, B, in, 14); \
SHA2_STEP1(B, C, D, E, F, G, H, A, in, 15); \
for (pcount = 16; pcount < 64; pcount += 16) { \
SHA2_STEP2(A, B, C, D, E, F, G, H, in, 0); \
SHA2_STEP2(H, A, B, C, D, E, F, G, in, 1); \
SHA2_STEP2(G, H, A, B, C, D, E, F, in, 2); \
SHA2_STEP2(F, G, H, A, B, C, D, E, in, 3); \
SHA2_STEP2(E, F, G, H, A, B, C, D, in, 4); \
SHA2_STEP2(D, E, F, G, H, A, B, C, in, 5); \
SHA2_STEP2(C, D, E, F, G, H, A, B, in, 6); \
SHA2_STEP2(B, C, D, E, F, G, H, A, in, 7); \
SHA2_STEP2(A, B, C, D, E, F, G, H, in, 8); \
SHA2_STEP2(H, A, B, C, D, E, F, G, in, 9); \
SHA2_STEP2(G, H, A, B, C, D, E, F, in, 10); \
SHA2_STEP2(F, G, H, A, B, C, D, E, in, 11); \
SHA2_STEP2(E, F, G, H, A, B, C, D, in, 12); \
SHA2_STEP2(D, E, F, G, H, A, B, C, in, 13); \
SHA2_STEP2(C, D, E, F, G, H, A, B, in, 14); \
SHA2_STEP2(B, C, D, E, F, G, H, A, in, 15); \
} \
(r)[0] = SPH_T32((r)[0] + A); \
(r)[1] = SPH_T32((r)[1] + B); \
(r)[2] = SPH_T32((r)[2] + C); \
(r)[3] = SPH_T32((r)[3] + D); \
(r)[4] = SPH_T32((r)[4] + E); \
(r)[5] = SPH_T32((r)[5] + F); \
(r)[6] = SPH_T32((r)[6] + G); \
(r)[7] = SPH_T32((r)[7] + H); \
} while (0)
#else
#define SHA2_ROUND_BODY(in, r) do { \
sph_u32 A, B, C, D, E, F, G, H, T1, T2; \
sph_u32 W00, W01, W02, W03, W04, W05, W06, W07; \
sph_u32 W08, W09, W10, W11, W12, W13, W14, W15; \
\
A = (r)[0]; \
B = (r)[1]; \
C = (r)[2]; \
D = (r)[3]; \
E = (r)[4]; \
F = (r)[5]; \
G = (r)[6]; \
H = (r)[7]; \
W00 = in(0); \
T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \
+ SPH_C32(0x428A2F98) + W00); \
T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \
D = SPH_T32(D + T1); \
H = SPH_T32(T1 + T2); \
W01 = in(1); \
T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \
+ SPH_C32(0x71374491) + W01); \
T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \
C = SPH_T32(C + T1); \
G = SPH_T32(T1 + T2); \
W02 = in(2); \
T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \
+ SPH_C32(0xB5C0FBCF) + W02); \
T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \
B = SPH_T32(B + T1); \
F = SPH_T32(T1 + T2); \
W03 = in(3); \
T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \
+ SPH_C32(0xE9B5DBA5) + W03); \
T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \
A = SPH_T32(A + T1); \
E = SPH_T32(T1 + T2); \
W04 = in(4); \
T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \
+ SPH_C32(0x3956C25B) + W04); \
T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \
H = SPH_T32(H + T1); \
D = SPH_T32(T1 + T2); \
W05 = in(5); \
T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \
+ SPH_C32(0x59F111F1) + W05); \
T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \
G = SPH_T32(G + T1); \
C = SPH_T32(T1 + T2); \
W06 = in(6); \
T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \
+ SPH_C32(0x923F82A4) + W06); \
T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \
F = SPH_T32(F + T1); \
B = SPH_T32(T1 + T2); \
W07 = in(7); \
T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \
+ SPH_C32(0xAB1C5ED5) + W07); \
T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \
E = SPH_T32(E + T1); \
A = SPH_T32(T1 + T2); \
W08 = in(8); \
T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \
+ SPH_C32(0xD807AA98) + W08); \
T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \
D = SPH_T32(D + T1); \
H = SPH_T32(T1 + T2); \
W09 = in(9); \
T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \
+ SPH_C32(0x12835B01) + W09); \
T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \
C = SPH_T32(C + T1); \
G = SPH_T32(T1 + T2); \
W10 = in(10); \
T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \
+ SPH_C32(0x243185BE) + W10); \
T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \
B = SPH_T32(B + T1); \
F = SPH_T32(T1 + T2); \
W11 = in(11); \
T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \
+ SPH_C32(0x550C7DC3) + W11); \
T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \
A = SPH_T32(A + T1); \
E = SPH_T32(T1 + T2); \
W12 = in(12); \
T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \
+ SPH_C32(0x72BE5D74) + W12); \
T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \
H = SPH_T32(H + T1); \
D = SPH_T32(T1 + T2); \
W13 = in(13); \
T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \
+ SPH_C32(0x80DEB1FE) + W13); \
T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \
G = SPH_T32(G + T1); \
C = SPH_T32(T1 + T2); \
W14 = in(14); \
T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \
+ SPH_C32(0x9BDC06A7) + W14); \
T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \
F = SPH_T32(F + T1); \
B = SPH_T32(T1 + T2); \
W15 = in(15); \
T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \
+ SPH_C32(0xC19BF174) + W15); \
T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \
E = SPH_T32(E + T1); \
A = SPH_T32(T1 + T2); \
W00 = SPH_T32(SSG2_1(W14) + W09 + SSG2_0(W01) + W00); \
T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \
+ SPH_C32(0xE49B69C1) + W00); \
T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \
D = SPH_T32(D + T1); \
H = SPH_T32(T1 + T2); \
W01 = SPH_T32(SSG2_1(W15) + W10 + SSG2_0(W02) + W01); \
T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \
+ SPH_C32(0xEFBE4786) + W01); \
T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \
C = SPH_T32(C + T1); \
G = SPH_T32(T1 + T2); \
W02 = SPH_T32(SSG2_1(W00) + W11 + SSG2_0(W03) + W02); \
T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \
+ SPH_C32(0x0FC19DC6) + W02); \
T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \
B = SPH_T32(B + T1); \
F = SPH_T32(T1 + T2); \
W03 = SPH_T32(SSG2_1(W01) + W12 + SSG2_0(W04) + W03); \
T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \
+ SPH_C32(0x240CA1CC) + W03); \
T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \
A = SPH_T32(A + T1); \
E = SPH_T32(T1 + T2); \
W04 = SPH_T32(SSG2_1(W02) + W13 + SSG2_0(W05) + W04); \
T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \
+ SPH_C32(0x2DE92C6F) + W04); \
T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \
H = SPH_T32(H + T1); \
D = SPH_T32(T1 + T2); \
W05 = SPH_T32(SSG2_1(W03) + W14 + SSG2_0(W06) + W05); \
T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \
+ SPH_C32(0x4A7484AA) + W05); \
T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \
G = SPH_T32(G + T1); \
C = SPH_T32(T1 + T2); \
W06 = SPH_T32(SSG2_1(W04) + W15 + SSG2_0(W07) + W06); \
T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \
+ SPH_C32(0x5CB0A9DC) + W06); \
T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \
F = SPH_T32(F + T1); \
B = SPH_T32(T1 + T2); \
W07 = SPH_T32(SSG2_1(W05) + W00 + SSG2_0(W08) + W07); \
T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \
+ SPH_C32(0x76F988DA) + W07); \
T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \
E = SPH_T32(E + T1); \
A = SPH_T32(T1 + T2); \
W08 = SPH_T32(SSG2_1(W06) + W01 + SSG2_0(W09) + W08); \
T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \
+ SPH_C32(0x983E5152) + W08); \
T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \
D = SPH_T32(D + T1); \
H = SPH_T32(T1 + T2); \
W09 = SPH_T32(SSG2_1(W07) + W02 + SSG2_0(W10) + W09); \
T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \
+ SPH_C32(0xA831C66D) + W09); \
T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \
C = SPH_T32(C + T1); \
G = SPH_T32(T1 + T2); \
W10 = SPH_T32(SSG2_1(W08) + W03 + SSG2_0(W11) + W10); \
T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \
+ SPH_C32(0xB00327C8) + W10); \
T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \
B = SPH_T32(B + T1); \
F = SPH_T32(T1 + T2); \
W11 = SPH_T32(SSG2_1(W09) + W04 + SSG2_0(W12) + W11); \
T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \
+ SPH_C32(0xBF597FC7) + W11); \
T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \
A = SPH_T32(A + T1); \
E = SPH_T32(T1 + T2); \
W12 = SPH_T32(SSG2_1(W10) + W05 + SSG2_0(W13) + W12); \
T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \
+ SPH_C32(0xC6E00BF3) + W12); \
T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \
H = SPH_T32(H + T1); \
D = SPH_T32(T1 + T2); \
W13 = SPH_T32(SSG2_1(W11) + W06 + SSG2_0(W14) + W13); \
T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \
+ SPH_C32(0xD5A79147) + W13); \
T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \
G = SPH_T32(G + T1); \
C = SPH_T32(T1 + T2); \
W14 = SPH_T32(SSG2_1(W12) + W07 + SSG2_0(W15) + W14); \
T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \
+ SPH_C32(0x06CA6351) + W14); \
T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \
F = SPH_T32(F + T1); \
B = SPH_T32(T1 + T2); \
W15 = SPH_T32(SSG2_1(W13) + W08 + SSG2_0(W00) + W15); \
T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \
+ SPH_C32(0x14292967) + W15); \
T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \
E = SPH_T32(E + T1); \
A = SPH_T32(T1 + T2); \
W00 = SPH_T32(SSG2_1(W14) + W09 + SSG2_0(W01) + W00); \
T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \
+ SPH_C32(0x27B70A85) + W00); \
T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \
D = SPH_T32(D + T1); \
H = SPH_T32(T1 + T2); \
W01 = SPH_T32(SSG2_1(W15) + W10 + SSG2_0(W02) + W01); \
T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \
+ SPH_C32(0x2E1B2138) + W01); \
T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \
C = SPH_T32(C + T1); \
G = SPH_T32(T1 + T2); \
W02 = SPH_T32(SSG2_1(W00) + W11 + SSG2_0(W03) + W02); \
T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \
+ SPH_C32(0x4D2C6DFC) + W02); \
T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \
B = SPH_T32(B + T1); \
F = SPH_T32(T1 + T2); \
W03 = SPH_T32(SSG2_1(W01) + W12 + SSG2_0(W04) + W03); \
T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \
+ SPH_C32(0x53380D13) + W03); \
T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \
A = SPH_T32(A + T1); \
E = SPH_T32(T1 + T2); \
W04 = SPH_T32(SSG2_1(W02) + W13 + SSG2_0(W05) + W04); \
T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \
+ SPH_C32(0x650A7354) + W04); \
T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \
H = SPH_T32(H + T1); \
D = SPH_T32(T1 + T2); \
W05 = SPH_T32(SSG2_1(W03) + W14 + SSG2_0(W06) + W05); \
T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \
+ SPH_C32(0x766A0ABB) + W05); \
T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \
G = SPH_T32(G + T1); \
C = SPH_T32(T1 + T2); \
W06 = SPH_T32(SSG2_1(W04) + W15 + SSG2_0(W07) + W06); \
T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \
+ SPH_C32(0x81C2C92E) + W06); \
T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \
F = SPH_T32(F + T1); \
B = SPH_T32(T1 + T2); \
W07 = SPH_T32(SSG2_1(W05) + W00 + SSG2_0(W08) + W07); \
T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \
+ SPH_C32(0x92722C85) + W07); \
T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \
E = SPH_T32(E + T1); \
A = SPH_T32(T1 + T2); \
W08 = SPH_T32(SSG2_1(W06) + W01 + SSG2_0(W09) + W08); \
T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \
+ SPH_C32(0xA2BFE8A1) + W08); \
T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \
D = SPH_T32(D + T1); \
H = SPH_T32(T1 + T2); \
W09 = SPH_T32(SSG2_1(W07) + W02 + SSG2_0(W10) + W09); \
T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \
+ SPH_C32(0xA81A664B) + W09); \
T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \
C = SPH_T32(C + T1); \
G = SPH_T32(T1 + T2); \
W10 = SPH_T32(SSG2_1(W08) + W03 + SSG2_0(W11) + W10); \
T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \
+ SPH_C32(0xC24B8B70) + W10); \
T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \
B = SPH_T32(B + T1); \
F = SPH_T32(T1 + T2); \
W11 = SPH_T32(SSG2_1(W09) + W04 + SSG2_0(W12) + W11); \
T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \
+ SPH_C32(0xC76C51A3) + W11); \
T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \
A = SPH_T32(A + T1); \
E = SPH_T32(T1 + T2); \
W12 = SPH_T32(SSG2_1(W10) + W05 + SSG2_0(W13) + W12); \
T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \
+ SPH_C32(0xD192E819) + W12); \
T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \
H = SPH_T32(H + T1); \
D = SPH_T32(T1 + T2); \
W13 = SPH_T32(SSG2_1(W11) + W06 + SSG2_0(W14) + W13); \
T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \
+ SPH_C32(0xD6990624) + W13); \
T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \
G = SPH_T32(G + T1); \
C = SPH_T32(T1 + T2); \
W14 = SPH_T32(SSG2_1(W12) + W07 + SSG2_0(W15) + W14); \
T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \
+ SPH_C32(0xF40E3585) + W14); \
T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \
F = SPH_T32(F + T1); \
B = SPH_T32(T1 + T2); \
W15 = SPH_T32(SSG2_1(W13) + W08 + SSG2_0(W00) + W15); \
T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \
+ SPH_C32(0x106AA070) + W15); \
T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \
E = SPH_T32(E + T1); \
A = SPH_T32(T1 + T2); \
W00 = SPH_T32(SSG2_1(W14) + W09 + SSG2_0(W01) + W00); \
T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \
+ SPH_C32(0x19A4C116) + W00); \
T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \
D = SPH_T32(D + T1); \
H = SPH_T32(T1 + T2); \
W01 = SPH_T32(SSG2_1(W15) + W10 + SSG2_0(W02) + W01); \
T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \
+ SPH_C32(0x1E376C08) + W01); \
T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \
C = SPH_T32(C + T1); \
G = SPH_T32(T1 + T2); \
W02 = SPH_T32(SSG2_1(W00) + W11 + SSG2_0(W03) + W02); \
T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \
+ SPH_C32(0x2748774C) + W02); \
T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \
B = SPH_T32(B + T1); \
F = SPH_T32(T1 + T2); \
W03 = SPH_T32(SSG2_1(W01) + W12 + SSG2_0(W04) + W03); \
T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \
+ SPH_C32(0x34B0BCB5) + W03); \
T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \
A = SPH_T32(A + T1); \
E = SPH_T32(T1 + T2); \
W04 = SPH_T32(SSG2_1(W02) + W13 + SSG2_0(W05) + W04); \
T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \
+ SPH_C32(0x391C0CB3) + W04); \
T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \
H = SPH_T32(H + T1); \
D = SPH_T32(T1 + T2); \
W05 = SPH_T32(SSG2_1(W03) + W14 + SSG2_0(W06) + W05); \
T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \
+ SPH_C32(0x4ED8AA4A) + W05); \
T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \
G = SPH_T32(G + T1); \
C = SPH_T32(T1 + T2); \
W06 = SPH_T32(SSG2_1(W04) + W15 + SSG2_0(W07) + W06); \
T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \
+ SPH_C32(0x5B9CCA4F) + W06); \
T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \
F = SPH_T32(F + T1); \
B = SPH_T32(T1 + T2); \
W07 = SPH_T32(SSG2_1(W05) + W00 + SSG2_0(W08) + W07); \
T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \
+ SPH_C32(0x682E6FF3) + W07); \
T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \
E = SPH_T32(E + T1); \
A = SPH_T32(T1 + T2); \
W08 = SPH_T32(SSG2_1(W06) + W01 + SSG2_0(W09) + W08); \
T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \
+ SPH_C32(0x748F82EE) + W08); \
T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \
D = SPH_T32(D + T1); \
H = SPH_T32(T1 + T2); \
W09 = SPH_T32(SSG2_1(W07) + W02 + SSG2_0(W10) + W09); \
T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \
+ SPH_C32(0x78A5636F) + W09); \
T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \
C = SPH_T32(C + T1); \
G = SPH_T32(T1 + T2); \
W10 = SPH_T32(SSG2_1(W08) + W03 + SSG2_0(W11) + W10); \
T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \
+ SPH_C32(0x84C87814) + W10); \
T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \
B = SPH_T32(B + T1); \
F = SPH_T32(T1 + T2); \
W11 = SPH_T32(SSG2_1(W09) + W04 + SSG2_0(W12) + W11); \
T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \
+ SPH_C32(0x8CC70208) + W11); \
T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \
A = SPH_T32(A + T1); \
E = SPH_T32(T1 + T2); \
W12 = SPH_T32(SSG2_1(W10) + W05 + SSG2_0(W13) + W12); \
T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \
+ SPH_C32(0x90BEFFFA) + W12); \
T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \
H = SPH_T32(H + T1); \
D = SPH_T32(T1 + T2); \
W13 = SPH_T32(SSG2_1(W11) + W06 + SSG2_0(W14) + W13); \
T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \
+ SPH_C32(0xA4506CEB) + W13); \
T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \
G = SPH_T32(G + T1); \
C = SPH_T32(T1 + T2); \
W14 = SPH_T32(SSG2_1(W12) + W07 + SSG2_0(W15) + W14); \
T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \
+ SPH_C32(0xBEF9A3F7) + W14); \
T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \
F = SPH_T32(F + T1); \
B = SPH_T32(T1 + T2); \
W15 = SPH_T32(SSG2_1(W13) + W08 + SSG2_0(W00) + W15); \
T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \
+ SPH_C32(0xC67178F2) + W15); \
T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \
E = SPH_T32(E + T1); \
A = SPH_T32(T1 + T2); \
(r)[0] = SPH_T32((r)[0] + A); \
(r)[1] = SPH_T32((r)[1] + B); \
(r)[2] = SPH_T32((r)[2] + C); \
(r)[3] = SPH_T32((r)[3] + D); \
(r)[4] = SPH_T32((r)[4] + E); \
(r)[5] = SPH_T32((r)[5] + F); \
(r)[6] = SPH_T32((r)[6] + G); \
(r)[7] = SPH_T32((r)[7] + H); \
} while (0)
#endif
/*
* One round of SHA-224 / SHA-256. The data must be aligned for 32-bit access.
*/
static void
sha2_round(const unsigned char *data, sph_u32 r[8])
{
#define SHA2_IN(x) sph_dec32be_aligned(data + (4 * (x)))
SHA2_ROUND_BODY(SHA2_IN, r);
#undef SHA2_IN
}
/* see sph_sha2.h */
void
sph_sha224_init(void *cc)
{
sph_sha224_context *sc;
sc = cc;
memcpy(sc->val, H224, sizeof H224);
#if SPH_64
sc->count = 0;
#else
sc->count_high = sc->count_low = 0;
#endif
}
/* see sph_sha2.h */
void
sph_sha256_init(void *cc)
{
sph_sha256_context *sc;
sc = cc;
memcpy(sc->val, H256, sizeof H256);
#if SPH_64
sc->count = 0;
#else
sc->count_high = sc->count_low = 0;
#endif
}
#define RFUN sha2_round
#define HASH sha224
#define BE32 1
#include "md_helper.c"
/* see sph_sha2.h */
void
sph_sha224_close(void *cc, void *dst)
{
sha224_close(cc, dst, 7);
sph_sha224_init(cc);
}
/* see sph_sha2.h */
void
sph_sha224_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
{
sha224_addbits_and_close(cc, ub, n, dst, 7);
sph_sha224_init(cc);
}
/* see sph_sha2.h */
void
sph_sha256_close(void *cc, void *dst)
{
sha224_close(cc, dst, 8);
sph_sha256_init(cc);
}
/* see sph_sha2.h */
void
sph_sha256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
{
sha224_addbits_and_close(cc, ub, n, dst, 8);
sph_sha256_init(cc);
}
/* see sph_sha2.h */
void
sph_sha224_comp(const sph_u32 msg[16], sph_u32 val[8])
{
#define SHA2_IN(x) msg[x]
SHA2_ROUND_BODY(SHA2_IN, val);
#undef SHA2_IN
}
#ifdef __cplusplus
}
#endif

255
sph_sha2big.c Normal file
View file

@ -0,0 +1,255 @@
/* $Id: sha2big.c 216 2010-06-08 09:46:57Z tp $ */
/*
* SHA-384 / SHA-512 implementation.
*
* ==========================(LICENSE BEGIN)============================
*
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ===========================(LICENSE END)=============================
*
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
*/
#include <stddef.h>
#include <string.h>
#include "sph_sha2.h"
#ifdef __cplusplus
extern "C"{
#endif
#if SPH_64
#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
#define MAJ(X, Y, Z) (((X) & (Y)) | (((X) | (Y)) & (Z)))
#define ROTR64 SPH_ROTR64
#define BSG5_0(x) (ROTR64(x, 28) ^ ROTR64(x, 34) ^ ROTR64(x, 39))
#define BSG5_1(x) (ROTR64(x, 14) ^ ROTR64(x, 18) ^ ROTR64(x, 41))
#define SSG5_0(x) (ROTR64(x, 1) ^ ROTR64(x, 8) ^ SPH_T64((x) >> 7))
#define SSG5_1(x) (ROTR64(x, 19) ^ ROTR64(x, 61) ^ SPH_T64((x) >> 6))
static const sph_u64 K512[80] = {
SPH_C64(0x428A2F98D728AE22), SPH_C64(0x7137449123EF65CD),
SPH_C64(0xB5C0FBCFEC4D3B2F), SPH_C64(0xE9B5DBA58189DBBC),
SPH_C64(0x3956C25BF348B538), SPH_C64(0x59F111F1B605D019),
SPH_C64(0x923F82A4AF194F9B), SPH_C64(0xAB1C5ED5DA6D8118),
SPH_C64(0xD807AA98A3030242), SPH_C64(0x12835B0145706FBE),
SPH_C64(0x243185BE4EE4B28C), SPH_C64(0x550C7DC3D5FFB4E2),
SPH_C64(0x72BE5D74F27B896F), SPH_C64(0x80DEB1FE3B1696B1),
SPH_C64(0x9BDC06A725C71235), SPH_C64(0xC19BF174CF692694),
SPH_C64(0xE49B69C19EF14AD2), SPH_C64(0xEFBE4786384F25E3),
SPH_C64(0x0FC19DC68B8CD5B5), SPH_C64(0x240CA1CC77AC9C65),
SPH_C64(0x2DE92C6F592B0275), SPH_C64(0x4A7484AA6EA6E483),
SPH_C64(0x5CB0A9DCBD41FBD4), SPH_C64(0x76F988DA831153B5),
SPH_C64(0x983E5152EE66DFAB), SPH_C64(0xA831C66D2DB43210),
SPH_C64(0xB00327C898FB213F), SPH_C64(0xBF597FC7BEEF0EE4),
SPH_C64(0xC6E00BF33DA88FC2), SPH_C64(0xD5A79147930AA725),
SPH_C64(0x06CA6351E003826F), SPH_C64(0x142929670A0E6E70),
SPH_C64(0x27B70A8546D22FFC), SPH_C64(0x2E1B21385C26C926),
SPH_C64(0x4D2C6DFC5AC42AED), SPH_C64(0x53380D139D95B3DF),
SPH_C64(0x650A73548BAF63DE), SPH_C64(0x766A0ABB3C77B2A8),
SPH_C64(0x81C2C92E47EDAEE6), SPH_C64(0x92722C851482353B),
SPH_C64(0xA2BFE8A14CF10364), SPH_C64(0xA81A664BBC423001),
SPH_C64(0xC24B8B70D0F89791), SPH_C64(0xC76C51A30654BE30),
SPH_C64(0xD192E819D6EF5218), SPH_C64(0xD69906245565A910),
SPH_C64(0xF40E35855771202A), SPH_C64(0x106AA07032BBD1B8),
SPH_C64(0x19A4C116B8D2D0C8), SPH_C64(0x1E376C085141AB53),
SPH_C64(0x2748774CDF8EEB99), SPH_C64(0x34B0BCB5E19B48A8),
SPH_C64(0x391C0CB3C5C95A63), SPH_C64(0x4ED8AA4AE3418ACB),
SPH_C64(0x5B9CCA4F7763E373), SPH_C64(0x682E6FF3D6B2B8A3),
SPH_C64(0x748F82EE5DEFB2FC), SPH_C64(0x78A5636F43172F60),
SPH_C64(0x84C87814A1F0AB72), SPH_C64(0x8CC702081A6439EC),
SPH_C64(0x90BEFFFA23631E28), SPH_C64(0xA4506CEBDE82BDE9),
SPH_C64(0xBEF9A3F7B2C67915), SPH_C64(0xC67178F2E372532B),
SPH_C64(0xCA273ECEEA26619C), SPH_C64(0xD186B8C721C0C207),
SPH_C64(0xEADA7DD6CDE0EB1E), SPH_C64(0xF57D4F7FEE6ED178),
SPH_C64(0x06F067AA72176FBA), SPH_C64(0x0A637DC5A2C898A6),
SPH_C64(0x113F9804BEF90DAE), SPH_C64(0x1B710B35131C471B),
SPH_C64(0x28DB77F523047D84), SPH_C64(0x32CAAB7B40C72493),
SPH_C64(0x3C9EBE0A15C9BEBC), SPH_C64(0x431D67C49C100D4C),
SPH_C64(0x4CC5D4BECB3E42B6), SPH_C64(0x597F299CFC657E2A),
SPH_C64(0x5FCB6FAB3AD6FAEC), SPH_C64(0x6C44198C4A475817)
};
static const sph_u64 H384[8] = {
SPH_C64(0xCBBB9D5DC1059ED8), SPH_C64(0x629A292A367CD507),
SPH_C64(0x9159015A3070DD17), SPH_C64(0x152FECD8F70E5939),
SPH_C64(0x67332667FFC00B31), SPH_C64(0x8EB44A8768581511),
SPH_C64(0xDB0C2E0D64F98FA7), SPH_C64(0x47B5481DBEFA4FA4)
};
static const sph_u64 H512[8] = {
SPH_C64(0x6A09E667F3BCC908), SPH_C64(0xBB67AE8584CAA73B),
SPH_C64(0x3C6EF372FE94F82B), SPH_C64(0xA54FF53A5F1D36F1),
SPH_C64(0x510E527FADE682D1), SPH_C64(0x9B05688C2B3E6C1F),
SPH_C64(0x1F83D9ABFB41BD6B), SPH_C64(0x5BE0CD19137E2179)
};
/*
* This macro defines the body for a SHA-384 / SHA-512 compression function
* implementation. The "in" parameter should evaluate, when applied to a
* numerical input parameter from 0 to 15, to an expression which yields
* the corresponding input block. The "r" parameter should evaluate to
* an array or pointer expression designating the array of 8 words which
* contains the input and output of the compression function.
*
* SHA-512 is hard for the compiler. If the loop is completely unrolled,
* then the code will be quite huge (possibly more than 100 kB), and the
* performance will be degraded due to cache misses on the code. We
* unroll only eight steps, which avoids all needless copies when
* 64-bit registers are swapped.
*/
#define SHA3_STEP(A, B, C, D, E, F, G, H, i) do { \
sph_u64 T1, T2; \
T1 = SPH_T64(H + BSG5_1(E) + CH(E, F, G) + K512[i] + W[i]); \
T2 = SPH_T64(BSG5_0(A) + MAJ(A, B, C)); \
D = SPH_T64(D + T1); \
H = SPH_T64(T1 + T2); \
} while (0)
#define SHA3_ROUND_BODY(in, r) do { \
int i; \
sph_u64 A, B, C, D, E, F, G, H; \
sph_u64 W[80]; \
\
for (i = 0; i < 16; i ++) \
W[i] = in(i); \
for (i = 16; i < 80; i ++) \
W[i] = SPH_T64(SSG5_1(W[i - 2]) + W[i - 7] \
+ SSG5_0(W[i - 15]) + W[i - 16]); \
A = (r)[0]; \
B = (r)[1]; \
C = (r)[2]; \
D = (r)[3]; \
E = (r)[4]; \
F = (r)[5]; \
G = (r)[6]; \
H = (r)[7]; \
for (i = 0; i < 80; i += 8) { \
SHA3_STEP(A, B, C, D, E, F, G, H, i + 0); \
SHA3_STEP(H, A, B, C, D, E, F, G, i + 1); \
SHA3_STEP(G, H, A, B, C, D, E, F, i + 2); \
SHA3_STEP(F, G, H, A, B, C, D, E, i + 3); \
SHA3_STEP(E, F, G, H, A, B, C, D, i + 4); \
SHA3_STEP(D, E, F, G, H, A, B, C, i + 5); \
SHA3_STEP(C, D, E, F, G, H, A, B, i + 6); \
SHA3_STEP(B, C, D, E, F, G, H, A, i + 7); \
} \
(r)[0] = SPH_T64((r)[0] + A); \
(r)[1] = SPH_T64((r)[1] + B); \
(r)[2] = SPH_T64((r)[2] + C); \
(r)[3] = SPH_T64((r)[3] + D); \
(r)[4] = SPH_T64((r)[4] + E); \
(r)[5] = SPH_T64((r)[5] + F); \
(r)[6] = SPH_T64((r)[6] + G); \
(r)[7] = SPH_T64((r)[7] + H); \
} while (0)
/*
* One round of SHA-384 / SHA-512. The data must be aligned for 64-bit access.
*/
static void
sha3_round(const unsigned char *data, sph_u64 r[8])
{
#define SHA3_IN(x) sph_dec64be_aligned(data + (8 * (x)))
SHA3_ROUND_BODY(SHA3_IN, r);
#undef SHA3_IN
}
/* see sph_sha3.h */
void
sph_sha384_init(void *cc)
{
sph_sha384_context *sc;
sc = cc;
memcpy(sc->val, H384, sizeof H384);
sc->count = 0;
}
/* see sph_sha3.h */
void
sph_sha512_init(void *cc)
{
sph_sha512_context *sc;
sc = cc;
memcpy(sc->val, H512, sizeof H512);
sc->count = 0;
}
#define RFUN sha3_round
#define HASH sha384
#define BE64 1
#include "md_helper.c"
/* see sph_sha3.h */
void
sph_sha384_close(void *cc, void *dst)
{
sha384_close(cc, dst, 6);
sph_sha384_init(cc);
}
/* see sph_sha3.h */
void
sph_sha384_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
{
sha384_addbits_and_close(cc, ub, n, dst, 6);
sph_sha384_init(cc);
}
/* see sph_sha3.h */
void
sph_sha512_close(void *cc, void *dst)
{
sha384_close(cc, dst, 8);
sph_sha512_init(cc);
}
/* see sph_sha3.h */
void
sph_sha512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
{
sha384_addbits_and_close(cc, ub, n, dst, 8);
sph_sha512_init(cc);
}
/* see sph_sha3.h */
void
sph_sha384_comp(const sph_u64 msg[16], sph_u64 val[8])
{
#define SHA3_IN(x) msg[x]
SHA3_ROUND_BODY(SHA3_IN, val);
#undef SHA3_IN
}
#endif
#ifdef __cplusplus
}
#endif