From 0b49eda6e731db2dc1162c2127e25bda8d667aaa Mon Sep 17 00:00:00 2001 From: furszy Date: Sat, 1 May 2021 09:31:59 -0300 Subject: [PATCH] Use libsodium's s < L check, instead checking that libsodium checks that. Adaptation coming from zcash@2902ac7ce8e754d09a5137cba82d8af10c172977 --- src/init.cpp | 5 +++++ src/sapling/sodium_sanity.cpp | 38 +++++++++++++++++++++++++++++++++++ src/sapling/sodium_sanity.h | 1 + src/test/test_pivx.cpp | 2 ++ 4 files changed, 46 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index c5211fc59b558..b9a632746fd9a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1217,6 +1217,11 @@ bool AppInitSanityChecks() { // ********************************************************* Step 4: sanity checks + // Initialize libsodium + if (init_and_check_sodium() == -1) { + return false; + } + // Initialize elliptic curve code RandomInit(); ECC_Start(); diff --git a/src/sapling/sodium_sanity.cpp b/src/sapling/sodium_sanity.cpp index 8f53700464faa..97cb85d61840e 100644 --- a/src/sapling/sodium_sanity.cpp +++ b/src/sapling/sodium_sanity.cpp @@ -10,6 +10,44 @@ #include +int init_and_check_sodium() +{ + if (sodium_init() == -1) { + return -1; + } + + // What follows is a runtime test that ensures the version of libsodium + // we're linked against checks that signatures are canonical (s < L). + const unsigned char message[1] = { 0 }; + + unsigned char pk[crypto_sign_PUBLICKEYBYTES]; + unsigned char sk[crypto_sign_SECRETKEYBYTES]; + unsigned char sig[crypto_sign_BYTES]; + + crypto_sign_keypair(pk, sk); + crypto_sign_detached(sig, NULL, message, sizeof(message), sk); + + assert(crypto_sign_verify_detached(sig, message, sizeof(message), pk) == 0); + + // Copied from libsodium/crypto_sign/ed25519/ref10/open.c + static const unsigned char L[32] = + { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; + + // Add L to S, which starts at sig[32]. + unsigned int s = 0; + for (size_t i = 0; i < 32; i++) { + s = sig[32 + i] + L[i] + (s >> 8); + sig[32 + i] = s & 0xff; + } + + assert(crypto_sign_verify_detached(sig, message, sizeof(message), pk) != 0); + + return 0; +} + void TestLibsodiumEd25519SignatureVerification( const std::string &scope, const std::string &msg, diff --git a/src/sapling/sodium_sanity.h b/src/sapling/sodium_sanity.h index f9c44593925b8..cd7b4faa3b62c 100644 --- a/src/sapling/sodium_sanity.h +++ b/src/sapling/sodium_sanity.h @@ -5,6 +5,7 @@ #ifndef PIVX_SODIUM_SANITY_H #define PIVX_SODIUM_SANITY_H +int init_and_check_sodium(); void libsodium_sanity_test(); #endif //PIVX_SODIUM_SANITY_H diff --git a/src/test/test_pivx.cpp b/src/test/test_pivx.cpp index 080bc5083448f..e9f726593c510 100644 --- a/src/test/test_pivx.cpp +++ b/src/test/test_pivx.cpp @@ -15,6 +15,7 @@ #include "net_processing.h" #include "rpc/server.h" #include "rpc/register.h" +#include "sapling/sodium_sanity.h" #include "script/sigcache.h" #include "sporkdb.h" #include "txmempool.h" @@ -40,6 +41,7 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) BasicTestingSetup::BasicTestingSetup() { + assert(init_and_check_sodium() != -1); ECC_Start(); SetupEnvironment(); InitSignatureCache();