Skip to content

Commit

Permalink
libsodium sanity check connected to app init.
Browse files Browse the repository at this point in the history
Abort at node startup if it is running a non-patched version of the libsodium library.

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.
  • Loading branch information
furszy committed May 1, 2021
1 parent 3e154b0 commit 7c6ad15
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 64 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down
3 changes: 3 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -765,6 +766,8 @@ bool InitSanityCheck(void)
return false;
}

libsodium_sanity_test();

return true;
}

Expand Down
76 changes: 76 additions & 0 deletions src/sapling/sodium_sanity.cpp
Original file line number Diff line number Diff line change
@@ -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 <sodium.h>

void TestLibsodiumEd25519SignatureVerification(
const std::string &scope,
const std::string &msg,
std::vector<unsigned char> pubkey,
std::vector<unsigned char> 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"));
}
10 changes: 10 additions & 0 deletions src/sapling/sodium_sanity.h
Original file line number Diff line number Diff line change
@@ -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
70 changes: 6 additions & 64 deletions src/test/libsodium_consensus_tests.cpp
Original file line number Diff line number Diff line change
@@ -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 <sodium.h>
#include "test/test_pivx.h"
#include "sapling/sodium_sanity.h"
#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(libsodium_consensus_tests, TestingSetup)

void TestLibsodiumEd25519SignatureVerification(
const std::string &scope,
const std::string &msg,
std::vector<unsigned char> pubkey,
std::vector<unsigned char> 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()

0 comments on commit 7c6ad15

Please sign in to comment.