Skip to content

Commit

Permalink
Auto merge of #4359 - str4d:2872-upgrade-libsodium, r=str4d
Browse files Browse the repository at this point in the history
Upgrade libsodium to 1.0.18

Includes patches that maintain consensus compatibility with libsodium 1.0.15 for Ed25519 pubkey and signature validation.

Replaces #4239. Closes #2872.
  • Loading branch information
zkbot committed Mar 10, 2020
2 parents ccd10d5 + 0cca79a commit dcd3614
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 3 deletions.
9 changes: 6 additions & 3 deletions depends/packages/libsodium.mk
@@ -1,12 +1,15 @@
package=libsodium
$(package)_version=1.0.15
$(package)_download_path=https://download.libsodium.org/libsodium/releases/old/unsupported/
$(package)_version=1.0.18
$(package)_download_path=https://download.libsodium.org/libsodium/releases/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4
$(package)_sha256_hash=6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e46636c1
$(package)_dependencies=
$(package)_patches=1.0.15-pubkey-validation.diff 1.0.15-signature-validation.diff
$(package)_config_opts=

define $(package)_preprocess_cmds
patch -p1 < $($(package)_patch_dir)/1.0.15-pubkey-validation.diff && \
patch -p1 < $($(package)_patch_dir)/1.0.15-signature-validation.diff && \
cd $($(package)_build_subdir); ./autogen.sh
endef

Expand Down
17 changes: 17 additions & 0 deletions depends/patches/libsodium/1.0.15-pubkey-validation.diff
@@ -0,0 +1,17 @@
diff -ur libsodium-1.0.18-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c libsodium-1.0.18/src/libsodium/crypto_sign/ed25519/ref10/open.c
--- libsodium-1.0.18-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c 2019-05-18 16:32:11.000000000 -0400
+++ libsodium-1.0.18/src/libsodium/crypto_sign/ed25519/ref10/open.c 2020-01-21 18:55:22.474233831 -0500
@@ -32,8 +32,11 @@
ge25519_has_small_order(sig) != 0) {
return -1;
}
- if (ge25519_is_canonical(pk) == 0 ||
- ge25519_has_small_order(pk) != 0) {
+ unsigned char d = 0;
+ for (int i = 0; i < 32; ++i) {
+ d |= pk[i];
+ }
+ if (d == 0) {
return -1;
}
#endif
78 changes: 78 additions & 0 deletions depends/patches/libsodium/1.0.15-signature-validation.diff
@@ -0,0 +1,78 @@
diff -ur libsodium-1.0.18-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c libsodium-1.0.18/src/libsodium/crypto_sign/ed25519/ref10/open.c
--- libsodium-1.0.18-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c 2019-05-18 21:32:11.000000000 +0100
+++ libsodium-1.0.18/src/libsodium/crypto_sign/ed25519/ref10/open.c 2020-02-18 00:00:08.544107613 +0000
@@ -10,6 +10,65 @@
#include "private/ed25519_ref10.h"
#include "utils.h"

+#ifndef ED25519_COMPAT
+int
+_crypto_sign_ed25519_small_order(const unsigned char p[32])
+{
+ CRYPTO_ALIGN(16)
+ static const unsigned char blacklist[][32] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4,
+ 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6,
+ 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05 },
+ { 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b,
+ 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39,
+ 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a },
+ { 0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4,
+ 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6,
+ 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85 },
+ { 0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b,
+ 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39,
+ 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa },
+ { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ { 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+ };
+ size_t i, j;
+ unsigned char c;
+
+ for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
+ c = 0;
+ for (j = 0; j < 32; j++) {
+ c |= p[j] ^ blacklist[i][j];
+ }
+ if (c == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif
+
int
_crypto_sign_ed25519_verify_detached(const unsigned char *sig,
const unsigned char *m,
@@ -29,7 +88,7 @@
}
#else
if (sc25519_is_canonical(sig + 32) == 0 ||
- ge25519_has_small_order(sig) != 0) {
+ _crypto_sign_ed25519_small_order(sig) != 0) {
return -1;
}
if (ge25519_is_canonical(pk) == 0 ||
1 change: 1 addition & 0 deletions src/Makefile.gtest.include
Expand Up @@ -12,6 +12,7 @@ zcash_gtest_SOURCES = \
gtest/main.cpp \
gtest/utils.cpp \
gtest/test_checktransaction.cpp \
gtest/test_consensus.cpp \
gtest/json_test_vectors.cpp \
gtest/json_test_vectors.h \
gtest/test_foundersreward.cpp
Expand Down
69 changes: 69 additions & 0 deletions src/gtest/test_consensus.cpp
@@ -0,0 +1,69 @@
#include <gtest/gtest.h>
#include <sodium.h>

#include "uint256.h"
#include "utilstrencodings.h"

void TestLibsodiumEd25519SignatureVerification(
const std::string &scope,
const std::string &msg,
std::vector<unsigned char> pubkey,
std::vector<unsigned char> sig)
{
SCOPED_TRACE(scope);

EXPECT_EQ(
crypto_sign_verify_detached(
sig.data(),
(const unsigned char*)msg.data(), msg.size(),
pubkey.data()),
0);
}

TEST(ConsensusTests, 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"));
}

0 comments on commit dcd3614

Please sign in to comment.