Skip to content

Commit

Permalink
Merge pull request #5575 from kwvg/secp256k1
Browse files Browse the repository at this point in the history
  • Loading branch information
PastaPastaPasta authored Nov 21, 2023
2 parents 9861bc7 + 00b3dd6 commit 39ce20c
Show file tree
Hide file tree
Showing 181 changed files with 47,049 additions and 5,387 deletions.
4 changes: 2 additions & 2 deletions ci/dash/build_src.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ rm -rf build-ci
mkdir build-ci
cd build-ci

../configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
../configure $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
make distdir VERSION=$BUILD_TARGET

cd dashcore-$BUILD_TARGET
./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
./configure $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)

make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false )

Expand Down
10 changes: 1 addition & 9 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1863,15 +1863,7 @@ LIBS_TEMP="$LIBS"
unset LIBS
LIBS="$LIBS_TEMP"

PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH"
unset PKG_CONFIG_PATH
PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP"

PKGCONFIG_LIBDIR_TEMP="$PKG_CONFIG_LIBDIR"
unset PKG_CONFIG_LIBDIR
PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP"

ac_configure_args="${ac_configure_args} --disable-shared --with-pic --enable-benchmark=no --enable-module-recovery --disable-openssl-tests"
ac_configure_args="${ac_configure_args} --disable-shared --with-pic --enable-benchmark=no --enable-module-recovery --disable-module-ecdh"
AC_CONFIG_SUBDIRS([src/dashbls src/secp256k1])

AC_OUTPUT
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.bench.include
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ bench_bench_dash_SOURCES = \
bench/bench_bitcoin.cpp \
bench/bench.cpp \
bench/bench.h \
bench/bip324_ecdh.cpp \
bench/block_assemble.cpp \
bench/bls.cpp \
bench/bls_dkg.cpp \
Expand All @@ -26,6 +27,7 @@ bench_bench_dash_SOURCES = \
bench/data.cpp \
bench/duplicate_inputs.cpp \
bench/ecdsa.cpp \
bench/ellswift.cpp \
bench/examples.cpp \
bench/rollingbloom.cpp \
bench/chacha20.cpp \
Expand Down
51 changes: 51 additions & 0 deletions src/bench/bip324_ecdh.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bench/bench.h>

#include <key.h>
#include <pubkey.h>
#include <random.h>
#include <span.h>

#include <array>
#include <cstddef>

static void BIP324_ECDH(benchmark::Bench& bench)
{
ECC_Start();
FastRandomContext rng;

std::array<std::byte, 32> key_data;
std::array<std::byte, EllSwiftPubKey::size()> our_ellswift_data;
std::array<std::byte, EllSwiftPubKey::size()> their_ellswift_data;

rng.fillrand(key_data);
rng.fillrand(our_ellswift_data);
rng.fillrand(their_ellswift_data);

bench.batch(1).unit("ecdh").run([&] {
CKey key;
key.Set(UCharCast(key_data.data()), UCharCast(key_data.data()) + 32, true);
EllSwiftPubKey our_ellswift(our_ellswift_data);
EllSwiftPubKey their_ellswift(their_ellswift_data);

auto ret = key.ComputeBIP324ECDHSecret(their_ellswift, our_ellswift, true);

// To make sure that the computation is not the same on every iteration (ellswift decoding
// is variable-time), distribute bytes from the shared secret over the 3 inputs. The most
// important one is their_ellswift, because that one is actually decoded, so it's given most
// bytes. The data is copied into the middle, so that both halves are affected:
// - Copy 8 bytes from the resulting shared secret into middle of the private key.
std::copy(ret.begin(), ret.begin() + 8, key_data.begin() + 12);
// - Copy 8 bytes from the resulting shared secret into the middle of our ellswift key.
std::copy(ret.begin() + 8, ret.begin() + 16, our_ellswift_data.begin() + 28);
// - Copy 16 bytes from the resulting shared secret into the middle of their ellswift key.
std::copy(ret.begin() + 16, ret.end(), their_ellswift_data.begin() + 24);
});

ECC_Stop();
}

BENCHMARK(BIP324_ECDH);
1 change: 0 additions & 1 deletion src/bench/ccoins_caching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
static void CCoinsCaching(benchmark::Bench& bench)
{
const ECCVerifyHandle verify_handle;
ECC_Start();

FillableSigningProvider keystore;
Expand Down
1 change: 0 additions & 1 deletion src/bench/checkqueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ static const unsigned int QUEUE_BATCH_SIZE = 128;
// and there is a little bit of work done between calls to Add.
static void CCheckQueueSpeedPrevectorJob(benchmark::Bench& bench)
{
const ECCVerifyHandle verify_handle;
ECC_Start();

struct PrevectorJob {
Expand Down
31 changes: 31 additions & 0 deletions src/bench/ellswift.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2022-2023 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bench/bench.h>

#include <key.h>
#include <random.h>

static void EllSwiftCreate(benchmark::Bench& bench)
{
ECC_Start();

CKey key;
key.MakeNewKey(true);

uint256 entropy = GetRandHash();

bench.batch(1).unit("pubkey").run([&] {
auto ret = key.EllSwiftCreate(AsBytes(Span{entropy}));
/* Use the first 32 bytes of the ellswift encoded public key as next private key. */
key.Set(UCharCast(ret.data()), UCharCast(ret.data()) + 32, true);
assert(key.IsValid());
/* Use the last 32 bytes of the ellswift encoded public key as next entropy. */
std::copy(ret.begin() + 32, ret.begin() + 64, BytePtr(entropy.data()));
});

ECC_Stop();
}

BENCHMARK(EllSwiftCreate);
12 changes: 2 additions & 10 deletions src/bitcoin-cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <chainparamsbase.h>
#include <clientversion.h>
#include <compat.h>
#include <rpc/client.h>
#include <rpc/mining.h>
#include <rpc/protocol.h>
Expand Down Expand Up @@ -914,16 +915,7 @@ static int CommandLineRPC(int argc, char *argv[])
return nRet;
}

#ifdef WIN32
// Export main() and ensure working ASLR on Windows.
// Exporting a symbol will prevent the linker from stripping
// the .reloc section from the binary, which is a requirement
// for ASLR. This is a temporary workaround until a fixed
// version of binutils is used for releases.
__declspec(dllexport) int main(int argc, char* argv[])
#else
int main(int argc, char* argv[])
#endif
MAIN_FUNCTION
{
RegisterPrettyTerminateHander();
RegisterPrettySignalHandlers();
Expand Down
5 changes: 2 additions & 3 deletions src/bitcoin-tx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <chainparams.h>
#include <clientversion.h>
#include <coins.h>
#include <compat.h>
#include <consensus/consensus.h>
#include <core_io.h>
#include <key_io.h>
Expand Down Expand Up @@ -616,8 +617,6 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)

class Secp256k1Init
{
ECCVerifyHandle globalVerifyHandle;

public:
Secp256k1Init() {
ECC_Start();
Expand Down Expand Up @@ -786,7 +785,7 @@ static int CommandLineRawTx(int argc, char* argv[])
return nRet;
}

int main(int argc, char* argv[])
MAIN_FUNCTION
{
RegisterPrettyTerminateHander();
RegisterPrettySignalHandlers();
Expand Down
4 changes: 2 additions & 2 deletions src/bitcoin-wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <chainparams.h>
#include <chainparamsbase.h>
#include <compat.h>
#include <logging.h>
#include <util/strencodings.h>
#include <util/system.h>
Expand Down Expand Up @@ -73,7 +74,7 @@ static bool WalletAppInit(int argc, char* argv[])
return true;
}

int main(int argc, char* argv[])
MAIN_FUNCTION
{
#ifdef WIN32
util::WinCmdLineArgs winArgs;
Expand Down Expand Up @@ -112,7 +113,6 @@ int main(int argc, char* argv[])

std::string name = gArgs.GetArg("-wallet", "");

ECCVerifyHandle globalVerifyHandle;
ECC_Start();
if (!WalletTool::ExecuteWalletToolFunc(method, name))
return EXIT_FAILURE;
Expand Down
2 changes: 1 addition & 1 deletion src/bitcoind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ static bool AppInit(int argc, char* argv[])
return fRet;
}

int main(int argc, char* argv[])
MAIN_FUNCTION
{
RegisterPrettyTerminateHander();
RegisterPrettySignalHandlers();
Expand Down
11 changes: 11 additions & 0 deletions src/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@ typedef void* sockopt_arg_type;
typedef char* sockopt_arg_type;
#endif

#ifdef WIN32
// Export main() and ensure working ASLR when using mingw-w64.
// Exporting a symbol will prevent the linker from stripping
// the .reloc section from the binary, which is a requirement
// for ASLR. While release builds are not affected, anyone
// building with a binutils < 2.36 is subject to this ld bug.
#define MAIN_FUNCTION __declspec(dllexport) int main(int argc, char* argv[])
#else
#define MAIN_FUNCTION int main(int argc, char* argv[])
#endif

// Note these both should work with the current usage of poll, but best to be safe
// WIN32 poll is broken https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/
// __APPLE__ poll is broke https://github.com/bitcoin/bitcoin/pull/14336#issuecomment-437384408
Expand Down
4 changes: 0 additions & 4 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,6 @@ static fs::path GetPidFile(const ArgsManager& args)
// shutdown thing.
//

static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;

void Interrupt(NodeContext& node)
{
InterruptHTTPServer();
Expand Down Expand Up @@ -399,7 +397,6 @@ void Shutdown(NodeContext& node)
PrepareShutdown(node);
}
// Shutdown part 2: delete wallet instance
globalVerifyHandle.reset();
ECC_Stop();
node.mempool.reset();
node.fee_estimator.reset();
Expand Down Expand Up @@ -1467,7 +1464,6 @@ bool AppInitSanityChecks()
LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo);
RandomInit();
ECC_Start();
globalVerifyHandle.reset(new ECCVerifyHandle());

// Sanity check
if (!InitSanityCheck())
Expand Down
59 changes: 55 additions & 4 deletions src/key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <random.h>

#include <secp256k1.h>
#include <secp256k1_ellswift.h>
#include <secp256k1_recovery.h>

static secp256k1_context* secp256k1_context_sign = nullptr;
Expand Down Expand Up @@ -226,6 +227,12 @@ bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, bool gr
assert(ret);
secp256k1_ecdsa_signature_serialize_der(secp256k1_context_sign, vchSig.data(), &nSigLen, &sig);
vchSig.resize(nSigLen);
// Additional verification step to prevent using a potentially corrupted signature
secp256k1_pubkey pk;
ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &pk, begin());
assert(ret);
ret = secp256k1_ecdsa_verify(secp256k1_context_static, &sig, hash.begin(), &pk);
assert(ret);
return true;
}

Expand All @@ -248,13 +255,21 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
return false;
vchSig.resize(CPubKey::COMPACT_SIGNATURE_SIZE);
int rec = -1;
secp256k1_ecdsa_recoverable_signature sig;
int ret = secp256k1_ecdsa_sign_recoverable(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, nullptr);
secp256k1_ecdsa_recoverable_signature rsig;
int ret = secp256k1_ecdsa_sign_recoverable(secp256k1_context_sign, &rsig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, nullptr);
assert(ret);
ret = secp256k1_ecdsa_recoverable_signature_serialize_compact(secp256k1_context_sign, &vchSig[1], &rec, &sig);
ret = secp256k1_ecdsa_recoverable_signature_serialize_compact(secp256k1_context_sign, &vchSig[1], &rec, &rsig);
assert(ret);
assert(rec != -1);
vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
// Additional verification step to prevent using a potentially corrupted signature
secp256k1_pubkey epk, rpk;
ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &epk, begin());
assert(ret);
ret = secp256k1_ecdsa_recover(secp256k1_context_static, &rpk, &rsig, hash.begin());
assert(ret);
ret = secp256k1_ec_pubkey_cmp(secp256k1_context_static, &epk, &rpk);
assert(ret == 0);
return true;
}

Expand Down Expand Up @@ -290,6 +305,42 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const
return ret;
}

EllSwiftPubKey CKey::EllSwiftCreate(Span<const std::byte> ent32) const
{
assert(fValid);
assert(ent32.size() == 32);
std::array<std::byte, EllSwiftPubKey::size()> encoded_pubkey;

auto success = secp256k1_ellswift_create(secp256k1_context_sign,
UCharCast(encoded_pubkey.data()),
keydata.data(),
UCharCast(ent32.data()));

// Should always succeed for valid keys (asserted above).
assert(success);
return {encoded_pubkey};
}

ECDHSecret CKey::ComputeBIP324ECDHSecret(const EllSwiftPubKey& their_ellswift, const EllSwiftPubKey& our_ellswift, bool initiating) const
{
assert(fValid);

ECDHSecret output;
// BIP324 uses the initiator as party A, and the responder as party B. Remap the inputs
// accordingly:
bool success = secp256k1_ellswift_xdh(secp256k1_context_sign,
UCharCast(output.data()),
UCharCast(initiating ? our_ellswift.data() : their_ellswift.data()),
UCharCast(initiating ? their_ellswift.data() : our_ellswift.data()),
keydata.data(),
initiating ? 0 : 1,
secp256k1_ellswift_xdh_hash_function_bip324,
nullptr);
// Should always succeed for valid keys (assert above).
assert(success);
return output;
}

bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const {
out.nDepth = nDepth + 1;
CKeyID id = key.GetPubKey().GetID();
Expand Down Expand Up @@ -348,7 +399,7 @@ bool ECC_InitSanityCheck() {
void ECC_Start() {
assert(secp256k1_context_sign == nullptr);

secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
assert(ctx != nullptr);

{
Expand Down
Loading

0 comments on commit 39ce20c

Please sign in to comment.