Skip to content

Commit 75f316a

Browse files
committed
libsodium sanity check connected to app init.
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.
1 parent 3e154b0 commit 75f316a

File tree

5 files changed

+97
-64
lines changed

5 files changed

+97
-64
lines changed

src/Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ BITCOIN_CORE_H = \
168168
compat/cpuid.h \
169169
compat/endian.h \
170170
compat/sanity.h \
171+
sapling/sodium_sanity.h \
171172
compressor.h \
172173
consensus/consensus.h \
173174
consensus/merkle.h \
@@ -537,6 +538,7 @@ libbitcoin_util_a_SOURCES = \
537538
clientversion.cpp \
538539
compat/glibc_sanity.cpp \
539540
compat/glibcxx_sanity.cpp \
541+
sapling/sodium_sanity.cpp \
540542
compat/strnlen.cpp \
541543
fs.cpp \
542544
interfaces/handler.cpp \

src/init.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "reverse_iterate.h"
4141
#include "rpc/register.h"
4242
#include "rpc/server.h"
43+
#include "sapling/sodium_sanity.h"
4344
#include "script/sigcache.h"
4445
#include "script/standard.h"
4546
#include "scheduler.h"
@@ -765,6 +766,8 @@ bool InitSanityCheck(void)
765766
return false;
766767
}
767768

769+
libsodium_sanity_test();
770+
768771
return true;
769772
}
770773

src/sapling/sodium_sanity.cpp

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright (c) 2020 The Zcash Core developers
2+
// Copyright (c) 2021 The PIVX Core developers
3+
// Distributed under the MIT software license, see the accompanying
4+
// file COPYING or https://www.opensource.org/licenses/mit-license.php.
5+
6+
#include "sodium_sanity.h"
7+
8+
#include "uint256.h"
9+
#include "utilstrencodings.h"
10+
11+
#include <sodium.h>
12+
13+
void TestLibsodiumEd25519SignatureVerification(
14+
const std::string &scope,
15+
const std::string &msg,
16+
std::vector<unsigned char> pubkey,
17+
std::vector<unsigned char> sig)
18+
{
19+
if (crypto_sign_verify_detached(sig.data(),
20+
(const unsigned char*)msg.data(),
21+
msg.size(),
22+
pubkey.data()) != 0) {
23+
throw std::runtime_error("Error, invalid sodium library linked.\n"
24+
"The program cannot continue running, not accepted network consensus modifications detected.\n"
25+
"To solve the issue build the binaries with libsodium 1.0.15");
26+
}
27+
}
28+
29+
void libsodium_sanity_test()
30+
{
31+
// libsodium <= 1.0.15 accepts valid signatures for a non-zero pubkey with
32+
// small order; this is currently part of our consensus rules.
33+
// libsodium >= 1.0.16 rejects all pubkeys with small order.
34+
//
35+
// These test vectors were generated by finding pairs of points (A, P) both
36+
// in the eight-torsion subgroup such that R = B + P and R = [1] B - [k] A
37+
// (where SHA512(bytes(R) || bytes(A) || message) represents k in
38+
// little-endian order, as in Ed25519).
39+
TestLibsodiumEd25519SignatureVerification(
40+
"Test vector 1",
41+
"zcash ed25519 libsodium compatibility",
42+
ParseHex("0100000000000000000000000000000000000000000000000000000000000000"),
43+
ParseHex("58666666666666666666666666666666666666666666666666666666666666660100000000000000000000000000000000000000000000000000000000000000"));
44+
TestLibsodiumEd25519SignatureVerification(
45+
"Test vector 2",
46+
"zcash ed25519 libsodium compatibility",
47+
ParseHex("0000000000000000000000000000000000000000000000000000000000000080"),
48+
ParseHex("58666666666666666666666666666666666666666666666666666666666666660100000000000000000000000000000000000000000000000000000000000000"));
49+
TestLibsodiumEd25519SignatureVerification(
50+
"Test vector 3",
51+
"zcash ed25519 libsodium compatibility",
52+
ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85"),
53+
ParseHex("da99e28ba529cdde35a25fba9059e78ecaee239f99755b9b1aa4f65df00803e20100000000000000000000000000000000000000000000000000000000000000"));
54+
TestLibsodiumEd25519SignatureVerification(
55+
"Test vector 4",
56+
"zcash ed25519 libsodium compatibility",
57+
ParseHex("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a"),
58+
ParseHex("95999999999999999999999999999999999999999999999999999999999999990100000000000000000000000000000000000000000000000000000000000000"));
59+
TestLibsodiumEd25519SignatureVerification(
60+
"Test vector 5",
61+
"zcash ed25519 libsodium compatibility",
62+
ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85"),
63+
ParseHex("13661d745ad63221ca5da0456fa618713511dc60668aa464e55b09a20ff7fc1d0100000000000000000000000000000000000000000000000000000000000000"));
64+
65+
// libsodium <= 1.0.15 contains a blocklist of small-order points that R is
66+
// checked against. However, it does not contain all canonical small-order
67+
// points; in particular, it is missing the negative of one of the points.
68+
//
69+
// This test case is the only pair of points (A, R) both in the eight-torsion
70+
// subgroup, that satisfies R = [0] B - [k] A and also evades the blocklist.
71+
TestLibsodiumEd25519SignatureVerification(
72+
"Small order R that is not rejected by libsodium <= 1.0.15",
73+
"zcash ed25519 libsodium compatibility",
74+
ParseHex("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a"),
75+
ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000"));
76+
}

src/sapling/sodium_sanity.h

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (c) 2021 The PIVX Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or https://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef PIVX_SODIUM_SANITY_H
6+
#define PIVX_SODIUM_SANITY_H
7+
8+
void libsodium_sanity_test();
9+
10+
#endif //PIVX_SODIUM_SANITY_H
+6-64
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,16 @@
1-
#include "test/test_pivx.h"
2-
3-
#include "uint256.h"
4-
#include "utilstrencodings.h"
1+
// Copyright (c) 2021 The PIVX Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
54

6-
#include <sodium.h>
5+
#include "test/test_pivx.h"
6+
#include "sapling/sodium_sanity.h"
77
#include <boost/test/unit_test.hpp>
88

99
BOOST_FIXTURE_TEST_SUITE(libsodium_consensus_tests, TestingSetup)
1010

11-
void TestLibsodiumEd25519SignatureVerification(
12-
const std::string &scope,
13-
const std::string &msg,
14-
std::vector<unsigned char> pubkey,
15-
std::vector<unsigned char> sig)
16-
{
17-
BOOST_CHECK_EQUAL(
18-
crypto_sign_verify_detached(
19-
sig.data(),
20-
(const unsigned char*)msg.data(), msg.size(),
21-
pubkey.data()),
22-
0);
23-
}
24-
2511
BOOST_AUTO_TEST_CASE(LibsodiumPubkeyValidation)
2612
{
27-
// libsodium <= 1.0.15 accepts valid signatures for a non-zero pubkey with
28-
// small order; this is currently part of our consensus rules.
29-
// libsodium >= 1.0.16 rejects all pubkeys with small order.
30-
//
31-
// These test vectors were generated by finding pairs of points (A, P) both
32-
// in the eight-torsion subgroup such that R = B + P and R = [1] B - [k] A
33-
// (where SHA512(bytes(R) || bytes(A) || message) represents k in
34-
// little-endian order, as in Ed25519).
35-
TestLibsodiumEd25519SignatureVerification(
36-
"Test vector 1",
37-
"zcash ed25519 libsodium compatibility",
38-
ParseHex("0100000000000000000000000000000000000000000000000000000000000000"),
39-
ParseHex("58666666666666666666666666666666666666666666666666666666666666660100000000000000000000000000000000000000000000000000000000000000"));
40-
TestLibsodiumEd25519SignatureVerification(
41-
"Test vector 2",
42-
"zcash ed25519 libsodium compatibility",
43-
ParseHex("0000000000000000000000000000000000000000000000000000000000000080"),
44-
ParseHex("58666666666666666666666666666666666666666666666666666666666666660100000000000000000000000000000000000000000000000000000000000000"));
45-
TestLibsodiumEd25519SignatureVerification(
46-
"Test vector 3",
47-
"zcash ed25519 libsodium compatibility",
48-
ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85"),
49-
ParseHex("da99e28ba529cdde35a25fba9059e78ecaee239f99755b9b1aa4f65df00803e20100000000000000000000000000000000000000000000000000000000000000"));
50-
TestLibsodiumEd25519SignatureVerification(
51-
"Test vector 4",
52-
"zcash ed25519 libsodium compatibility",
53-
ParseHex("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a"),
54-
ParseHex("95999999999999999999999999999999999999999999999999999999999999990100000000000000000000000000000000000000000000000000000000000000"));
55-
TestLibsodiumEd25519SignatureVerification(
56-
"Test vector 5",
57-
"zcash ed25519 libsodium compatibility",
58-
ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85"),
59-
ParseHex("13661d745ad63221ca5da0456fa618713511dc60668aa464e55b09a20ff7fc1d0100000000000000000000000000000000000000000000000000000000000000"));
60-
61-
// libsodium <= 1.0.15 contains a blocklist of small-order points that R is
62-
// checked against. However, it does not contain all canonical small-order
63-
// points; in particular, it is missing the negative of one of the points.
64-
//
65-
// This test case is the only pair of points (A, R) both in the eight-torsion
66-
// subgroup, that satisfies R = [0] B - [k] A and also evades the blocklist.
67-
TestLibsodiumEd25519SignatureVerification(
68-
"Small order R that is not rejected by libsodium <= 1.0.15",
69-
"zcash ed25519 libsodium compatibility",
70-
ParseHex("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a"),
71-
ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000"));
13+
libsodium_sanity_test();
7214
}
7315

7416
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)