diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index c89d761f1..992a9654a 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -79,10 +79,8 @@ jobs: - name: Mac OS build C++ and test if: startsWith(matrix.os, 'macos') run: | - ls -l export MACOSX_DEPLOYMENT_TARGET=10.14 mkdir -p build - ls -l build cd build cmake ../ cmake --build . -- -j 6 diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 57e9defcc..09ede6314 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -4,8 +4,8 @@ on: push: branches: - main - tags: - - '**' + release: + types: [published] pull_request: branches: - '**' @@ -45,25 +45,25 @@ jobs: cibw-build: 'cp37-*' manylinux: arm: manylinux2014 - intel: manylinux2010 + intel: manylinux2014 matrix: '3.7' - major-dot-minor: '3.8' cibw-build: 'cp38-*' manylinux: arm: manylinux2014 - intel: manylinux2010 + intel: manylinux2014 matrix: '3.8' - major-dot-minor: '3.9' cibw-build: 'cp39-*' manylinux: arm: manylinux2014 - intel: manylinux2010 + intel: manylinux2014 matrix: '3.9' - major-dot-minor: '3.10' cibw-build: 'cp310-*' manylinux: arm: manylinux2014 - intel: manylinux2010 + intel: manylinux2014 matrix: '3.10' - major-dot-minor: '3.11' cibw-build: 'cp311-*' @@ -112,6 +112,11 @@ jobs: with: fetch-depth: 0 + - name: Set Env + uses: Chia-Network/actions/setjobenv@main + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: chia-network/actions/setup-python@main with: python-version: ${{ matrix.python.major-dot-minor }} @@ -139,18 +144,13 @@ jobs: && curl -L https://github.com/Kitware/CMake/releases/download/v3.17.3/cmake-3.17.3-Linux-`uname -m`.sh > cmake.sh && yes | sh cmake.sh | cat && rm -f /usr/bin/cmake - && curl -L https://gmplib.org/download/gmp/gmp-6.2.1.tar.lz | tar x --lzip - && cp contrib/gmp-patch-6.2.1/longlong.h gmp-6.2.1/ - && cp contrib/gmp-patch-6.2.1/compat.c gmp-6.2.1/ - && cd gmp-6.2.1 && ./configure --enable-fat - && make && make install && cd .. && rm -rf gmp-6.2.1 && cmake --version && uname -a CIBW_BEFORE_BUILD_LINUX: > python -m pip install --upgrade pip CIBW_ARCHS_MACOS: ${{ matrix.os.cibw-archs-macos[matrix.arch.matrix] }} CIBW_BEFORE_ALL_MACOS: > - brew install gmp boost cmake + brew install cmake CIBW_BEFORE_BUILD_MACOS: > python -m pip install --upgrade pip CIBW_ENVIRONMENT_MACOS: "MACOSX_DEPLOYMENT_TARGET=10.14" @@ -193,6 +193,11 @@ jobs: with: fetch-depth: 0 + - name: Set Env + uses: Chia-Network/actions/setjobenv@main + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: Chia-Network/actions/setup-python@main with: python-version: ${{ matrix.python.major-dot-minor }} @@ -303,7 +308,7 @@ jobs: run: pip install twine - name: Publish distribution to PyPI - if: startsWith(github.event.ref, 'refs/tags') && steps.check_secrets.outputs.HAS_SECRET + if: env.RELEASE == 'true' && steps.check_secrets.outputs.HAS_SECRET env: TWINE_USERNAME: __token__ TWINE_NON_INTERACTIVE: 1 @@ -311,7 +316,7 @@ jobs: run: twine upload --non-interactive --skip-existing --verbose 'dist/*' - name: Publish distribution to Test PyPI - if: steps.check_secrets.outputs.HAS_SECRET + if: env.PRE_RELEASE == 'true' && steps.check_secrets.outputs.HAS_SECRET env: TWINE_REPOSITORY_URL: https://test.pypi.org/legacy/ TWINE_USERNAME: __token__ diff --git a/.github/workflows/js-bindings.yml b/.github/workflows/js-bindings.yml index 8666d086e..b82dd8cae 100644 --- a/.github/workflows/js-bindings.yml +++ b/.github/workflows/js-bindings.yml @@ -4,8 +4,8 @@ on: push: branches: - main - tags: - - '**' + release: + types: [published] pull_request: branches: - '**' @@ -23,6 +23,11 @@ jobs: with: fetch-depth: 0 + - name: Set Env + uses: Chia-Network/actions/setjobenv@main + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/setup-node@v3 with: node-version: 16 @@ -46,7 +51,7 @@ jobs: run: ./js_build.sh - name: Publish - if: startsWith(github.ref, 'refs/tags/') + if: env.FULL_RELEASE == 'true' working-directory: ${{ github.workspace }}/js_build/js-bindings env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/relic-nightly.yml b/.github/workflows/relic-nightly.yml deleted file mode 100644 index cce0e8d3f..000000000 --- a/.github/workflows/relic-nightly.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: Build and Test with Relic Nightly - -on: - schedule: - - cron: "0 11 * * *" - workflow_dispatch: - -concurrency: - # SHA is added to the end if on `main` to let all main workflows run - group: ${{ github.ref }}-${{ github.workflow }}-${{ github.event_name }}-${{ (github.ref == 'refs/heads/main') && github.sha || '' }} - cancel-in-progress: true - -jobs: - build_wheels: - name: Build and Test with Relic Nightly - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [macos-latest, ubuntu-latest] - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Ubuntu build C++ and test Relic at origin/main - if: startsWith(matrix.os, 'ubuntu') - run: | - echo "Relic origin/main commit:" - curl -H "application/vnd.github.v3.sha" \ - https://api.github.com/repos/relic-toolkit/relic/commits/main | \ - head -10 - sudo apt-get update - sudo apt-get install snap -y - sudo apt-get remove --purge cmake -y - sudo snap install cmake --classic - hash -r - cmake --version - export RELIC_MAIN=1 - mkdir -p build - cd build - cmake ../ - cmake --build . -- -j 6 - echo "Running ./src/runtest" - ./src/runtest - - - name: Mac OS build C++ and test - if: startsWith(matrix.os, 'macos') - run: | - ls -l - export MACOSX_DEPLOYMENT_TARGET=10.14 - export RELIC_MAIN=1 - mkdir -p build - ls -l build - cd build - cmake ../ - cmake --build . -- -j 6 - echo "Running ./src/runtest" - ./src/runtest - - - uses: actions/setup-python@v4 - name: Install Python - with: - python-version: '3.8' - - - name: Test pure python implementation - run: | - python python-impl/impl-test.py - - - name: Install emsdk - uses: mymindstorm/setup-emsdk@v12 - - - name: Test javascript bindings - run: | - emcc -v - export RELIC_MAIN=1 - sh emsdk_build.sh - sh js_test.sh diff --git a/.github/workflows/stale-issue.yml b/.github/workflows/stale-issue.yml old mode 100755 new mode 100644 diff --git a/.gitignore b/.gitignore index 6abe2ea06..22feb7f41 100644 --- a/.gitignore +++ b/.gitignore @@ -23,12 +23,6 @@ main .o obj/ src/*.o -contrib/relic/CTestTestfile.cmake -contrib/relic/bench/CTestTestfile.cmake -contrib/relic/bin -contrib/relic/include/relic_conf.h -contrib/relic/test/CTestTestfile.cmake -contrib/gmp-6.1.2/ .idea .vscode diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d8d1e3af..c1553c3e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,12 @@ endif() project(BLS) +if(MSVC) + enable_language(ASM_MASM) +else() + enable_language(ASM) +endif() + set(BUILD_BLS_PYTHON_BINDINGS "1" CACHE STRING "") set(BUILD_BLS_TESTS "1" CACHE STRING "") set(BUILD_BLS_BENCHMARKS "1" CACHE STRING "") @@ -33,6 +39,7 @@ include(FetchContent) FetchContent_Declare(Sodium GIT_REPOSITORY https://github.com/AmineKhaldi/libsodium-cmake.git + # Latest commit at the moment this was added here # Anchored to libsodium v1.0.18 GIT_TAG f73a3fe1afdc4e37ac5fe0ddd401bf521f6bba65 @@ -42,128 +49,17 @@ set(SODIUM_DISABLE_TESTS "on" CACHE STRING "") set(SODIUM_CHIA_MINIMAL "on" CACHE STRING "") FetchContent_MakeAvailable(Sodium) -if(DEFINED ENV{RELIC_MAIN}) - set(RELIC_GIT_TAG "origin/main") - set(RELIC_REPOSITORY "https://github.com/relic-toolkit/relic.git") -else() - # This is currently anchored to upstream aecdcae7956f542fbee2392c1f0feb0a8ac41dc5 - set(RELIC_GIT_TAG "2a4ed8ded3a9a5ac5e39f3877f357264b2e16f11") - set(RELIC_REPOSITORY "https://github.com/Chia-Network/relic.git") -endif() +set(BLST_GIT_TAG "a8cd361c9f671577aeab3f074098443af92a53fc") +set(BLST_REPOSITORY "https://github.com/supranational/blst") -message(STATUS "Relic will be built from: ${RELIC_GIT_TAG} and repository ${RELIC_REPOSITORY}") +message(STATUS "blst will be built from: ${BLST_GIT_TAG} and repository ${BLST_REPOSITORY}") FetchContent_Declare( - relic - GIT_REPOSITORY ${RELIC_REPOSITORY} - GIT_TAG ${RELIC_GIT_TAG} + blst + GIT_REPOSITORY ${BLST_REPOSITORY} + GIT_TAG ${BLST_GIT_TAG} ) - -# Relic related options - -set(STBIN "off" CACHE STRING "Relic - Build static binaries") - -if(MSVC) - set(ARITH "gmp" CACHE STRING "") - # We'll be using our custom MPIR build instead of GMP for MSVC builds - FetchContent_Declare( - chia_mpir - GIT_REPOSITORY https://github.com/Chia-Network/mpir_gc_x64.git - GIT_SHALLOW true - ) - FetchContent_MakeAvailable(chia_mpir) - set(MPIR_INCLUDE_DIR ${chia_mpir_SOURCE_DIR} CACHE STRING "") - set(MPIR_IMPLIB "${chia_mpir_SOURCE_DIR}/mpir.lib" CACHE STRING "") -else() - find_package(gmp) - if(GMP_FOUND) - message(STATUS "Found libgmp") - set(ARITH "gmp" CACHE STRING "") - else() - set(ARITH "easy" CACHE STRING "") - endif() -endif() - -if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(WSIZE "32" CACHE STRING "Relic - Processor word size") -else() - set(WSIZE "64" CACHE STRING "Relic - Processor word size") -endif() - -if(EMSCRIPTEN) - # emscripten needs arch set to be none since it can't compile assembly - set(ARCH "" CACHE STRING "") - # emscripten is a 32 bit compiler - set(WSIZE "32" CACHE STRING "Relic - Processor word size") -endif() - -if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(TIMER "ANSI" CACHE STRING "") - set(MULTI "OPENMP" CACHE STRING "") -else() - set(TIMER "CYCLE" CACHE STRING "") - set(MULTI "PTHREAD" CACHE STRING "") -endif() - -set(CHECK "off" CACHE STRING "") -set(VERBS "off" CACHE STRING "") -set(ALLOC "AUTO" CACHE STRING "") -set(SHLIB "off" CACHE STRING "") -set(DOCUM "off" CACHE STRING "") -set(FP_PRIME "381" CACHE STRING "Relic - Prime modulus size") - -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(SEED "UDEV" CACHE STRING "") - set(FP_QNRES "off" CACHE STRING "") -elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(SEED "WCGR" CACHE STRING "") - set(FP_QNRES "on" CACHE STRING "") -else() - set(SEED "UDEV" CACHE STRING "") - set(FP_QNRES "on" CACHE STRING "") -endif() - -if(DEFINED ENV{RELIC_MAIN}) - set(FP_METHD "INTEG;INTEG;INTEG;MONTY;LOWER;JMPDS;SLIDE" CACHE STRING "") - if(MSVC) - set(CFLAGS "" CACHE STRING "") - else() - set(CFLAGS "-O3 -funroll-loops -fomit-frame-pointer" CACHE STRING "") - endif() -else() - set(FP_METHD "INTEG;INTEG;INTEG;MONTY;LOWER;SLIDE" CACHE STRING "") - if(MSVC) - set(COMP_FLAGS "" CACHE STRING "") - else() - set(COMP_FLAGS "-O3 -funroll-loops -fomit-frame-pointer" CACHE STRING "") - endif() -endif() - -set(FP_PMERS "off" CACHE STRING "") -set(FPX_METHD "INTEG;INTEG;LAZYR" CACHE STRING "") -set(EP_PLAIN "off" CACHE STRING "") -set(EP_SUPER "off" CACHE STRING "") -# Disable relic tests and benchmarks -set(TESTS "0" CACHE STRING "Relic - Number of times each test is ran") -set(BENCH "0" CACHE STRING "Relic - Number of times each benchmark is ran") - -set(QUIET "on" CACHE STRING "Relic - Build with printing disabled") - -set(PP_EXT "LAZYR" CACHE STRING "") -set(PP_METHD "LAZYR;OATEP" CACHE STRING "") - -FetchContent_MakeAvailable(relic) - -function(handle_mpir_dlls _target) - file(GLOB chia_mpir_dlls ${chia_mpir_SOURCE_DIR}/*.dll) - foreach(mpir_dll IN LISTS chia_mpir_dlls) - add_custom_command( - TARGET ${_target} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${mpir_dll} $ - ) - endforeach() -endfunction() +FetchContent_MakeAvailable(blst) add_subdirectory(src) diff --git a/README.md b/README.md index 26f854aa2..a1dda3f7d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ NOTE: THIS LIBRARY IS NOT YET FORMALLY REVIEWED FOR SECURITY NOTE: THIS LIBRARY WAS SHIFTED TO THE IETF BLS SPECIFICATION ON 7/16/20 -Implements BLS signatures with aggregation using [relic toolkit](https://github.com/relic-toolkit/relic) +Implements BLS signatures with aggregation using [blst library](https://github.com/supranational/blst.git) for cryptographic primitives (pairings, EC, hashing) according to the [IETF BLS RFC](https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/) with [these curve parameters](https://datatracker.ietf.org/doc/draft-irtf-cfrg-pairing-friendly-curves/) @@ -204,14 +204,13 @@ On a 3.5 GHz i7 Mac, verification takes about 1.1ms per signature, and signing t ### Link the library to use it ```bash -g++ -Wl,-no_pie -std=c++11 -Ibls-signatures/build/_deps/relic-src/include -Ibls-signatures/build/_deps/relic-build/include -Ibls-signatures/src -L./bls-signatures/build/ -l bls yourapp.cpp +g++ -Wl,-no_pie -std=c++11 -Ibls-signatures/src -L./bls-signatures/build/ -l bls yourapp.cpp ``` ## Notes on dependencies -We use Libsodium and have GMP as an optional dependency: libsodium gives secure memory -allocation, and GMP speeds up the library by ~ 3x. MPIR is used on Windows via -GitHub Actions instead. To install them, either download them from github and +We use Libsodium which provides secure memory +allocation. To install it, either download them from github and follow the instructions for each repo, or use a package manager like APT or brew. You can follow the recipe used to build python wheels for multiple platforms in `.github/workflows/`. @@ -240,10 +239,10 @@ them with a source wheel on PyPi. MacOS ARM64 is supported but not automated due to a lack of M1 CI runners. See `.github/workflows/build.yml`. CMake uses [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) to download [pybind11](https://github.com/pybind/pybind11) for the Python -bindings and relic from a chia relic forked repository for Windows. Building +bindings. Building is then managed by [cibuildwheel](https://github.com/joerick/cibuildwheel). Further installation is then available via `pip install blspy` e.g. The ci -builds include GMP and a statically linked libsodium. +builds include a statically linked libsodium. ## Contributing and workflow @@ -288,12 +287,7 @@ the following copyright notice. >ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -## GMP license +## BLST license -GMP is distributed under the -[GNU LGPL v3 license](https://www.gnu.org/licenses/lgpl-3.0.html) - -## Relic license - -Relic is used with the -[Apache 2.0 license](https://github.com/relic-toolkit/relic/blob/master/LICENSE.Apache-2.0) +BLST is used with the +[Apache 2.0 license](https://github.com/supranational/blst/blob/master/LICENSE) diff --git a/cmake_modules/Findgmp.cmake b/cmake_modules/Findgmp.cmake deleted file mode 100644 index 16f1f8b44..000000000 --- a/cmake_modules/Findgmp.cmake +++ /dev/null @@ -1,87 +0,0 @@ -# Try to find the GMP library -# https://gmplib.org/ -# -# This module supports requiring a minimum version, e.g. you can do -# find_package(GMP 6.0.0) -# to require version 6.0.0 to newer of GMP. -# -# Once done this will define -# -# GMP_FOUND - system has GMP lib with correct version -# GMP_INCLUDES - the GMP include directory -# GMP_LIBRARIES - the GMP library -# GMP_VERSION - GMP version -# -# Copyright (c) 2016 Jack Poulson, -# Redistribution and use is allowed according to the terms of the BSD license. - -find_path(GMP_INCLUDES NAMES gmp.h PATHS $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR}) - -# Set GMP_FIND_VERSION to 5.1.0 if no minimum version is specified -if(NOT GMP_FIND_VERSION) - if(NOT GMP_FIND_VERSION_MAJOR) - set(GMP_FIND_VERSION_MAJOR 5) - endif() - if(NOT GMP_FIND_VERSION_MINOR) - set(GMP_FIND_VERSION_MINOR 1) - endif() - if(NOT GMP_FIND_VERSION_PATCH) - set(GMP_FIND_VERSION_PATCH 0) - endif() - set(GMP_FIND_VERSION - "${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}") -endif() - -message("GMP_INCLUDES=${GMP_INCLUDES}") -if(GMP_INCLUDES) - # Since the GMP version macros may be in a file included by gmp.h of the form - # gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them. - file(GLOB GMP_HEADERS "${GMP_INCLUDES}/gmp.h" "${GMP_INCLUDES}/gmp-*.h") - foreach(gmp_header_filename ${GMP_HEADERS}) - file(READ "${gmp_header_filename}" _gmp_version_header) - string(REGEX MATCH - "define[ \t]+__GNU_MP_VERSION[ \t]+([0-9]+)" _gmp_major_version_match - "${_gmp_version_header}") - if(_gmp_major_version_match) - set(GMP_MAJOR_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_MINOR[ \t]+([0-9]+)" - _gmp_minor_version_match "${_gmp_version_header}") - set(GMP_MINOR_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_PATCHLEVEL[ \t]+([0-9]+)" - _gmp_patchlevel_version_match "${_gmp_version_header}") - set(GMP_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") - set(GMP_VERSION - ${GMP_MAJOR_VERSION}.${GMP_MINOR_VERSION}.${GMP_PATCHLEVEL_VERSION}) - endif() - endforeach() - - # Check whether found version exists and exceeds the minimum requirement - if(NOT GMP_VERSION) - set(GMP_VERSION_OK FALSE) - message(STATUS "GMP version was not detected") - elseif(${GMP_VERSION} VERSION_LESS ${GMP_FIND_VERSION}) - set(GMP_VERSION_OK FALSE) - message(STATUS "GMP version ${GMP_VERSION} found in ${GMP_INCLUDES}, " - "but at least version ${GMP_FIND_VERSION} is required") - else() - set(GMP_VERSION_OK TRUE) - endif() -endif() - -if(STBIN) - set(_gmp_lib_name libgmp.a) -else() - set(_gmp_lib_name libgmp.so) -endif() - -find_library(GMP_LIBRARIES - NAMES - ${_gmp_lib_name} gmp.lib libgmp-10 libgmp gmp - PATHS - $ENV{GMPDIR} ${LIB_INSTALL_DIR} -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(gmp DEFAULT_MSG - GMP_INCLUDES GMP_LIBRARIES GMP_VERSION_OK) -mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES) diff --git a/contrib/gmp-patch-6.2.1/compat.c b/contrib/gmp-patch-6.2.1/compat.c deleted file mode 100644 index 3f563dd00..000000000 --- a/contrib/gmp-patch-6.2.1/compat.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Old function entrypoints retained for binary compatibility. - -Copyright 2000, 2001 Free Software Foundation, Inc. - -This file is part of the GNU MP Library. - -The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of either: - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at your - option) any later version. - -or - - * the GNU General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - -or both in parallel, as here. - -The GNU MP Library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received copies of the GNU General Public License and the -GNU Lesser General Public License along with the GNU MP Library. If not, -see https://www.gnu.org/licenses/. */ - -#include -#include "gmp-impl.h" - -/* RUNTIMECPUID */ -int bCheckedBMI = 0; -int bBMI1 = 0; -int bBMI2 = 0; -int bCheckedLZCNT = 0; -int bLZCNT = 0; - -/* mpn_divexact_by3 was a function in gmp 3.0.1, but as of gmp 3.1 it's a - macro calling mpn_divexact_by3c. */ -mp_limb_t -__MPN (divexact_by3) (mp_ptr dst, mp_srcptr src, mp_size_t size) -{ - return mpn_divexact_by3 (dst, src, size); -} - - -/* mpn_divmod_1 was a function in gmp 3.0.1 and earlier, but marked obsolete - in both gmp 2 and 3. As of gmp 3.1 it's a macro calling mpn_divrem_1. */ -mp_limb_t -__MPN (divmod_1) (mp_ptr dst, mp_srcptr src, mp_size_t size, mp_limb_t divisor) -{ - return mpn_divmod_1 (dst, src, size, divisor); -} - - -/* mpz_legendre was a separate function in gmp 3.1.1 and earlier, but as of - 4.0 it's a #define alias for mpz_jacobi. */ -int -__gmpz_legendre (mpz_srcptr a, mpz_srcptr b) -{ - return mpz_jacobi (a, b); -} diff --git a/contrib/gmp-patch-6.2.1/longlong.h b/contrib/gmp-patch-6.2.1/longlong.h deleted file mode 100644 index c0a746891..000000000 --- a/contrib/gmp-patch-6.2.1/longlong.h +++ /dev/null @@ -1,2355 +0,0 @@ -/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. - -Copyright 1991-1994, 1996, 1997, 1999-2005, 2007-2009, 2011-2020 Free Software -Foundation, Inc. - -This file is part of the GNU MP Library. - -The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of either: - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at your - option) any later version. - -or - - * the GNU General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - -or both in parallel, as here. - -The GNU MP Library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received copies of the GNU General Public License and the -GNU Lesser General Public License along with the GNU MP Library. If not, -see https://www.gnu.org/licenses/. */ - -/* You have to define the following before including this file: - - UWtype -- An unsigned type, default type for operations (typically a "word") - UHWtype -- An unsigned type, at least half the size of UWtype - UDWtype -- An unsigned type, at least twice as large a UWtype - W_TYPE_SIZE -- size in bits of UWtype - - SItype, USItype -- Signed and unsigned 32 bit types - DItype, UDItype -- Signed and unsigned 64 bit types - - On a 32 bit machine UWtype should typically be USItype; - on a 64 bit machine, UWtype should typically be UDItype. - - Optionally, define: - - LONGLONG_STANDALONE -- Avoid code that needs machine-dependent support files - NO_ASM -- Disable inline asm - - - CAUTION! Using this version of longlong.h outside of GMP is not safe. You - need to include gmp.h and gmp-impl.h, or certain things might not work as - expected. -*/ - -#define __BITS4 (W_TYPE_SIZE / 4) -#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) -#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) -#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) - -/* This is used to make sure no undesirable sharing between different libraries - that use this file takes place. */ -#ifndef __MPN -#define __MPN(x) __##x -#endif - -/* Define auxiliary asm macros. - - 1) umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two - UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype - word product in HIGH_PROD and LOW_PROD. - - 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a - UDWtype product. This is just a variant of umul_ppmm. - - 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, - denominator) divides a UDWtype, composed by the UWtype integers - HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient - in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less - than DENOMINATOR for correct operation. If, in addition, the most - significant bit of DENOMINATOR must be 1, then the pre-processor symbol - UDIV_NEEDS_NORMALIZATION is defined to 1. - - 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, - denominator). Like udiv_qrnnd but the numbers are signed. The quotient - is rounded towards 0. - - 5) count_leading_zeros(count, x) counts the number of zero-bits from the - msb to the first non-zero bit in the UWtype X. This is the number of - steps X needs to be shifted left to set the msb. Undefined for X == 0, - unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. - - 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts - from the least significant end. - - 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, - high_addend_2, low_addend_2) adds two UWtype integers, composed by - HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 - respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow - (i.e. carry out) is not stored anywhere, and is lost. - - 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, - high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, - composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and - LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE - and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, - and is lost. - - If any of these macros are left undefined for a particular CPU, - C macros are used. - - - Notes: - - For add_ssaaaa the two high and two low addends can both commute, but - unfortunately gcc only supports one "%" commutative in each asm block. - This has always been so but is only documented in recent versions - (eg. pre-release 3.3). Having two or more "%"s can cause an internal - compiler error in certain rare circumstances. - - Apparently it was only the last "%" that was ever actually respected, so - the code has been updated to leave just that. Clearly there's a free - choice whether high or low should get it, if there's a reason to favour - one over the other. Also obviously when the constraints on the two - operands are identical there's no benefit to the reloader in any "%" at - all. - - */ - -/* The CPUs come in alphabetical order below. - - Please add support for more CPUs here, or improve the current support - for the CPUs below! */ - - -/* count_leading_zeros_gcc_clz is count_leading_zeros implemented with gcc - 3.4 __builtin_clzl or __builtin_clzll, according to our limb size. - Similarly count_trailing_zeros_gcc_ctz using __builtin_ctzl or - __builtin_ctzll. - - These builtins are only used when we check what code comes out, on some - chips they're merely libgcc calls, where we will instead want an inline - in that case (either asm or generic C). - - These builtins are better than an asm block of the same insn, since an - asm block doesn't give gcc any information about scheduling or resource - usage. We keep an asm block for use on prior versions of gcc though. - - For reference, __builtin_ffs existed in gcc prior to __builtin_clz, but - it's not used (for count_leading_zeros) because it generally gives extra - code to ensure the result is 0 when the input is 0, which we don't need - or want. */ - -#ifdef _LONG_LONG_LIMB -#define count_leading_zeros_gcc_clz(count,x) \ - do { \ - ASSERT ((x) != 0); \ - (count) = __builtin_clzll (x); \ - } while (0) -#else -#define count_leading_zeros_gcc_clz(count,x) \ - do { \ - ASSERT ((x) != 0); \ - (count) = __builtin_clzl (x); \ - } while (0) -#endif - -#ifdef _LONG_LONG_LIMB -#define count_trailing_zeros_gcc_ctz(count,x) \ - do { \ - ASSERT ((x) != 0); \ - (count) = __builtin_ctzll (x); \ - } while (0) -#else -#define count_trailing_zeros_gcc_ctz(count,x) \ - do { \ - ASSERT ((x) != 0); \ - (count) = __builtin_ctzl (x); \ - } while (0) -#endif - - -/* FIXME: The macros using external routines like __MPN(count_leading_zeros) - don't need to be under !NO_ASM */ -#if ! defined (NO_ASM) - -#if defined (__alpha) && W_TYPE_SIZE == 64 -/* Most alpha-based machines, except Cray systems. */ -#if defined (__GNUC__) -#if __GMP_GNUC_PREREQ (3,3) -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - UDItype __m0 = (m0), __m1 = (m1); \ - (ph) = __builtin_alpha_umulh (__m0, __m1); \ - (pl) = __m0 * __m1; \ - } while (0) -#else -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - UDItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("umulh %r1,%2,%0" \ - : "=r" (ph) \ - : "%rJ" (__m0), "rI" (__m1)); \ - (pl) = __m0 * __m1; \ - } while (0) -#endif -#else /* ! __GNUC__ */ -#include -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - UDItype __m0 = (m0), __m1 = (m1); \ - (ph) = __UMULH (__m0, __m1); \ - (pl) = __m0 * __m1; \ - } while (0) -#endif -#ifndef LONGLONG_STANDALONE -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { UWtype __di; \ - __di = __MPN(invert_limb) (d); \ - udiv_qrnnd_preinv (q, r, n1, n0, d, __di); \ - } while (0) -#define UDIV_PREINV_ALWAYS 1 -#define UDIV_NEEDS_NORMALIZATION 1 -#endif /* LONGLONG_STANDALONE */ - -/* clz_tab is required in all configurations, since mpn/alpha/cntlz.asm - always goes into libgmp.so, even when not actually used. */ -#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB - -#if defined (__GNUC__) && HAVE_HOST_CPU_alpha_CIX -#define count_leading_zeros(COUNT,X) \ - __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X)) -#define count_trailing_zeros(COUNT,X) \ - __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X)) -#endif /* clz/ctz using cix */ - -#if ! defined (count_leading_zeros) \ - && defined (__GNUC__) && ! defined (LONGLONG_STANDALONE) -/* ALPHA_CMPBGE_0 gives "cmpbge $31,src,dst", ie. test src bytes == 0. - "$31" is written explicitly in the asm, since an "r" constraint won't - select reg 31. There seems no need to worry about "r31" syntax for cray, - since gcc itself (pre-release 3.4) emits just $31 in various places. */ -#define ALPHA_CMPBGE_0(dst, src) \ - do { asm ("cmpbge $31, %1, %0" : "=r" (dst) : "r" (src)); } while (0) -/* Zero bytes are turned into bits with cmpbge, a __clz_tab lookup counts - them, locating the highest non-zero byte. A second __clz_tab lookup - counts the leading zero bits in that byte, giving the result. */ -#define count_leading_zeros(count, x) \ - do { \ - UWtype __clz__b, __clz__c, __clz__x = (x); \ - ALPHA_CMPBGE_0 (__clz__b, __clz__x); /* zero bytes */ \ - __clz__b = __clz_tab [(__clz__b >> 1) ^ 0x7F]; /* 8 to 1 byte */ \ - __clz__b = __clz__b * 8 - 7; /* 57 to 1 shift */ \ - __clz__x >>= __clz__b; \ - __clz__c = __clz_tab [__clz__x]; /* 8 to 1 bit */ \ - __clz__b = 65 - __clz__b; \ - (count) = __clz__b - __clz__c; \ - } while (0) -#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB -#endif /* clz using cmpbge */ - -#if ! defined (count_leading_zeros) && ! defined (LONGLONG_STANDALONE) -#if HAVE_ATTRIBUTE_CONST -long __MPN(count_leading_zeros) (UDItype) __attribute__ ((const)); -#else -long __MPN(count_leading_zeros) (UDItype); -#endif -#define count_leading_zeros(count, x) \ - ((count) = __MPN(count_leading_zeros) (x)) -#endif /* clz using mpn */ -#endif /* __alpha */ - -#if defined (__AVR) && W_TYPE_SIZE == 8 -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - unsigned short __p = (unsigned short) (m0) * (m1); \ - (ph) = __p >> 8; \ - (pl) = __p; \ - } while (0) -#endif /* AVR */ - -#if defined (_CRAY) && W_TYPE_SIZE == 64 -#include -#define UDIV_PREINV_ALWAYS 1 -#define UDIV_NEEDS_NORMALIZATION 1 -long __MPN(count_leading_zeros) (UDItype); -#define count_leading_zeros(count, x) \ - ((count) = _leadz ((UWtype) (x))) -#if defined (_CRAYIEEE) /* I.e., Cray T90/ieee, T3D, and T3E */ -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - UDItype __m0 = (m0), __m1 = (m1); \ - (ph) = _int_mult_upper (__m0, __m1); \ - (pl) = __m0 * __m1; \ - } while (0) -#ifndef LONGLONG_STANDALONE -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { UWtype __di; \ - __di = __MPN(invert_limb) (d); \ - udiv_qrnnd_preinv (q, r, n1, n0, d, __di); \ - } while (0) -#endif /* LONGLONG_STANDALONE */ -#endif /* _CRAYIEEE */ -#endif /* _CRAY */ - -#if defined (__ia64) && W_TYPE_SIZE == 64 -/* This form encourages gcc (pre-release 3.4 at least) to emit predicated - "sub r=r,r" and "sub r=r,r,1", giving a 2 cycle latency. The generic - code using "al>= _c; \ - if (_x >= 1 << 4) \ - _x >>= 4, _c += 4; \ - if (_x >= 1 << 2) \ - _x >>= 2, _c += 2; \ - _c += _x >> 1; \ - (count) = W_TYPE_SIZE - 1 - _c; \ - } while (0) -/* similar to what gcc does for __builtin_ffs, but 0 based rather than 1 - based, and we don't need a special case for x==0 here */ -#define count_trailing_zeros(count, x) \ - do { \ - UWtype __ctz_x = (x); \ - __asm__ ("popcnt %0 = %1" \ - : "=r" (count) \ - : "r" ((__ctz_x-1) & ~__ctz_x)); \ - } while (0) -#endif -#if defined (__INTEL_COMPILER) -#include -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - UWtype __m0 = (m0), __m1 = (m1); \ - ph = _m64_xmahu (__m0, __m1, 0); \ - pl = __m0 * __m1; \ - } while (0) -#endif -#ifndef LONGLONG_STANDALONE -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { UWtype __di; \ - __di = __MPN(invert_limb) (d); \ - udiv_qrnnd_preinv (q, r, n1, n0, d, __di); \ - } while (0) -#define UDIV_PREINV_ALWAYS 1 -#define UDIV_NEEDS_NORMALIZATION 1 -#endif -#endif - - -#if defined (__GNUC__) - -/* We sometimes need to clobber "cc" with gcc2, but that would not be - understood by gcc1. Use cpp to avoid major code duplication. */ -#if __GNUC__ < 2 -#define __CLOBBER_CC -#define __AND_CLOBBER_CC -#else /* __GNUC__ >= 2 */ -#define __CLOBBER_CC : "cc" -#define __AND_CLOBBER_CC , "cc" -#endif /* __GNUC__ < 2 */ - -#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add %1,%4,%5\n\taddc %0,%2,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "rI" (bh), "%r" (al), "rI" (bl)) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub %1,%4,%5\n\tsubc %0,%2,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "rI" (bh), "r" (al), "rI" (bl)) -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - USItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("multiplu %0,%1,%2" \ - : "=r" (xl) \ - : "r" (__m0), "r" (__m1)); \ - __asm__ ("multmu %0,%1,%2" \ - : "=r" (xh) \ - : "r" (__m0), "r" (__m1)); \ - } while (0) -#define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("dividu %0,%3,%4" \ - : "=r" (q), "=q" (r) \ - : "1" (n1), "r" (n0), "r" (d)) -#define count_leading_zeros(count, x) \ - __asm__ ("clz %0,%1" \ - : "=r" (count) \ - : "r" (x)) -#define COUNT_LEADING_ZEROS_0 32 -#endif /* __a29k__ */ - -#if defined (__arc__) -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add.f\t%1, %4, %5\n\tadc\t%0, %2, %3" \ - : "=r" (sh), \ - "=&r" (sl) \ - : "r" ((USItype) (ah)), \ - "rICal" ((USItype) (bh)), \ - "%r" ((USItype) (al)), \ - "rICal" ((USItype) (bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub.f\t%1, %4, %5\n\tsbc\t%0, %2, %3" \ - : "=r" (sh), \ - "=&r" (sl) \ - : "r" ((USItype) (ah)), \ - "rICal" ((USItype) (bh)), \ - "r" ((USItype) (al)), \ - "rICal" ((USItype) (bl))) -#endif - -#if defined (__arm__) && (defined (__thumb2__) || !defined (__thumb__)) \ - && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (bl) && -(USItype)(bl) < (USItype)(bl)) \ - __asm__ ("subs\t%1, %4, %5\n\tadc\t%0, %2, %3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "rI" (bh), \ - "%r" (al), "rI" (-(USItype)(bl)) __CLOBBER_CC); \ - else \ - __asm__ ("adds\t%1, %4, %5\n\tadc\t%0, %2, %3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "rI" (bh), "%r" (al), "rI" (bl) __CLOBBER_CC); \ - } while (0) -/* FIXME: Extend the immediate range for the low word by using both ADDS and - SUBS, since they set carry in the same way. We need separate definitions - for thumb and non-thumb since thumb lacks RSC. */ -#if defined (__thumb__) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (ah) && __builtin_constant_p (bh) \ - && (ah) == (bh)) \ - __asm__ ("subs\t%1, %2, %3\n\tsbc\t%0, %0, %0" \ - : "=r" (sh), "=r" (sl) \ - : "r" (al), "rI" (bl) __CLOBBER_CC); \ - else if (__builtin_constant_p (al)) \ - __asm__ ("rsbs\t%1, %5, %4\n\tsbc\t%0, %2, %3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "rI" (bh), "rI" (al), "r" (bl) __CLOBBER_CC); \ - else if (__builtin_constant_p (bl)) \ - __asm__ ("subs\t%1, %4, %5\n\tsbc\t%0, %2, %3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "rI" (bh), "r" (al), "rI" (bl) __CLOBBER_CC); \ - else \ - __asm__ ("subs\t%1, %4, %5\n\tsbc\t%0, %2, %3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "rI" (bh), "r" (al), "rI" (bl) __CLOBBER_CC); \ - } while (0) -#else -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (ah) && __builtin_constant_p (bh) \ - && (ah) == (bh)) \ - __asm__ ("subs\t%1, %2, %3\n\tsbc\t%0, %0, %0" \ - : "=r" (sh), "=r" (sl) \ - : "r" (al), "rI" (bl) __CLOBBER_CC); \ - else if (__builtin_constant_p (al)) \ - { \ - if (__builtin_constant_p (ah)) \ - __asm__ ("rsbs\t%1, %5, %4\n\trsc\t%0, %3, %2" \ - : "=r" (sh), "=&r" (sl) \ - : "rI" (ah), "r" (bh), "rI" (al), "r" (bl) __CLOBBER_CC); \ - else \ - __asm__ ("rsbs\t%1, %5, %4\n\tsbc\t%0, %2, %3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "rI" (bh), "rI" (al), "r" (bl) __CLOBBER_CC); \ - } \ - else if (__builtin_constant_p (ah)) \ - { \ - if (__builtin_constant_p (bl)) \ - __asm__ ("subs\t%1, %4, %5\n\trsc\t%0, %3, %2" \ - : "=r" (sh), "=&r" (sl) \ - : "rI" (ah), "r" (bh), "r" (al), "rI" (bl) __CLOBBER_CC); \ - else \ - __asm__ ("rsbs\t%1, %5, %4\n\trsc\t%0, %3, %2" \ - : "=r" (sh), "=&r" (sl) \ - : "rI" (ah), "r" (bh), "rI" (al), "r" (bl) __CLOBBER_CC); \ - } \ - else if (__builtin_constant_p (bl)) \ - __asm__ ("subs\t%1, %4, %5\n\tsbc\t%0, %2, %3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "rI" (bh), "r" (al), "rI" (bl) __CLOBBER_CC); \ - else \ - __asm__ ("subs\t%1, %4, %5\n\tsbc\t%0, %2, %3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "rI" (bh), "r" (al), "rI" (bl) __CLOBBER_CC); \ - } while (0) -#endif -#if defined (__ARM_ARCH_2__) || defined (__ARM_ARCH_2A__) \ - || defined (__ARM_ARCH_3__) -#define umul_ppmm(xh, xl, a, b) \ - do { \ - register USItype __t0, __t1, __t2; \ - __asm__ ("%@ Inlined umul_ppmm\n" \ - " mov %2, %5, lsr #16\n" \ - " mov %0, %6, lsr #16\n" \ - " bic %3, %5, %2, lsl #16\n" \ - " bic %4, %6, %0, lsl #16\n" \ - " mul %1, %3, %4\n" \ - " mul %4, %2, %4\n" \ - " mul %3, %0, %3\n" \ - " mul %0, %2, %0\n" \ - " adds %3, %4, %3\n" \ - " addcs %0, %0, #65536\n" \ - " adds %1, %1, %3, lsl #16\n" \ - " adc %0, %0, %3, lsr #16" \ - : "=&r" ((USItype) (xh)), "=r" ((USItype) (xl)), \ - "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ - : "r" ((USItype) (a)), "r" ((USItype) (b)) __CLOBBER_CC); \ - } while (0) -#ifndef LONGLONG_STANDALONE -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { UWtype __r; \ - (q) = __MPN(udiv_qrnnd) (&__r, (n1), (n0), (d)); \ - (r) = __r; \ - } while (0) -extern UWtype __MPN(udiv_qrnnd) (UWtype *, UWtype, UWtype, UWtype); -#endif /* LONGLONG_STANDALONE */ -#else /* ARMv4 or newer */ -#define umul_ppmm(xh, xl, a, b) \ - __asm__ ("umull %0,%1,%2,%3" : "=&r" (xl), "=&r" (xh) : "r" (a), "r" (b)) -#define smul_ppmm(xh, xl, a, b) \ - __asm__ ("smull %0,%1,%2,%3" : "=&r" (xl), "=&r" (xh) : "r" (a), "r" (b)) -#ifndef LONGLONG_STANDALONE -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { UWtype __di; \ - __di = __MPN(invert_limb) (d); \ - udiv_qrnnd_preinv (q, r, n1, n0, d, __di); \ - } while (0) -#define UDIV_PREINV_ALWAYS 1 -#define UDIV_NEEDS_NORMALIZATION 1 -#endif /* LONGLONG_STANDALONE */ -#endif /* defined(__ARM_ARCH_2__) ... */ -#define count_leading_zeros(count, x) count_leading_zeros_gcc_clz(count, x) -#define count_trailing_zeros(count, x) count_trailing_zeros_gcc_ctz(count, x) -#endif /* __arm__ */ - -#if defined (__aarch64__) && W_TYPE_SIZE == 64 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (bl) && ~(UDItype)(bl) <= (UDItype)(bl)) \ - __asm__ ("subs\t%1, %x4, %5\n\tadc\t%0, %x2, %x3" \ - : "=r" (sh), "=&r" (sl) \ - : "rZ" ((UDItype)(ah)), "rZ" ((UDItype)(bh)), \ - "%r" ((UDItype)(al)), "rI" (-(UDItype)(bl)) __CLOBBER_CC);\ - else \ - __asm__ ("adds\t%1, %x4, %5\n\tadc\t%0, %x2, %x3" \ - : "=r" (sh), "=&r" (sl) \ - : "rZ" ((UDItype)(ah)), "rZ" ((UDItype)(bh)), \ - "%r" ((UDItype)(al)), "rI" ((UDItype)(bl)) __CLOBBER_CC);\ - } while (0) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (bl) && ~(UDItype)(bl) <= (UDItype)(bl)) \ - __asm__ ("adds\t%1, %x4, %5\n\tsbc\t%0, %x2, %x3" \ - : "=r,r" (sh), "=&r,&r" (sl) \ - : "rZ,rZ" ((UDItype)(ah)), "rZ,rZ" ((UDItype)(bh)), \ - "r,Z" ((UDItype)(al)), "rI,r" (-(UDItype)(bl)) __CLOBBER_CC);\ - else \ - __asm__ ("subs\t%1, %x4, %5\n\tsbc\t%0, %x2, %x3" \ - : "=r,r" (sh), "=&r,&r" (sl) \ - : "rZ,rZ" ((UDItype)(ah)), "rZ,rZ" ((UDItype)(bh)), \ - "r,Z" ((UDItype)(al)), "rI,r" ((UDItype)(bl)) __CLOBBER_CC);\ - } while(0); -#if __GMP_GNUC_PREREQ (4,9) -#define umul_ppmm(w1, w0, u, v) \ - do { \ - typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ - __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \ - w1 = __ll >> 64; \ - w0 = __ll; \ - } while (0) -#endif -#if !defined (umul_ppmm) -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - UDItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("umulh\t%0, %1, %2" : "=r" (ph) : "r" (__m0), "r" (__m1)); \ - (pl) = __m0 * __m1; \ - } while (0) -#endif -#define count_leading_zeros(count, x) count_leading_zeros_gcc_clz(count, x) -#define count_trailing_zeros(count, x) count_trailing_zeros_gcc_ctz(count, x) -#endif /* __aarch64__ */ - -#if defined (__clipper__) && W_TYPE_SIZE == 32 -#define umul_ppmm(w1, w0, u, v) \ - ({union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __x; \ - __asm__ ("mulwux %2,%0" \ - : "=r" (__x.__ll) \ - : "%0" ((USItype)(u)), "r" ((USItype)(v))); \ - (w1) = __x.__i.__h; (w0) = __x.__i.__l;}) -#define smul_ppmm(w1, w0, u, v) \ - ({union {DItype __ll; \ - struct {SItype __l, __h;} __i; \ - } __x; \ - __asm__ ("mulwx %2,%0" \ - : "=r" (__x.__ll) \ - : "%0" ((SItype)(u)), "r" ((SItype)(v))); \ - (w1) = __x.__i.__h; (w0) = __x.__i.__l;}) -#define __umulsidi3(u, v) \ - ({UDItype __w; \ - __asm__ ("mulwux %2,%0" \ - : "=r" (__w) : "%0" ((USItype)(u)), "r" ((USItype)(v))); \ - __w; }) -#endif /* __clipper__ */ - -/* Fujitsu vector computers. */ -#if defined (__uxp__) && W_TYPE_SIZE == 32 -#define umul_ppmm(ph, pl, u, v) \ - do { \ - union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __asm__ ("mult.lu %1,%2,%0" : "=r" (__x.__ll) : "%r" (u), "rK" (v));\ - (ph) = __x.__i.__h; \ - (pl) = __x.__i.__l; \ - } while (0) -#define smul_ppmm(ph, pl, u, v) \ - do { \ - union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __asm__ ("mult.l %1,%2,%0" : "=r" (__x.__ll) : "%r" (u), "rK" (v)); \ - (ph) = __x.__i.__h; \ - (pl) = __x.__i.__l; \ - } while (0) -#endif - -#if defined (__gmicro__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add.w %5,%1\n\taddx %3,%0" \ - : "=g" (sh), "=&g" (sl) \ - : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ - "%1" ((USItype)(al)), "g" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub.w %5,%1\n\tsubx %3,%0" \ - : "=g" (sh), "=&g" (sl) \ - : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ - "1" ((USItype)(al)), "g" ((USItype)(bl))) -#define umul_ppmm(ph, pl, m0, m1) \ - __asm__ ("mulx %3,%0,%1" \ - : "=g" (ph), "=r" (pl) \ - : "%0" ((USItype)(m0)), "g" ((USItype)(m1))) -#define udiv_qrnnd(q, r, nh, nl, d) \ - __asm__ ("divx %4,%0,%1" \ - : "=g" (q), "=r" (r) \ - : "1" ((USItype)(nh)), "0" ((USItype)(nl)), "g" ((USItype)(d))) -#define count_leading_zeros(count, x) \ - __asm__ ("bsch/1 %1,%0" \ - : "=g" (count) : "g" ((USItype)(x)), "0" ((USItype)0)) -#endif - -#if defined (__hppa) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add%I5 %5,%r4,%1\n\taddc %r2,%r3,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "rM" (ah), "rM" (bh), "%rM" (al), "rI" (bl)) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub%I4 %4,%r5,%1\n\tsubb %r2,%r3,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "rM" (ah), "rM" (bh), "rI" (al), "rM" (bl)) -#if defined (_PA_RISC1_1) -#define umul_ppmm(wh, wl, u, v) \ - do { \ - union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __asm__ ("xmpyu %1,%2,%0" : "=*f" (__x.__ll) : "*f" (u), "*f" (v)); \ - (wh) = __x.__i.__h; \ - (wl) = __x.__i.__l; \ - } while (0) -#endif -#define count_leading_zeros(count, x) \ - do { \ - USItype __tmp; \ - __asm__ ( \ - "ldi 1,%0\n" \ -" extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ -" extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ -" ldo 16(%0),%0 ; Yes. Perform add.\n" \ -" extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ -" extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ -" ldo 8(%0),%0 ; Yes. Perform add.\n" \ -" extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ -" extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ -" ldo 4(%0),%0 ; Yes. Perform add.\n" \ -" extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ -" extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ -" ldo 2(%0),%0 ; Yes. Perform add.\n" \ -" extru %1,30,1,%1 ; Extract bit 1.\n" \ -" sub %0,%1,%0 ; Subtract it.\n" \ - : "=r" (count), "=r" (__tmp) : "1" (x)); \ - } while (0) -#endif /* hppa */ - -/* These macros are for ABI=2.0w. In ABI=2.0n they can't be used, since GCC - (3.2) puts longlong into two adjacent 32-bit registers. Presumably this - is just a case of no direct support for 2.0n but treating it like 1.0. */ -#if defined (__hppa) && W_TYPE_SIZE == 64 && ! defined (_LONG_LONG_LIMB) -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add%I5 %5,%r4,%1\n\tadd,dc %r2,%r3,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "rM" (ah), "rM" (bh), "%rM" (al), "rI" (bl)) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub%I4 %4,%r5,%1\n\tsub,db %r2,%r3,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "rM" (ah), "rM" (bh), "rI" (al), "rM" (bl)) -#endif /* hppa */ - -#if (defined (__i370__) || defined (__s390__) || defined (__mvs__)) && W_TYPE_SIZE == 32 -#if defined (__zarch__) || defined (HAVE_HOST_CPU_s390_zarch) -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ -/* if (__builtin_constant_p (bl)) \ - __asm__ ("alfi\t%1,%o5\n\talcr\t%0,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "0" (ah), "r" (bh), "%1" (al), "n" (bl) __CLOBBER_CC);\ - else \ -*/ __asm__ ("alr\t%1,%5\n\talcr\t%0,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "0" (ah), "r" (bh), "%1" (al), "r" (bl)__CLOBBER_CC); \ - } while (0) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ -/* if (__builtin_constant_p (bl)) \ - __asm__ ("slfi\t%1,%o5\n\tslbr\t%0,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "0" (ah), "r" (bh), "1" (al), "n" (bl) __CLOBBER_CC); \ - else \ -*/ __asm__ ("slr\t%1,%5\n\tslbr\t%0,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "0" (ah), "r" (bh), "1" (al), "r" (bl) __CLOBBER_CC); \ - } while (0) -#if __GMP_GNUC_PREREQ (4,5) -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __x.__ll = (UDItype) (m0) * (UDItype) (m1); \ - (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ - } while (0) -#else -#if 0 -/* FIXME: this fails if gcc knows about the 64-bit registers. Use only - with a new enough processor pretending we have 32-bit registers. */ -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __asm__ ("mlr\t%0,%2" \ - : "=r" (__x.__ll) \ - : "%0" (m0), "r" (m1)); \ - (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ - } while (0) -#else -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - /* When we have 64-bit regs and gcc is aware of that, we cannot simply use - DImode for the product, since that would be allocated to a single 64-bit - register, whereas mlr uses the low 32-bits of an even-odd register pair. - */ \ - register USItype __r0 __asm__ ("0"); \ - register USItype __r1 __asm__ ("1") = (m0); \ - __asm__ ("mlr\t%0,%3" \ - : "=r" (__r0), "=r" (__r1) \ - : "r" (__r1), "r" (m1)); \ - (xh) = __r0; (xl) = __r1; \ - } while (0) -#endif /* if 0 */ -#endif -#if 0 -/* FIXME: this fails if gcc knows about the 64-bit registers. Use only - with a new enough processor pretending we have 32-bit registers. */ -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { \ - union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __x.__i.__h = n1; __x.__i.__l = n0; \ - __asm__ ("dlr\t%0,%2" \ - : "=r" (__x.__ll) \ - : "0" (__x.__ll), "r" (d)); \ - (q) = __x.__i.__l; (r) = __x.__i.__h; \ - } while (0) -#else -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { \ - register USItype __r0 __asm__ ("0") = (n1); \ - register USItype __r1 __asm__ ("1") = (n0); \ - __asm__ ("dlr\t%0,%4" \ - : "=r" (__r0), "=r" (__r1) \ - : "r" (__r0), "r" (__r1), "r" (d)); \ - (q) = __r1; (r) = __r0; \ - } while (0) -#endif /* if 0 */ -#else /* if __zarch__ */ -/* FIXME: this fails if gcc knows about the 64-bit registers. */ -#define smul_ppmm(xh, xl, m0, m1) \ - do { \ - union {DItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __asm__ ("mr\t%0,%2" \ - : "=r" (__x.__ll) \ - : "%0" (m0), "r" (m1)); \ - (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ - } while (0) -/* FIXME: this fails if gcc knows about the 64-bit registers. */ -#define sdiv_qrnnd(q, r, n1, n0, d) \ - do { \ - union {DItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __x.__i.__h = n1; __x.__i.__l = n0; \ - __asm__ ("dr\t%0,%2" \ - : "=r" (__x.__ll) \ - : "0" (__x.__ll), "r" (d)); \ - (q) = __x.__i.__l; (r) = __x.__i.__h; \ - } while (0) -#endif /* if __zarch__ */ -#endif - -#if defined (__s390x__) && W_TYPE_SIZE == 64 -/* We need to cast operands with register constraints, otherwise their types - will be assumed to be SImode by gcc. For these machines, such operations - will insert a value into the low 32 bits, and leave the high 32 bits with - garbage. */ -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ - __asm__ ("algr\t%1,%5\n\talcgr\t%0,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((UDItype)(ah)), "r" ((UDItype)(bh)), \ - "%1" ((UDItype)(al)), "r" ((UDItype)(bl)) __CLOBBER_CC); \ - } while (0) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - __asm__ ("slgr\t%1,%5\n\tslbgr\t%0,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((UDItype)(ah)), "r" ((UDItype)(bh)), \ - "1" ((UDItype)(al)), "r" ((UDItype)(bl)) __CLOBBER_CC); \ - } while (0) -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - union {unsigned int __attribute__ ((mode(TI))) __ll; \ - struct {UDItype __h, __l;} __i; \ - } __x; \ - __asm__ ("mlgr\t%0,%2" \ - : "=r" (__x.__ll) \ - : "%0" ((UDItype)(m0)), "r" ((UDItype)(m1))); \ - (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ - } while (0) -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { \ - union {unsigned int __attribute__ ((mode(TI))) __ll; \ - struct {UDItype __h, __l;} __i; \ - } __x; \ - __x.__i.__h = n1; __x.__i.__l = n0; \ - __asm__ ("dlgr\t%0,%2" \ - : "=r" (__x.__ll) \ - : "0" (__x.__ll), "r" ((UDItype)(d))); \ - (q) = __x.__i.__l; (r) = __x.__i.__h; \ - } while (0) -#if 0 /* FIXME: Enable for z10 (?) */ -#define count_leading_zeros(cnt, x) \ - do { \ - union {unsigned int __attribute__ ((mode(TI))) __ll; \ - struct {UDItype __h, __l;} __i; \ - } __clr_cnt; \ - __asm__ ("flogr\t%0,%1" \ - : "=r" (__clr_cnt.__ll) \ - : "r" (x) __CLOBBER_CC); \ - (cnt) = __clr_cnt.__i.__h; \ - } while (0) -#endif -#endif - -/* On x86 and x86_64, every asm implicitly clobbers "flags" and "fpsr", - so we don't need __CLOBBER_CC. */ -#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addl %5,%k1\n\tadcl %3,%k0" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ - "%1" ((USItype)(al)), "g" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subl %5,%k1\n\tsbbl %3,%k0" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ - "1" ((USItype)(al)), "g" ((USItype)(bl))) -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("mull %3" \ - : "=a" (w0), "=d" (w1) \ - : "%0" ((USItype)(u)), "rm" ((USItype)(v))) -#define udiv_qrnnd(q, r, n1, n0, dx) /* d renamed to dx avoiding "=d" */\ - __asm__ ("divl %4" /* stringification in K&R C */ \ - : "=a" (q), "=d" (r) \ - : "0" ((USItype)(n0)), "1" ((USItype)(n1)), "rm" ((USItype)(dx))) - -#if HAVE_HOST_CPU_i586 || HAVE_HOST_CPU_pentium || HAVE_HOST_CPU_pentiummmx -/* Pentium bsrl takes between 10 and 72 cycles depending where the most - significant 1 bit is, hence the use of the following alternatives. bsfl - is slow too, between 18 and 42 depending where the least significant 1 - bit is, so let the generic count_trailing_zeros below make use of the - count_leading_zeros here too. */ - -#if HAVE_HOST_CPU_pentiummmx && ! defined (LONGLONG_STANDALONE) -/* The following should be a fixed 14 or 15 cycles, but possibly plus an L1 - cache miss reading from __clz_tab. For P55 it's favoured over the float - below so as to avoid mixing MMX and x87, since the penalty for switching - between the two is about 100 cycles. - - The asm block sets __shift to -3 if the high 24 bits are clear, -2 for - 16, -1 for 8, or 0 otherwise. This could be written equivalently as - follows, but as of gcc 2.95.2 it results in conditional jumps. - - __shift = -(__n < 0x1000000); - __shift -= (__n < 0x10000); - __shift -= (__n < 0x100); - - The middle two sbbl and cmpl's pair, and with luck something gcc - generates might pair with the first cmpl and the last sbbl. The "32+1" - constant could be folded into __clz_tab[], but it doesn't seem worth - making a different table just for that. */ - -#define count_leading_zeros(c,n) \ - do { \ - USItype __n = (n); \ - USItype __shift; \ - __asm__ ("cmpl $0x1000000, %1\n" \ - "sbbl %0, %0\n" \ - "cmpl $0x10000, %1\n" \ - "sbbl $0, %0\n" \ - "cmpl $0x100, %1\n" \ - "sbbl $0, %0\n" \ - : "=&r" (__shift) : "r" (__n)); \ - __shift = __shift*8 + 24 + 1; \ - (c) = 32 + 1 - __shift - __clz_tab[__n >> __shift]; \ - } while (0) -#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB -#define COUNT_LEADING_ZEROS_0 31 /* n==0 indistinguishable from n==1 */ - -#else /* ! pentiummmx || LONGLONG_STANDALONE */ -/* The following should be a fixed 14 cycles or so. Some scheduling - opportunities should be available between the float load/store too. This - sort of code is used in gcc 3 for __builtin_ffs (with "n&-n") and is - apparently suggested by the Intel optimizing manual (don't know exactly - where). gcc 2.95 or up will be best for this, so the "double" is - correctly aligned on the stack. */ -#define count_leading_zeros(c,n) \ - do { \ - union { \ - double d; \ - unsigned a[2]; \ - } __u; \ - __u.d = (UWtype) (n); \ - (c) = 0x3FF + 31 - (__u.a[1] >> 20); \ - } while (0) -#define COUNT_LEADING_ZEROS_0 (0x3FF + 31) -#endif /* pentiummx */ - -#else /* ! pentium */ - -#if __GMP_GNUC_PREREQ (3,4) /* using bsrl */ -#define count_leading_zeros(count,x) count_leading_zeros_gcc_clz(count,x) -#endif /* gcc clz */ - -/* On P6, gcc prior to 3.0 generates a partial register stall for - __cbtmp^31, due to using "xorb $31" instead of "xorl $31", the former - being 1 code byte smaller. "31-__cbtmp" is a workaround, probably at the - cost of one extra instruction. Do this for "i386" too, since that means - generic x86. */ -#if ! defined (count_leading_zeros) && __GNUC__ < 3 \ - && (HAVE_HOST_CPU_i386 \ - || HAVE_HOST_CPU_i686 \ - || HAVE_HOST_CPU_pentiumpro \ - || HAVE_HOST_CPU_pentium2 \ - || HAVE_HOST_CPU_pentium3) -#define count_leading_zeros(count, x) \ - do { \ - USItype __cbtmp; \ - ASSERT ((x) != 0); \ - __asm__ ("bsrl %1,%0" : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ - (count) = 31 - __cbtmp; \ - } while (0) -#endif /* gcc<3 asm bsrl */ - -#ifndef count_leading_zeros -#define count_leading_zeros(count, x) \ - do { \ - USItype __cbtmp; \ - ASSERT ((x) != 0); \ - __asm__ ("bsrl %1,%0" : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ - (count) = __cbtmp ^ 31; \ - } while (0) -#endif /* asm bsrl */ - -#if __GMP_GNUC_PREREQ (3,4) /* using bsfl */ -#define count_trailing_zeros(count,x) count_trailing_zeros_gcc_ctz(count,x) -#endif /* gcc ctz */ - -#ifndef count_trailing_zeros -#define count_trailing_zeros(count, x) \ - do { \ - ASSERT ((x) != 0); \ - __asm__ ("bsfl %1,%k0" : "=r" (count) : "rm" ((USItype)(x))); \ - } while (0) -#endif /* asm bsfl */ - -#endif /* ! pentium */ - -#endif /* 80x86 */ - -#if defined (__amd64__) && W_TYPE_SIZE == 64 - -#ifndef RUNTIMECPUID -#define RUNTIMECPUID - -extern int bCheckedBMI; -extern int bBMI1; -extern int bBMI2; - -inline void hasBMI() -{ - if(bCheckedBMI) - return; - - bCheckedBMI = 1; - int info[4] = {0}; -#if defined(_MSC_VER) - __cpuid(info, 0x7); -#elif defined(__GNUC__) || defined(__clang__) -#if defined(ARCH_X86) && defined(__PIC__) - __asm__ __volatile__ ( - "xchg{l} {%%}ebx, %k1;" - "cpuid;" - "xchg{l} {%%}ebx, %k1;" - : "=a"(info[0]), "=&r"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(0x7), "c"(0) - ); -#else - __asm__ __volatile__ ( - "cpuid" : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(0x7), "c"(0) - ); -#endif -#endif - bBMI1 = ((info[1] & (1 << 3)) != 0); - bBMI2 = ((info[1] & (1 << 8)) != 0); -} - -inline int hasBMI1() -{ - hasBMI(); - return bBMI1; -} - -inline int hasBMI2() -{ - hasBMI(); - return bBMI2; -} - -extern int bCheckedLZCNT; -extern int bLZCNT; - -inline int hasLZCNT() -{ - if(bCheckedLZCNT) - return bLZCNT; - - bCheckedLZCNT = 1; - int info[4] = {0}; - #if defined(_MSC_VER) - __cpuid(info, 0x80000001); - #elif defined(__GNUC__) || defined(__clang__) - #if defined(ARCH_X86) && defined(__PIC__) - __asm__ __volatile__ ( - "xchg{l} {%%}ebx, %k1;" - "cpuid;" - "xchg{l} {%%}ebx, %k1;" - : "=a"(info[0]), "=&r"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(0x80000001), "c"(0) - ); - #else - __asm__ __volatile__ ( - "cpuid" : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(0x80000001), "c"(0) - ); - #endif - #endif - - bLZCNT = ((info[2] & (1 << 5)) != 0); - return bLZCNT; -} - -#endif // RUNTIMECPUID - -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addq %5,%q1\n\tadcq %3,%q0" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((UDItype)(ah)), "rme" ((UDItype)(bh)), \ - "%1" ((UDItype)(al)), "rme" ((UDItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subq %5,%q1\n\tsbbq %3,%q0" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((UDItype)(ah)), "rme" ((UDItype)(bh)), \ - "1" ((UDItype)(al)), "rme" ((UDItype)(bl))) -#define umul_ppmm(w1, w0, u, v) \ - if(hasBMI2()) { \ - __asm__ ("mulx\t%3, %q0, %q1" \ - : "=r" (w0), "=r" (w1) \ - : "%d" ((UDItype)(u)), "rm" ((UDItype)(v))); \ - } else { \ - __asm__ ("mulq\t%3" \ - : "=a" (w0), "=d" (w1) \ - : "%0" ((UDItype)(u)), "rm" ((UDItype)(v))); \ - } -#define udiv_qrnnd(q, r, n1, n0, dx) /* d renamed to dx avoiding "=d" */\ - __asm__ ("divq %4" /* stringification in K&R C */ \ - : "=a" (q), "=d" (r) \ - : "0" ((UDItype)(n0)), "1" ((UDItype)(n1)), "rm" ((UDItype)(dx))) - -#define count_leading_zeros(count, x) \ - if(hasLZCNT()) { \ - do { \ - /* This is lzcnt, spelled for older assemblers. Destination and */ \ - /* source must be a 64-bit registers, hence cast and %q. */ \ - __asm__ ("rep;bsr\t%1, %q0" : "=r" (count) : "rm" ((UDItype)(x))); \ - } while (0); \ - } else { \ - do { \ - UDItype __cbtmp; \ - ASSERT ((x) != 0); \ - __asm__ ("bsr\t%1,%0" : "=r" (__cbtmp) : "rm" ((UDItype)(x))); \ - (count) = __cbtmp ^ 63; \ - } while (0); \ - } -#define COUNT_LEADING_ZEROS_0 64 - -#define count_trailing_zeros(count, x) \ - if(hasBMI1()) { \ - do { \ - /* This is tzcnt, spelled for older assemblers. Destination and */ \ - /* source must be a 64-bit registers, hence cast and %q. */ \ - __asm__ ("rep;bsf\t%1, %q0" : "=r" (count) : "rm" ((UDItype)(x))); \ - } while (0); \ - } else { \ - do { \ - ASSERT ((x) != 0); \ - __asm__ ("bsf\t%1, %q0" : "=r" (count) : "rm" ((UDItype)(x))); \ - } while (0); \ - } -#define COUNT_TRAILING_ZEROS_0 64 -#endif /* __amd64__ */ - -#if defined (__i860__) && W_TYPE_SIZE == 32 -#define rshift_rhlc(r,h,l,c) \ - __asm__ ("shr %3,r0,r0\;shrd %1,%2,%0" \ - "=r" (r) : "r" (h), "r" (l), "rn" (c)) -#endif /* i860 */ - -#if defined (__i960__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("cmpo 1,0\;addc %5,%4,%1\;addc %3,%2,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "dI" (ah), "dI" (bh), "%dI" (al), "dI" (bl)) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("cmpo 0,0\;subc %5,%4,%1\;subc %3,%2,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "dI" (ah), "dI" (bh), "dI" (al), "dI" (bl)) -#define umul_ppmm(w1, w0, u, v) \ - ({union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __x; \ - __asm__ ("emul %2,%1,%0" \ - : "=d" (__x.__ll) : "%dI" (u), "dI" (v)); \ - (w1) = __x.__i.__h; (w0) = __x.__i.__l;}) -#define __umulsidi3(u, v) \ - ({UDItype __w; \ - __asm__ ("emul %2,%1,%0" : "=d" (__w) : "%dI" (u), "dI" (v)); \ - __w; }) -#define udiv_qrnnd(q, r, nh, nl, d) \ - do { \ - union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __nn; \ - __nn.__i.__h = (nh); __nn.__i.__l = (nl); \ - __asm__ ("ediv %d,%n,%0" \ - : "=d" (__rq.__ll) : "dI" (__nn.__ll), "dI" (d)); \ - (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ - } while (0) -#define count_leading_zeros(count, x) \ - do { \ - USItype __cbtmp; \ - __asm__ ("scanbit %1,%0" : "=r" (__cbtmp) : "r" (x)); \ - (count) = __cbtmp ^ 31; \ - } while (0) -#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ -#if defined (__i960mx) /* what is the proper symbol to test??? */ -#define rshift_rhlc(r,h,l,c) \ - do { \ - union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __nn; \ - __nn.__i.__h = (h); __nn.__i.__l = (l); \ - __asm__ ("shre %2,%1,%0" : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \ - } -#endif /* i960mx */ -#endif /* i960 */ - -#if (defined (__mc68000__) || defined (__mc68020__) || defined(mc68020) \ - || defined (__m68k__) || defined (__mc5200__) || defined (__mc5206e__) \ - || defined (__mc5307__)) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \ - : "=d" (sh), "=&d" (sl) \ - : "0" ((USItype)(ah)), "d" ((USItype)(bh)), \ - "%1" ((USItype)(al)), "g" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \ - : "=d" (sh), "=&d" (sl) \ - : "0" ((USItype)(ah)), "d" ((USItype)(bh)), \ - "1" ((USItype)(al)), "g" ((USItype)(bl))) -/* The '020, '030, '040 and CPU32 have 32x32->64 and 64/32->32q-32r. */ -#if defined (__mc68020__) || defined(mc68020) \ - || defined (__mc68030__) || defined (mc68030) \ - || defined (__mc68040__) || defined (mc68040) \ - || defined (__mcpu32__) || defined (mcpu32) \ - || defined (__NeXT__) -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("mulu%.l %3,%1:%0" \ - : "=d" (w0), "=d" (w1) \ - : "%0" ((USItype)(u)), "dmi" ((USItype)(v))) -#define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("divu%.l %4,%1:%0" \ - : "=d" (q), "=d" (r) \ - : "0" ((USItype)(n0)), "1" ((USItype)(n1)), "dmi" ((USItype)(d))) -#define sdiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("divs%.l %4,%1:%0" \ - : "=d" (q), "=d" (r) \ - : "0" ((USItype)(n0)), "1" ((USItype)(n1)), "dmi" ((USItype)(d))) -#else /* for other 68k family members use 16x16->32 multiplication */ -#define umul_ppmm(xh, xl, a, b) \ - do { USItype __umul_tmp1, __umul_tmp2; \ - __asm__ ("| Inlined umul_ppmm\n" \ -" move%.l %5,%3\n" \ -" move%.l %2,%0\n" \ -" move%.w %3,%1\n" \ -" swap %3\n" \ -" swap %0\n" \ -" mulu%.w %2,%1\n" \ -" mulu%.w %3,%0\n" \ -" mulu%.w %2,%3\n" \ -" swap %2\n" \ -" mulu%.w %5,%2\n" \ -" add%.l %3,%2\n" \ -" jcc 1f\n" \ -" add%.l %#0x10000,%0\n" \ -"1: move%.l %2,%3\n" \ -" clr%.w %2\n" \ -" swap %2\n" \ -" swap %3\n" \ -" clr%.w %3\n" \ -" add%.l %3,%1\n" \ -" addx%.l %2,%0\n" \ -" | End inlined umul_ppmm" \ - : "=&d" (xh), "=&d" (xl), \ - "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \ - : "%2" ((USItype)(a)), "d" ((USItype)(b))); \ - } while (0) -#endif /* not mc68020 */ -/* The '020, '030, '040 and '060 have bitfield insns. - GCC 3.4 defines __mc68020__ when in CPU32 mode, check for __mcpu32__ to - exclude bfffo on that chip (bitfield insns not available). */ -#if (defined (__mc68020__) || defined (mc68020) \ - || defined (__mc68030__) || defined (mc68030) \ - || defined (__mc68040__) || defined (mc68040) \ - || defined (__mc68060__) || defined (mc68060) \ - || defined (__NeXT__)) \ - && ! defined (__mcpu32__) -#define count_leading_zeros(count, x) \ - __asm__ ("bfffo %1{%b2:%b2},%0" \ - : "=d" (count) \ - : "od" ((USItype) (x)), "n" (0)) -#define COUNT_LEADING_ZEROS_0 32 -#endif -#endif /* mc68000 */ - -#if defined (__m88000__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3" \ - : "=r" (sh), "=&r" (sl) \ - : "rJ" (ah), "rJ" (bh), "%rJ" (al), "rJ" (bl)) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3" \ - : "=r" (sh), "=&r" (sl) \ - : "rJ" (ah), "rJ" (bh), "rJ" (al), "rJ" (bl)) -#define count_leading_zeros(count, x) \ - do { \ - USItype __cbtmp; \ - __asm__ ("ff1 %0,%1" : "=r" (__cbtmp) : "r" (x)); \ - (count) = __cbtmp ^ 31; \ - } while (0) -#define COUNT_LEADING_ZEROS_0 63 /* sic */ -#if defined (__m88110__) -#define umul_ppmm(wh, wl, u, v) \ - do { \ - union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __asm__ ("mulu.d %0,%1,%2" : "=r" (__x.__ll) : "r" (u), "r" (v)); \ - (wh) = __x.__i.__h; \ - (wl) = __x.__i.__l; \ - } while (0) -#define udiv_qrnnd(q, r, n1, n0, d) \ - ({union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x, __q; \ - __x.__i.__h = (n1); __x.__i.__l = (n0); \ - __asm__ ("divu.d %0,%1,%2" \ - : "=r" (__q.__ll) : "r" (__x.__ll), "r" (d)); \ - (r) = (n0) - __q.__l * (d); (q) = __q.__l; }) -#endif /* __m88110__ */ -#endif /* __m88000__ */ - -#if defined (__mips) && W_TYPE_SIZE == 32 -#if __GMP_GNUC_PREREQ (4,4) -#define umul_ppmm(w1, w0, u, v) \ - do { \ - UDItype __ll = (UDItype)(u) * (v); \ - w1 = __ll >> 32; \ - w0 = __ll; \ - } while (0) -#endif -#if !defined (umul_ppmm) && __GMP_GNUC_PREREQ (2,7) && !defined (__clang__) -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("multu %2,%3" : "=l" (w0), "=h" (w1) : "d" (u), "d" (v)) -#endif -#if !defined (umul_ppmm) -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("multu %2,%3\n\tmflo %0\n\tmfhi %1" \ - : "=d" (w0), "=d" (w1) : "d" (u), "d" (v)) -#endif -#endif /* __mips */ - -#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64 -#if defined (_MIPS_ARCH_MIPS64R6) -#define umul_ppmm(w1, w0, u, v) \ - do { \ - UDItype __m0 = (u), __m1 = (v); \ - (w0) = __m0 * __m1; \ - __asm__ ("dmuhu\t%0, %1, %2" : "=d" (w1) : "d" (__m0), "d" (__m1)); \ - } while (0) -#endif -#if !defined (umul_ppmm) && __GMP_GNUC_PREREQ (4,4) -#define umul_ppmm(w1, w0, u, v) \ - do { \ - typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ - __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \ - w1 = __ll >> 64; \ - w0 = __ll; \ - } while (0) -#endif -#if !defined (umul_ppmm) && __GMP_GNUC_PREREQ (2,7) && !defined (__clang__) -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("dmultu %2,%3" \ - : "=l" (w0), "=h" (w1) \ - : "d" ((UDItype)(u)), "d" ((UDItype)(v))) -#endif -#if !defined (umul_ppmm) -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("dmultu %2,%3\n\tmflo %0\n\tmfhi %1" \ - : "=d" (w0), "=d" (w1) \ - : "d" ((UDItype)(u)), "d" ((UDItype)(v))) -#endif -#endif /* __mips */ - -#if defined (__mmix__) && W_TYPE_SIZE == 64 -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("MULU %0,%2,%3" : "=r" (w0), "=z" (w1) : "r" (u), "r" (v)) -#endif - -#if defined (__ns32000__) && W_TYPE_SIZE == 32 -#define umul_ppmm(w1, w0, u, v) \ - ({union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __x; \ - __asm__ ("meid %2,%0" \ - : "=g" (__x.__ll) \ - : "%0" ((USItype)(u)), "g" ((USItype)(v))); \ - (w1) = __x.__i.__h; (w0) = __x.__i.__l;}) -#define __umulsidi3(u, v) \ - ({UDItype __w; \ - __asm__ ("meid %2,%0" \ - : "=g" (__w) \ - : "%0" ((USItype)(u)), "g" ((USItype)(v))); \ - __w; }) -#define udiv_qrnnd(q, r, n1, n0, d) \ - ({union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __x; \ - __x.__i.__h = (n1); __x.__i.__l = (n0); \ - __asm__ ("deid %2,%0" \ - : "=g" (__x.__ll) \ - : "0" (__x.__ll), "g" ((USItype)(d))); \ - (r) = __x.__i.__l; (q) = __x.__i.__h; }) -#define count_trailing_zeros(count,x) \ - do { \ - __asm__ ("ffsd %2,%0" \ - : "=r" (count) \ - : "0" ((USItype) 0), "r" ((USItype) (x))); \ - } while (0) -#endif /* __ns32000__ */ - -/* In the past we had a block of various #defines tested - _ARCH_PPC - AIX - _ARCH_PWR - AIX - __powerpc__ - gcc - __POWERPC__ - BEOS - __ppc__ - Darwin - PPC - old gcc, GNU/Linux, SysV - The plain PPC test was not good for vxWorks, since PPC is defined on all - CPUs there (eg. m68k too), as a constant one is expected to compare - CPU_FAMILY against. - - At any rate, this was pretty unattractive and a bit fragile. The use of - HAVE_HOST_CPU_FAMILY is designed to cut through it all and be sure of - getting the desired effect. - - ENHANCE-ME: We should test _IBMR2 here when we add assembly support for - the system vendor compilers. (Is that vendor compilers with inline asm, - or what?) */ - -#if (HAVE_HOST_CPU_FAMILY_power || HAVE_HOST_CPU_FAMILY_powerpc) \ - && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (bh) && (bh) == 0) \ - __asm__ ("add%I4c %1,%3,%4\n\taddze %0,%2" \ - : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ - __asm__ ("add%I4c %1,%3,%4\n\taddme %0,%2" \ - : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl) \ - __CLOBBER_CC); \ - else \ - __asm__ ("add%I5c %1,%4,%5\n\tadde %0,%2,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "r" (bh), "%r" (al), "rI" (bl) \ - __CLOBBER_CC); \ - } while (0) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (ah) && (ah) == 0) \ - __asm__ ("subf%I3c %1,%4,%3\n\tsubfze %0,%2" \ - : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \ - __asm__ ("subf%I3c %1,%4,%3\n\tsubfme %0,%2" \ - : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (bh) && (bh) == 0) \ - __asm__ ("subf%I3c %1,%4,%3\n\taddme %0,%2" \ - : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ - __asm__ ("subf%I3c %1,%4,%3\n\taddze %0,%2" \ - : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl) \ - __CLOBBER_CC); \ - else \ - __asm__ ("subf%I4c %1,%5,%4\n\tsubfe %0,%3,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" (ah), "r" (bh), "rI" (al), "r" (bl) \ - __CLOBBER_CC); \ - } while (0) -#define count_leading_zeros(count, x) \ - __asm__ ("cntlzw %0,%1" : "=r" (count) : "r" (x)) -#define COUNT_LEADING_ZEROS_0 32 -#if HAVE_HOST_CPU_FAMILY_powerpc -#if __GMP_GNUC_PREREQ (4,4) -#define umul_ppmm(w1, w0, u, v) \ - do { \ - UDItype __ll = (UDItype)(u) * (v); \ - w1 = __ll >> 32; \ - w0 = __ll; \ - } while (0) -#endif -#if !defined (umul_ppmm) -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - USItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ - (pl) = __m0 * __m1; \ - } while (0) -#endif -#define smul_ppmm(ph, pl, m0, m1) \ - do { \ - SItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ - (pl) = __m0 * __m1; \ - } while (0) -#else -#define smul_ppmm(xh, xl, m0, m1) \ - __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1)) -#define sdiv_qrnnd(q, r, nh, nl, d) \ - __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d)) -#endif -#endif /* 32-bit POWER architecture variants. */ - -/* We should test _IBMR2 here when we add assembly support for the system - vendor compilers. */ -#if HAVE_HOST_CPU_FAMILY_powerpc && W_TYPE_SIZE == 64 -#if !defined (_LONG_LONG_LIMB) -/* _LONG_LONG_LIMB is ABI=mode32 where adde operates on 32-bit values. So - use adde etc only when not _LONG_LONG_LIMB. */ -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (bh) && (bh) == 0) \ - __asm__ ("add%I4c %1,%3,%4\n\taddze %0,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(ah)), \ - "%r" ((UDItype)(al)), "rI" ((UDItype)(bl)) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ - __asm__ ("add%I4c %1,%3,%4\n\taddme %0,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(ah)), \ - "%r" ((UDItype)(al)), "rI" ((UDItype)(bl)) \ - __CLOBBER_CC); \ - else \ - __asm__ ("add%I5c %1,%4,%5\n\tadde %0,%2,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(ah)), "r" ((UDItype)(bh)), \ - "%r" ((UDItype)(al)), "rI" ((UDItype)(bl)) \ - __CLOBBER_CC); \ - } while (0) -/* We use "*rI" for the constant operand here, since with just "I", gcc barfs. - This might seem strange, but gcc folds away the dead code late. */ -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (bl) \ - && (bl) > -0x8000 && (bl) <= 0x8000 && (bl) != 0) { \ - if (__builtin_constant_p (ah) && (ah) == 0) \ - __asm__ ("addic %1,%3,%4\n\tsubfze %0,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(bh)), \ - "r" ((UDItype)(al)), "*rI" (-((UDItype)(bl))) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ - __asm__ ("addic %1,%3,%4\n\tsubfme %0,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(bh)), \ - "r" ((UDItype)(al)), "*rI" (-((UDItype)(bl))) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (bh) && (bh) == 0) \ - __asm__ ("addic %1,%3,%4\n\taddme %0,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(ah)), \ - "r" ((UDItype)(al)), "*rI" (-((UDItype)(bl))) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ - __asm__ ("addic %1,%3,%4\n\taddze %0,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(ah)), \ - "r" ((UDItype)(al)), "*rI" (-((UDItype)(bl))) \ - __CLOBBER_CC); \ - else \ - __asm__ ("addic %1,%4,%5\n\tsubfe %0,%3,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(ah)), "r" ((UDItype)(bh)), \ - "r" ((UDItype)(al)), "*rI" (-((UDItype)(bl))) \ - __CLOBBER_CC); \ - } else { \ - if (__builtin_constant_p (ah) && (ah) == 0) \ - __asm__ ("subf%I3c %1,%4,%3\n\tsubfze %0,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(bh)), \ - "rI" ((UDItype)(al)), "r" ((UDItype)(bl)) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ - __asm__ ("subf%I3c %1,%4,%3\n\tsubfme %0,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(bh)), \ - "rI" ((UDItype)(al)), "r" ((UDItype)(bl)) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (bh) && (bh) == 0) \ - __asm__ ("subf%I3c %1,%4,%3\n\taddme %0,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(ah)), \ - "rI" ((UDItype)(al)), "r" ((UDItype)(bl)) \ - __CLOBBER_CC); \ - else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ - __asm__ ("subf%I3c %1,%4,%3\n\taddze %0,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(ah)), \ - "rI" ((UDItype)(al)), "r" ((UDItype)(bl)) \ - __CLOBBER_CC); \ - else \ - __asm__ ("subf%I4c %1,%5,%4\n\tsubfe %0,%3,%2" \ - : "=r" (sh), "=&r" (sl) \ - : "r" ((UDItype)(ah)), "r" ((UDItype)(bh)), \ - "rI" ((UDItype)(al)), "r" ((UDItype)(bl)) \ - __CLOBBER_CC); \ - } \ - } while (0) -#endif /* ! _LONG_LONG_LIMB */ -#define count_leading_zeros(count, x) \ - __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x)) -#define COUNT_LEADING_ZEROS_0 64 -#if __GMP_GNUC_PREREQ (4,8) -#define umul_ppmm(w1, w0, u, v) \ - do { \ - typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ - __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \ - w1 = __ll >> 64; \ - w0 = __ll; \ - } while (0) -#endif -#if !defined (umul_ppmm) -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - UDItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (__m0), "r" (__m1)); \ - (pl) = __m0 * __m1; \ - } while (0) -#endif -#define smul_ppmm(ph, pl, m0, m1) \ - do { \ - DItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (__m0), "r" (__m1)); \ - (pl) = __m0 * __m1; \ - } while (0) -#endif /* 64-bit PowerPC. */ - -#if defined (__pyr__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addw %5,%1\n\taddwc %3,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ - "%1" ((USItype)(al)), "g" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subw %5,%1\n\tsubwb %3,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ - "1" ((USItype)(al)), "g" ((USItype)(bl))) -/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */ -#define umul_ppmm(w1, w0, u, v) \ - ({union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __asm__ ("movw %1,%R0\n\tuemul %2,%0" \ - : "=&r" (__x.__ll) \ - : "g" ((USItype) (u)), "g" ((USItype)(v))); \ - (w1) = __x.__i.__h; (w0) = __x.__i.__l;}) -#endif /* __pyr__ */ - -#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("a %1,%5\n\tae %0,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((USItype)(ah)), "r" ((USItype)(bh)), \ - "%1" ((USItype)(al)), "r" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("s %1,%5\n\tse %0,%3" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((USItype)(ah)), "r" ((USItype)(bh)), \ - "1" ((USItype)(al)), "r" ((USItype)(bl))) -#define smul_ppmm(ph, pl, m0, m1) \ - __asm__ ( \ - "s r2,r2\n" \ -" mts r10,%2\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" m r2,%3\n" \ -" cas %0,r2,r0\n" \ -" mfs r10,%1" \ - : "=r" (ph), "=r" (pl) \ - : "%r" ((USItype)(m0)), "r" ((USItype)(m1)) \ - : "r2") -#define count_leading_zeros(count, x) \ - do { \ - if ((x) >= 0x10000) \ - __asm__ ("clz %0,%1" \ - : "=r" (count) : "r" ((USItype)(x) >> 16)); \ - else \ - { \ - __asm__ ("clz %0,%1" \ - : "=r" (count) : "r" ((USItype)(x))); \ - (count) += 16; \ - } \ - } while (0) -#endif /* RT/ROMP */ - -#if defined (__riscv64) && W_TYPE_SIZE == 64 -#define umul_ppmm(ph, pl, u, v) \ - do { \ - UDItype __u = (u), __v = (v); \ - (pl) = __u * __v; \ - __asm__ ("mulhu\t%2, %1, %0" : "=r" (ph) : "%r" (__u), "r" (__v)); \ - } while (0) -#endif - -#if (defined (__SH2__) || defined (__SH3__) || defined (__SH4__)) && W_TYPE_SIZE == 32 -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("dmulu.l %2,%3\n\tsts macl,%1\n\tsts mach,%0" \ - : "=r" (w1), "=r" (w0) : "r" (u), "r" (v) : "macl", "mach") -#endif - -#if defined (__sparc__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "rJ" (ah), "rI" (bh),"%rJ" (al), "rI" (bl) \ - __CLOBBER_CC) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "rJ" (ah), "rI" (bh), "rJ" (al), "rI" (bl) \ - __CLOBBER_CC) -/* FIXME: When gcc -mcpu=v9 is used on solaris, gcc/config/sol2-sld-64.h - doesn't define anything to indicate that to us, it only sets __sparcv8. */ -#if defined (__sparc_v9__) || defined (__sparcv9) -/* Perhaps we should use floating-point operations here? */ -#if 0 -/* Triggers a bug making mpz/tests/t-gcd.c fail. - Perhaps we simply need explicitly zero-extend the inputs? */ -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("mulx %2,%3,%%g1; srl %%g1,0,%1; srlx %%g1,32,%0" : \ - "=r" (w1), "=r" (w0) : "r" (u), "r" (v) : "g1") -#else -/* Use v8 umul until above bug is fixed. */ -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("umul %2,%3,%1;rd %%y,%0" : "=r" (w1), "=r" (w0) : "r" (u), "r" (v)) -#endif -/* Use a plain v8 divide for v9. */ -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { \ - USItype __q; \ - __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ - : "=r" (__q) : "r" (n1), "r" (n0), "r" (d)); \ - (r) = (n0) - __q * (d); \ - (q) = __q; \ - } while (0) -#else -#if defined (__sparc_v8__) /* gcc normal */ \ - || defined (__sparcv8) /* gcc solaris */ \ - || HAVE_HOST_CPU_supersparc -/* Don't match immediate range because, 1) it is not often useful, - 2) the 'I' flag thinks of the range as a 13 bit signed interval, - while we want to match a 13 bit interval, sign extended to 32 bits, - but INTERPRETED AS UNSIGNED. */ -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("umul %2,%3,%1;rd %%y,%0" : "=r" (w1), "=r" (w0) : "r" (u), "r" (v)) - -#if HAVE_HOST_CPU_supersparc -#else -/* Don't use this on SuperSPARC because its udiv only handles 53 bit - dividends and will trap to the kernel for the rest. */ -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { \ - USItype __q; \ - __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ - : "=r" (__q) : "r" (n1), "r" (n0), "r" (d)); \ - (r) = (n0) - __q * (d); \ - (q) = __q; \ - } while (0) -#endif /* HAVE_HOST_CPU_supersparc */ - -#else /* ! __sparc_v8__ */ -#if defined (__sparclite__) -/* This has hardware multiply but not divide. It also has two additional - instructions scan (ffs from high bit) and divscc. */ -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("umul %2,%3,%1;rd %%y,%0" : "=r" (w1), "=r" (w0) : "r" (u), "r" (v)) -#define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("! Inlined udiv_qrnnd\n" \ -" wr %%g0,%2,%%y ! Not a delayed write for sparclite\n" \ -" tst %%g0\n" \ -" divscc %3,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%%g1\n" \ -" divscc %%g1,%4,%0\n" \ -" rd %%y,%1\n" \ -" bl,a 1f\n" \ -" add %1,%4,%1\n" \ -"1: ! End of inline udiv_qrnnd" \ - : "=r" (q), "=r" (r) : "r" (n1), "r" (n0), "rI" (d) \ - : "%g1" __AND_CLOBBER_CC) -#define count_leading_zeros(count, x) \ - __asm__ ("scan %1,1,%0" : "=r" (count) : "r" (x)) -/* Early sparclites return 63 for an argument of 0, but they warn that future - implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 - undefined. */ -#endif /* __sparclite__ */ -#endif /* __sparc_v8__ */ -#endif /* __sparc_v9__ */ -/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ -#ifndef umul_ppmm -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("! Inlined umul_ppmm\n" \ -" wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n" \ -" sra %3,31,%%g2 ! Don't move this insn\n" \ -" and %2,%%g2,%%g2 ! Don't move this insn\n" \ -" andcc %%g0,0,%%g1 ! Don't move this insn\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,%3,%%g1\n" \ -" mulscc %%g1,0,%%g1\n" \ -" add %%g1,%%g2,%0\n" \ -" rd %%y,%1" \ - : "=r" (w1), "=r" (w0) : "%rI" (u), "r" (v) \ - : "%g1", "%g2" __AND_CLOBBER_CC) -#endif -#ifndef udiv_qrnnd -#ifndef LONGLONG_STANDALONE -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { UWtype __r; \ - (q) = __MPN(udiv_qrnnd) (&__r, (n1), (n0), (d)); \ - (r) = __r; \ - } while (0) -extern UWtype __MPN(udiv_qrnnd) (UWtype *, UWtype, UWtype, UWtype); -#endif /* LONGLONG_STANDALONE */ -#endif /* udiv_qrnnd */ -#endif /* __sparc__ */ - -#if defined (__sparc__) && W_TYPE_SIZE == 64 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ( \ - "addcc %r4,%5,%1\n" \ - " addccc %r6,%7,%%g0\n" \ - " addc %r2,%3,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "rJ" ((UDItype)(ah)), "rI" ((UDItype)(bh)), \ - "%rJ" ((UDItype)(al)), "rI" ((UDItype)(bl)), \ - "%rJ" ((UDItype)(al) >> 32), "rI" ((UDItype)(bl) >> 32) \ - __CLOBBER_CC) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ( \ - "subcc %r4,%5,%1\n" \ - " subccc %r6,%7,%%g0\n" \ - " subc %r2,%3,%0" \ - : "=r" (sh), "=&r" (sl) \ - : "rJ" ((UDItype)(ah)), "rI" ((UDItype)(bh)), \ - "rJ" ((UDItype)(al)), "rI" ((UDItype)(bl)), \ - "rJ" ((UDItype)(al) >> 32), "rI" ((UDItype)(bl) >> 32) \ - __CLOBBER_CC) -#if __VIS__ >= 0x300 -#undef add_ssaaaa -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ( \ - "addcc %r4, %5, %1\n" \ - " addxc %r2, %r3, %0" \ - : "=r" (sh), "=&r" (sl) \ - : "rJ" ((UDItype)(ah)), "rJ" ((UDItype)(bh)), \ - "%rJ" ((UDItype)(al)), "rI" ((UDItype)(bl)) __CLOBBER_CC) -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - UDItype __m0 = (m0), __m1 = (m1); \ - (pl) = __m0 * __m1; \ - __asm__ ("umulxhi\t%2, %1, %0" \ - : "=r" (ph) \ - : "%r" (__m0), "r" (__m1)); \ - } while (0) -#define count_leading_zeros(count, x) \ - __asm__ ("lzd\t%1,%0" : "=r" (count) : "r" (x)) -/* Needed by count_leading_zeros_32 in sparc64.h. */ -#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB -#endif -#endif - -#if (defined (__vax) || defined (__vax__)) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \ - : "=g" (sh), "=&g" (sl) \ - : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ - "%1" ((USItype)(al)), "g" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \ - : "=g" (sh), "=&g" (sl) \ - : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ - "1" ((USItype)(al)), "g" ((USItype)(bl))) -#define smul_ppmm(xh, xl, m0, m1) \ - do { \ - union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __x; \ - USItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("emul %1,%2,$0,%0" \ - : "=g" (__x.__ll) : "g" (__m0), "g" (__m1)); \ - (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ - } while (0) -#define sdiv_qrnnd(q, r, n1, n0, d) \ - do { \ - union {DItype __ll; \ - struct {SItype __l, __h;} __i; \ - } __x; \ - __x.__i.__h = n1; __x.__i.__l = n0; \ - __asm__ ("ediv %3,%2,%0,%1" \ - : "=g" (q), "=g" (r) : "g" (__x.__ll), "g" (d)); \ - } while (0) -#if 0 -/* FIXME: This instruction appears to be unimplemented on some systems (vax - 8800 maybe). */ -#define count_trailing_zeros(count,x) \ - do { \ - __asm__ ("ffs 0, 31, %1, %0" \ - : "=g" (count) \ - : "g" ((USItype) (x))); \ - } while (0) -#endif -#endif /* vax */ - -#if defined (__z8000__) && W_TYPE_SIZE == 16 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((unsigned int)(ah)), "r" ((unsigned int)(bh)), \ - "%1" ((unsigned int)(al)), "rQR" ((unsigned int)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ - : "=r" (sh), "=&r" (sl) \ - : "0" ((unsigned int)(ah)), "r" ((unsigned int)(bh)), \ - "1" ((unsigned int)(al)), "rQR" ((unsigned int)(bl))) -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - union {long int __ll; \ - struct {unsigned int __h, __l;} __i; \ - } __x; \ - unsigned int __m0 = (m0), __m1 = (m1); \ - __asm__ ("mult %S0,%H3" \ - : "=r" (__x.__i.__h), "=r" (__x.__i.__l) \ - : "%1" (m0), "rQR" (m1)); \ - (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ - (xh) += ((((signed int) __m0 >> 15) & __m1) \ - + (((signed int) __m1 >> 15) & __m0)); \ - } while (0) -#endif /* __z8000__ */ - -#endif /* __GNUC__ */ - -#endif /* NO_ASM */ - - -/* FIXME: "sidi" here is highly doubtful, should sometimes be "diti". */ -#if !defined (umul_ppmm) && defined (__umulsidi3) -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - UDWtype __ll = __umulsidi3 (m0, m1); \ - ph = (UWtype) (__ll >> W_TYPE_SIZE); \ - pl = (UWtype) __ll; \ - } while (0) -#endif - -#if !defined (__umulsidi3) -#define __umulsidi3(u, v) \ - ({UWtype __hi, __lo; \ - umul_ppmm (__hi, __lo, u, v); \ - ((UDWtype) __hi << W_TYPE_SIZE) | __lo; }) -#endif - - -#if defined (__cplusplus) -#define __longlong_h_C "C" -#else -#define __longlong_h_C -#endif - -/* Use mpn_umul_ppmm or mpn_udiv_qrnnd functions, if they exist. The "_r" - forms have "reversed" arguments, meaning the pointer is last, which - sometimes allows better parameter passing, in particular on 64-bit - hppa. */ - -#define mpn_umul_ppmm __MPN(umul_ppmm) -extern __longlong_h_C UWtype mpn_umul_ppmm (UWtype *, UWtype, UWtype); - -#if ! defined (umul_ppmm) && HAVE_NATIVE_mpn_umul_ppmm \ - && ! defined (LONGLONG_STANDALONE) -#define umul_ppmm(wh, wl, u, v) \ - do { \ - UWtype __umul_ppmm__p0; \ - (wh) = mpn_umul_ppmm (&__umul_ppmm__p0, (UWtype) (u), (UWtype) (v));\ - (wl) = __umul_ppmm__p0; \ - } while (0) -#endif - -#define mpn_umul_ppmm_r __MPN(umul_ppmm_r) -extern __longlong_h_C UWtype mpn_umul_ppmm_r (UWtype, UWtype, UWtype *); - -#if ! defined (umul_ppmm) && HAVE_NATIVE_mpn_umul_ppmm_r \ - && ! defined (LONGLONG_STANDALONE) -#define umul_ppmm(wh, wl, u, v) \ - do { \ - UWtype __umul_p0; \ - (wh) = mpn_umul_ppmm_r ((UWtype) (u), (UWtype) (v), &__umul_p0); \ - (wl) = __umul_p0; \ - } while (0) -#endif - -#define mpn_udiv_qrnnd __MPN(udiv_qrnnd) -extern __longlong_h_C UWtype mpn_udiv_qrnnd (UWtype *, UWtype, UWtype, UWtype); - -#if ! defined (udiv_qrnnd) && HAVE_NATIVE_mpn_udiv_qrnnd \ - && ! defined (LONGLONG_STANDALONE) -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { \ - UWtype __udiv_qrnnd_r; \ - (q) = mpn_udiv_qrnnd (&__udiv_qrnnd_r, \ - (UWtype) (n1), (UWtype) (n0), (UWtype) d); \ - (r) = __udiv_qrnnd_r; \ - } while (0) -#endif - -#define mpn_udiv_qrnnd_r __MPN(udiv_qrnnd_r) -extern __longlong_h_C UWtype mpn_udiv_qrnnd_r (UWtype, UWtype, UWtype, UWtype *); - -#if ! defined (udiv_qrnnd) && HAVE_NATIVE_mpn_udiv_qrnnd_r \ - && ! defined (LONGLONG_STANDALONE) -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { \ - UWtype __udiv_qrnnd_r; \ - (q) = mpn_udiv_qrnnd_r ((UWtype) (n1), (UWtype) (n0), (UWtype) d, \ - &__udiv_qrnnd_r); \ - (r) = __udiv_qrnnd_r; \ - } while (0) -#endif - - -/* If this machine has no inline assembler, use C macros. */ - -#if !defined (add_ssaaaa) -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ - UWtype __x; \ - UWtype __al = (al); \ - UWtype __bl = (bl); \ - __x = __al + __bl; \ - (sh) = (ah) + (bh) + (__x < __al); \ - (sl) = __x; \ - } while (0) -#endif - -#if !defined (sub_ddmmss) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - UWtype __x; \ - UWtype __al = (al); \ - UWtype __bl = (bl); \ - __x = __al - __bl; \ - (sh) = (ah) - (bh) - (__al < __bl); \ - (sl) = __x; \ - } while (0) -#endif - -/* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of - smul_ppmm. */ -#if !defined (umul_ppmm) && defined (smul_ppmm) -#define umul_ppmm(w1, w0, u, v) \ - do { \ - UWtype __w1; \ - UWtype __xm0 = (u), __xm1 = (v); \ - smul_ppmm (__w1, w0, __xm0, __xm1); \ - (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1) \ - + (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0); \ - } while (0) -#endif - -/* If we still don't have umul_ppmm, define it using plain C. - - For reference, when this code is used for squaring (ie. u and v identical - expressions), gcc recognises __x1 and __x2 are the same and generates 3 - multiplies, not 4. The subsequent additions could be optimized a bit, - but the only place GMP currently uses such a square is mpn_sqr_basecase, - and chips obliged to use this generic C umul will have plenty of worse - performance problems than a couple of extra instructions on the diagonal - of sqr_basecase. */ - -#if !defined (umul_ppmm) -#define umul_ppmm(w1, w0, u, v) \ - do { \ - UWtype __x0, __x1, __x2, __x3; \ - UHWtype __ul, __vl, __uh, __vh; \ - UWtype __u = (u), __v = (v); \ - \ - __ul = __ll_lowpart (__u); \ - __uh = __ll_highpart (__u); \ - __vl = __ll_lowpart (__v); \ - __vh = __ll_highpart (__v); \ - \ - __x0 = (UWtype) __ul * __vl; \ - __x1 = (UWtype) __ul * __vh; \ - __x2 = (UWtype) __uh * __vl; \ - __x3 = (UWtype) __uh * __vh; \ - \ - __x1 += __ll_highpart (__x0);/* this can't give carry */ \ - __x1 += __x2; /* but this indeed can */ \ - if (__x1 < __x2) /* did we get it? */ \ - __x3 += __ll_B; /* yes, add it in the proper pos. */ \ - \ - (w1) = __x3 + __ll_highpart (__x1); \ - (w0) = (__x1 << W_TYPE_SIZE/2) + __ll_lowpart (__x0); \ - } while (0) -#endif - -/* If we don't have smul_ppmm, define it using umul_ppmm (which surely will - exist in one form or another. */ -#if !defined (smul_ppmm) -#define smul_ppmm(w1, w0, u, v) \ - do { \ - UWtype __w1; \ - UWtype __xm0 = (u), __xm1 = (v); \ - umul_ppmm (__w1, w0, __xm0, __xm1); \ - (w1) = __w1 - (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1) \ - - (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0); \ - } while (0) -#endif - -/* Define this unconditionally, so it can be used for debugging. */ -#define __udiv_qrnnd_c(q, r, n1, n0, d) \ - do { \ - UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ - \ - ASSERT ((d) != 0); \ - ASSERT ((n1) < (d)); \ - \ - __d1 = __ll_highpart (d); \ - __d0 = __ll_lowpart (d); \ - \ - __q1 = (n1) / __d1; \ - __r1 = (n1) - __q1 * __d1; \ - __m = __q1 * __d0; \ - __r1 = __r1 * __ll_B | __ll_highpart (n0); \ - if (__r1 < __m) \ - { \ - __q1--, __r1 += (d); \ - if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ - if (__r1 < __m) \ - __q1--, __r1 += (d); \ - } \ - __r1 -= __m; \ - \ - __q0 = __r1 / __d1; \ - __r0 = __r1 - __q0 * __d1; \ - __m = __q0 * __d0; \ - __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ - if (__r0 < __m) \ - { \ - __q0--, __r0 += (d); \ - if (__r0 >= (d)) \ - if (__r0 < __m) \ - __q0--, __r0 += (d); \ - } \ - __r0 -= __m; \ - \ - (q) = __q1 * __ll_B | __q0; \ - (r) = __r0; \ - } while (0) - -/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through - __udiv_w_sdiv (defined in libgcc or elsewhere). */ -#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) \ - && ! defined (LONGLONG_STANDALONE) -#define udiv_qrnnd(q, r, nh, nl, d) \ - do { \ - UWtype __r; \ - (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \ - (r) = __r; \ - } while (0) -__GMP_DECLSPEC UWtype __MPN(udiv_w_sdiv) (UWtype *, UWtype, UWtype, UWtype); -#endif - -/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ -#if !defined (udiv_qrnnd) -#define UDIV_NEEDS_NORMALIZATION 1 -#define udiv_qrnnd __udiv_qrnnd_c -#endif - -#if !defined (count_leading_zeros) -#define count_leading_zeros(count, x) \ - do { \ - UWtype __xr = (x); \ - UWtype __a; \ - \ - if (W_TYPE_SIZE == 32) \ - { \ - __a = __xr < ((UWtype) 1 << 2*__BITS4) \ - ? (__xr < ((UWtype) 1 << __BITS4) ? 1 : __BITS4 + 1) \ - : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 + 1 \ - : 3*__BITS4 + 1); \ - } \ - else \ - { \ - for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ - if (((__xr >> __a) & 0xff) != 0) \ - break; \ - ++__a; \ - } \ - \ - (count) = W_TYPE_SIZE + 1 - __a - __clz_tab[__xr >> __a]; \ - } while (0) -/* This version gives a well-defined value for zero. */ -#define COUNT_LEADING_ZEROS_0 (W_TYPE_SIZE - 1) -#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB -#define COUNT_LEADING_ZEROS_SLOW -#endif - -/* clz_tab needed by mpn/x86/pentium/mod_1.asm in a fat binary */ -#if HAVE_HOST_CPU_FAMILY_x86 && WANT_FAT_BINARY -#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB -#endif - -#ifdef COUNT_LEADING_ZEROS_NEED_CLZ_TAB -extern const unsigned char __GMP_DECLSPEC __clz_tab[129]; -#endif - -#if !defined (count_trailing_zeros) -#if !defined (COUNT_LEADING_ZEROS_SLOW) -/* Define count_trailing_zeros using an asm count_leading_zeros. */ -#define count_trailing_zeros(count, x) \ - do { \ - UWtype __ctz_x = (x); \ - UWtype __ctz_c; \ - ASSERT (__ctz_x != 0); \ - count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ - (count) = W_TYPE_SIZE - 1 - __ctz_c; \ - } while (0) -#else -/* Define count_trailing_zeros in plain C, assuming small counts are common. - We use clz_tab without ado, since the C count_leading_zeros above will have - pulled it in. */ -#define count_trailing_zeros(count, x) \ - do { \ - UWtype __ctz_x = (x); \ - int __ctz_c; \ - \ - if (LIKELY ((__ctz_x & 0xff) != 0)) \ - (count) = __clz_tab[__ctz_x & -__ctz_x] - 2; \ - else \ - { \ - for (__ctz_c = 8 - 2; __ctz_c < W_TYPE_SIZE - 2; __ctz_c += 8) \ - { \ - __ctz_x >>= 8; \ - if (LIKELY ((__ctz_x & 0xff) != 0)) \ - break; \ - } \ - \ - (count) = __ctz_c + __clz_tab[__ctz_x & -__ctz_x]; \ - } \ - } while (0) -#endif -#endif - -#ifndef UDIV_NEEDS_NORMALIZATION -#define UDIV_NEEDS_NORMALIZATION 0 -#endif - -/* Whether udiv_qrnnd is actually implemented with udiv_qrnnd_preinv, and - that hence the latter should always be used. */ -#ifndef UDIV_PREINV_ALWAYS -#define UDIV_PREINV_ALWAYS 0 -#endif diff --git a/js-bindings/CMakeLists.txt b/js-bindings/CMakeLists.txt index 08a0d4a57..7f6f81d5a 100644 --- a/js-bindings/CMakeLists.txt +++ b/js-bindings/CMakeLists.txt @@ -3,8 +3,6 @@ set(CMAKE_CXX_STANDARD 17) include_directories( ${INCLUDE_DIRECTORIES} - ${CMAKE_BINARY_DIR}/_deps/relic-src/include - ${CMAKE_BINARY_DIR}/_deps/relic-build/include ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/catch ) diff --git a/js-bindings/blsjs.d.ts b/js-bindings/blsjs.d.ts index 22e69d8e0..b6ea52b69 100644 --- a/js-bindings/blsjs.d.ts +++ b/js-bindings/blsjs.d.ts @@ -47,7 +47,6 @@ export declare class G1Element { deepcopy(): G1Element; get_fingerprint(): number; add(el: G1Element): G1Element; - mul(bn: Bignum): G1Element; equal_to(el: G1Element): boolean; delete(): void; } @@ -62,7 +61,6 @@ export declare class G2Element { negate(): G2Element; deepcopy(): G2Element; add(el: G2Element): G2Element; - mul(bn: Bignum): G2Element; equal_to(el: G2Element): boolean; delete(): void; } @@ -81,12 +79,6 @@ export declare class PrivateKey { delete(): void; } -export declare class Bignum { - static from_string(s: string, radix: number): Bignum; - toString(radix: number): string; - delete(): void; -} - export declare class Util { static hash256(msg: Uint8Array): Uint8Array; static hex_str(msg: Uint8Array): string; @@ -99,7 +91,6 @@ export interface ModuleInstance { G1Element: typeof G1Element; G2Element: typeof G2Element; PrivateKey: typeof PrivateKey; - Bignum: typeof Bignum; Util: typeof Util; } diff --git a/js-bindings/helpers.cpp b/js-bindings/helpers.cpp index e58f5e490..41a92a0a2 100644 --- a/js-bindings/helpers.cpp +++ b/js-bindings/helpers.cpp @@ -26,12 +26,6 @@ namespace helpers { return buffer; } - val toUint8Array(bn_t bn) { - std::vector vec = toVector(bn); - val buffer = toUint8Array(vec); - return buffer; - } - std::vector toVector(uint8_t *pointer, size_t data_size) { std::vector data; data.reserve(data_size); @@ -48,13 +42,6 @@ namespace helpers { return vec; } - std::vector toVector(bn_t bn) { - uint8_t buf[bn_size_bin(bn)]; - bn_write_bin(buf, bn_size_bin(bn), bn); - std::vector vec = helpers::toVector(buf, bn_size_bin(bn)); - return vec; - } - std::vector> jsBuffersArrayToVector(val buffersArray) { auto l = buffersArray["length"].as(); std::vector> vec; @@ -64,20 +51,6 @@ namespace helpers { return vec; } - std::vector jsBuffersArrayToBnVector(val buffersArray) { - auto l = buffersArray["length"].as(); - std::vector vec; - for (unsigned i = 0; i < l; ++i) { - bn_t data; - bn_new(data); - std::vector bnVec = toVector(buffersArray[i]); - bn_read_bin(data, bnVec.data(), static_cast(bnVec.size())); - bn_t *point = &data; - vec.push_back(point); - } - return vec; - } - val byteArraysVectorToJsBuffersArray(std::vector arraysVector, size_t element_size) { auto vecSize = arraysVector.size(); std::vector valVector; diff --git a/js-bindings/helpers.h b/js-bindings/helpers.h index 1d3d093fd..e48d52893 100644 --- a/js-bindings/helpers.h +++ b/js-bindings/helpers.h @@ -18,9 +18,6 @@ #include #include #include "emscripten/val.h" -extern "C" { -#include "relic.h" -} #include "../src/bls.hpp" using namespace emscripten; @@ -31,14 +28,10 @@ namespace helpers { val toUint8Array(std::vector vec); - val toUint8Array(bn_t bn); - std::vector toVector(uint8_t *pointer, size_t data_size); std::vector toVector(val jsBuffer); - std::vector toVector(bn_t bn); - template inline std::vector toVectorFromJSArray(val jsArray) { auto l = jsArray["length"].as(); @@ -62,8 +55,6 @@ namespace helpers { std::vector> jsBuffersArrayToVector(val buffersArray); - std::vector jsBuffersArrayToBnVector(val buffersArray); - val byteArraysVectorToJsBuffersArray(std::vector arraysVector, size_t element_size); } // namespace helpers diff --git a/js-bindings/jsbindings.cpp b/js-bindings/jsbindings.cpp index 038f55ce5..2e9eded88 100644 --- a/js-bindings/jsbindings.cpp +++ b/js-bindings/jsbindings.cpp @@ -70,7 +70,6 @@ EMSCRIPTEN_BINDINGS(blsjs) { .function("deepcopy", &G1ElementWrapper::Deepcopy) .function("get_fingerprint", &G1ElementWrapper::GetFingerprint) .function("add", &G1ElementWrapper::Add) - .function("mul", &G1ElementWrapper::Mul) .function("equal_to", &G1ElementWrapper::EqualTo); class_("G2Element") @@ -85,7 +84,6 @@ EMSCRIPTEN_BINDINGS(blsjs) { .function("negate", &G2ElementWrapper::Negate) .function("deepcopy", &G2ElementWrapper::Deepcopy) .function("add", &G2ElementWrapper::Add) - .function("mul", &G2ElementWrapper::Mul) .function("equal_to", &G2ElementWrapper::EqualTo); class_("PrivateKey") @@ -101,11 +99,6 @@ EMSCRIPTEN_BINDINGS(blsjs) { .function("mul_g2", &PrivateKeyWrapper::MulG2) .function("equal_to", &PrivateKeyWrapper::EqualTo); - class_("Bignum") - .class_function("fromString", &BignumWrapper::FromString) // Not removing this for compatibility - .class_function("from_string", &BignumWrapper::FromString) - .function("toString", &BignumWrapper::ToString); - class_("Util") .class_function("hash256", &UtilWrapper::Hash256) .class_function("hex_str", &UtilWrapper::HexStr); diff --git a/js-bindings/tests/test.js b/js-bindings/tests/test.js index d87dee101..7444e82cc 100644 --- a/js-bindings/tests/test.js +++ b/js-bindings/tests/test.js @@ -22,7 +22,6 @@ blsjs().then((blsjs) => { const modules = [ 'AugSchemeMPL', 'BasicSchemeMPL', - "Bignum", 'G1Element', 'G2Element', 'PopSchemeMPL', @@ -42,7 +41,6 @@ blsjs().then((blsjs) => { const { AugSchemeMPL, BasicSchemeMPL, - Bignum, G1Element, G2Element, PopSchemeMPL, @@ -380,17 +378,11 @@ blsjs().then((blsjs) => { assert(AugSchemeMPL.aggregate_verify([], [], new G2Element())); } - function test_bignum() { - const mersenne = Bignum.fromString('162259276829213363391578010288127', 10); - assert(mersenne.toString(16).toLowerCase() == '7ffffffffffffffffffffffffff'); - } - test_schemes(); test_vectors_invalid(); test_vectors_valid(); test_readme(); test_aggregate_verify_zero_items(); - test_bignum(); }).then(function() { console.log("\nAll tests passed."); }); diff --git a/js-bindings/wrappers/BignumWrapper.cpp b/js-bindings/wrappers/BignumWrapper.cpp deleted file mode 100644 index 5ff4da42f..000000000 --- a/js-bindings/wrappers/BignumWrapper.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2020 Chia Network Inc - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "../helpers.h" -#include "BignumWrapper.h" - -namespace js_wrappers { -Bignum::Bignum() { - bn_make(&content, 1); -} - -Bignum::~Bignum() { - bn_clean(&content); -} - -Bignum::Bignum(const Bignum &other) { - bn_copy(&content, &other.content); -} - -bn_st *Bignum::operator &() { return &content; } - -BignumWrapper::BignumWrapper(const Bignum &bn) : JSWrapper(bn) {} - -BignumWrapper BignumWrapper::FromString(const std::string &s, int radix) { - Bignum result; - bn_read_str(&result, s.c_str(), s.size(), radix); - return BignumWrapper(result); -} - -std::string BignumWrapper::ToString(int radix) { - auto wrapper = GetWrappedInstance(); - int strsize = bn_size_str(&wrapper, radix); - std::vector strholder(strsize); - bn_write_str(&strholder[0], strsize, &wrapper, radix); - return std::string(&strholder[0], strsize - 1); -} -} // namespace js_wrappers diff --git a/js-bindings/wrappers/BignumWrapper.h b/js-bindings/wrappers/BignumWrapper.h deleted file mode 100644 index ac8f79550..000000000 --- a/js-bindings/wrappers/BignumWrapper.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Chia Network Inc - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef JS_BINDINGS_WRAPPERS_BIGNUMWRAPPER_H_ -#define JS_BINDINGS_WRAPPERS_BIGNUMWRAPPER_H_ - -#include "../helpers.h" -#include "JSWrapper.h" - -namespace js_wrappers { -class Bignum { -public: - Bignum(); - ~Bignum(); - Bignum(const Bignum &other); - - bn_st *operator &(); - -private: - bn_st content; -}; - -class BignumWrapper : public JSWrapper { -public: - explicit BignumWrapper(const Bignum &bn); - static BignumWrapper FromString(const std::string &s, int radix); - std::string ToString(int radix); -}; -} // namespace js_wrappers - -#endif // JS_BINDINGS_WRAPPERS_SIGNATUREWRAPPER_H_ diff --git a/js-bindings/wrappers/G1ElementWrapper.cpp b/js-bindings/wrappers/G1ElementWrapper.cpp index 0d6305148..f623a5062 100644 --- a/js-bindings/wrappers/G1ElementWrapper.cpp +++ b/js-bindings/wrappers/G1ElementWrapper.cpp @@ -44,16 +44,6 @@ G1ElementWrapper G1ElementWrapper::Add(const G1ElementWrapper &other) { return G1ElementWrapper(GetWrappedInstance() + other.GetWrappedInstance()); } -G1ElementWrapper G1ElementWrapper::Mul(const BignumWrapper &other) { - bn_t factor; - // Since the type of bn_t is bn_st[0], we can do this dance to make a temporary - // copy of the struct itself to hand to G1ElementWrapper's multiply. The - // type was clearly intended to by by-value in argument lists (degrade to ptr) - // but value semantics in C++ complicates matters. - factor[0] = *(&other.GetWrappedInstance()); - return G1ElementWrapper(GetWrappedInstance() * factor); -} - bool G1ElementWrapper::EqualTo(const G1ElementWrapper &others) { return GetWrappedInstance() == others.GetWrappedInstance(); } diff --git a/js-bindings/wrappers/G1ElementWrapper.h b/js-bindings/wrappers/G1ElementWrapper.h index c65d11573..495c43b32 100644 --- a/js-bindings/wrappers/G1ElementWrapper.h +++ b/js-bindings/wrappers/G1ElementWrapper.h @@ -17,7 +17,6 @@ #include "../helpers.h" #include "JSWrapper.h" -#include "BignumWrapper.h" namespace js_wrappers { class G1ElementWrapper : public JSWrapper { @@ -38,8 +37,6 @@ class G1ElementWrapper : public JSWrapper { G1ElementWrapper Add(const G1ElementWrapper &other); - G1ElementWrapper Mul(const BignumWrapper &other); - bool EqualTo(const G1ElementWrapper &others); G1ElementWrapper Negate(); diff --git a/js-bindings/wrappers/G2ElementWrapper.cpp b/js-bindings/wrappers/G2ElementWrapper.cpp index 980a7dd8e..de4a208f5 100644 --- a/js-bindings/wrappers/G2ElementWrapper.cpp +++ b/js-bindings/wrappers/G2ElementWrapper.cpp @@ -67,16 +67,6 @@ G2ElementWrapper G2ElementWrapper::Add(const G2ElementWrapper& other) { return G2ElementWrapper(GetWrappedInstance() + other.GetWrappedInstance()); } -G2ElementWrapper G2ElementWrapper::Mul(const BignumWrapper& other) { - bn_t factor; - // Since the type of bn_t is bn_st[0], we can do this dance to make a - // temporary copy of the struct itself to hand to G2ElementWrapper's - // multiply. The type was clearly intended to by by-value in argument lists - // (degrade to ptr) but value semantics in C++ complicates matters. - factor[0] = *(&other.GetWrappedInstance()); - return G2ElementWrapper(GetWrappedInstance() * factor); -} - bool G2ElementWrapper::EqualTo(const G2ElementWrapper& others) { return GetWrappedInstance() == others.GetWrappedInstance(); } diff --git a/js-bindings/wrappers/G2ElementWrapper.h b/js-bindings/wrappers/G2ElementWrapper.h index 6f53e0ba7..cc21197ee 100644 --- a/js-bindings/wrappers/G2ElementWrapper.h +++ b/js-bindings/wrappers/G2ElementWrapper.h @@ -17,7 +17,6 @@ #include "../helpers.h" #include "JSWrapper.h" -#include "BignumWrapper.h" namespace js_wrappers { class G2ElementWrapper : public JSWrapper { @@ -46,8 +45,6 @@ class G2ElementWrapper : public JSWrapper { G2ElementWrapper Add(const G2ElementWrapper &other); - G2ElementWrapper Mul(const BignumWrapper &other); - bool EqualTo(const G2ElementWrapper &others); }; } // namespace js_wrappers diff --git a/python-bindings/CMakeLists.txt b/python-bindings/CMakeLists.txt index 364386696..9ddc24e33 100644 --- a/python-bindings/CMakeLists.txt +++ b/python-bindings/CMakeLists.txt @@ -2,10 +2,9 @@ FetchContent_Declare( pybind11 GIT_REPOSITORY https://github.com/pybind/pybind11.git - GIT_TAG v2.10.0 + GIT_TAG v2.10.0 ) FetchContent_MakeAvailable(pybind11) pybind11_add_module(blspy ${CMAKE_CURRENT_SOURCE_DIR}/pythonbindings.cpp) target_link_libraries(blspy PRIVATE bls) -handle_mpir_dlls(blspy) diff --git a/python-bindings/README.md b/python-bindings/README.md index 0de31c9a8..0bae6e973 100644 --- a/python-bindings/README.md +++ b/python-bindings/README.md @@ -16,7 +16,6 @@ pip3 install . ``` Cmake, a c++ compiler, and a recent version of pip3 (v18) are required for source install. -GMP(speed) is an optional dependency. Public keys are G1Elements, and signatures are G2Elements. Then, to use: diff --git a/python-bindings/pythonbindings.cpp b/python-bindings/pythonbindings.cpp index 402759f39..fcfd58daf 100644 --- a/python-bindings/pythonbindings.cpp +++ b/python-bindings/pythonbindings.cpp @@ -442,20 +442,6 @@ PYBIND11_MODULE(blspy, m) return self + other; }, py::is_operator()) - .def( - "__mul__", - [](G1Element &self, bn_t other) { - py::gil_scoped_release release; - return self * (*(bn_t *)&other); - }, - py::is_operator()) - .def( - "__rmul__", - [](G1Element &self, bn_t other) { - py::gil_scoped_release release; - return self * (*(bn_t *)&other); - }, - py::is_operator()) .def( "__and__", [](G1Element &self, G2Element &other) { @@ -588,21 +574,6 @@ PYBIND11_MODULE(blspy, m) return self + other; }, py::is_operator()) - .def( - "__mul__", - [](G2Element &self, bn_t other) { - py::gil_scoped_release release; - return self * (*(bn_t *)&other); - }, - py::is_operator()) - .def( - "__rmul__", - [](G2Element &self, bn_t other) { - py::gil_scoped_release release; - return self * (*(bn_t *)&other); - }, - py::is_operator()) - .def( "__repr__", [](const G2Element &ele) { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd99ba976..0258c739a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,66 +1,77 @@ - file(GLOB HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) source_group("SrcHeaders" FILES ${HEADERS}) -add_library(bls +list(APPEND bls_sources ${HEADERS} - ${CMAKE_CURRENT_SOURCE_DIR}/privatekey.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/bls.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/elements.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/schemes.cpp -) - -target_include_directories(bls - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} - $<$:${GMP_INCLUDES}> - ${relic_SOURCE_DIR}/include - ${relic_BINARY_DIR}/include + privatekey.cpp + bls.cpp + elements.cpp + schemes.cpp + ${blst_SOURCE_DIR}/src/server.c ) -target_compile_definitions(bls - PRIVATE - BLSALLOC_SODIUM=1 -) +if(MSVC) + list(APPEND bls_sources + ${blst_SOURCE_DIR}/build/win64/add_mod_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/add_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/add_mod_384x384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ct_inverse_mod_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ct_is_square_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ctq_inverse_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/div3w-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/mulq_mont_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/mulq_mont_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/sha256-x86_64.asm + ) +else() + list(APPEND bls_sources + ${blst_SOURCE_DIR}/build/assembly.S + ) + add_compile_options(-fno-builtin) + add_compile_options(-fPIC) + add_compile_options(-Wall) + add_compile_options(-Wextra) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + add_compile_options(-mno-avx) + endif() +endif() -target_link_libraries(bls - PUBLIC - relic_s - sodium -) +add_library(bls ${bls_sources}) +target_include_directories(bls PUBLIC ${blst_SOURCE_DIR}) +target_compile_definitions(bls PRIVATE __BLST_PORTABLE__ BLSALLOC_SODIUM=1) +target_link_libraries(bls PUBLIC sodium) if(WITH_COVERAGE) target_compile_options(bls PRIVATE --coverage) target_link_options(bls PRIVATE --coverage) endif() -install(DIRECTORY ${relic_SOURCE_DIR}/include/ DESTINATION include/chiabls) -install(DIRECTORY ${relic_BINARY_DIR}/include/ DESTINATION include/chiabls) +install(DIRECTORY ${blst_SOURCE_DIR}/include/ DESTINATION include/chiabls) +install(DIRECTORY ${blst_BINARY_DIR}/include/ DESTINATION include/chiabls) install(FILES ${HEADERS} DESTINATION include/chiabls) install(FILES $ DESTINATION lib) -if(MSVC AND (BUILD_BLS_TESTS OR BUILD_BLS_BENCHMARKS)) - handle_mpir_dlls(bls) -endif() - if(BUILD_BLS_TESTS) FetchContent_Declare( Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v3.3.2 + GIT_TAG v3.3.2 ) FetchContent_MakeAvailable(Catch2) find_package(Threads REQUIRED) add_executable(runtest test.cpp) + if(EMSCRIPTEN) target_link_options(runtest PRIVATE "-sEXPORTED_FUNCTIONS=_malloc") endif() + target_link_libraries(runtest PRIVATE - bls - Catch2::Catch2 - Threads::Threads + bls + Catch2::Catch2 + Threads::Threads ) + if(WITH_COVERAGE) target_compile_options(runtest PRIVATE --coverage) target_link_options(runtest PRIVATE --coverage) diff --git a/src/bls.cpp b/src/bls.cpp index 17e8e4c1f..a67b62101 100644 --- a/src/bls.cpp +++ b/src/bls.cpp @@ -27,24 +27,8 @@ bool BLSInitResult = BLS::Init(); Util::SecureAllocCallback Util::secureAllocCallback; Util::SecureFreeCallback Util::secureFreeCallback; -static void relic_core_initializer(void* ptr) -{ - core_init(); - if (err_get_code() != RLC_OK) { - throw std::runtime_error("core_init() failed"); - } - - const int r = ep_param_set_any_pairf(); - if (r != RLC_OK) { - throw std::runtime_error("ep_param_set_any_pairf() failed"); - } -} - bool BLS::Init() { - if (ALLOC != AUTO) { - throw std::runtime_error("Must have ALLOC == AUTO"); - } #if BLSALLOC_SODIUM if (sodium_init() < 0) { throw std::runtime_error("libsodium init failed"); @@ -54,12 +38,6 @@ bool BLS::Init() SetSecureAllocator(malloc, free); #endif -#if MULTI != RELIC_NONE - core_set_thread_initializer(relic_core_initializer, nullptr); -#else - relic_core_initializer(nullptr); -#endif - return true; } @@ -71,16 +49,4 @@ void BLS::SetSecureAllocator( Util::secureFreeCallback = freeCb; } - -void BLS::CheckRelicErrors() -{ - if (!core_get()) { - throw std::runtime_error("Library not initialized properly. Call BLS::Init()"); - } - if (core_get()->code != RLC_OK) { - core_get()->code = RLC_OK; - throw std::invalid_argument("Relic library error"); - } -} - } // end namespace bls diff --git a/src/bls.hpp b/src/bls.hpp index 77d653af2..0381fc597 100644 --- a/src/bls.hpp +++ b/src/bls.hpp @@ -36,8 +36,6 @@ class BLS { static bool Init(); static void SetSecureAllocator(Util::SecureAllocCallback allocCb, Util::SecureFreeCallback freeCb); - - static void CheckRelicErrors(); }; } // end namespace bls diff --git a/src/elements.cpp b/src/elements.cpp index 1ad87f86c..bdb3bc6ec 100644 --- a/src/elements.cpp +++ b/src/elements.cpp @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include #include "bls.hpp" @@ -20,7 +22,8 @@ namespace bls { const size_t G1Element::SIZE; -G1Element G1Element::FromBytes(Bytes const bytes) { +G1Element G1Element::FromBytes(Bytes const bytes) +{ G1Element ele = G1Element::FromBytesUnchecked(bytes); ele.CheckValid(); return ele; @@ -32,21 +35,17 @@ G1Element G1Element::FromBytesUnchecked(Bytes const bytes) throw std::invalid_argument("G1Element::FromBytes: Invalid size"); } - G1Element ele; - - // convert bytes to relic form - uint8_t buffer[G1Element::SIZE + 1]; - std::memcpy(buffer + 1, bytes.begin(), G1Element::SIZE); - buffer[0] = 0x00; - buffer[1] &= 0x1f; // erase 3 msbs from given input - - bool fZerosOnly = Util::HasOnlyZeros(Bytes(buffer, G1Element::SIZE + 1)); + // check if the element is canonical + const uint8_t* raw_bytes = bytes.begin(); + bool fZerosOnly = + Util::HasOnlyZeros(Bytes(raw_bytes + 1, bytes.size() - 1)); if ((bytes[0] & 0xc0) == 0xc0) { // representing infinity // enforce that infinity must be 0xc0000..00 if (bytes[0] != 0xc0 || !fZerosOnly) { - throw std::invalid_argument("Given G1 infinity element must be canonical"); + throw std::invalid_argument( + "Given G1 infinity element must be canonical"); } - return ele; + return G1Element(); // return infinity element (point all zero) } else { if ((bytes[0] & 0xc0) != 0x80) { throw std::invalid_argument( @@ -54,18 +53,17 @@ G1Element G1Element::FromBytesUnchecked(Bytes const bytes) } if (fZerosOnly) { - throw std::invalid_argument("G1 non-infinity element can't have only zeros"); - } - - if (bytes[0] & 0x20) { // sign bit - buffer[0] = 0x03; - } else { - buffer[0] = 0x02; + throw std::invalid_argument( + "G1 non-infinity element can't have only zeros"); } } - g1_read_bin(ele.p, buffer, G1Element::SIZE + 1); - BLS::CheckRelicErrors(); - return ele; + + blst_p1_affine a; + BLST_ERROR err = blst_p1_uncompress(&a, bytes.begin()); + if (err != BLST_SUCCESS) + throw std::invalid_argument("G1Element::FromBytes: Invalid bytes"); + + return G1Element::FromAffine(a); } G1Element G1Element::FromByteVector(const std::vector& bytevec) @@ -73,27 +71,46 @@ G1Element G1Element::FromByteVector(const std::vector& bytevec) return G1Element::FromBytes(Bytes(bytevec)); } -G1Element G1Element::FromNative(const g1_t element) +G1Element G1Element::FromNative(const blst_p1& element) { G1Element ele; - g1_copy(ele.p, element); + memcpy(&(ele.p), &element, sizeof(blst_p1)); return ele; } -G1Element G1Element::FromMessage(const std::vector& message, - const uint8_t* dst, - int dst_len) +G1Element G1Element::FromAffine(const blst_p1_affine& element) +{ + G1Element ele; + blst_p1_from_affine(&(ele.p), &element); + return ele; +} + +G1Element G1Element::FromMessage( + const std::vector& message, + const uint8_t* dst, + int dst_len) { return FromMessage(Bytes(message), dst, dst_len); } -G1Element G1Element::FromMessage(Bytes const message, - const uint8_t* dst, - int dst_len) +G1Element G1Element::FromMessage( + Bytes const message, + const uint8_t* dst, + int dst_len) { G1Element ans; - ep_map_dst(ans.p, message.begin(), (int)message.size(), dst, dst_len); - BLS::CheckRelicErrors(); + const byte* aug = nullptr; + size_t aug_len = 0; + + blst_hash_to_g1( + &(ans.p), + message.begin(), + (int)message.size(), + dst, + dst_len, + aug, + aug_len); + assert(ans.IsValid()); return ans; } @@ -101,35 +118,42 @@ G1Element G1Element::FromMessage(Bytes const message, G1Element G1Element::Generator() { G1Element ele; - g1_get_gen(ele.p); - BLS::CheckRelicErrors(); + ele.p = *(blst_p1_generator()); return ele; } -bool G1Element::IsValid() const { - // Infinity no longer valid in Relic - // https://github.com/relic-toolkit/relic/commit/f3be2babb955cf9f82743e0ae5ef265d3da6c02b - if (g1_is_infty((g1_st*)p) == 1) +bool G1Element::IsValid() const +{ + // Infinity was considered a valid G1Element in older Relic versions + // on which this library was previously based. + // For historical compatibililty this behavior is maintained. + + if (blst_p1_is_inf(&p)) return true; - return g1_is_valid((g1_st*)p); + return blst_p1_in_g1(&p); } -void G1Element::CheckValid() const { +void G1Element::CheckValid() const +{ if (!IsValid()) throw std::invalid_argument("G1 element is invalid"); - BLS::CheckRelicErrors(); } -void G1Element::ToNative(g1_t output) const { - g1_copy(output, p); +void G1Element::ToNative(blst_p1* output) const +{ + memcpy(output, &p, sizeof(blst_p1)); +} + +void G1Element::ToAffine(blst_p1_affine* output) const +{ + blst_p1_to_affine(output, &p); } G1Element G1Element::Negate() const { - G1Element ans; - g1_neg(ans.p, p); - BLS::CheckRelicErrors(); + G1Element ans = G1Element::FromNative(p); + blst_p1_cneg(&(ans.p), true); return ans; } @@ -144,70 +168,57 @@ uint32_t G1Element::GetFingerprint() const return Util::FourBytesToInt(hash); } -std::vector G1Element::Serialize() const { - uint8_t buffer[G1Element::SIZE + 1]; - g1_write_bin(buffer, G1Element::SIZE + 1, p, 1); - - if (buffer[0] == 0x00) { // infinity - std::vector result(G1Element::SIZE, 0); - result[0] = 0xc0; - return result; - } - - if (buffer[0] == 0x03) { // sign bit set - buffer[1] |= 0x20; - } - - buffer[1] |= 0x80; // indicate compression - return std::vector(buffer + 1, buffer + 1 + G1Element::SIZE); +std::vector G1Element::Serialize() const +{ + uint8_t buffer[G1Element::SIZE]; + blst_p1_compress(buffer, &p); + return std::vector(buffer, buffer + G1Element::SIZE); } -bool operator==(const G1Element & a, const G1Element &b) +bool operator==(const G1Element& a, const G1Element& b) { - return g1_cmp(a.p, b.p) == RLC_EQ; + return blst_p1_is_equal(&(a.p), &(b.p)); } -bool operator!=(const G1Element & a, const G1Element & b) { return !(a == b); } +bool operator!=(const G1Element& a, const G1Element& b) { return !(a == b); } -std::ostream& operator<<(std::ostream& os, const G1Element &ele) +std::ostream& operator<<(std::ostream& os, const G1Element& ele) { return os << Util::HexStr(ele.Serialize()); } G1Element& operator+=(G1Element& a, const G1Element& b) { - g1_add(a.p, a.p, b.p); - BLS::CheckRelicErrors(); + blst_p1_add_or_double(&(a.p), &(a.p), &(b.p)); return a; } G1Element operator+(const G1Element& a, const G1Element& b) { G1Element ans; - g1_add(ans.p, a.p, b.p); - BLS::CheckRelicErrors(); + blst_p1_add_or_double(&(ans.p), &(a.p), &(b.p)); return ans; } -G1Element operator*(const G1Element& a, const bn_t& k) +G1Element operator*(const G1Element& a, const blst_scalar& k) { G1Element ans; - g1_mul(ans.p, (g1_st*)a.p, (bn_st*)k); - BLS::CheckRelicErrors(); + byte* bte = Util::SecAlloc(32); + blst_bendian_from_scalar(bte, &k); + blst_p1_mult(&(ans.p), &(a.p), bte, 256); + Util::SecFree(bte); + return ans; } -G1Element operator*(const bn_t& k, const G1Element& a) { return a * k; } - - +G1Element operator*(const blst_scalar& k, const G1Element& a) { return a * k; } // G2Element definitions below - - const size_t G2Element::SIZE; -G2Element G2Element::FromBytes(Bytes const bytes) { +G2Element G2Element::FromBytes(Bytes const bytes) +{ G2Element ele = G2Element::FromBytesUnchecked(bytes); ele.CheckValid(); return ele; @@ -219,45 +230,12 @@ G2Element G2Element::FromBytesUnchecked(Bytes const bytes) throw std::invalid_argument("G2Element::FromBytes: Invalid size"); } - G2Element ele; - uint8_t buffer[G2Element::SIZE + 1]; - std::memcpy(buffer + 1, bytes.begin() + G2Element::SIZE / 2, G2Element::SIZE / 2); - std::memcpy(buffer + 1 + G2Element::SIZE / 2, bytes.begin(), G2Element::SIZE / 2); - buffer[0] = 0x00; - buffer[49] &= 0x1f; // erase 3 msbs from input - - if ((bytes[48] & 0xe0) != 0x00) { - throw std::invalid_argument( - "Given G2 element must always have 48th byte start with 0b000"); - } - bool fZerosOnly = Util::HasOnlyZeros(Bytes(buffer, G2Element::SIZE + 1)); - if (((bytes[0] & 0xc0) == 0xc0)) { // infinity - // enforce that infinity must be 0xc0000..00 - if (bytes[0] != 0xc0 || !fZerosOnly) { - throw std::invalid_argument( - "Given G2 infinity element must be canonical"); - } - return ele; - } else { - if (((bytes[0] & 0xc0) != 0x80)) { - throw std::invalid_argument( - "G2 non-inf element must have 0th byte start with 0b10"); - } - - if (fZerosOnly) { - throw std::invalid_argument("G2 non-infinity element can't have only zeros"); - } - - if (bytes[0] & 0x20) { - buffer[0] = 0x03; - } else { - buffer[0] = 0x02; - } - } + blst_p2_affine a; + BLST_ERROR err = blst_p2_uncompress(&a, bytes.begin()); + if (err != BLST_SUCCESS) + throw std::invalid_argument("G2Element::FromBytes: Invalid bytes"); - g2_read_bin(ele.q, buffer, G2Element::SIZE + 1); - BLS::CheckRelicErrors(); - return ele; + return G2Element::FromAffine(a); } G2Element G2Element::FromByteVector(const std::vector& bytevec) @@ -265,27 +243,46 @@ G2Element G2Element::FromByteVector(const std::vector& bytevec) return G2Element::FromBytes(Bytes(bytevec)); } -G2Element G2Element::FromNative(const g2_t element) +G2Element G2Element::FromNative(const blst_p2& element) { G2Element ele; - g2_copy(ele.q, (g2_st*)element); + memcpy(&(ele.q), &element, sizeof(blst_p2)); return ele; } -G2Element G2Element::FromMessage(const std::vector& message, - const uint8_t* dst, - int dst_len) +G2Element G2Element::FromAffine(const blst_p2_affine& element) +{ + G2Element ele; + blst_p2_from_affine(&(ele.q), &element); + return ele; +} + +G2Element G2Element::FromMessage( + const std::vector& message, + const uint8_t* dst, + int dst_len) { return FromMessage(Bytes(message), dst, dst_len); } -G2Element G2Element::FromMessage(Bytes const message, - const uint8_t* dst, - int dst_len) +G2Element G2Element::FromMessage( + Bytes const message, + const uint8_t* dst, + int dst_len) { G2Element ans; - ep2_map_dst(ans.q, message.begin(), (int)message.size(), dst, dst_len); - BLS::CheckRelicErrors(); + const byte* aug = nullptr; + size_t aug_len = 0; + + blst_hash_to_g2( + &(ans.q), + message.begin(), + (int)message.size(), + dst, + dst_len, + aug, + aug_len); + assert(ans.IsValid()); return ans; } @@ -293,114 +290,108 @@ G2Element G2Element::FromMessage(Bytes const message, G2Element G2Element::Generator() { G2Element ele; - g2_get_gen(ele.q); - BLS::CheckRelicErrors(); + ele.q = (*blst_p2_generator()); return ele; } -bool G2Element::IsValid() const { - // Infinity no longer valid in Relic - // https://github.com/relic-toolkit/relic/commit/f3be2babb955cf9f82743e0ae5ef265d3da6c02b - if (g2_is_infty((g2_st*)q) == 1) +bool G2Element::IsValid() const +{ + // Infinity was considered a valid G2Element in older Relic versions + // on which this library was previously based. + // For historical compatibililty this behavior is maintained. + + if (blst_p2_is_inf(&q)) return true; - return g2_is_valid((g2_st*)q); + return blst_p2_in_g2(&q); } -void G2Element::CheckValid() const { +void G2Element::CheckValid() const +{ if (!IsValid()) throw std::invalid_argument("G2 element is invalid"); - BLS::CheckRelicErrors(); } -void G2Element::ToNative(g2_t output) const { - g2_copy(output, (g2_st*)q); +void G2Element::ToNative(blst_p2* output) const +{ + memcpy(output, (blst_p2*)&q, sizeof(blst_p2)); +} + +void G2Element::ToAffine(blst_p2_affine* output) const +{ + blst_p2_to_affine(output, &q); } G2Element G2Element::Negate() const { - G2Element ans; - g2_neg(ans.q, (g2_st*)q); - BLS::CheckRelicErrors(); + G2Element ans = G2Element::FromNative(q); + blst_p2_cneg(&(ans.q), true); return ans; } GTElement G2Element::Pair(const G1Element& a) const { return a & (*this); } -std::vector G2Element::Serialize() const { - uint8_t buffer[G2Element::SIZE + 1]; - g2_write_bin(buffer, G2Element::SIZE + 1, (g2_st*)q, 1); - - if (buffer[0] == 0x00) { // infinity - std::vector result(G2Element::SIZE, 0); - result[0] = 0xc0; - return result; - } - - // remove leading 3 bits - buffer[1] &= 0x1f; - buffer[49] &= 0x1f; - if (buffer[0] == 0x03) { - buffer[49] |= 0xa0; // swapped later to 0 - } else { - buffer[49] |= 0x80; - } - - // Swap buffer, relic uses the opposite ordering for Fq2 elements - std::vector result(G2Element::SIZE, 0); - std::memcpy(result.data(), buffer + 1 + G2Element::SIZE / 2, G2Element::SIZE / 2); - std::memcpy(result.data() + G2Element::SIZE / 2, buffer + 1, G2Element::SIZE / 2); - return result; +std::vector G2Element::Serialize() const +{ + uint8_t buffer[G2Element::SIZE]; + blst_p2_compress(buffer, &q); + return std::vector(buffer, buffer + G2Element::SIZE); } bool operator==(G2Element const& a, G2Element const& b) { - return g2_cmp((g2_st*)a.q, (g2_st*)b.q) == RLC_EQ; + return blst_p2_is_equal(&(a.q), &(b.q)); } bool operator!=(G2Element const& a, G2Element const& b) { return !(a == b); } -std::ostream& operator<<(std::ostream& os, const G2Element & s) +std::ostream& operator<<(std::ostream& os, const G2Element& s) { return os << Util::HexStr(s.Serialize()); } G2Element& operator+=(G2Element& a, const G2Element& b) { - g2_add(a.q, a.q, (g2_st*)b.q); - BLS::CheckRelicErrors(); + blst_p2_add_or_double(&(a.q), &(a.q), &(b.q)); return a; } G2Element operator+(const G2Element& a, const G2Element& b) { G2Element ans; - g2_add(ans.q, (g2_st*)a.q, (g2_st*)b.q); - BLS::CheckRelicErrors(); + blst_p2_add_or_double(&(ans.q), &(a.q), &(b.q)); return ans; } -G2Element operator*(const G2Element& a, const bn_t& k) +G2Element operator*(const G2Element& a, const blst_scalar& k) { G2Element ans; - g2_mul(ans.q, (g2_st*)a.q, (bn_st*)k); - BLS::CheckRelicErrors(); + byte* bte = Util::SecAlloc(32); + blst_bendian_from_scalar(bte, &k); + blst_p2_mult(&(ans.q), &(a.q), bte, 256); + Util::SecFree(bte); + return ans; } -G2Element operator*(const bn_t& k, const G2Element& a) { return a * k; } - - +G2Element operator*(const blst_scalar& k, const G2Element& a) { return a * k; } // GTElement const size_t GTElement::SIZE; +/* + * Currently deserliazation is not available - these are currently + * broken and just return the zero element + */ GTElement GTElement::FromBytes(Bytes const bytes) { GTElement ele = GTElement::FromBytesUnchecked(bytes); - if (gt_is_valid(*(gt_t*)&ele) == 0) - throw std::invalid_argument("GTElement is invalid"); + // + // this doesn't seem to be the proper check as it doesn't work as expeced + // + // if (!blst_fp12_in_group(&(ele.r))) + // throw std::invalid_argument("GTElement is invalid"); return ele; } @@ -410,8 +401,7 @@ GTElement GTElement::FromBytesUnchecked(Bytes const bytes) throw std::invalid_argument("GTElement::FromBytes: Invalid size"); } GTElement ele = GTElement(); - gt_read_bin(ele.r, bytes.begin(), GTElement::SIZE); - BLS::CheckRelicErrors(); + memcpy(&(ele.r), bytes.begin(), SIZE); return ele; } @@ -420,23 +410,37 @@ GTElement GTElement::FromByteVector(const std::vector& bytevec) return GTElement::FromBytes(Bytes(bytevec)); } -GTElement GTElement::FromNative(const gt_t* element) +GTElement GTElement::FromNative(const blst_fp12* element) { GTElement ele = GTElement(); - gt_copy(ele.r, *(gt_t*)element); + ele.r = *element; return ele; } -GTElement GTElement::Unity() { +GTElement GTElement::FromAffine(const blst_p1_affine& affine) +{ GTElement ele = GTElement(); - gt_set_unity(ele.r); + blst_aggregated_in_g1(&ele.r, &affine); return ele; } +GTElement GTElement::FromAffine(const blst_p2_affine& affine) +{ + GTElement ele = GTElement(); + blst_aggregated_in_g2(&ele.r, &affine); + return ele; +} + +GTElement GTElement::Unity() +{ + GTElement ele = GTElement(); + ele.FromNative(blst_fp12_one()); + return ele; +} bool operator==(GTElement const& a, GTElement const& b) { - return gt_cmp(*(gt_t*)(a.r), *(gt_t*)(b.r)) == RLC_EQ; + return blst_fp12_is_equal(&(a.r), &(b.r)); } bool operator!=(GTElement const& a, GTElement const& b) { return !(a == b); } @@ -448,31 +452,31 @@ std::ostream& operator<<(std::ostream& os, GTElement const& ele) GTElement operator&(const G1Element& a, const G2Element& b) { - G1Element nonConstA(a); - gt_t ans; - gt_new(ans); - g2_t tmp; - g2_null(tmp); - g2_new(tmp); - b.ToNative(tmp); - pp_map_oatep_k12(ans, nonConstA.p, tmp); + blst_fp12 ans; + + blst_p1_affine aff1; + blst_p2_affine aff2; + a.ToAffine(&aff1); + b.ToAffine(&aff2); + + blst_miller_loop(&ans, &aff2, &aff1); + blst_final_exp(&ans, &ans); + GTElement ret = GTElement::FromNative(&ans); - gt_free(ans); - g2_free(tmp); + return ret; } GTElement operator*(GTElement& a, GTElement& b) { GTElement ans; - fp12_mul(ans.r, a.r, b.r); - BLS::CheckRelicErrors(); + blst_fp12_mul(&(ans.r), &(a.r), &(b.r)); return ans; } void GTElement::Serialize(uint8_t* buffer) const { - gt_write_bin(buffer, GTElement::SIZE, *(gt_t*)&r, 1); + memcpy(buffer, &r, GTElement::SIZE); } std::vector GTElement::Serialize() const diff --git a/src/elements.hpp b/src/elements.hpp index 6c9bbeff5..af7dd6e25 100644 --- a/src/elements.hpp +++ b/src/elements.hpp @@ -16,17 +16,12 @@ #define SRC_BLSELEMENTS_HPP_ extern "C" { -#include "relic.h" +#include "bindings/blst.h" } -#include "relic_conf.h" -#include "util.hpp" - -#if defined GMP && ARITH == GMP -#include -#endif - #include +#include "util.hpp" + namespace bls { class G1Element; class G2Element; @@ -36,25 +31,27 @@ class G1Element { public: static const size_t SIZE = 48; - G1Element() { - g1_set_infty(p); - } + G1Element() { memset(&p, 0x00, sizeof(blst_p1)); } static G1Element FromBytes(Bytes bytes); static G1Element FromBytesUnchecked(Bytes bytes); static G1Element FromByteVector(const std::vector &bytevec); - static G1Element FromNative(const g1_t element); - static G1Element FromMessage(const std::vector &message, - const uint8_t *dst, - int dst_len); - static G1Element FromMessage(Bytes message, - const uint8_t* dst, - int dst_len); + static G1Element FromNative(const blst_p1 &element); + static G1Element FromAffine(const blst_p1_affine &element); + static G1Element FromMessage( + const std::vector &message, + const uint8_t *dst, + int dst_len); + static G1Element FromMessage( + Bytes message, + const uint8_t *dst, + int dst_len); static G1Element Generator(); bool IsValid() const; void CheckValid() const; - void ToNative(g1_t output) const; + void ToNative(blst_p1 *output) const; + void ToAffine(blst_p1_affine *output) const; G1Element Negate() const; GTElement Pair(const G2Element &b) const; uint32_t GetFingerprint() const; @@ -63,39 +60,41 @@ class G1Element { friend bool operator==(const G1Element &a, const G1Element &b); friend bool operator!=(const G1Element &a, const G1Element &b); friend std::ostream &operator<<(std::ostream &os, const G1Element &s); - friend G1Element& operator+=(G1Element& a, const G1Element& b); + friend G1Element &operator+=(G1Element &a, const G1Element &b); friend G1Element operator+(const G1Element &a, const G1Element &b); - friend G1Element operator*(const G1Element &a, const bn_t &k); - friend G1Element operator*(const bn_t &k, const G1Element &a); + friend G1Element operator*(const G1Element &a, const blst_scalar &k); + friend G1Element operator*(const blst_scalar &k, const G1Element &a); friend GTElement operator&(const G1Element &a, const G2Element &b); private: - g1_t p; + blst_p1 p; }; class G2Element { public: static const size_t SIZE = 96; - G2Element() { - g2_set_infty(q); - } + G2Element() { memset(&q, 0x00, sizeof(blst_p2)); } static G2Element FromBytes(Bytes bytes); static G2Element FromBytesUnchecked(Bytes bytes); static G2Element FromByteVector(const std::vector &bytevec); - static G2Element FromNative(const g2_t element); - static G2Element FromMessage(const std::vector& message, - const uint8_t* dst, - int dst_len); - static G2Element FromMessage(Bytes message, - const uint8_t* dst, - int dst_len); + static G2Element FromNative(const blst_p2 &element); + static G2Element FromAffine(const blst_p2_affine &element); + static G2Element FromMessage( + const std::vector &message, + const uint8_t *dst, + int dst_len); + static G2Element FromMessage( + Bytes message, + const uint8_t *dst, + int dst_len); static G2Element Generator(); bool IsValid() const; void CheckValid() const; - void ToNative(g2_t output) const; + void ToNative(blst_p2 *output) const; + void ToAffine(blst_p2_affine *output) const; G2Element Negate() const; GTElement Pair(const G1Element &a) const; std::vector Serialize() const; @@ -103,22 +102,25 @@ class G2Element { friend bool operator==(G2Element const &a, G2Element const &b); friend bool operator!=(G2Element const &a, G2Element const &b); friend std::ostream &operator<<(std::ostream &os, const G2Element &s); - friend G2Element& operator+=(G2Element& a, const G2Element& b); + friend G2Element &operator+=(G2Element &a, const G2Element &b); friend G2Element operator+(const G2Element &a, const G2Element &b); - friend G2Element operator*(const G2Element &a, const bn_t &k); - friend G2Element operator*(const bn_t &k, const G2Element &a); + friend G2Element operator*(const G2Element &a, const blst_scalar &k); + friend G2Element operator*(const blst_scalar &k, const G2Element &a); private: - g2_t q; + blst_p2 q; }; class GTElement { public: - static const size_t SIZE = 384; + static const size_t SIZE = sizeof(blst_fp12); + static GTElement FromBytes(Bytes bytes); static GTElement FromBytesUnchecked(Bytes bytes); static GTElement FromByteVector(const std::vector &bytevec); - static GTElement FromNative(const gt_t *element); + static GTElement FromNative(const blst_fp12 *element); + static GTElement FromAffine(const blst_p1_affine &element); + static GTElement FromAffine(const blst_p2_affine &element); static GTElement Unity(); // unity void Serialize(uint8_t *buffer) const; @@ -128,10 +130,9 @@ class GTElement { friend bool operator!=(GTElement const &a, GTElement const &b); friend std::ostream &operator<<(std::ostream &os, const GTElement &s); friend GTElement operator*(GTElement &a, GTElement &b); - GTElement &operator=(const GTElement &rhs); private: - gt_t r; + blst_fp12 r; GTElement() {} }; diff --git a/src/hdkeys.hpp b/src/hdkeys.hpp index 629ec5e3d..3c8295454 100644 --- a/src/hdkeys.hpp +++ b/src/hdkeys.hpp @@ -15,16 +15,11 @@ #ifndef SRC_BLSHDKEYS_HPP_ #define SRC_BLSHDKEYS_HPP_ -#include "relic_conf.h" #include -#if defined GMP && ARITH == GMP -#include -#endif - -#include "util.hpp" -#include "privatekey.hpp" #include "hkdf.hpp" +#include "privatekey.hpp" +#include "util.hpp" namespace bls { @@ -32,14 +27,14 @@ class HDKeys { /** * Implements HD keys as specified in EIP2333. **/ - public: +public: static const uint8_t HASH_LEN = 32; static PrivateKey KeyGen(const std::vector& seed) { return KeyGen(Bytes(seed)); } - + static PrivateKey KeyGen(const Bytes& seed) { // KeyGen @@ -56,65 +51,44 @@ class HDKeys { throw std::invalid_argument("Seed size must be at least 32 bytes"); } - // "BLS-SIG-KEYGEN-SALT-" in ascii - const uint8_t saltHkdf[20] = {66, 76, 83, 45, 83, 73, 71, 45, 75, 69, - 89, 71, 69, 78, 45, 83, 65, 76, 84, 45}; + blst_scalar* skBn = Util::SecAlloc(1); + blst_keygen_v3(skBn, seed.begin(), seed.size(), info, infoLen); + uint8_t* skBytes = Util::SecAlloc(32); + blst_bendian_from_scalar(skBytes, skBn); - uint8_t *prk = Util::SecAlloc(32); - uint8_t *ikmHkdf = Util::SecAlloc(seed.size() + 1); - memcpy(ikmHkdf, seed.begin(), seed.size()); - ikmHkdf[seed.size()] = 0; - - const uint8_t L = 48; // `ceil((3 * ceil(log2(r))) / 16)`, where `r` is the - // order of the BLS 12-381 curve - - uint8_t *okmHkdf = Util::SecAlloc(L); - - uint8_t keyInfoHkdf[infoLen + 2]; - memcpy(keyInfoHkdf, info, infoLen); - keyInfoHkdf[infoLen] = 0; // Two bytes for L, 0 and 48 - keyInfoHkdf[infoLen + 1] = L; - - HKDF256::ExtractExpand( - okmHkdf, - L, - ikmHkdf, - seed.size() + 1, - saltHkdf, - 20, - keyInfoHkdf, - infoLen + 2); - - bn_t order; - bn_new(order); - g1_get_ord(order); - - // Make sure private key is less than the curve order - bn_t *skBn = Util::SecAlloc(1); - bn_new(*skBn); - bn_read_bin(*skBn, okmHkdf, L); - bn_mod_basic(*skBn, *skBn, order); - - uint8_t *skBytes = Util::SecAlloc(32); - bn_write_bin(skBytes, 32, *skBn); PrivateKey k = PrivateKey::FromBytes(Bytes(skBytes, 32)); - Util::SecFree(prk); - Util::SecFree(ikmHkdf); Util::SecFree(skBn); - Util::SecFree(okmHkdf); Util::SecFree(skBytes); return k; } - static void IKMToLamportSk(uint8_t* outputLamportSk, const uint8_t* ikm, size_t ikmLen, const uint8_t* salt, size_t saltLen) { + static void IKMToLamportSk( + uint8_t* outputLamportSk, + const uint8_t* ikm, + size_t ikmLen, + const uint8_t* salt, + size_t saltLen) + { // Expands the ikm to 255*HASH_LEN bytes for the lamport sk const uint8_t info[1] = {0}; - HKDF256::ExtractExpand(outputLamportSk, HASH_LEN * 255, ikm, ikmLen, salt, saltLen, info, 0); + HKDF256::ExtractExpand( + outputLamportSk, + HASH_LEN * 255, + ikm, + ikmLen, + salt, + saltLen, + info, + 0); } - static void ParentSkToLamportPK(uint8_t* outputLamportPk, const PrivateKey& parentSk, uint32_t index) { + static void ParentSkToLamportPK( + uint8_t* outputLamportPk, + const PrivateKey& parentSk, + uint32_t index) + { uint8_t* salt = Util::SecAlloc(4); uint8_t* ikm = Util::SecAlloc(HASH_LEN); uint8_t* notIkm = Util::SecAlloc(HASH_LEN); @@ -134,11 +108,15 @@ class HDKeys { uint8_t* lamportPk = Util::SecAlloc(HASH_LEN * 255 * 2); for (size_t i = 0; i < 255; i++) { - Util::Hash256(lamportPk + i * HASH_LEN, lamport0 + i * HASH_LEN, HASH_LEN); + Util::Hash256( + lamportPk + i * HASH_LEN, lamport0 + i * HASH_LEN, HASH_LEN); } - for (size_t i=0; i < 255; i++) { - Util::Hash256(lamportPk + 255 * HASH_LEN + i * HASH_LEN, lamport1 + i * HASH_LEN, HASH_LEN); + for (size_t i = 0; i < 255; i++) { + Util::Hash256( + lamportPk + 255 * HASH_LEN + i * HASH_LEN, + lamport1 + i * HASH_LEN, + HASH_LEN); } Util::Hash256(outputLamportPk, lamportPk, HASH_LEN * 255 * 2); @@ -150,7 +128,8 @@ class HDKeys { Util::SecFree(lamportPk); } - static PrivateKey DeriveChildSk(const PrivateKey& parentSk, uint32_t index) { + static PrivateKey DeriveChildSk(const PrivateKey& parentSk, uint32_t index) + { uint8_t* lamportPk = Util::SecAlloc(HASH_LEN); HDKeys::ParentSkToLamportPK(lamportPk, parentSk, index); std::vector lamportPkVector(lamportPk, lamportPk + HASH_LEN); @@ -159,21 +138,29 @@ class HDKeys { return child; } - static PrivateKey DeriveChildSkUnhardened(const PrivateKey& parentSk, uint32_t index) { + static PrivateKey DeriveChildSkUnhardened( + const PrivateKey& parentSk, + uint32_t index) + { uint8_t* buf = Util::SecAlloc(G1Element::SIZE + 4); uint8_t* digest = Util::SecAlloc(HASH_LEN); - memcpy(buf, parentSk.GetG1Element().Serialize().data(), G1Element::SIZE); + memcpy( + buf, parentSk.GetG1Element().Serialize().data(), G1Element::SIZE); Util::IntToFourBytes(buf + G1Element::SIZE, index); Util::Hash256(digest, buf, G1Element::SIZE + 4); - PrivateKey ret = PrivateKey::Aggregate({parentSk, PrivateKey::FromBytes(Bytes(digest, HASH_LEN), true)}); + PrivateKey ret = PrivateKey::Aggregate( + {parentSk, PrivateKey::FromBytes(Bytes(digest, HASH_LEN), true)}); Util::SecFree(buf); Util::SecFree(digest); return ret; } - static G1Element DeriveChildG1Unhardened(const G1Element& pk, uint32_t index) { + static G1Element DeriveChildG1Unhardened( + const G1Element& pk, + uint32_t index) + { uint8_t* buf = Util::SecAlloc(G1Element::SIZE + 4); uint8_t* digest = Util::SecAlloc(HASH_LEN); memcpy(buf, pk.Serialize().data(), G1Element::SIZE); @@ -181,35 +168,29 @@ class HDKeys { Util::IntToFourBytes(buf + G1Element::SIZE, index); Util::Hash256(digest, buf, G1Element::SIZE + 4); - bn_t nonce, ord; - bn_new(nonce); - bn_zero(nonce); - bn_read_bin(nonce, digest, HASH_LEN); - bn_new(ord); - g1_get_ord(ord); - bn_mod_basic(nonce, nonce, ord); + blst_scalar nonce; + blst_scalar_from_lendian(&nonce, digest); Util::SecFree(buf); Util::SecFree(digest); G1Element gen = G1Element::Generator(); - return pk + gen * nonce; + + return pk + (gen * nonce); } - static G2Element DeriveChildG2Unhardened(const G2Element& pk, uint32_t index) { + static G2Element DeriveChildG2Unhardened( + const G2Element& pk, + uint32_t index) + { uint8_t* buf = Util::SecAlloc(G2Element::SIZE + 4); uint8_t* digest = Util::SecAlloc(HASH_LEN); memcpy(buf, pk.Serialize().data(), G2Element::SIZE); Util::IntToFourBytes(buf + G2Element::SIZE, index); Util::Hash256(digest, buf, G2Element::SIZE + 4); - bn_t nonce, ord; - bn_new(nonce); - bn_zero(nonce); - bn_read_bin(nonce, digest, HASH_LEN); - bn_new(ord); - g1_get_ord(ord); - bn_mod_basic(nonce, nonce, ord); + blst_scalar nonce; + blst_scalar_from_lendian(&nonce, digest); Util::SecFree(buf); Util::SecFree(digest); @@ -218,5 +199,5 @@ class HDKeys { return pk + gen * nonce; } }; -} // end namespace bls +} // end namespace bls #endif // SRC_BLSHDKEYS_HPP_ diff --git a/src/hkdf.hpp b/src/hkdf.hpp index a7ddc863e..27b519b98 100644 --- a/src/hkdf.hpp +++ b/src/hkdf.hpp @@ -15,13 +15,7 @@ #ifndef SRC_BLSHKDF_HPP_ #define SRC_BLSHKDF_HPP_ -#include "relic_conf.h" #include - -#if defined GMP && ARITH == GMP -#include -#endif - #include #include "util.hpp" @@ -40,7 +34,7 @@ class HKDF256 { // assert(ikm_len == 32); // Used for EIP2333 key derivation // Hash256 used as the hash function (sha256) // PRK Output is 32 bytes (HashLen) - md_hmac(prk_output, ikm, ikm_len, salt, saltLen); + Util::md_hmac(prk_output, ikm, ikm_len, salt, saltLen); } static void Expand(uint8_t* okm, size_t L, const uint8_t* prk, const uint8_t* info, const size_t infoLen) { @@ -59,12 +53,12 @@ class HKDF256 { if (i == 1) { memcpy(hmacInput1, info, infoLen); hmacInput1[infoLen] = i; - md_hmac(T, hmacInput1, infoLen + 1, prk, HASH_LEN); + Util::md_hmac(T, hmacInput1, infoLen + 1, prk, HASH_LEN); } else { memcpy(hmacInput, T, HASH_LEN); memcpy(hmacInput + HASH_LEN, info, infoLen); hmacInput[HASH_LEN + infoLen] = i; - md_hmac(T, hmacInput, HASH_LEN + infoLen + 1, prk, HASH_LEN); + Util::md_hmac(T, hmacInput, HASH_LEN + infoLen + 1, prk, HASH_LEN); } size_t to_write = L - bytesWritten; if (to_write > HASH_LEN) { diff --git a/src/privatekey.cpp b/src/privatekey.cpp index 46e37d244..c4c2cfb9b 100644 --- a/src/privatekey.cpp +++ b/src/privatekey.cpp @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "bls.hpp" namespace bls { @@ -19,44 +21,47 @@ namespace bls { const size_t PrivateKey::PRIVATE_KEY_SIZE; // Construct a private key from a bytearray. -PrivateKey PrivateKey::FromBytes(const Bytes& bytes, bool modOrder) +PrivateKey PrivateKey::FromBytes(const Bytes &bytes, bool modOrder) { if (bytes.size() != PRIVATE_KEY_SIZE) { throw std::invalid_argument("PrivateKey::FromBytes: Invalid size"); } PrivateKey k; - bn_read_bin(k.keydata, bytes.begin(), PrivateKey::PRIVATE_KEY_SIZE); - bn_t ord; - bn_new(ord); - g1_get_ord(ord); - if (modOrder) { - bn_mod_basic(k.keydata, k.keydata, ord); - } else { - if (bn_cmp(k.keydata, ord) > 0) { - throw std::invalid_argument( - "PrivateKey byte data must be less than the group order"); - } + if (modOrder) + // this allows any bytes to be input and does proper mod order + blst_scalar_from_be_bytes(k.keydata, bytes.begin(), bytes.size()); + else + // this should only be the output of deserialization + blst_scalar_from_bendian(k.keydata, bytes.begin()); + + if (Util::HasOnlyZeros(bytes)) { + return k; // don't check anything else, we allow zero private key } + + if (!blst_sk_check(k.keydata)) + throw std::invalid_argument( + "PrivateKey byte data must be less than the group order"); + return k; } // Construct a private key from a bytearray. -PrivateKey PrivateKey::FromByteVector(const std::vector bytes, bool modOrder) +PrivateKey PrivateKey::FromByteVector( + const std::vector bytes, + bool modOrder) { return PrivateKey::FromBytes(Bytes(bytes), modOrder); } -PrivateKey::PrivateKey() { - AllocateKeyData(); -}; +PrivateKey::PrivateKey() { AllocateKeyData(); }; // Construct a private key from another private key. PrivateKey::PrivateKey(const PrivateKey &privateKey) { privateKey.CheckKeyData(); AllocateKeyData(); - bn_copy(keydata, privateKey.keydata); + memcpy(keydata, privateKey.keydata, 32); } PrivateKey::PrivateKey(PrivateKey &&k) @@ -65,14 +70,11 @@ PrivateKey::PrivateKey(PrivateKey &&k) k.InvalidateCaches(); } -PrivateKey::~PrivateKey() -{ - DeallocateKeyData(); -} +PrivateKey::~PrivateKey() { DeallocateKeyData(); } void PrivateKey::DeallocateKeyData() { - if(keydata != nullptr) { + if (keydata != nullptr) { Util::SecFree(keydata); keydata = nullptr; } @@ -85,16 +87,16 @@ void PrivateKey::InvalidateCaches() fG2CacheValid = false; } -PrivateKey& PrivateKey::operator=(const PrivateKey& other) +PrivateKey &PrivateKey::operator=(const PrivateKey &other) { CheckKeyData(); other.CheckKeyData(); InvalidateCaches(); - bn_copy(keydata, other.keydata); + memcpy(keydata, other.keydata, 32); return *this; } -PrivateKey& PrivateKey::operator=(PrivateKey&& other) +PrivateKey &PrivateKey::operator=(PrivateKey &&other) { DeallocateKeyData(); keydata = std::exchange(other.keydata, nullptr); @@ -102,28 +104,28 @@ PrivateKey& PrivateKey::operator=(PrivateKey&& other) return *this; } -const G1Element& PrivateKey::GetG1Element() const +const G1Element &PrivateKey::GetG1Element() const { if (!fG1CacheValid) { CheckKeyData(); - g1_st *p = Util::SecAlloc(1); - g1_mul_gen(p, keydata); + blst_p1 *p = Util::SecAlloc(1); + blst_sk_to_pk_in_g1(p, keydata); - g1Cache = G1Element::FromNative(p); + g1Cache = G1Element::FromNative(*p); Util::SecFree(p); fG1CacheValid = true; } return g1Cache; } -const G2Element& PrivateKey::GetG2Element() const +const G2Element &PrivateKey::GetG2Element() const { if (!fG2CacheValid) { CheckKeyData(); - g2_st *q = Util::SecAlloc(1); - g2_mul_gen(q, keydata); + blst_p2 *q = Util::SecAlloc(1); + blst_sk_to_pk_in_g2(q, keydata); - g2Cache = G2Element::FromNative(q); + g2Cache = G2Element::FromNative(*q); Util::SecFree(q); fG2CacheValid = true; } @@ -133,11 +135,15 @@ const G2Element& PrivateKey::GetG2Element() const G1Element operator*(const G1Element &a, const PrivateKey &k) { k.CheckKeyData(); - g1_st* ans = Util::SecAlloc(1); + + blst_p1 *ans = Util::SecAlloc(1); a.ToNative(ans); - g1_mul(ans, ans, k.keydata); - G1Element ret = G1Element::FromNative(ans); + byte *bte = Util::SecAlloc(32); + blst_bendian_from_scalar(bte, k.keydata); + blst_p1_mult(ans, ans, bte, 256); + G1Element ret = G1Element::FromNative(*ans); Util::SecFree(ans); + Util::SecFree(bte); return ret; } @@ -146,25 +152,30 @@ G1Element operator*(const PrivateKey &k, const G1Element &a) { return a * k; } G2Element operator*(const G2Element &a, const PrivateKey &k) { k.CheckKeyData(); - g2_st* ans = Util::SecAlloc(1); + blst_p2 *ans = Util::SecAlloc(1); a.ToNative(ans); - g2_mul(ans, ans, k.keydata); - G2Element ret = G2Element::FromNative(ans); + byte *bte = Util::SecAlloc(32); + blst_bendian_from_scalar(bte, k.keydata); + blst_p2_mult(ans, ans, bte, 256); + G2Element ret = G2Element::FromNative(*ans); Util::SecFree(ans); + Util::SecFree(bte); return ret; } G2Element operator*(const PrivateKey &k, const G2Element &a) { return a * k; } -G2Element PrivateKey::GetG2Power(const G2Element& element) const +G2Element PrivateKey::GetG2Power(const G2Element &element) const { CheckKeyData(); - g2_st* q = Util::SecAlloc(1); + blst_p2 *q = Util::SecAlloc(1); element.ToNative(q); - g2_mul(q, q, keydata); - - const G2Element ret = G2Element::FromNative(q); + byte *bte = Util::SecAlloc(32); + blst_bendian_from_scalar(bte, keydata); + blst_p2_mult(q, q, bte, 255); + const G2Element ret = G2Element::FromNative(*q); Util::SecFree(q); + Util::SecFree(bte); return ret; } @@ -174,30 +185,29 @@ PrivateKey PrivateKey::Aggregate(std::vector const &privateKeys) throw std::length_error("Number of private keys must be at least 1"); } - bn_t order; - bn_new(order); - g1_get_ord(order); - PrivateKey ret; assert(ret.IsZero()); for (size_t i = 0; i < privateKeys.size(); i++) { privateKeys[i].CheckKeyData(); - bn_add(ret.keydata, ret.keydata, privateKeys[i].keydata); - bn_mod_basic(ret.keydata, ret.keydata, order); + blst_sk_add_n_check(ret.keydata, ret.keydata, privateKeys[i].keydata); } return ret; } -bool PrivateKey::IsZero() const { +bool PrivateKey::IsZero() const +{ CheckKeyData(); - return bn_is_zero(keydata); + blst_scalar zro; + memset(&zro, 0x00, sizeof(blst_scalar)); + + return memcmp(keydata, &zro, 32) == 0; } bool operator==(const PrivateKey &a, const PrivateKey &b) { a.CheckKeyData(); b.CheckKeyData(); - return bn_cmp(a.keydata, b.keydata) == RLC_EQ; + return memcmp(a.keydata, b.keydata, sizeof(blst_scalar)) == 0; } bool operator!=(const PrivateKey &a, const PrivateKey &b) { return !(a == b); } @@ -208,7 +218,7 @@ void PrivateKey::Serialize(uint8_t *buffer) const throw std::runtime_error("PrivateKey::Serialize buffer invalid"); } CheckKeyData(); - bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, keydata); + blst_bendian_from_scalar(buffer, keydata); } std::vector PrivateKey::Serialize() const @@ -226,11 +236,12 @@ G2Element PrivateKey::SignG2( { CheckKeyData(); - g2_st* pt = Util::SecAlloc(1); + blst_p2 *pt = Util::SecAlloc(1); + + blst_hash_to_g2(pt, msg, len, dst, dst_len, nullptr, 0); + blst_sign_pk_in_g1(pt, pt, keydata); - ep2_map_dst(pt, msg, len, dst, dst_len); - g2_mul(pt, pt, keydata); - G2Element ret = G2Element::FromNative(pt); + G2Element ret = G2Element::FromNative(*pt); Util::SecFree(pt); return ret; } @@ -238,15 +249,15 @@ G2Element PrivateKey::SignG2( void PrivateKey::AllocateKeyData() { assert(!keydata); - keydata = Util::SecAlloc(1); - keydata->alloc = RLC_BN_SIZE; - bn_zero(keydata); + keydata = Util::SecAlloc(1); + memset(keydata, 0x00, sizeof(blst_scalar)); } void PrivateKey::CheckKeyData() const { if (keydata == nullptr) { - throw std::runtime_error("PrivateKey::CheckKeyData keydata not initialized"); + throw std::runtime_error( + "PrivateKey::CheckKeyData keydata not initialized"); } } diff --git a/src/privatekey.hpp b/src/privatekey.hpp index c73890a1d..6a133042e 100644 --- a/src/privatekey.hpp +++ b/src/privatekey.hpp @@ -15,12 +15,6 @@ #ifndef SRC_BLSPRIVATEKEY_HPP_ #define SRC_BLSPRIVATEKEY_HPP_ -#include "relic_conf.h" - -#if defined GMP && ARITH == GMP -#include -#endif - #include "elements.hpp" namespace bls { @@ -92,7 +86,7 @@ class PrivateKey { void InvalidateCaches(); // The actual byte data - bn_st* keydata{nullptr}; + blst_scalar* keydata{nullptr}; mutable bool fG1CacheValid{false}; mutable G1Element g1Cache; diff --git a/src/schemes.cpp b/src/schemes.cpp index acecab0f7..bac0d5b97 100644 --- a/src/schemes.cpp +++ b/src/schemes.cpp @@ -12,12 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "schemes.hpp" + +#include + #include #include #include "bls.hpp" #include "elements.hpp" -#include "schemes.hpp" #include "hdkeys.hpp" using std::string; @@ -25,13 +28,13 @@ using std::vector; namespace bls { -enum InvariantResult { BAD=false, GOOD=true, CONTINUE }; +enum InvariantResult { BAD = false, GOOD = true, CONTINUE }; // Enforce argument invariants for Agg Sig Verification InvariantResult VerifyAggregateSignatureArguments( const size_t nPubKeys, const size_t nMessages, - const G2Element &signature) + const G2Element& signature) { if (nPubKeys == 0) { return (nMessages == 0 && signature == G2Element() ? GOOD : BAD); @@ -45,82 +48,100 @@ InvariantResult VerifyAggregateSignatureArguments( /* These are all for the min-pubkey-size variant. TODO : analogs for min-signature-size */ -const std::string BasicSchemeMPL::CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"; -const std::string AugSchemeMPL::CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_"; -const std::string PopSchemeMPL::CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; -const std::string PopSchemeMPL::POP_CIPHERSUITE_ID = "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; +const std::string BasicSchemeMPL::CIPHERSUITE_ID = + "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"; +const std::string AugSchemeMPL::CIPHERSUITE_ID = + "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_"; +const std::string PopSchemeMPL::CIPHERSUITE_ID = + "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; +const std::string PopSchemeMPL::POP_CIPHERSUITE_ID = + "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; -PrivateKey CoreMPL::KeyGen(const vector& seed) { +PrivateKey CoreMPL::KeyGen(const vector& seed) +{ return HDKeys::KeyGen(seed); } -PrivateKey CoreMPL::KeyGen(const Bytes& seed) { - return HDKeys::KeyGen(seed); -} +PrivateKey CoreMPL::KeyGen(const Bytes& seed) { return HDKeys::KeyGen(seed); } -vector CoreMPL::SkToPk(const PrivateKey &seckey) +vector CoreMPL::SkToPk(const PrivateKey& seckey) { return seckey.GetG1Element().Serialize(); } -G1Element CoreMPL::SkToG1(const PrivateKey &seckey) +G1Element CoreMPL::SkToG1(const PrivateKey& seckey) { return seckey.GetG1Element(); } -G2Element CoreMPL::Sign(const PrivateKey &seckey, const vector &message) +G2Element CoreMPL::Sign( + const PrivateKey& seckey, + const vector& message) { return CoreMPL::Sign(seckey, Bytes(message)); } G2Element CoreMPL::Sign(const PrivateKey& seckey, const Bytes& message) { - return seckey.SignG2(message.begin(), message.size(), (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length()); + return seckey.SignG2( + message.begin(), + message.size(), + (const uint8_t*)strCiphersuiteId.c_str(), + strCiphersuiteId.length()); } -bool CoreMPL::Verify(const vector &pubkey, - const vector &message, // unhashed - const vector &signature) +bool CoreMPL::Verify( + const vector& pubkey, + const vector& message, // unhashed + const vector& signature) { - return CoreMPL::Verify(G1Element::FromBytes(Bytes(pubkey)), - Bytes(message), - G2Element::FromBytes(Bytes(signature))); + return CoreMPL::Verify( + G1Element::FromBytes(Bytes(pubkey)), + Bytes(message), + G2Element::FromBytes(Bytes(signature))); } -bool CoreMPL::Verify(const Bytes& pubkey, const Bytes& message, const Bytes& signature) +bool CoreMPL::Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature) { - return CoreMPL::Verify(G1Element::FromBytes(pubkey), message, G2Element::FromBytes(signature)); + return CoreMPL::Verify( + G1Element::FromBytes(pubkey), message, G2Element::FromBytes(signature)); } -bool CoreMPL::Verify(const G1Element &pubkey, - const vector &message, // unhashed - const G2Element &signature) +bool CoreMPL::Verify( + const G1Element& pubkey, + const vector& message, // unhashed + const G2Element& signature) { return CoreMPL::Verify(pubkey, Bytes(message), signature); } -bool CoreMPL::Verify(const G1Element& pubkey, const Bytes& message, const G2Element& signature) +bool CoreMPL::Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature) { - const G2Element hashedPoint = G2Element::FromMessage(message, (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length()); + blst_p1_affine pubkeyAffine; + blst_p2_affine sigAffine; - std::vector vecG1(2); - std::vector vecG2(2); + pubkey.ToAffine(&pubkeyAffine); + signature.ToAffine(&sigAffine); - G1Element::Generator().Negate().ToNative(&vecG1[0]); - if (!pubkey.IsValid()) { - return false; - } - if (!signature.IsValid()) { - return false; - } - pubkey.ToNative(&vecG1[1]); - signature.ToNative(&vecG2[0]); - hashedPoint.ToNative(&vecG2[1]); + auto err = blst_core_verify_pk_in_g1( + &pubkeyAffine, + &sigAffine, + true, /*hash*/ + message.begin(), + message.size(), + (const uint8_t*)strCiphersuiteId.c_str(), + strCiphersuiteId.length()); - return CoreMPL::NativeVerify((g1_t*)vecG1.data(), (g2_t*)vecG2.data(), 2); + return err == BLST_SUCCESS; } -vector CoreMPL::Aggregate(const vector> &signatures) +vector CoreMPL::Aggregate(const vector>& signatures) { vector elements; for (const vector& signature : signatures) { @@ -138,7 +159,7 @@ vector CoreMPL::Aggregate(const vector& signatures) return CoreMPL::Aggregate(elements).Serialize(); } -G2Element CoreMPL::Aggregate(const vector &signatures) +G2Element CoreMPL::Aggregate(const vector& signatures) { G2Element aggregated; for (const G2Element& signature : signatures) { @@ -147,7 +168,7 @@ G2Element CoreMPL::Aggregate(const vector &signatures) return aggregated; } -G1Element CoreMPL::Aggregate(const vector &publicKeys) +G1Element CoreMPL::Aggregate(const vector& publicKeys) { G1Element aggregated; for (const G1Element& publicKey : publicKeys) { @@ -156,22 +177,26 @@ G1Element CoreMPL::Aggregate(const vector &publicKeys) return aggregated; } -bool CoreMPL::AggregateVerify(const vector> &pubkeys, - const vector> &messages, // unhashed - const vector &signature) +bool CoreMPL::AggregateVerify( + const vector>& pubkeys, + const vector>& messages, // unhashed + const vector& signature) { const std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); const std::vector vecMessagesBytes(messages.begin(), messages.end()); - return CoreMPL::AggregateVerify(vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); + return CoreMPL::AggregateVerify( + vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); } -bool CoreMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, // unhashed - const Bytes& signature) +bool CoreMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, // unhashed + const Bytes& signature) { const size_t nPubKeys = pubkeys.size(); const G2Element signatureElement = G2Element::FromBytes(signature); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signatureElement); + const auto arg_check = VerifyAggregateSignatureArguments( + nPubKeys, messages.size(), signatureElement); if (arg_check != CONTINUE) { return arg_check; } @@ -183,104 +208,109 @@ bool CoreMPL::AggregateVerify(const vector& pubkeys, return CoreMPL::AggregateVerify(pubkeyElements, messages, signatureElement); } -bool CoreMPL::AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) +bool CoreMPL::AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) { - return CoreMPL::AggregateVerify(pubkeys, std::vector(messages.begin(), messages.end()), signature); + return CoreMPL::AggregateVerify( + pubkeys, + std::vector(messages.begin(), messages.end()), + signature); } -bool CoreMPL::AggregateVerify(const vector& pubkeys, - const vector &messages, - const G2Element& signature) +bool CoreMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + const auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) { return arg_check; } - std::vector vecG1(nPubKeys + 1); - std::vector vecG2(nPubKeys + 1); - G1Element::Generator().Negate().ToNative(&vecG1[0]); - if (!signature.IsValid()) { - return false; - } - signature.ToNative(&vecG2[0]); + blst_pairing* ctx = (blst_pairing*)malloc(blst_pairing_sizeof()); + blst_pairing_init( + ctx, + true /*hash*/, + (const uint8_t*)strCiphersuiteId.c_str(), + strCiphersuiteId.length()); - for (size_t i = 0; i < nPubKeys; ++i) { - if (!pubkeys[i].IsValid()) { - return false; - } - pubkeys[i].ToNative(&vecG1[i + 1]); - G2Element::FromMessage(messages[i], (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length()).ToNative(&vecG2[i + 1]); - } + blst_p1_affine pk_affine; + blst_p2_affine sig_affine; + blst_fp12 gtsig; - return CoreMPL::NativeVerify((g1_t*)vecG1.data(), (g2_t*)vecG2.data(), nPubKeys + 1); -} + signature.ToAffine(&sig_affine); -bool CoreMPL::NativeVerify(g1_t *pubkeys, g2_t *mappedHashes, size_t length) -{ - gt_t target, candidate, tmpPairing; - fp12_zero(target); - fp_set_dig(target[0][0][0], 1); - fp12_zero(candidate); - fp_set_dig(candidate[0][0][0], 1); + blst_aggregated_in_g2(>sig, &sig_affine); - // prod e(pubkey[i], hash[i]) * e(-g1, aggSig) - // Performs pubKeys.size() pairings, 250 at a time + for (size_t i = 0; i < nPubKeys; i++) { + pubkeys[i].ToAffine(&pk_affine); - for (size_t i = 0; i < length; i += 250) { - size_t numPairings = std::min((length - i), (size_t)250); - pc_map_sim(tmpPairing, pubkeys + i, mappedHashes + i, numPairings); - fp12_mul(candidate, candidate, tmpPairing); - } + auto err = blst_pairing_aggregate_pk_in_g1( + ctx, &pk_affine, nullptr, messages[i].begin(), messages[i].size()); - // 1 =? prod e(pubkey[i], hash[i]) * e(-g1, aggSig) - if (gt_cmp(target, candidate) != RLC_EQ || core_get()->code != RLC_OK) { - core_get()->code = RLC_OK; - return false; + if (err != BLST_SUCCESS) { + free(ctx); + return false; + } } - BLS::CheckRelicErrors(); - return true; + + blst_pairing_commit(ctx); + auto ret = blst_pairing_finalverify(ctx, >sig); + free(ctx); + return ret; } -PrivateKey CoreMPL::DeriveChildSk(const PrivateKey& sk, uint32_t index) { +PrivateKey CoreMPL::DeriveChildSk(const PrivateKey& sk, uint32_t index) +{ return HDKeys::DeriveChildSk(sk, index); } -PrivateKey CoreMPL::DeriveChildSkUnhardened(const PrivateKey& sk, uint32_t index) { +PrivateKey CoreMPL::DeriveChildSkUnhardened( + const PrivateKey& sk, + uint32_t index) +{ return HDKeys::DeriveChildSkUnhardened(sk, index); } -G1Element CoreMPL::DeriveChildPkUnhardened(const G1Element& pk, uint32_t index) { +G1Element CoreMPL::DeriveChildPkUnhardened(const G1Element& pk, uint32_t index) +{ return HDKeys::DeriveChildG1Unhardened(pk, index); } -bool BasicSchemeMPL::AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) +bool BasicSchemeMPL::AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) { const size_t nPubKeys = pubkeys.size(); - auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), G2Element::FromByteVector(signature)); + auto arg_check = VerifyAggregateSignatureArguments( + nPubKeys, messages.size(), G2Element::FromByteVector(signature)); if (arg_check != CONTINUE) { return arg_check; } - const std::set> setMessages(messages.begin(), messages.end()); + const std::set> setMessages( + messages.begin(), messages.end()); if (setMessages.size() != nPubKeys) { return false; } return CoreMPL::AggregateVerify(pubkeys, messages, signature); } -bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) +bool BasicSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), G2Element::FromBytes(signature)); - if (arg_check != CONTINUE) return arg_check; + const auto arg_check = VerifyAggregateSignatureArguments( + nPubKeys, messages.size(), G2Element::FromBytes(signature)); + if (arg_check != CONTINUE) + return arg_check; std::set> setMessages; for (const auto& message : messages) { @@ -292,30 +322,36 @@ bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, return CoreMPL::AggregateVerify(pubkeys, messages, signature); } -bool BasicSchemeMPL::AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) +bool BasicSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + const auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) { return arg_check; } - const std::set> setMessages(messages.begin(), messages.end()); + const std::set> setMessages( + messages.begin(), messages.end()); if (setMessages.size() != nPubKeys) { return false; } return CoreMPL::AggregateVerify(pubkeys, messages, signature); } -bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector &messages, - const G2Element& signature) +bool BasicSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); - if (arg_check != CONTINUE) return arg_check; + const auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + if (arg_check != CONTINUE) + return arg_check; std::set> setMessages; for (const auto& message : messages) { @@ -327,7 +363,9 @@ bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, return CoreMPL::AggregateVerify(pubkeys, messages, signature); } -G2Element AugSchemeMPL::Sign(const PrivateKey &seckey, const vector &message) +G2Element AugSchemeMPL::Sign( + const PrivateKey& seckey, + const vector& message) { return AugSchemeMPL::Sign(seckey, message, seckey.GetG1Element()); } @@ -338,17 +376,19 @@ G2Element AugSchemeMPL::Sign(const PrivateKey& seckey, const Bytes& message) } // Used for prepending different augMessage -G2Element AugSchemeMPL::Sign(const PrivateKey &seckey, - const vector &message, - const G1Element &prepend_pk) +G2Element AugSchemeMPL::Sign( + const PrivateKey& seckey, + const vector& message, + const G1Element& prepend_pk) { return AugSchemeMPL::Sign(seckey, Bytes(message), prepend_pk); } // Used for prepending different augMessage -G2Element AugSchemeMPL::Sign(const PrivateKey& seckey, - const Bytes& message, - const G1Element& prepend_pk) +G2Element AugSchemeMPL::Sign( + const PrivateKey& seckey, + const Bytes& message, + const G1Element& prepend_pk) { vector augMessage = prepend_pk.Serialize(); augMessage.reserve(augMessage.size() + message.size()); @@ -356,9 +396,10 @@ G2Element AugSchemeMPL::Sign(const PrivateKey& seckey, return CoreMPL::Sign(seckey, augMessage); } -bool AugSchemeMPL::Verify(const vector &pubkey, - const vector &message, - const vector &signature) +bool AugSchemeMPL::Verify( + const vector& pubkey, + const vector& message, + const vector& signature) { vector augMessage(pubkey); augMessage.reserve(augMessage.size() + message.size()); @@ -366,9 +407,10 @@ bool AugSchemeMPL::Verify(const vector &pubkey, return CoreMPL::Verify(pubkey, augMessage, signature); } -bool AugSchemeMPL::Verify(const Bytes& pubkey, - const Bytes& message, - const Bytes& signature) +bool AugSchemeMPL::Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature) { vector augMessage(pubkey.begin(), pubkey.end()); augMessage.reserve(augMessage.size() + message.size()); @@ -376,16 +418,18 @@ bool AugSchemeMPL::Verify(const Bytes& pubkey, return CoreMPL::Verify(pubkey, Bytes(augMessage), Bytes(signature)); } -bool AugSchemeMPL::Verify(const G1Element &pubkey, - const vector &message, - const G2Element &signature) +bool AugSchemeMPL::Verify( + const G1Element& pubkey, + const vector& message, + const G2Element& signature) { return AugSchemeMPL::Verify(pubkey, Bytes(message), signature); } -bool AugSchemeMPL::Verify(const G1Element& pubkey, - const Bytes& message, - const G2Element& signature) +bool AugSchemeMPL::Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature) { vector augMessage = pubkey.Serialize(); augMessage.reserve(augMessage.size() + message.size()); @@ -393,21 +437,25 @@ bool AugSchemeMPL::Verify(const G1Element& pubkey, return CoreMPL::Verify(pubkey, augMessage, signature); } -bool AugSchemeMPL::AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) +bool AugSchemeMPL::AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) { std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); std::vector vecMessagesBytes(messages.begin(), messages.end()); - return AugSchemeMPL::AggregateVerify(vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); + return AugSchemeMPL::AggregateVerify( + vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); } -bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) +bool AugSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) { size_t nPubKeys = pubkeys.size(); - auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), G2Element::FromBytes(signature)); + auto arg_check = VerifyAggregateSignatureArguments( + nPubKeys, messages.size(), G2Element::FromBytes(signature)); if (arg_check != CONTINUE) { return arg_check; } @@ -420,30 +468,34 @@ bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, aug.insert(aug.end(), messages[i].begin(), messages[i].end()); } - std::vector vecAugMessageBytes(augMessages.begin(), augMessages.end()); + std::vector vecAugMessageBytes( + augMessages.begin(), augMessages.end()); return CoreMPL::AggregateVerify(pubkeys, vecAugMessageBytes, signature); } -bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector>& messages, - const G2Element& signature) +bool AugSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) { std::vector vecMessagesBytes(messages.begin(), messages.end()); return AugSchemeMPL::AggregateVerify(pubkeys, vecMessagesBytes, signature); } -bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature) +bool AugSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) { size_t nPubKeys = pubkeys.size(); - auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) { return arg_check; } vector> augMessages(nPubKeys); - for (int i = 0; i < nPubKeys; ++i) { + for (size_t i = 0; i < nPubKeys; ++i) { vector& aug = augMessages[i]; vector&& pubkey = pubkeys[i].Serialize(); aug.reserve(pubkey.size() + messages[i].size()); @@ -454,84 +506,89 @@ bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, return CoreMPL::AggregateVerify(pubkeys, augMessages, signature); } -G2Element PopSchemeMPL::PopProve(const PrivateKey &seckey) +G2Element PopSchemeMPL::PopProve(const PrivateKey& seckey) { - const G1Element& pk = seckey.GetG1Element(); - const G2Element hashedKey = G2Element::FromMessage(pk.Serialize(), (const uint8_t *)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); - return seckey.GetG2Power(hashedKey); -} + std::vector pubkey_bytes = seckey.GetG1Element().Serialize(); + return seckey.SignG2( + pubkey_bytes.data(), + pubkey_bytes.size(), + (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), + POP_CIPHERSUITE_ID.length()); +} -bool PopSchemeMPL::PopVerify(const G1Element &pubkey, const G2Element &signature_proof) +bool PopSchemeMPL::PopVerify( + const G1Element& pubkey, + const G2Element& signature_proof) { - const G2Element hashedPoint = G2Element::FromMessage(pubkey.Serialize(), (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); + blst_p1_affine pubkeyAffine; + blst_p2_affine sigAffine; - g1_t g1s[2]; - g2_t g2s[2]; + pubkey.ToAffine(&pubkeyAffine); + signature_proof.ToAffine(&sigAffine); + std::vector pubkey_bytes = pubkey.Serialize(); - if (!pubkey.IsValid()) { - return false; - } - if (!signature_proof.IsValid()) { - return false; - } - G1Element::Generator().Negate().ToNative(g1s[0]); - pubkey.ToNative(g1s[1]); - signature_proof.ToNative(g2s[0]); - hashedPoint.ToNative(g2s[1]); + auto err = blst_core_verify_pk_in_g1( + &pubkeyAffine, + &sigAffine, + true, /*hash*/ + pubkey_bytes.data(), + pubkey_bytes.size(), + (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), + POP_CIPHERSUITE_ID.length()); - return CoreMPL::NativeVerify(g1s, g2s, 2); + return err == BLST_SUCCESS; } -bool PopSchemeMPL::PopVerify(const vector &pubkey, const vector &proof) +bool PopSchemeMPL::PopVerify( + const vector& pubkey, + const vector& proof) { return PopSchemeMPL::PopVerify(Bytes(pubkey), Bytes(proof)); } bool PopSchemeMPL::PopVerify(const Bytes& pubkey, const Bytes& proof) { - const G2Element hashedPoint = G2Element::FromMessage(pubkey, (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); - - g1_t g1s[2]; - g2_t g2s[2]; - - G1Element::Generator().Negate().ToNative(g1s[0]); - G1Element::FromBytes(pubkey).ToNative(g1s[1]); - G2Element::FromBytes(proof).ToNative(g2s[0]); - hashedPoint.ToNative(g2s[1]); - - return CoreMPL::NativeVerify(g1s, g2s, 2); + return PopSchemeMPL::PopVerify( + G1Element::FromBytes(pubkey), G2Element::FromBytes(proof)); } -bool PopSchemeMPL::FastAggregateVerify(const vector &pubkeys, - const vector &message, - const G2Element &signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector& pubkeys, + const vector& message, + const G2Element& signature) { - return PopSchemeMPL::FastAggregateVerify(pubkeys, Bytes(message), signature); + return PopSchemeMPL::FastAggregateVerify( + pubkeys, Bytes(message), signature); } -bool PopSchemeMPL::FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const G2Element& signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const G2Element& signature) { if (pubkeys.size() == 0) { return false; } - // No VerifyAggregateSignatureArguments checks required here as we have exactly one pubkey and one message. + // No VerifyAggregateSignatureArguments checks required here as we have + // exactly one pubkey and one message. return CoreMPL::Verify(CoreMPL::Aggregate(pubkeys), message, signature); } -bool PopSchemeMPL::FastAggregateVerify(const vector> &pubkeys, - const vector &message, - const vector &signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector>& pubkeys, + const vector& message, + const vector& signature) { const std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); - return PopSchemeMPL::FastAggregateVerify(vecPubKeyBytes, Bytes(message), Bytes(signature)); + return PopSchemeMPL::FastAggregateVerify( + vecPubKeyBytes, Bytes(message), Bytes(signature)); } -bool PopSchemeMPL::FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const Bytes& signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const Bytes& signature) { const size_t nPubKeys = pubkeys.size(); if (nPubKeys == 0) { @@ -543,6 +600,7 @@ bool PopSchemeMPL::FastAggregateVerify(const vector& pubkeys, pkelements.push_back(G1Element::FromBytes(pubkeys[i])); } - return PopSchemeMPL::FastAggregateVerify(pkelements, message, G2Element::FromBytes(signature)); + return PopSchemeMPL::FastAggregateVerify( + pkelements, message, G2Element::FromBytes(signature)); } } // end namespace bls diff --git a/src/schemes.hpp b/src/schemes.hpp index 49300607c..c0393f253 100644 --- a/src/schemes.hpp +++ b/src/schemes.hpp @@ -18,12 +18,6 @@ #include #include -#include "relic_conf.h" - -#if defined GMP && ARITH == GMP -#include -#endif - #include "elements.hpp" #include "privatekey.hpp" @@ -35,7 +29,6 @@ namespace bls { class Bytes; class CoreMPL { - public: CoreMPL() = delete; CoreMPL(const std::string& strId) : strCiphersuiteId(strId) {} @@ -46,47 +39,62 @@ class CoreMPL { virtual PrivateKey KeyGen(const Bytes& seed); // Generates a public key from a secret key - virtual vector SkToPk(const PrivateKey &seckey); + virtual vector SkToPk(const PrivateKey& seckey); - virtual G1Element SkToG1(const PrivateKey &seckey); + virtual G1Element SkToG1(const PrivateKey& seckey); - virtual G2Element Sign(const PrivateKey &seckey, const vector &message); + virtual G2Element Sign( + const PrivateKey& seckey, + const vector& message); virtual G2Element Sign(const PrivateKey& seckey, const Bytes& message); - virtual bool Verify(const vector &pubkey, - const vector &message, - const vector &signature); + virtual bool Verify( + const vector& pubkey, + const vector& message, + const vector& signature); - virtual bool Verify(const Bytes& pubkey, const Bytes& message, const Bytes& signature); + virtual bool Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature); - virtual bool Verify(const G1Element &pubkey, - const vector &message, - const G2Element &signature); + virtual bool Verify( + const G1Element& pubkey, + const vector& message, + const G2Element& signature); - virtual bool Verify(const G1Element& pubkey, const Bytes& message, const G2Element& signature); + virtual bool Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature); - virtual vector Aggregate(const vector> &signatures); + virtual vector Aggregate( + const vector>& signatures); virtual vector Aggregate(const vector& signatures); - virtual G2Element Aggregate(const vector &signatures); + virtual G2Element Aggregate(const vector& signatures); - virtual G1Element Aggregate(const vector &publicKeys); + virtual G1Element Aggregate(const vector& publicKeys); - virtual bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature); + virtual bool AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature); - virtual bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature); + virtual bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature); - virtual bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature); + virtual bool AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature); - virtual bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature); + virtual bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature); PrivateKey DeriveChildSk(const PrivateKey& sk, uint32_t index); PrivateKey DeriveChildSkUnhardened(const PrivateKey& sk, uint32_t index); @@ -94,113 +102,131 @@ class CoreMPL { protected: const std::string& strCiphersuiteId; - bool NativeVerify(g1_t *pubKeys, g2_t *mappedHashes, size_t length); + // bool NativeVerify(blst_p1 *pubKeys, blst_p2 *mappedHashes, size_t + // length); }; class BasicSchemeMPL final : public CoreMPL { public: static const std::string CIPHERSUITE_ID; BasicSchemeMPL() : CoreMPL(BasicSchemeMPL::CIPHERSUITE_ID) {} - bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) override; - - bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature) override; + bool AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) override; }; class AugSchemeMPL final : public CoreMPL { - public: static const std::string CIPHERSUITE_ID; AugSchemeMPL() : CoreMPL(AugSchemeMPL::CIPHERSUITE_ID) {} - G2Element Sign(const PrivateKey &seckey, const vector &message) override; + G2Element Sign(const PrivateKey& seckey, const vector& message) + override; G2Element Sign(const PrivateKey& seckey, const Bytes& message) override; // Used for prepending different augMessage - G2Element Sign(const PrivateKey &seckey, - const vector &message, - const G1Element &prepend_pk); + G2Element Sign( + const PrivateKey& seckey, + const vector& message, + const G1Element& prepend_pk); // Used for prepending different augMessage - G2Element Sign(const PrivateKey& seckey, - const Bytes& message, - const G1Element& prepend_pk); - - bool Verify(const vector &pubkey, - const vector &message, - const vector &signature) override; - - bool Verify(const Bytes& pubkey, - const Bytes& message, - const Bytes& signature) override; - - bool Verify(const G1Element &pubkey, - const vector &message, - const G2Element &signature) override; - - bool Verify(const G1Element& pubkey, - const Bytes& message, - const G2Element& signature) override; - - bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) override; - - bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature) override; + G2Element Sign( + const PrivateKey& seckey, + const Bytes& message, + const G1Element& prepend_pk); + + bool Verify( + const vector& pubkey, + const vector& message, + const vector& signature) override; + + bool Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature) override; + + bool Verify( + const G1Element& pubkey, + const vector& message, + const G2Element& signature) override; + + bool Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature) override; + + bool AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) override; }; class PopSchemeMPL final : public CoreMPL { - public: static const std::string CIPHERSUITE_ID; static const std::string POP_CIPHERSUITE_ID; PopSchemeMPL() : CoreMPL(PopSchemeMPL::CIPHERSUITE_ID) {} - G2Element PopProve(const PrivateKey &seckey); + G2Element PopProve(const PrivateKey& seckey); - bool PopVerify(const G1Element &pubkey, const G2Element &signature_proof); + bool PopVerify(const G1Element& pubkey, const G2Element& signature_proof); - bool PopVerify(const vector &pubkey, const vector &proof); + bool PopVerify(const vector& pubkey, const vector& proof); bool PopVerify(const Bytes& pubkey, const Bytes& proof); - bool FastAggregateVerify(const vector &pubkeys, - const vector &message, - const G2Element &signature); - - bool FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const G2Element& signature); - - bool FastAggregateVerify(const vector> &pubkeys, - const vector &message, - const vector &signature); - - bool FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const Bytes& signature); + bool FastAggregateVerify( + const vector& pubkeys, + const vector& message, + const G2Element& signature); + + bool FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const G2Element& signature); + + bool FastAggregateVerify( + const vector>& pubkeys, + const vector& message, + const vector& signature); + + bool FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const Bytes& signature); }; } // end namespace bls diff --git a/src/test-bench.cpp b/src/test-bench.cpp index af351821e..07a3ee0dc 100644 --- a/src/test-bench.cpp +++ b/src/test-bench.cpp @@ -13,22 +13,27 @@ // limitations under the License. #include + #include "bls.hpp" #include "test-utils.hpp" -extern "C" { -#include "relic.h" -} - using std::string; using std::vector; -using std::cout; -using std::endl; using namespace bls; +std::vector wjbgetRandomSeed() +{ + uint8_t buf[32]; -void benchSigs() { + for (int i = 0; i < 32; i++) buf[i] = rand(); + + std::vector ret(buf, buf + 32); + return ret; +} + +void benchSigs() +{ string testName = "Signing"; const int numIters = 5000; PrivateKey sk = AugSchemeMPL().KeyGen(getRandomSeed()); @@ -42,21 +47,22 @@ void benchSigs() { endStopwatch(testName, start, numIters); } -void benchVerification() { +void benchVerification() +{ string testName = "Verification"; const int numIters = 10000; PrivateKey sk = AugSchemeMPL().KeyGen(getRandomSeed()); G1Element pk = sk.GetG1Element(); - std::vector sigs; + vector pkBytes = pk.Serialize(); for (int i = 0; i < numIters; i++) { uint8_t message[4]; Util::IntToFourBytes(message, i); vector messageBytes(message, message + 4); - sigs.push_back(AugSchemeMPL().Sign(sk, messageBytes)); + G2Element sig = AugSchemeMPL().Sign(sk, messageBytes); + sigs.push_back(sig); } - auto start = startStopwatch(); for (int i = 0; i < numIters; i++) { uint8_t message[4]; @@ -68,7 +74,8 @@ void benchVerification() { endStopwatch(testName, start, numIters); } -void benchBatchVerification() { +void benchBatchVerification() +{ const int numIters = 100000; vector> sig_bytes; @@ -114,7 +121,8 @@ void benchBatchVerification() { endStopwatch("Batch verification", start, numIters); } -void benchFastAggregateVerification() { +void benchFastAggregateVerification() +{ const int numIters = 5000; vector sigs; @@ -134,7 +142,6 @@ void benchFastAggregateVerification() { G2Element aggSig = PopSchemeMPL().Aggregate(sigs); endStopwatch("PopScheme Aggregation", start, numIters); - start = startStopwatch(); for (int i = 0; i < numIters; i++) { bool ok = PopSchemeMPL().PopVerify(pks[i], pops[i]); @@ -148,7 +155,8 @@ void benchFastAggregateVerification() { endStopwatch("PopScheme verification", start, numIters); } -int main(int argc, char* argv[]) { +int main(int argc, char* argv[]) +{ benchSigs(); benchVerification(); benchBatchVerification(); diff --git a/src/test-utils.hpp b/src/test-utils.hpp index 154079ff4..237940c87 100644 --- a/src/test-utils.hpp +++ b/src/test-utils.hpp @@ -47,10 +47,10 @@ void endStopwatch(string testName, std::vector getRandomSeed() { uint8_t buf[32]; - bn_t r; - bn_new(r); - bn_rand(r, RLC_POS, 256); - bn_write_bin(buf, 32, r); + + for (int i = 0; i < 32; i++) + buf[i] = rand (); + std::vector ret(buf, buf + 32); return ret; } diff --git a/src/test.cpp b/src/test.cpp index 045e8c715..6376d9df8 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -13,24 +13,25 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include #include - +#include #include #include "bls.hpp" -extern "C" { -#include "relic.h" -} #include "test-utils.hpp" -using std::cout; -using std::endl; using std::string; using std::vector; using namespace bls; -void TestHKDF(string ikm_hex, string salt_hex, string info_hex, string prk_expected_hex, string okm_expected_hex, int L) { +void TestHKDF( + string ikm_hex, + string salt_hex, + string info_hex, + string prk_expected_hex, + string okm_expected_hex, + int L) +{ vector ikm = Util::HexToBytes(ikm_hex); vector salt = Util::HexToBytes(salt_hex); vector info = Util::HexToBytes(info_hex); @@ -42,22 +43,24 @@ void TestHKDF(string ikm_hex, string salt_hex, string info_hex, string prk_expec HKDF256::Expand(okm, L, prk, info.data(), info.size()); REQUIRE(32 == prk_expected.size()); - REQUIRE(L == okm_expected.size()); + REQUIRE(L == (int)okm_expected.size()); - for (size_t i=0; i < 32; i++) { + for (size_t i = 0; i < 32; i++) { REQUIRE(prk[i] == prk_expected[i]); } - for (size_t i=0; i < L; i++) { + for (int i = 0; i < L; i++) { REQUIRE(okm[i] == okm_expected[i]); } delete[] okm; } -TEST_CASE("class PrivateKey") { +TEST_CASE("class PrivateKey") +{ uint8_t buffer[PrivateKey::PRIVATE_KEY_SIZE]; memcpy(buffer, getRandomSeed().data(), PrivateKey::PRIVATE_KEY_SIZE); - SECTION("Copy {constructor|assignment operator}") { + SECTION("Copy {constructor|assignment operator}") + { PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); PrivateKey pk2 = PrivateKey::FromByteVector(getRandomSeed(), true); PrivateKey pk3 = PrivateKey(pk2); @@ -66,15 +69,16 @@ TEST_CASE("class PrivateKey") { REQUIRE(!pk3.IsZero()); REQUIRE(pk1 != pk2); REQUIRE(pk3 == pk2); - REQUIRE(pk2.GetG1Element().IsValid()); // cache previous g1 - REQUIRE(pk2.GetG2Element().IsValid()); // cache previous g2 + REQUIRE(pk2.GetG1Element().IsValid()); // cache previous g1 + REQUIRE(pk2.GetG2Element().IsValid()); // cache previous g2 pk2 = pk1; REQUIRE(pk1 == pk2); REQUIRE(pk1.GetG1Element() == pk2.GetG1Element()); REQUIRE(pk1.GetG2Element() == pk2.GetG2Element()); REQUIRE(pk3 != pk2); } - SECTION("Move {constructor|assignment operator}") { + SECTION("Move {constructor|assignment operator}") + { PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); std::vector vec1 = pk1.Serialize(); PrivateKey pk2 = PrivateKey::FromByteVector(getRandomSeed(), true); @@ -94,7 +98,8 @@ TEST_CASE("class PrivateKey") { REQUIRE_THROWS(pk2.IsZero()); REQUIRE_THROWS(pk3.IsZero()); } - SECTION("Equality operators") { + SECTION("Equality operators") + { PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); PrivateKey pk2 = PrivateKey::FromByteVector(getRandomSeed(), true); PrivateKey pk3 = pk2; @@ -102,28 +107,42 @@ TEST_CASE("class PrivateKey") { REQUIRE(pk1 != pk3); REQUIRE(pk2 == pk3); } - SECTION("(De)Serialization") { + SECTION("(De)Serialization") + { PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); REQUIRE_THROWS_AS(pk1.Serialize(nullptr), std::runtime_error); pk1.Serialize(buffer); - REQUIRE(memcmp(buffer, pk1.Serialize().data(), PrivateKey::PRIVATE_KEY_SIZE) == 0); - PrivateKey pk2 = PrivateKey:: FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true); + REQUIRE( + memcmp( + buffer, pk1.Serialize().data(), PrivateKey::PRIVATE_KEY_SIZE) == + 0); + PrivateKey pk2 = PrivateKey::FromBytes( + Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true); REQUIRE(pk1 == pk2); - REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE - 1), true)); - REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE + 1), true)); - REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); - bn_t order; - bn_new(order); - g1_get_ord(order); - bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, order); - REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), false)); - REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); - bn_add(order, order, order); - bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, order); - REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), false)); - REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); + REQUIRE_THROWS(PrivateKey::FromBytes( + Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE - 1), true)); + REQUIRE_THROWS(PrivateKey::FromBytes( + Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE + 1), true)); + REQUIRE_NOTHROW(PrivateKey::FromBytes( + Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); + // blst_scalar order; + // memcpy(&order, BLS12_381_r, sizeof(blst_scalar)); + // g1_get_ord(order); + // bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, order); + // REQUIRE_NOTHROW(PrivateKey::FromBytes( + // Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), false)); + // REQUIRE_NOTHROW(PrivateKey::FromBytes( + // Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); + // blst_sk_add_n_check(&order, &order, &order); + // bn_add(order, order, order); + // bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, order); + // REQUIRE_THROWS(PrivateKey::FromBytes( + // Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), false)); + // REQUIRE_NOTHROW(PrivateKey::FromBytes( + // Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); } - SECTION("keydata checks") { + SECTION("keydata checks") + { PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); G1Element g1 = pk1.GetG1Element(); G2Element g2 = pk1.GetG2Element(); @@ -143,69 +162,86 @@ TEST_CASE("class PrivateKey") { REQUIRE_THROWS(pk1 != pk2); REQUIRE_THROWS(pk1.Serialize(buffer)); REQUIRE_THROWS(pk1.Serialize()); - REQUIRE_THROWS(pk1.SignG2(buffer, sizeof(buffer), buffer, sizeof(buffer))); + REQUIRE_THROWS( + pk1.SignG2(buffer, sizeof(buffer), buffer, sizeof(buffer))); } } -TEST_CASE("HKDF") { +TEST_CASE("HKDF") +{ // https://tools.ietf.org/html/rfc5869 test vectors - SECTION("Test case 2") { - TestHKDF("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "000102030405060708090a0b0c", - "f0f1f2f3f4f5f6f7f8f9", - "077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", - "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", - 42 - ); + SECTION("Test case 2") + { + TestHKDF( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + "077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", + "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34" + "007208d5b887185865", + 42); } - SECTION("Test case 2") { - TestHKDF("000102030405060708090a0b0c0d0e0f" - "101112131415161718191a1b1c1d1e1f" - "202122232425262728292a2b2c2d2e2f" - "303132333435363738393a3b3c3d3e3f" - "404142434445464748494a4b4c4d4e4f", // 80 octets - "0x606162636465666768696a6b6c6d6e6f" - "707172737475767778797a7b7c7d7e7f" - "808182838485868788898a8b8c8d8e8f" - "909192939495969798999a9b9c9d9e9f" - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", // 80 octets - "0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", // 80 octets - "0x06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244", // 32 octets - "0xb11e398dc80327a1c8e7f78c596a4934" - "4f012eda2d4efad8a050cc4c19afa97c" - "59045a99cac7827271cb41c65e590e09" - "da3275600c2f09b8367793a9aca3db71" - "cc30c58179ec3e87c14c01d5c1f3434f" - "1d87", // 82 octets - 82 - ); + SECTION("Test case 2") + { + TestHKDF( + "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f", // 80 octets + "0x606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", // 80 octets + "0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", // 80 octets + "0x06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc24" + "4", // 32 octets + "0xb11e398dc80327a1c8e7f78c596a4934" + "4f012eda2d4efad8a050cc4c19afa97c" + "59045a99cac7827271cb41c65e590e09" + "da3275600c2f09b8367793a9aca3db71" + "cc30c58179ec3e87c14c01d5c1f3434f" + "1d87", // 82 octets + 82); } - SECTION("Test case 3") { - TestHKDF("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "", - "", - "19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04", - "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8", - 42 - ); + SECTION("Test case 3") + { + TestHKDF( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + "19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04", + "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d" + "201395faa4b61a96c8", + 42); } - SECTION("Works with multiple of 32") { - // This generates exactly 64 bytes. Uses a 32 byte key and 4 byte salt as in EIP2333. - TestHKDF("8704f9ac024139fe62511375cf9bc534c0507dcf00c41603ac935cd5943ce0b4b88599390de14e743ca2f56a73a04eae13aa3f3b969b39d8701e0d69a6f8d42f", - "53d8e19b", - "", - "eb01c9cd916653df76ffa61b6ab8a74e254ebfd9bfc43e624cc12a72b0373dee", - "8faabea85fc0c64e7ca86217cdc6dcdc88551c3244d56719e630a3521063082c46455c2fd5483811f9520a748f0099c1dfcfa52c54e1c22b5cdf70efb0f3c676", - 64 - ); + SECTION("Works with multiple of 32") + { + // This generates exactly 64 bytes. Uses a 32 byte key and 4 byte salt + // as in EIP2333. + TestHKDF( + "8704f9ac024139fe62511375cf9bc534c0507dcf00c41603ac935cd5943ce0b4b8" + "8599390de14e743ca2f56a73a04eae13aa3f3b969b39d8701e0d69a6f8d42f", + "53d8e19b", + "", + "eb01c9cd916653df76ffa61b6ab8a74e254ebfd9bfc43e624cc12a72b0373dee", + "8faabea85fc0c64e7ca86217cdc6dcdc88551c3244d56719e630a3521063082c46" + "455c2fd5483811f9520a748f0099c1dfcfa52c54e1c22b5cdf70efb0f3c676", + 64); } } -void TestEIP2333(string seedHex, string masterSkHex, string childSkHex, uint32_t childIndex) { +void TestEIP2333( + string seedHex, + string masterSkHex, + string childSkHex, + uint32_t childIndex) +{ auto masterSk = Util::HexToBytes(masterSkHex); auto childSk = Util::HexToBytes(childSkHex); @@ -219,60 +255,73 @@ void TestEIP2333(string seedHex, string masterSkHex, string childSkHex, uint32_t REQUIRE(calculatedMaster.size() == 32); REQUIRE(calculatedChild.size() == 32); - for (int i=0; i<32; i++) { + for (int i = 0; i < 32; i++) { REQUIRE(calculatedMaster[i] == masterSk[i]); } - for (int i=0; i<32; i++) { + for (int i = 0; i < 32; i++) { REQUIRE(calculatedChild[i] == childSk[i]); } } -TEST_CASE("EIP-2333 hardened HD keys") { - // The comments in the test cases correspond to integers that are converted to - // bytes using python int.to_bytes(32, "big").hex(), since the EIP spec provides ints, but c++ - // does not support bigint by default - SECTION("EIP-2333 Test case 1"){ - TestEIP2333("3141592653589793238462643383279502884197169399375105820974944592", - // 36167147331491996618072159372207345412841461318189449162487002442599770291484 - "4ff5e145590ed7b71e577bb04032396d1619ff41cb4e350053ed2dce8d1efd1c", - // 41787458189896526028601807066547832426569899195138584349427756863968330588237 - "5c62dcf9654481292aafa3348f1d1b0017bbfb44d6881d26d2b17836b38f204d", - 3141592653 - ); +TEST_CASE("EIP-2333 hardened HD keys") +{ + // The comments in the test cases correspond to integers that are converted + // to bytes using python int.to_bytes(32, "big").hex(), since the EIP spec + // provides ints, but c++ does not support bigint by default + SECTION("EIP-2333 Test case 1") + { + TestEIP2333( + "3141592653589793238462643383279502884197169399375105820974944592", + // 36167147331491996618072159372207345412841461318189449162487002442599770291484 + "4ff5e145590ed7b71e577bb04032396d1619ff41cb4e350053ed2dce8d1efd1c", + // 41787458189896526028601807066547832426569899195138584349427756863968330588237 + "5c62dcf9654481292aafa3348f1d1b0017bbfb44d6881d26d2b17836b38f204d", + 3141592653); } - SECTION("EIP-2333 Test case 2"){ - TestEIP2333("0x0099FF991111002299DD7744EE3355BBDD8844115566CC55663355668888CC00", - // 13904094584487173309420026178174172335998687531503061311232927109397516192843 - "1ebd704b86732c3f05f30563dee6189838e73998ebc9c209ccff422adee10c4b", - // 12482522899285304316694838079579801944734479969002030150864436005368716366140 - "1b98db8b24296038eae3f64c25d693a269ef1e4d7ae0f691c572a46cf3c0913c", - 4294967295 - ); + SECTION("EIP-2333 Test case 2") + { + TestEIP2333( + "0x0099FF991111002299DD7744EE3355BBDD8844115566CC55663355668888CC0" + "0", + // 13904094584487173309420026178174172335998687531503061311232927109397516192843 + "1ebd704b86732c3f05f30563dee6189838e73998ebc9c209ccff422adee10c4b", + // 12482522899285304316694838079579801944734479969002030150864436005368716366140 + "1b98db8b24296038eae3f64c25d693a269ef1e4d7ae0f691c572a46cf3c0913c", + 4294967295); } - SECTION("EIP-2333 Test case 3"){ - TestEIP2333("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", - // 44010626067374404458092393860968061149521094673473131545188652121635313364506 - "614d21b10c0e4996ac0608e0e7452d5720d95d20fe03c59a3321000a42432e1a", - // 4011524214304750350566588165922015929937602165683407445189263506512578573606 - "08de7136e4afc56ae3ec03b20517d9c1232705a747f588fd17832f36ae337526", - 42 - ); + SECTION("EIP-2333 Test case 3") + { + TestEIP2333( + "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa" + "3", + // 44010626067374404458092393860968061149521094673473131545188652121635313364506 + "614d21b10c0e4996ac0608e0e7452d5720d95d20fe03c59a3321000a42432e1a", + // 4011524214304750350566588165922015929937602165683407445189263506512578573606 + "08de7136e4afc56ae3ec03b20517d9c1232705a747f588fd17832f36ae337526", + 42); } - SECTION("EIP-2333 Test vector with intermediate values"){ - TestEIP2333("c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04", - // 5399117110774477986698372024995405256382522670366369834617409486544348441851 - "0x0befcabff4a664461cc8f190cdd51c05621eb2837c71a1362df5b465a674ecfb", - // 11812940737387919040225825939013910852517748782307378293770044673328955938106 - "1a1de3346883401f1e3b2281be5774080edb8e5ebe6f776b0f7af9fea942553a", - 0 - ); + SECTION("EIP-2333 Test vector with intermediate values") + { + TestEIP2333( + "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f" + "09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04", + // 5399117110774477986698372024995405256382522670366369834617409486544348441851 + "0x0befcabff4a664461cc8f190cdd51c05621eb2837c71a1362df5b465a674ecf" + "b", + // 11812940737387919040225825939013910852517748782307378293770044673328955938106 + "1a1de3346883401f1e3b2281be5774080edb8e5ebe6f776b0f7af9fea942553a", + 0); } } -TEST_CASE("Unhardened HD keys") { - SECTION("Should match derivation through private and public keys"){ - const vector seed = {1, 50, 6, 244, 24, 199, 1, 25, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; +TEST_CASE("Unhardened HD keys") +{ + SECTION("Should match derivation through private and public keys") + { + const vector seed = {1, 50, 6, 244, 24, 199, 1, 25, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29}; PrivateKey sk = BasicSchemeMPL().KeyGen(seed); G1Element pk = sk.GetG1Element(); @@ -282,15 +331,20 @@ TEST_CASE("Unhardened HD keys") { REQUIRE(childSk.GetG1Element() == childPk); - PrivateKey grandchildSk = BasicSchemeMPL().DeriveChildSkUnhardened(childSk, 12142); - G1Element grandcihldPk = BasicSchemeMPL().DeriveChildPkUnhardened(childPk, 12142); + PrivateKey grandchildSk = + BasicSchemeMPL().DeriveChildSkUnhardened(childSk, 12142); + G1Element grandchildPk = + BasicSchemeMPL().DeriveChildPkUnhardened(childPk, 12142); - REQUIRE(grandchildSk.GetG1Element() == grandcihldPk); + REQUIRE(grandchildSk.GetG1Element() == grandchildPk); } - SECTION("Should derive public child from parent") { - const vector seed = {2, 50, 6, 244, 24, 199, 1, 25, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; + SECTION("Should derive public child from parent") + { + const vector seed = {2, 50, 6, 244, 24, 199, 1, 25, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29}; PrivateKey sk = BasicSchemeMPL().KeyGen(seed); G1Element pk = sk.GetG1Element(); @@ -305,10 +359,17 @@ TEST_CASE("Unhardened HD keys") { } } -TEST_CASE("IETF test vectors") { - SECTION ("Pyecc vector") { - string sig1BasicHex = "96ba34fac33c7f129d602a0bc8a3d43f9abc014eceaab7359146b4b150e57b808645738f35671e9e10e0d862a30cab70074eb5831d13e6a5b162d01eebe687d0164adbd0a864370a7c222a2768d7704da254f1bf1823665bc2361f9dd8c00e99"; - string sk = "0x0101010101010101010101010101010101010101010101010101010101010101"; +TEST_CASE("IETF test vectors") +{ + SECTION("Pyecc vector") + { + string sig1BasicHex = + "96ba34fac33c7f129d602a0bc8a3d43f9abc014eceaab7359146b4b150e57b8086" + "45738f35671e9e10e0d862a30cab70074eb5831d13e6a5b162d01eebe687d0164a" + "dbd0a864370a7c222a2768d7704da254f1bf1823665bc2361f9dd8c00e99"; + string sk = + "0x010101010101010101010101010101010101010101010101010101010101010" + "1"; vector msg = {3, 1, 4, 1, 5, 9}; auto skobj = PrivateKey::FromBytes(Bytes(Util::HexToBytes(sk))); G2Element sig = BasicSchemeMPL().Sign(skobj, msg); @@ -320,9 +381,10 @@ TEST_CASE("IETF test vectors") { } } - -TEST_CASE("Chia test vectors") { - SECTION("Chia test vectors 1 (Basic)") { +TEST_CASE("Chia test vectors") +{ + SECTION("Chia test vectors 1 (Basic)") + { vector seed1(32, 0x00); // All 0s vector seed2(32, 0x01); // All 1s vector message1 = {7, 8, 9}; @@ -332,7 +394,6 @@ TEST_CASE("Chia test vectors") { G1Element pk1 = sk1.GetG1Element(); G2Element sig1 = BasicSchemeMPL().Sign(sk1, message1); - PrivateKey sk2 = BasicSchemeMPL().KeyGen(seed2); G1Element pk2 = sk2.GetG1Element(); G2Element sig2 = BasicSchemeMPL().Sign(sk2, message2); @@ -360,20 +421,26 @@ TEST_CASE("Chia test vectors") { REQUIRE( Util::HexStr(sig2.Serialize()) == - "a9c4d3e689b82c7ec7e838dac2380cb014f9a08f6cd6ba044c263746e39a8f7a60ffee4afb7" - "8f146c2e421360784d58f0029491e3bd8ab84f0011d258471ba4e87059de295d9aba845c044e" + "a9c4d3e689b82c7ec7e838dac2380cb014f9a08f6cd6ba044c263746e39a8f7a60" + "ffee4afb7" + "8f146c2e421360784d58f0029491e3bd8ab84f0011d258471ba4e87059de295d9a" + "ba845c044e" "e83f6cf2411efd379ef38bf4cf41d5f3c0ae1205d"); G2Element aggSig1 = BasicSchemeMPL().Aggregate({sig1, sig2}); REQUIRE( Util::HexStr(aggSig1.Serialize()) == - "aee003c8cdaf3531b6b0ca354031b0819f7586b5846796615aee8108fec75ef838d181f9d24" - "4a94d195d7b0231d4afcf06f27f0cc4d3c72162545c240de7d5034a7ef3a2a03c0159de982fb" + "aee003c8cdaf3531b6b0ca354031b0819f7586b5846796615aee8108fec75ef838" + "d181f9d24" + "4a94d195d7b0231d4afcf06f27f0cc4d3c72162545c240de7d5034a7ef3a2a03c0" + "159de982fb" "c2e7790aeb455e27beae91d64e077c70b5506dea3"); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message1, message2}, aggSig1)); - REQUIRE(!BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message1, message2}, sig1)); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message1, message2}, aggSig1)); + REQUIRE(!BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message1, message2}, sig1)); REQUIRE(!BasicSchemeMPL().Verify(pk1, message1, sig2)); REQUIRE(!BasicSchemeMPL().Verify(pk1, message2, sig1)); @@ -387,15 +454,21 @@ TEST_CASE("Chia test vectors") { G2Element aggSig2 = BasicSchemeMPL().Aggregate({sig3, sig4, sig5}); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk1, pk2}, vector>{message3, message4, message5}, aggSig2)); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {pk1, pk1, pk2}, + vector>{message3, message4, message5}, + aggSig2)); REQUIRE( Util::HexStr(aggSig2.Serialize()) == - "a0b1378d518bea4d1100adbc7bdbc4ff64f2c219ed6395cd36fe5d2aa44a4b8e710b607afd9" - "65e505a5ac3283291b75413d09478ab4b5cfbafbeea366de2d0c0bcf61deddaa521f6020460f" + "a0b1378d518bea4d1100adbc7bdbc4ff64f2c219ed6395cd36fe5d2aa44a4b8e71" + "0b607afd9" + "65e505a5ac3283291b75413d09478ab4b5cfbafbeea366de2d0c0bcf61deddaa52" + "1f6020460f" "d547ab37659ae207968b545727beba0a3c5572b9c"); } - SECTION("Chia test vector 2 (Augmented, aggregate of aggregates)") { + SECTION("Chia test vector 2 (Augmented, aggregate of aggregates)") + { vector message1 = {1, 2, 3, 40}; vector message2 = {5, 6, 70, 201}; vector message3 = {9, 10, 11, 12, 13}; @@ -417,20 +490,26 @@ TEST_CASE("Chia test vectors") { G2Element sig5 = AugSchemeMPL().Sign(sk1, message1); G2Element sig6 = AugSchemeMPL().Sign(sk1, message4); - G2Element aggSigL = AugSchemeMPL().Aggregate({sig1, sig2}); G2Element aggSigR = AugSchemeMPL().Aggregate({sig3, sig4, sig5}); G2Element aggSig = AugSchemeMPL().Aggregate({aggSigL, aggSigR, sig6}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2, pk2, pk1, pk1, pk1}, vector>{message1, message2, message1, message3, message1, message4}, aggSig)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2, pk2, pk1, pk1, pk1}, + vector>{ + message1, message2, message1, message3, message1, message4}, + aggSig)); REQUIRE( Util::HexStr(aggSig.Serialize()) == - "a1d5360dcb418d33b29b90b912b4accde535cf0e52caf467a005dc632d9f7af44b6c4e9acd4" - "6eac218b28cdb07a3e3bc087df1cd1e3213aa4e11322a3ff3847bbba0b2fd19ddc25ca964871" + "a1d5360dcb418d33b29b90b912b4accde535cf0e52caf467a005dc632d9f7af44b" + "6c4e9acd4" + "6eac218b28cdb07a3e3bc087df1cd1e3213aa4e11322a3ff3847bbba0b2fd19ddc" + "25ca964871" "997b9bceeab37a4c2565876da19382ea32a962200"); } - SECTION("Chia test vector 3 (PoP)") { + SECTION("Chia test vector 3 (PoP)") + { vector message1 = {1, 2, 3, 40, 50}; vector seed1(32, 0x04); // All 4s @@ -440,13 +519,16 @@ TEST_CASE("Chia test vectors") { G2Element pop = PopSchemeMPL().PopProve(sk1); REQUIRE(PopSchemeMPL().PopVerify(sk1.GetG1Element(), pop)); - REQUIRE(Util::HexStr(pop.Serialize()) == "84f709159435f0dc73b3e8bf6c78d85282d19231555a8ee3b6e2573aaf66872d9203fefa1ef" - "700e34e7c3f3fb28210100558c6871c53f1ef6055b9f06b0d1abe22ad584ad3b957f3018a8f5" - "8227c6c716b1e15791459850f2289168fa0cf9115"); + REQUIRE( + Util::HexStr(pop.Serialize()) == + "84f709159435f0dc73b3e8bf6c78d85282d19231555a8ee3b6e2573aaf66872d92" + "03fefa1ef" + "700e34e7c3f3fb28210100558c6871c53f1ef6055b9f06b0d1abe22ad584ad3b95" + "7f3018a8f5" + "8227c6c716b1e15791459850f2289168fa0cf9115"); } } - TEST_CASE("Key generation") { SECTION("Should generate a keypair from a seed") @@ -457,12 +539,10 @@ TEST_CASE("Key generation") REQUIRE_THROWS(BasicSchemeMPL().KeyGen(seed1)); PrivateKey sk = BasicSchemeMPL().KeyGen(seed2); G1Element pk = sk.GetG1Element(); - REQUIRE(core_get()->code == RLC_OK); REQUIRE(pk.GetFingerprint() == 0x8ee7ba56); } } - TEST_CASE("Error handling") { SECTION("Should throw on a bad private key") @@ -472,7 +552,8 @@ TEST_CASE("Error handling") uint8_t* skData = Util::SecAlloc(G2Element::SIZE); sk1.Serialize(skData); skData[0] = 255; - REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE))); + REQUIRE_THROWS( + PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE))); Util::SecFree(skData); } @@ -481,7 +562,8 @@ TEST_CASE("Error handling") vector buf(G1Element::SIZE, 0); for (int i = 0; i < 0xFF; i++) { buf[0] = (uint8_t)i; - if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have only zero values + if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have + // only zero values REQUIRE_NOTHROW(G1Element::FromByteVector(buf)); } else { REQUIRE_THROWS(G1Element::FromByteVector(buf)); @@ -494,47 +576,20 @@ TEST_CASE("Error handling") vector buf(G2Element::SIZE, 0); for (int i = 0; i < 0xFF; i++) { buf[0] = (uint8_t)i; - if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have only zero values + if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have + // only zero values REQUIRE_NOTHROW(G2Element::FromByteVector(buf)); } else { REQUIRE_THROWS(G2Element::FromByteVector(buf)); } } - // Trigger "G2 element must always have 48th byte start with 0b000" error case + // Trigger "G2 element must always have 48th byte start with 0b000" + // error case buf[48] = 0xFF; REQUIRE_THROWS(G2Element::FromByteVector(buf)); } - - SECTION("Error handling should be thread safe") - { - core_get()->code = 10; - REQUIRE(core_get()->code == 10); - - ctx_t* ctx1 = core_get(); - - // spawn a thread and make sure it uses a different/same context depending on relic's multithreading setup - std::thread([&]() { -#if MULTI != RELIC_NONE - REQUIRE(ctx1 != core_get()); - REQUIRE(core_get()->code == RLC_OK); -#else - REQUIRE(ctx1 == core_get()); - REQUIRE(core_get()->code != RLC_OK); -#endif - core_get()->code = 1; - }).join(); - -#if MULTI != RELIC_NONE - REQUIRE(core_get()->code == 10); -#else - REQUIRE(core_get()->code == 1); -#endif - // reset so that future test cases don't fail - core_get()->code = RLC_OK; - } } - TEST_CASE("Util tests") { SECTION("Should convert an int to four bytes") @@ -552,7 +607,6 @@ TEST_CASE("Util tests") } } - TEST_CASE("Signature tests") { SECTION("Should use copy constructor") @@ -566,7 +620,8 @@ TEST_CASE("Signature tests") uint8_t skBytes[PrivateKey::PRIVATE_KEY_SIZE]; sk2.Serialize(skBytes); - PrivateKey sk4 = PrivateKey::FromBytes(Bytes(skBytes, PrivateKey::PRIVATE_KEY_SIZE)); + PrivateKey sk4 = + PrivateKey::FromBytes(Bytes(skBytes, PrivateKey::PRIVATE_KEY_SIZE)); G1Element pk2 = G1Element(pk1); G2Element sig1 = BasicSchemeMPL().Sign(sk4, message1); @@ -575,7 +630,8 @@ TEST_CASE("Signature tests") REQUIRE(BasicSchemeMPL().Verify(pk2, message1, sig2)); } - SECTION("Should sign with the zero key") { + SECTION("Should sign with the zero key") + { vector sk0(32, 0); PrivateKey sk = PrivateKey::FromByteVector(sk0); REQUIRE(sk.GetG1Element() == G1Element()); // Infinity @@ -626,7 +682,8 @@ TEST_CASE("Signature tests") uint8_t* skData = Util::SecAlloc(G2Element::SIZE); sk1.Serialize(skData); - PrivateKey sk2 = PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE)); + PrivateKey sk2 = + PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE)); REQUIRE(sk1 == sk2); auto pkData = pk1.Serialize(); @@ -648,7 +705,6 @@ TEST_CASE("Signature tests") SECTION("Should not verify aggregate with same message under BasicScheme") { vector message = {100, 2, 254, 88, 90, 45, 23}; - uint8_t hash[BLS::MESSAGE_HASH_LEN]; vector seed(32, 0x50); vector seed2(32, 0x70); @@ -663,13 +719,17 @@ TEST_CASE("Signature tests") G2Element sig2 = BasicSchemeMPL().Sign(sk2, message); G2Element aggSig = BasicSchemeMPL().Aggregate({sig1, sig2}); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSig) == false); + REQUIRE( + BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, + vector>{message, message}, + aggSig) == false); } - SECTION("Should verify aggregate with same message under AugScheme/PopScheme") + SECTION( + "Should verify aggregate with same message under AugScheme/PopScheme") { vector message = {100, 2, 254, 88, 90, 45, 23}; - uint8_t hash[BLS::MESSAGE_HASH_LEN]; vector seed(32, 0x50); vector seed2(32, 0x70); @@ -683,19 +743,21 @@ TEST_CASE("Signature tests") G2Element sig1Aug = AugSchemeMPL().Sign(sk1, message); G2Element sig2Aug = AugSchemeMPL().Sign(sk2, message); G2Element aggSigAug = AugSchemeMPL().Aggregate({sig1Aug, sig2Aug}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSigAug)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message, message}, aggSigAug)); G2Element sig1Pop = PopSchemeMPL().Sign(sk1, message); G2Element sig2Pop = PopSchemeMPL().Sign(sk2, message); G2Element aggSigPop = PopSchemeMPL().Aggregate({sig1Pop, sig2Pop}); - REQUIRE(PopSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSigPop)); + REQUIRE(PopSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message, message}, aggSigPop)); } SECTION("Should Aug aggregate many G2Elements, diff message") { vector pks; vector sigs; - vector > ms; + vector> ms; for (uint8_t i = 0; i < 80; i++) { vector message = {0, 100, 2, 45, 64, 12, 12, 63, i}; @@ -714,8 +776,8 @@ TEST_CASE("Signature tests") SECTION("Aggregate Verification of zero items with infinity should pass") { vector pks_as_g1; - vector > pks_as_bytes; - vector > msgs; + vector> pks_as_bytes; + vector> msgs; vector sigs; sigs.push_back(G2Element()); @@ -725,22 +787,43 @@ TEST_CASE("Signature tests") REQUIRE(aggSig == G2Element()); REQUIRE(AugSchemeMPL().AggregateVerify(pks_as_g1, msgs, aggSig)); - REQUIRE(AugSchemeMPL().AggregateVerify(pks_as_bytes, msgs, aggSig.Serialize())); + REQUIRE(AugSchemeMPL().AggregateVerify( + pks_as_bytes, msgs, aggSig.Serialize())); REQUIRE(BasicSchemeMPL().AggregateVerify(pks_as_g1, msgs, aggSig)); - REQUIRE(BasicSchemeMPL().AggregateVerify(pks_as_bytes, msgs, aggSig.Serialize())); + REQUIRE(BasicSchemeMPL().AggregateVerify( + pks_as_bytes, msgs, aggSig.Serialize())); - // FastAggregateVerify takes one message, and requires at least one key + // FastAggregateVerify takes one message, and requires at least one key vector msg; REQUIRE(pks_as_g1.size() == 0); - REQUIRE(PopSchemeMPL().FastAggregateVerify(pks_as_g1, msg, aggSig) == false); + REQUIRE( + PopSchemeMPL().FastAggregateVerify(pks_as_g1, msg, aggSig) == + false); REQUIRE(pks_as_bytes.size() == 0); - REQUIRE(PopSchemeMPL().FastAggregateVerify(pks_as_bytes, msg, aggSig.Serialize()) == false); + REQUIRE( + PopSchemeMPL().FastAggregateVerify( + pks_as_bytes, msg, aggSig.Serialize()) == false); + } + SECTION("Aggregate same sig element") + { + vector message = {100, 2, 254, 88, 90, 45, 23}; + + vector seed(32, 0x50); + PrivateKey sk1 = BasicSchemeMPL().KeyGen(seed); + + G1Element pk1 = sk1.GetG1Element(); + + G2Element sig1Aug = AugSchemeMPL().Sign(sk1, message); + G2Element aggSigAug = AugSchemeMPL().Aggregate({sig1Aug, sig1Aug}); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk1}, vector>{message, message}, aggSigAug)); } } -TEST_CASE("Agg sks") { +TEST_CASE("Agg sks") +{ SECTION("Should create aggregates with agg sk (basic scheme)") { const vector message = {100, 2, 254, 88, 90, 45, 23}; @@ -765,7 +848,6 @@ TEST_CASE("Agg sks") { const G2Element aggSig2 = BasicSchemeMPL().Sign(aggSk, message); - const G2Element aggSig = BasicSchemeMPL().Aggregate({sig1, sig2}); REQUIRE(aggSig == aggSig2); @@ -774,8 +856,16 @@ TEST_CASE("Agg sks") { REQUIRE(BasicSchemeMPL().Verify(aggPubKey, message, aggSig2)); // Verify aggregate with both keys (Fails since not distinct) - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSig) == false); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSig2) == false); + REQUIRE( + BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, + vector>{message, message}, + aggSig) == false); + REQUIRE( + BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, + vector>{message, message}, + aggSig2) == false); // Try the same with distinct message, and same sk vector message2 = {200, 29, 54, 8, 9, 29, 155, 55}; @@ -797,12 +887,17 @@ TEST_CASE("Agg sks") { REQUIRE(pkFinal != aggPubKey); // Cannot verify with aggPubKey (since we have multiple messages) - REQUIRE(BasicSchemeMPL().AggregateVerify({aggPubKey, pk2}, vector>{message, message2}, aggSigFinal)); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {aggPubKey, pk2}, + vector>{message, message2}, + aggSigFinal)); } } -TEST_CASE("Advanced") { - SECTION("Should aggregate with multiple levels, degenerate") { +TEST_CASE("Advanced") +{ + SECTION("Should aggregate with multiple levels, degenerate") + { vector message1 = {100, 2, 254, 88, 90, 45, 23}; PrivateKey sk1 = AugSchemeMPL().KeyGen(getRandomSeed()); G1Element pk1 = sk1.GetG1Element(); @@ -821,7 +916,8 @@ TEST_CASE("Advanced") { REQUIRE(AugSchemeMPL().AggregateVerify(pks, ms, aggSig)); } - SECTION("Should aggregate with multiple levels, different messages") { + SECTION("Should aggregate with multiple levels, different messages") + { vector message1 = {100, 2, 254, 88, 90, 45, 23}; vector message2 = {192, 29, 2, 0, 0, 45, 23}; vector message3 = {52, 29, 2, 0, 0, 45, 102}; @@ -859,25 +955,24 @@ TEST_CASE("Advanced") { SECTION("README") { // Example seed, used to generate private key. Always use - // a secure RNG with sufficient entropy to generate a seed (at least 32 bytes). - vector seed = {0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, - 19, 18, 12, 89, 6, 220, 18, 102, 58, 209, 82, - 12, 62, 89, 110, 182, 9, 44, 20, 254, 22}; + // a secure RNG with sufficient entropy to generate a seed (at least 32 + // bytes). + vector seed = {0, 50, 6, 244, 24, 199, 1, 25, + 52, 88, 192, 19, 18, 12, 89, 6, + 220, 18, 102, 58, 209, 82, 12, 62, + 89, 110, 182, 9, 44, 20, 254, 22}; PrivateKey sk = AugSchemeMPL().KeyGen(seed); G1Element pk = sk.GetG1Element(); - vector message = {1, 2, 3, 4, 5}; // Message is passed in as a byte vector + vector message = { + 1, 2, 3, 4, 5}; // Message is passed in as a byte vector G2Element signature = AugSchemeMPL().Sign(sk, message); vector skBytes = sk.Serialize(); vector pkBytes = pk.Serialize(); vector signatureBytes = signature.Serialize(); - cout << Util::HexStr(skBytes) << endl; // 32 bytes - cout << Util::HexStr(pkBytes) << endl; // 48 bytes - cout << Util::HexStr(signatureBytes) << endl; // 96 bytes - // Takes array of 32 bytes PrivateKey skc = PrivateKey::FromByteVector(skBytes); @@ -907,7 +1002,8 @@ TEST_CASE("Advanced") { // Signatures can be noninteractively combined by anyone G2Element aggSig = AugSchemeMPL().Aggregate({sig1, sig2}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message2}, aggSig)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message, message2}, aggSig)); seed[0] = 3; PrivateKey sk3 = AugSchemeMPL().KeyGen(seed); @@ -915,14 +1011,17 @@ TEST_CASE("Advanced") { vector message3 = {100, 2, 254, 88, 90, 45, 23}; G2Element sig3 = AugSchemeMPL().Sign(sk3, message3); - // Arbitrary trees of aggregates G2Element aggSigFinal = AugSchemeMPL().Aggregate({aggSig, sig3}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2, pk3}, vector>{message, message2, message3}, aggSigFinal)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2, pk3}, + vector>{message, message2, message3}, + aggSigFinal)); - // If the same message is signed, you can use Proof of Posession (PopScheme) for efficiency - // A proof of possession MUST be passed around with the PK to ensure security. + // If the same message is signed, you can use Proof of Posession + // (PopScheme) for efficiency A proof of possession MUST be passed + // around with the PK to ensure security. G2Element popSig1 = PopSchemeMPL().Sign(sk1, message); G2Element popSig2 = PopSchemeMPL().Sign(sk2, message); @@ -934,9 +1033,11 @@ TEST_CASE("Advanced") { REQUIRE(PopSchemeMPL().PopVerify(pk1, pop1)); REQUIRE(PopSchemeMPL().PopVerify(pk2, pop2)); REQUIRE(PopSchemeMPL().PopVerify(pk3, pop3)); - G2Element popSigAgg = PopSchemeMPL().Aggregate({popSig1, popSig2, popSig3}); + G2Element popSigAgg = + PopSchemeMPL().Aggregate({popSig1, popSig2, popSig3}); - REQUIRE(PopSchemeMPL().FastAggregateVerify({pk1, pk2, pk3}, message, popSigAgg)); + REQUIRE(PopSchemeMPL().FastAggregateVerify( + {pk1, pk2, pk3}, message, popSigAgg)); // Aggregate public key, indistinguishable from a single public key G1Element popAggPk = pk1 + pk2 + pk3; @@ -946,17 +1047,20 @@ TEST_CASE("Advanced") { PrivateKey aggSk = PrivateKey::Aggregate({sk1, sk2, sk3}); REQUIRE(PopSchemeMPL().Sign(aggSk, message) == popSigAgg); - PrivateKey masterSk = AugSchemeMPL().KeyGen(seed); PrivateKey child = AugSchemeMPL().DeriveChildSk(masterSk, 152); PrivateKey grandchild = AugSchemeMPL().DeriveChildSk(child, 952); G1Element masterPk = masterSk.GetG1Element(); - PrivateKey childU = AugSchemeMPL().DeriveChildSkUnhardened(masterSk, 22); - PrivateKey grandchildU = AugSchemeMPL().DeriveChildSkUnhardened(childU, 0); + PrivateKey childU = + AugSchemeMPL().DeriveChildSkUnhardened(masterSk, 22); + PrivateKey grandchildU = + AugSchemeMPL().DeriveChildSkUnhardened(childU, 0); - G1Element childUPk = AugSchemeMPL().DeriveChildPkUnhardened(masterPk, 22); - G1Element grandchildUPk = AugSchemeMPL().DeriveChildPkUnhardened(childUPk, 0); + G1Element childUPk = + AugSchemeMPL().DeriveChildPkUnhardened(masterPk, 22); + G1Element grandchildUPk = + AugSchemeMPL().DeriveChildPkUnhardened(childUPk, 0); REQUIRE(grandchildUPk == grandchildU.GetG1Element()); } @@ -978,12 +1082,16 @@ TEST_CASE("Advanced") { G2Element g2Bytes = G2Element::FromBytes(Bytes(vecG2Element)); REQUIRE(g2Vector == g2Bytes); - G1Element g1MessageVector = G1Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); - G1Element g1MessageBytes = G1Element::FromMessage(Bytes(vecHash), vecHash.data(), vecHash.size()); + G1Element g1MessageVector = + G1Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); + G1Element g1MessageBytes = G1Element::FromMessage( + Bytes(vecHash), vecHash.data(), vecHash.size()); REQUIRE(g1MessageVector == g1MessageBytes); - G2Element g2MessageVector = G2Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); - G2Element g2MessageBytes = G2Element::FromMessage(Bytes(vecHash), vecHash.data(), vecHash.size()); + G2Element g2MessageVector = + G2Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); + G2Element g2MessageBytes = G2Element::FromMessage( + Bytes(vecHash), vecHash.data(), vecHash.size()); REQUIRE(g2MessageVector == g2MessageBytes); G1Element g1_1 = pk1.GetG1Element(); @@ -991,29 +1099,40 @@ TEST_CASE("Advanced") { G1Element g1_3 = pk3.GetG1Element(); G2Element g2BasicSignVector1 = BasicSchemeMPL().Sign(pk1, vecHash); - G2Element g2BasicSignBytes1 = BasicSchemeMPL().Sign(pk1, Bytes(vecHash)); + G2Element g2BasicSignBytes1 = + BasicSchemeMPL().Sign(pk1, Bytes(vecHash)); REQUIRE(g2BasicSignVector1 == g2BasicSignBytes1); G2Element g2BasicSign2 = BasicSchemeMPL().Sign(pk2, Bytes(vecHash)); - G2Element g2BasicSign3 = BasicSchemeMPL().Sign(pk3, Bytes(vecG2Element)); + G2Element g2BasicSign3 = + BasicSchemeMPL().Sign(pk3, Bytes(vecG2Element)); REQUIRE(g2BasicSignVector1 != g2BasicSign2); - REQUIRE(BasicSchemeMPL().Verify(Bytes(g1_1.Serialize()), Bytes(vecHash), Bytes(g2BasicSignVector1.Serialize()))); - REQUIRE(BasicSchemeMPL().Verify(g1_1, Bytes(vecHash), g2BasicSignVector1)); + REQUIRE(BasicSchemeMPL().Verify( + Bytes(g1_1.Serialize()), + Bytes(vecHash), + Bytes(g2BasicSignVector1.Serialize()))); + REQUIRE( + BasicSchemeMPL().Verify(g1_1, Bytes(vecHash), g2BasicSignVector1)); - vector> vecG1Vector = {g1_1.Serialize(), g1_3.Serialize()}; - vector> vecG2Vector = {g2BasicSignVector1.Serialize(), g2BasicSign3.Serialize()}; + vector> vecG1Vector = { + g1_1.Serialize(), g1_3.Serialize()}; + vector> vecG2Vector = { + g2BasicSignVector1.Serialize(), g2BasicSign3.Serialize()}; vector> vecHashes = {vecHash, vecG2Element}; vector aggVector = BasicSchemeMPL().Aggregate(vecG2Vector); - vector aggBytes = BasicSchemeMPL().Aggregate(vector{vecG2Vector.begin(), vecG2Vector.end()}); + vector aggBytes = BasicSchemeMPL().Aggregate( + vector{vecG2Vector.begin(), vecG2Vector.end()}); REQUIRE(aggVector == aggBytes); - REQUIRE(BasicSchemeMPL().AggregateVerify(vector{vecG1Vector.begin(), vecG1Vector.end()}, - vector{vecHashes.begin(), vecHashes.end()}, - Bytes(aggVector))); - REQUIRE(BasicSchemeMPL().AggregateVerify({g1_1, g1_3}, - vector{vecHashes.begin(), vecHashes.end()}, - G2Element::FromByteVector(aggVector))); + REQUIRE(BasicSchemeMPL().AggregateVerify( + vector{vecG1Vector.begin(), vecG1Vector.end()}, + vector{vecHashes.begin(), vecHashes.end()}, + Bytes(aggVector))); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {g1_1, g1_3}, + vector{vecHashes.begin(), vecHashes.end()}, + G2Element::FromByteVector(aggVector))); G2Element g2AugSignVector1 = AugSchemeMPL().Sign(pk1, vecHash); G2Element g2AugSignBytes1 = AugSchemeMPL().Sign(pk1, Bytes(vecHash)); @@ -1021,40 +1140,53 @@ TEST_CASE("Advanced") { REQUIRE(g2AugSignVector1 == g2AugSignBytes1); REQUIRE(g2AugSignVector1 != g2AugSign2); - REQUIRE(AugSchemeMPL().Verify(Bytes(g1_1.Serialize()), Bytes(vecHash), Bytes(g2AugSignVector1.Serialize()))); + REQUIRE(AugSchemeMPL().Verify( + Bytes(g1_1.Serialize()), + Bytes(vecHash), + Bytes(g2AugSignVector1.Serialize()))); REQUIRE(AugSchemeMPL().Verify(g1_1, Bytes(vecHash), g2AugSignVector1)); - vector> vecG1AugVector = {g1_1.Serialize(), g1_2.Serialize()}; - vector> vecG2AugVector = {g2AugSignVector1.Serialize(), g2AugSign2.Serialize()}; + vector> vecG1AugVector = { + g1_1.Serialize(), g1_2.Serialize()}; + vector> vecG2AugVector = { + g2AugSignVector1.Serialize(), g2AugSign2.Serialize()}; vector aggAugVector = AugSchemeMPL().Aggregate(vecG2AugVector); - vector aggAugBytes = AugSchemeMPL().Aggregate(vector{vecG2AugVector.begin(), vecG2AugVector.end()}); + vector aggAugBytes = AugSchemeMPL().Aggregate( + vector{vecG2AugVector.begin(), vecG2AugVector.end()}); REQUIRE(aggAugVector == aggAugBytes); - REQUIRE(AugSchemeMPL().AggregateVerify(vector{vecG1AugVector.begin(), vecG1AugVector.end()}, - vector{vecHashes.begin(), vecHashes.end()}, - Bytes(aggAugVector))); - REQUIRE(AugSchemeMPL().AggregateVerify({g1_1, g1_2}, - vector{vecHashes.begin(), vecHashes.end()}, - G2Element::FromByteVector(aggAugVector))); + REQUIRE(AugSchemeMPL().AggregateVerify( + vector{vecG1AugVector.begin(), vecG1AugVector.end()}, + vector{vecHashes.begin(), vecHashes.end()}, + Bytes(aggAugVector))); + REQUIRE(AugSchemeMPL().AggregateVerify( + {g1_1, g1_2}, + vector{vecHashes.begin(), vecHashes.end()}, + G2Element::FromByteVector(aggAugVector))); G2Element proof = PopSchemeMPL().PopProve(pk1); REQUIRE(PopSchemeMPL().PopVerify(g1_1, proof)); - REQUIRE(PopSchemeMPL().PopVerify(Bytes(g1_1.Serialize()), Bytes(proof.Serialize()))); + REQUIRE(PopSchemeMPL().PopVerify( + Bytes(g1_1.Serialize()), Bytes(proof.Serialize()))); G2Element g2Pop1 = PopSchemeMPL().Sign(pk1, vecHash); G2Element g2Pop2 = PopSchemeMPL().Sign(pk2, vecHash); G2Element g2PopAgg = PopSchemeMPL().Aggregate({g2Pop1, g2Pop2}); vecG1Vector = {g1_1.Serialize(), g1_2.Serialize()}; - REQUIRE(PopSchemeMPL().FastAggregateVerify({g1_1, g1_2}, Bytes(vecHash), g2PopAgg)); - REQUIRE(PopSchemeMPL().FastAggregateVerify(vector{vecG1Vector.begin(), vecG1Vector.end()}, - Bytes(vecHash), Bytes(g2PopAgg.Serialize()))); + REQUIRE(PopSchemeMPL().FastAggregateVerify( + {g1_1, g1_2}, Bytes(vecHash), g2PopAgg)); + REQUIRE(PopSchemeMPL().FastAggregateVerify( + vector{vecG1Vector.begin(), vecG1Vector.end()}, + Bytes(vecHash), + Bytes(g2PopAgg.Serialize()))); } } - -TEST_CASE("Schemes") { - SECTION("Basic Scheme") { +TEST_CASE("Schemes") +{ + SECTION("Basic Scheme") + { vector seed1(32, 0x04); vector seed2(32, 0x05); vector msg1 = {7, 8, 9}; @@ -1067,7 +1199,6 @@ TEST_CASE("Schemes") { G2Element sig1 = BasicSchemeMPL().Sign(sk1, msg1); vector sig1v = BasicSchemeMPL().Sign(sk1, msg1).Serialize(); - REQUIRE(BasicSchemeMPL().Verify(pk1v, msg1, sig1v)); PrivateKey sk2 = BasicSchemeMPL().KeyGen(seed2); @@ -1087,7 +1218,8 @@ TEST_CASE("Schemes") { REQUIRE(BasicSchemeMPL().Verify(pk2v, msg1, sig1v) == false); G2Element aggsig = BasicSchemeMPL().Aggregate({sig1, sig2}); - vector aggsigv = BasicSchemeMPL().Aggregate(vector>{sig1v, sig2v}); + vector aggsigv = + BasicSchemeMPL().Aggregate(vector>{sig1v, sig2v}); REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, msgs, aggsig)); REQUIRE(BasicSchemeMPL().AggregateVerify({pk1v, pk2v}, msgs, aggsigv)); } @@ -1126,7 +1258,8 @@ TEST_CASE("Schemes") { REQUIRE(AugSchemeMPL().Verify(pk2v, msg1, sig1v) == false); G2Element aggsig = AugSchemeMPL().Aggregate({sig1, sig2}); - vector aggsigv = AugSchemeMPL().Aggregate(vector>{sig1v, sig2v}); + vector aggsigv = + AugSchemeMPL().Aggregate(vector>{sig1v, sig2v}); REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2}, msgs, aggsig)); REQUIRE(AugSchemeMPL().AggregateVerify({pk1v, pk2v}, msgs, aggsigv)); } @@ -1165,7 +1298,8 @@ TEST_CASE("Schemes") { REQUIRE(PopSchemeMPL().Verify(pk2v, msg1, sig1v) == false); G2Element aggsig = PopSchemeMPL().Aggregate({sig1, sig2}); - vector aggsigv = PopSchemeMPL().Aggregate(vector>{sig1v, sig2v}); + vector aggsigv = + PopSchemeMPL().Aggregate(vector>{sig1v, sig2v}); REQUIRE(PopSchemeMPL().AggregateVerify({pk1, pk2}, msgs, aggsig)); REQUIRE(PopSchemeMPL().AggregateVerify({pk1v, pk2v}, msgs, aggsigv)); @@ -1180,8 +1314,8 @@ TEST_CASE("Schemes") { G2Element sig2_same = PopSchemeMPL().Sign(sk2, msg1); vector sig2v_same = PopSchemeMPL().Sign(sk2, msg1).Serialize(); G2Element aggsig_same = PopSchemeMPL().Aggregate({sig1, sig2_same}); - vector aggsigv_same = - PopSchemeMPL().Aggregate(vector>{sig1v, sig2v_same}); + vector aggsigv_same = PopSchemeMPL().Aggregate( + vector>{sig1v, sig2v_same}); REQUIRE( PopSchemeMPL().FastAggregateVerify({pk1, pk2}, msg1, aggsig_same)); REQUIRE(PopSchemeMPL().FastAggregateVerify( @@ -1191,7 +1325,8 @@ TEST_CASE("Schemes") { TEST_CASE("CheckValid") { - SECTION("Valid points should succeed") { + SECTION("Valid points should succeed") + { vector seed(32, 0x05); vector msg1 = {10, 11, 12}; @@ -1217,32 +1352,36 @@ TEST_CASE("CheckValid") G1Element::FromBytes(Bytes(Util::HexToBytes(badPointHex)))); // FromBytesUnchecked does not throw - G1Element pk = + G1Element bad_pk = G1Element::FromBytesUnchecked(Bytes(Util::HexToBytes(badPointHex))); - REQUIRE(pk.IsValid() == false); - REQUIRE_THROWS(pk.CheckValid()); + REQUIRE(bad_pk.IsValid() == false); + REQUIRE_THROWS(bad_pk.CheckValid()); vector seed(32, 0x05); vector msg1 = {10, 11, 12}; PrivateKey sk1 = BasicSchemeMPL().KeyGen(seed); - G1Element pk1 = BasicSchemeMPL().SkToG1(sk1); + G1Element good_pk = BasicSchemeMPL().SkToG1(sk1); + REQUIRE(good_pk.IsValid() == true); G2Element sig1 = AugSchemeMPL().Sign(sk1, msg1); - REQUIRE(AugSchemeMPL().Verify(pk, msg1, sig1) == false); + REQUIRE(AugSchemeMPL().Verify(bad_pk, msg1, sig1) == false); + REQUIRE(AugSchemeMPL().Verify(good_pk, msg1, sig1) == true); } - SECTION("Invalid G2 points should not succeed") { - g2_t point_native; - g2_set_infty(point_native); - fp2_rand(point_native->x); - fp2_rand(point_native->y); - fp2_rand(point_native->z); + SECTION("Invalid G2 points should not succeed") + { + blst_p2 point_native; + memset(&point_native, 0, sizeof(blst_p2)); + + // copy some probably invalid data into the point + memcpy(&(point_native.x), (void*)memcpy, sizeof(point_native.x)); + memcpy(&(point_native.y), (void*)memset, sizeof(point_native.y)); + memcpy(&(point_native.z), (void*)printf, sizeof(point_native.z)); G2Element point = G2Element::FromNative(point_native); REQUIRE(point.IsValid() == false); REQUIRE_THROWS(point.CheckValid()); auto badSer = point.Serialize(); - std::cout < seed(32, 0x05); + blst_p1_affine p1_affine; + + PrivateKey sk1 = BasicSchemeMPL().KeyGen(seed); + G1Element pk1 = BasicSchemeMPL().SkToG1(sk1); + pk1.CheckValid(); + pk1.ToAffine(&p1_affine); + GTElement gt1 = GTElement::FromAffine(p1_affine); + + auto outbuf = gt1.Serialize(); + + auto gt2 = GTElement::FromBytesUnchecked(outbuf); + + REQUIRE(gt1 == gt2); + } + + SECTION("GTElement pairing") + { + vector seed(32, 0x05), seed2(32, 0x06); + vector msg1 = {7, 8, 9}; + vector msg2 = {10, 11, 12}; + + auto sk1 = BasicSchemeMPL().KeyGen(seed); + auto sk2 = BasicSchemeMPL().KeyGen(seed2); + + auto pk1 = sk1.GetG1Element(); + auto pk2 = sk2.GetG1Element(); + + auto sig1 = BasicSchemeMPL().Sign(sk1, msg1); + auto sig2 = BasicSchemeMPL().Sign(sk2, msg2); + + auto aggsig = BasicSchemeMPL().Aggregate({sig1, sig2}); + + REQUIRE(BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{msg1, msg2}, aggsig)); + + auto pair1 = pk1.Pair(G2Element::FromMessage( + msg1, + (const uint8_t*)BasicSchemeMPL::CIPHERSUITE_ID.c_str(), + BasicSchemeMPL::CIPHERSUITE_ID.length())); + auto pair2 = pk2.Pair(G2Element::FromMessage( + msg2, + (const uint8_t*)BasicSchemeMPL::CIPHERSUITE_ID.c_str(), + BasicSchemeMPL::CIPHERSUITE_ID.length())); + auto pair = pair1 * pair2; + + auto agg_sig_pair = G1Element::Generator().Pair(aggsig); + + REQUIRE(pair == agg_sig_pair); + } +} + int main(int argc, char* argv[]) { int result = Catch::Session().run(argc, argv); diff --git a/src/util.hpp b/src/util.hpp index 37fd8547a..1ed710589 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -60,9 +61,41 @@ class Util { public: static void Hash256(uint8_t* output, const uint8_t* message, size_t messageLen) { - md_map_sh256(output, message, messageLen); + blst_sha256(output, message, messageLen); } +static void md_hmac(uint8_t *mac, const uint8_t *in, int in_len, const uint8_t *key, + int key_len) { + #define block_size 64 + #define RLC_MD_LEN 32 + uint8_t opad[block_size + RLC_MD_LEN]; + uint8_t *ipad = (uint8_t *)malloc(block_size + in_len); + uint8_t _key[block_size]; + + if (ipad == NULL) + throw std::runtime_error("out of memory"); + + if (key_len > block_size) { + Hash256(_key, key, key_len); + key = _key; + key_len = RLC_MD_LEN; + } + + memcpy(_key, key, key_len); + memset(_key + key_len, 0, block_size - key_len); + key = _key; + + for (int i = 0; i < block_size; i++) { + opad[i] = 0x5C ^ key[i]; + ipad[i] = 0x36 ^ key[i]; + } + memcpy(ipad + block_size, in, in_len); + Hash256(opad + block_size, ipad, block_size + in_len); + Hash256(mac, opad, block_size + RLC_MD_LEN); + + free(ipad); +} + static std::string HexStr(const uint8_t* data, size_t len) { std::stringstream s; s << std::hex;