Files
secp256k1-zkp/ci/ci.sh
Kgothatso Ngako 3b68633f59 chilldkg: CI wiring, ctime_tests coverage, declassify fixes
CI:
- ci/ci.sh: new CHILLDKG environment variable, passed to configure as
  --enable-module-chilldkg (mirroring FROST).
- .github/workflows/ci.yml: default CHILLDKG: 'no' and CHILLDKG: 'yes'
  in every job that enables FROST, except the x86_64 matrix entry that
  deliberately builds without the ecdh module (chilldkg requires
  schnorrsig + ecdh; the configure-time dependency error would fire
  there). YAML validity and per-job dependency presence checked
  programmatically.

ctime_tests:
- src/ctime_tests.c: run a full ChillDKG session (n = 2, t = 2) through
  the public API under the memory checker: hostpubkey_gen, params_hash,
  participant_step1, coordinator_step1, participant_step2,
  coordinator_finalize, participant_finalize, participant_recover and
  recovery_ack_sign. Host secret keys, session randomness, aux
  randomness and the resulting secret shares are undefined (secret);
  all protocol messages, the certificate, threshold public key, public
  shares, recovery data, ack signature and the secret-free state1
  objects are defined (public). state2 stays secret (contains the
  secret share).

Constant-time fixes found by running the new block under
MemorySanitizer (valgrind unavailable locally; MSan build via clang +
CMake). All are missing declassifications of secret-derived but public
(or public-outcome) values, following the frost module's
secp256k1_declassify pattern with justification comments; no real
constant-time bugs were found:
- hostpubkey_gen: declassify the computed host public key before
  serialization (public output).
- participant_step1: declassify the zero-randomness check result (only
  reveals "the RNG returned 32 zero bytes", which aborts the session).
- encpedpop participant_step1: declassify the pubnonce point before
  serialization (public, part of pmsg1).
- chilldkg_schnorrsig_sign: declassify the signer public key before
  normalization/parity branch, and declassify the return value (a
  failure only reveals a zero derived nonce, negligible probability).
- vss_commit: declassify the VSS commitments before serialization
  (public, part of pmsg1).
- vss_verify_secshare: declassify secshare*G before the infinity/eq
  checks (equals the public pubshare in honest runs; the discrete log
  is not revealed).
- simplpedpop_participant_investigate (proactive audit; not reached by
  ctime_tests): declassify the secshare-sum comparison result (the
  public fault code reveals it anyway).

Verified: MSan ctime_tests exits 0; autotools make check 10/10 (the
local tree is configured without --enable-ctime-tests because neither
valgrind nor an MSan-instrumented gcc build is available; CI runs
ctime_tests under valgrind as before); CMake ctest 428/428;
./tests --target=chilldkg and ./chilldkg_example pass.
2026-08-31 10:25:14 +02:00

159 lines
4.6 KiB
Bash
Executable File

#!/bin/sh
set -eux
export LC_ALL=C
# Print commit and relevant CI environment to allow reproducing the job outside of CI.
git show --no-patch
print_environment() {
# Turn off -x because it messes up the output
set +x
# There are many ways to print variable names and their content. This one
# does not rely on bash.
for var in WERROR_CFLAGS MAKEFLAGS BUILD \
ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \
EXPERIMENTAL ECDH RECOVERY EXTRAKEYS SCHNORRSIG MUSIG SCHNORRSIG_HALFAGG ELLSWIFT \
ECDSA_S2C GENERATOR RANGEPROOF SURJECTIONPROOF WHITELIST ECDSAADAPTOR BPPP \
FROST CHILLDKG SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS SYMBOL_CHECK \
EXAMPLES \
HOST WRAPPER_CMD \
CC CFLAGS CPPFLAGS AR NM \
UBSAN_OPTIONS ASAN_OPTIONS LSAN_OPTIONS
do
eval "isset=\${$var+x}"
if [ -n "$isset" ]; then
eval "val=\${$var}"
# shellcheck disable=SC2154
printf '%s="%s" ' "$var" "$val"
fi
done
echo "$0"
set -x
}
print_environment
env >> test_env.log
# If gcc is requested, assert that it's in fact gcc (and not some symlinked Apple clang).
case "${CC:-undefined}" in
*gcc*)
$CC -v 2>&1 | grep -q "gcc version" || exit 1;
;;
esac
if [ -n "${CC+x}" ]; then
# The MSVC compiler "cl" doesn't understand "-v"
$CC -v || true
fi
if [ "$WITH_VALGRIND" = "yes" ]; then
valgrind --version
fi
if [ -n "$WRAPPER_CMD" ]; then
$WRAPPER_CMD --version
fi
./autogen.sh
./configure \
--enable-experimental="$EXPERIMENTAL" \
--with-test-override-wide-multiply="$WIDEMUL" --with-asm="$ASM" \
--with-ecmult-window="$ECMULTWINDOW" \
--with-ecmult-gen-kb="$ECMULTGENKB" \
--enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \
--enable-module-ellswift="$ELLSWIFT" \
--enable-module-extrakeys="$EXTRAKEYS" \
--enable-module-ecdsa-s2c="$ECDSA_S2C" \
--enable-module-bppp="$BPPP" \
--enable-module-rangeproof="$RANGEPROOF" --enable-module-surjectionproof="$SURJECTIONPROOF" --enable-module-whitelist="$WHITELIST" --enable-module-generator="$GENERATOR" \
--enable-module-schnorrsig="$SCHNORRSIG" --enable-module-ecdsa-adaptor="$ECDSAADAPTOR" \
--enable-module-musig="$MUSIG" \
--enable-module-schnorrsig-halfagg="$SCHNORRSIG_HALFAGG" \
--enable-module-frost="$FROST" \
--enable-module-chilldkg="$CHILLDKG" \
--enable-examples="$EXAMPLES" \
--enable-ctime-tests="$CTIMETESTS" \
--with-valgrind="$WITH_VALGRIND" \
--host="$HOST" $EXTRAFLAGS
# We have set "-j<n>" in MAKEFLAGS.
build_exit_code=0
make > make.log 2>&1 || build_exit_code=$?
cat make.log
if [ $build_exit_code -ne 0 ]; then
case "${CC:-undefined}" in
*snapshot*)
# Ignore internal compiler errors in gcc-snapshot and clang-snapshot
grep -e "internal compiler error:" -e "PLEASE submit a bug report" make.log
exit $?
;;
*)
exit 1
;;
esac
fi
# Print information about binaries so that we can see that the architecture is correct
file *tests* || true
file bench* || true
file .libs/* || true
if [ "$SYMBOL_CHECK" = "yes" ]
then
python3 --version
case "$HOST" in
*mingw*)
ls -l .libs
python3 ./tools/symbol-check.py .libs/libsecp256k1-*.dll
;;
*)
python3 ./tools/symbol-check.py .libs/libsecp256k1.so
;;
esac
fi
# This tells `make check` to wrap test invocations.
export LOG_COMPILER="$WRAPPER_CMD"
make "$BUILD"
# Using the local `libtool` because on macOS the system's libtool has nothing to do with GNU libtool
EXEC='./libtool --mode=execute'
if [ -n "$WRAPPER_CMD" ]
then
EXEC="$EXEC $WRAPPER_CMD"
fi
if [ "$BENCH" = "yes" ]
then
{
$EXEC ./bench_ecmult
$EXEC ./bench_internal
$EXEC ./bench
if [ "$BPPP" = "yes" ]
then
$EXEC ./bench_bppp
fi
} >> bench.log 2>&1
fi
if [ "$CTIMETESTS" = "yes" ]
then
if [ "$WITH_VALGRIND" = "yes" ]; then
./libtool --mode=execute valgrind --error-exitcode=42 ./ctime_tests > ctime_tests.log 2>&1
else
$EXEC ./ctime_tests > ctime_tests.log 2>&1
fi
fi
# Rebuild precomputed files (if not cross-compiling).
if [ -z "$HOST" ]
then
make clean-precomp clean-testvectors
make precomp testvectors
fi
# Check that no repo files have been modified by the build.
# (This fails for example if the precomp files need to be updated in the repo.)
git diff --exit-code