diff --git a/CMakeLists.txt b/CMakeLists.txt index 4953b410075e4..2e2b7e7f14d66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -419,6 +419,7 @@ set(UTIL_SOURCES ./src/compat/strnlen.cpp ./src/compat/glibc_sanity.cpp ./src/compat/glibcxx_sanity.cpp + ./src/sapling/sodium_sanity.cpp ./src/chainparamsbase.cpp ./src/clientversion.cpp ./src/fs.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 66bb002e5a56f..17353812c84c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -168,6 +168,7 @@ BITCOIN_CORE_H = \ compat/cpuid.h \ compat/endian.h \ compat/sanity.h \ + sapling/sodium_sanity.h \ compressor.h \ consensus/consensus.h \ consensus/merkle.h \ @@ -537,6 +538,7 @@ libbitcoin_util_a_SOURCES = \ clientversion.cpp \ compat/glibc_sanity.cpp \ compat/glibcxx_sanity.cpp \ + sapling/sodium_sanity.cpp \ compat/strnlen.cpp \ fs.cpp \ interfaces/handler.cpp \ diff --git a/src/init.cpp b/src/init.cpp index bd33edc127925..c5211fc59b558 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -40,6 +40,7 @@ #include "reverse_iterate.h" #include "rpc/register.h" #include "rpc/server.h" +#include "sapling/sodium_sanity.h" #include "script/sigcache.h" #include "script/standard.h" #include "scheduler.h" @@ -765,6 +766,8 @@ bool InitSanityCheck(void) return false; } + libsodium_sanity_test(); + return true; } diff --git a/src/sapling/sodium_sanity.cpp b/src/sapling/sodium_sanity.cpp new file mode 100644 index 0000000000000..8f53700464faa --- /dev/null +++ b/src/sapling/sodium_sanity.cpp @@ -0,0 +1,76 @@ +// Copyright (c) 2020 The Zcash Core developers +// Copyright (c) 2021 The PIVX Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php. + +#include "sodium_sanity.h" + +#include "uint256.h" +#include "utilstrencodings.h" + +#include + +void TestLibsodiumEd25519SignatureVerification( + const std::string &scope, + const std::string &msg, + std::vector pubkey, + std::vector sig) +{ + if (crypto_sign_verify_detached(sig.data(), + (const unsigned char*)msg.data(), + msg.size(), + pubkey.data()) != 0) { + throw std::runtime_error("Error, invalid sodium signature verification.\n" + "The program cannot continue running, not accepted network consensus modifications detected.\n" + "To solve the issue build the binaries using libsodium 1.0.15 or a patched version of libsodium 1.0.17 (patches available in depends/libsodium)"); + } +} + +void libsodium_sanity_test() +{ + // libsodium <= 1.0.15 accepts valid signatures for a non-zero pubkey with + // small order; this is currently part of our consensus rules. + // libsodium >= 1.0.16 rejects all pubkeys with small order. + // + // These test vectors were generated by finding pairs of points (A, P) both + // in the eight-torsion subgroup such that R = B + P and R = [1] B - [k] A + // (where SHA512(bytes(R) || bytes(A) || message) represents k in + // little-endian order, as in Ed25519). + TestLibsodiumEd25519SignatureVerification( + "Test vector 1", + "zcash ed25519 libsodium compatibility", + ParseHex("0100000000000000000000000000000000000000000000000000000000000000"), + ParseHex("58666666666666666666666666666666666666666666666666666666666666660100000000000000000000000000000000000000000000000000000000000000")); + TestLibsodiumEd25519SignatureVerification( + "Test vector 2", + "zcash ed25519 libsodium compatibility", + ParseHex("0000000000000000000000000000000000000000000000000000000000000080"), + ParseHex("58666666666666666666666666666666666666666666666666666666666666660100000000000000000000000000000000000000000000000000000000000000")); + TestLibsodiumEd25519SignatureVerification( + "Test vector 3", + "zcash ed25519 libsodium compatibility", + ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85"), + ParseHex("da99e28ba529cdde35a25fba9059e78ecaee239f99755b9b1aa4f65df00803e20100000000000000000000000000000000000000000000000000000000000000")); + TestLibsodiumEd25519SignatureVerification( + "Test vector 4", + "zcash ed25519 libsodium compatibility", + ParseHex("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a"), + ParseHex("95999999999999999999999999999999999999999999999999999999999999990100000000000000000000000000000000000000000000000000000000000000")); + TestLibsodiumEd25519SignatureVerification( + "Test vector 5", + "zcash ed25519 libsodium compatibility", + ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85"), + ParseHex("13661d745ad63221ca5da0456fa618713511dc60668aa464e55b09a20ff7fc1d0100000000000000000000000000000000000000000000000000000000000000")); + + // libsodium <= 1.0.15 contains a blocklist of small-order points that R is + // checked against. However, it does not contain all canonical small-order + // points; in particular, it is missing the negative of one of the points. + // + // This test case is the only pair of points (A, R) both in the eight-torsion + // subgroup, that satisfies R = [0] B - [k] A and also evades the blocklist. + TestLibsodiumEd25519SignatureVerification( + "Small order R that is not rejected by libsodium <= 1.0.15", + "zcash ed25519 libsodium compatibility", + ParseHex("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a"), + ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000")); +} \ No newline at end of file diff --git a/src/sapling/sodium_sanity.h b/src/sapling/sodium_sanity.h new file mode 100644 index 0000000000000..f9c44593925b8 --- /dev/null +++ b/src/sapling/sodium_sanity.h @@ -0,0 +1,10 @@ +// Copyright (c) 2021 The PIVX Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php. + +#ifndef PIVX_SODIUM_SANITY_H +#define PIVX_SODIUM_SANITY_H + +void libsodium_sanity_test(); + +#endif //PIVX_SODIUM_SANITY_H diff --git a/src/test/libsodium_consensus_tests.cpp b/src/test/libsodium_consensus_tests.cpp index c190b655304ea..2b4fa39e2f4bf 100644 --- a/src/test/libsodium_consensus_tests.cpp +++ b/src/test/libsodium_consensus_tests.cpp @@ -1,74 +1,16 @@ -#include "test/test_pivx.h" - -#include "uint256.h" -#include "utilstrencodings.h" +// Copyright (c) 2021 The PIVX Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . -#include +#include "test/test_pivx.h" +#include "sapling/sodium_sanity.h" #include BOOST_FIXTURE_TEST_SUITE(libsodium_consensus_tests, TestingSetup) -void TestLibsodiumEd25519SignatureVerification( - const std::string &scope, - const std::string &msg, - std::vector pubkey, - std::vector sig) -{ - BOOST_CHECK_EQUAL( - crypto_sign_verify_detached( - sig.data(), - (const unsigned char*)msg.data(), msg.size(), - pubkey.data()), - 0); -} - BOOST_AUTO_TEST_CASE(LibsodiumPubkeyValidation) { - // libsodium <= 1.0.15 accepts valid signatures for a non-zero pubkey with - // small order; this is currently part of our consensus rules. - // libsodium >= 1.0.16 rejects all pubkeys with small order. - // - // These test vectors were generated by finding pairs of points (A, P) both - // in the eight-torsion subgroup such that R = B + P and R = [1] B - [k] A - // (where SHA512(bytes(R) || bytes(A) || message) represents k in - // little-endian order, as in Ed25519). - TestLibsodiumEd25519SignatureVerification( - "Test vector 1", - "zcash ed25519 libsodium compatibility", - ParseHex("0100000000000000000000000000000000000000000000000000000000000000"), - ParseHex("58666666666666666666666666666666666666666666666666666666666666660100000000000000000000000000000000000000000000000000000000000000")); - TestLibsodiumEd25519SignatureVerification( - "Test vector 2", - "zcash ed25519 libsodium compatibility", - ParseHex("0000000000000000000000000000000000000000000000000000000000000080"), - ParseHex("58666666666666666666666666666666666666666666666666666666666666660100000000000000000000000000000000000000000000000000000000000000")); - TestLibsodiumEd25519SignatureVerification( - "Test vector 3", - "zcash ed25519 libsodium compatibility", - ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85"), - ParseHex("da99e28ba529cdde35a25fba9059e78ecaee239f99755b9b1aa4f65df00803e20100000000000000000000000000000000000000000000000000000000000000")); - TestLibsodiumEd25519SignatureVerification( - "Test vector 4", - "zcash ed25519 libsodium compatibility", - ParseHex("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a"), - ParseHex("95999999999999999999999999999999999999999999999999999999999999990100000000000000000000000000000000000000000000000000000000000000")); - TestLibsodiumEd25519SignatureVerification( - "Test vector 5", - "zcash ed25519 libsodium compatibility", - ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85"), - ParseHex("13661d745ad63221ca5da0456fa618713511dc60668aa464e55b09a20ff7fc1d0100000000000000000000000000000000000000000000000000000000000000")); - - // libsodium <= 1.0.15 contains a blocklist of small-order points that R is - // checked against. However, it does not contain all canonical small-order - // points; in particular, it is missing the negative of one of the points. - // - // This test case is the only pair of points (A, R) both in the eight-torsion - // subgroup, that satisfies R = [0] B - [k] A and also evades the blocklist. - TestLibsodiumEd25519SignatureVerification( - "Small order R that is not rejected by libsodium <= 1.0.15", - "zcash ed25519 libsodium compatibility", - ParseHex("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a"), - ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000")); + libsodium_sanity_test(); } BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file