diff --git a/src/init.cpp b/src/init.cpp index c5211fc59b558c..b9a632746fd9a3 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 c0782e5b85282a..7b64b79fca7124 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 f9c44593925b85..cd7b4faa3b62cb 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 080bc5083448f9..e9f726593c5106 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();