From 084f3139395aa2ce2aee555188777fa52f2963db Mon Sep 17 00:00:00 2001 From: div72 Date: Sat, 7 Oct 2023 12:19:43 +0300 Subject: [PATCH 01/12] crypto: add MD5 implementation from BoringSSL Mostly sourced from crypto/fips/module/md5/ at `6d3db84c47643271cb553593ee67362be3820874`. --- src/Makefile.am | 4 +- src/crypto/CMakeLists.txt | 1 + src/gridcoin/md5.c | 421 ++++++++++++++++++++++++++++++++++++++ src/gridcoin/md5.h | 31 +++ src/test/crypto_tests.cpp | 21 ++ 5 files changed, 477 insertions(+), 1 deletion(-) create mode 100644 src/gridcoin/md5.c create mode 100644 src/gridcoin/md5.h diff --git a/src/Makefile.am b/src/Makefile.am index 4a6883ec0c..1f6dd98424 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -383,7 +383,9 @@ crypto_libgridcoin_crypto_base_a_SOURCES = \ crypto/sha512.cpp \ crypto/sha512.h \ crypto/siphash.cpp \ - crypto/siphash.h + crypto/siphash.h \ + gridcoin/md5.c \ + gridcoin/md5.h if USE_ASM crypto_libgridcoin_crypto_base_a_SOURCES += crypto/sha256_sse4.cpp diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index 93396debd5..f7972902be 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(gridcoin_crypto_base STATIC sha3.cpp sha512.cpp siphash.cpp + ../gridcoin/md5.c ) if(USE_ASM) diff --git a/src/gridcoin/md5.c b/src/gridcoin/md5.c new file mode 100644 index 0000000000..da50664e12 --- /dev/null +++ b/src/gridcoin/md5.c @@ -0,0 +1,421 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#define CRYPTO_load_u32_le(data) (uint32_t)data[0] | ((uint32_t)data[1] << 8) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24) +#define CRYPTO_store_u32_le(dst, src) (dst)[0] = src & 0xFF; (dst)[1] = src & 0xFF00; (dst)[2] = src & 0xFF0000; (dst)[3] = src & 0xFF000000 +#define CRYPTO_load_u32_be(data) (uint32_t)data[3] | ((uint32_t)data[2] << 8) | ((uint32_t)data[1] << 16) | ((uint32_t)data[0] << 24) +#define CRYPTO_store_u32_be(dst, src) (dst)[3] = src & 0xFF; (dst)[2] = src & 0xFF00; (dst)[1] = src & 0xFF0000; (dst)[0] = src & 0xFF000000 + +static inline uint32_t CRYPTO_rotl_u32(uint32_t value, int shift) { +#if defined(_MSC_VER) + return _rotl(value, shift); +#else + return (value << shift) | (value >> ((-shift) & 31)); +#endif +} + +// This is a generic 32-bit "collector" for message digest algorithms. It +// collects input character stream into chunks of 32-bit values and invokes the +// block function that performs the actual hash calculations. +// +// To make use of this mechanism, the hash context should be defined with the +// following parameters. +// +// typedef struct _state_st { +// uint32_t h[ / sizeof(uint32_t)]; +// uint32_t Nl, Nh; +// uint8_t data[]; +// unsigned num; +// ... +// } _CTX; +// +// is the output length of the hash in bytes, before +// any truncation (e.g. 64 for SHA-224 and SHA-256, 128 for SHA-384 and +// SHA-512). +// +// |h| is the hash state and is updated by a function of type +// |crypto_md32_block_func|. |data| is the partial unprocessed block and has +// |num| bytes. |Nl| and |Nh| maintain the number of bits processed so far. + +// A crypto_md32_block_func should incorporate |num_blocks| of input from |data| +// into |state|. It is assumed the caller has sized |state| and |data| for the +// hash function. +typedef void (*crypto_md32_block_func)(uint32_t *state, const uint8_t *data, + size_t num_blocks); + +// crypto_md32_update adds |len| bytes from |in| to the digest. |data| must be a +// buffer of length |block_size| with the first |*num| bytes containing a +// partial block. This function combines the partial block with |in| and +// incorporates any complete blocks into the digest state |h|. It then updates +// |data| and |*num| with the new partial block and updates |*Nh| and |*Nl| with +// the data consumed. +static inline void crypto_md32_update(crypto_md32_block_func block_func, + uint32_t *h, uint8_t *data, + size_t block_size, unsigned *num, + uint32_t *Nh, uint32_t *Nl, + const uint8_t *in, size_t len) { + if (len == 0) { + return; + } + + uint32_t l = *Nl + (((uint32_t)len) << 3); + if (l < *Nl) { + // Handle carries. + (*Nh)++; + } + *Nh += (uint32_t)(len >> 29); + *Nl = l; + + size_t n = *num; + if (n != 0) { + if (len >= block_size || len + n >= block_size) { + memcpy(data + n, in, block_size - n); + block_func(h, data, 1); + n = block_size - n; + in += n; + len -= n; + *num = 0; + // Keep |data| zeroed when unused. + memset(data, 0, block_size); + } else { + memcpy(data + n, in, len); + *num += (unsigned)len; + return; + } + } + + n = len / block_size; + if (n > 0) { + block_func(h, in, n); + n *= block_size; + in += n; + len -= n; + } + + if (len != 0) { + *num = (unsigned)len; + memcpy(data, in, len); + } +} + +// crypto_md32_final incorporates the partial block and trailing length into the +// digest state |h|. The trailing length is encoded in little-endian if +// |is_big_endian| is zero and big-endian otherwise. |data| must be a buffer of +// length |block_size| with the first |*num| bytes containing a partial block. +// |Nh| and |Nl| contain the total number of bits processed. On return, this +// function clears the partial block in |data| and +// |*num|. +// +// This function does not serialize |h| into a final digest. This is the +// responsibility of the caller. +static inline void crypto_md32_final(crypto_md32_block_func block_func, + uint32_t *h, uint8_t *data, + size_t block_size, unsigned *num, + uint32_t Nh, uint32_t Nl, + int is_big_endian) { + // |data| always has room for at least one byte. A full block would have + // been consumed. + size_t n = *num; + assert(n < block_size); + data[n] = 0x80; + n++; + + // Fill the block with zeros if there isn't room for a 64-bit length. + if (n > block_size - 8) { + memset(data + n, 0, block_size - n); + n = 0; + block_func(h, data, 1); + } + memset(data + n, 0, block_size - 8 - n); + + // Append a 64-bit length to the block and process it. + if (is_big_endian) { + CRYPTO_store_u32_be(data + block_size - 8, Nh); + CRYPTO_store_u32_be(data + block_size - 4, Nl); + } else { + CRYPTO_store_u32_le(data + block_size - 8, Nl); + CRYPTO_store_u32_le(data + block_size - 4, Nh); + } + block_func(h, data, 1); + *num = 0; + memset(data, 0, block_size); +} + +int MD5_Init(MD5_CTX *md5) { + memset(md5, 0, sizeof(MD5_CTX)); + md5->h[0] = 0x67452301UL; + md5->h[1] = 0xefcdab89UL; + md5->h[2] = 0x98badcfeUL; + md5->h[3] = 0x10325476UL; + return 1; +} + +static void md5_block_data_order(uint32_t *state, const uint8_t *data, + size_t num); + +void MD5_Transform(MD5_CTX *c, const uint8_t data[MD5_CBLOCK]) { + md5_block_data_order(c->h, data, 1); +} + +int MD5_Update(MD5_CTX *c, const void *data, size_t len) { + crypto_md32_update(&md5_block_data_order, c->h, c->data, MD5_CBLOCK, &c->num, + &c->Nh, &c->Nl, data, len); + return 1; +} + +int MD5_Final(uint8_t out[MD5_DIGEST_LENGTH], MD5_CTX *c) { + crypto_md32_final(&md5_block_data_order, c->h, c->data, MD5_CBLOCK, &c->num, + c->Nh, c->Nl, /*is_big_endian=*/0); + + CRYPTO_store_u32_le(out, c->h[0]); + CRYPTO_store_u32_le(out + 4, c->h[1]); + CRYPTO_store_u32_le(out + 8, c->h[2]); + CRYPTO_store_u32_le(out + 12, c->h[3]); + return 1; +} + +uint8_t *MD5(const uint8_t *data, size_t len, uint8_t out[MD5_DIGEST_LENGTH]) { + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, data, len); + MD5_Final(out, &ctx); + + return out; +} + +// As pointed out by Wei Dai , the above can be +// simplified to the code below. Wei attributes these optimizations +// to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. +#define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d)) +#define G(b, c, d) ((((b) ^ (c)) & (d)) ^ (c)) +#define H(b, c, d) ((b) ^ (c) ^ (d)) +#define I(b, c, d) (((~(d)) | (b)) ^ (c)) + +#define R0(a, b, c, d, k, s, t) \ + do { \ + (a) += ((k) + (t) + F((b), (c), (d))); \ + (a) = CRYPTO_rotl_u32(a, s); \ + (a) += (b); \ + } while (0) + +#define R1(a, b, c, d, k, s, t) \ + do { \ + (a) += ((k) + (t) + G((b), (c), (d))); \ + (a) = CRYPTO_rotl_u32(a, s); \ + (a) += (b); \ + } while (0) + +#define R2(a, b, c, d, k, s, t) \ + do { \ + (a) += ((k) + (t) + H((b), (c), (d))); \ + (a) = CRYPTO_rotl_u32(a, s); \ + (a) += (b); \ + } while (0) + +#define R3(a, b, c, d, k, s, t) \ + do { \ + (a) += ((k) + (t) + I((b), (c), (d))); \ + (a) = CRYPTO_rotl_u32(a, s); \ + (a) += (b); \ + } while (0) + +#ifndef MD5_ASM +#ifdef X +#undef X +#endif + + +static void md5_block_data_order(uint32_t *state, const uint8_t *data, + size_t num) { + uint32_t A, B, C, D; + uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12, + XX13, XX14, XX15; +#define X(i) XX##i + + A = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + + for (; num--;) { + X(0) = CRYPTO_load_u32_le(data); + data += 4; + X(1) = CRYPTO_load_u32_le(data); + data += 4; + // Round 0 + R0(A, B, C, D, X(0), 7, 0xd76aa478L); + X(2) = CRYPTO_load_u32_le(data); + data += 4; + R0(D, A, B, C, X(1), 12, 0xe8c7b756L); + X(3) = CRYPTO_load_u32_le(data); + data += 4; + R0(C, D, A, B, X(2), 17, 0x242070dbL); + X(4) = CRYPTO_load_u32_le(data); + data += 4; + R0(B, C, D, A, X(3), 22, 0xc1bdceeeL); + X(5) = CRYPTO_load_u32_le(data); + data += 4; + R0(A, B, C, D, X(4), 7, 0xf57c0fafL); + X(6) = CRYPTO_load_u32_le(data); + data += 4; + R0(D, A, B, C, X(5), 12, 0x4787c62aL); + X(7) = CRYPTO_load_u32_le(data); + data += 4; + R0(C, D, A, B, X(6), 17, 0xa8304613L); + X(8) = CRYPTO_load_u32_le(data); + data += 4; + R0(B, C, D, A, X(7), 22, 0xfd469501L); + X(9) = CRYPTO_load_u32_le(data); + data += 4; + R0(A, B, C, D, X(8), 7, 0x698098d8L); + X(10) = CRYPTO_load_u32_le(data); + data += 4; + R0(D, A, B, C, X(9), 12, 0x8b44f7afL); + X(11) = CRYPTO_load_u32_le(data); + data += 4; + R0(C, D, A, B, X(10), 17, 0xffff5bb1L); + X(12) = CRYPTO_load_u32_le(data); + data += 4; + R0(B, C, D, A, X(11), 22, 0x895cd7beL); + X(13) = CRYPTO_load_u32_le(data); + data += 4; + R0(A, B, C, D, X(12), 7, 0x6b901122L); + X(14) = CRYPTO_load_u32_le(data); + data += 4; + R0(D, A, B, C, X(13), 12, 0xfd987193L); + X(15) = CRYPTO_load_u32_le(data); + data += 4; + R0(C, D, A, B, X(14), 17, 0xa679438eL); + R0(B, C, D, A, X(15), 22, 0x49b40821L); + // Round 1 + R1(A, B, C, D, X(1), 5, 0xf61e2562L); + R1(D, A, B, C, X(6), 9, 0xc040b340L); + R1(C, D, A, B, X(11), 14, 0x265e5a51L); + R1(B, C, D, A, X(0), 20, 0xe9b6c7aaL); + R1(A, B, C, D, X(5), 5, 0xd62f105dL); + R1(D, A, B, C, X(10), 9, 0x02441453L); + R1(C, D, A, B, X(15), 14, 0xd8a1e681L); + R1(B, C, D, A, X(4), 20, 0xe7d3fbc8L); + R1(A, B, C, D, X(9), 5, 0x21e1cde6L); + R1(D, A, B, C, X(14), 9, 0xc33707d6L); + R1(C, D, A, B, X(3), 14, 0xf4d50d87L); + R1(B, C, D, A, X(8), 20, 0x455a14edL); + R1(A, B, C, D, X(13), 5, 0xa9e3e905L); + R1(D, A, B, C, X(2), 9, 0xfcefa3f8L); + R1(C, D, A, B, X(7), 14, 0x676f02d9L); + R1(B, C, D, A, X(12), 20, 0x8d2a4c8aL); + // Round 2 + R2(A, B, C, D, X(5), 4, 0xfffa3942L); + R2(D, A, B, C, X(8), 11, 0x8771f681L); + R2(C, D, A, B, X(11), 16, 0x6d9d6122L); + R2(B, C, D, A, X(14), 23, 0xfde5380cL); + R2(A, B, C, D, X(1), 4, 0xa4beea44L); + R2(D, A, B, C, X(4), 11, 0x4bdecfa9L); + R2(C, D, A, B, X(7), 16, 0xf6bb4b60L); + R2(B, C, D, A, X(10), 23, 0xbebfbc70L); + R2(A, B, C, D, X(13), 4, 0x289b7ec6L); + R2(D, A, B, C, X(0), 11, 0xeaa127faL); + R2(C, D, A, B, X(3), 16, 0xd4ef3085L); + R2(B, C, D, A, X(6), 23, 0x04881d05L); + R2(A, B, C, D, X(9), 4, 0xd9d4d039L); + R2(D, A, B, C, X(12), 11, 0xe6db99e5L); + R2(C, D, A, B, X(15), 16, 0x1fa27cf8L); + R2(B, C, D, A, X(2), 23, 0xc4ac5665L); + // Round 3 + R3(A, B, C, D, X(0), 6, 0xf4292244L); + R3(D, A, B, C, X(7), 10, 0x432aff97L); + R3(C, D, A, B, X(14), 15, 0xab9423a7L); + R3(B, C, D, A, X(5), 21, 0xfc93a039L); + R3(A, B, C, D, X(12), 6, 0x655b59c3L); + R3(D, A, B, C, X(3), 10, 0x8f0ccc92L); + R3(C, D, A, B, X(10), 15, 0xffeff47dL); + R3(B, C, D, A, X(1), 21, 0x85845dd1L); + R3(A, B, C, D, X(8), 6, 0x6fa87e4fL); + R3(D, A, B, C, X(15), 10, 0xfe2ce6e0L); + R3(C, D, A, B, X(6), 15, 0xa3014314L); + R3(B, C, D, A, X(13), 21, 0x4e0811a1L); + R3(A, B, C, D, X(4), 6, 0xf7537e82L); + R3(D, A, B, C, X(11), 10, 0xbd3af235L); + R3(C, D, A, B, X(2), 15, 0x2ad7d2bbL); + R3(B, C, D, A, X(9), 21, 0xeb86d391L); + + A = state[0] += A; + B = state[1] += B; + C = state[2] += C; + D = state[3] += D; + } +} +#undef X +#endif + +#undef F +#undef G +#undef H +#undef I +#undef R0 +#undef R1 +#undef R2 +#undef R3 +#undef CRYPTO_load_u32_le +#undef CRYPTO_store_u32_le +#undef CRYPTO_load_u32_be +#undef CRYPTO_store_u32_be diff --git a/src/gridcoin/md5.h b/src/gridcoin/md5.h new file mode 100644 index 0000000000..3c8f3e0ef5 --- /dev/null +++ b/src/gridcoin/md5.h @@ -0,0 +1,31 @@ +// Copyright (c) 2023 The Gridcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#ifndef GRIDCOIN_MD5_H +#define GRIDCOIN_MD5_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#define MD5_CBLOCK 64 +#define MD5_DIGEST_LENGTH 16 + +typedef struct MD5_CTX { + uint32_t h[4]; + uint32_t Nl, Nh; + uint8_t data[MD5_CBLOCK]; + unsigned num; +} MD5_CTX; + +uint8_t *MD5(const uint8_t *data, size_t len, uint8_t out[MD5_DIGEST_LENGTH]); + +#if defined(__cplusplus) +} +#endif + +#endif // GRIDCOIN_MD5_H diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 6addce5f0b..1bd36c4666 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,14 @@ static void TestVector(const Hasher &h, const In &in, const Out &out) { } } +static void TestMD5(const std::string &in, const std::string &hexout) { + assert(hexout.size() == 2 * MD5_DIGEST_LENGTH); + + uint8_t out[MD5_DIGEST_LENGTH]; + MD5((const uint8_t*)in.data(), in.size(), out); + + BOOST_CHECK(std::memcmp(out, ParseHex(hexout).data(), MD5_DIGEST_LENGTH) == 0); +} static void TestSHA1(const std::string &in, const std::string &hexout) { TestVector(CSHA1(), in, ParseHex(hexout));} static void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(CSHA256(), in, ParseHex(hexout));} static void TestSHA512(const std::string &in, const std::string &hexout) { TestVector(CSHA512(), in, ParseHex(hexout));} @@ -187,6 +196,18 @@ static std::string LongTestString() const std::string test1 = LongTestString(); +BOOST_AUTO_TEST_CASE(md5_testvectors) { + TestMD5("", "d41d8cd98f00b204e9800998ecf8427e"); + TestMD5("a", "0cc175b9c0f1b6a831c399e269772661"); + TestMD5("abc", "900150983cd24fb0d6963f7d28e17f72"); + TestMD5("message digest", "f96b697d7cb7938d525a2f31aaf161d0"); + TestMD5("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"); + TestMD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f"); + TestMD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"); + TestMD5(std::string(1000000, 'a'), "7707d6ae4e027c70eea2a935c2296f21"); + TestMD5(test1, "12ebd71b1cadcfde2bb6905987b8a52e"); +} + BOOST_AUTO_TEST_CASE(ripemd160_testvectors) { TestRIPEMD160("", "9c1185a5c5e9fc54612808977ee8f548b2258d31"); TestRIPEMD160("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"); From f2d993ec9d83b0b516b9cd36a59a4c00c5a74495 Mon Sep 17 00:00:00 2001 From: div72 Date: Sat, 7 Oct 2023 13:36:10 +0300 Subject: [PATCH 02/12] crypto: use vendored MD5 implementation --- src/gridcoin/cpid.cpp | 2 +- src/gridcoin/quorum.cpp | 2 +- src/gridcoin/researcher.cpp | 2 +- src/gridcoin/superblock.cpp | 2 +- src/test/gridcoin/superblock_tests.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gridcoin/cpid.cpp b/src/gridcoin/cpid.cpp index ff8a689c2d..f5d24096f1 100644 --- a/src/gridcoin/cpid.cpp +++ b/src/gridcoin/cpid.cpp @@ -3,10 +3,10 @@ // file COPYING or https://opensource.org/licenses/mit-license.php. #include "gridcoin/cpid.h" +#include #include "util.h" #include -#include using namespace GRC; diff --git a/src/gridcoin/quorum.cpp b/src/gridcoin/quorum.cpp index 49626dd582..792b29744f 100644 --- a/src/gridcoin/quorum.cpp +++ b/src/gridcoin/quorum.cpp @@ -7,6 +7,7 @@ #include "main.h" #include "gridcoin/claim.h" #include "gridcoin/magnitude.h" +#include #include "gridcoin/quorum.h" #include "gridcoin/scraper/scraper_net.h" #include "gridcoin/superblock.h" @@ -14,7 +15,6 @@ #include "util/reverse_iterator.h" #include -#include #include using namespace GRC; diff --git a/src/gridcoin/researcher.cpp b/src/gridcoin/researcher.cpp index 7e1e4e3e21..22f69bd5d3 100644 --- a/src/gridcoin/researcher.cpp +++ b/src/gridcoin/researcher.cpp @@ -8,6 +8,7 @@ #include "gridcoin/boinc.h" #include "gridcoin/contract/message.h" #include "gridcoin/magnitude.h" +#include #include "gridcoin/project.h" #include "gridcoin/protocol.h" #include "gridcoin/quorum.h" @@ -23,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/src/gridcoin/superblock.cpp b/src/gridcoin/superblock.cpp index 5e557a08c0..b070721c56 100644 --- a/src/gridcoin/superblock.cpp +++ b/src/gridcoin/superblock.cpp @@ -6,6 +6,7 @@ #include "compat/endian.h" #include "hash.h" #include "main.h" +#include #include "gridcoin/superblock.h" #include "gridcoin/support/xml.h" #include "node/blockstorage.h" @@ -13,7 +14,6 @@ #include "util.h" #include "util/reverse_iterator.h" -#include using namespace GRC; diff --git a/src/test/gridcoin/superblock_tests.cpp b/src/test/gridcoin/superblock_tests.cpp index 7f32329c35..f2e880c3f2 100644 --- a/src/test/gridcoin/superblock_tests.cpp +++ b/src/test/gridcoin/superblock_tests.cpp @@ -4,6 +4,7 @@ #include "base58.h" #include "compat/endian.h" +#include #include "gridcoin/scraper/scraper_net.h" #include "gridcoin/superblock.h" #include "gridcoin/support/xml.h" @@ -13,7 +14,6 @@ #include #include #include -#include #include #include "test/data/superblock.txt.h" From 0cf35b786a136d60c70df6181079895f89bbebed Mon Sep 17 00:00:00 2001 From: div72 Date: Sat, 7 Oct 2023 13:58:45 +0300 Subject: [PATCH 03/12] upgrade: use vendored SHA256 implementation --- src/gridcoin/upgrade.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/gridcoin/upgrade.cpp b/src/gridcoin/upgrade.cpp index 5402f03cdf..aa45fe12bd 100644 --- a/src/gridcoin/upgrade.cpp +++ b/src/gridcoin/upgrade.cpp @@ -3,6 +3,7 @@ // file COPYING or https://opensource.org/licenses/mit-license.php. #include "gridcoin/upgrade.h" +#include #include "util.h" #include "init.h" @@ -16,7 +17,6 @@ #include #include -#include using namespace GRC; @@ -428,13 +428,10 @@ void Upgrade::VerifySHA256SUM() return; } - unsigned char digest[SHA256_DIGEST_LENGTH]; - - SHA256_CTX ctx; - SHA256_Init(&ctx); + CSHA256 hasher; fs::path fileloc = GetDataDir() / "snapshot.zip"; - unsigned char *buffer[32768]; + uint8_t buffer[32768]; int bytesread = 0; CAutoFile file(fsbridge::fopen(fileloc, "rb"), SER_DISK, CLIENT_VERSION); @@ -453,15 +450,16 @@ void Upgrade::VerifySHA256SUM() unsigned int read_count = 0; while ((bytesread = fread(buffer, 1, sizeof(buffer), file.Get()))) { - SHA256_Update(&ctx, buffer, bytesread); + hasher.Write(buffer, bytesread); ++read_count; DownloadStatus.SetSHA256SUMProgress(read_count * 100 / total_reads); } - SHA256_Final(digest, &ctx); + uint8_t digest[CSHA256::OUTPUT_SIZE]; + hasher.Finalize(digest); - const std::vector digest_vector(digest, digest + SHA256_DIGEST_LENGTH); + const std::vector digest_vector(digest, digest + CSHA256::OUTPUT_SIZE); std::string FileSHA256SUM = HexStr(digest_vector); From 979ca56b4cd1c02df7d65025e000a482970aa1d4 Mon Sep 17 00:00:00 2001 From: div72 Date: Sun, 8 Oct 2023 20:03:06 +0300 Subject: [PATCH 04/12] crypto: use vendored HMAC-SHA256 implementation for PBKDF2 --- src/pbkdf2.cpp | 86 ++++++-------------------------------------------- src/pbkdf2.h | 17 ++-------- 2 files changed, 11 insertions(+), 92 deletions(-) diff --git a/src/pbkdf2.cpp b/src/pbkdf2.cpp index 8c5b2d9c22..c59a894089 100644 --- a/src/pbkdf2.cpp +++ b/src/pbkdf2.cpp @@ -28,71 +28,6 @@ be32enc(void *pp, uint32_t x) } - -/* Initialize an HMAC-SHA256 operation with the given key. */ -void -HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) -{ - unsigned char pad[64]; - unsigned char khash[32]; - const unsigned char * K = (const unsigned char *)_K; - size_t i; - - /* If Klen > 64, the key is really SHA256(K). */ - if (Klen > 64) { - SHA256_Init(&ctx->ictx); - SHA256_Update(&ctx->ictx, K, Klen); - SHA256_Final(khash, &ctx->ictx); - K = khash; - Klen = 32; - } - - /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ - SHA256_Init(&ctx->ictx); - memset(pad, 0x36, 64); - for (i = 0; i < Klen; i++) - pad[i] ^= K[i]; - SHA256_Update(&ctx->ictx, pad, 64); - - /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ - SHA256_Init(&ctx->octx); - memset(pad, 0x5c, 64); - for (i = 0; i < Klen; i++) - pad[i] ^= K[i]; - SHA256_Update(&ctx->octx, pad, 64); - - /* Clean the stack. */ - memset(khash, 0, 32); -} - -/* Add bytes to the HMAC-SHA256 operation. */ -void -HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len) -{ - - /* Feed data to the inner SHA256 operation. */ - SHA256_Update(&ctx->ictx, in, len); -} - -/* Finish an HMAC-SHA256 operation. */ -void -HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx) -{ - unsigned char ihash[32]; - - /* Finish the inner SHA256 operation. */ - SHA256_Final(ihash, &ctx->ictx); - - /* Feed the inner hash to the outer SHA256 operation. */ - SHA256_Update(&ctx->octx, ihash, 32); - - /* Finish the outer SHA256 operation. */ - SHA256_Final(digest, &ctx->octx); - - /* Clean the stack. */ - memset(ihash, 0, 32); -} - /** * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and @@ -102,7 +37,8 @@ void PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) { - HMAC_SHA256_CTX PShctx, hctx; + CHMAC_SHA256 bare(passwd, passwdlen); + CHMAC_SHA256 salted(passwd, passwdlen); size_t i; uint8_t ivec[4]; uint8_t U[32]; @@ -112,8 +48,7 @@ PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, size_t clen; /* Compute HMAC state after processing P and S. */ - HMAC_SHA256_Init(&PShctx, passwd, passwdlen); - HMAC_SHA256_Update(&PShctx, salt, saltlen); + salted.Write(salt, saltlen); /* Iterate through the blocks. */ for (i = 0; i * 32 < dkLen; i++) { @@ -121,18 +56,18 @@ PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, be32enc(ivec, (uint32_t)(i + 1)); /* Compute U_1 = PRF(P, S || INT(i)). */ - memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); - HMAC_SHA256_Update(&hctx, ivec, 4); - HMAC_SHA256_Final(U, &hctx); + CHMAC_SHA256 U_1 = salted; + U_1.Write(ivec, 4); + U_1.Finalize(U); /* T_i = U_1 ... */ memcpy(T, U, 32); for (j = 2; j <= c; j++) { /* Compute U_j. */ - HMAC_SHA256_Init(&hctx, passwd, passwdlen); - HMAC_SHA256_Update(&hctx, U, 32); - HMAC_SHA256_Final(U, &hctx); + CHMAC_SHA256 U_j = bare; + U_j.Write(U, 32); + U_j.Finalize(U); /* ... xor U_j ... */ for (k = 0; k < 32; k++) @@ -145,8 +80,5 @@ PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, clen = 32; memcpy(&buf[i * 32], T, clen); } - - /* Clean PShctx, since we never called _Final on it. */ - memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); } diff --git a/src/pbkdf2.h b/src/pbkdf2.h index c585a129c1..905622dab5 100644 --- a/src/pbkdf2.h +++ b/src/pbkdf2.h @@ -3,22 +3,9 @@ #ifndef BITCOIN_PBKDF2_H #define BITCOIN_PBKDF2_H -#include -#include - -typedef struct HMAC_SHA256Context { - SHA256_CTX ictx; - SHA256_CTX octx; -} HMAC_SHA256_CTX; - -void -HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen); +#include -void -HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len); - -void -HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx); +#include void PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, From f8b4afb800d8e629d98f90edd0f45942c9c7cbd7 Mon Sep 17 00:00:00 2001 From: div72 Date: Mon, 9 Oct 2023 00:04:30 +0300 Subject: [PATCH 05/12] script: remove code for disallowed ops --- src/script.cpp | 144 ------------------------------------------------- 1 file changed, 144 deletions(-) diff --git a/src/script.cpp b/src/script.cpp index bd451e3a1f..41cb6ba498 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -673,65 +673,6 @@ bool EvalScript(vector >& stack, const CScript& script, co } break; - - // - // Splice ops - // - case OP_CAT: - { - // (x1 x2 -- out) - if (stack.size() < 2) - return false; - valtype& vch1 = stacktop(-2); - valtype& vch2 = stacktop(-1); - vch1.insert(vch1.end(), vch2.begin(), vch2.end()); - popstack(stack); - if (stacktop(-1).size() > MAX_SCRIPT_ELEMENT_SIZE) - return false; - } - break; - - case OP_SUBSTR: - { - // (in begin size -- out) - if (stack.size() < 3) - return false; - valtype& vch = stacktop(-3); - int nBegin = CastToBigNum(stacktop(-2)).getint(); - int nEnd = nBegin + CastToBigNum(stacktop(-1)).getint(); - if (nBegin < 0 || nEnd < nBegin) - return false; - if (nBegin > (int)vch.size()) - nBegin = vch.size(); - if (nEnd > (int)vch.size()) - nEnd = vch.size(); - vch.erase(vch.begin() + nEnd, vch.end()); - vch.erase(vch.begin(), vch.begin() + nBegin); - popstack(stack); - popstack(stack); - } - break; - - case OP_LEFT: - case OP_RIGHT: - { - // (in size -- out) - if (stack.size() < 2) - return false; - valtype& vch = stacktop(-2); - int nSize = CastToBigNum(stacktop(-1)).getint(); - if (nSize < 0) - return false; - if (nSize > (int)vch.size()) - nSize = vch.size(); - if (opcode == OP_LEFT) - vch.erase(vch.begin() + nSize, vch.end()); - else - vch.erase(vch.begin(), vch.end() - nSize); - popstack(stack); - } - break; - case OP_SIZE: { // (in -- in size) @@ -742,55 +683,6 @@ bool EvalScript(vector >& stack, const CScript& script, co } break; - - // - // Bitwise logic - // - case OP_INVERT: - { - // (in - out) - if (stack.size() < 1) - return false; - valtype& vch = stacktop(-1); - for (unsigned int i = 0; i < vch.size(); i++) - vch[i] = ~vch[i]; - } - break; - - // - // WARNING: These disabled opcodes exhibit unexpected behavior - // when used on signed integers due to a bug in MakeSameSize() - // [see definition of MakeSameSize() above]. - // - case OP_AND: - case OP_OR: - case OP_XOR: - { - // (x1 x2 - out) - if (stack.size() < 2) - return false; - valtype& vch1 = stacktop(-2); - valtype& vch2 = stacktop(-1); - MakeSameSize(vch1, vch2); // <-- NOT SAFE FOR SIGNED VALUES - if (opcode == OP_AND) - { - for (unsigned int i = 0; i < vch1.size(); i++) - vch1[i] &= vch2[i]; - } - else if (opcode == OP_OR) - { - for (unsigned int i = 0; i < vch1.size(); i++) - vch1[i] |= vch2[i]; - } - else if (opcode == OP_XOR) - { - for (unsigned int i = 0; i < vch1.size(); i++) - vch1[i] ^= vch2[i]; - } - popstack(stack); - } - break; - case OP_EQUAL: case OP_EQUALVERIFY: //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL @@ -825,8 +717,6 @@ bool EvalScript(vector >& stack, const CScript& script, co // case OP_1ADD: case OP_1SUB: - case OP_2MUL: - case OP_2DIV: case OP_NEGATE: case OP_ABS: case OP_NOT: @@ -840,8 +730,6 @@ bool EvalScript(vector >& stack, const CScript& script, co { case OP_1ADD: bn += bnOne; break; case OP_1SUB: bn -= bnOne; break; - case OP_2MUL: bn <<= 1; break; - case OP_2DIV: bn >>= 1; break; case OP_NEGATE: bn = -bn; break; case OP_ABS: if (bn < bnZero) bn = -bn; break; case OP_NOT: bn = (bn == bnZero); break; @@ -855,11 +743,6 @@ bool EvalScript(vector >& stack, const CScript& script, co case OP_ADD: case OP_SUB: - case OP_MUL: - case OP_DIV: - case OP_MOD: - case OP_LSHIFT: - case OP_RSHIFT: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: @@ -888,33 +771,6 @@ bool EvalScript(vector >& stack, const CScript& script, co bn = bn1 - bn2; break; - case OP_MUL: - if (!BN_mul(&bn, &bn1, &bn2, pctx)) - return false; - break; - - case OP_DIV: - if (!BN_div(&bn, nullptr, &bn1, &bn2, pctx)) - return false; - break; - - case OP_MOD: - if (!BN_mod(&bn, &bn1, &bn2, pctx)) - return false; - break; - - case OP_LSHIFT: - if (bn2 < bnZero || bn2 > CBigNum(2048)) - return false; - bn = bn1 << bn2.getulong(); - break; - - case OP_RSHIFT: - if (bn2 < bnZero || bn2 > CBigNum(2048)) - return false; - bn = bn1 >> bn2.getulong(); - break; - case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break; case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break; case OP_NUMEQUAL: bn = (bn1 == bn2); break; From 4bf96868464ca95f01b27692176db2164d499b05 Mon Sep 17 00:00:00 2001 From: div72 Date: Mon, 9 Oct 2023 00:08:11 +0300 Subject: [PATCH 06/12] script: use CScriptNum instead of CBigNum --- src/script.cpp | 46 +++++------- src/script.h | 193 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 204 insertions(+), 35 deletions(-) diff --git a/src/script.cpp b/src/script.cpp index 41cb6ba498..45d5e9000f 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -6,7 +6,6 @@ #include "script.h" #include #include "keystore.h" -#include "bignum.h" #include "key.h" #include "main.h" #include "random.h" @@ -26,20 +25,10 @@ bool CheckSig(vector vchSig, vector vchPubKey, CSc static const valtype vchFalse(0); static const valtype vchZero(0); static const valtype vchTrue(1, 1); -static const CBigNum bnZero(0); -static const CBigNum bnOne(1); -static const CBigNum bnFalse(0); -static const CBigNum bnTrue(1); -static const size_t nMaxNumSize = 4; - - -CBigNum CastToBigNum(const valtype& vch) -{ - if (vch.size() > nMaxNumSize) - throw runtime_error("CastToBigNum() : overflow"); - // Get rid of extra leading zeros - return CBigNum(CBigNum(vch).getvch()); -} +static const CScriptNum bnZero(0); +static const CScriptNum bnOne(1); +static const CScriptNum bnFalse(0); +static const CScriptNum bnTrue(1); bool CastToBool(const valtype& vch) { @@ -332,7 +321,6 @@ static bool IsCanonicalSignature(const valtype &vchSig) { bool EvalScript(vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType) { - CAutoBN_CTX pctx; CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); CScript::const_iterator pbegincodehash = script.begin(); @@ -405,7 +393,7 @@ bool EvalScript(vector >& stack, const CScript& script, co case OP_16: { // ( -- value) - CBigNum bn((int)opcode - (int)(OP_1 - 1)); + CScriptNum bn((int)opcode - (int)(OP_1 - 1)); stack.push_back(bn.getvch()); } break; @@ -581,7 +569,7 @@ bool EvalScript(vector >& stack, const CScript& script, co case OP_DEPTH: { // -- stacksize - CBigNum bn(stack.size()); + CScriptNum bn(stack.size()); stack.push_back(bn.getvch()); } break; @@ -631,7 +619,7 @@ bool EvalScript(vector >& stack, const CScript& script, co // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack.size() < 2) return false; - int n = CastToBigNum(stacktop(-1)).getint(); + int n = CScriptNum(stacktop(-1), false).getint(); popstack(stack); if (n < 0 || n >= (int)stack.size()) return false; @@ -678,7 +666,7 @@ bool EvalScript(vector >& stack, const CScript& script, co // (in -- in size) if (stack.size() < 1) return false; - CBigNum bn(stacktop(-1).size()); + CScriptNum bn(stacktop(-1).size()); stack.push_back(bn.getvch()); } break; @@ -725,7 +713,7 @@ bool EvalScript(vector >& stack, const CScript& script, co // (in -- out) if (stack.size() < 1) return false; - CBigNum bn = CastToBigNum(stacktop(-1)); + CScriptNum bn(stacktop(-1), false); switch (opcode) { case OP_1ADD: bn += bnOne; break; @@ -758,9 +746,9 @@ bool EvalScript(vector >& stack, const CScript& script, co // (x1 x2 -- out) if (stack.size() < 2) return false; - CBigNum bn1 = CastToBigNum(stacktop(-2)); - CBigNum bn2 = CastToBigNum(stacktop(-1)); - CBigNum bn; + CScriptNum bn1(stacktop(-2), false); + CScriptNum bn2(stacktop(-1), false); + CScriptNum bn(0); switch (opcode) { case OP_ADD: @@ -803,9 +791,9 @@ bool EvalScript(vector >& stack, const CScript& script, co // (x min max -- out) if (stack.size() < 3) return false; - CBigNum bn1 = CastToBigNum(stacktop(-3)); - CBigNum bn2 = CastToBigNum(stacktop(-2)); - CBigNum bn3 = CastToBigNum(stacktop(-1)); + CScriptNum bn1(stacktop(-3), false); + CScriptNum bn2(stacktop(-2), false); + CScriptNum bn3(stacktop(-1), false); bool fValue = (bn2 <= bn1 && bn1 < bn3); popstack(stack); popstack(stack); @@ -898,7 +886,7 @@ bool EvalScript(vector >& stack, const CScript& script, co if ((int)stack.size() < i) return false; - int nKeysCount = CastToBigNum(stacktop(-i)).getint(); + int nKeysCount = CScriptNum(stacktop(-i), false).getint(); if (nKeysCount < 0 || nKeysCount > 20) return false; nOpCount += nKeysCount; @@ -909,7 +897,7 @@ bool EvalScript(vector >& stack, const CScript& script, co if ((int)stack.size() < i) return false; - int nSigsCount = CastToBigNum(stacktop(-i)).getint(); + int nSigsCount = CScriptNum(stacktop(-i), false).getint(); if (nSigsCount < 0 || nSigsCount > nKeysCount) return false; int isig = ++i; diff --git a/src/script.h b/src/script.h index 51e55abd7e..5cf9feafe3 100644 --- a/src/script.h +++ b/src/script.h @@ -15,7 +15,6 @@ #include "keystore.h" -#include "bignum.h" #include "prevector.h" #include #include "wallet/ismine.h" @@ -246,11 +245,193 @@ enum opcodetype const char* GetOpName(opcodetype opcode); +class scriptnum_error : public std::runtime_error +{ +public: + explicit scriptnum_error(const std::string& str) : std::runtime_error(str) {} +}; + +class CScriptNum +{ +/** + * Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers. + * The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1], + * but results may overflow (and are valid as long as they are not used in a subsequent + * numeric operation). CScriptNum enforces those semantics by storing results as + * an int64 and allowing out-of-range values to be returned as a vector of bytes but + * throwing an exception if arithmetic is done or the result is interpreted as an integer. + */ +public: + + explicit CScriptNum(const int64_t& n) + { + m_value = n; + } + + static const size_t nDefaultMaxNumSize = 4; + + explicit CScriptNum(const std::vector& vch, bool fRequireMinimal, + const size_t nMaxNumSize = nDefaultMaxNumSize) + { + if (vch.size() > nMaxNumSize) { + throw scriptnum_error("script number overflow"); + } + if (fRequireMinimal && vch.size() > 0) { + // Check that the number is encoded with the minimum possible + // number of bytes. + // + // If the most-significant-byte - excluding the sign bit - is zero + // then we're not minimal. Note how this test also rejects the + // negative-zero encoding, 0x80. + if ((vch.back() & 0x7f) == 0) { + // One exception: if there's more than one byte and the most + // significant bit of the second-most-significant-byte is set + // it would conflict with the sign bit. An example of this case + // is +-255, which encode to 0xff00 and 0xff80 respectively. + // (big-endian). + if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) { + throw scriptnum_error("non-minimally encoded script number"); + } + } + } + m_value = set_vch(vch); + } + + inline bool operator==(const int64_t& rhs) const { return m_value == rhs; } + inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; } + inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; } + inline bool operator< (const int64_t& rhs) const { return m_value < rhs; } + inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; } + inline bool operator> (const int64_t& rhs) const { return m_value > rhs; } + + inline bool operator==(const CScriptNum& rhs) const { return operator==(rhs.m_value); } + inline bool operator!=(const CScriptNum& rhs) const { return operator!=(rhs.m_value); } + inline bool operator<=(const CScriptNum& rhs) const { return operator<=(rhs.m_value); } + inline bool operator< (const CScriptNum& rhs) const { return operator< (rhs.m_value); } + inline bool operator>=(const CScriptNum& rhs) const { return operator>=(rhs.m_value); } + inline bool operator> (const CScriptNum& rhs) const { return operator> (rhs.m_value); } + + inline CScriptNum operator+( const int64_t& rhs) const { return CScriptNum(m_value + rhs);} + inline CScriptNum operator-( const int64_t& rhs) const { return CScriptNum(m_value - rhs);} + inline CScriptNum operator+( const CScriptNum& rhs) const { return operator+(rhs.m_value); } + inline CScriptNum operator-( const CScriptNum& rhs) const { return operator-(rhs.m_value); } + + inline CScriptNum& operator+=( const CScriptNum& rhs) { return operator+=(rhs.m_value); } + inline CScriptNum& operator-=( const CScriptNum& rhs) { return operator-=(rhs.m_value); } + + inline CScriptNum operator&( const int64_t& rhs) const { return CScriptNum(m_value & rhs);} + inline CScriptNum operator&( const CScriptNum& rhs) const { return operator&(rhs.m_value); } + + inline CScriptNum& operator&=( const CScriptNum& rhs) { return operator&=(rhs.m_value); } + + inline CScriptNum operator-() const + { + assert(m_value != std::numeric_limits::min()); + return CScriptNum(-m_value); + } + + inline CScriptNum& operator=( const int64_t& rhs) + { + m_value = rhs; + return *this; + } + + inline CScriptNum& operator+=( const int64_t& rhs) + { + assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits::max() - rhs) || + (rhs < 0 && m_value >= std::numeric_limits::min() - rhs)); + m_value += rhs; + return *this; + } + + inline CScriptNum& operator-=( const int64_t& rhs) + { + assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits::min() + rhs) || + (rhs < 0 && m_value <= std::numeric_limits::max() + rhs)); + m_value -= rhs; + return *this; + } + + inline CScriptNum& operator&=( const int64_t& rhs) + { + m_value &= rhs; + return *this; + } + + int getint() const + { + if (m_value > std::numeric_limits::max()) + return std::numeric_limits::max(); + else if (m_value < std::numeric_limits::min()) + return std::numeric_limits::min(); + return m_value; + } + + int64_t GetInt64() const { return m_value; } + + std::vector getvch() const + { + return serialize(m_value); + } + + static std::vector serialize(const int64_t& value) + { + if(value == 0) + return std::vector(); + + std::vector result; + const bool neg = value < 0; + uint64_t absvalue = neg ? ~static_cast(value) + 1 : static_cast(value); + + while(absvalue) + { + result.push_back(absvalue & 0xff); + absvalue >>= 8; + } + +// - If the most significant byte is >= 0x80 and the value is positive, push a +// new zero-byte to make the significant byte < 0x80 again. + +// - If the most significant byte is >= 0x80 and the value is negative, push a +// new 0x80 byte that will be popped off when converting to an integral. + +// - If the most significant byte is < 0x80 and the value is negative, add +// 0x80 to it, since it will be subtracted and interpreted as a negative when +// converting to an integral. + + if (result.back() & 0x80) + result.push_back(neg ? 0x80 : 0); + else if (neg) + result.back() |= 0x80; + + return result; + } + +private: + static int64_t set_vch(const std::vector& vch) + { + if (vch.empty()) + return 0; + + int64_t result = 0; + for (size_t i = 0; i != vch.size(); ++i) + result |= static_cast(vch[i]) << 8*i; + + // If the input vector's most significant byte is 0x80, remove it from + // the result's msb and return a negative. + if (vch.back() & 0x80) + return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1))))); + + return result; + } + + int64_t m_value; +}; inline std::string ValueString(const std::vector& vch) { if (vch.size() <= 4) - return strprintf("%d", CBigNum(vch).getint()); + return strprintf("%d", CScriptNum(vch, false).getint()); else return HexStr(vch); } @@ -269,7 +450,7 @@ class CScript : public CScriptBase } else { - CBigNum bn(n); + CScriptNum bn(n); *this << bn.getvch(); } return *this; @@ -283,7 +464,7 @@ class CScript : public CScriptBase } else { - CBigNum bn(n); + CScriptNum bn(n); *this << bn.getvch(); } return *this; @@ -334,7 +515,7 @@ class CScript : public CScriptBase explicit CScript(opcodetype b) { operator<<(b); } explicit CScript(const uint256& b) { operator<<(b); } - explicit CScript(const CBigNum& b) { operator<<(b); } + explicit CScript(const CScriptNum& b) { operator<<(b); } explicit CScript(const std::vector& b) { operator<<(b); } @@ -378,7 +559,7 @@ class CScript : public CScriptBase return (*this) << vchKey; } - CScript& operator<<(const CBigNum& b) + CScript& operator<<(const CScriptNum& b) { *this << b.getvch(); return *this; From f7c13bed581200d3908615fa0b5cbb7a4da526fd Mon Sep 17 00:00:00 2001 From: div72 Date: Mon, 9 Oct 2023 00:10:25 +0300 Subject: [PATCH 07/12] refactor: remove usages of CBigNum --- src/Makefile.am | 1 - src/Makefile.test.include | 1 - src/bignum.h | 731 ---------------------------- src/gridcoin/staking/difficulty.cpp | 5 +- src/gridcoin/staking/kernel.cpp | 8 +- src/main.cpp | 2 +- src/miner.cpp | 6 +- src/test/CMakeLists.txt | 1 - src/test/bignum_tests.cpp | 124 ----- src/validation.cpp | 8 +- 10 files changed, 14 insertions(+), 873 deletions(-) delete mode 100644 src/bignum.h delete mode 100755 src/test/bignum_tests.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 1f6dd98424..441d48e36b 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,7 +81,6 @@ GRIDCOIN_CORE_H = \ attributes.h \ banman.h \ base58.h \ - bignum.h \ chainparams.h \ chainparamsbase.h \ checkpoints.h \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 6b3e20afce..6c4da11b4e 100755 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -38,7 +38,6 @@ GRIDCOIN_TESTS =\ test/base32_tests.cpp \ test/base58_tests.cpp \ test/base64_tests.cpp \ - test/bignum_tests.cpp \ test/bip32_tests.cpp \ test/compilerbug_tests.cpp \ test/crypto_tests.cpp \ diff --git a/src/bignum.h b/src/bignum.h deleted file mode 100644 index d5a62d1782..0000000000 --- a/src/bignum.h +++ /dev/null @@ -1,731 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or https://opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_BIGNUM_H -#define BITCOIN_BIGNUM_H - -#include -#include "serialize.h" -#include "uint256.h" -#include "version.h" - -#include - -#include -#include - -#include - -/** Errors thrown by the bignum class */ -class bignum_error : public std::runtime_error -{ -public: - explicit bignum_error(const std::string& str) : std::runtime_error(str) {} -}; - - -/** RAII encapsulated BN_CTX (OpenSSL bignum context) */ -class CAutoBN_CTX -{ -protected: - BN_CTX* pctx; - BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; } - -public: - CAutoBN_CTX() - { - pctx = BN_CTX_new(); - if (pctx == nullptr) - throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned nullptr"); - } - - ~CAutoBN_CTX() - { - if (pctx != nullptr) - BN_CTX_free(pctx); - } - - operator BN_CTX*() { return pctx; } - BN_CTX& operator*() { return *pctx; } - BN_CTX** operator&() { return &pctx; } - bool operator!() { return (pctx == nullptr); } -}; - -/* RAII wrapper for BIGNUM instance */ -class CBigNumBase -{ -protected: - BIGNUM* pbn; - -public: - CBigNumBase() - : pbn(BN_new()) - { - if (pbn == nullptr) - throw bignum_error("CBigNum : BN_new() returned nullptr"); - } - - ~CBigNumBase() - { - BN_clear_free(pbn); - } -}; - -/** C++ wrapper for BIGNUM (OpenSSL bignum) */ -class CBigNum : public CBigNumBase -{ -public: - CBigNum() - {} - - CBigNum(const CBigNum& b) - { - if (!BN_copy(pbn, &b)) - throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed"); - } - - CBigNum& operator=(const CBigNum& b) - { - if (!BN_copy(pbn, &b)) - throw bignum_error("CBigNum::operator= : BN_copy failed"); - return (*this); - } - - //CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'. - CBigNum(signed char n) { if (n >= 0) setulong(n); else setint64(n); } - CBigNum(short n) { if (n >= 0) setulong(n); else setint64(n); } - CBigNum(int n) { if (n >= 0) setulong(n); else setint64(n); } - CBigNum(long n) { if (n >= 0) setulong(n); else setint64(n); } - CBigNum(long long n) { setint64(n); } - CBigNum(unsigned char n) { setulong(n); } - CBigNum(unsigned short n) { setulong(n); } - CBigNum(unsigned int n) { setulong(n); } - CBigNum(unsigned long n) { setulong(n); } - CBigNum(unsigned long long n) { setuint64(n); } - explicit CBigNum(uint256 n) { setuint256(n); } - - explicit CBigNum(const std::vector& vch) - { - setvch(vch); - } - - /** Generates a cryptographically secure random number between zero and range exclusive - * i.e. 0 < returned number < range - * @param range The upper bound on the number. - * @return - */ - static CBigNum randBignum(const CBigNum& range) { - CBigNum ret; - if(!BN_rand_range(&ret, &range)){ - throw bignum_error("CBigNum:rand element : BN_rand_range failed"); - } - return ret; - } - - /** Generates a cryptographically secure random k-bit number - * @param k The bit length of the number. - * @return - */ - static CBigNum RandKBitBigum(const uint32_t k){ - CBigNum ret; - if(!BN_rand(&ret, k, -1, 0)){ - throw bignum_error("CBigNum:rand element : BN_rand failed"); - } - return ret; - } - - /**Returns the size in bits of the underlying bignum. - * - * @return the size - */ - int bitSize() const{ - return BN_num_bits(pbn); - } - - - void setulong(unsigned long n) - { - if (!BN_set_word(pbn, n)) - throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed"); - } - - unsigned long getulong() const - { - return BN_get_word(pbn); - } - - unsigned int getuint() const - { - return BN_get_word(pbn); - } - - int getint() const - { - unsigned long n = BN_get_word(pbn); - if (!BN_is_negative(pbn)) - return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::max() : n); - else - return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::min() : -(int)n); - } - - void setint64(int64_t sn) - { - unsigned char pch[sizeof(sn) + 6]; - unsigned char* p = pch + 4; - bool fNegative; - uint64_t n; - - if (sn < (int64_t)0) - { - // Since the minimum signed integer cannot be represented as positive so long as its type is signed, and it's not well-defined what happens if you make it unsigned before negating it, we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate - n = -(sn + 1); - ++n; - fNegative = true; - } else { - n = sn; - fNegative = false; - } - - bool fLeadingZeroes = true; - for (int i = 0; i < 8; i++) - { - unsigned char c = (n >> 56) & 0xff; - n <<= 8; - if (fLeadingZeroes) - { - if (c == 0) - continue; - if (c & 0x80) - *p++ = (fNegative ? 0x80 : 0); - else if (fNegative) - c |= 0x80; - fLeadingZeroes = false; - } - *p++ = c; - } - unsigned int nSize = p - (pch + 4); - pch[0] = (nSize >> 24) & 0xff; - pch[1] = (nSize >> 16) & 0xff; - pch[2] = (nSize >> 8) & 0xff; - pch[3] = (nSize) & 0xff; - BN_mpi2bn(pch, p - pch, pbn); - } - - uint64_t getuint64() - { - unsigned int nSize = BN_bn2mpi(pbn, nullptr); - if (nSize < 4) - return 0; - std::vector vch(nSize); - BN_bn2mpi(pbn, &vch[0]); - if (vch.size() > 4) - vch[4] &= 0x7f; - uint64_t n = 0; - for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--) - ((unsigned char*)&n)[i] = vch[j]; - return n; - } - - void setuint64(uint64_t n) - { - unsigned char pch[sizeof(n) + 6]; - unsigned char* p = pch + 4; - bool fLeadingZeroes = true; - for (int i = 0; i < 8; i++) - { - unsigned char c = (n >> 56) & 0xff; - n <<= 8; - if (fLeadingZeroes) - { - if (c == 0) - continue; - if (c & 0x80) - *p++ = 0; - fLeadingZeroes = false; - } - *p++ = c; - } - unsigned int nSize = p - (pch + 4); - pch[0] = (nSize >> 24) & 0xff; - pch[1] = (nSize >> 16) & 0xff; - pch[2] = (nSize >> 8) & 0xff; - pch[3] = (nSize) & 0xff; - BN_mpi2bn(pch, p - pch, pbn); - } - - void setuint256(uint256 n) - { - unsigned char pch[sizeof(n) + 6]; - unsigned char* p = pch + 4; - bool fLeadingZeroes = true; - unsigned char* pbegin = (unsigned char*)&n; - unsigned char* psrc = pbegin + sizeof(n); - while (psrc != pbegin) - { - unsigned char c = *(--psrc); - if (fLeadingZeroes) - { - if (c == 0) - continue; - if (c & 0x80) - *p++ = 0; - fLeadingZeroes = false; - } - *p++ = c; - } - unsigned int nSize = p - (pch + 4); - pch[0] = (nSize >> 24) & 0xff; - pch[1] = (nSize >> 16) & 0xff; - pch[2] = (nSize >> 8) & 0xff; - pch[3] = (nSize >> 0) & 0xff; - BN_mpi2bn(pch, p - pch, pbn); - } - - uint256 getuint256() const - { - unsigned int nSize = BN_bn2mpi(pbn, nullptr); - if (nSize < 4) - return uint256(); - std::vector vch(nSize); - BN_bn2mpi(pbn, &vch[0]); - if (vch.size() > 4) - vch[4] &= 0x7f; - uint256 n; - for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--) - ((unsigned char*)&n)[i] = vch[j]; - return n; - } - - - void setvch(const std::vector& vch) - { - std::vector vch2(vch.size() + 4); - unsigned int nSize = vch.size(); - // BIGNUM's byte stream format expects 4 bytes of - // big endian size data info at the front - vch2[0] = (nSize >> 24) & 0xff; - vch2[1] = (nSize >> 16) & 0xff; - vch2[2] = (nSize >> 8) & 0xff; - vch2[3] = (nSize >> 0) & 0xff; - // swap data to big endian - reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4); - BN_mpi2bn(&vch2[0], vch2.size(), pbn); - } - - std::vector getvch() const - { - unsigned int nSize = BN_bn2mpi(pbn, nullptr); - if (nSize <= 4) - return std::vector(); - std::vector vch(nSize); - BN_bn2mpi(pbn, &vch[0]); - vch.erase(vch.begin(), vch.begin() + 4); - reverse(vch.begin(), vch.end()); - return vch; - } - - CBigNum& SetCompact(unsigned int nCompact) - { - unsigned int nSize = nCompact >> 24; - std::vector vch(4 + nSize); - vch[3] = nSize; - if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff; - if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff; - if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff; - BN_mpi2bn(&vch[0], vch.size(), pbn); - return *this; - } - - unsigned int GetCompact() const - { - unsigned int nSize = BN_bn2mpi(pbn, nullptr); - std::vector vch(nSize); - nSize -= 4; - BN_bn2mpi(pbn, &vch[0]); - unsigned int nCompact = nSize << 24; - if (nSize >= 1) nCompact |= (vch[4] << 16); - if (nSize >= 2) nCompact |= (vch[5] << 8); - if (nSize >= 3) nCompact |= (vch[6] << 0); - return nCompact; - } - - void SetHex(const std::string& str) - { - // skip 0x - const char* psz = str.c_str(); - while (IsSpace(*psz)) - psz++; - bool fNegative = false; - if (*psz == '-') - { - fNegative = true; - psz++; - } - if (psz[0] == '0' && ToLower((unsigned char)psz[1]) == 'x') - psz += 2; - while (IsSpace(*psz)) - psz++; - - // hex string to bignum - *this = 0; - while (HexDigit(*psz) >= 0) - { - *this <<= 4; - int n = HexDigit((unsigned char)*psz++); - *this += n; - } - if (fNegative) - *this = 0 - *this; - } - - std::string ToString(int nBase=10) const - { - CAutoBN_CTX pctx; - CBigNum bnBase = nBase; - CBigNum bn0 = 0; - std::string str; - CBigNum bn = *this; - BN_set_negative(&bn, false); - CBigNum dv; - CBigNum rem; - if (BN_cmp(&bn, &bn0) == 0) - return "0"; - while (BN_cmp(&bn, &bn0) > 0) - { - if (!BN_div(&dv, &rem, &bn, &bnBase, pctx)) - throw bignum_error("CBigNum::ToString() : BN_div failed"); - bn = dv; - unsigned int c = rem.getulong(); - str += "0123456789abcdef"[c]; - } - if (BN_is_negative(pbn)) - str += "-"; - reverse(str.begin(), str.end()); - return str; - } - - std::string GetHex() const - { - return ToString(16); - } - - template - void Serialize(Stream& s) const - { - ::Serialize(s, getvch()); - } - - template - void Unserialize(Stream& s) - { - std::vector vch; - ::Unserialize(s, vch); - setvch(vch); - } - - /** - * exponentiation with an int. this^e - * @param e the exponent as an int - * @return - */ - CBigNum pow(const int e) const { - return this->pow(CBigNum(e)); - } - - /** - * exponentiation this^e - * @param e the exponent - * @return - */ - CBigNum pow(const CBigNum& e) const { - CAutoBN_CTX pctx; - CBigNum ret; - if (!BN_exp(&ret, pbn, &e, pctx)) - throw bignum_error("CBigNum::pow : BN_exp failed"); - return ret; - } - - /** - * modular multiplication: (this * b) mod m - * @param b operand - * @param m modulus - */ - CBigNum mul_mod(const CBigNum& b, const CBigNum& m) const { - CAutoBN_CTX pctx; - CBigNum ret; - if (!BN_mod_mul(&ret, pbn, &b, &m, pctx)) - throw bignum_error("CBigNum::mul_mod : BN_mod_mul failed"); - - return ret; - } - - /** - * modular exponentiation: this^e mod n - * @param e exponent - * @param m modulus - */ - CBigNum pow_mod(const CBigNum& e, const CBigNum& m) const { - CAutoBN_CTX pctx; - CBigNum ret; - if( e < 0){ - // g^-x = (g^-1)^x - CBigNum inv = this->inverse(m); - CBigNum posE = e * -1; - if (!BN_mod_exp(&ret, &inv, &posE, &m, pctx)) - throw bignum_error("CBigNum::pow_mod: BN_mod_exp failed on negative exponent"); - }else - if (!BN_mod_exp(&ret, pbn, &e, &m, pctx)) - throw bignum_error("CBigNum::pow_mod : BN_mod_exp failed"); - - return ret; - } - - /** - * Calculates the inverse of this element mod m. - * i.e. i such this*i = 1 mod m - * @param m the modu - * @return the inverse - */ - CBigNum inverse(const CBigNum& m) const { - CAutoBN_CTX pctx; - CBigNum ret; - if (!BN_mod_inverse(&ret, pbn, &m, pctx)) - throw bignum_error("CBigNum::inverse*= :BN_mod_inverse"); - return ret; - } - - /** - * Generates a random (safe) prime of numBits bits - * @param numBits the number of bits - * @param safe true for a safe prime - * @return the prime - */ - static CBigNum generatePrime(const unsigned int numBits, bool safe = false) { - CBigNum ret; - if (!BN_generate_prime_ex(&ret, numBits, safe, nullptr, nullptr, nullptr)) - throw bignum_error("CBigNum::generatePrime*= :BN_generate_prime_ex"); - return ret; - } - - /** - * Calculates the greatest common divisor (GCD) of two numbers. - * @param m the second element - * @return the GCD - */ - CBigNum gcd( const CBigNum& b) const{ - CAutoBN_CTX pctx; - CBigNum ret; - if (!BN_gcd(&ret, pbn, &b, pctx)) - throw bignum_error("CBigNum::gcd*= :BN_gcd"); - return ret; - } - - /** - * Miller-Rabin primality test on this element - * @param checks: optional, the number of Miller-Rabin tests to run - * default causes error rate of 2^-80. - * @return true if prime - */ - bool isPrime(const int checks=BN_prime_checks) const { - CAutoBN_CTX pctx; - int ret = BN_is_prime_ex(pbn, checks, pctx, nullptr); - if(ret < 0){ - throw bignum_error("CBigNum::isPrime :BN_is_prime_ex"); - } - return ret; - } - - bool isOne() const - { - return BN_is_one(pbn); - } - - - bool operator!() const - { - return BN_is_zero(pbn); - } - - CBigNum& operator+=(const CBigNum& b) - { - if (!BN_add(pbn, pbn, &b)) - throw bignum_error("CBigNum::operator+= : BN_add failed"); - return *this; - } - - CBigNum& operator-=(const CBigNum& b) - { - *this = *this - b; - return *this; - } - - CBigNum& operator*=(const CBigNum& b) - { - CAutoBN_CTX pctx; - if (!BN_mul(pbn, pbn, &b, pctx)) - throw bignum_error("CBigNum::operator*= : BN_mul failed"); - return *this; - } - - CBigNum& operator/=(const CBigNum& b) - { - *this = *this / b; - return *this; - } - - CBigNum& operator%=(const CBigNum& b) - { - *this = *this % b; - return *this; - } - - CBigNum& operator<<=(unsigned int shift) - { - if (!BN_lshift(pbn, pbn, shift)) - throw bignum_error("CBigNum:operator<<= : BN_lshift failed"); - return *this; - } - - CBigNum& operator>>=(unsigned int shift) - { - // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number - // if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL - CBigNum a = 1; - a <<= shift; - if (BN_cmp(&a, pbn) > 0) - { - *this = 0; - return *this; - } - - if (!BN_rshift(pbn, pbn, shift)) - throw bignum_error("CBigNum:operator>>= : BN_rshift failed"); - return *this; - } - - - CBigNum& operator++() - { - // prefix operator - if (!BN_add(pbn, pbn, BN_value_one())) - throw bignum_error("CBigNum::operator++ : BN_add failed"); - return *this; - } - - const CBigNum operator++(int) - { - // postfix operator - const CBigNum ret = *this; - ++(*this); - return ret; - } - - CBigNum& operator--() - { - // prefix operator - CBigNum r; - if (!BN_sub(&r, pbn, BN_value_one())) - throw bignum_error("CBigNum::operator-- : BN_sub failed"); - *this = r; - return *this; - } - - const CBigNum operator--(int) - { - // postfix operator - const CBigNum ret = *this; - --(*this); - return ret; - } - - BIGNUM* operator&() { return pbn; } - const BIGNUM* operator&() const { return pbn; } - - friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b); - friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b); - friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b); - friend inline const CBigNum operator*(const CBigNum& a, const CBigNum& b); - friend inline bool operator<(const CBigNum& a, const CBigNum& b); -}; - - - -inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) -{ - CBigNum r; - if (!BN_add(&r, &a, &b)) - throw bignum_error("CBigNum::operator+ : BN_add failed"); - return r; -} - -inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) -{ - CBigNum r; - if (!BN_sub(&r, &a, &b)) - throw bignum_error("CBigNum::operator- : BN_sub failed"); - return r; -} - -inline const CBigNum operator-(const CBigNum& a) -{ - CBigNum r(a); - BN_set_negative(&r, !BN_is_negative(&r)); - return r; -} - -inline const CBigNum operator*(const CBigNum& a, const CBigNum& b) -{ - CAutoBN_CTX pctx; - CBigNum r; - if (!BN_mul(&r, &a, &b, pctx)) - throw bignum_error("CBigNum::operator* : BN_mul failed"); - return r; -} - -inline const CBigNum operator/(const CBigNum& a, const CBigNum& b) -{ - CAutoBN_CTX pctx; - CBigNum r; - if (!BN_div(&r, nullptr, &a, &b, pctx)) - throw bignum_error("CBigNum::operator/ : BN_div failed"); - return r; -} - -inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) -{ - CAutoBN_CTX pctx; - CBigNum r; - if (!BN_nnmod(&r, &a, &b, pctx)) - throw bignum_error("CBigNum::operator% : BN_div failed"); - return r; -} - -inline const CBigNum operator<<(const CBigNum& a, unsigned int shift) -{ - CBigNum r; - if (!BN_lshift(&r, &a, shift)) - throw bignum_error("CBigNum:operator<< : BN_lshift failed"); - return r; -} - -inline const CBigNum operator>>(const CBigNum& a, unsigned int shift) -{ - CBigNum r = a; - r >>= shift; - return r; -} - -inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); } -inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); } -inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); } -inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); } -inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); } -inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); } - -inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b) { return strm << b.ToString(10); } - -typedef CBigNum Bignum; - -#endif diff --git a/src/gridcoin/staking/difficulty.cpp b/src/gridcoin/staking/difficulty.cpp index 5303197ca4..b2cb8f097a 100644 --- a/src/gridcoin/staking/difficulty.cpp +++ b/src/gridcoin/staking/difficulty.cpp @@ -4,7 +4,6 @@ // file COPYING or https://opensource.org/licenses/mit-license.php. #include "amount.h" -#include "bignum.h" #include "chainparams.h" #include "init.h" #include "gridcoin/staking/difficulty.h" @@ -21,7 +20,7 @@ using namespace GRC; namespace { constexpr int64_t TARGET_TIMESPAN = 16 * 60; // 16 mins in seconds -const CBigNum PROOF_OF_STAKE_LIMIT(ArithToUint256(~arith_uint256() >> 20)); +const arith_uint256 PROOF_OF_STAKE_LIMIT = ~arith_uint256() >> 20; // ppcoin: find last block index up to pindex const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake) @@ -61,7 +60,7 @@ unsigned int GRC::GetNextTargetRequired(const CBlockIndex* pindexLast) // ppcoin: target change every block // ppcoin: retarget with exponential moving toward target spacing - CBigNum bnNew; + arith_uint256 bnNew; bnNew.SetCompact(pindexPrev->nBits); // Gridcoin - Reset Diff to 1 on 12-19-2014 (R Halford) - Diff sticking at diff --git a/src/gridcoin/staking/kernel.cpp b/src/gridcoin/staking/kernel.cpp index 47e436643b..511ef3fe18 100644 --- a/src/gridcoin/staking/kernel.cpp +++ b/src/gridcoin/staking/kernel.cpp @@ -461,7 +461,7 @@ bool GRC::CalculateLegacyV3HashProof( << coinstake.nTime << por_nonce; - out_hash_proof = CBigNum(out.GetHash()).getuint256(); + out_hash_proof = out.GetHash(); return true; } @@ -631,10 +631,10 @@ bool GRC::CheckProofOfStakeV8( //Stake refactoring TomasBrod int64_t Weight = CalculateStakeWeightV8(txPrev, prevout.n); - CBigNum bnHashProof(hashProofOfStake); + arith_uint256 bnHashProof = UintToArith256(hashProofOfStake); // Base target - CBigNum bnTarget; + arith_uint256 bnTarget; bnTarget.SetCompact(Block.nBits); // Weighted target bnTarget *= Weight; @@ -646,7 +646,7 @@ bool GRC::CheckProofOfStakeV8( " Trg %72s", generated_by_me?" Local,":"", (double)header.nTime, (double)txPrev.nTime, (double)tx.nTime, Block.nBits, (double)Weight, - CBigNum(hashProofOfStake).GetHex(), bnTarget.GetHex() + hashProofOfStake.GetHex(), bnTarget.GetHex() ); // Now check if proof-of-stake hash meets target protocol diff --git a/src/main.cpp b/src/main.cpp index 32aad9f3aa..4fbe0e2740 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1675,7 +1675,7 @@ bool LoadBlockIndex(bool fAllowNew) txNew.nTime = 1413033777; txNew.vin.resize(1); txNew.vout.resize(1); - txNew.vin[0].scriptSig = CScript() << 0 << CBigNum(42) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); + txNew.vin[0].scriptSig = CScript() << 0 << CScriptNum(42) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); txNew.vout[0].SetEmpty(); CBlock block; block.vtx.push_back(txNew); diff --git a/src/miner.cpp b/src/miner.cpp index c7c1cde861..59aaf77d08 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -662,7 +662,7 @@ bool CreateCoinStake(CBlock &blocknew, CKey &key, function += ": "; int64_t CoinWeight; - CBigNum StakeKernelHash; + arith_uint256 StakeKernelHash; CTxDB txdb("r"); int64_t StakeWeightSum = 0; double StakeValueSum = 0; @@ -730,9 +730,9 @@ bool CreateCoinStake(CBlock &blocknew, CKey &key, CoinWeight = GRC::CalculateStakeWeightV8(CoinTx, CoinTxN); - StakeKernelHash.setuint256(GRC::CalculateStakeHashV8(block_time, CoinTx, CoinTxN, txnew.nTime, StakeModifier)); + StakeKernelHash = UintToArith256(GRC::CalculateStakeHashV8(block_time, CoinTx, CoinTxN, txnew.nTime, StakeModifier)); - CBigNum StakeTarget; + arith_uint256 StakeTarget; StakeTarget.SetCompact(blocknew.nBits); StakeTarget *= CoinWeight; StakeWeightSum += CoinWeight; diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 7c4c42d638..7bed59e789 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -12,7 +12,6 @@ add_executable(test_gridcoin base32_tests.cpp base58_tests.cpp base64_tests.cpp - bignum_tests.cpp bip32_tests.cpp #compilerbug_tests.cpp crypto_tests.cpp diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp deleted file mode 100755 index c3da4a571c..0000000000 --- a/src/test/bignum_tests.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include -#include - -#include "bignum.h" -#include "util.h" - -#include - -BOOST_AUTO_TEST_SUITE(bignum_tests) - -// Unfortunately there's no standard way of preventing a function from being -// inlined, so we define a macro for it. -// -// You should use it like this: -// NOINLINE void function() {...} -#if defined(__GNUC__) -// This also works and will be defined for any compiler implementing GCC -// extensions, such as Clang and ICC. -#define NOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) -#define NOINLINE __declspec(noinline) -#else -// We give out a warning because it impacts the correctness of one bignum test. -#warning You should define NOINLINE for your compiler. -#define NOINLINE -#endif - -// For the following test case, it is useful to use additional tools. -// -// The simplest one to use is the compiler flag -ftrapv, which detects integer -// overflows and similar errors. However, due to optimizations and compilers -// taking advantage of undefined behavior sometimes it may not actually detect -// anything. -// -// You can also use compiler-based stack protection to possibly detect possible -// stack buffer overruns. -// -// For more accurate diagnostics, you can use an undefined arithmetic operation -// detector such as the clang's undefined behaviour checker. -// See also: https://clang.llvm.org/docs/UsersManual.html#controlling-code-generation -// -// It might also be useful to use Google's AddressSanitizer to detect -// stack buffer overruns, which valgrind can't currently detect. - -// Let's force this code not to be inlined, in order to actually -// test a generic version of the function. This increases the chance -// that -ftrapv will detect overflows. -NOINLINE void mysetint64(CBigNum& num, int64_t n) -{ - num.setint64(n); -} - -// For each number, we do 2 tests: one with inline code, then we reset the -// value to 0, then the second one with a non-inlined function. -BOOST_AUTO_TEST_CASE(bignum_setint64) -{ - int64_t n; - - { - n = 0; - CBigNum num(n); - BOOST_CHECK(num.ToString() == "0"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "0"); - } - { - n = 1; - CBigNum num(n); - BOOST_CHECK(num.ToString() == "1"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "1"); - } - { - n = -1; - CBigNum num(n); - BOOST_CHECK(num.ToString() == "-1"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "-1"); - } - { - n = 5; - CBigNum num(n); - BOOST_CHECK(num.ToString() == "5"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "5"); - } - { - n = -5; - CBigNum num(n); - BOOST_CHECK(num.ToString() == "-5"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "-5"); - } - { - n = std::numeric_limits::min(); - CBigNum num(n); - BOOST_CHECK(num.ToString() == "-9223372036854775808"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "-9223372036854775808"); - } - { - n = std::numeric_limits::max(); - CBigNum num(n); - BOOST_CHECK(num.ToString() == "9223372036854775807"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "9223372036854775807"); - } -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/validation.cpp b/src/validation.cpp index ee78d93bf5..d9b12eb165 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -485,7 +485,7 @@ bool ConnectInputs(CTransaction& tx, CTxDB& txdb, MapPrevTx inputs, std::map Date: Thu, 19 Oct 2023 22:45:14 +0300 Subject: [PATCH 08/12] staking: use 320-bit integers for target calculations While a non-weighted stake target hash can fit 236-bit integers[0], the multiplication by the 64-bit stake can cause the weighted target hash to go up to 300-bits. While I think this would have been better fixed by lowering the stake target hash limit to be 192-bit so that the weighted target hash fits 256-bit, this would break consensus and there are already blocks that require weighted target hashes higher than 2**256 to verify. The existing blob_int class requires bits which are multiples of 32, so 320 is used. [0] - src/gridcoin/staking/difficulty.cpp:24 # The PROOF_OF_STAKE_LIMIT is set to uint256 maximum right shifted by 20 resulting in a 236-bit limit. That's enforced by the GRC::GetNextTargetRequired function which is used to generate the nBits of blocks. --- src/arith_uint256.cpp | 21 ++++++++++++++++++++- src/arith_uint256.h | 17 +++++++++++++++++ src/gridcoin/staking/kernel.cpp | 7 +++---- src/miner.cpp | 7 +++---- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index 536a787fee..946c47a384 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -7,6 +7,7 @@ #include #include +#include template @@ -146,7 +147,13 @@ double base_uint::getdouble() const template std::string base_uint::GetHex() const { - return ArithToUint256(*this).GetHex(); + static constexpr ssize_t BYTES = BITS / 8; + + uint8_t pn_rev[BYTES]; + for (int i = 0; i < BYTES; ++i) { + pn_rev[i] = ((uint8_t*)&pn)[BYTES - 1 - i]; + } + return HexStr(pn_rev); } template @@ -257,3 +264,15 @@ arith_uint256 UintToArith256(const uint256 &a) b.pn[x] = ReadLE32(a.begin() + x*4); return b; } + +// Explicit instantiations for base_uint<320> +template base_uint<320>& base_uint<320>::operator<<=(unsigned int); +template base_uint<320>& base_uint<320>::operator*=(const base_uint<320>& b); +template int base_uint<320>::CompareTo(const base_uint<320>&) const; +template std::string base_uint<320>::GetHex() const; + +arith_uint320::arith_uint320(const uint256& b) { + std::memset(pn, 0, sizeof(pn)); + std::memcpy(pn, b.data(), b.size()); +} + diff --git a/src/arith_uint256.h b/src/arith_uint256.h index c63a76ea03..26d6a45ca7 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -13,6 +13,7 @@ #include class uint256; +class arith_uint320; class uint_error : public std::runtime_error { public: @@ -279,6 +280,22 @@ class arith_uint256 : public base_uint<256> { friend uint256 ArithToUint256(const arith_uint256 &); friend arith_uint256 UintToArith256(const uint256 &); + friend class arith_uint320; +}; + +/** 320-bit unsigned big integer. */ +class arith_uint320 : public base_uint<320> { +public: + arith_uint320() {} + arith_uint320(const base_uint<320>& b) : base_uint<320>(b) {} + arith_uint320(uint64_t b) : base_uint<320>(b) {} + + arith_uint320(const arith_uint256& b) { + std::memset(pn, 0, sizeof(pn)); + std::memcpy(pn, b.pn, sizeof(b.pn)); + } + + arith_uint320(const uint256& b); }; uint256 ArithToUint256(const arith_uint256 &); diff --git a/src/gridcoin/staking/kernel.cpp b/src/gridcoin/staking/kernel.cpp index 511ef3fe18..7f1952140d 100644 --- a/src/gridcoin/staking/kernel.cpp +++ b/src/gridcoin/staking/kernel.cpp @@ -631,13 +631,12 @@ bool GRC::CheckProofOfStakeV8( //Stake refactoring TomasBrod int64_t Weight = CalculateStakeWeightV8(txPrev, prevout.n); - arith_uint256 bnHashProof = UintToArith256(hashProofOfStake); + arith_uint320 bnHashProof = arith_uint320(hashProofOfStake); // Base target - arith_uint256 bnTarget; - bnTarget.SetCompact(Block.nBits); + arith_uint320 bnTarget = arith_uint256().SetCompact(Block.nBits); // Weighted target - bnTarget *= Weight; + bnTarget *= arith_uint320(Weight); LogPrint(BCLog::LogFlags::VERBOSE, diff --git a/src/miner.cpp b/src/miner.cpp index 59aaf77d08..21f6a73597 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -732,9 +732,8 @@ bool CreateCoinStake(CBlock &blocknew, CKey &key, StakeKernelHash = UintToArith256(GRC::CalculateStakeHashV8(block_time, CoinTx, CoinTxN, txnew.nTime, StakeModifier)); - arith_uint256 StakeTarget; - StakeTarget.SetCompact(blocknew.nBits); - StakeTarget *= CoinWeight; + arith_uint320 StakeTarget = arith_uint256().SetCompact(blocknew.nBits); + StakeTarget *= arith_uint320(CoinWeight); StakeWeightSum += CoinWeight; StakeWeightMin = std::min(StakeWeightMin, CoinWeight); StakeWeightMax = std::max(StakeWeightMax, CoinWeight); @@ -754,7 +753,7 @@ bool CreateCoinStake(CBlock &blocknew, CKey &key, StakeKernelDiff, GRC::GetBlockDifficulty(blocknew.nBits)); - if (StakeKernelHash <= StakeTarget) + if (arith_uint320(StakeKernelHash) <= StakeTarget) { // Found a kernel LogPrintf("CreateCoinStake: Found Kernel"); From 7cf37cae79e5bb649ac41f97bc74e1923884ada0 Mon Sep 17 00:00:00 2001 From: div72 Date: Sun, 22 Oct 2023 20:40:13 +0300 Subject: [PATCH 09/12] build: add PIE_FLAGS to CFLAGS for crypto lib --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index 441d48e36b..258897767f 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -357,6 +357,7 @@ nodist_libgridcoin_util_a_SOURCES = $(srcdir)/obj/build.h # crypto primitives library +crypto_libgridcoin_crypto_base_a_CFLAGS = $(AM_CFLAGS) $(PIE_FLAGS) crypto_libgridcoin_crypto_base_a_CPPFLAGS = $(AM_CPPFLAGS) crypto_libgridcoin_crypto_base_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) crypto_libgridcoin_crypto_base_a_SOURCES = \ From 9afa0443e77be87b937ba25a17f8aa8a58d810b1 Mon Sep 17 00:00:00 2001 From: div72 Date: Tue, 24 Oct 2023 00:22:06 +0300 Subject: [PATCH 10/12] crypto: fix integer stores The lack of bit shifts caused the upper bytes to be interpreted as zero, after the implicit cast to uint8_t. --- src/gridcoin/md5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gridcoin/md5.c b/src/gridcoin/md5.c index da50664e12..9e1c206555 100644 --- a/src/gridcoin/md5.c +++ b/src/gridcoin/md5.c @@ -61,9 +61,9 @@ #include #define CRYPTO_load_u32_le(data) (uint32_t)data[0] | ((uint32_t)data[1] << 8) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24) -#define CRYPTO_store_u32_le(dst, src) (dst)[0] = src & 0xFF; (dst)[1] = src & 0xFF00; (dst)[2] = src & 0xFF0000; (dst)[3] = src & 0xFF000000 +#define CRYPTO_store_u32_le(dst, src) (dst)[0] = (src & 0xFF); (dst)[1] = (src & 0xFF00) >> 8; (dst)[2] = (src & 0xFF0000) >> 16; (dst)[3] = (src & 0xFF000000) >> 24 #define CRYPTO_load_u32_be(data) (uint32_t)data[3] | ((uint32_t)data[2] << 8) | ((uint32_t)data[1] << 16) | ((uint32_t)data[0] << 24) -#define CRYPTO_store_u32_be(dst, src) (dst)[3] = src & 0xFF; (dst)[2] = src & 0xFF00; (dst)[1] = src & 0xFF0000; (dst)[0] = src & 0xFF000000 +#define CRYPTO_store_u32_be(dst, src) (dst)[3] = (src & 0xFF); (dst)[2] = (src & 0xFF00) >> 8; (dst)[1] = (src & 0xFF0000) >> 16; (dst)[0] = (src & 0xFF000000) >> 24 static inline uint32_t CRYPTO_rotl_u32(uint32_t value, int shift) { #if defined(_MSC_VER) From d5e2b8dfd268d13f77c00e165d3da84244adf7a4 Mon Sep 17 00:00:00 2001 From: div72 Date: Tue, 24 Oct 2023 00:23:36 +0300 Subject: [PATCH 11/12] crypto: rename MD5 function to GRC__MD5 Since the system OpenSSL is also linked currently, that can take precedence over the vendored MD5. --- src/gridcoin/cpid.cpp | 2 +- src/gridcoin/md5.c | 2 +- src/gridcoin/md5.h | 2 +- src/gridcoin/quorum.cpp | 6 +++--- src/gridcoin/researcher.cpp | 6 +++--- src/gridcoin/superblock.cpp | 2 +- src/test/crypto_tests.cpp | 2 +- src/test/gridcoin/superblock_tests.cpp | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/gridcoin/cpid.cpp b/src/gridcoin/cpid.cpp index f5d24096f1..f0edebf5b9 100644 --- a/src/gridcoin/cpid.cpp +++ b/src/gridcoin/cpid.cpp @@ -67,7 +67,7 @@ Cpid Cpid::Hash(const std::string& internal, const std::string& email) std::vector input(internal.begin(), internal.end()); input.insert(input.end(), email.begin(), email.end()); - MD5(input.data(), input.size(), cpid.m_bytes.data()); + GRC__MD5(input.data(), input.size(), cpid.m_bytes.data()); return cpid; } diff --git a/src/gridcoin/md5.c b/src/gridcoin/md5.c index 9e1c206555..7b210a42b5 100644 --- a/src/gridcoin/md5.c +++ b/src/gridcoin/md5.c @@ -233,7 +233,7 @@ int MD5_Final(uint8_t out[MD5_DIGEST_LENGTH], MD5_CTX *c) { return 1; } -uint8_t *MD5(const uint8_t *data, size_t len, uint8_t out[MD5_DIGEST_LENGTH]) { +uint8_t *GRC__MD5(const uint8_t *data, size_t len, uint8_t out[MD5_DIGEST_LENGTH]) { MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, data, len); diff --git a/src/gridcoin/md5.h b/src/gridcoin/md5.h index 3c8f3e0ef5..9bd5be4ecc 100644 --- a/src/gridcoin/md5.h +++ b/src/gridcoin/md5.h @@ -22,7 +22,7 @@ typedef struct MD5_CTX { unsigned num; } MD5_CTX; -uint8_t *MD5(const uint8_t *data, size_t len, uint8_t out[MD5_DIGEST_LENGTH]); +uint8_t *GRC__MD5(const uint8_t *data, size_t len, uint8_t out[MD5_DIGEST_LENGTH]); #if defined(__cplusplus) } diff --git a/src/gridcoin/quorum.cpp b/src/gridcoin/quorum.cpp index 792b29744f..92cd83f0f5 100644 --- a/src/gridcoin/quorum.cpp +++ b/src/gridcoin/quorum.cpp @@ -313,9 +313,9 @@ class LegacyConsensus std::string input = grc_address + "_" + ToString(GetDayOfYear(time)); std::vector address_day_hash(16); - MD5(reinterpret_cast(input.data()), - input.size(), - address_day_hash.data()); + GRC__MD5(reinterpret_cast(input.data()), + input.size(), + address_day_hash.data()); return arith_uint256("0x" + HexStr(address_day_hash)) < reference_hash; } diff --git a/src/gridcoin/researcher.cpp b/src/gridcoin/researcher.cpp index 22f69bd5d3..ad36cf0f3b 100644 --- a/src/gridcoin/researcher.cpp +++ b/src/gridcoin/researcher.cpp @@ -393,9 +393,9 @@ std::optional FallbackToCpidByEmail( const std::string email = Researcher::Email(); std::vector email_hash_bytes(16); - MD5(reinterpret_cast(email.data()), - email.size(), - email_hash_bytes.data()); + GRC__MD5(reinterpret_cast(email.data()), + email.size(), + email_hash_bytes.data()); if (HexStr(email_hash_bytes) != email_hash) { return std::nullopt; diff --git a/src/gridcoin/superblock.cpp b/src/gridcoin/superblock.cpp index b070721c56..4b9e7c61d7 100644 --- a/src/gridcoin/superblock.cpp +++ b/src/gridcoin/superblock.cpp @@ -1083,7 +1083,7 @@ QuorumHash QuorumHash::Hash(const Superblock& superblock) } Md5Sum output; - MD5((const unsigned char*)input.data(), input.size(), output.data()); + GRC__MD5((const unsigned char*)input.data(), input.size(), output.data()); return QuorumHash(output); } diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 1bd36c4666..3e99c8d9b9 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -59,7 +59,7 @@ static void TestMD5(const std::string &in, const std::string &hexout) { assert(hexout.size() == 2 * MD5_DIGEST_LENGTH); uint8_t out[MD5_DIGEST_LENGTH]; - MD5((const uint8_t*)in.data(), in.size(), out); + GRC__MD5((const uint8_t*)in.data(), in.size(), out); BOOST_CHECK(std::memcmp(out, ParseHex(hexout).data(), MD5_DIGEST_LENGTH) == 0); } diff --git a/src/test/gridcoin/superblock_tests.cpp b/src/test/gridcoin/superblock_tests.cpp index f2e880c3f2..61a8a7642c 100644 --- a/src/test/gridcoin/superblock_tests.cpp +++ b/src/test/gridcoin/superblock_tests.cpp @@ -141,7 +141,7 @@ struct Legacy { const char* chIn = s1.c_str(); unsigned char digest2[16]; - MD5((unsigned char*)chIn, strlen(chIn), (unsigned char*)&digest2); + GRC__MD5((unsigned char*)chIn, strlen(chIn), (unsigned char*)&digest2); const std::vector digest_vector(digest2, digest2 + sizeof(digest2)); From e7bc015174d6cdbfe145763e648b476a0d20eada Mon Sep 17 00:00:00 2001 From: div72 Date: Tue, 24 Oct 2023 00:33:18 +0300 Subject: [PATCH 12/12] crypto: mark internal MD5 functions as static Avoiding conflicts with OpenSSL. --- src/gridcoin/md5.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gridcoin/md5.c b/src/gridcoin/md5.c index 7b210a42b5..18a0923825 100644 --- a/src/gridcoin/md5.c +++ b/src/gridcoin/md5.c @@ -200,7 +200,7 @@ static inline void crypto_md32_final(crypto_md32_block_func block_func, memset(data, 0, block_size); } -int MD5_Init(MD5_CTX *md5) { +static int MD5_Init(MD5_CTX *md5) { memset(md5, 0, sizeof(MD5_CTX)); md5->h[0] = 0x67452301UL; md5->h[1] = 0xefcdab89UL; @@ -212,17 +212,17 @@ int MD5_Init(MD5_CTX *md5) { static void md5_block_data_order(uint32_t *state, const uint8_t *data, size_t num); -void MD5_Transform(MD5_CTX *c, const uint8_t data[MD5_CBLOCK]) { +static void MD5_Transform(MD5_CTX *c, const uint8_t data[MD5_CBLOCK]) { md5_block_data_order(c->h, data, 1); } -int MD5_Update(MD5_CTX *c, const void *data, size_t len) { +static int MD5_Update(MD5_CTX *c, const void *data, size_t len) { crypto_md32_update(&md5_block_data_order, c->h, c->data, MD5_CBLOCK, &c->num, &c->Nh, &c->Nl, data, len); return 1; } -int MD5_Final(uint8_t out[MD5_DIGEST_LENGTH], MD5_CTX *c) { +static int MD5_Final(uint8_t out[MD5_DIGEST_LENGTH], MD5_CTX *c) { crypto_md32_final(&md5_block_data_order, c->h, c->data, MD5_CBLOCK, &c->num, c->Nh, c->Nl, /*is_big_endian=*/0);