diff --git a/.github/actions/run-in-docker-action/action.yml b/.github/actions/run-in-docker-action/action.yml index 5d46ca1b..bbbcf324 100644 --- a/.github/actions/run-in-docker-action/action.yml +++ b/.github/actions/run-in-docker-action/action.yml @@ -6,8 +6,7 @@ inputs: required: true scope: description: 'A cached image scope' - required: false - default: ${{ runner.arch }} + required: true command: description: 'A command to run in a container' required: true @@ -45,7 +44,7 @@ runs: $(echo '${{ toJSON(env) }}' | jq -r 'keys[] | "--env \(.) "') \ --volume ${{ github.workspace }}:${{ github.workspace }} \ --workdir ${{ github.workspace }} \ - $(docker images -q | head -n1) \ + ${{ case(steps.main_builder.outcome == 'success', steps.main_builder.outputs.imageid, steps.retry_builder.outputs.imageid) }} \ bash -c " git config --global --add safe.directory ${{ github.workspace }} ${{ inputs.command }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6ff9e36..0c745ea8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,10 @@ on: - '**' tags-ignore: - '**' + schedule: + # Run on the default branch every Monday morning. + # This also warms the Docker caches after key rotation. + - cron: '22 2 * * 1' concurrency: group: ${{ github.event_name != 'pull_request' && github.run_id || github.ref }} @@ -50,11 +54,16 @@ env: SYMBOL_CHECK: 'yes' # Compile and run the examples. EXAMPLES: 'yes' + # Disable Docker build summary generation. + # See https://github.com/docker/build-push-action/blob/master/README.md#environment-variables. + DOCKER_BUILD_SUMMARY: false jobs: docker_cache: name: "Build ${{ matrix.arch }} Docker image" runs-on: ${{ matrix.runner }} + outputs: + cache_scope: ${{ steps.cache_timestamp.outputs.period }} strategy: fail-fast: false @@ -66,6 +75,10 @@ jobs: runner: ubuntu-24.04-arm steps: + - name: Get cache validity period + id: cache_timestamp + run: echo "period=$((10#$(date +%V) / 4))" >> "$GITHUB_OUTPUT" + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: @@ -77,8 +90,8 @@ jobs: uses: docker/build-push-action@v6 with: file: ./ci/linux-debian.Dockerfile - cache-from: type=gha,scope=${{ runner.arch }} - cache-to: type=gha,scope=${{ runner.arch }},mode=min + cache-from: type=gha,scope=${{ runner.arch }}-${{ steps.cache_timestamp.outputs.period }} + cache-to: type=gha,scope=${{ runner.arch }}-${{ steps.cache_timestamp.outputs.period }},mode=min x86_64-debian: name: "x86_64: Linux (Debian stable)" @@ -124,6 +137,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile + scope: ${{ runner.arch }}-${{ needs.docker_cache.outputs.cache_scope }} command: ./ci/ci.sh - &PRINT_LOGS @@ -723,6 +737,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile + scope: ${{ runner.arch }}-${{ needs.docker_cache.outputs.cache_scope }} command: | g++ -Werror include/*.h clang -Werror -x c++-header include/*.h diff --git a/.gitignore b/.gitignore index 66d2e6e8..8658272e 100644 --- a/.gitignore +++ b/.gitignore @@ -49,27 +49,16 @@ coverage.*.html *.gcno *.gcov -build-aux/ar-lib -build-aux/config.guess -build-aux/config.sub -build-aux/depcomp -build-aux/install-sh -build-aux/ltmain.sh -build-aux/m4/libtool.m4 -build-aux/m4/lt~obsolete.m4 -build-aux/m4/ltoptions.m4 -build-aux/m4/ltsugar.m4 -build-aux/m4/ltversion.m4 -build-aux/missing -build-aux/compile -build-aux/test-driver +/autotools-aux/ +!/autotools-aux/m4/bitcoin_secp.m4 + libsecp256k1.pc contrib/gh-pr-create.sh ### CMake /CMakeUserPresets.json -# Default CMake build directory. -/build +# CMake build directories. +/*build* ### Python __pycache__/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 2235c9cb..ce6a706e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,6 +225,7 @@ else() try_append_c_flags(-Wcast-align=strict) # GCC >= 8.0. try_append_c_flags(-Wconditional-uninitialized) # Clang >= 3.0 only. try_append_c_flags(-Wextra) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions. + try_append_c_flags(-Wleading-whitespace=spaces) # GCC >= 15.0 try_append_c_flags(-Wnested-externs) try_append_c_flags(-Wno-long-long) # GCC >= 3.0, -Wlong-long is implied by -pedantic. try_append_c_flags(-Wno-overlength-strings) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic. @@ -232,6 +233,7 @@ else() try_append_c_flags(-Wreserved-identifier) # Clang >= 13.0 only. try_append_c_flags(-Wshadow) try_append_c_flags(-Wstrict-prototypes) + try_append_c_flags(-Wtrailing-whitespace=any) # GCC >= 15.0 try_append_c_flags(-Wundef) endif() diff --git a/Makefile.am b/Makefile.am index 4191a57f..51c8f6bf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -ACLOCAL_AMFLAGS = -I build-aux/m4 +ACLOCAL_AMFLAGS = -I autotools-aux/m4 # AM_CFLAGS will be automatically prepended to CFLAGS by Automake when compiling some foo # which does not have an explicit foo_CFLAGS variable set. diff --git a/build-aux/m4/bitcoin_secp.m4 b/autotools-aux/m4/bitcoin_secp.m4 similarity index 100% rename from build-aux/m4/bitcoin_secp.m4 rename to autotools-aux/m4/bitcoin_secp.m4 diff --git a/cmake/DiscoverTests.cmake b/cmake/DiscoverTests.cmake new file mode 100644 index 00000000..683780a8 --- /dev/null +++ b/cmake/DiscoverTests.cmake @@ -0,0 +1,71 @@ +# TODO: rework/remove once test discovery is implemented upstream: +# https://gitlab.kitware.com/cmake/cmake/-/issues/26920 +function(discover_tests target) + set(options "") + set(oneValueArgs DISCOVERY_MATCH TEST_NAME_REPLACEMENT TEST_ARGS_REPLACEMENT) + set(multiValueArgs DISCOVERY_ARGS PROPERTIES) + cmake_parse_arguments(PARSE_ARGV 1 arg "${options}" "${oneValueArgs}" "${multiValueArgs}") + + set(file_base ${CMAKE_CURRENT_BINARY_DIR}/${target}) + set(include_file ${file_base}_include.cmake) + + set(properties_content) + list(LENGTH arg_PROPERTIES properties_len) + if(properties_len GREATER "0") + set(properties_content " set_tests_properties(\"\${test_name}\" PROPERTIES\n") + math(EXPR num_properties "${properties_len} / 2") + foreach(i RANGE 0 ${num_properties} 2) + math(EXPR value_index "${i} + 1") + list(GET arg_PROPERTIES ${i} name) + list(GET arg_PROPERTIES ${value_index} value) + string(APPEND properties_content " \"${name}\" \"${value}\"\n") + endforeach() + string(APPEND properties_content " )\n") + endif() + + string(CONCAT include_content + "set(runner [[$]])\n" + "set(launcher [[$]])\n" + "set(emulator [[$<$:$>]])\n" + "\n" + "execute_process(\n" + " COMMAND \${launcher} \${emulator} \${runner} ${arg_DISCOVERY_ARGS}\n" + " OUTPUT_VARIABLE output OUTPUT_STRIP_TRAILING_WHITESPACE\n" + " ERROR_VARIABLE output ERROR_STRIP_TRAILING_WHITESPACE\n" + " RESULT_VARIABLE result\n" + ")\n" + "\n" + "if(NOT result EQUAL 0)\n" + " add_test([[${target}_DISCOVERY_FAILURE]] \${launcher} \${emulator} \${runner} ${arg_DISCOVERY_ARGS})\n" + "else()\n" + " string(REPLACE \"\\n\" \";\" lines \"\${output}\")\n" + " foreach(line IN LISTS lines)\n" + " if(line MATCHES \"${arg_DISCOVERY_MATCH}\")\n" + " string(REGEX REPLACE \"${arg_DISCOVERY_MATCH}\" \"${arg_TEST_NAME_REPLACEMENT}\" test_name \"\${line}\")\n" + " string(REGEX REPLACE \"${arg_DISCOVERY_MATCH}\" \"${arg_TEST_ARGS_REPLACEMENT}\" test_args \"\${line}\")\n" + " separate_arguments(test_args)\n" + " add_test(\"\${test_name}\" \${launcher} \${emulator} \${runner} \${test_args})\n" + ${properties_content} + " endif()\n" + " endforeach()\n" + "endif()\n" + ) + + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + file(GENERATE + OUTPUT ${file_base}_include-$.cmake + CONTENT "${include_content}" + ) + file(WRITE ${include_file} + "include(\"${file_base}_include-\${CTEST_CONFIGURATION_TYPE}.cmake\")" + ) + else() + file(GENERATE + OUTPUT ${include_file} + CONTENT "${include_content}" + ) + endif() + + set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES ${include_file}) +endfunction() diff --git a/configure.ac b/configure.ac index 99ef0884..1d961b09 100644 --- a/configure.ac +++ b/configure.ac @@ -19,8 +19,8 @@ define(_LIB_VERSION_AGE, 0) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([build-aux/m4]) +AC_CONFIG_AUX_DIR([autotools-aux]) +AC_CONFIG_MACRO_DIR([autotools-aux/m4]) AC_CANONICAL_HOST # Require Automake 1.11.2 for AM_PROG_AR @@ -111,6 +111,8 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [ SECP_TRY_APPEND_CFLAGS([-Wcast-align=strict], $1) # GCC >= 8.0 SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only SECP_TRY_APPEND_CFLAGS([-Wreserved-identifier], $1) # Clang >= 13.0 only + SECP_TRY_APPEND_CFLAGS([-Wtrailing-whitespace=any], $1) # GCC >= 15.0 + SECP_TRY_APPEND_CFLAGS([-Wleading-whitespace=spaces], $1) # GCC >= 15.0 CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS" fi diff --git a/doc/release-process.md b/doc/release-process.md index a64bae0f..3cf183df 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -61,7 +61,7 @@ Perform these checks when reviewing the release PR (see below): 4. Open a PR to the master branch with a commit (using message `"release cleanup: bump version after $MAJOR.$MINOR.$PATCH"`, for example) that * sets `_PKG_VERSION_IS_RELEASE` to `false` and increments `_PKG_VERSION_PATCH` and `_LIB_VERSION_REVISION` in `configure.ac`, * increments the `$PATCH` component of `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_REVISION` in `CMakeLists.txt`, and - * adds an `[Unreleased]` section header to the [CHANGELOG.md](../CHANGELOG.md). + * adds an `[Unreleased]` section header and a corresponding `[Unreleased]` link at the bottom of [CHANGELOG.md](../CHANGELOG.md). If other maintainers are not present to approve the PR, it can be merged without ACKs. 5. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md). diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c9da9de6..808917c4 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,8 +8,10 @@ function(add_example name) secp256k1 $<$:bcrypt> ) - set(test_name ${name}_example) - add_test(NAME secp256k1_${test_name} COMMAND ${target_name}) + add_test(NAME secp256k1.example.${name} COMMAND ${target_name}) + set_tests_properties(secp256k1.example.${name} PROPERTIES + LABELS secp256k1_example + ) endfunction() add_example(ecdsa) diff --git a/include/secp256k1.h b/include/secp256k1.h index 2799d4a1..9de45f1f 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -349,7 +349,7 @@ SECP256K1_API void secp256k1_context_destroy( * writes the message to stderr and calls abort. This default callback can be * replaced at link time if the preprocessor macro * USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build - * has been configured with --enable-external-default-callbacks (GNU Autotools) or + * has been configured with --enable-external-default-callbacks (GNU Autotools) or * -DSECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS=ON (CMake). Then the * following two symbols must be provided to link against: * - void secp256k1_default_illegal_callback_fn(const char *message, void *data); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cf371e9e..938d8040 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -147,7 +147,7 @@ set_target_properties(secp256k1_objs PROPERTIES ) # This emulates Libtool to make sure Libtool and CMake agree on the ABI version, -# see below "Calculate the version variables" in build-aux/ltmain.sh. +# see below "Calculate the version variables" in autotools-aux/ltmain.sh. math(EXPR ${PROJECT_NAME}_soversion "${${PROJECT_NAME}_LIB_VERSION_CURRENT} - ${${PROJECT_NAME}_LIB_VERSION_AGE}") set_target_properties(secp256k1 PROPERTIES SOVERSION ${${PROJECT_NAME}_soversion} @@ -196,15 +196,24 @@ if(SECP256K1_BUILD_TESTS) list(APPEND TEST_DEFINITIONS SUPPORTS_CONCURRENCY=1) endif() - add_executable(noverify_tests tests.c) - target_link_libraries(noverify_tests secp256k1_precomputed secp256k1_asm) - target_compile_definitions(noverify_tests PRIVATE ${TEST_DEFINITIONS}) - add_test(NAME secp256k1_noverify_tests COMMAND noverify_tests) + function(add_executable_and_tests exe_name verify_definition) + add_executable(${exe_name} tests.c) + target_link_libraries(${exe_name} secp256k1_precomputed secp256k1_asm) + target_compile_definitions(${exe_name} PRIVATE ${verify_definition} ${TEST_DEFINITIONS}) + include(DiscoverTests) + discover_tests(${exe_name} + DISCOVERY_ARGS "--list_tests" + DISCOVERY_MATCH "^\\t\\\\[ *[0-9]+\\\\] ([^ ].*)$" + TEST_NAME_REPLACEMENT "secp256k1.${exe_name}.\\\\1" + TEST_ARGS_REPLACEMENT "--target=\\\\1 --log=1" + PROPERTIES + LABELS "secp256k1_${exe_name}" + ) + endfunction() + + add_executable_and_tests(noverify_tests "") if(NOT CMAKE_BUILD_TYPE STREQUAL "Coverage") - add_executable(tests tests.c) - target_compile_definitions(tests PRIVATE VERIFY ${TEST_DEFINITIONS}) - target_link_libraries(tests secp256k1_precomputed secp256k1_asm) - add_test(NAME secp256k1_tests COMMAND tests) + add_executable_and_tests(tests VERIFY) endif() unset(TEST_DEFINITIONS) endif() @@ -214,7 +223,10 @@ if(SECP256K1_BUILD_EXHAUSTIVE_TESTS) add_executable(exhaustive_tests tests_exhaustive.c) target_link_libraries(exhaustive_tests secp256k1_asm) target_compile_definitions(exhaustive_tests PRIVATE $<$>:VERIFY>) - add_test(NAME secp256k1_exhaustive_tests COMMAND exhaustive_tests) + add_test(NAME secp256k1.exhaustive_tests COMMAND exhaustive_tests) + set_tests_properties(secp256k1.exhaustive_tests PROPERTIES + LABELS secp256k1_exhaustive + ) endif() if(SECP256K1_BUILD_CTIME_TESTS) diff --git a/src/bench.c b/src/bench.c index a5231b71..de7fef94 100644 --- a/src/bench.c +++ b/src/bench.c @@ -12,7 +12,7 @@ #include "util.h" #include "bench.h" -static void help(int default_iters) { +static void help(const char *executable_path, int default_iters) { printf("Benchmarks the following algorithms:\n"); printf(" - ECDSA signing/verification\n"); @@ -36,7 +36,7 @@ static void help(int default_iters) { printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); printf("\n"); - printf("Usage: ./bench [args]\n"); + printf("Usage: %s [args]\n", executable_path); printf("By default, all benchmarks will be run.\n"); printf("args:\n"); printf(" help : display this help and exit\n"); @@ -189,7 +189,7 @@ int main(int argc, char** argv) { int default_iters = 20000; int iters = get_iters(default_iters); if (iters == 0) { - help(default_iters); + help(argv[0], default_iters); return EXIT_FAILURE; } @@ -197,11 +197,11 @@ int main(int argc, char** argv) { if (have_flag(argc, argv, "-h") || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { - help(default_iters); + help(argv[0], default_iters); return EXIT_SUCCESS; } else if (invalid_args) { fprintf(stderr, "./bench: unrecognized argument.\n\n"); - help(default_iters); + help(argv[0], default_iters); return EXIT_FAILURE; } } diff --git a/src/bench.h b/src/bench.h index 72a3f211..f88277aa 100644 --- a/src/bench.h +++ b/src/bench.h @@ -59,7 +59,7 @@ static void print_number(const int64_t x) { y /= 10; } } else if (c == 0) { /* fractional part is 0 */ - buffer[--ptr] = '0'; + buffer[--ptr] = '0'; } buffer[--ptr] = '.'; do { diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index bcf8b431..7393730d 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -19,13 +19,13 @@ #define POINTS 32768 -static void help(char **argv, int default_iters) { +static void help(const char *executable_path, int default_iters) { printf("Benchmark EC multiplication algorithms\n"); printf("\n"); printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); printf("\n"); - printf("Usage: %s \n", argv[0]); + printf("Usage: %s [args]\n", executable_path); printf("The output shows the number of multiplied and summed points right after the\n"); printf("function name. The letter 'g' indicates that one of the points is the generator.\n"); printf("The benchmarks are divided by the number of points.\n"); @@ -314,7 +314,7 @@ int main(int argc, char **argv) { int default_iters = 10000; int iters = get_iters(default_iters); if (iters == 0) { - help(argv, default_iters); + help(argv[0], default_iters); return EXIT_FAILURE; } @@ -324,7 +324,7 @@ int main(int argc, char **argv) { if(have_flag(argc, argv, "-h") || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { - help(argv, default_iters); + help(argv[0], default_iters); return EXIT_SUCCESS; } else if(have_flag(argc, argv, "pippenger_wnaf")) { printf("Using pippenger_wnaf:\n"); @@ -336,7 +336,7 @@ int main(int argc, char **argv) { printf("Using simple algorithm:\n"); } else { fprintf(stderr, "%s: unrecognized argument '%s'.\n\n", argv[0], argv[1]); - help(argv, default_iters); + help(argv[0], default_iters); return EXIT_FAILURE; } } diff --git a/src/bench_internal.c b/src/bench_internal.c index 3739a1d2..7539ccbb 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -18,13 +18,13 @@ #include "ecmult_impl.h" #include "bench.h" -static void help(int default_iters) { +static void help(const char *executable_path, int default_iters) { printf("Benchmarks various internal routines.\n"); printf("\n"); printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); printf("\n"); - printf("Usage: ./bench_internal [args]\n"); + printf("Usage: %s [args]\n", executable_path); printf("By default, all benchmarks will be run.\n"); printf("args:\n"); printf(" help : display this help and exit\n"); @@ -416,7 +416,7 @@ int main(int argc, char **argv) { int default_iters = 20000; int iters = get_iters(default_iters); if (iters == 0) { - help(default_iters); + help(argv[0], default_iters); return EXIT_FAILURE; } @@ -424,7 +424,7 @@ int main(int argc, char **argv) { if (have_flag(argc, argv, "-h") || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { - help(default_iters); + help(argv[0], default_iters); return EXIT_SUCCESS; } } diff --git a/src/checkmem.h b/src/checkmem.h index 08eae47d..88c65c8e 100644 --- a/src/checkmem.h +++ b/src/checkmem.h @@ -78,10 +78,15 @@ # if defined(__clang__) && defined(__APPLE__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wreserved-identifier" +# elif defined(__GNUC__) && (__GNUC__ >= 15) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wtrailing-whitespace" # endif # include # if defined(__clang__) && defined(__APPLE__) # pragma clang diagnostic pop +# elif defined(__GNUC__) && (__GNUC__ >= 15) +# pragma GCC diagnostic pop # endif # define SECP256K1_CHECKMEM_ENABLED 1 # define SECP256K1_CHECKMEM_UNDEFINE(p, len) VALGRIND_MAKE_MEM_UNDEFINED((p), (len)) diff --git a/src/ctime_tests.c b/src/ctime_tests.c index 69a7688d..3a12d0bc 100644 --- a/src/ctime_tests.c +++ b/src/ctime_tests.c @@ -57,7 +57,7 @@ int main(void) { if (!SECP256K1_CHECKMEM_RUNNING()) { fprintf(stderr, "This test can only usefully be run inside valgrind because it was not compiled under msan.\n"); - fprintf(stderr, "Usage: libtool --mode=execute valgrind ./ctime_tests\n"); + fprintf(stderr, "Usage: valgrind ./ctime_tests (or with Autotools: libtool --mode=execute valgrind ./ctime_tests)\n"); return EXIT_FAILURE; } ctx = secp256k1_context_create(SECP256K1_CONTEXT_DECLASSIFY); diff --git a/src/ecmult.h b/src/ecmult.h index 326a5eeb..8d0a9f49 100644 --- a/src/ecmult.h +++ b/src/ecmult.h @@ -38,7 +38,7 @@ #endif /** The number of entries a table with precomputed multiples needs to have. */ -#define ECMULT_TABLE_SIZE(w) (1L << ((w)-2)) +#define ECMULT_TABLE_SIZE(w) ((size_t)1 << ((w)-2)) /** Double multiply: R = na*A + ng*G */ static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); diff --git a/src/ecmult_compute_table_impl.h b/src/ecmult_compute_table_impl.h index 69d59ce5..09b899b4 100644 --- a/src/ecmult_compute_table_impl.h +++ b/src/ecmult_compute_table_impl.h @@ -16,7 +16,7 @@ static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen) { secp256k1_gej gj; secp256k1_ge ge, dgen; - int j; + size_t j; gj = *gen; secp256k1_ge_set_gej_var(&ge, &gj); diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index c421750d..1a05244c 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -70,10 +70,10 @@ * Lastly the zr[0] value, which isn't used above, is set so that: * - a.z = z(pre_a[0]) / zr[0] */ -static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_ge *pre_a, secp256k1_fe *zr, secp256k1_fe *z, const secp256k1_gej *a) { +static void secp256k1_ecmult_odd_multiples_table(size_t n, secp256k1_ge *pre_a, secp256k1_fe *zr, secp256k1_fe *z, const secp256k1_gej *a) { secp256k1_gej d, ai; secp256k1_ge d_ge; - int i; + size_t i; VERIFY_CHECK(!secp256k1_gej_is_infinity(a)); @@ -311,8 +311,9 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state * } for (np = 0; np < no; ++np) { - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_fe_mul(&state->aux[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i].x, &secp256k1_const_beta); + size_t j; + for (j = 0; j < ECMULT_TABLE_SIZE(WINDOW_A); j++) { + secp256k1_fe_mul(&state->aux[np * ECMULT_TABLE_SIZE(WINDOW_A) + j], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + j].x, &secp256k1_const_beta); } } @@ -517,7 +518,6 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi size_t np; size_t no = 0; int i; - int j; for (np = 0; np < num; ++np) { if (secp256k1_scalar_is_zero(&sc[np]) || secp256k1_ge_is_infinity(&pt[np])) { @@ -535,16 +535,17 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi for (i = n_wnaf - 1; i >= 0; i--) { secp256k1_gej running_sum; + int j; + size_t buc; - for(j = 0; j < ECMULT_TABLE_SIZE(bucket_window+2); j++) { - secp256k1_gej_set_infinity(&buckets[j]); + for (buc = 0; buc < ECMULT_TABLE_SIZE(bucket_window+2); buc++) { + secp256k1_gej_set_infinity(&buckets[buc]); } for (np = 0; np < no; ++np) { int n = state->wnaf_na[np*n_wnaf + i]; struct secp256k1_pippenger_point_state point_state = state->ps[np]; secp256k1_ge tmp; - int idx; if (i == 0) { /* correct for wnaf skew */ @@ -555,16 +556,16 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi } } if (n > 0) { - idx = (n - 1)/2; - secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL); + buc = (n - 1)/2; + secp256k1_gej_add_ge_var(&buckets[buc], &buckets[buc], &pt[point_state.input_pos], NULL); } else if (n < 0) { - idx = -(n + 1)/2; + buc = -(n + 1)/2; secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]); - secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL); + secp256k1_gej_add_ge_var(&buckets[buc], &buckets[buc], &tmp, NULL); } } - for(j = 0; j < bucket_window; j++) { + for (j = 0; j < bucket_window; j++) { secp256k1_gej_double_var(r, r, NULL); } @@ -577,8 +578,8 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi * * The doubling is done implicitly by deferring the final window doubling (of 'r'). */ - for(j = ECMULT_TABLE_SIZE(bucket_window+2) - 1; j > 0; j--) { - secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL); + for (buc = ECMULT_TABLE_SIZE(bucket_window+2) - 1; buc > 0; buc--) { + secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[buc], NULL); secp256k1_gej_add_var(r, r, &running_sum, NULL); } diff --git a/src/field.h b/src/field.h index e3f0234f..945029ec 100644 --- a/src/field.h +++ b/src/field.h @@ -233,7 +233,7 @@ static void secp256k1_fe_add_int(secp256k1_fe *r, int a); #define secp256k1_fe_mul_int(r, a) ASSERT_INT_CONST_AND_DO(a, secp256k1_fe_mul_int_unchecked(r, a)) /** Like secp256k1_fe_mul_int but a is not checked to be an integer constant expression. - * + * * Should not be called directly outside of tests. */ static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a); diff --git a/src/hash.h b/src/hash.h index 6d903ca7..43cdd60c 100644 --- a/src/hash.h +++ b/src/hash.h @@ -17,6 +17,10 @@ typedef struct { } secp256k1_sha256; static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); +/* Initialize a SHA256 hash state with a precomputed midstate. + * The byte counter must be a multiple of 64, i.e., there must be no unwritten + * bytes in the buffer. */ +static void secp256k1_sha256_initialize_midstate(secp256k1_sha256 *hash, uint64_t bytes, const uint32_t state[8]); static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); static void secp256k1_sha256_clear(secp256k1_sha256 *hash); diff --git a/src/hash_impl.h b/src/hash_impl.h index 43419177..da3b4660 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -40,6 +40,13 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { hash->bytes = 0; } +static void secp256k1_sha256_initialize_midstate(secp256k1_sha256 *hash, uint64_t bytes, const uint32_t state[8]) { + VERIFY_CHECK((bytes & 0x3F) == 0); + VERIFY_CHECK(state != NULL); + memcpy(hash->s, state, sizeof(hash->s)); + hash->bytes = bytes; +} + /** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* buf) { uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index 096f4a3c..f9ef0ac8 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -383,17 +383,11 @@ static void secp256k1_ellswift_elligatorswift_var(unsigned char *u32, secp256k1_ /** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_encode". */ static void secp256k1_ellswift_sha256_init_encode(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); - hash->s[0] = 0xd1a6524bul; - hash->s[1] = 0x028594b3ul; - hash->s[2] = 0x96e42f4eul; - hash->s[3] = 0x1037a177ul; - hash->s[4] = 0x1b8fcb8bul; - hash->s[5] = 0x56023885ul; - hash->s[6] = 0x2560ede1ul; - hash->s[7] = 0xd626b715ul; - - hash->bytes = 64; + static const uint32_t midstate[8] = { + 0xd1a6524bul, 0x028594b3ul, 0x96e42f4eul, 0x1037a177ul, + 0x1b8fcb8bul, 0x56023885ul, 0x2560ede1ul, 0xd626b715ul + }; + secp256k1_sha256_initialize_midstate(hash, 64, midstate); } int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64, const secp256k1_pubkey *pubkey, const unsigned char *rnd32) { @@ -427,17 +421,11 @@ int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64 /** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_create". */ static void secp256k1_ellswift_sha256_init_create(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); - hash->s[0] = 0xd29e1bf5ul; - hash->s[1] = 0xf7025f42ul; - hash->s[2] = 0x9b024773ul; - hash->s[3] = 0x094cb7d5ul; - hash->s[4] = 0xe59ed789ul; - hash->s[5] = 0x03bc9786ul; - hash->s[6] = 0x68335b35ul; - hash->s[7] = 0x4e363b53ul; - - hash->bytes = 64; + static const uint32_t midstate[8] = { + 0xd29e1bf5ul, 0xf7025f42ul, 0x9b024773ul, 0x094cb7d5ul, + 0xe59ed789ul, 0x03bc9786ul, 0x68335b35ul, 0x4e363b53ul + }; + secp256k1_sha256_initialize_midstate(hash, 64, midstate); } int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64, const unsigned char *seckey32, const unsigned char *auxrnd32) { @@ -510,17 +498,11 @@ static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsign /** Set hash state to the BIP340 tagged hash midstate for "bip324_ellswift_xonly_ecdh". */ static void secp256k1_ellswift_sha256_init_bip324(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); - hash->s[0] = 0x8c12d730ul; - hash->s[1] = 0x827bd392ul; - hash->s[2] = 0x9e4fb2eeul; - hash->s[3] = 0x207b373eul; - hash->s[4] = 0x2292bd7aul; - hash->s[5] = 0xaa5441bcul; - hash->s[6] = 0x15c3779ful; - hash->s[7] = 0xcfb52549ul; - - hash->bytes = 64; + static const uint32_t midstate[8] = { + 0x8c12d730ul, 0x827bd392ul, 0x9e4fb2eeul, 0x207b373eul, + 0x2292bd7aul, 0xaa5441bcul, 0x15c3779ful, 0xcfb52549ul + }; + secp256k1_sha256_initialize_midstate(hash, 64, midstate); } static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { @@ -564,7 +546,7 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output, /* Load private key (using one if invalid). */ secp256k1_scalar_set_b32(&s, seckey32, &overflow); - overflow = secp256k1_scalar_is_zero(&s); + overflow |= secp256k1_scalar_is_zero(&s); secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow); /* Compute shared X coordinate. */ diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index 4cc7f4b5..e3090411 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -460,6 +460,33 @@ void ellswift_hash_init_tests(void) { test_sha256_tag_midstate(&sha_optimized, bip324_tag, sizeof(bip324_tag)); } +void ellswift_xdh_bad_scalar_tests(void) { + unsigned char s_zero[32] = { 0 }; + unsigned char s_overflow_minus1[32] = { 0 }; + unsigned char s_overflow_plus1[32] = { 0 }; + unsigned char s_good[32] = { 0 }; + unsigned char ell_a64[64], ell_b64[64]; + unsigned char output[32]; + secp256k1_scalar rand_scalar; + + testutil_random_scalar_order(&rand_scalar); + secp256k1_scalar_get_b32(s_good, &rand_scalar); + + CHECK(secp256k1_ellswift_create(CTX, ell_a64, s_good, NULL) == 1); + + testrand256_test(ell_b64); + testrand256_test(ell_b64 + 32); + + memcpy(s_overflow_minus1, secp256k1_group_order_bytes, 32); + s_overflow_minus1[31] -= 1; + memcpy(s_overflow_plus1, secp256k1_group_order_bytes, 32); + s_overflow_plus1[31] += 1; + CHECK(secp256k1_ellswift_xdh(CTX, output, ell_a64, ell_b64, s_zero, 0, &ellswift_xdh_hash_x32, NULL) == 0); + CHECK(secp256k1_ellswift_xdh(CTX, output, ell_a64, ell_b64, secp256k1_group_order_bytes, 0, &ellswift_xdh_hash_x32, NULL) == 0); + CHECK(secp256k1_ellswift_xdh(CTX, output, ell_a64, ell_b64, s_overflow_plus1, 0, &ellswift_xdh_hash_x32, NULL) == 0); + CHECK(secp256k1_ellswift_xdh(CTX, output, ell_a64, ell_b64, s_overflow_minus1, 0, &ellswift_xdh_hash_x32, NULL) == 1); +} + /* --- Test registry --- */ static const struct tf_test_entry tests_ellswift[] = { CASE1(ellswift_encoding_test_vectors_tests), @@ -470,6 +497,7 @@ static const struct tf_test_entry tests_ellswift[] = { CASE1(ellswift_compute_shared_secret_tests), CASE1(ellswift_xdh_correctness_tests), CASE1(ellswift_hash_init_tests), + CASE1(ellswift_xdh_bad_scalar_tests), }; #endif diff --git a/src/modules/musig/keyagg_impl.h b/src/modules/musig/keyagg_impl.h index e412a27e..4eb48ddc 100644 --- a/src/modules/musig/keyagg_impl.h +++ b/src/modules/musig/keyagg_impl.h @@ -62,17 +62,11 @@ static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_k /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */ static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - - sha->s[0] = 0xb399d5e0ul; - sha->s[1] = 0xc8fff302ul; - sha->s[2] = 0x6badac71ul; - sha->s[3] = 0x07c5b7f1ul; - sha->s[4] = 0x9701e2eful; - sha->s[5] = 0x2a72ecf8ul; - sha->s[6] = 0x201a4c7bul; - sha->s[7] = 0xab148a38ul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0xb399d5e0ul, 0xc8fff302ul, 0x6badac71ul, 0x07c5b7f1ul, + 0x9701e2eful, 0x2a72ecf8ul, 0x201a4c7bul, 0xab148a38ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Computes pks_hash = tagged_hash(pk[0], ..., pk[np-1]) */ @@ -97,17 +91,11 @@ static int secp256k1_musig_compute_pks_hash(const secp256k1_context *ctx, unsign /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */ static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - - sha->s[0] = 0x6ef02c5aul; - sha->s[1] = 0x06a480deul; - sha->s[2] = 0x1f298665ul; - sha->s[3] = 0x1d1134f2ul; - sha->s[4] = 0x56a0b063ul; - sha->s[5] = 0x52da4147ul; - sha->s[6] = 0xf280d9d4ul; - sha->s[7] = 0x4484be15ul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x6ef02c5aul, 0x06a480deul, 0x1f298665ul, 0x1d1134f2ul, + 0x56a0b063ul, 0x52da4147ul, 0xf280d9d4ul, 0x4484be15ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Compute KeyAgg coefficient which is constant 1 for the second pubkey and diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index d1c64c96..c3ef3c9f 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -309,31 +309,21 @@ static void secp256k1_nonce_function_musig_helper(secp256k1_sha256 *sha, unsigne /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("MuSig/aux")||SHA256("MuSig/aux"). */ static void secp256k1_nonce_function_musig_sha256_tagged_aux(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0xa19e884bul; - sha->s[1] = 0xf463fe7eul; - sha->s[2] = 0x2f18f9a2ul; - sha->s[3] = 0xbeb0f9fful; - sha->s[4] = 0x0f37e8b0ul; - sha->s[5] = 0x06ebd26ful; - sha->s[6] = 0xe3b243d2ul; - sha->s[7] = 0x522fb150ul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0xa19e884bul, 0xf463fe7eul, 0x2f18f9a2ul, 0xbeb0f9fful, + 0x0f37e8b0ul, 0x06ebd26ful, 0xe3b243d2ul, 0x522fb150ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("MuSig/nonce")||SHA256("MuSig/nonce"). */ static void secp256k1_nonce_function_musig_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x07101b64ul; - sha->s[1] = 0x18003414ul; - sha->s[2] = 0x0391bc43ul; - sha->s[3] = 0x0e6258eeul; - sha->s[4] = 0x29d26b72ul; - sha->s[5] = 0x8343937eul; - sha->s[6] = 0xb7a0a4fbul; - sha->s[7] = 0xff568a30ul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x07101b64ul, 0x18003414ul, 0x0391bc43ul, 0x0e6258eeul, + 0x29d26b72ul, 0x8343937eul, 0xb7a0a4fbul, 0xff568a30ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_secrand, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) { @@ -543,16 +533,11 @@ int secp256k1_musig_nonce_agg(const secp256k1_context* ctx, secp256k1_musig_aggn /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("MuSig/noncecoef")||SHA256("MuSig/noncecoef"). */ static void secp256k1_musig_compute_noncehash_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x2c7d5a45ul; - sha->s[1] = 0x06bf7e53ul; - sha->s[2] = 0x89be68a6ul; - sha->s[3] = 0x971254c0ul; - sha->s[4] = 0x60ac12d2ul; - sha->s[5] = 0x72846dcdul; - sha->s[6] = 0x6c81212ful; - sha->s[7] = 0xde7a2500ul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x2c7d5a45ul, 0x06bf7e53ul, 0x89be68a6ul, 0x971254c0ul, + 0x60ac12d2ul, 0x72846dcdul, 0x6c81212ful, 0xde7a2500ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* tagged_hash(aggnonce[0], aggnonce[1], agg_pk, msg) */ diff --git a/src/modules/schnorrsig/bench_impl.h b/src/modules/schnorrsig/bench_impl.h index 93a878ed..069464d0 100644 --- a/src/modules/schnorrsig/bench_impl.h +++ b/src/modules/schnorrsig/bench_impl.h @@ -51,18 +51,18 @@ static void run_schnorrsig_bench(int iters, int argc, char** argv) { int d = argc == 1; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *)); - data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); - data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); - data.sigs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); + data.keypairs = malloc(iters * sizeof(secp256k1_keypair *)); + data.pk = malloc(iters * sizeof(unsigned char *)); + data.msgs = malloc(iters * sizeof(unsigned char *)); + data.sigs = malloc(iters * sizeof(unsigned char *)); CHECK(MSGLEN >= 4); for (i = 0; i < iters; i++) { unsigned char sk[32]; - unsigned char *msg = (unsigned char *)malloc(MSGLEN); - unsigned char *sig = (unsigned char *)malloc(64); - secp256k1_keypair *keypair = (secp256k1_keypair *)malloc(sizeof(*keypair)); - unsigned char *pk_char = (unsigned char *)malloc(32); + unsigned char *msg = malloc(MSGLEN); + unsigned char *sig = malloc(64); + secp256k1_keypair *keypair = malloc(sizeof(*keypair)); + unsigned char *pk_char = malloc(32); secp256k1_xonly_pubkey pk; msg[0] = sk[0] = i; msg[1] = sk[1] = i >> 8; diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index b410b19e..21c1f412 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -14,33 +14,21 @@ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */ static void secp256k1_nonce_function_bip340_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x46615b35ul; - sha->s[1] = 0xf4bfbff7ul; - sha->s[2] = 0x9f8dc671ul; - sha->s[3] = 0x83627ab3ul; - sha->s[4] = 0x60217180ul; - sha->s[5] = 0x57358661ul; - sha->s[6] = 0x21a29e54ul; - sha->s[7] = 0x68b07b4cul; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x46615b35ul, 0xf4bfbff7ul, 0x9f8dc671ul, 0x83627ab3ul, + 0x60217180ul, 0x57358661ul, 0x21a29e54ul, 0x68b07b4cul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */ static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x24dd3219ul; - sha->s[1] = 0x4eba7e70ul; - sha->s[2] = 0xca0fabb9ul; - sha->s[3] = 0x0fa3166dul; - sha->s[4] = 0x3afbe4b1ul; - sha->s[5] = 0x4c44df97ul; - sha->s[6] = 0x4aac2739ul; - sha->s[7] = 0x249e850aul; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x24dd3219ul, 0x4eba7e70ul, 0xca0fabb9ul, 0x0fa3166dul, + 0x3afbe4b1ul, 0x4c44df97ul, 0x4aac2739ul, 0x249e850aul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* algo argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340 @@ -104,16 +92,11 @@ const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */ static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x9cecba11ul; - sha->s[1] = 0x23925381ul; - sha->s[2] = 0x11679112ul; - sha->s[3] = 0xd1627e0ful; - sha->s[4] = 0x97c87550ul; - sha->s[5] = 0x003cc765ul; - sha->s[6] = 0x90f61164ul; - sha->s[7] = 0x33e9b66aul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x9cecba11ul, 0x23925381ul, 0x11679112ul, 0xd1627e0ful, + 0x97c87550ul, 0x003cc765ul, 0x90f61164ul, 0x33e9b66aul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32) diff --git a/src/precompute_ecmult.c b/src/precompute_ecmult.c index 021fe394..8579c85f 100644 --- a/src/precompute_ecmult.c +++ b/src/precompute_ecmult.c @@ -20,7 +20,7 @@ #include "ecmult_compute_table_impl.h" static void print_table(FILE *fp, const char *name, int window_g, const secp256k1_ge_storage* table) { - int j; + size_t j; int i; fprintf(fp, "const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name); diff --git a/src/secp256k1.c b/src/secp256k1.c index 69bc9d94..f1388f3e 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -161,7 +161,7 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne secp256k1_context* secp256k1_context_create(unsigned int flags) { size_t const prealloc_size = secp256k1_context_preallocated_size(flags); - secp256k1_context* ctx = (secp256k1_context*)checked_malloc(&default_error_callback, prealloc_size); + secp256k1_context* ctx = checked_malloc(&default_error_callback, prealloc_size); if (EXPECT(secp256k1_context_preallocated_create(ctx, flags) == NULL, 0)) { free(ctx); return NULL; @@ -189,7 +189,7 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { ARG_CHECK(secp256k1_context_is_proper(ctx)); prealloc_size = secp256k1_context_preallocated_clone_size(ctx); - ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size); + ret = checked_malloc(&ctx->error_callback, prealloc_size); ret = secp256k1_context_preallocated_clone(ctx, ret); return ret; } diff --git a/src/testrand.h b/src/testrand.h index 9734a504..3e31d50f 100644 --- a/src/testrand.h +++ b/src/testrand.h @@ -45,7 +45,4 @@ static void testrand_flip(unsigned char *b, size_t len); /** Initialize the test RNG using (hex encoded) array up to 16 bytes, or randomly if hexseed is NULL. */ static void testrand_init(const char* hexseed); -/** Print final test information. */ -static void testrand_finish(void); - #endif /* SECP256K1_TESTRAND_H */ diff --git a/src/testrand_impl.h b/src/testrand_impl.h index 3670bd76..cccc12be 100644 --- a/src/testrand_impl.h +++ b/src/testrand_impl.h @@ -176,10 +176,4 @@ static void testrand_init(const char* hexseed) { testrand_seed(seed16); } -static void testrand_finish(void) { - unsigned char run32[32]; - testrand256(run32); - printf("random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", run32[0], run32[1], run32[2], run32[3], run32[4], run32[5], run32[6], run32[7], run32[8], run32[9], run32[10], run32[11], run32[12], run32[13], run32[14], run32[15]); -} - #endif /* SECP256K1_TESTRAND_IMPL_H */ diff --git a/src/tests.c b/src/tests.c index 6a8b3491..c187d173 100644 --- a/src/tests.c +++ b/src/tests.c @@ -785,6 +785,19 @@ static void run_tagged_sha256_tests(void) { CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0); } +static void run_sha256_initialize_midstate_tests(void) { + /* Midstate for the tagged hash with tag "sha256_midstate_test_tag". */ + static const unsigned char tag[] = "sha256_midstate_test_tag"; + static const uint32_t midstate[8] = { + 0xa9ec59eaul, 0x9b4c2ffful, 0x400821e2ul, 0x0dcf3847ul, + 0xbe7ea179ul, 0xa5772bdcul, 0x7d29bfe3ul, 0xa486b855ul + }; + secp256k1_sha256 sha; + + secp256k1_sha256_initialize_midstate(&sha, 64, midstate); + test_sha256_tag_midstate(&sha, tag, sizeof(tag) - 1); +} + /***** MODINV TESTS *****/ /* Compute the modular inverse of (odd) x mod 2^64. */ @@ -2247,8 +2260,58 @@ static void run_scalar_set_b32_seckey_tests(void) { CHECK(secp256k1_scalar_set_b32_seckey(&s2, b32) == 0); } +static void test_scalar_check_overflow(void) { + secp256k1_scalar s; + const secp256k1_scalar n_minus_1 = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364140UL + ); + const secp256k1_scalar n = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL + ); + const secp256k1_scalar n_plus_1 = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364142UL + ); + const secp256k1_scalar max = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL + ); + + int i; + + secp256k1_scalar_set_int(&s, 0); + CHECK(secp256k1_scalar_check_overflow(&s) == 0); + CHECK(secp256k1_scalar_check_overflow(&n_minus_1) == 0); + CHECK(secp256k1_scalar_check_overflow(&n) == 1); + CHECK(secp256k1_scalar_check_overflow(&n_plus_1) == 1); + CHECK(secp256k1_scalar_check_overflow(&max) == 1); + + for (i = 0; i < 2 * COUNT; i++) { + int expected_overflow; + int overflow = 0; + unsigned char b32[32]; + + testrand256(b32); + + /* Force top bits to be 0xFF sometimes to ensure we hit overflows */ + if (i % 2 == 0) { + memset(b32, 0xFF, 16); + } + + expected_overflow = (secp256k1_memcmp_var(b32, secp256k1_group_order_bytes, 32) >= 0); + + secp256k1_scalar_set_b32(&s, b32, &overflow); + CHECK(overflow == expected_overflow); + } +} + static void run_scalar_tests(void) { int i; + + test_scalar_check_overflow(); + for (i = 0; i < 128 * COUNT; i++) { scalar_test(); } @@ -2312,15 +2375,6 @@ static void run_scalar_tests(void) { } } - { - /* Does check_overflow check catch all ones? */ - static const secp256k1_scalar overflowed = SECP256K1_SCALAR_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL - ); - CHECK(secp256k1_scalar_check_overflow(&overflowed)); - } - { /* Static test vectors. * These were reduced from ~10^12 random vectors based on comparison-decision @@ -3732,8 +3786,8 @@ static void test_ge(void) { * negation, and then those two again but with randomized Z coordinate. * - The same is then done for lambda*p1 and lambda^2*p1. */ - secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs)); - secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs)); + secp256k1_ge *ge = checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs)); + secp256k1_gej *gej = checked_malloc(&CTX->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs)); secp256k1_fe zf, r; secp256k1_fe zfi2, zfi3; @@ -3867,7 +3921,7 @@ static void test_ge(void) { /* Test adding all points together in random order equals infinity. */ { secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; - secp256k1_gej *gej_shuffled = (secp256k1_gej *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_gej)); + secp256k1_gej *gej_shuffled = checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_gej)); for (i = 0; i < 4 * runs + 1; i++) { gej_shuffled[i] = gej[i]; } @@ -3888,8 +3942,8 @@ static void test_ge(void) { /* Test batch gej -> ge conversion without known z ratios. */ { - secp256k1_ge *ge_set_all_var = (secp256k1_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge *ge_set_all = (secp256k1_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_ge *ge_set_all_var = checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_ge *ge_set_all = checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); secp256k1_ge_set_all_gej_var(&ge_set_all_var[0], &gej[0], 4 * runs + 1); for (i = 0; i < 4 * runs + 1; i++) { secp256k1_fe s; @@ -5337,8 +5391,8 @@ static void test_ecmult_multi_batch_size_helper(void) { static void test_ecmult_multi_batching(void) { static const int n_points = 2*ECMULT_PIPPENGER_THRESHOLD; secp256k1_scalar scG; - secp256k1_scalar *sc = (secp256k1_scalar *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_scalar) * n_points); - secp256k1_ge *pt = (secp256k1_ge *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * n_points); + secp256k1_scalar *sc = checked_malloc(&CTX->error_callback, sizeof(secp256k1_scalar) * n_points); + secp256k1_ge *pt = checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * n_points); secp256k1_gej r; secp256k1_gej r2; ecmult_multi_data data; @@ -7903,6 +7957,7 @@ static const struct tf_test_entry tests_hash[] = { CASE(hmac_sha256_tests), CASE(rfc6979_hmac_sha256_tests), CASE(tagged_sha256_tests), + CASE(sha256_initialize_midstate_tests), }; static const struct tf_test_entry tests_scalar[] = { @@ -8067,4 +8122,3 @@ int main(int argc, char **argv) { if (tf_init(&tf, argc, argv) != 0) return EXIT_FAILURE; return tf_run(&tf); } - diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 13bda611..68d4bec3 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -459,8 +459,6 @@ int main(int argc, char** argv) { secp256k1_context_destroy(ctx); } - testrand_finish(); - printf("no problems found\n"); return EXIT_SUCCESS; }