Compare commits

..

No commits in common. "master" and "aix" have entirely different histories.
master ... aix

18 changed files with 205 additions and 5327 deletions

4
.gitignore vendored
View file

@ -26,7 +26,3 @@ config.sub
mingw32-config.cache mingw32-config.cache
.idea/
compile_commands.json

View file

@ -1,16 +1,17 @@
# #
# Dockerfile for cpuminer # Dockerfile for cpuminer
# usage: docker run lbry/cpuminer --url xxxx --user xxxx --pass xxxx # usage: docker run creack/cpuminer --url xxxx --user xxxx --pass xxxx
# ex: docker run lbry/cpuminer --url stratum+tcp://lbc.pool.com:80 --user worker1 --pass abcdef # ex: docker run creack/cpuminer --url stratum+tcp://ltc.pool.com:80 --user creack.worker1 --pass abcdef
# #
# #
FROM ubuntu:18.04 FROM ubuntu:14.04
MAINTAINER Guillaume J. Charmes <guillaume@charmes.net>
RUN apt-get update -qq && \ RUN apt-get update -qq && \
apt-get install -qqy automake libcurl4-openssl-dev git make gcc apt-get install -qqy automake libcurl4-openssl-dev git make
RUN git clone https://github.com/lbryio/cpuminer RUN git clone https://github.com/pooler/cpuminer
RUN cd cpuminer && \ RUN cd cpuminer && \
./autogen.sh && \ ./autogen.sh && \

View file

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

9
NEWS
View file

@ -1,12 +1,3 @@
Version 2.5.1 - Jun 25, 2020
- Add support for bech32 addresses (BIP 173)
Version 2.5.0 - Jun 22, 2017
- Add Segwit support
- Add support for 64-bit PowerPC
Version 2.4.5 - Jun 10, 2016 Version 2.4.5 - Jun 10, 2016
- Fix a memory leak affecting long polling - Fix a memory leak affecting long polling

4
README
View file

@ -13,8 +13,8 @@ Dependencies:
Basic *nix build instructions: Basic *nix build instructions:
./autogen.sh # only needed if building from git repo ./autogen.sh # only needed if building from git repo
./nomacro.pl # in case the assembler doesn't support macros ./nomacro.pl # only needed if building on Mac OS X or with Clang
./configure CFLAGS="-O3" # make sure -O3 is an O and not a zero! ./configure CFLAGS="-O3" # Make sure -O3 is an O and not a zero!
make make
Notes for AIX users: Notes for AIX users:

View file

@ -1,4 +1,4 @@
AC_INIT([cpuminer], [2.5.1]) AC_INIT([cpuminer], [2.4.5])
AC_PREREQ([2.59c]) AC_PREREQ([2.59c])
AC_CANONICAL_SYSTEM AC_CANONICAL_SYSTEM

View file

@ -101,15 +101,13 @@ struct workio_cmd {
}; };
enum algos { enum algos {
ALGO_LBRY, /* lbry */ ALGO_SCRYPT, /* scrypt(1024,1,1) */
ALGO_SCRYPT, /* scrypt(1024,1,1) */ ALGO_SHA256D, /* SHA-256d */
ALGO_SHA256D, /* SHA-256d */
}; };
static const char *algo_names[] = { static const char *algo_names[] = {
[ALGO_LBRY] = "lbry", [ALGO_SCRYPT] = "scrypt",
[ALGO_SCRYPT] = "scrypt", [ALGO_SHA256D] = "sha256d",
[ALGO_SHA256D] = "sha256d",
}; };
bool opt_debug = false; bool opt_debug = false;
@ -119,8 +117,8 @@ bool opt_redirect = true;
bool want_longpoll = true; bool want_longpoll = true;
bool have_longpoll = false; bool have_longpoll = false;
bool have_gbt = true; bool have_gbt = true;
bool allow_getwork = false; bool allow_getwork = true;
bool want_stratum = false; bool want_stratum = true;
bool have_stratum = false; bool have_stratum = false;
bool use_syslog = false; bool use_syslog = false;
static bool opt_background = false; static bool opt_background = false;
@ -129,7 +127,7 @@ static int opt_retries = -1;
static int opt_fail_pause = 30; static int opt_fail_pause = 30;
int opt_timeout = 0; int opt_timeout = 0;
static int opt_scantime = 5; static int opt_scantime = 5;
static enum algos opt_algo = ALGO_LBRY; static enum algos opt_algo = ALGO_SCRYPT;
static int opt_scrypt_n = 1024; static int opt_scrypt_n = 1024;
static int opt_n_threads; static int opt_n_threads;
static int num_processors; static int num_processors;
@ -137,7 +135,7 @@ static char *rpc_url;
static char *rpc_userpass; static char *rpc_userpass;
static char *rpc_user, *rpc_pass; static char *rpc_user, *rpc_pass;
static int pk_script_size; static int pk_script_size;
static unsigned char pk_script[42]; static unsigned char pk_script[25];
static char coinbase_sig[101] = ""; static char coinbase_sig[101] = "";
char *opt_cert; char *opt_cert;
char *opt_proxy; char *opt_proxy;
@ -171,8 +169,7 @@ static char const usage[] = "\
Usage: " PROGRAM_NAME " [OPTIONS]\n\ Usage: " PROGRAM_NAME " [OPTIONS]\n\
Options:\n\ Options:\n\
-a, --algo=ALGO specify the algorithm to use\n\ -a, --algo=ALGO specify the algorithm to use\n\
lbry (default)\n\ scrypt scrypt(1024, 1, 1) (default)\n\
scrypt scrypt(1024, 1, 1)\n\
scrypt:N scrypt(N, 1, 1)\n\ scrypt:N scrypt(N, 1, 1)\n\
sha256d SHA-256d\n\ sha256d SHA-256d\n\
-o, --url=URL URL of mining server\n\ -o, --url=URL URL of mining server\n\
@ -185,15 +182,15 @@ Options:\n\
-r, --retries=N number of times to retry if a network call fails\n\ -r, --retries=N number of times to retry if a network call fails\n\
(default: retry indefinitely)\n\ (default: retry indefinitely)\n\
-R, --retry-pause=N time to pause between retries, in seconds (default: 30)\n\ -R, --retry-pause=N time to pause between retries, in seconds (default: 30)\n\
-T, --timeout=N timeout for long polling, in seconds (default: 70sec)\n\ -T, --timeout=N timeout for long polling, in seconds (default: none)\n\
-s, --scantime=N upper bound on time spent scanning current work when\n\ -s, --scantime=N upper bound on time spent scanning current work when\n\
long polling is unavailable, in seconds (default: 5)\n\ long polling is unavailable, in seconds (default: 5)\n\
--coinbase-addr=ADDR payout address for solo mining\n\ --coinbase-addr=ADDR payout address for solo mining\n\
--coinbase-sig=TEXT data to insert in the coinbase when possible\n\ --coinbase-sig=TEXT data to insert in the coinbase when possible\n\
--no-longpoll disable long polling support\n\ --no-longpoll disable long polling support\n\
--getwork enable getwork support\n\ --no-getwork disable getwork support\n\
--no-gbt disable getblocktemplate support\n\ --no-gbt disable getblocktemplate support\n\
--stratum enable X-Stratum support\n\ --no-stratum disable X-Stratum support\n\
--no-redirect ignore requests to change the URL of the mining server\n\ --no-redirect ignore requests to change the URL of the mining server\n\
-q, --quiet disable per-thread hashmeter output\n\ -q, --quiet disable per-thread hashmeter output\n\
-D, --debug enable debug output\n\ -D, --debug enable debug output\n\
@ -235,10 +232,10 @@ static struct option const options[] = {
{ "debug", 0, NULL, 'D' }, { "debug", 0, NULL, 'D' },
{ "help", 0, NULL, 'h' }, { "help", 0, NULL, 'h' },
{ "no-gbt", 0, NULL, 1011 }, { "no-gbt", 0, NULL, 1011 },
{ "getwork", 0, NULL, 1010 }, { "no-getwork", 0, NULL, 1010 },
{ "no-longpoll", 0, NULL, 1003 }, { "no-longpoll", 0, NULL, 1003 },
{ "no-redirect", 0, NULL, 1009 }, { "no-redirect", 0, NULL, 1009 },
{ "stratum", 0, NULL, 1007 }, { "no-stratum", 0, NULL, 1007 },
{ "pass", 1, NULL, 'p' }, { "pass", 1, NULL, 'p' },
{ "protocol-dump", 0, NULL, 'P' }, { "protocol-dump", 0, NULL, 'P' },
{ "proxy", 1, NULL, 'x' }, { "proxy", 1, NULL, 'x' },
@ -259,7 +256,7 @@ static struct option const options[] = {
}; };
struct work { struct work {
uint32_t data[40]; uint32_t data[32];
uint32_t target[8]; uint32_t target[8];
int height; int height;
@ -352,10 +349,8 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
uint32_t version, curtime, bits; uint32_t version, curtime, bits;
uint32_t prevhash[8]; uint32_t prevhash[8];
uint32_t target[8]; uint32_t target[8];
uint32_t claimtrie[8];
int cbtx_size; int cbtx_size;
unsigned char *cbtx = NULL, *cbtx_txid = NULL; unsigned char *cbtx = NULL;
unsigned char *tx = NULL;
int tx_count, tx_size; int tx_count, tx_size;
unsigned char txc_vi[9]; unsigned char txc_vi[9];
unsigned char (*merkle_tree)[32] = NULL; unsigned char (*merkle_tree)[32] = NULL;
@ -405,11 +400,6 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
} }
version = json_integer_value(tmp); version = json_integer_value(tmp);
if (opt_algo == ALGO_LBRY && 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)))) { if (unlikely(!jobj_binary(val, "previousblockhash", prevhash, sizeof(prevhash)))) {
applog(LOG_ERR, "JSON invalid previousblockhash"); applog(LOG_ERR, "JSON invalid previousblockhash");
goto out; goto out;
@ -455,23 +445,6 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
applog(LOG_ERR, "JSON invalid coinbasetxn"); applog(LOG_ERR, "JSON invalid coinbasetxn");
goto out; goto out;
} }
bool hasWitness = *(uint16_t*)(cbtx + 4) == 256;
if (hasWitness && coinbase_append) {
// TODO: make this work by using index 43 instead of 41 in the coinbase_append handler below
// and then would we pass it in as one of our supported capabilities? Sure.
applog(LOG_ERR, "This tool cannot append onto segwit transactions");
goto out;
}
if (hasWitness) {
cbtx_hex = json_string_value(json_object_get(tmp, "txid"));
size_t txid_size = strlen(cbtx_hex) / 2;
cbtx_txid = malloc(txid_size + 1);
if (txid_size != 32 || !hex2bin(cbtx_txid, cbtx_hex, txid_size)) {
applog(LOG_ERR, "Invalid txid on coinbase");
goto out;
}
memrev(cbtx_txid, 32);
}
} else { } else {
int64_t cbvalue; int64_t cbvalue;
if (!pk_script_size) { if (!pk_script_size) {
@ -495,18 +468,12 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
le32enc((uint32_t *)(cbtx+37), 0xffffffff); /* prev txout index */ le32enc((uint32_t *)(cbtx+37), 0xffffffff); /* prev txout index */
cbtx_size = 43; cbtx_size = 43;
/* BIP 34: height in coinbase */ /* BIP 34: height in coinbase */
if (work->height >= 1 && work->height <= 16) { for (n = work->height; n; n >>= 8) {
/* Use OP_1-OP_16 to conform to Bitcoin's implementation. */ cbtx[cbtx_size++] = n & 0xff;
cbtx[42] = work->height + 0x50; if (n < 0x100 && n >= 0x80)
cbtx[cbtx_size++] = 0x00; /* OP_0; pads to 2 bytes */ cbtx[cbtx_size++] = 0;
} else {
for (n = work->height; n; n >>= 8) {
cbtx[cbtx_size++] = n & 0xff;
if (n < 0x100 && n >= 0x80)
cbtx[cbtx_size++] = 0;
}
cbtx[42] = cbtx_size - 43;
} }
cbtx[42] = cbtx_size - 43;
cbtx[41] = cbtx_size - 42; /* scriptsig length */ cbtx[41] = cbtx_size - 42; /* scriptsig length */
le32enc((uint32_t *)(cbtx+cbtx_size), 0xffffffff); /* sequence */ le32enc((uint32_t *)(cbtx+cbtx_size), 0xffffffff); /* sequence */
cbtx_size += 4; cbtx_size += 4;
@ -588,7 +555,7 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
if (xsig_len) { if (xsig_len) {
unsigned char *ssig_end = cbtx + 42 + cbtx[41]; unsigned char *ssig_end = cbtx + 42 + cbtx[41];
int push_len = cbtx[41] + xsig_len < 76 ? 1 : int push_len = cbtx[41] + xsig_len < 76 ? 1 :
cbtx[41] + 2 + xsig_len > 100 ? 0 : 2; cbtx[41] + 2 + xsig_len > 100 ? 0 : 2;
n = xsig_len + push_len; n = xsig_len + push_len;
memmove(ssig_end + n, ssig_end, cbtx_size - 42 - cbtx[41]); memmove(ssig_end + n, ssig_end, cbtx_size - 42 - cbtx[41]);
cbtx[41] += n; cbtx[41] += n;
@ -605,21 +572,14 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
work->txs = malloc(2 * (n + cbtx_size + tx_size) + 1); work->txs = malloc(2 * (n + cbtx_size + tx_size) + 1);
bin2hex(work->txs, txc_vi, n); bin2hex(work->txs, txc_vi, n);
bin2hex(work->txs + 2*n, cbtx, cbtx_size); bin2hex(work->txs + 2*n, cbtx, cbtx_size);
char *txs_end = work->txs + strlen(work->txs);
/* generate merkle root */ /* generate merkle root */
merkle_tree = malloc(32 * ((1 + tx_count + 1) & ~1)); merkle_tree = malloc(32 * ((1 + tx_count + 1) & ~1));
size_t tx_buf_size = 32 * 1024; sha256d(merkle_tree[0], cbtx, cbtx_size);
tx = malloc(tx_buf_size);
if (cbtx_txid)
memcpy(merkle_tree[0], cbtx_txid, 32);
else
sha256d(merkle_tree[0], cbtx, cbtx_size);
for (i = 0; i < tx_count; i++) { for (i = 0; i < tx_count; i++) {
tmp = json_array_get(txa, i); tmp = json_array_get(txa, i);
const char *tx_hex = json_string_value(json_object_get(tmp, "data")); const char *tx_hex = json_string_value(json_object_get(tmp, "data"));
const size_t tx_hex_len = tx_hex ? strlen(tx_hex) : 0; const int tx_size = tx_hex ? strlen(tx_hex) / 2 : 0;
const int tx_size = tx_hex_len / 2;
if (segwit) { if (segwit) {
const char *txid = json_string_value(json_object_get(tmp, "txid")); const char *txid = json_string_value(json_object_get(tmp, "txid"));
if (!txid || !hex2bin(merkle_tree[1 + i], txid, 32)) { if (!txid || !hex2bin(merkle_tree[1 + i], txid, 32)) {
@ -628,23 +588,18 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
} }
memrev(merkle_tree[1 + i], 32); memrev(merkle_tree[1 + i], 32);
} else { } else {
if (tx_size > tx_buf_size) { unsigned char *tx = malloc(tx_size);
free(tx);
tx_buf_size = tx_size * 2;
tx = malloc(tx_buf_size);
}
if (!tx_hex || !hex2bin(tx, tx_hex, tx_size)) { if (!tx_hex || !hex2bin(tx, tx_hex, tx_size)) {
applog(LOG_ERR, "JSON invalid transactions"); applog(LOG_ERR, "JSON invalid transactions");
free(tx);
goto out; goto out;
} }
sha256d(merkle_tree[1 + i], tx, tx_size); sha256d(merkle_tree[1 + i], tx, tx_size);
free(tx);
} }
if (!submit_coinbase) { if (!submit_coinbase)
strcpy(txs_end, tx_hex); strcat(work->txs, tx_hex);
txs_end += tx_hex_len;
}
} }
free(tx); tx = NULL;
n = 1 + tx_count; n = 1 + tx_count;
while (n > 1) { while (n > 1) {
if (n % 2) { if (n % 2) {
@ -662,17 +617,11 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
work->data[8 - i] = le32dec(prevhash + i); work->data[8 - i] = le32dec(prevhash + i);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
work->data[9 + i] = be32dec((uint32_t *)merkle_tree[0] + i); work->data[9 + i] = be32dec((uint32_t *)merkle_tree[0] + i);
int offset = 0; work->data[17] = swab32(curtime);
if (opt_algo == ALGO_LBRY) { work->data[18] = le32dec(&bits);
for (i = 0; i < 8; i++) memset(work->data + 19, 0x00, 52);
work->data[24 - i] = le32dec(claimtrie + i); work->data[20] = 0x80000000;
offset = 8; work->data[31] = 0x00000280;
}
work->data[17 + offset] = swab32(curtime);
work->data[18 + offset] = le32dec(&bits);
memset(work->data + 19 + offset, 0x00, 52);
work->data[20 + offset] = 0x80000000;
work->data[31 + offset] = 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"); applog(LOG_ERR, "JSON invalid target");
@ -707,16 +656,14 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
rc = true; rc = true;
out: out:
free(tx);
free(cbtx); free(cbtx);
free(cbtx_txid);
free(merkle_tree); free(merkle_tree);
return rc; return rc;
} }
static void share_result(int result, const char *reason) static void share_result(int result, const char *reason)
{ {
char s[370]; char s[345];
double hashrate; double hashrate;
int i; int i;
@ -743,7 +690,7 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
{ {
json_t *val, *res, *reason; json_t *val, *res, *reason;
char data_str[2 * sizeof(work->data) + 1]; char data_str[2 * sizeof(work->data) + 1];
char s[370]; char s[345];
int i; int i;
bool rc = false; bool rc = false;
@ -758,9 +705,8 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
uint32_t ntime, nonce; uint32_t ntime, nonce;
char ntimestr[9], noncestr[9], *xnonce2str, *req; char ntimestr[9], noncestr[9], *xnonce2str, *req;
int offset = opt_algo == ALGO_LBRY ? 8 : 0; le32enc(&ntime, work->data[17]);
le32enc(&ntime, work->data[17 + offset]); le32enc(&nonce, work->data[19]);
le32enc(&nonce, work->data[19 + offset]);
bin2hex(ntimestr, (const unsigned char *)(&ntime), 4); bin2hex(ntimestr, (const unsigned char *)(&ntime), 4);
bin2hex(noncestr, (const unsigned char *)(&nonce), 4); bin2hex(noncestr, (const unsigned char *)(&nonce), 4);
xnonce2str = abin2hex(work->xnonce2, work->xnonce2_len); xnonce2str = abin2hex(work->xnonce2, work->xnonce2_len);
@ -781,21 +727,20 @@ static bool submit_upstream_work(CURL *curl, struct work *work)
for (i = 0; i < ARRAY_SIZE(work->data); i++) for (i = 0; i < ARRAY_SIZE(work->data); i++)
be32enc(work->data + i, work->data[i]); be32enc(work->data + i, work->data[i]);
int offset = opt_algo == ALGO_LBRY ? 112 : 80; bin2hex(data_str, (unsigned char *)work->data, 80);
bin2hex(data_str, (unsigned char *)work->data, offset);
if (work->workid) { if (work->workid) {
char *params; char *params;
val = json_object(); val = json_object();
json_object_set_new(val, "workid", json_string(work->workid)); json_object_set_new(val, "workid", json_string(work->workid));
params = json_dumps(val, 0); params = json_dumps(val, 0);
json_decref(val); json_decref(val);
req = malloc(160 + 2*offset + strlen(work->txs) + strlen(params)); req = malloc(128 + 2*80 + strlen(work->txs) + strlen(params));
sprintf(req, sprintf(req,
"{\"method\": \"submitblock\", \"params\": [\"%s%s\", %s], \"id\":1}\r\n", "{\"method\": \"submitblock\", \"params\": [\"%s%s\", %s], \"id\":1}\r\n",
data_str, work->txs, params); data_str, work->txs, params);
free(params); free(params);
} else { } else {
req = malloc(160 + 2*offset + strlen(work->txs)); req = malloc(128 + 2*80 + strlen(work->txs));
sprintf(req, sprintf(req,
"{\"method\": \"submitblock\", \"params\": [\"%s%s\"], \"id\":1}\r\n", "{\"method\": \"submitblock\", \"params\": [\"%s%s\"], \"id\":1}\r\n",
data_str, work->txs); data_str, work->txs);
@ -880,8 +825,8 @@ static bool get_upstream_work(CURL *curl, struct work *work)
start: start:
gettimeofday(&tv_start, NULL); gettimeofday(&tv_start, NULL);
val = json_rpc_call(curl, rpc_url, rpc_userpass, val = json_rpc_call(curl, rpc_url, rpc_userpass,
have_gbt ? gbt_req : getwork_req, have_gbt ? gbt_req : getwork_req,
&err, have_gbt ? JSON_RPC_QUIET_404 : 0); &err, have_gbt ? JSON_RPC_QUIET_404 : 0);
gettimeofday(&tv_end, NULL); gettimeofday(&tv_end, NULL);
if (have_stratum) { if (have_stratum) {
@ -918,7 +863,7 @@ start:
if (opt_debug && rc) { if (opt_debug && rc) {
timeval_subtract(&diff, &tv_end, &tv_start); timeval_subtract(&diff, &tv_end, &tv_start);
applog(LOG_DEBUG, "DEBUG: got new work in %d ms", applog(LOG_DEBUG, "DEBUG: got new work in %d ms",
diff.tv_sec * 1000 + diff.tv_usec / 1000); diff.tv_sec * 1000 + diff.tv_usec / 1000);
} }
json_decref(val); json_decref(val);
@ -1111,7 +1056,7 @@ err_out:
static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work) static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
{ {
unsigned char merkle_root[64]; unsigned char merkle_root[64];
int i, offset = 0; int i;
pthread_mutex_lock(&sctx->work_lock); pthread_mutex_lock(&sctx->work_lock);
@ -1132,29 +1077,23 @@ static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
for (i = 0; i < sctx->xnonce2_size && !++sctx->job.xnonce2[i]; i++); for (i = 0; i < sctx->xnonce2_size && !++sctx->job.xnonce2[i]; i++);
/* Assemble block header */ /* Assemble block header */
memset(work->data, 0, sizeof(work->data)); memset(work->data, 0, 128);
work->data[0] = le32dec(sctx->job.version); work->data[0] = le32dec(sctx->job.version);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
work->data[1 + i] = le32dec((uint32_t *)sctx->job.prevhash + i); work->data[1 + i] = le32dec((uint32_t *)sctx->job.prevhash + i);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
work->data[9 + i] = be32dec((uint32_t *)merkle_root + i); work->data[9 + i] = be32dec((uint32_t *)merkle_root + i);
work->data[17] = le32dec(sctx->job.ntime);
if (sctx->job.needs_claimhash) { work->data[18] = le32dec(sctx->job.nbits);
offset = 8; work->data[20] = 0x80000000;
for (i = 0; i < 8; i++) work->data[31] = 0x00000280;
work->data[24 - i] = le32dec((uint32_t *)sctx->job.claimhash + i);
}
work->data[17 + offset] = le32dec(sctx->job.ntime);
work->data[18 + offset] = le32dec(sctx->job.nbits);
work->data[20 + offset] = 0x80000000;
work->data[31 + offset] = 0x00000280;
pthread_mutex_unlock(&sctx->work_lock); pthread_mutex_unlock(&sctx->work_lock);
if (opt_debug) { if (opt_debug) {
char *xnonce2str = abin2hex(work->xnonce2, work->xnonce2_len); char *xnonce2str = abin2hex(work->xnonce2, work->xnonce2_len);
applog(LOG_DEBUG, "DEBUG: job_id='%s' extranonce2=%s ntime=%08x", applog(LOG_DEBUG, "DEBUG: job_id='%s' extranonce2=%s ntime=%08x",
work->job_id, xnonce2str, swab32(work->data[17 + offset])); work->job_id, xnonce2str, swab32(work->data[17]));
free(xnonce2str); free(xnonce2str);
} }
@ -1164,9 +1103,6 @@ static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
diff_to_target(work->target, sctx->job.diff); diff_to_target(work->target, sctx->job.diff);
} }
extern int scanhash_lbry(int thr_id, uint32_t *pdata, const uint32_t *ptarget,
uint32_t max_nonce, uint64_t *hashes_done);
static void *miner_thread(void *userdata) static void *miner_thread(void *userdata)
{ {
struct thr_info *mythr = userdata; struct thr_info *mythr = userdata;
@ -1191,7 +1127,7 @@ static void *miner_thread(void *userdata)
if (num_processors > 1 && opt_n_threads % num_processors == 0) { if (num_processors > 1 && opt_n_threads % num_processors == 0) {
if (!opt_quiet) if (!opt_quiet)
applog(LOG_INFO, "Binding thread %d to cpu %d", applog(LOG_INFO, "Binding thread %d to cpu %d",
thr_id, thr_id % num_processors); thr_id, thr_id % num_processors);
affine_to_cpu(thr_id, thr_id % num_processors); affine_to_cpu(thr_id, thr_id % num_processors);
} }
@ -1204,8 +1140,6 @@ static void *miner_thread(void *userdata)
} }
} }
int offset = opt_algo == ALGO_LBRY ? 8 : 0;
while (1) { while (1) {
unsigned long hashes_done; unsigned long hashes_done;
struct timeval tv_start, tv_end, diff; struct timeval tv_start, tv_end, diff;
@ -1216,15 +1150,15 @@ static void *miner_thread(void *userdata)
while (time(NULL) >= g_work_time + 120) while (time(NULL) >= g_work_time + 120)
sleep(1); sleep(1);
pthread_mutex_lock(&g_work_lock); pthread_mutex_lock(&g_work_lock);
if (work.data[19 + offset] >= end_nonce && !memcmp(work.data, g_work.data, 76 + offset * 4)) if (work.data[19] >= end_nonce && !memcmp(work.data, g_work.data, 76))
stratum_gen_work(&stratum, &g_work); stratum_gen_work(&stratum, &g_work);
} else { } else {
int min_scantime = have_longpoll ? LP_SCANTIME : opt_scantime; int min_scantime = have_longpoll ? LP_SCANTIME : opt_scantime;
/* obtain new work from internal workio thread */ /* obtain new work from internal workio thread */
pthread_mutex_lock(&g_work_lock); pthread_mutex_lock(&g_work_lock);
if (!have_stratum && if (!have_stratum &&
(time(NULL) - g_work_time >= min_scantime || (time(NULL) - g_work_time >= min_scantime ||
work.data[19 + offset] >= end_nonce)) { work.data[19] >= end_nonce)) {
work_free(&g_work); work_free(&g_work);
if (unlikely(!get_work(mythr, &g_work))) { if (unlikely(!get_work(mythr, &g_work))) {
applog(LOG_ERR, "work retrieval failed, exiting " applog(LOG_ERR, "work retrieval failed, exiting "
@ -1239,56 +1173,52 @@ static void *miner_thread(void *userdata)
continue; continue;
} }
} }
if (memcmp(work.data, g_work.data, 76 + offset * 4)) { if (memcmp(work.data, g_work.data, 76)) {
work_free(&work); work_free(&work);
work_copy(&work, &g_work); work_copy(&work, &g_work);
work.data[19 + offset] = 0xffffffffU / opt_n_threads * thr_id; work.data[19] = 0xffffffffU / opt_n_threads * thr_id;
} else } else
work.data[19 + offset]++; work.data[19]++;
pthread_mutex_unlock(&g_work_lock); pthread_mutex_unlock(&g_work_lock);
work_restart[thr_id].restart = 0; work_restart[thr_id].restart = 0;
/* adjust max_nonce to meet target scan time */ /* adjust max_nonce to meet target scan time */
if (have_stratum) if (have_stratum)
max64 = LP_SCANTIME; max64 = LP_SCANTIME;
else else
max64 = g_work_time + (have_longpoll ? LP_SCANTIME : opt_scantime) max64 = g_work_time + (have_longpoll ? LP_SCANTIME : opt_scantime)
- time(NULL); - time(NULL);
max64 *= thr_hashrates[thr_id]; max64 *= thr_hashrates[thr_id];
if (max64 <= 0) { if (max64 <= 0) {
switch (opt_algo) { switch (opt_algo) {
case ALGO_SCRYPT: case ALGO_SCRYPT:
max64 = opt_scrypt_n < 16 ? 0x3ffff : 0x3fffff / opt_scrypt_n; max64 = opt_scrypt_n < 16 ? 0x3ffff : 0x3fffff / opt_scrypt_n;
break; break;
case ALGO_LBRY:
case ALGO_SHA256D: case ALGO_SHA256D:
max64 = 0x1fffff; max64 = 0x1fffff;
break; break;
} }
} }
if (work.data[19 + offset] + max64 > end_nonce) if (work.data[19] + max64 > end_nonce)
max_nonce = end_nonce; max_nonce = end_nonce;
else else
max_nonce = work.data[19 + offset] + max64; max_nonce = work.data[19] + max64;
hashes_done = 0; hashes_done = 0;
gettimeofday(&tv_start, NULL); gettimeofday(&tv_start, NULL);
/* scan nonces for a proof-of-work hash */ /* scan nonces for a proof-of-work hash */
switch (opt_algo) { switch (opt_algo) {
case ALGO_LBRY:
rc = scanhash_lbry(thr_id, work.data, work.target,
max_nonce, &hashes_done);
break;
case ALGO_SCRYPT: case ALGO_SCRYPT:
rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target, rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target,
max_nonce, &hashes_done, opt_scrypt_n); max_nonce, &hashes_done, opt_scrypt_n);
break; break;
case ALGO_SHA256D: case ALGO_SHA256D:
rc = scanhash_sha256d(thr_id, work.data, work.target, rc = scanhash_sha256d(thr_id, work.data, work.target,
max_nonce, &hashes_done); max_nonce, &hashes_done);
break; break;
default: default:
/* should never happen */ /* should never happen */
goto out; goto out;
@ -1387,8 +1317,8 @@ start:
sprintf(req, gbt_lp_req, lp_id); sprintf(req, gbt_lp_req, lp_id);
} }
val = json_rpc_call(curl, lp_url, rpc_userpass, val = json_rpc_call(curl, lp_url, rpc_userpass,
req ? req : getwork_req, &err, req ? req : getwork_req, &err,
JSON_RPC_LONGPOLL); JSON_RPC_LONGPOLL);
free(req); free(req);
if (have_stratum) { if (have_stratum) {
if (val) if (val)
@ -1397,6 +1327,7 @@ start:
} }
if (likely(val)) { if (likely(val)) {
bool rc; bool rc;
applog(LOG_INFO, "LONGPOLL pushed new work");
res = json_object_get(val, "result"); res = json_object_get(val, "result");
soval = json_object_get(res, "submitold"); soval = json_object_get(res, "submitold");
submit_old = soval ? json_is_true(soval) : false; submit_old = soval ? json_is_true(soval) : false;
@ -1490,8 +1421,8 @@ static void *stratum_thread(void *userdata)
restart_threads(); restart_threads();
if (!stratum_connect(&stratum, stratum.url) || if (!stratum_connect(&stratum, stratum.url) ||
!stratum_subscribe(&stratum) || !stratum_subscribe(&stratum) ||
!stratum_authorize(&stratum, rpc_user, rpc_pass)) { !stratum_authorize(&stratum, rpc_user, rpc_pass)) {
stratum_disconnect(&stratum); stratum_disconnect(&stratum);
if (opt_retries >= 0 && ++failures > opt_retries) { if (opt_retries >= 0 && ++failures > opt_retries) {
applog(LOG_ERR, "...terminating workio thread"); applog(LOG_ERR, "...terminating workio thread");
@ -1504,7 +1435,7 @@ static void *stratum_thread(void *userdata)
} }
if (stratum.job.job_id && if (stratum.job.job_id &&
(!g_work_time || strcmp(stratum.job.job_id, g_work.job_id))) { (!g_work_time || strcmp(stratum.job.job_id, g_work.job_id))) {
pthread_mutex_lock(&g_work_lock); pthread_mutex_lock(&g_work_lock);
stratum_gen_work(&stratum, &g_work); stratum_gen_work(&stratum, &g_work);
time(&g_work_time); time(&g_work_time);
@ -1731,9 +1662,9 @@ static void parse_arg(int key, char *arg, char *pname)
hp = ap; hp = ap;
if (ap != arg) { if (ap != arg) {
if (strncasecmp(arg, "http://", 7) && if (strncasecmp(arg, "http://", 7) &&
strncasecmp(arg, "https://", 8) && strncasecmp(arg, "https://", 8) &&
strncasecmp(arg, "stratum+tcp://", 14) && strncasecmp(arg, "stratum+tcp://", 14) &&
strncasecmp(arg, "stratum+tcps://", 15)) { strncasecmp(arg, "stratum+tcps://", 15)) {
fprintf(stderr, "%s: unknown protocol -- '%s'\n", fprintf(stderr, "%s: unknown protocol -- '%s'\n",
pname, arg); pname, arg);
show_usage_and_exit(1); show_usage_and_exit(1);
@ -1800,13 +1731,13 @@ static void parse_arg(int key, char *arg, char *pname)
want_longpoll = false; want_longpoll = false;
break; break;
case 1007: case 1007:
want_stratum = true; want_stratum = false;
break; break;
case 1009: case 1009:
opt_redirect = false; opt_redirect = false;
break; break;
case 1010: case 1010:
allow_getwork = true; allow_getwork = false;
break; break;
case 1011: case 1011:
have_gbt = false; have_gbt = false;
@ -1945,9 +1876,9 @@ int main(int argc, char *argv[])
pthread_mutex_init(&stratum.work_lock, NULL); pthread_mutex_init(&stratum.work_lock, NULL);
flags = opt_benchmark || (strncasecmp(rpc_url, "https://", 8) && flags = opt_benchmark || (strncasecmp(rpc_url, "https://", 8) &&
strncasecmp(rpc_url, "stratum+tcps://", 15)) strncasecmp(rpc_url, "stratum+tcps://", 15))
? (CURL_GLOBAL_ALL & ~CURL_GLOBAL_SSL) ? (CURL_GLOBAL_ALL & ~CURL_GLOBAL_SSL)
: CURL_GLOBAL_ALL; : CURL_GLOBAL_ALL;
if (curl_global_init(flags)) { if (curl_global_init(flags)) {
applog(LOG_ERR, "CURL initialization failed"); applog(LOG_ERR, "CURL initialization failed");
return 1; return 1;
@ -2036,7 +1967,6 @@ int main(int argc, char *argv[])
} }
if (want_stratum) { if (want_stratum) {
/* init stratum thread info */ /* init stratum thread info */
stratum.job.needs_claimhash = opt_algo == ALGO_LBRY;
stratum_thr_id = opt_n_threads + 2; stratum_thr_id = opt_n_threads + 2;
thr = &thr_info[stratum_thr_id]; thr = &thr_info[stratum_thr_id];
thr->id = stratum_thr_id; thr->id = stratum_thr_id;

128
lbry.c
View file

@ -1,128 +0,0 @@
#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;
}

12
miner.h
View file

@ -58,14 +58,6 @@ enum {
#define likely(expr) (expr) #define likely(expr) (expr)
#endif #endif
#if defined(_MSC_VER)
#define THREADLOCAL __declspec(thread)
#elif defined(__GNUC__)
#define THREADLOCAL __thread
#else
#define THREADLOCAL
#endif
#ifndef ARRAY_SIZE #ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif #endif
@ -145,7 +137,7 @@ void sha256_transform(uint32_t *state, const uint32_t *block, int swap);
void sha256d(unsigned char *hash, const unsigned char *data, int len); void sha256d(unsigned char *hash, const unsigned char *data, int len);
#ifdef USE_ASM #ifdef USE_ASM
#if (defined(__APCS_32__) && defined(__ARM_NEON__)) || defined(__ALTIVEC__) || defined(__i386__) || defined(__x86_64__) #if defined(__ARM_NEON__) || defined(__ALTIVEC__) || defined(__i386__) || defined(__x86_64__)
#define HAVE_SHA256_4WAY 1 #define HAVE_SHA256_4WAY 1
int sha256_use_4way(); int sha256_use_4way();
void sha256_init_4way(uint32_t *state); void sha256_init_4way(uint32_t *state);
@ -228,8 +220,6 @@ struct stratum_job {
unsigned char ntime[4]; unsigned char ntime[4];
bool clean; bool clean;
double diff; double diff;
unsigned char claimhash[32];
bool needs_claimhash;
}; };
struct stratum_ctx { struct stratum_ctx {

View file

@ -1,4 +1,4 @@
.TH MINERD 1 "June 2020" "cpuminer 2.5.1" .TH MINERD 1 "June 2016" "cpuminer 2.4.5"
.SH NAME .SH NAME
minerd \- CPU miner for Bitcoin and Litecoin minerd \- CPU miner for Bitcoin and Litecoin
.SH SYNOPSIS .SH SYNOPSIS
@ -93,7 +93,6 @@ Only supported when using the HTTPS protocol.
Set a payout address for solo mining. Set a payout address for solo mining.
This is only used in getblocktemplate mode, This is only used in getblocktemplate mode,
and only if the server does not provide a coinbase transaction. and only if the server does not provide a coinbase transaction.
It can be either a base-58 address, or a bech32 address (BIP 173).
.TP .TP
\fB\-\-coinbase\-sig\fR=\fITEXT\fR \fB\-\-coinbase\-sig\fR=\fITEXT\fR
Set a string to be included in the coinbase (if allowed by the server). Set a string to be included in the coinbase (if allowed by the server).

View file

@ -1,348 +0,0 @@
/* $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);
}

View file

@ -1,281 +0,0 @@
/* $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

View file

@ -1,378 +0,0 @@
/* $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

File diff suppressed because it is too large Load diff

View file

@ -1,841 +0,0 @@
/* $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

View file

@ -1,698 +0,0 @@
/* $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

View file

@ -1,255 +0,0 @@
/* $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

346
util.c
View file

@ -1,8 +1,7 @@
/* /*
* Copyright 2010 Jeff Garzik * Copyright 2010 Jeff Garzik
* Copyright 2012 Luke Dashjr * Copyright 2012 Luke Dashjr
* Copyright 2012-2020 pooler * Copyright 2012-2017 pooler
* Copyright 2017 Pieter Wuille
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free * under the terms of the GNU General Public License as published by the Free
@ -38,18 +37,21 @@
#include "miner.h" #include "miner.h"
#include "elist.h" #include "elist.h"
struct data_buffer {
void *buf;
size_t len;
};
struct upload_buffer {
const void *buf;
size_t len;
size_t pos;
};
struct header_info { struct header_info {
char *lp_path; char *lp_path;
char *reason; char *reason;
char *stratum_url; char *stratum_url;
size_t content_length;
};
struct data_buffer {
void *buf;
size_t len;
size_t allocated;
struct header_info *headers;
}; };
struct tq_ent { struct tq_ent {
@ -185,51 +187,65 @@ static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb,
{ {
struct data_buffer *db = user_data; struct data_buffer *db = user_data;
size_t len = size * nmemb; size_t len = size * nmemb;
size_t newalloc, reqalloc; size_t oldlen, newlen;
void *newmem; void *newmem;
static const unsigned char zero = 0; static const unsigned char zero = 0;
static const size_t max_realloc_increase = 8 * 1024 * 1024;
static const size_t initial_alloc = 16 * 1024;
/* minimum required allocation size */ oldlen = db->len;
reqalloc = db->len + len + 1; newlen = oldlen + len;
if (reqalloc > db->allocated) { newmem = realloc(db->buf, newlen + 1);
if (db->len > 0) { if (!newmem)
newalloc = db->allocated * 2; return 0;
} else {
if (db->headers->content_length > 0)
newalloc = db->headers->content_length + 1;
else
newalloc = initial_alloc;
}
if (db->headers->content_length == 0) { db->buf = newmem;
/* limit the maximum buffer increase */ db->len = newlen;
if (newalloc - db->allocated > max_realloc_increase) memcpy(db->buf + oldlen, ptr, len);
newalloc = db->allocated + max_realloc_increase; memcpy(db->buf + newlen, &zero, 1); /* null terminate */
}
/* ensure we have a big enough allocation */
if (reqalloc > newalloc)
newalloc = reqalloc;
newmem = realloc(db->buf, newalloc);
if (!newmem)
return 0;
db->buf = newmem;
db->allocated = newalloc;
}
memcpy(db->buf + db->len, ptr, len); /* append new data */
memcpy(db->buf + db->len + len, &zero, 1); /* null terminate */
db->len += len;
return len; return len;
} }
static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb,
void *user_data)
{
struct upload_buffer *ub = user_data;
int len = size * nmemb;
if (len > ub->len - ub->pos)
len = ub->len - ub->pos;
if (len) {
memcpy(ptr, ub->buf + ub->pos, len);
ub->pos += len;
}
return len;
}
#if LIBCURL_VERSION_NUM >= 0x071200
static int seek_data_cb(void *user_data, curl_off_t offset, int origin)
{
struct upload_buffer *ub = user_data;
switch (origin) {
case SEEK_SET:
ub->pos = offset;
break;
case SEEK_CUR:
ub->pos += offset;
break;
case SEEK_END:
ub->pos = ub->len + offset;
break;
default:
return 1; /* CURL_SEEKFUNC_FAIL */
}
return 0; /* CURL_SEEKFUNC_OK */
}
#endif
static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data) static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data)
{ {
struct header_info *hi = user_data; struct header_info *hi = user_data;
@ -281,9 +297,6 @@ static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data)
val = NULL; val = NULL;
} }
if (!strcasecmp("Content-Length", key))
hi->content_length = strtoul(val, NULL, 10);
out: out:
free(key); free(key);
free(val); free(val);
@ -342,14 +355,15 @@ json_t *json_rpc_call(CURL *curl, const char *url,
int rc; int rc;
long http_rc; long http_rc;
struct data_buffer all_data = {0}; struct data_buffer all_data = {0};
struct upload_buffer upload_data;
char *json_buf; char *json_buf;
json_error_t err; json_error_t err;
struct curl_slist *headers = NULL; struct curl_slist *headers = NULL;
char len_hdr[64];
char curl_err_str[CURL_ERROR_SIZE]; char curl_err_str[CURL_ERROR_SIZE];
long timeout = (flags & JSON_RPC_LONGPOLL) ? opt_timeout : 70; long timeout = (flags & JSON_RPC_LONGPOLL) ? opt_timeout : 30;
struct header_info hi = {0}; struct header_info hi = {0};
all_data.headers = &hi;
/* it is assumed that 'curl' is freshly [re]initialized at this pt */ /* it is assumed that 'curl' is freshly [re]initialized at this pt */
if (opt_protocol) if (opt_protocol)
@ -363,6 +377,12 @@ json_t *json_rpc_call(CURL *curl, const char *url,
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1); curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, upload_data_cb);
curl_easy_setopt(curl, CURLOPT_READDATA, &upload_data);
#if LIBCURL_VERSION_NUM >= 0x071200
curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, &seek_data_cb);
curl_easy_setopt(curl, CURLOPT_SEEKDATA, &upload_data);
#endif
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
if (opt_redirect) if (opt_redirect)
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
@ -381,12 +401,19 @@ json_t *json_rpc_call(CURL *curl, const char *url,
if (flags & JSON_RPC_LONGPOLL) if (flags & JSON_RPC_LONGPOLL)
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb); curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb);
#endif #endif
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, rpc_req); curl_easy_setopt(curl, CURLOPT_POST, 1);
if (opt_protocol) if (opt_protocol)
applog(LOG_DEBUG, "JSON protocol request:\n%s\n", rpc_req); applog(LOG_DEBUG, "JSON protocol request:\n%s\n", rpc_req);
upload_data.buf = rpc_req;
upload_data.len = strlen(rpc_req);
upload_data.pos = 0;
sprintf(len_hdr, "Content-Length: %lu",
(unsigned long) upload_data.len);
headers = curl_slist_append(headers, "Content-Type: application/json"); headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, len_hdr);
headers = curl_slist_append(headers, "User-Agent: " USER_AGENT); headers = curl_slist_append(headers, "User-Agent: " USER_AGENT);
headers = curl_slist_append(headers, "X-Mining-Extensions: midstate"); headers = curl_slist_append(headers, "X-Mining-Extensions: midstate");
headers = curl_slist_append(headers, "Accept:"); /* disable Accept hdr*/ headers = curl_slist_append(headers, "Accept:"); /* disable Accept hdr*/
@ -508,42 +535,29 @@ char *abin2hex(const unsigned char *p, size_t len)
bool hex2bin(unsigned char *p, const char *hexstr, size_t len) bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
{ {
if(hexstr == NULL) char hex_byte[3];
return false; char *ep;
size_t hexstr_len = strlen(hexstr); hex_byte[2] = '\0';
if((hexstr_len % 2) != 0) {
applog(LOG_ERR, "hex2bin str truncated");
return false;
}
size_t bin_len = hexstr_len / 2; while (*hexstr && len) {
if (bin_len > len) { if (!hexstr[1]) {
applog(LOG_ERR, "hex2bin buffer too small"); applog(LOG_ERR, "hex2bin str truncated");
return false;
}
memset(p, 0, len);
size_t i = 0;
while (i < hexstr_len) {
char c = hexstr[i];
unsigned char nibble;
if(c >= '0' && c <= '9') {
nibble = (c - '0');
} else if (c >= 'A' && c <= 'F') {
nibble = (10 + (c - 'A'));
} else if (c >= 'a' && c <= 'f') {
nibble = (10 + (c - 'a'));
} else {
applog(LOG_ERR, "hex2bin invalid hex");
return false; return false;
} }
p[(i / 2)] |= (nibble << ((1 - (i % 2)) * 4)); hex_byte[0] = hexstr[0];
i++; hex_byte[1] = hexstr[1];
*p = (unsigned char) strtol(hex_byte, &ep, 16);
if (*ep) {
applog(LOG_ERR, "hex2bin failed on '%s'", hex_byte);
return false;
}
p++;
hexstr += 2;
len--;
} }
return true; return (len == 0 && *hexstr == 0) ? true : false;
} }
int varint_encode(unsigned char *p, uint64_t n) int varint_encode(unsigned char *p, uint64_t n)
@ -645,136 +659,6 @@ static int b58check(unsigned char *bin, size_t binsz, const char *b58)
return bin[0]; return bin[0];
} }
static uint32_t bech32_polymod_step(uint32_t pre) {
uint8_t b = pre >> 25;
return ((pre & 0x1FFFFFF) << 5) ^
(-((b >> 0) & 1) & 0x3b6a57b2UL) ^
(-((b >> 1) & 1) & 0x26508e6dUL) ^
(-((b >> 2) & 1) & 0x1ea119faUL) ^
(-((b >> 3) & 1) & 0x3d4233ddUL) ^
(-((b >> 4) & 1) & 0x2a1462b3UL);
}
static const int8_t bech32_charset_rev[128] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
-1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
-1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
};
static bool bech32_decode(char *hrp, uint8_t *data, size_t *data_len, const char *input) {
uint32_t chk = 1;
size_t i;
size_t input_len = strlen(input);
size_t hrp_len;
int have_lower = 0, have_upper = 0;
if (input_len < 8 || input_len > 90) {
return false;
}
*data_len = 0;
while (*data_len < input_len && input[(input_len - 1) - *data_len] != '1') {
++(*data_len);
}
hrp_len = input_len - (1 + *data_len);
if (1 + *data_len >= input_len || *data_len < 6) {
return false;
}
*(data_len) -= 6;
for (i = 0; i < hrp_len; ++i) {
int ch = input[i];
if (ch < 33 || ch > 126) {
return false;
}
if (ch >= 'a' && ch <= 'z') {
have_lower = 1;
} else if (ch >= 'A' && ch <= 'Z') {
have_upper = 1;
ch = (ch - 'A') + 'a';
}
hrp[i] = ch;
chk = bech32_polymod_step(chk) ^ (ch >> 5);
}
hrp[i] = 0;
chk = bech32_polymod_step(chk);
for (i = 0; i < hrp_len; ++i) {
chk = bech32_polymod_step(chk) ^ (input[i] & 0x1f);
}
++i;
while (i < input_len) {
int v = (input[i] & 0x80) ? -1 : bech32_charset_rev[(int)input[i]];
if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1;
if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1;
if (v == -1) {
return false;
}
chk = bech32_polymod_step(chk) ^ v;
if (i + 6 < input_len) {
data[i - (1 + hrp_len)] = v;
}
++i;
}
if (have_lower && have_upper) {
return false;
}
return chk == 1;
}
static bool convert_bits(uint8_t *out, size_t *outlen, int outbits, const uint8_t *in, size_t inlen, int inbits, int pad) {
uint32_t val = 0;
int bits = 0;
uint32_t maxv = (((uint32_t)1) << outbits) - 1;
while (inlen--) {
val = (val << inbits) | *(in++);
bits += inbits;
while (bits >= outbits) {
bits -= outbits;
out[(*outlen)++] = (val >> bits) & maxv;
}
}
if (pad) {
if (bits) {
out[(*outlen)++] = (val << (outbits - bits)) & maxv;
}
} else if (((val << (outbits - bits)) & maxv) || bits >= inbits) {
return false;
}
return true;
}
static bool segwit_addr_decode(int *witver, uint8_t *witdata, size_t *witdata_len, const char *addr) {
uint8_t data[84];
char hrp_actual[84];
size_t data_len;
if (!bech32_decode(hrp_actual, data, &data_len, addr)) return false;
if (data_len == 0 || data_len > 65) return false;
if (data[0] > 16) return false;
*witdata_len = 0;
if (!convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) return false;
if (*witdata_len < 2 || *witdata_len > 40) return false;
if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) return false;
*witver = data[0];
return true;
}
static size_t bech32_to_script(uint8_t *out, size_t outsz, const char *addr) {
uint8_t witprog[40];
size_t witprog_len;
int witver;
if (!segwit_addr_decode(&witver, witprog, &witprog_len, addr))
return 0;
if (outsz < witprog_len + 2)
return 0;
out[0] = witver ? (0x50 + witver) : 0;
out[1] = witprog_len;
memcpy(out + 2, witprog, witprog_len);
return witprog_len + 2;
}
size_t address_to_script(unsigned char *out, size_t outsz, const char *addr) size_t address_to_script(unsigned char *out, size_t outsz, const char *addr)
{ {
unsigned char addrbin[25]; unsigned char addrbin[25];
@ -782,12 +666,12 @@ size_t address_to_script(unsigned char *out, size_t outsz, const char *addr)
size_t rv; size_t rv;
if (!b58dec(addrbin, sizeof(addrbin), addr)) if (!b58dec(addrbin, sizeof(addrbin), addr))
return bech32_to_script(out, outsz, addr); return 0;
addrver = b58check(addrbin, sizeof(addrbin), addr); addrver = b58check(addrbin, sizeof(addrbin), addr);
if (addrver < 0) if (addrver < 0)
return 0; return 0;
switch (addrver) { switch (addrver) {
case 0x7a: /* LBRY mainnet script hash */ case 5: /* Bitcoin script hash */
case 196: /* Testnet script hash */ case 196: /* Testnet script hash */
if (outsz < (rv = 23)) if (outsz < (rv = 23))
return rv; return rv;
@ -1049,7 +933,7 @@ out:
return sret; return sret;
} }
#if LIBCURL_VERSION_NUM >= 0x071101 && LIBCURL_VERSION_NUM < 0x072d00 #if LIBCURL_VERSION_NUM >= 0x071101
static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose, static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose,
struct curl_sockaddr *addr) struct curl_sockaddr *addr)
{ {
@ -1107,7 +991,7 @@ bool stratum_connect(struct stratum_ctx *sctx, const char *url)
#if LIBCURL_VERSION_NUM >= 0x070f06 #if LIBCURL_VERSION_NUM >= 0x070f06
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb); curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb);
#endif #endif
#if LIBCURL_VERSION_NUM >= 0x071101 && LIBCURL_VERSION_NUM < 0x072d00 #if LIBCURL_VERSION_NUM >= 0x071101
curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket_grab_cb); curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket_grab_cb);
curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sctx->sock); curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sctx->sock);
#endif #endif
@ -1121,9 +1005,7 @@ bool stratum_connect(struct stratum_ctx *sctx, const char *url)
return false; return false;
} }
#if LIBCURL_VERSION_NUM >= 0x072d00 #if LIBCURL_VERSION_NUM < 0x071101
curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sctx->sock);
#elif LIBCURL_VERSION_NUM < 0x071101
/* CURLINFO_LASTSOCKET is broken on Win64; only use it as a last resort */ /* CURLINFO_LASTSOCKET is broken on Win64; only use it as a last resort */
curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&sctx->sock); curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&sctx->sock);
#endif #endif
@ -1321,27 +1203,25 @@ out:
static bool stratum_notify(struct stratum_ctx *sctx, json_t *params) static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
{ {
const char *job_id, *prevhash, *coinb1, *coinb2, *version, *nbits, *ntime, *claimhash; const char *job_id, *prevhash, *coinb1, *coinb2, *version, *nbits, *ntime;
size_t coinb1_size, coinb2_size; size_t coinb1_size, coinb2_size;
bool clean, ret = false; bool clean, ret = false;
int merkle_count, i, idx = 0; int merkle_count, i;
json_t *merkle_arr; json_t *merkle_arr;
unsigned char **merkle; unsigned char **merkle;
job_id = json_string_value(json_array_get(params, idx++)); job_id = json_string_value(json_array_get(params, 0));
prevhash = json_string_value(json_array_get(params, idx++)); prevhash = json_string_value(json_array_get(params, 1));
if (sctx->job.needs_claimhash) coinb1 = json_string_value(json_array_get(params, 2));
claimhash = json_string_value(json_array_get(params, idx++)); coinb2 = json_string_value(json_array_get(params, 3));
coinb1 = json_string_value(json_array_get(params, idx++)); merkle_arr = json_array_get(params, 4);
coinb2 = json_string_value(json_array_get(params, idx++));
merkle_arr = json_array_get(params, idx++);
if (!merkle_arr || !json_is_array(merkle_arr)) if (!merkle_arr || !json_is_array(merkle_arr))
goto out; goto out;
merkle_count = json_array_size(merkle_arr); merkle_count = json_array_size(merkle_arr);
version = json_string_value(json_array_get(params, idx++)); version = json_string_value(json_array_get(params, 5));
nbits = json_string_value(json_array_get(params, idx++)); nbits = json_string_value(json_array_get(params, 6));
ntime = json_string_value(json_array_get(params, idx++)); ntime = json_string_value(json_array_get(params, 7));
clean = json_is_true(json_array_get(params, idx++)); clean = json_is_true(json_array_get(params, 8));
if (!job_id || !prevhash || !coinb1 || !coinb2 || !version || !nbits || !ntime || if (!job_id || !prevhash || !coinb1 || !coinb2 || !version || !nbits || !ntime ||
strlen(prevhash) != 64 || strlen(version) != 8 || strlen(prevhash) != 64 || strlen(version) != 8 ||
@ -1380,8 +1260,6 @@ static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
free(sctx->job.job_id); free(sctx->job.job_id);
sctx->job.job_id = strdup(job_id); sctx->job.job_id = strdup(job_id);
hex2bin(sctx->job.prevhash, prevhash, 32); hex2bin(sctx->job.prevhash, prevhash, 32);
if (sctx->job.needs_claimhash)
hex2bin(sctx->job.claimhash, claimhash, 32);
for (i = 0; i < sctx->job.merkle_count; i++) for (i = 0; i < sctx->job.merkle_count; i++)
free(sctx->job.merkle[i]); free(sctx->job.merkle[i]);