diff --git a/projects/bitcoin-core/Dockerfile b/projects/bitcoin-core/Dockerfile index 734470e3cf96..8556c8924530 100644 --- a/projects/bitcoin-core/Dockerfile +++ b/projects/bitcoin-core/Dockerfile @@ -27,5 +27,12 @@ RUN apt-get update && apt-get install -y \ RUN git clone --depth=1 https://github.com/bitcoin/bitcoin.git bitcoin-core RUN git clone --depth=1 https://github.com/bitcoin-core/qa-assets bitcoin-core/assets +RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz +RUN git clone --depth 1 https://github.com/bitcoin-core/secp256k1.git +RUN git clone --depth 1 https://github.com/randombit/botan.git +RUN git clone --depth 1 https://github.com/trezor/trezor-firmware.git +RUN git clone --depth 1 https://github.com/google/wycheproof.git +RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2 WORKDIR bitcoin-core COPY build.sh $SRC/ +COPY build_cryptofuzz.sh $SRC/ diff --git a/projects/bitcoin-core/build.sh b/projects/bitcoin-core/build.sh index db9654792884..f2a2cb0d64ae 100755 --- a/projects/bitcoin-core/build.sh +++ b/projects/bitcoin-core/build.sh @@ -15,6 +15,10 @@ # ################################################################################ +bash $SRC/build_cryptofuzz.sh + +cd $SRC/bitcoin-core/ + # Build dependencies # This will also force static builds if [ "$ARCHITECTURE" = "i386" ]; then @@ -67,4 +71,4 @@ for fuzz_target in ${FUZZ_TARGETS[@]}; do cd assets/fuzz_seed_corpus zip --recurse-paths --quiet --junk-paths "$OUT/${fuzz_target}_seed_corpus.zip" "${fuzz_target}" ) -done +done \ No newline at end of file diff --git a/projects/bitcoin-core/build_cryptofuzz.sh b/projects/bitcoin-core/build_cryptofuzz.sh new file mode 100644 index 000000000000..c69d419d9913 --- /dev/null +++ b/projects/bitcoin-core/build_cryptofuzz.sh @@ -0,0 +1,128 @@ +#!/bin/bash -eu +# Copyright 2021 Google LLC +# +# 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. +# +################################################################################ + +export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL" +export LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" + +# Install Boost headers +cd $SRC/ +tar jxf boost_1_74_0.tar.bz2 +cd boost_1_74_0/ +CFLAGS="" CXXFLAGS="" ./bootstrap.sh +CFLAGS="" CXXFLAGS="" ./b2 headers +export CXXFLAGS="$CXXFLAGS -I $SRC/boost_1_74_0/" + +# Prevent Boost compilation error with -std=c++17 +export CXXFLAGS="$CXXFLAGS -D_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR" + +# Preconfigure libsecp256k1 +cd $SRC/secp256k1/ +autoreconf -ivf +export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SECP256K1" + +function build_libsecp256k1() { + # Build libsecp256k1 + cd $SRC/secp256k1/ + + if test -f "Makefile"; then + # Remove old configuration if it exists + make clean + fi + + if [[ $CFLAGS = *sanitize=memory* ]] + then + ./configure --enable-static --disable-tests --disable-benchmark --disable-exhaustive-tests --enable-module-recovery --enable-experimental --with-asm=no "$@" + else + ./configure --enable-static --disable-tests --disable-benchmark --disable-exhaustive-tests --enable-module-recovery --enable-experimental "$@" + fi + make + + export SECP256K1_INCLUDE_PATH=$(realpath include) + export LIBSECP256K1_A_PATH=$(realpath .libs/libsecp256k1.a) + + # Build libsecp256k1 Cryptofuzz module + cd $SRC/cryptofuzz/modules/secp256k1/ + make -B -j$(nproc) +} + +# Build Trezor firmware +cd $SRC/trezor-firmware/crypto/ +# Rename blake2b_* functions to avoid symbol collisions with other libraries +sed -i "s/\>extra_options.h +echo -n '--operations=Digest,HMAC,KDF_HKDF,SymmetricEncrypt,SymmetricDecrypt,ECC_PrivateToPublic,ECC_ValidatePubkey,ECDSA_Sign,ECDSA_Verify,ECDSA_Recover,BignumCalc_Mod_2Exp256 ' >>extra_options.h +echo -n '--curves=secp256k1 ' >>extra_options.h +echo -n '--digests=NULL,SHA1,SHA256,SHA512,RIPEMD160,SHA3-256,SIPHASH64 ' >>extra_options.h +echo -n '--ciphers=CHACHA20,AES_256_CBC ' >>extra_options.h +echo -n '--calcops=Add,And,Div,IsEq,IsGt,IsGte,IsLt,IsLte,IsOdd,Mul,NumBits,Or,Set,Sub,Xor ' >>extra_options.h +echo -n '"' >>extra_options.h +cd modules/bitcoin/ +make -B -j$(nproc) +cd ../trezor/ +make -B -j$(nproc) +cd ../botan/ +make -B -j$(nproc) +cd ../../ + +# Build with 3 configurations of libsecp256k1 +# Discussion: https://github.com/google/oss-fuzz/pull/5717#issuecomment-842765383 + +build_libsecp256k1 "--with-ecmult-window=2" "--with-ecmult-gen-precision=2" +cd $SRC/cryptofuzz/ +make -B -j$(nproc) +cp cryptofuzz $OUT/cryptofuzz-bitcoin-cryptography-w2-p2 + +build_libsecp256k1 "--with-ecmult-window=15" "--with-ecmult-gen-precision=4" +cd $SRC/cryptofuzz/ +rm cryptofuzz +make +cp cryptofuzz $OUT/cryptofuzz-bitcoin-cryptography-w15-p4 + +build_libsecp256k1 "--with-ecmult-window=24" "--with-ecmult-gen-precision=8" +cd $SRC/cryptofuzz/ +rm cryptofuzz +make +cp cryptofuzz $OUT/cryptofuzz-bitcoin-cryptography-w24-p8 + +# Convert Wycheproof test vectors to Cryptofuzz corpus format +mkdir $SRC/corpus-cryptofuzz-wycheproof/ +find $SRC/wycheproof/testvectors/ -type f -name 'ecdsa_secp256k1_*' -exec $SRC/cryptofuzz/cryptofuzz --from-wycheproof={},$SRC/corpus-cryptofuzz-wycheproof/ \; +# Pack it and use it as seed corpus +zip -j $OUT/cryptofuzz-bitcoin-cryptography_seed_corpus.zip $SRC/corpus-cryptofuzz-wycheproof/*