Some theory -- Constant-time code verification...:
In many cases, checking if the implementation is constant-time is not trivial and tools are needed.
Using Valgrind for constant-time tests.
The key details about fixes -- https://en.cppreference.com/w/c/language/volatile:
... within a single thread of execution, a volatile access cannot be optimized out...
System: Ubuntu 23.04 Default compilers:
- gcc version 12.2.0
- clang version 15.0.7
A fix -- PR1257.
$ sudo apt install clang-13
$ git checkout v0.3.0
$ cmake -B ../v0.3.0-clang-13 -DCMAKE_C_COMPILER=clang-13 \
-DSECP256K1_BUILD_CTIME_TESTS=ON \
-DSECP256K1_VALGRIND=ON \
-DCMAKE_BUILD_TYPE=None \
-DCMAKE_C_FLAGS="-O1"
$ cmake --build ../v0.3.0-clang-13
$ valgrind ../v0.3.0-clang-13/src/ctime_tests
==94124== Memcheck, a memory error detector
==94124== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==94124== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==94124== Command: ../v0.3.0-clang-13/src/ctime_tests
==94124==
==94124==
==94124== HEAP SUMMARY:
==94124== in use at exit: 0 bytes in 0 blocks
==94124== total heap usage: 1 allocs, 1 frees, 208 bytes allocated
==94124==
==94124== All heap blocks were freed -- no leaks are possible
==94124==
==94124== For lists of detected and suppressed errors, rerun with: -s
==94124== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0
$ cmake -B ../v0.3.0-clang-15 -DCMAKE_C_COMPILER=clang-15 \
-DSECP256K1_BUILD_CTIME_TESTS=ON \
-DSECP256K1_VALGRIND=ON \
-DCMAKE_BUILD_TYPE=None \
-DCMAKE_C_FLAGS="-O1"
$ cmake --build ../v0.3.0-clang-15
$ valgrind ../v0.3.0-clang-15/src/ctime_tests
==101364== Memcheck, a memory error detector
==101364== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==101364== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==101364== Command: ../v0.3.0-clang-15/src/ctime_tests
==101364==
==101364== Conditional jump or move depends on uninitialised value(s)
==101364== at 0x48726E4: secp256k1_ecmult_gen (in /home/hebasto/git/secp256k1/v0.3.0-clang-15/src/libsecp256k1.so.2.0.0)
==101364== by 0x485AF39: secp256k1_ec_pubkey_create (in /home/hebasto/git/secp256k1/v0.3.0-clang-15/src/libsecp256k1.so.2.0.0)
==101364== by 0x1093AD: main (in /home/hebasto/git/secp256k1/v0.3.0-clang-15/src/ctime_tests)
==101364==
...
==101364==
==101364== HEAP SUMMARY:
==101364== in use at exit: 0 bytes in 0 blocks
==101364== total heap usage: 1 allocs, 1 frees, 208 bytes allocated
==101364==
==101364== All heap blocks were freed -- no leaks are possible
==101364==
==101364== Use --track-origins=yes to see where uninitialised values come from
==101364== For lists of detected and suppressed errors, rerun with: -s
==101364== ERROR SUMMARY: 6606 errors from 10 contexts (suppressed: 0 from 0)
$ git checkout v0.3.1
$ cmake -B ../v0.3.1-clang-15 -DCMAKE_C_COMPILER=clang-15 \
-DSECP256K1_BUILD_CTIME_TESTS=ON \
-DSECP256K1_VALGRIND=ON \
-DCMAKE_BUILD_TYPE=None \
-DCMAKE_C_FLAGS="-O1"
$ cmake --build ../v0.3.1-clang-15
$ valgrind ../v0.3.1-clang-15/src/ctime_tests
==106010== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==106010== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==106010== Command: ../v0.3.1-clang-15/src/ctime_tests
==106010==
==106010==
==106010== HEAP SUMMARY:
==106010== in use at exit: 0 bytes in 0 blocks
==106010== total heap usage: 1 allocs, 1 frees, 208 bytes allocated
==106010==
==106010== All heap blocks were freed -- no leaks are possible
==106010==
==106010== For lists of detected and suppressed errors, rerun with: -s
==106010== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
A fix -- PR1303.
$ sudo apt install gcc-13
$ cmake -B ../v0.3.1-gcc-12 -DCMAKE_C_COMPILER=gcc-12 \
-DSECP256K1_BUILD_CTIME_TESTS=ON \
-DSECP256K1_VALGRIND=ON \
-DCMAKE_BUILD_TYPE=None \
-DCMAKE_C_FLAGS="-O1"
$ cmake --build ../v0.3.1-gcc-12
$ valgrind ../v0.3.1-gcc-12/src/ctime_tests
==132191== Memcheck, a memory error detector
==132191== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==132191== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==132191== Command: ../v0.3.1-gcc-12/src/ctime_tests
==132191==
==132191==
==132191== HEAP SUMMARY:
==132191== in use at exit: 0 bytes in 0 blocks
==132191== total heap usage: 1 allocs, 1 frees, 208 bytes allocated
==132191==
==132191== All heap blocks were freed -- no leaks are possible
==132191==
==132191== For lists of detected and suppressed errors, rerun with: -s
==132191== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$ cmake -B ../v0.3.1-gcc-13 -DCMAKE_C_COMPILER=gcc-13 \
-DSECP256K1_BUILD_CTIME_TESTS=ON \
-DSECP256K1_VALGRIND=ON \
-DCMAKE_BUILD_TYPE=None \
-DCMAKE_C_FLAGS="-O1"
$ cmake --build ../v0.3.1-gcc-13
$ valgrind ../v0.3.1-gcc-13/src/ctime_tests
==134495== Memcheck, a memory error detector
==134495== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==134495== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==134495== Command: ../v0.3.1-gcc-13/src/ctime_tests
==134495==
==134495== Conditional jump or move depends on uninitialised value(s)
==134495== at 0x48596E1: secp256k1_scalar_cond_negate (in /home/hebasto/git/secp256k1/v0.3.1-gcc-13/src/libsecp256k1.so.2.0.1)
==134495== by 0x4863F93: secp256k1_ecdsa_sign (in /home/hebasto/git/secp256k1/v0.3.1-gcc-13/src/libsecp256k1.so.2.0.1)
==134495== by 0x1096D0: main (in /home/hebasto/git/secp256k1/v0.3.1-gcc-13/src/ctime_tests)
==134495==
...
==134495==
==134495== HEAP SUMMARY:
==134495== in use at exit: 0 bytes in 0 blocks
==134495== total heap usage: 1 allocs, 1 frees, 208 bytes allocated
==134495==
==134495== All heap blocks were freed -- no leaks are possible
==134495==
==134495== Use --track-origins=yes to see where uninitialised values come from
==134495== For lists of detected and suppressed errors, rerun with: -s
==134495== ERROR SUMMARY: 9 errors from 9 contexts (suppressed: 0 from 0)
$ git checkout v0.3.2
$ cmake -B ../v0.3.2-gcc-13 -DCMAKE_C_COMPILER=gcc-13 \
-DSECP256K1_BUILD_CTIME_TESTS=ON \
-DSECP256K1_VALGRIND=ON \
-DCMAKE_BUILD_TYPE=None \
-DCMAKE_C_FLAGS="-O1"
$ cmake --build ../v0.3.2-gcc-13
$ valgrind ../v0.3.2-gcc-13/src/ctime_tests
==137308== Memcheck, a memory error detector
==137308== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==137308== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==137308== Command: ../v0.3.2-gcc-13/src/ctime_tests
==137308==
==137308==
==137308== HEAP SUMMARY:
==137308== in use at exit: 0 bytes in 0 blocks
==137308== total heap usage: 1 allocs, 1 frees, 208 bytes allocated
==137308==
==137308== All heap blocks were freed -- no leaks are possible
==137308==
==137308== For lists of detected and suppressed errors, rerun with: -s
==137308== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)