diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 9d9132a2ca623..30dab77a2a7ec 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -73,13 +73,13 @@ jobs: config: - name: Linux os: ubuntu-18.04 - packages: python3-zmq qttools5-dev qtbase5-dev qttools5-dev-tools libqt5svg5-dev libqt5charts5-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev libgmp-dev libsodium-dev cargo + packages: python3-zmq qttools5-dev qtbase5-dev qttools5-dev-tools libqt5svg5-dev libqt5charts5-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev libgmp-dev cargo cc: gcc cxx: g++ - name: macOS os: macos-10.15 - packages: python3 autoconf automake berkeley-db4 libtool boost miniupnpc libnatpmp pkg-config qt5 zmq libevent qrencode gmp libsodium rust + packages: python3 autoconf automake berkeley-db4 libtool boost miniupnpc libnatpmp pkg-config qt5 zmq libevent qrencode gmp rust cc: $(brew --prefix llvm)/bin/clang cxx: $(brew --prefix llvm)/bin/clang++ @@ -93,11 +93,17 @@ jobs: sudo apt-add-repository "ppa:ondrej/php" -y sudo apt-get --yes update sudo apt-get install --no-install-recommends --no-upgrade -qq "$APT_BASE" ${{ matrix.config.packages }} + sudo dpkg --remove --force-depends libsodium-dev fi if [[ ${{ matrix.config.os }} = macos* ]]; then brew install "$APT_BASE" ${{ matrix.config.packages }} + brew uninstall --ignore-dependencies libsodium fi + echo "Installing libsodium.." + sudo ./contrib/install_sodium.sh `pwd` + echo "libsodium install finished.." + - name: Prepare ccache timestamp id: ccache_cache_timestamp shell: cmake -P {0} @@ -118,8 +124,8 @@ jobs: CC=${{ matrix.config.cc }} CXX=${{ matrix.config.cxx }} if [[ ${{ matrix.config.os }} = macos* ]]; then - export CPPFLAGS="-I/usr/local/Cellar/gmp/6.2.1/include" - export LDFLAGS="-L/usr/local/Cellar/gmp/6.2.1/lib" + export CPPFLAGS="-I/usr/local/Cellar/gmp/6.2.1/include -I/usr/local/include" + export LDFLAGS="-L/usr/local/Cellar/gmp/6.2.1/lib -L/usr/local/lib" fi export CC export CXX @@ -303,7 +309,16 @@ jobs: - name: x86_64 Linux [GOAL:install] [bionic] [no depends only system libs] os: ubuntu-18.04 host: x86_64-unknown-linux-gnu - apt_get: python3-zmq qtbase5-dev qttools5-dev-tools libqt5svg5-dev libqt5charts5-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libqrencode-dev libgmp-dev libsodium-dev cargo + apt_get: python3-zmq qtbase5-dev qttools5-dev-tools libqt5svg5-dev libqt5charts5-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libqrencode-dev libgmp-dev cargo + unit_tests: true + no_depends: 1 + goal: install + BITCOIN_CONFIG: "--enable-zmq --with-incompatible-bdb --with-gui=qt5 CPPFLAGS=-DDEBUG_LOCKORDER" + + - name: x86_64 Linux [GOAL:install] [focal] [no depends only system libs] + os: ubuntu-20.04 + host: x86_64-unknown-linux-gnu + apt_get: python3-zmq qtbase5-dev qttools5-dev-tools libqt5svg5-dev libqt5charts5-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libsodium1.0.17-dev libzmq3-dev libqrencode-dev libgmp-dev cargo unit_tests: true no_depends: 1 goal: install @@ -323,7 +338,7 @@ jobs: - name: macOS 10.15 [GOAL:deploy] [native macOS using syslibs no unit or functional tests] os: macos-10.15 host: x86_64-apple-darwin19.6.0 - brew_install: autoconf automake ccache berkeley-db4 libtool boost miniupnpc pkg-config python3 qt5 zmq libevent qrencode gmp libsodium rust librsvg + brew_install: autoconf automake ccache berkeley-db4 libtool boost miniupnpc pkg-config python3 qt5 zmq libevent qrencode gmp rust librsvg unit_tests: false functional_tests: false no_depends: 1 @@ -340,6 +355,7 @@ jobs: run: | if [[ ${{ matrix.config.os }} = ubuntu* ]]; then sudo apt-add-repository "ppa:ondrej/php" -y + sudo apt-add-repository "ppa:fuzzbawls/libsodium1.0.17" -y sudo apt-get --yes update sudo apt-get install --no-install-recommends --no-upgrade -qq "$APT_BASE" ${{ matrix.config.apt_get }} fi @@ -348,6 +364,21 @@ jobs: pip3 install ds_store mac_alias fi + if [ "${{ matrix.config.no_depends }}" = 1 ]; then + if [ "${{ matrix.config.os }}" != "ubuntu-20.04" ] && "${{ matrix.config.os }}" != "macos-10.15" ]; then + sudo dpkg --remove --force-depends libsodium-dev + fi + + if [[ ${{ matrix.config.os }} = macos* ]]; then + brew install "$APT_BASE" ${{ matrix.config.packages }} + brew uninstall --ignore-dependencies libsodium + fi + + echo "Installing libsodium.." + sudo ./contrib/install_sodium.sh `pwd` + echo "libsodium install finished.." + fi + - name: depends cache files if: matrix.config.no_depends != 1 uses: actions/cache@v2 diff --git a/CMakeLists.txt b/CMakeLists.txt index cff73d1a9638f..1746bc0648977 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -409,6 +409,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 diff --git a/configure.ac b/configure.ac index 7456cb67df48a..f5c194fcba53b 100644 --- a/configure.ac +++ b/configure.ac @@ -1166,7 +1166,7 @@ if test x$use_pkgconfig = xyes; then if test x$TARGET_OS != xwindows; then PKG_CHECK_MODULES([EVENT_PTHREADS], [libevent_pthreads],, [AC_MSG_ERROR(libevent_pthreads not found.)]) fi - PKG_CHECK_MODULES([SODIUM], [libsodium],, [AC_MSG_ERROR(libsodium not found.)]) + PKG_CHECK_MODULES([SODIUM], [libsodium], [have_sodium=yes], [AC_MSG_ERROR(libsodium not found.)]) fi if test "x$use_zmq" = "xyes"; then @@ -1188,7 +1188,7 @@ else if test x$TARGET_OS != xwindows; then AC_CHECK_LIB([event_pthreads],[main],EVENT_PTHREADS_LIBS=-levent_pthreads,AC_MSG_ERROR(libevent_pthreads missing)) fi - AC_CHECK_HEADER([sodium/core.h],, AC_MSG_ERROR(libsodium headers missing),) + AC_CHECK_HEADER([sodium/core.h], [have_sodium=yes], AC_MSG_ERROR(libsodium headers missing),) AC_CHECK_LIB([sodium],[main],SODIUM_LIBS=-lsodium,AC_MSG_ERROR(libsodium missing)) fi @@ -1223,6 +1223,31 @@ else fi fi +dnl check for supported sodium library version +if test x$have_sodium != xno; then + AC_MSG_CHECKING([whether libsodium library version is supported]) + AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[ + #include + ]], [[ + #if SODIUM_LIBRARY_VERSION_MAJOR <= 10 + // Everything is okay + #elif SODIUM_LIBRARY_VERSION_MAJOR == 10 + #if SODIUM_LIBRARY_VERSION_MINOR == 0 + // Everything is okay + #else + # error libsodium library minor version is unsupported + #endif + #else + # error libsodium library major version is unsupported + #endif + ]])],[ + AC_MSG_RESULT(yes) + ],[ + AC_MSG_RESULT(no) + AC_MSG_ERROR([libsodium library version > 10.1 is unsupported.]) + ]) +fi + dnl gmp check GMP_CHECK if test x"$has_gmp" != x"yes"; then diff --git a/contrib/cmake/FindSodium.cmake b/contrib/cmake/FindSodium.cmake index b38c994e34a7b..918f8ee0f6df4 100644 --- a/contrib/cmake/FindSodium.cmake +++ b/contrib/cmake/FindSodium.cmake @@ -86,123 +86,6 @@ if (UNIX) find_library(sodium_LIBRARY_RELEASE NAMES ${${XPREFIX}_LIBRARIES} HINTS ${${XPREFIX}_LIBRARY_DIRS} ) - - - ######################################################################## - # Windows -elseif (WIN32) - set(sodium_DIR "$ENV{sodium_DIR}" CACHE FILEPATH "sodium install directory") - mark_as_advanced(sodium_DIR) - - find_path(sodium_INCLUDE_DIR sodium.h - HINTS ${sodium_DIR} - PATH_SUFFIXES include - ) - - if (MSVC) - # detect target architecture - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/arch.cpp" [=[ - #if defined _M_IX86 - #error ARCH_VALUE x86_32 - #elif defined _M_X64 - #error ARCH_VALUE x86_64 - #endif - #error ARCH_VALUE unknown - ]=]) - try_compile(_UNUSED_VAR "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/arch.cpp" - OUTPUT_VARIABLE _COMPILATION_LOG - ) - string(REGEX REPLACE ".*ARCH_VALUE ([a-zA-Z0-9_]+).*" "\\1" _TARGET_ARCH "${_COMPILATION_LOG}") - - # construct library path - if (_TARGET_ARCH STREQUAL "x86_32") - string(APPEND _PLATFORM_PATH "Win32") - elseif(_TARGET_ARCH STREQUAL "x86_64") - string(APPEND _PLATFORM_PATH "x64") - else() - message(FATAL_ERROR "the ${_TARGET_ARCH} architecture is not supported by Findsodium.cmake.") - endif() - string(APPEND _PLATFORM_PATH "/$$CONFIG$$") - - if (MSVC_VERSION LESS 1900) - math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 60") - else() - math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 50") - endif() - string(APPEND _PLATFORM_PATH "/v${_VS_VERSION}") - - if (sodium_USE_STATIC_LIBS) - string(APPEND _PLATFORM_PATH "/static") - else() - string(APPEND _PLATFORM_PATH "/dynamic") - endif() - - string(REPLACE "$$CONFIG$$" "Debug" _DEBUG_PATH_SUFFIX "${_PLATFORM_PATH}") - string(REPLACE "$$CONFIG$$" "Release" _RELEASE_PATH_SUFFIX "${_PLATFORM_PATH}") - - find_library(sodium_LIBRARY_DEBUG libsodium.lib - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX} - ) - find_library(sodium_LIBRARY_RELEASE libsodium.lib - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX} - ) - if (NOT sodium_USE_STATIC_LIBS) - set(CMAKE_FIND_LIBRARY_SUFFIXES_BCK ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") - find_library(sodium_DLL_DEBUG libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX} - ) - find_library(sodium_DLL_RELEASE libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX} - ) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BCK}) - endif() - - elseif(_GCC_COMPATIBLE) - if (sodium_USE_STATIC_LIBS) - find_library(sodium_LIBRARY_DEBUG libsodium.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - find_library(sodium_LIBRARY_RELEASE libsodium.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - else() - find_library(sodium_LIBRARY_DEBUG libsodium.dll.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - find_library(sodium_LIBRARY_RELEASE libsodium.dll.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - - file(GLOB _DLL - LIST_DIRECTORIES false - RELATIVE "${sodium_DIR}/bin" - "${sodium_DIR}/bin/libsodium*.dll" - ) - find_library(sodium_DLL_DEBUG ${_DLL} libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES bin - ) - find_library(sodium_DLL_RELEASE ${_DLL} libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES bin - ) - endif() - else() - message(FATAL_ERROR "this platform is not supported by FindSodium.cmake") - endif() - - - ######################################################################## - # unsupported else() message(FATAL_ERROR "this platform is not supported by FindSodium.cmake") endif() @@ -213,12 +96,25 @@ endif() # extract sodium version if (sodium_INCLUDE_DIR) - set(_VERSION_HEADER "${_INCLUDE_DIR}/sodium/version.h") - if (EXISTS _VERSION_HEADER) + set(_VERSION_HEADER "${sodium_INCLUDE_DIR}/sodium/version.h") + if (EXISTS "${_VERSION_HEADER}") file(READ "${_VERSION_HEADER}" _VERSION_HEADER_CONTENT) string(REGEX REPLACE ".*#[ \t]*define[ \t]*SODIUM_VERSION_STRING[ \t]*\"([^\n]*)\".*" "\\1" sodium_VERSION "${_VERSION_HEADER_CONTENT}") - set(sodium_VERSION "${sodium_VERSION}" PARENT_SCOPE) + set(sodium_VERSION "${sodium_VERSION}") + message(STATUS "Found libsodium version ${sodium_VERSION}") + + # extract the sodium library version + string(REGEX REPLACE ".*#[ \t]*define[ \t]*SODIUM_LIBRARY_VERSION_MAJOR[ \t]*([^\n]*).*" "\\1" + sodium_LIBRARY_VERSION_MAJOR "${_VERSION_HEADER_CONTENT}") + string(REGEX REPLACE ".*#[ \t]*define[ \t]*SODIUM_LIBRARY_VERSION_MINOR[ \t]*([^\n]*).*" "\\1" + sodium_LIBRARY_VERSION_MINOR "${_VERSION_HEADER_CONTENT}") + set(sodium_LIBRARY_VERSION "${sodium_LIBRARY_VERSION_MAJOR}.${sodium_LIBRARY_VERSION_MINOR}") + message(STATUS "libsodium library version found: ${sodium_LIBRARY_VERSION}") + if (${sodium_LIBRARY_VERSION} VERSION_GREATER "10.0") + message(FATAL_ERROR "Unsupported libsodium library version ${sodium_LIBRARY_VERSION}!") + endif() + endif() endif() @@ -243,10 +139,6 @@ endif() mark_as_advanced(sodium_INCLUDE_DIR) mark_as_advanced(sodium_LIBRARY_DEBUG) mark_as_advanced(sodium_LIBRARY_RELEASE) -if (WIN32) - mark_as_advanced(sodium_DLL_DEBUG) - mark_as_advanced(sodium_DLL_RELEASE) -endif() # create imported target if(sodium_USE_STATIC_LIBS) @@ -273,22 +165,5 @@ else() IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}" IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}" ) - elseif (WIN32) - set_target_properties(sodium PROPERTIES - IMPORTED_IMPLIB "${sodium_LIBRARY_RELEASE}" - IMPORTED_IMPLIB_DEBUG "${sodium_LIBRARY_DEBUG}" - ) - if (NOT (sodium_DLL_DEBUG MATCHES ".*-NOTFOUND")) - set_target_properties(sodium PROPERTIES - IMPORTED_LOCATION_DEBUG "${sodium_DLL_DEBUG}" - ) - endif() - if (NOT (sodium_DLL_RELEASE MATCHES ".*-NOTFOUND")) - set_target_properties(sodium PROPERTIES - IMPORTED_LOCATION_RELWITHDEBINFO "${sodium_DLL_RELEASE}" - IMPORTED_LOCATION_MINSIZEREL "${sodium_DLL_RELEASE}" - IMPORTED_LOCATION_RELEASE "${sodium_DLL_RELEASE}" - ) - endif() endif() endif() \ No newline at end of file diff --git a/contrib/install_sodium.sh b/contrib/install_sodium.sh new file mode 100755 index 0000000000000..800bc635a892a --- /dev/null +++ b/contrib/install_sodium.sh @@ -0,0 +1,85 @@ +#!/bin/sh + +# Install patched libsodium 1.0.17. + +export LC_ALL=C +set -e + +if [ -z "${1}" ]; then + echo "Usage: $0 [ ...]" + echo + echo "Must specify a single argument: the directory in which sodium will be built." + echo "This is probably \`pwd\` if you're at the root of the pivx repository." + exit 1 +fi + +expand_path() { + echo "$(cd "${1}" && pwd -P)" +} + +ROOT_PREFIX="$(expand_path ${1})"; +SODIUM_PREFIX="$ROOT_PREFIX/sodium"; shift; +echo $SODIUM_PREFIX +echo $ROOT_PREFIX +SODIUM_VERSION='1.0.17' +SODIUM_HASH='0cc3dae33e642cc187b5ceb467e0ad0e1b51dcba577de1190e9ffa17766ac2b1' +SODIUM_URL="https://download.libsodium.org/libsodium/releases/libsodium-${SODIUM_VERSION}.tar.gz" + +check_exists() { + which "$1" >/dev/null 2>&1 +} + +sha256_check() { + # Args: + # + if check_exists sha256sum; then + echo "${1} ${2}" | sha256sum -c + elif check_exists sha256; then + if [ "$(uname)" = "FreeBSD" ]; then + sha256 -c "${1}" "${2}" + else + echo "${1} ${2}" | sha256 -c + fi + else + echo "${1} ${2}" | shasum -a 256 -c + fi +} + +http_get() { + # Args: + # + # It's acceptable that we don't require SSL here because we manually verify + # content hashes below. + # + if [ -f "${2}" ]; then + echo "File ${2} already exists; not downloading again" + elif check_exists curl; then + curl --insecure --retry 5 "${1}" -o "${2}" + else + wget --no-check-certificate "${1}" -O "${2}" + fi + + sha256_check "${3}" "${2}" +} + +mkdir -p "${SODIUM_PREFIX}" +http_get "${SODIUM_URL}" "libsodium-${SODIUM_VERSION}.tar.gz" "${SODIUM_HASH}" +tar -xzvf libsodium-${SODIUM_VERSION}.tar.gz -C "$SODIUM_PREFIX" +cd "${SODIUM_PREFIX}/libsodium-${SODIUM_VERSION}/" + +# Apply patches +echo "Applying patches.." +patch -p1 < "${ROOT_PREFIX}/depends/patches/libsodium/1.0.15-pubkey-validation.diff" && \ +patch -p1 < "${ROOT_PREFIX}/depends/patches/libsodium/1.0.15-signature-validation.diff" && \ +patch -p1 < "${ROOT_PREFIX}/depends/patches/libsodium/1.0.15-library-version.diff" && \ +DO_NOT_UPDATE_CONFIG_SCRIPTS=1 ./autogen.sh + +# make +"${SODIUM_PREFIX}/libsodium-${SODIUM_VERSION}/configure" --enable-static --disable-shared +make && make check + +make install + +echo +echo "sodium build complete." +echo diff --git a/depends/packages/libsodium.mk b/depends/packages/libsodium.mk index 173a4f0d0eb8c..4a45a68bdad5c 100644 --- a/depends/packages/libsodium.mk +++ b/depends/packages/libsodium.mk @@ -1,13 +1,17 @@ package=libsodium -$(package)_version=1.0.15 -$(package)_download_path=https://download.libsodium.org/libsodium/releases/old/unsupported/ +$(package)_version=1.0.17 +$(package)_download_path=https://download.libsodium.org/libsodium/releases/ $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4 +$(package)_sha256_hash=0cc3dae33e642cc187b5ceb467e0ad0e1b51dcba577de1190e9ffa17766ac2b1 $(package)_dependencies= +$(package)_patches=1.0.15-pubkey-validation.diff 1.0.15-signature-validation.diff 1.0.15-library-version.diff $(package)_config_opts= define $(package)_preprocess_cmds - cd $($(package)_build_subdir); ./autogen.sh + patch -p1 < $($(package)_patch_dir)/1.0.15-pubkey-validation.diff && \ + patch -p1 < $($(package)_patch_dir)/1.0.15-signature-validation.diff && \ + patch -p1 < $($(package)_patch_dir)/1.0.15-library-version.diff && \ + cd $($(package)_build_subdir); DO_NOT_UPDATE_CONFIG_SCRIPTS=1 ./autogen.sh endef define $(package)_config_cmds diff --git a/depends/patches/libsodium/1.0.15-library-version.diff b/depends/patches/libsodium/1.0.15-library-version.diff new file mode 100644 index 0000000000000..18455776311f3 --- /dev/null +++ b/depends/patches/libsodium/1.0.15-library-version.diff @@ -0,0 +1,12 @@ +diff -ur libsodium-1.0.17-orig/configure.ac libsodium-1.0.17/configure.ac +--- libsodium-1.0.17-orig/configure.ac 2019-01-06 12:29:47.000000000 -0800 ++++ libsodium-1.0.17/configure.ac 2021-05-17 18:22:25.582171400 -0700 +@@ -15,7 +15,7 @@ + AC_SUBST(VERSION) + + SODIUM_LIBRARY_VERSION_MAJOR=10 +-SODIUM_LIBRARY_VERSION_MINOR=2 ++SODIUM_LIBRARY_VERSION_MINOR=0 + DLL_VERSION=23 + SODIUM_LIBRARY_VERSION=25:0:2 + # | | | diff --git a/depends/patches/libsodium/1.0.15-pubkey-validation.diff b/depends/patches/libsodium/1.0.15-pubkey-validation.diff new file mode 100644 index 0000000000000..e516d1025671e --- /dev/null +++ b/depends/patches/libsodium/1.0.15-pubkey-validation.diff @@ -0,0 +1,17 @@ +diff -ur libsodium-1.0.17-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c libsodium-1.0.17/src/libsodium/crypto_sign/ed25519/ref10/open.c +--- libsodium-1.0.17-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c 2019-05-18 16:32:11.000000000 -0400 ++++ libsodium-1.0.17/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 diff --git a/depends/patches/libsodium/1.0.15-signature-validation.diff b/depends/patches/libsodium/1.0.15-signature-validation.diff new file mode 100644 index 0000000000000..dc9522f17918c --- /dev/null +++ b/depends/patches/libsodium/1.0.15-signature-validation.diff @@ -0,0 +1,94 @@ +diff -ur libsodium-1.0.17-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c libsodium-1.0.17/src/libsodium/crypto_sign/ed25519/ref10/open.c +--- libsodium-1.0.17-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c 2019-05-18 21:32:11.000000000 +0100 ++++ libsodium-1.0.17/src/libsodium/crypto_sign/ed25519/ref10/open.c 2020-02-18 00:00:08.544107613 +0000 +@@ -10,6 +10,81 @@ + #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] = { ++ /* 0 (order 4) */ ++ { 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 }, ++ /* 1 (order 1) */ ++ { 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 }, ++ /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 ++ (order 8) */ ++ { 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 }, ++ /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 ++ (order 8) */ ++ { 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 }, ++ /* p-1 (order 2) */ ++ { 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 }, ++ /* p (order 4) */ ++ { 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 }, ++ /* p+1 (order 1) */ ++ { 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 }, ++ /* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 ++ (order 8) */ ++ { 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 }, ++ /* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 ++ (order 8) */ ++ { 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 }, ++ /* 2p-1 (order 2) */ ++ { 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 }, ++ /* 2p (order 4) */ ++ { 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 }, ++ /* 2p+1 (order 1) */ ++ { 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 +104,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 || diff --git a/src/Makefile.am b/src/Makefile.am index 08ced54a504e1..fc60274a6e8a5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ @@ -545,6 +546,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 \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 8874296e4d269..755da218fd2ae 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -113,6 +113,7 @@ BITCOIN_TESTS =\ test/key_tests.cpp \ test/dbwrapper_tests.cpp \ test/validation_tests.cpp \ + test/libsodium_consensus_tests.cpp \ test/main_tests.cpp \ test/mempool_tests.cpp \ test/merkle_tests.cpp \ diff --git a/src/init.cpp b/src/init.cpp index 8b674186fb7a1..f55a3dc795977 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -41,6 +41,7 @@ #include "policy/policy.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" @@ -784,6 +785,8 @@ bool InitSanityCheck(void) return false; } + libsodium_sanity_test(); + return true; } @@ -1229,6 +1232,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 new file mode 100644 index 0000000000000..97cb85d61840e --- /dev/null +++ b/src/sapling/sodium_sanity.cpp @@ -0,0 +1,114 @@ +// 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 + +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, + std::vector pubkey, + std::vector 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")); +} \ No newline at end of file diff --git a/src/sapling/sodium_sanity.h b/src/sapling/sodium_sanity.h new file mode 100644 index 0000000000000..cd7b4faa3b62c --- /dev/null +++ b/src/sapling/sodium_sanity.h @@ -0,0 +1,11 @@ +// 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 + +int init_and_check_sodium(); +void libsodium_sanity_test(); + +#endif //PIVX_SODIUM_SANITY_H diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 6be158fdb62e9..237680eedb931 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -102,6 +102,7 @@ set(BITCOIN_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/hash_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/key_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/dbwrapper_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/libsodium_consensus_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/main_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mempool_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/merkle_tests.cpp diff --git a/src/test/libsodium_consensus_tests.cpp b/src/test/libsodium_consensus_tests.cpp new file mode 100644 index 0000000000000..2b4fa39e2f4bf --- /dev/null +++ b/src/test/libsodium_consensus_tests.cpp @@ -0,0 +1,16 @@ +// 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 "test/test_pivx.h" +#include "sapling/sodium_sanity.h" +#include + +BOOST_FIXTURE_TEST_SUITE(libsodium_consensus_tests, TestingSetup) + +BOOST_AUTO_TEST_CASE(LibsodiumPubkeyValidation) +{ + libsodium_sanity_test(); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/src/test/test_pivx.cpp b/src/test/test_pivx.cpp index b56d27c6757f0..4f5a8f37ab62e 100644 --- a/src/test/test_pivx.cpp +++ b/src/test/test_pivx.cpp @@ -17,6 +17,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" @@ -43,6 +44,7 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) BasicTestingSetup::BasicTestingSetup(const std::string& chainName) : m_path_root(fs::temp_directory_path() / "test_pivx" / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30)))) { + assert(init_and_check_sodium() != -1); ECC_Start(); SetupEnvironment(); InitSignatureCache();