aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/devtools/README.md13
-rwxr-xr-xcontrib/devtools/git-subtree-check.sh74
-rw-r--r--doc/release-process.md17
-rwxr-xr-xqa/rpc-tests/wallet.py41
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/alert.cpp9
-rw-r--r--src/alert.h4
-rw-r--r--src/init.cpp2
-rw-r--r--src/key.cpp18
-rw-r--r--src/key.h3
-rw-r--r--src/main.cpp10
-rw-r--r--src/pow.cpp6
-rw-r--r--src/qt/forms/sendcoinsdialog.ui2
-rw-r--r--src/secp256k1/Makefile.am10
-rw-r--r--src/secp256k1/README.md20
-rw-r--r--src/secp256k1/configure.ac12
-rw-r--r--src/secp256k1/include/secp256k1.h46
-rw-r--r--src/secp256k1/src/bench.h29
-rw-r--r--src/secp256k1/src/bench_internal.c318
-rw-r--r--src/secp256k1/src/bench_inv.c52
-rw-r--r--src/secp256k1/src/bench_recover.c17
-rw-r--r--src/secp256k1/src/bench_sign.c15
-rw-r--r--src/secp256k1/src/bench_verify.c14
-rw-r--r--src/secp256k1/src/ecdsa.h4
-rw-r--r--src/secp256k1/src/ecdsa_impl.h173
-rw-r--r--src/secp256k1/src/eckey_impl.h19
-rw-r--r--src/secp256k1/src/ecmult_gen_impl.h57
-rw-r--r--src/secp256k1/src/ecmult_impl.h144
-rw-r--r--src/secp256k1/src/field.h27
-rw-r--r--src/secp256k1/src/field_10x26.h26
-rw-r--r--src/secp256k1/src/field_10x26_impl.h185
-rw-r--r--src/secp256k1/src/field_5x52.h26
-rw-r--r--src/secp256k1/src/field_5x52_impl.h82
-rw-r--r--src/secp256k1/src/field_5x52_int128_impl.h120
-rw-r--r--src/secp256k1/src/field_impl.h187
-rw-r--r--src/secp256k1/src/group.h42
-rw-r--r--src/secp256k1/src/group_impl.h250
-rw-r--r--src/secp256k1/src/hash.h4
-rw-r--r--src/secp256k1/src/hash_impl.h117
-rw-r--r--src/secp256k1/src/num_gmp_impl.h29
-rw-r--r--src/secp256k1/src/scalar.h7
-rw-r--r--src/secp256k1/src/scalar_4x64.h2
-rw-r--r--src/secp256k1/src/scalar_4x64_impl.h551
-rw-r--r--src/secp256k1/src/scalar_8x32.h2
-rw-r--r--src/secp256k1/src/scalar_8x32_impl.h87
-rw-r--r--src/secp256k1/src/scalar_impl.h279
-rw-r--r--src/secp256k1/src/secp256k1.c311
-rw-r--r--src/secp256k1/src/testrand.h6
-rw-r--r--src/secp256k1/src/testrand_impl.h48
-rw-r--r--src/secp256k1/src/tests.c651
-rw-r--r--src/secp256k1/src/util.h21
-rw-r--r--src/test/alert_tests.cpp7
-rw-r--r--src/test/data/script_invalid.json46
-rw-r--r--src/test/data/script_valid.json42
-rw-r--r--src/test/mempool_tests.cpp104
-rw-r--r--src/txmempool.cpp12
-rw-r--r--src/wallet/wallet.cpp21
-rw-r--r--src/wallet/wallet.h7
58 files changed, 2878 insertions, 1551 deletions
diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md
index 40495cce8b..f90afa7f20 100644
--- a/contrib/devtools/README.md
+++ b/contrib/devtools/README.md
@@ -81,3 +81,16 @@ It will do the following automatically:
See doc/translation-process.md for more information.
+git-subtree-check.sh
+====================
+
+Run this script from the root of the repository to verify that a subtree matches the contents of
+the commit it claims to have been updated to.
+
+To use, make sure that you have fetched the upstream repository branch in which the subtree is
+maintained:
+* for src/secp256k1: https://github.com/bitcoin/secp256k1.git (branch master)
+* for sec/leveldb: https://github.com/bitcoin/leveldb.git (branch bitcoin-fork)
+
+Usage: git-subtree-check.sh DIR COMMIT
+COMMIT may be omitted, in which case HEAD is used.
diff --git a/contrib/devtools/git-subtree-check.sh b/contrib/devtools/git-subtree-check.sh
new file mode 100755
index 0000000000..1cb82fe682
--- /dev/null
+++ b/contrib/devtools/git-subtree-check.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+DIR="$1"
+COMMIT="$2"
+if [ -z "$COMMIT" ]; then
+ COMMIT=HEAD
+fi
+
+# Taken from git-subtree (Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>)
+find_latest_squash()
+{
+ dir="$1"
+ sq=
+ main=
+ sub=
+ git log --grep="^git-subtree-dir: $dir/*\$" \
+ --pretty=format:'START %H%n%s%n%n%b%nEND%n' "$COMMIT" |
+ while read a b junk; do
+ case "$a" in
+ START) sq="$b" ;;
+ git-subtree-mainline:) main="$b" ;;
+ git-subtree-split:) sub="$b" ;;
+ END)
+ if [ -n "$sub" ]; then
+ if [ -n "$main" ]; then
+ # a rejoin commit?
+ # Pretend its sub was a squash.
+ sq="$sub"
+ fi
+ echo "$sq" "$sub"
+ break
+ fi
+ sq=
+ main=
+ sub=
+ ;;
+ esac
+ done
+}
+
+latest_squash="$(find_latest_squash "$DIR")"
+if [ -z "$latest_squash" ]; then
+ echo "ERROR: $DIR is not a subtree" >&2
+ exit 2
+fi
+
+set $latest_squash
+old=$1
+rev=$2
+if [ "d$(git cat-file -t $rev 2>/dev/null)" != dcommit ]; then
+ echo "ERROR: subtree commit $rev unavailable. Fetch/update the subtree repository" >&2
+ exit 2
+fi
+tree_subtree=$(git show -s --format="%T" $rev)
+echo "$DIR in $COMMIT was last updated to upstream commit $rev (tree $tree_subtree)"
+tree_actual=$(git ls-tree -d "$COMMIT" "$DIR" | head -n 1)
+if [ -z "$tree_actual" ]; then
+ echo "FAIL: subtree directory $DIR not found in $COMMIT" >&2
+ exit 1
+fi
+set $tree_actual
+tree_actual_type=$2
+tree_actual_tree=$3
+echo "$DIR in $COMMIT currently refers to $tree_actual_type $tree_actual_tree"
+if [ "d$tree_actual_type" != "dtree" ]; then
+ echo "FAIL: subtree directory $DIR is not a tree in $COMMIT" >&2
+ exit 1
+fi
+if [ "$tree_actual_tree" != "$tree_subtree" ]; then
+ git diff-tree $tree_actual_tree $tree_subtree >&2
+ echo "FAIL: subtree directory tree doesn't match subtree commit tree" >&2
+ exit 1
+fi
+echo "GOOD"
diff --git a/doc/release-process.md b/doc/release-process.md
index 016090c594..5dad9bf5de 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -133,15 +133,22 @@ rm SHA256SUMS
Note: check that SHA256SUMS itself doesn't end up in SHA256SUMS, which is a spurious/nonsensical entry.
- Upload zips and installers, as well as `SHA256SUMS.asc` from last step, to the bitcoin.org server
+ into `/var/www/bin/bitcoin-core-${VERSION}`
- Update bitcoin.org version
- - Make a pull request to add a file named `YYYY-MM-DD-vX.Y.Z.md` with the release notes
- to https://github.com/bitcoin/bitcoin.org/tree/master/_releases
- ([Example for 0.9.2.1](https://raw.githubusercontent.com/bitcoin/bitcoin.org/master/_releases/2014-06-19-v0.9.2.1.md)).
+ - First, check to see if the Bitcoin.org maintainers have prepared a
+ release: https://github.com/bitcoin/bitcoin.org/labels/Releases
- - After the pull request is merged, the website will automatically show the newest version, as well
- as update the OS download links. Ping Saivann in case anything goes wrong
+ - If they have, it will have previously failed their Travis CI
+ checks because the final release files weren't uploaded.
+ Trigger a Travis CI rebuild---if it passes, merge.
+
+ - If they have not prepared a release, follow the Bitcoin.org release
+ instructions: https://github.com/bitcoin/bitcoin.org#release-notes
+
+ - After the pull request is merged, the website will automatically show the newest version within 15 minutes, as well
+ as update the OS download links. Ping @saivann/@harding (saivann/harding on Freenode) in case anything goes wrong
- Announce the release:
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index 7616625b8a..0301f160c1 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -150,6 +150,47 @@ class WalletTest (BitcoinTestFramework):
sync_mempools(self.nodes)
assert(txid1 in self.nodes[3].getrawmempool())
+
+
+ #do some -walletbroadcast tests
+ stop_nodes(self.nodes)
+ wait_bitcoinds()
+ self.nodes = start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"],["-walletbroadcast=0"],["-walletbroadcast=0"]])
+ connect_nodes_bi(self.nodes,0,1)
+ connect_nodes_bi(self.nodes,1,2)
+ connect_nodes_bi(self.nodes,0,2)
+ self.sync_all()
+ txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2);
+ txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
+ self.nodes[1].setgenerate(True, 1) #mine a block, tx should not be in there
+ self.sync_all()
+ assert_equal(self.nodes[2].getbalance(), Decimal('59.99800000')); #should not be changed because tx was not broadcasted
+
+ #now broadcast from another node, mine a block, sync, and check the balance
+ self.nodes[1].sendrawtransaction(txObjNotBroadcasted['hex'])
+ self.nodes[1].setgenerate(True, 1)
+ self.sync_all()
+ txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
+ assert_equal(self.nodes[2].getbalance(), Decimal('61.99800000')); #should not be
+
+ #create another tx
+ txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2);
+
+ #restart the nodes with -walletbroadcast=1
+ stop_nodes(self.nodes)
+ wait_bitcoinds()
+ self.nodes = start_nodes(3, self.options.tmpdir)
+ connect_nodes_bi(self.nodes,0,1)
+ connect_nodes_bi(self.nodes,1,2)
+ connect_nodes_bi(self.nodes,0,2)
+ sync_blocks(self.nodes)
+
+ self.nodes[0].setgenerate(True, 1)
+ sync_blocks(self.nodes)
+
+ #tx should be added to balance because after restarting the nodes tx should be broadcastet
+ assert_equal(self.nodes[2].getbalance(), Decimal('63.99800000')); #should not be
+
if __name__ == '__main__':
WalletTest ().main ()
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 8dd0a28454..52ff3f224f 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -50,6 +50,7 @@ BITCOIN_TESTS =\
test/hash_tests.cpp \
test/key_tests.cpp \
test/main_tests.cpp \
+ test/mempool_tests.cpp \
test/miner_tests.cpp \
test/mruset_tests.cpp \
test/multisig_tests.cpp \
diff --git a/src/alert.cpp b/src/alert.cpp
index 323939913b..aa7ac748da 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -5,7 +5,6 @@
#include "alert.h"
-#include "chainparams.h"
#include "clientversion.h"
#include "net.h"
#include "pubkey.h"
@@ -145,9 +144,9 @@ bool CAlert::RelayTo(CNode* pnode) const
return false;
}
-bool CAlert::CheckSignature() const
+bool CAlert::CheckSignature(const std::vector<unsigned char>& alertKey) const
{
- CPubKey key(Params().AlertKey());
+ CPubKey key(alertKey);
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
return error("CAlert::CheckSignature(): verify signature failed");
@@ -169,9 +168,9 @@ CAlert CAlert::getAlertByHash(const uint256 &hash)
return retval;
}
-bool CAlert::ProcessAlert(bool fThread)
+bool CAlert::ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread)
{
- if (!CheckSignature())
+ if (!CheckSignature(alertKey))
return false;
if (!IsInEffect())
return false;
diff --git a/src/alert.h b/src/alert.h
index af42171af5..746967c4af 100644
--- a/src/alert.h
+++ b/src/alert.h
@@ -100,8 +100,8 @@ public:
bool AppliesTo(int nVersion, std::string strSubVerIn) const;
bool AppliesToMe() const;
bool RelayTo(CNode* pnode) const;
- bool CheckSignature() const;
- bool ProcessAlert(bool fThread = true); // fThread means run -alertnotify in a free-running thread
+ bool CheckSignature(const std::vector<unsigned char>& alertKey) const;
+ bool ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread = true); // fThread means run -alertnotify in a free-running thread
static void Notify(const std::string& strMessage, bool fThread);
/*
diff --git a/src/init.cpp b/src/init.cpp
index d6957ebdbc..53e521983f 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -337,6 +337,7 @@ std::string HelpMessage(HelpMessageMode mode)
FormatMoney(maxTxFee)));
strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup"));
strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat"));
+ strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), true));
strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
" " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
@@ -1243,6 +1244,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
}
}
+ pwalletMain->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", true));
} // (!fDisableWallet)
#else // ENABLE_WALLET
LogPrintf("No wallet compiled in!\n");
diff --git a/src/key.cpp b/src/key.cpp
index 64c9bc7119..e146e47d0d 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -5,6 +5,7 @@
#include "key.h"
#include "arith_uint256.h"
+#include "crypto/common.h"
#include "crypto/hmac_sha512.h"
#include "eccryptoverify.h"
#include "pubkey.h"
@@ -73,25 +74,14 @@ CPubKey CKey::GetPubKey() const {
return result;
}
-extern "C"
-{
-static int secp256k1_nonce_function_test_case(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int attempt, const void *data)
-{
- const uint32_t *test_case = static_cast<const uint32_t*>(data);
- uint256 nonce;
- secp256k1_nonce_function_rfc6979(nonce.begin(), msg32, key32, attempt, NULL);
- nonce = ArithToUint256(UintToArith256(nonce) + *test_case);
- memcpy(nonce32, nonce.begin(), 32);
- return 1;
-}
-}
-
bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const {
if (!fValid)
return false;
vchSig.resize(72);
int nSigLen = 72;
- int ret = secp256k1_ecdsa_sign(hash.begin(), (unsigned char*)&vchSig[0], &nSigLen, begin(), test_case == 0 ? secp256k1_nonce_function_rfc6979 : secp256k1_nonce_function_test_case, test_case == 0 ? NULL : &test_case);
+ unsigned char extra_entropy[32] = {0};
+ WriteLE32(extra_entropy, test_case);
+ int ret = secp256k1_ecdsa_sign(hash.begin(), (unsigned char*)&vchSig[0], &nSigLen, begin(), secp256k1_nonce_function_rfc6979, test_case ? extra_entropy : NULL);
assert(ret);
vchSig.resize(nSigLen);
return true;
diff --git a/src/key.h b/src/key.h
index 1f1d142887..104a8f5c72 100644
--- a/src/key.h
+++ b/src/key.h
@@ -124,8 +124,7 @@ public:
/**
* Create a DER-serialized signature.
- * The test_case parameter tweaks the deterministic nonce, and is only for
- * testing. It should be zero for normal use.
+ * The test_case parameter tweaks the deterministic nonce.
*/
bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case = 0) const;
diff --git a/src/main.cpp b/src/main.cpp
index 011016204e..8fb6766301 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -3248,6 +3248,7 @@ void static CheckBlockIndex()
CBlockIndex* pindexFirstInvalid = NULL; // Oldest ancestor of pindex which is invalid.
CBlockIndex* pindexFirstMissing = NULL; // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA.
CBlockIndex* pindexFirstNotTreeValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not).
+ CBlockIndex* pindexFirstNotTransactionsValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not).
CBlockIndex* pindexFirstNotChainValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not).
CBlockIndex* pindexFirstNotScriptsValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not).
while (pindex != NULL) {
@@ -3255,6 +3256,7 @@ void static CheckBlockIndex()
if (pindexFirstInvalid == NULL && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
if (pindexFirstMissing == NULL && !(pindex->nStatus & BLOCK_HAVE_DATA)) pindexFirstMissing = pindex;
if (pindex->pprev != NULL && pindexFirstNotTreeValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TREE) pindexFirstNotTreeValid = pindex;
+ if (pindex->pprev != NULL && pindexFirstNotTransactionsValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TRANSACTIONS) pindexFirstNotTransactionsValid = pindex;
if (pindex->pprev != NULL && pindexFirstNotChainValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_CHAIN) pindexFirstNotChainValid = pindex;
if (pindex->pprev != NULL && pindexFirstNotScriptsValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS) pindexFirstNotScriptsValid = pindex;
@@ -3264,7 +3266,12 @@ void static CheckBlockIndex()
assert(pindex->GetBlockHash() == Params().HashGenesisBlock()); // Genesis block's hash must match.
assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block.
}
+ // HAVE_DATA is equivalent to VALID_TRANSACTIONS and equivalent to nTx > 0 (we stored the number of transactions in the block)
+ assert(!(pindex->nStatus & BLOCK_HAVE_DATA) == (pindex->nTx == 0));
+ assert(((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindex->nTx > 0));
+ // All parents having data is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to nChainTx being set.
assert((pindexFirstMissing != NULL) == (pindex->nChainTx == 0)); // nChainTx == 0 is used to signal that all parent block's transaction data is available.
+ assert((pindexFirstNotTransactionsValid != NULL) == (pindex->nChainTx == 0));
assert(pindex->nHeight == nHeight); // nHeight must be consistent.
assert(pindex->pprev == NULL || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's.
assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks.
@@ -3320,6 +3327,7 @@ void static CheckBlockIndex()
if (pindex == pindexFirstInvalid) pindexFirstInvalid = NULL;
if (pindex == pindexFirstMissing) pindexFirstMissing = NULL;
if (pindex == pindexFirstNotTreeValid) pindexFirstNotTreeValid = NULL;
+ if (pindex == pindexFirstNotTransactionsValid) pindexFirstNotTransactionsValid = NULL;
if (pindex == pindexFirstNotChainValid) pindexFirstNotChainValid = NULL;
if (pindex == pindexFirstNotScriptsValid) pindexFirstNotScriptsValid = NULL;
// Find our parent.
@@ -4262,7 +4270,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
uint256 alertHash = alert.GetHash();
if (pfrom->setKnown.count(alertHash) == 0)
{
- if (alert.ProcessAlert())
+ if (alert.ProcessAlert(Params().AlertKey()))
{
// Relay
pfrom->setKnown.insert(alertHash);
diff --git a/src/pow.cpp b/src/pow.cpp
index 3c5a8d9d96..cf7ac387f2 100644
--- a/src/pow.cpp
+++ b/src/pow.cpp
@@ -42,9 +42,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
}
// Go back by what we want to be 14 days worth of blocks
- const CBlockIndex* pindexFirst = pindexLast;
- for (int i = 0; pindexFirst && i < params.DifficultyAdjustmentInterval()-1; i++)
- pindexFirst = pindexFirst->pprev;
+ int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
+ assert(nHeightFirst >= 0);
+ const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
assert(pindexFirst);
return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui
index b1ed7a27b5..8911b41cbf 100644
--- a/src/qt/forms/sendcoinsdialog.ui
+++ b/src/qt/forms/sendcoinsdialog.ui
@@ -807,7 +807,7 @@
<string>collapse fee-settings</string>
</property>
<property name="text">
- <string>Minimize</string>
+ <string>Hide</string>
</property>
</widget>
</item>
diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am
index 985c172eba..cc15338b7e 100644
--- a/src/secp256k1/Makefile.am
+++ b/src/secp256k1/Makefile.am
@@ -49,7 +49,7 @@ libsecp256k1_la_LIBADD = $(SECP_LIBS)
noinst_PROGRAMS =
if USE_BENCHMARK
-noinst_PROGRAMS += bench_verify bench_recover bench_sign bench_inv
+noinst_PROGRAMS += bench_verify bench_recover bench_sign bench_internal
bench_verify_SOURCES = src/bench_verify.c
bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS)
bench_verify_LDFLAGS = -static
@@ -59,10 +59,10 @@ bench_recover_LDFLAGS = -static
bench_sign_SOURCES = src/bench_sign.c
bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS)
bench_sign_LDFLAGS = -static
-bench_inv_SOURCES = src/bench_inv.c
-bench_inv_LDADD = $(SECP_LIBS)
-bench_inv_LDFLAGS = -static
-bench_inv_CPPFLAGS = $(SECP_INCLUDES)
+bench_internal_SOURCES = src/bench_internal.c
+bench_internal_LDADD = $(SECP_LIBS)
+bench_internal_LDFLAGS = -static
+bench_internal_CPPFLAGS = $(SECP_INCLUDES)
endif
if USE_TESTS
diff --git a/src/secp256k1/README.md b/src/secp256k1/README.md
index 1e49f49416..6095db4220 100644
--- a/src/secp256k1/README.md
+++ b/src/secp256k1/README.md
@@ -5,25 +5,29 @@ libsecp256k1
Optimized C library for EC operations on curve secp256k1.
-This library is experimental, so use at your own risk.
+This library is a work in progress and is being used to research best practices. Use at your own risk.
Features:
-* Low-level field and group operations on secp256k1.
-* ECDSA signing/verification and key generation.
+* secp256k1 ECDSA signing/verification and key generation.
* Adding/multiplying private/public keys.
* Serialization/parsing of private keys, public keys, signatures.
+* Constant time, constant memory access signing and pubkey generation.
+* Derandomized DSA (via RFC6979 or with a caller provided function.)
* Very efficient implementation.
Implementation details
----------------------
* General
- * Avoid dynamic memory usage almost everywhere.
+ * No runtime heap allocation.
+ * Extensive testing infrastructure.
+ * Structured to facilitate review and analysis.
+ * Intended to be portable to any system with a C89 compiler and uint64_t support.
+ * Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.")
* Field operations
* Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1).
* Using 5 52-bit limbs (including hand-optimized assembly for x86_64, by Diederik Huys).
* Using 10 26-bit limbs.
- * Using GMP.
* Field inverses and square roots using a sliding window over blocks of 1s (by Peter Dettman).
* Scalar operations
* Optimized implementation without data-dependent branches of arithmetic modulo the curve's order.
@@ -33,14 +37,15 @@ Implementation details
* Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7).
* Use addition between points in Jacobian and affine coordinates where possible.
* Use a unified addition/doubling formula where necessary to avoid data-dependent branches.
+ * Point/x comparison without a field inversion by comparison in the Jacobian coordinate space.
* Point multiplication for verification (a*P + b*G).
* Use wNAF notation for point multiplicands.
* Use a much larger window for multiples of G, using precomputed multiples.
* Use Shamir's trick to do the multiplication with the public key and the generator simultaneously.
- * Optionally use secp256k1's efficiently-computable endomorphism to split the multiplicands into 4 half-sized ones first.
+ * Optionally (off by default) use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones.
* Point multiplication for signing
* Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions.
- * Slice the precomputed table in memory per byte, so memory access to the table becomes uniform.
+ * Access the table with branch-free conditional moves so memory access is uniform.
* No data-dependent branches
* The precomputed tables add and eventually subtract points for which no known scalar (private key) is known, preventing even an attacker with control over the private key used to control the data internally.
@@ -52,4 +57,5 @@ libsecp256k1 is built using autotools:
$ ./autogen.sh
$ ./configure
$ make
+ $ ./tests
$ sudo make install # optional
diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac
index f691156ff7..3dc1829516 100644
--- a/src/secp256k1/configure.ac
+++ b/src/secp256k1/configure.ac
@@ -5,7 +5,7 @@ AC_CONFIG_MACRO_DIR([build-aux/m4])
AC_CANONICAL_HOST
AH_TOP([#ifndef LIBSECP256K1_CONFIG_H])
AH_TOP([#define LIBSECP256K1_CONFIG_H])
-AH_BOTTOM([#endif //LIBSECP256K1_CONFIG_H])
+AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/])
AM_INIT_AUTOMAKE([foreign subdir-objects])
LT_INIT
@@ -22,9 +22,9 @@ if test "x$CFLAGS" = "x"; then
CFLAGS="-O3 -g"
fi
-AC_PROG_CC_C99
-if test x"$ac_cv_prog_cc_c99" = x"no"; then
- AC_MSG_ERROR([c99 compiler support required])
+AC_PROG_CC_C89
+if test x"$ac_cv_prog_cc_c89" = x"no"; then
+ AC_MSG_ERROR([c89 compiler support required])
fi
case $host in
@@ -70,7 +70,7 @@ esac
CFLAGS="$CFLAGS -W"
-warn_CFLAGS="-Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function"
+warn_CFLAGS="-std=c89 -pedantic -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -Wno-long-long -Wno-overlength-strings"
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $warn_CFLAGS"
AC_MSG_CHECKING([if ${CC} supports ${warn_CFLAGS}])
@@ -305,6 +305,8 @@ if test x"$use_endomorphism" = x"yes"; then
AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization])
fi
+AC_C_BIGENDIAN()
+
AC_MSG_NOTICE([Using assembly optimizations: $set_asm])
AC_MSG_NOTICE([Using field implementation: $set_field])
AC_MSG_NOTICE([Using bignum implementation: $set_bignum])
diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h
index cfdae31eaf..a6e39d13db 100644
--- a/src/secp256k1/include/secp256k1.h
+++ b/src/secp256k1/include/secp256k1.h
@@ -78,7 +78,7 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
/** A pointer to a function to deterministically generate a nonce.
- * Returns: 1 if a nonce was succesfully generated. 0 will cause signing to fail.
+ * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail.
* In: msg32: the 32-byte message hash being verified (will not be NULL)
* key32: pointer to a 32-byte secret key (will not be NULL)
* attempt: how many iterations we have tried to find a nonce.
@@ -97,7 +97,10 @@ typedef int (*secp256k1_nonce_function_t)(
const void *data
);
-/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. */
+/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function.
+ * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
+ * extra entropy.
+ */
extern const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979;
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
@@ -106,15 +109,43 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default;
/** Create an ECDSA signature.
* Returns: 1: signature created
- * 0: the nonce generation function failed
+ * 0: the nonce generation function failed, the private key was invalid, or there is not
+ * enough space in the signature (as indicated by siglen).
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
- * seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid)
+ * seckey: pointer to a 32-byte secret key (cannot be NULL)
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
* In/Out: siglen: pointer to an int with the length of sig, which will be updated
- * to contain the actual signature length (<=72).
+ * to contain the actual signature length (<=72). If 0 is returned, this will be
+ * set to zero.
* Requires starting using SECP256K1_START_SIGN.
+ *
+ * The sig always has an s value in the lower half of the range (From 0x1
+ * to 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
+ * inclusive), unlike many other implementations.
+ * With ECDSA a third-party can can forge a second distinct signature
+ * of the same message given a single initial signature without knowing
+ * the key by setting s to its additive inverse mod-order, 'flipping' the
+ * sign of the random point R which is not included in the signature.
+ * Since the forgery is of the same message this isn't universally
+ * problematic, but in systems where message malleability or uniqueness
+ * of signatures is important this can cause issues. This forgery can be
+ * blocked by all verifiers forcing signers to use a canonical form. The
+ * lower-S form reduces the size of signatures slightly on average when
+ * variable length encodings (such as DER) are used and is cheap to
+ * verify, making it a good choice. Security of always using lower-S is
+ * assured because anyone can trivially modify a signature after the
+ * fact to enforce this property. Adjusting it inside the signing
+ * function avoids the need to re-serialize or have curve specific
+ * constants outside of the library. By always using a canonical form
+ * even in applications where it isn't needed it becomes possible to
+ * impose a requirement later if a need is discovered.
+ * No other forms of ECDSA malleability are known and none seem likely,
+ * but there is no formal proof that ECDSA, even with this additional
+ * restriction, is free of other malleability. Commonly used serialization
+ * schemes will also accept various non-unique encodings, so care should
+ * be taken when this property is required for an application.
*/
int secp256k1_ecdsa_sign(
const unsigned char *msg32,
@@ -127,12 +158,13 @@ int secp256k1_ecdsa_sign(
/** Create a compact ECDSA signature (64 byte + recovery id).
* Returns: 1: signature created
- * 0: the nonce generation function failed
+ * 0: the nonce generation function failed, or the secret key was invalid.
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
- * seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid)
+ * seckey: pointer to a 32-byte secret key (cannot be NULL)
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
* Out: sig: pointer to a 64-byte array where the signature will be placed (cannot be NULL)
+ * In case 0 is returned, the returned signature length will be zero.
* recid: pointer to an int, which will be updated to contain the recovery id (can be NULL)
* Requires starting using SECP256K1_START_SIGN.
*/
diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h
index 668ec39f71..0559b3e853 100644
--- a/src/secp256k1/src/bench.h
+++ b/src/secp256k1/src/bench.h
@@ -17,21 +17,40 @@ static double gettimedouble(void) {
return tv.tv_usec * 0.000001 + tv.tv_sec;
}
-void run_benchmark(void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) {
+void print_number(double x) {
+ double y = x;
+ int c = 0;
+ if (y < 0.0) y = -y;
+ while (y < 100.0) {
+ y *= 10.0;
+ c++;
+ }
+ printf("%.*f", c, x);
+}
+
+void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) {
+ int i;
double min = HUGE_VAL;
double sum = 0.0;
double max = 0.0;
- for (int i = 0; i < count; i++) {
+ for (i = 0; i < count; i++) {
+ double begin, total;
if (setup) setup(data);
- double begin = gettimedouble();
+ begin = gettimedouble();
benchmark(data);
- double total = gettimedouble() - begin;
+ total = gettimedouble() - begin;
if (teardown) teardown(data);
if (total < min) min = total;
if (total > max) max = total;
sum += total;
}
- printf("min %.3fus / avg %.3fus / max %.3fus\n", min * 1000000.0 / iter, (sum / count) * 1000000.0 / iter, max * 1000000.0 / iter);
+ printf("%s: min ", name);
+ print_number(min * 1000000.0 / iter);
+ printf("us / avg ");
+ print_number((sum / count) * 1000000.0 / iter);
+ printf("us / avg ");
+ print_number(max * 1000000.0 / iter);
+ printf("us\n");
}
#endif
diff --git a/src/secp256k1/src/bench_internal.c b/src/secp256k1/src/bench_internal.c
new file mode 100644
index 0000000000..a960549b94
--- /dev/null
+++ b/src/secp256k1/src/bench_internal.c
@@ -0,0 +1,318 @@
+/**********************************************************************
+ * Copyright (c) 2014-2015 Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+#include <stdio.h>
+
+#include "include/secp256k1.h"
+
+#include "util.h"
+#include "hash_impl.h"
+#include "num_impl.h"
+#include "field_impl.h"
+#include "group_impl.h"
+#include "scalar_impl.h"
+#include "ecmult_impl.h"
+#include "bench.h"
+
+typedef struct {
+ secp256k1_scalar_t scalar_x, scalar_y;
+ secp256k1_fe_t fe_x, fe_y;
+ secp256k1_ge_t ge_x, ge_y;
+ secp256k1_gej_t gej_x, gej_y;
+ unsigned char data[32];
+ int wnaf[256];
+} bench_inv_t;
+
+void bench_setup(void* arg) {
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ static const unsigned char init_x[32] = {
+ 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13,
+ 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35,
+ 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59,
+ 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83
+ };
+
+ static const unsigned char init_y[32] = {
+ 0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83,
+ 0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5,
+ 0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9,
+ 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3
+ };
+
+ secp256k1_scalar_set_b32(&data->scalar_x, init_x, NULL);
+ secp256k1_scalar_set_b32(&data->scalar_y, init_y, NULL);
+ secp256k1_fe_set_b32(&data->fe_x, init_x);
+ secp256k1_fe_set_b32(&data->fe_y, init_y);
+ CHECK(secp256k1_ge_set_xo_var(&data->ge_x, &data->fe_x, 0));
+ CHECK(secp256k1_ge_set_xo_var(&data->ge_y, &data->fe_y, 1));
+ secp256k1_gej_set_ge(&data->gej_x, &data->ge_x);
+ secp256k1_gej_set_ge(&data->gej_y, &data->ge_y);
+ memcpy(data->data, init_x, 32);
+}
+
+void bench_scalar_add(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 2000000; i++) {
+ secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ }
+}
+
+void bench_scalar_negate(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 2000000; i++) {
+ secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x);
+ }
+}
+
+void bench_scalar_sqr(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 200000; i++) {
+ secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x);
+ }
+}
+
+void bench_scalar_mul(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 200000; i++) {
+ secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ }
+}
+
+#ifdef USE_ENDOMORPHISM
+void bench_scalar_split(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 20000; i++) {
+ secp256k1_scalar_t l, r;
+ secp256k1_scalar_split_lambda_var(&l, &r, &data->scalar_x);
+ secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ }
+}
+#endif
+
+void bench_scalar_inverse(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 2000; i++) {
+ secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x);
+ secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ }
+}
+
+void bench_scalar_inverse_var(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 2000; i++) {
+ secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x);
+ secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ }
+}
+
+void bench_field_normalize(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 2000000; i++) {
+ secp256k1_fe_normalize(&data->fe_x);
+ }
+}
+
+void bench_field_normalize_weak(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 2000000; i++) {
+ secp256k1_fe_normalize_weak(&data->fe_x);
+ }
+}
+
+void bench_field_mul(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 200000; i++) {
+ secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y);
+ }
+}
+
+void bench_field_sqr(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 200000; i++) {
+ secp256k1_fe_sqr(&data->fe_x, &data->fe_x);
+ }
+}
+
+void bench_field_inverse(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 20000; i++) {
+ secp256k1_fe_inv(&data->fe_x, &data->fe_x);
+ secp256k1_fe_add(&data->fe_x, &data->fe_y);
+ }
+}
+
+void bench_field_inverse_var(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 20000; i++) {
+ secp256k1_fe_inv_var(&data->fe_x, &data->fe_x);
+ secp256k1_fe_add(&data->fe_x, &data->fe_y);
+ }
+}
+
+void bench_field_sqrt_var(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 20000; i++) {
+ secp256k1_fe_sqrt_var(&data->fe_x, &data->fe_x);
+ secp256k1_fe_add(&data->fe_x, &data->fe_y);
+ }
+}
+
+void bench_group_double_var(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 200000; i++) {
+ secp256k1_gej_double_var(&data->gej_x, &data->gej_x);
+ }
+}
+
+void bench_group_add_var(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 200000; i++) {
+ secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y);
+ }
+}
+
+void bench_group_add_affine(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 200000; i++) {
+ secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y);
+ }
+}
+
+void bench_group_add_affine_var(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 200000; i++) {
+ secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y);
+ }
+}
+
+void bench_ecmult_wnaf(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+
+ for (i = 0; i < 20000; i++) {
+ secp256k1_ecmult_wnaf(data->wnaf, &data->scalar_x, WINDOW_A);
+ secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ }
+}
+
+
+void bench_sha256(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+ secp256k1_sha256_t sha;
+
+ for (i = 0; i < 20000; i++) {
+ secp256k1_sha256_initialize(&sha);
+ secp256k1_sha256_write(&sha, data->data, 32);
+ secp256k1_sha256_finalize(&sha, data->data);
+ }
+}
+
+void bench_hmac_sha256(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+ secp256k1_hmac_sha256_t hmac;
+
+ for (i = 0; i < 20000; i++) {
+ secp256k1_hmac_sha256_initialize(&hmac, data->data, 32);
+ secp256k1_hmac_sha256_write(&hmac, data->data, 32);
+ secp256k1_hmac_sha256_finalize(&hmac, data->data);
+ }
+}
+
+void bench_rfc6979_hmac_sha256(void* arg) {
+ int i;
+ bench_inv_t *data = (bench_inv_t*)arg;
+ secp256k1_rfc6979_hmac_sha256_t rng;
+
+ for (i = 0; i < 20000; i++) {
+ secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 32, data->data, 32, NULL, 0);
+ secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32);
+ }
+}
+
+
+int have_flag(int argc, char** argv, char *flag) {
+ char** argm = argv + argc;
+ argv++;
+ if (argv == argm) {
+ return 1;
+ }
+ while (argv != NULL && argv != argm) {
+ if (strcmp(*argv, flag) == 0) return 1;
+ argv++;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ bench_inv_t data;
+ if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000);
+ if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000);
+ if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000);
+ if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, 200000);
+#ifdef USE_ENDOMORPHISM
+ if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, 20000);
+#endif
+ if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, 2000);
+ if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, 2000);
+
+ if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, 2000000);
+ if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, 2000000);
+ if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, 200000);
+ if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, 200000);
+ if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, 20000);
+ if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, 20000);
+ if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt_var", bench_field_sqrt_var, bench_setup, NULL, &data, 10, 20000);
+
+ if (have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, 200000);
+ if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, 200000);
+ if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000);
+ if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000);
+
+ if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000);
+
+ if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, 20000);
+ if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, 20000);
+ if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, 20000);
+ return 0;
+}
diff --git a/src/secp256k1/src/bench_inv.c b/src/secp256k1/src/bench_inv.c
deleted file mode 100644
index 3bdedea30e..0000000000
--- a/src/secp256k1/src/bench_inv.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/**********************************************************************
- * Copyright (c) 2014 Pieter Wuille *
- * Distributed under the MIT software license, see the accompanying *
- * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
- **********************************************************************/
-#include <stdio.h>
-
-#include "include/secp256k1.h"
-
-#include "util.h"
-#include "num_impl.h"
-#include "field_impl.h"
-#include "group_impl.h"
-#include "scalar_impl.h"
-#include "bench.h"
-
-typedef struct {
- secp256k1_scalar_t base, x;
-} bench_inv_t;
-
-void bench_inv_setup(void* arg) {
- bench_inv_t *data = (bench_inv_t*)arg;
-
- static const unsigned char init[32] = {
- 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13,
- 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35,
- 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59,
- 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83
- };
-
- secp256k1_scalar_set_b32(&data->base, init, NULL);
- secp256k1_scalar_set_b32(&data->x, init, NULL);
-}
-
-void bench_inv(void* arg) {
- bench_inv_t *data = (bench_inv_t*)arg;
-
- for (int i=0; i<20000; i++) {
- secp256k1_scalar_inverse(&data->x, &data->x);
- secp256k1_scalar_add(&data->x, &data->x, &data->base);
- }
-}
-
-int main(void) {
- secp256k1_ge_start();
-
- bench_inv_t data;
- run_benchmark(bench_inv, bench_inv_setup, NULL, &data, 10, 20000);
-
- secp256k1_ge_stop();
- return 0;
-}
diff --git a/src/secp256k1/src/bench_recover.c b/src/secp256k1/src/bench_recover.c
index b1e0f33efa..6991cc9d6c 100644
--- a/src/secp256k1/src/bench_recover.c
+++ b/src/secp256k1/src/bench_recover.c
@@ -14,13 +14,15 @@ typedef struct {
} bench_recover_t;
void bench_recover(void* arg) {
+ int i;
bench_recover_t *data = (bench_recover_t*)arg;
-
unsigned char pubkey[33];
- for (int i=0; i<20000; i++) {
+
+ for (i = 0; i < 20000; i++) {
+ int j;
int pubkeylen = 33;
CHECK(secp256k1_ecdsa_recover_compact(data->msg, data->sig, pubkey, &pubkeylen, 1, i % 2));
- for (int j = 0; j < 32; j++) {
+ for (j = 0; j < 32; j++) {
data->sig[j + 32] = data->msg[j]; /* Move former message to S. */
data->msg[j] = data->sig[j]; /* Move former R to message. */
data->sig[j] = pubkey[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */
@@ -29,17 +31,18 @@ void bench_recover(void* arg) {
}
void bench_recover_setup(void* arg) {
+ int i;
bench_recover_t *data = (bench_recover_t*)arg;
- for (int i = 0; i < 32; i++) data->msg[i] = 1 + i;
- for (int i = 0; i < 64; i++) data->sig[i] = 65 + i;
+ for (i = 0; i < 32; i++) data->msg[i] = 1 + i;
+ for (i = 0; i < 64; i++) data->sig[i] = 65 + i;
}
int main(void) {
+ bench_recover_t data;
secp256k1_start(SECP256K1_START_VERIFY);
- bench_recover_t data;
- run_benchmark(bench_recover, bench_recover_setup, NULL, &data, 10, 20000);
+ run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, 20000);
secp256k1_stop();
return 0;
diff --git a/src/secp256k1/src/bench_sign.c b/src/secp256k1/src/bench_sign.c
index 2276f00b9a..c5b6829a84 100644
--- a/src/secp256k1/src/bench_sign.c
+++ b/src/secp256k1/src/bench_sign.c
@@ -14,20 +14,23 @@ typedef struct {
} bench_sign_t;
static void bench_sign_setup(void* arg) {
+ int i;
bench_sign_t *data = (bench_sign_t*)arg;
- for (int i = 0; i < 32; i++) data->msg[i] = i + 1;
- for (int i = 0; i < 32; i++) data->key[i] = i + 65;
+ for (i = 0; i < 32; i++) data->msg[i] = i + 1;
+ for (i = 0; i < 32; i++) data->key[i] = i + 65;
}
static void bench_sign(void* arg) {
+ int i;
bench_sign_t *data = (bench_sign_t*)arg;
unsigned char sig[64];
- for (int i=0; i<20000; i++) {
+ for (i = 0; i < 20000; i++) {
+ int j;
int recid = 0;
CHECK(secp256k1_ecdsa_sign_compact(data->msg, sig, data->key, NULL, NULL, &recid));
- for (int j = 0; j < 32; j++) {
+ for (j = 0; j < 32; j++) {
data->msg[j] = sig[j]; /* Move former R to message. */
data->key[j] = sig[j + 32]; /* Move former S to key. */
}
@@ -35,10 +38,10 @@ static void bench_sign(void* arg) {
}
int main(void) {
+ bench_sign_t data;
secp256k1_start(SECP256K1_START_SIGN);
- bench_sign_t data;
- run_benchmark(bench_sign, bench_sign_setup, NULL, &data, 10, 20000);
+ run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000);
secp256k1_stop();
return 0;
diff --git a/src/secp256k1/src/bench_verify.c b/src/secp256k1/src/bench_verify.c
index a58ca84347..c279305a0d 100644
--- a/src/secp256k1/src/bench_verify.c
+++ b/src/secp256k1/src/bench_verify.c
@@ -21,9 +21,10 @@ typedef struct {
} benchmark_verify_t;
static void benchmark_verify(void* arg) {
+ int i;
benchmark_verify_t* data = (benchmark_verify_t*)arg;
- for (int i=0; i<20000; i++) {
+ for (i = 0; i < 20000; i++) {
data->sig[data->siglen - 1] ^= (i & 0xFF);
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
@@ -35,18 +36,19 @@ static void benchmark_verify(void* arg) {
}
int main(void) {
- secp256k1_start(SECP256K1_START_VERIFY | SECP256K1_START_SIGN);
-
+ int i;
benchmark_verify_t data;
- for (int i = 0; i < 32; i++) data.msg[i] = 1 + i;
- for (int i = 0; i < 32; i++) data.key[i] = 33 + i;
+ secp256k1_start(SECP256K1_START_VERIFY | SECP256K1_START_SIGN);
+
+ for (i = 0; i < 32; i++) data.msg[i] = 1 + i;
+ for (i = 0; i < 32; i++) data.key[i] = 33 + i;
data.siglen = 72;
secp256k1_ecdsa_sign(data.msg, data.sig, &data.siglen, data.key, NULL, NULL);
data.pubkeylen = 33;
CHECK(secp256k1_ec_pubkey_create(data.pubkey, &data.pubkeylen, data.key, 1));
- run_benchmark(benchmark_verify, NULL, NULL, &data, 10, 20000);
+ run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000);
secp256k1_stop();
return 0;
diff --git a/src/secp256k1/src/ecdsa.h b/src/secp256k1/src/ecdsa.h
index 5fc5230c36..c195e7afcb 100644
--- a/src/secp256k1/src/ecdsa.h
+++ b/src/secp256k1/src/ecdsa.h
@@ -10,9 +10,6 @@
#include "scalar.h"
#include "group.h"
-static void secp256k1_ecsda_start(void);
-static void secp256k1_ecdsa_stop(void);
-
typedef struct {
secp256k1_scalar_t r, s;
} secp256k1_ecdsa_sig_t;
@@ -22,6 +19,5 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
-static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s);
#endif
diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h
index 674650c1e9..1a77649390 100644
--- a/src/secp256k1/src/ecdsa_impl.h
+++ b/src/secp256k1/src/ecdsa_impl.h
@@ -15,71 +15,69 @@
#include "ecmult_gen.h"
#include "ecdsa.h"
-typedef struct {
- secp256k1_fe_t order_as_fe;
- secp256k1_fe_t p_minus_order;
-} secp256k1_ecdsa_consts_t;
-
-static const secp256k1_ecdsa_consts_t *secp256k1_ecdsa_consts = NULL;
-
-static void secp256k1_ecdsa_start(void) {
- if (secp256k1_ecdsa_consts != NULL)
- return;
-
- /* Allocate. */
- secp256k1_ecdsa_consts_t *ret = (secp256k1_ecdsa_consts_t*)checked_malloc(sizeof(secp256k1_ecdsa_consts_t));
-
- static const unsigned char order[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
- 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
- 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41
- };
-
- secp256k1_fe_set_b32(&ret->order_as_fe, order);
- secp256k1_fe_negate(&ret->p_minus_order, &ret->order_as_fe, 1);
- secp256k1_fe_normalize_var(&ret->p_minus_order);
-
- /* Set the global pointer. */
- secp256k1_ecdsa_consts = ret;
-}
-
-static void secp256k1_ecdsa_stop(void) {
- if (secp256k1_ecdsa_consts == NULL)
- return;
-
- secp256k1_ecdsa_consts_t *c = (secp256k1_ecdsa_consts_t*)secp256k1_ecdsa_consts;
- secp256k1_ecdsa_consts = NULL;
- free(c);
-}
+/** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1
+ * sage: for t in xrange(1023, -1, -1):
+ * .. p = 2**256 - 2**32 - t
+ * .. if p.is_prime():
+ * .. print '%x'%p
+ * .. break
+ * 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'
+ * sage: a = 0
+ * sage: b = 7
+ * sage: F = FiniteField (p)
+ * sage: '%x' % (EllipticCurve ([F (a), F (b)]).order())
+ * 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
+ */
+static const secp256k1_fe_t secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST(
+ 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL,
+ 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL
+);
+
+/** Difference between field and order, values 'p' and 'n' values defined in
+ * "Standards for Efficient Cryptography" (SEC2) 2.7.1.
+ * sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
+ * sage: a = 0
+ * sage: b = 7
+ * sage: F = FiniteField (p)
+ * sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order())
+ * '14551231950b75fc4402da1722fc9baee'
+ */
+static const secp256k1_fe_t secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST(
+ 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL
+);
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) {
+ unsigned char ra[32] = {0}, sa[32] = {0};
+ const unsigned char *rp;
+ const unsigned char *sp;
+ int lenr;
+ int lens;
+ int overflow;
if (sig[0] != 0x30) return 0;
- int lenr = sig[3];
+ lenr = sig[3];
if (5+lenr >= size) return 0;
- int lens = sig[lenr+5];
+ lens = sig[lenr+5];
if (sig[1] != lenr+lens+4) return 0;
if (lenr+lens+6 > size) return 0;
if (sig[2] != 0x02) return 0;
if (lenr == 0) return 0;
if (sig[lenr+4] != 0x02) return 0;
if (lens == 0) return 0;
- const unsigned char *sp = sig + 6 + lenr;
+ sp = sig + 6 + lenr;
while (lens > 0 && sp[0] == 0) {
lens--;
sp++;
}
if (lens > 32) return 0;
- const unsigned char *rp = sig + 4;
+ rp = sig + 4;
while (lenr > 0 && rp[0] == 0) {
lenr--;
rp++;
}
if (lenr > 32) return 0;
- unsigned char ra[32] = {0}, sa[32] = {0};
memcpy(ra + 32 - lenr, rp, lenr);
memcpy(sa + 32 - lens, sp, lens);
- int overflow = 0;
+ overflow = 0;
secp256k1_scalar_set_b32(&r->r, ra, &overflow);
if (overflow) return 0;
secp256k1_scalar_set_b32(&r->s, sa, &overflow);
@@ -89,10 +87,10 @@ static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned ch
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) {
unsigned char r[33] = {0}, s[33] = {0};
- secp256k1_scalar_get_b32(&r[1], &a->r);
- secp256k1_scalar_get_b32(&s[1], &a->s);
unsigned char *rp = r, *sp = s;
int lenR = 33, lenS = 33;
+ secp256k1_scalar_get_b32(&r[1], &a->r);
+ secp256k1_scalar_get_b32(&s[1], &a->s);
while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; }
while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; }
if (*size < 6+lenS+lenR)
@@ -110,93 +108,100 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se
}
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
+ unsigned char c[32];
+ secp256k1_scalar_t sn, u1, u2;
+ secp256k1_fe_t xr;
+ secp256k1_gej_t pubkeyj;
+ secp256k1_gej_t pr;
+
if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s))
return 0;
- secp256k1_scalar_t sn, u1, u2;
secp256k1_scalar_inverse_var(&sn, &sig->s);
secp256k1_scalar_mul(&u1, &sn, message);
secp256k1_scalar_mul(&u2, &sn, &sig->r);
- secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey);
- secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
+ secp256k1_gej_set_ge(&pubkeyj, pubkey);
+ secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
if (secp256k1_gej_is_infinity(&pr)) {
return 0;
}
- unsigned char c[32];
secp256k1_scalar_get_b32(c, &sig->r);
- secp256k1_fe_t xr;
secp256k1_fe_set_b32(&xr, c);
- // We now have the recomputed R point in pr, and its claimed x coordinate (modulo n)
- // in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p),
- // compute the remainder modulo n, and compare it to xr. However:
- //
- // xr == X(pr) mod n
- // <=> exists h. (xr + h * n < p && xr + h * n == X(pr))
- // [Since 2 * n > p, h can only be 0 or 1]
- // <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr))
- // [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p]
- // <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p)
- // [Multiplying both sides of the equations by pr.z^2 mod p]
- // <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x)
- //
- // Thus, we can avoid the inversion, but we have to check both cases separately.
- // secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test.
+ /** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n)
+ * in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p),
+ * compute the remainder modulo n, and compare it to xr. However:
+ *
+ * xr == X(pr) mod n
+ * <=> exists h. (xr + h * n < p && xr + h * n == X(pr))
+ * [Since 2 * n > p, h can only be 0 or 1]
+ * <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr))
+ * [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p]
+ * <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p)
+ * [Multiplying both sides of the equations by pr.z^2 mod p]
+ * <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x)
+ *
+ * Thus, we can avoid the inversion, but we have to check both cases separately.
+ * secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test.
+ */
if (secp256k1_gej_eq_x_var(&xr, &pr)) {
- // xr.x == xr * xr.z^2 mod p, so the signature is valid.
+ /* xr.x == xr * xr.z^2 mod p, so the signature is valid. */
return 1;
}
- if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_consts->p_minus_order) >= 0) {
- // xr + p >= n, so we can skip testing the second case.
+ if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) {
+ /* xr + p >= n, so we can skip testing the second case. */
return 0;
}
- secp256k1_fe_add(&xr, &secp256k1_ecdsa_consts->order_as_fe);
+ secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe);
if (secp256k1_gej_eq_x_var(&xr, &pr)) {
- // (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid.
+ /* (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid. */
return 1;
}
return 0;
}
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
+ unsigned char brx[32];
+ secp256k1_fe_t fx;
+ secp256k1_ge_t x;
+ secp256k1_gej_t xj;
+ secp256k1_scalar_t rn, u1, u2;
+ secp256k1_gej_t qj;
+
if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s))
return 0;
- unsigned char brx[32];
secp256k1_scalar_get_b32(brx, &sig->r);
- secp256k1_fe_t fx;
VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* brx comes from a scalar, so is less than the order; certainly less than p */
if (recid & 2) {
- if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_consts->p_minus_order) >= 0)
+ if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0)
return 0;
- secp256k1_fe_add(&fx, &secp256k1_ecdsa_consts->order_as_fe);
+ secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe);
}
- secp256k1_ge_t x;
if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1))
return 0;
- secp256k1_gej_t xj;
secp256k1_gej_set_ge(&xj, &x);
- secp256k1_scalar_t rn, u1, u2;
secp256k1_scalar_inverse_var(&rn, &sig->r);
secp256k1_scalar_mul(&u1, &rn, message);
secp256k1_scalar_negate(&u1, &u1);
secp256k1_scalar_mul(&u2, &rn, &sig->s);
- secp256k1_gej_t qj;
secp256k1_ecmult(&qj, &xj, &u2, &u1);
secp256k1_ge_set_gej_var(pubkey, &qj);
return !secp256k1_gej_is_infinity(&qj);
}
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
+ unsigned char b[32];
secp256k1_gej_t rp;
- secp256k1_ecmult_gen(&rp, nonce);
secp256k1_ge_t r;
+ secp256k1_scalar_t n;
+ int overflow = 0;
+
+ secp256k1_ecmult_gen(&rp, nonce);
secp256k1_ge_set_gej(&r, &rp);
- unsigned char b[32];
secp256k1_fe_normalize(&r.x);
secp256k1_fe_normalize(&r.y);
secp256k1_fe_get_b32(b, &r.x);
- int overflow = 0;
secp256k1_scalar_set_b32(&sig->r, b, &overflow);
if (secp256k1_scalar_is_zero(&sig->r)) {
/* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. */
@@ -206,7 +211,6 @@ static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_
}
if (recid)
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
- secp256k1_scalar_t n;
secp256k1_scalar_mul(&n, &sig->r, seckey);
secp256k1_scalar_add(&n, &n, message);
secp256k1_scalar_inverse(&sig->s, nonce);
@@ -224,9 +228,4 @@ static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_
return 1;
}
-static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s) {
- sig->r = *r;
- sig->s = *s;
-}
-
#endif
diff --git a/src/secp256k1/src/eckey_impl.h b/src/secp256k1/src/eckey_impl.h
index b3fa7d9bd2..3e06d05b47 100644
--- a/src/secp256k1/src/eckey_impl.h
+++ b/src/secp256k1/src/eckey_impl.h
@@ -51,13 +51,16 @@ static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char
}
static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen) {
+ unsigned char c[32] = {0};
const unsigned char *end = privkey + privkeylen;
+ int lenb = 0;
+ int len = 0;
+ int overflow = 0;
/* sequence header */
if (end < privkey+1 || *privkey != 0x30)
return 0;
privkey++;
/* sequence length constructor */
- int lenb = 0;
if (end < privkey+1 || !(*privkey & 0x80))
return 0;
lenb = *privkey & ~0x80; privkey++;
@@ -66,7 +69,6 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned
if (end < privkey+lenb)
return 0;
/* sequence length */
- int len = 0;
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0);
privkey += lenb;
if (end < privkey+len)
@@ -78,8 +80,6 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned
/* sequence element 1: octet string, up to 32 bytes */
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1])
return 0;
- int overflow = 0;
- unsigned char c[32] = {0};
memcpy(c + 32 - privkey[1], privkey + 2, privkey[1]);
secp256k1_scalar_set_b32(key, c, &overflow);
memset(c, 0, 32);
@@ -88,8 +88,9 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned
static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed) {
secp256k1_gej_t rp;
- secp256k1_ecmult_gen(&rp, key);
secp256k1_ge_t r;
+ int pubkeylen = 0;
+ secp256k1_ecmult_gen(&rp, key);
secp256k1_ge_set_gej(&r, &rp);
if (compressed) {
static const unsigned char begin[] = {
@@ -110,7 +111,6 @@ static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privke
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
- int pubkeylen = 0;
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1)) {
return 0;
}
@@ -137,7 +137,6 @@ static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privke
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
- int pubkeylen = 0;
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0)) {
return 0;
}
@@ -156,8 +155,8 @@ static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) {
secp256k1_gej_t pt;
- secp256k1_gej_set_ge(&pt, key);
secp256k1_scalar_t one;
+ secp256k1_gej_set_ge(&pt, key);
secp256k1_scalar_set_int(&one, 1);
secp256k1_ecmult(&pt, &pt, &one, tweak);
@@ -176,12 +175,12 @@ static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp
}
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) {
+ secp256k1_scalar_t zero;
+ secp256k1_gej_t pt;
if (secp256k1_scalar_is_zero(tweak))
return 0;
- secp256k1_scalar_t zero;
secp256k1_scalar_set_int(&zero, 0);
- secp256k1_gej_t pt;
secp256k1_gej_set_ge(&pt, key);
secp256k1_ecmult(&pt, &pt, tweak, &zero);
secp256k1_ge_set_gej(key, &pt);
diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h
index 48436316e1..849452c7a1 100644
--- a/src/secp256k1/src/ecmult_gen_impl.h
+++ b/src/secp256k1/src/ecmult_gen_impl.h
@@ -24,49 +24,53 @@ typedef struct {
* None of the resulting prec group elements have a known scalar, and neither do any of
* the intermediate sums while computing a*G.
*/
- secp256k1_fe_t prec[64][16][2]; /* prec[j][i] = (16^j * i * G + U_i).{x,y} */
+ secp256k1_ge_storage_t prec[64][16]; /* prec[j][i] = 16^j * i * G + U_i */
} secp256k1_ecmult_gen_consts_t;
static const secp256k1_ecmult_gen_consts_t *secp256k1_ecmult_gen_consts = NULL;
static void secp256k1_ecmult_gen_start(void) {
+ secp256k1_ge_t prec[1024];
+ secp256k1_gej_t gj;
+ secp256k1_gej_t nums_gej;
+ secp256k1_ecmult_gen_consts_t *ret;
+ int i, j;
if (secp256k1_ecmult_gen_consts != NULL)
return;
/* Allocate the precomputation table. */
- secp256k1_ecmult_gen_consts_t *ret = (secp256k1_ecmult_gen_consts_t*)checked_malloc(sizeof(secp256k1_ecmult_gen_consts_t));
+ ret = (secp256k1_ecmult_gen_consts_t*)checked_malloc(sizeof(secp256k1_ecmult_gen_consts_t));
/* get the generator */
- const secp256k1_ge_t *g = &secp256k1_ge_consts->g;
- secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g);
+ secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */
- secp256k1_gej_t nums_gej;
{
- static const unsigned char nums_b32[32] = "The scalar for this x is unknown";
+ static const unsigned char nums_b32[33] = "The scalar for this x is unknown";
secp256k1_fe_t nums_x;
- VERIFY_CHECK(secp256k1_fe_set_b32(&nums_x, nums_b32));
secp256k1_ge_t nums_ge;
+ VERIFY_CHECK(secp256k1_fe_set_b32(&nums_x, nums_b32));
VERIFY_CHECK(secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0));
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
/* Add G to make the bits in x uniformly distributed. */
- secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, g);
+ secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g);
}
/* compute prec. */
- secp256k1_ge_t prec[1024];
{
secp256k1_gej_t precj[1024]; /* Jacobian versions of prec. */
- secp256k1_gej_t gbase; gbase = gj; /* 16^j * G */
- secp256k1_gej_t numsbase; numsbase = nums_gej; /* 2^j * nums. */
- for (int j=0; j<64; j++) {
+ secp256k1_gej_t gbase;
+ secp256k1_gej_t numsbase;
+ gbase = gj; /* 16^j * G */
+ numsbase = nums_gej; /* 2^j * nums. */
+ for (j = 0; j < 64; j++) {
/* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */
precj[j*16] = numsbase;
- for (int i=1; i<16; i++) {
+ for (i = 1; i < 16; i++) {
secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase);
}
/* Multiply gbase by 16. */
- for (int i=0; i<4; i++) {
+ for (i = 0; i < 4; i++) {
secp256k1_gej_double_var(&gbase, &gbase);
}
/* Multiply numbase by 2. */
@@ -79,11 +83,9 @@ static void secp256k1_ecmult_gen_start(void) {
}
secp256k1_ge_set_all_gej_var(1024, prec, precj);
}
- for (int j=0; j<64; j++) {
- for (int i=0; i<16; i++) {
- VERIFY_CHECK(!secp256k1_ge_is_infinity(&prec[j*16 + i]));
- ret->prec[j][i][0] = prec[j*16 + i].x;
- ret->prec[j][i][1] = prec[j*16 + i].y;
+ for (j = 0; j < 64; j++) {
+ for (i = 0; i < 16; i++) {
+ secp256k1_ge_to_storage(&ret->prec[j][i], &prec[j*16 + i]);
}
}
@@ -92,26 +94,29 @@ static void secp256k1_ecmult_gen_start(void) {
}
static void secp256k1_ecmult_gen_stop(void) {
+ secp256k1_ecmult_gen_consts_t *c;
if (secp256k1_ecmult_gen_consts == NULL)
return;
- secp256k1_ecmult_gen_consts_t *c = (secp256k1_ecmult_gen_consts_t*)secp256k1_ecmult_gen_consts;
+ c = (secp256k1_ecmult_gen_consts_t*)secp256k1_ecmult_gen_consts;
secp256k1_ecmult_gen_consts = NULL;
free(c);
}
static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *gn) {
const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts;
- secp256k1_gej_set_infinity(r);
secp256k1_ge_t add;
- add.infinity = 0;
+ secp256k1_ge_storage_t adds;
int bits;
- for (int j=0; j<64; j++) {
+ int i, j;
+ secp256k1_gej_set_infinity(r);
+ add.infinity = 0;
+ for (j = 0; j < 64; j++) {
bits = secp256k1_scalar_get_bits(gn, j * 4, 4);
- for (int i=0; i<16; i++) {
- secp256k1_fe_cmov(&add.x, &c->prec[j][i][0], i == bits);
- secp256k1_fe_cmov(&add.y, &c->prec[j][i][1], i == bits);
+ for (i = 0; i < 16; i++) {
+ secp256k1_ge_storage_cmov(&adds, &c->prec[j][i], i == bits);
}
+ secp256k1_ge_from_storage(&add, &adds);
secp256k1_gej_add_ge(r, r, &add);
}
bits = 0;
diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h
index 345cfae733..ece0b0a459 100644
--- a/src/secp256k1/src/ecmult_impl.h
+++ b/src/secp256k1/src/ecmult_impl.h
@@ -37,22 +37,31 @@
* G is constant, so it only needs to be done once in advance.
*/
static void secp256k1_ecmult_table_precomp_gej_var(secp256k1_gej_t *pre, const secp256k1_gej_t *a, int w) {
+ secp256k1_gej_t d;
+ int i;
pre[0] = *a;
- secp256k1_gej_t d; secp256k1_gej_double_var(&d, &pre[0]);
- for (int i=1; i<(1 << (w-2)); i++)
+ secp256k1_gej_double_var(&d, &pre[0]);
+ for (i = 1; i < (1 << (w-2)); i++)
secp256k1_gej_add_var(&pre[i], &d, &pre[i-1]);
}
-static void secp256k1_ecmult_table_precomp_ge_var(secp256k1_ge_t *pre, const secp256k1_gej_t *a, int w) {
+static void secp256k1_ecmult_table_precomp_ge_storage_var(secp256k1_ge_storage_t *pre, const secp256k1_gej_t *a, int w) {
+ secp256k1_gej_t d;
+ int i;
const int table_size = 1 << (w-2);
secp256k1_gej_t *prej = checked_malloc(sizeof(secp256k1_gej_t) * table_size);
+ secp256k1_ge_t *prea = checked_malloc(sizeof(secp256k1_ge_t) * table_size);
prej[0] = *a;
- secp256k1_gej_t d; secp256k1_gej_double_var(&d, a);
- for (int i=1; i<table_size; i++) {
+ secp256k1_gej_double_var(&d, a);
+ for (i = 1; i < table_size; i++) {
secp256k1_gej_add_var(&prej[i], &d, &prej[i-1]);
}
- secp256k1_ge_set_all_gej_var(table_size, pre, prej);
+ secp256k1_ge_set_all_gej_var(table_size, prea, prej);
+ for (i = 0; i < table_size; i++) {
+ secp256k1_ge_to_storage(&pre[i], &prea[i]);
+ }
free(prej);
+ free(prea);
}
/** The number of entries a table with precomputed multiples needs to have. */
@@ -60,51 +69,63 @@ static void secp256k1_ecmult_table_precomp_ge_var(secp256k1_ge_t *pre, const sec
/** The following two macro retrieves a particular odd multiple from a table
* of precomputed multiples. */
-#define ECMULT_TABLE_GET(r,pre,n,w,neg) do { \
+#define ECMULT_TABLE_GET_GEJ(r,pre,n,w) do { \
VERIFY_CHECK(((n) & 1) == 1); \
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
if ((n) > 0) \
*(r) = (pre)[((n)-1)/2]; \
else \
- (neg)((r), &(pre)[(-(n)-1)/2]); \
+ secp256k1_gej_neg((r), &(pre)[(-(n)-1)/2]); \
+} while(0)
+#define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \
+ VERIFY_CHECK(((n) & 1) == 1); \
+ VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
+ VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
+ if ((n) > 0) \
+ secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \
+ else {\
+ secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \
+ secp256k1_ge_neg((r), (r)); \
+ } \
} while(0)
-
-#define ECMULT_TABLE_GET_GEJ(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_gej_neg)
-#define ECMULT_TABLE_GET_GE(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg)
typedef struct {
/* For accelerating the computation of a*P + b*G: */
- secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of the generator */
+ secp256k1_ge_storage_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of the generator */
#ifdef USE_ENDOMORPHISM
- secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of 2^128*generator */
+ secp256k1_ge_storage_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of 2^128*generator */
#endif
} secp256k1_ecmult_consts_t;
static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL;
static void secp256k1_ecmult_start(void) {
+ secp256k1_gej_t gj;
+ secp256k1_ecmult_consts_t *ret;
if (secp256k1_ecmult_consts != NULL)
return;
/* Allocate the precomputation table. */
- secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)checked_malloc(sizeof(secp256k1_ecmult_consts_t));
+ ret = (secp256k1_ecmult_consts_t*)checked_malloc(sizeof(secp256k1_ecmult_consts_t));
/* get the generator */
- const secp256k1_ge_t *g = &secp256k1_ge_consts->g;
- secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g);
+ secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
-#ifdef USE_ENDOMORPHISM
- /* calculate 2^128*generator */
- secp256k1_gej_t g_128j = gj;
- for (int i=0; i<128; i++)
- secp256k1_gej_double_var(&g_128j, &g_128j);
-#endif
/* precompute the tables with odd multiples */
- secp256k1_ecmult_table_precomp_ge_var(ret->pre_g, &gj, WINDOW_G);
+ secp256k1_ecmult_table_precomp_ge_storage_var(ret->pre_g, &gj, WINDOW_G);
+
#ifdef USE_ENDOMORPHISM
- secp256k1_ecmult_table_precomp_ge_var(ret->pre_g_128, &g_128j, WINDOW_G);
+ {
+ secp256k1_gej_t g_128j;
+ int i;
+ /* calculate 2^128*generator */
+ g_128j = gj;
+ for (i = 0; i < 128; i++)
+ secp256k1_gej_double_var(&g_128j, &g_128j);
+ secp256k1_ecmult_table_precomp_ge_storage_var(ret->pre_g_128, &g_128j, WINDOW_G);
+ }
#endif
/* Set the global pointer to the precomputation table. */
@@ -112,10 +133,11 @@ static void secp256k1_ecmult_start(void) {
}
static void secp256k1_ecmult_stop(void) {
+ secp256k1_ecmult_consts_t *c;
if (secp256k1_ecmult_consts == NULL)
return;
- secp256k1_ecmult_consts_t *c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts;
+ c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts;
secp256k1_ecmult_consts = NULL;
free(c);
}
@@ -129,16 +151,18 @@ static void secp256k1_ecmult_stop(void) {
*/
static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) {
secp256k1_scalar_t s = *a;
-
+ int set_bits = 0;
+ int bit = 0;
int sign = 1;
+
if (secp256k1_scalar_get_bits(&s, 255, 1)) {
secp256k1_scalar_negate(&s, &s);
sign = -1;
}
- int set_bits = 0;
- int bit = 0;
while (bit < 256) {
+ int now;
+ int word;
if (secp256k1_scalar_get_bits(&s, bit, 1) == 0) {
bit++;
continue;
@@ -146,11 +170,11 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w)
while (set_bits < bit) {
wnaf[set_bits++] = 0;
}
- int now = w;
+ now = w;
if (bit + now > 256) {
now = 256 - bit;
}
- int word = secp256k1_scalar_get_bits_var(&s, bit, now);
+ word = secp256k1_scalar_get_bits_var(&s, bit, now);
if (word & (1 << (w-1))) {
secp256k1_scalar_add_bit(&s, bit + w);
wnaf[set_bits++] = sign * (word - (1 << w));
@@ -163,58 +187,74 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w)
}
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) {
+ secp256k1_gej_t tmpj;
+ secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
+ secp256k1_ge_t tmpa;
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
-
#ifdef USE_ENDOMORPHISM
+ secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_scalar_t na_1, na_lam;
+ /* Splitted G factors. */
+ secp256k1_scalar_t ng_1, ng_128;
+ int wnaf_na_1[130];
+ int wnaf_na_lam[130];
+ int bits_na_1;
+ int bits_na_lam;
+ int wnaf_ng_1[129];
+ int bits_ng_1;
+ int wnaf_ng_128[129];
+ int bits_ng_128;
+#else
+ int wnaf_na[256];
+ int bits_na;
+ int wnaf_ng[257];
+ int bits_ng;
+#endif
+ int i;
+ int bits;
+
+#ifdef USE_ENDOMORPHISM
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
secp256k1_scalar_split_lambda_var(&na_1, &na_lam, na);
/* build wnaf representation for na_1 and na_lam. */
- int wnaf_na_1[130]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);
- int wnaf_na_lam[130]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A);
+ bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);
+ bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A);
VERIFY_CHECK(bits_na_1 <= 130);
VERIFY_CHECK(bits_na_lam <= 130);
- int bits = bits_na_1;
+ bits = bits_na_1;
if (bits_na_lam > bits) bits = bits_na_lam;
#else
/* build wnaf representation for na. */
- int wnaf_na[256]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
- int bits = bits_na;
+ bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
+ bits = bits_na;
#endif
/* calculate odd multiples of a */
- secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ecmult_table_precomp_gej_var(pre_a, a, WINDOW_A);
#ifdef USE_ENDOMORPHISM
- secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
- for (int i=0; i<ECMULT_TABLE_SIZE(WINDOW_A); i++)
+ for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++)
secp256k1_gej_mul_lambda(&pre_a_lam[i], &pre_a[i]);
- /* Splitted G factors. */
- secp256k1_scalar_t ng_1, ng_128;
-
/* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */
secp256k1_scalar_split_128(&ng_1, &ng_128, ng);
/* Build wnaf representation for ng_1 and ng_128 */
- int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G);
- int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G);
+ bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G);
+ bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G);
if (bits_ng_1 > bits) bits = bits_ng_1;
if (bits_ng_128 > bits) bits = bits_ng_128;
#else
- int wnaf_ng[257]; int bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, ng, WINDOW_G);
+ bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, ng, WINDOW_G);
if (bits_ng > bits) bits = bits_ng;
#endif
secp256k1_gej_set_infinity(r);
- secp256k1_gej_t tmpj;
- secp256k1_ge_t tmpa;
- for (int i=bits-1; i>=0; i--) {
- secp256k1_gej_double_var(r, r);
+ for (i = bits-1; i >= 0; i--) {
int n;
+ secp256k1_gej_double_var(r, r);
#ifdef USE_ENDOMORPHISM
if (i < bits_na_1 && (n = wnaf_na_1[i])) {
ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A);
@@ -225,11 +265,11 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
secp256k1_gej_add_var(r, r, &tmpj);
}
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
- ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G);
+ ECMULT_TABLE_GET_GE_STORAGE(&tmpa, c->pre_g, n, WINDOW_G);
secp256k1_gej_add_ge_var(r, r, &tmpa);
}
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
- ECMULT_TABLE_GET_GE(&tmpa, c->pre_g_128, n, WINDOW_G);
+ ECMULT_TABLE_GET_GE_STORAGE(&tmpa, c->pre_g_128, n, WINDOW_G);
secp256k1_gej_add_ge_var(r, r, &tmpa);
}
#else
@@ -238,7 +278,7 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
secp256k1_gej_add_var(r, r, &tmpj);
}
if (i < bits_ng && (n = wnaf_ng[i])) {
- ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G);
+ ECMULT_TABLE_GET_GE_STORAGE(&tmpa, c->pre_g, n, WINDOW_G);
secp256k1_gej_add_ge_var(r, r, &tmpa);
}
#endif
diff --git a/src/secp256k1/src/field.h b/src/secp256k1/src/field.h
index 14e2b813c1..9e6d7d3c04 100644
--- a/src/secp256k1/src/field.h
+++ b/src/secp256k1/src/field.h
@@ -30,21 +30,6 @@
#error "Please select field implementation"
#endif
-typedef struct {
-#ifndef USE_NUM_NONE
- secp256k1_num_t p;
-#endif
- secp256k1_fe_t order;
-} secp256k1_fe_consts_t;
-
-static const secp256k1_fe_consts_t *secp256k1_fe_consts = NULL;
-
-/** Initialize field element precomputation data. */
-static void secp256k1_fe_start(void);
-
-/** Unload field element precomputation data. */
-static void secp256k1_fe_stop(void);
-
/** Normalize a field element. */
static void secp256k1_fe_normalize(secp256k1_fe_t *r);
@@ -117,15 +102,15 @@ static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a);
/** Calculate the (modular) inverses of a batch of field elements. Requires the inputs' magnitudes to be
* at most 8. The output magnitudes are 1 (but not guaranteed to be normalized). The inputs and
* outputs must not overlap in memory. */
-static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t r[len], const secp256k1_fe_t a[len]);
+static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t *r, const secp256k1_fe_t *a);
-/** Convert a field element to a hexadecimal string. */
-static void secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a);
+/** Convert a field element to the storage type. */
+static void secp256k1_fe_to_storage(secp256k1_fe_storage_t *r, const secp256k1_fe_t*);
-/** Convert a hexadecimal string to a field element. */
-static int secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen);
+/** Convert a field element back from the storage type. */
+static void secp256k1_fe_from_storage(secp256k1_fe_t *r, const secp256k1_fe_storage_t*);
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
-static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag);
+static void secp256k1_fe_storage_cmov(secp256k1_fe_storage_t *r, const secp256k1_fe_storage_t *a, int flag);
#endif
diff --git a/src/secp256k1/src/field_10x26.h b/src/secp256k1/src/field_10x26.h
index 66fb3f2563..44bce6525d 100644
--- a/src/secp256k1/src/field_10x26.h
+++ b/src/secp256k1/src/field_10x26.h
@@ -18,4 +18,30 @@ typedef struct {
#endif
} secp256k1_fe_t;
+/* Unpacks a constant into a overlapping multi-limbed FE element. */
+#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \
+ (d0) & 0x3FFFFFFUL, \
+ ((d0) >> 26) | ((d1) & 0xFFFFFUL) << 6, \
+ ((d1) >> 20) | ((d2) & 0x3FFFUL) << 12, \
+ ((d2) >> 14) | ((d3) & 0xFFUL) << 18, \
+ ((d3) >> 8) | ((d4) & 0x3) << 24, \
+ ((d4) >> 2) & 0x3FFFFFFUL, \
+ ((d4) >> 28) | ((d5) & 0x3FFFFFUL) << 4, \
+ ((d5) >> 22) | ((d6) & 0xFFFF) << 10, \
+ ((d6) >> 16) | ((d7) & 0x3FF) << 16, \
+ ((d7) >> 10) \
+}
+
+#ifdef VERIFY
+#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1}
+#else
+#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))}
+#endif
+
+typedef struct {
+ uint32_t n[8];
+} secp256k1_fe_storage_t;
+
+#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}
+
#endif
diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h
index 9ef60a807a..0afbb18a4a 100644
--- a/src/secp256k1/src/field_10x26_impl.h
+++ b/src/secp256k1/src/field_10x26_impl.h
@@ -13,9 +13,6 @@
#include "num.h"
#include "field.h"
-static void secp256k1_fe_inner_start(void) {}
-static void secp256k1_fe_inner_stop(void) {}
-
#ifdef VERIFY
static void secp256k1_fe_verify(const secp256k1_fe_t *a) {
const uint32_t *d = a->n;
@@ -54,8 +51,8 @@ static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
/* Reduce t9 at the start so there will be at most a single carry from the first pass */
- uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
uint32_t m;
+ uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x3D1UL; t1 += (x << 6);
@@ -140,8 +137,8 @@ static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
/* Reduce t9 at the start so there will be at most a single carry from the first pass */
- uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
uint32_t m;
+ uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x3D1UL; t1 += (x << 6);
@@ -195,12 +192,12 @@ static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
- /* Reduce t9 at the start so there will be at most a single carry from the first pass */
- uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
-
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
uint32_t z0, z1;
+ /* Reduce t9 at the start so there will be at most a single carry from the first pass */
+ uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
+
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x3D1UL; t1 += (x << 6);
t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; z0 = t0; z1 = t0 ^ 0x3D0UL;
@@ -221,23 +218,36 @@ static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
}
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe_t *r) {
- uint32_t t0 = r->n[0], t9 = r->n[9];
+ uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
+ uint32_t z0, z1;
+ uint32_t x;
+
+ t0 = r->n[0];
+ t9 = r->n[9];
/* Reduce t9 at the start so there will be at most a single carry from the first pass */
- uint32_t x = t9 >> 22;
+ x = t9 >> 22;
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x3D1UL;
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
- uint32_t z0 = t0 & 0x3FFFFFFUL, z1 = z0 ^ 0x3D0UL;
+ z0 = t0 & 0x3FFFFFFUL;
+ z1 = z0 ^ 0x3D0UL;
/* Fast return path should catch the majority of cases */
if ((z0 != 0UL) & (z1 != 0x3FFFFFFUL))
return 0;
- uint32_t t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
- t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8];
+ t1 = r->n[1];
+ t2 = r->n[2];
+ t3 = r->n[3];
+ t4 = r->n[4];
+ t5 = r->n[5];
+ t6 = r->n[6];
+ t7 = r->n[7];
+ t8 = r->n[8];
+
t9 &= 0x03FFFFFUL;
t1 += (x << 6);
@@ -269,11 +279,11 @@ SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
}
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
+ const uint32_t *t = a->n;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
- const uint32_t *t = a->n;
return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0;
}
@@ -286,23 +296,25 @@ SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
}
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe_t *a) {
+ int i;
#ifdef VERIFY
a->magnitude = 0;
a->normalized = 1;
#endif
- for (int i=0; i<10; i++) {
+ for (i=0; i<10; i++) {
a->n[i] = 0;
}
}
static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+ int i;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
VERIFY_CHECK(b->normalized);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
#endif
- for (int i = 9; i >= 0; i--) {
+ for (i = 9; i >= 0; i--) {
if (a->n[i] > b->n[i]) return 1;
if (a->n[i] < b->n[i]) return -1;
}
@@ -310,10 +322,12 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b
}
static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
+ int i;
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
- for (int i=0; i<32; i++) {
- for (int j=0; j<4; j++) {
+ for (i=0; i<32; i++) {
+ int j;
+ for (j=0; j<4; j++) {
int limb = (8*i+2*j)/26;
int shift = (8*i+2*j)%26;
r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift;
@@ -332,13 +346,15 @@ static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) {
+ int i;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
- for (int i=0; i<32; i++) {
+ for (i=0; i<32; i++) {
+ int j;
int c = 0;
- for (int j=0; j<4; j++) {
+ for (j=0; j<4; j++) {
int limb = (8*i+2*j)/26;
int shift = (8*i+2*j)%26;
c |= ((a->n[limb] >> shift) & 0x3) << (2 * j);
@@ -415,6 +431,11 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1
#endif
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b) {
+ uint64_t c, d;
+ uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8;
+ uint32_t t9, t1, t0, t2, t3, t4, t5, t6, t7;
+ const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL;
+
VERIFY_BITS(a[0], 30);
VERIFY_BITS(a[1], 30);
VERIFY_BITS(a[2], 30);
@@ -436,14 +457,11 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
VERIFY_BITS(b[8], 30);
VERIFY_BITS(b[9], 26);
- const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL;
/** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n.
* px is a shorthand for sum(a[i]*b[x-i], i=0..x).
* Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0].
*/
- uint64_t c, d;
-
d = (uint64_t)a[0] * b[9]
+ (uint64_t)a[1] * b[8]
+ (uint64_t)a[2] * b[7]
@@ -456,7 +474,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[9] * b[0];
/* VERIFY_BITS(d, 64); */
/* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
- uint32_t t9 = d & M; d >>= 26;
+ t9 = d & M; d >>= 26;
VERIFY_BITS(t9, 26);
VERIFY_BITS(d, 38);
/* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
@@ -475,12 +493,12 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[9] * b[1];
VERIFY_BITS(d, 63);
/* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
- uint64_t u0 = d & M; d >>= 26; c += u0 * R0;
+ u0 = d & M; d >>= 26; c += u0 * R0;
VERIFY_BITS(u0, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 61);
/* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
- uint32_t t0 = c & M; c >>= 26; c += u0 * R1;
+ t0 = c & M; c >>= 26; c += u0 * R1;
VERIFY_BITS(t0, 26);
VERIFY_BITS(c, 37);
/* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
@@ -500,12 +518,12 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[9] * b[2];
VERIFY_BITS(d, 63);
/* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
- uint64_t u1 = d & M; d >>= 26; c += u1 * R0;
+ u1 = d & M; d >>= 26; c += u1 * R0;
VERIFY_BITS(u1, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 63);
/* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
- uint32_t t1 = c & M; c >>= 26; c += u1 * R1;
+ t1 = c & M; c >>= 26; c += u1 * R1;
VERIFY_BITS(t1, 26);
VERIFY_BITS(c, 38);
/* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
@@ -525,12 +543,12 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[9] * b[3];
VERIFY_BITS(d, 63);
/* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
- uint64_t u2 = d & M; d >>= 26; c += u2 * R0;
+ u2 = d & M; d >>= 26; c += u2 * R0;
VERIFY_BITS(u2, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 63);
/* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
- uint32_t t2 = c & M; c >>= 26; c += u2 * R1;
+ t2 = c & M; c >>= 26; c += u2 * R1;
VERIFY_BITS(t2, 26);
VERIFY_BITS(c, 38);
/* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
@@ -550,12 +568,12 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[9] * b[4];
VERIFY_BITS(d, 63);
/* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
- uint64_t u3 = d & M; d >>= 26; c += u3 * R0;
+ u3 = d & M; d >>= 26; c += u3 * R0;
VERIFY_BITS(u3, 26);
VERIFY_BITS(d, 37);
/* VERIFY_BITS(c, 64); */
/* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
- uint32_t t3 = c & M; c >>= 26; c += u3 * R1;
+ t3 = c & M; c >>= 26; c += u3 * R1;
VERIFY_BITS(t3, 26);
VERIFY_BITS(c, 39);
/* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
@@ -575,12 +593,12 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[9] * b[5];
VERIFY_BITS(d, 62);
/* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
- uint64_t u4 = d & M; d >>= 26; c += u4 * R0;
+ u4 = d & M; d >>= 26; c += u4 * R0;
VERIFY_BITS(u4, 26);
VERIFY_BITS(d, 36);
/* VERIFY_BITS(c, 64); */
/* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
- uint32_t t4 = c & M; c >>= 26; c += u4 * R1;
+ t4 = c & M; c >>= 26; c += u4 * R1;
VERIFY_BITS(t4, 26);
VERIFY_BITS(c, 39);
/* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
@@ -600,12 +618,12 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[9] * b[6];
VERIFY_BITS(d, 62);
/* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
- uint64_t u5 = d & M; d >>= 26; c += u5 * R0;
+ u5 = d & M; d >>= 26; c += u5 * R0;
VERIFY_BITS(u5, 26);
VERIFY_BITS(d, 36);
/* VERIFY_BITS(c, 64); */
/* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
- uint32_t t5 = c & M; c >>= 26; c += u5 * R1;
+ t5 = c & M; c >>= 26; c += u5 * R1;
VERIFY_BITS(t5, 26);
VERIFY_BITS(c, 39);
/* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
@@ -625,12 +643,12 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[9] * b[7];
VERIFY_BITS(d, 61);
/* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
- uint64_t u6 = d & M; d >>= 26; c += u6 * R0;
+ u6 = d & M; d >>= 26; c += u6 * R0;
VERIFY_BITS(u6, 26);
VERIFY_BITS(d, 35);
/* VERIFY_BITS(c, 64); */
/* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
- uint32_t t6 = c & M; c >>= 26; c += u6 * R1;
+ t6 = c & M; c >>= 26; c += u6 * R1;
VERIFY_BITS(t6, 26);
VERIFY_BITS(c, 39);
/* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
@@ -651,13 +669,13 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[9] * b[8];
VERIFY_BITS(d, 58);
/* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
- uint64_t u7 = d & M; d >>= 26; c += u7 * R0;
+ u7 = d & M; d >>= 26; c += u7 * R0;
VERIFY_BITS(u7, 26);
VERIFY_BITS(d, 32);
/* VERIFY_BITS(c, 64); */
VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL);
/* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
- uint32_t t7 = c & M; c >>= 26; c += u7 * R1;
+ t7 = c & M; c >>= 26; c += u7 * R1;
VERIFY_BITS(t7, 26);
VERIFY_BITS(c, 38);
/* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
@@ -678,7 +696,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
d += (uint64_t)a[9] * b[9];
VERIFY_BITS(d, 57);
/* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- uint64_t u8 = d & M; d >>= 26; c += u8 * R0;
+ u8 = d & M; d >>= 26; c += u8 * R0;
VERIFY_BITS(u8, 26);
VERIFY_BITS(d, 31);
/* VERIFY_BITS(c, 64); */
@@ -742,6 +760,11 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t
}
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a) {
+ uint64_t c, d;
+ uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8;
+ uint32_t t9, t0, t1, t2, t3, t4, t5, t6, t7;
+ const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL;
+
VERIFY_BITS(a[0], 30);
VERIFY_BITS(a[1], 30);
VERIFY_BITS(a[2], 30);
@@ -753,14 +776,11 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
VERIFY_BITS(a[8], 30);
VERIFY_BITS(a[9], 26);
- const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL;
/** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n.
* px is a shorthand for sum(a[i]*a[x-i], i=0..x).
* Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0].
*/
- uint64_t c, d;
-
d = (uint64_t)(a[0]*2) * a[9]
+ (uint64_t)(a[1]*2) * a[8]
+ (uint64_t)(a[2]*2) * a[7]
@@ -768,7 +788,7 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
+ (uint64_t)(a[4]*2) * a[5];
/* VERIFY_BITS(d, 64); */
/* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
- uint32_t t9 = d & M; d >>= 26;
+ t9 = d & M; d >>= 26;
VERIFY_BITS(t9, 26);
VERIFY_BITS(d, 38);
/* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
@@ -783,12 +803,12 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[5] * a[5];
VERIFY_BITS(d, 63);
/* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
- uint64_t u0 = d & M; d >>= 26; c += u0 * R0;
+ u0 = d & M; d >>= 26; c += u0 * R0;
VERIFY_BITS(u0, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 61);
/* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
- uint32_t t0 = c & M; c >>= 26; c += u0 * R1;
+ t0 = c & M; c >>= 26; c += u0 * R1;
VERIFY_BITS(t0, 26);
VERIFY_BITS(c, 37);
/* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
@@ -803,12 +823,12 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
+ (uint64_t)(a[5]*2) * a[6];
VERIFY_BITS(d, 63);
/* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
- uint64_t u1 = d & M; d >>= 26; c += u1 * R0;
+ u1 = d & M; d >>= 26; c += u1 * R0;
VERIFY_BITS(u1, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 63);
/* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
- uint32_t t1 = c & M; c >>= 26; c += u1 * R1;
+ t1 = c & M; c >>= 26; c += u1 * R1;
VERIFY_BITS(t1, 26);
VERIFY_BITS(c, 38);
/* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
@@ -824,12 +844,12 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[6] * a[6];
VERIFY_BITS(d, 63);
/* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
- uint64_t u2 = d & M; d >>= 26; c += u2 * R0;
+ u2 = d & M; d >>= 26; c += u2 * R0;
VERIFY_BITS(u2, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 63);
/* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
- uint32_t t2 = c & M; c >>= 26; c += u2 * R1;
+ t2 = c & M; c >>= 26; c += u2 * R1;
VERIFY_BITS(t2, 26);
VERIFY_BITS(c, 38);
/* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
@@ -844,12 +864,12 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
+ (uint64_t)(a[6]*2) * a[7];
VERIFY_BITS(d, 63);
/* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
- uint64_t u3 = d & M; d >>= 26; c += u3 * R0;
+ u3 = d & M; d >>= 26; c += u3 * R0;
VERIFY_BITS(u3, 26);
VERIFY_BITS(d, 37);
/* VERIFY_BITS(c, 64); */
/* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
- uint32_t t3 = c & M; c >>= 26; c += u3 * R1;
+ t3 = c & M; c >>= 26; c += u3 * R1;
VERIFY_BITS(t3, 26);
VERIFY_BITS(c, 39);
/* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
@@ -865,12 +885,12 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[7] * a[7];
VERIFY_BITS(d, 62);
/* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
- uint64_t u4 = d & M; d >>= 26; c += u4 * R0;
+ u4 = d & M; d >>= 26; c += u4 * R0;
VERIFY_BITS(u4, 26);
VERIFY_BITS(d, 36);
/* VERIFY_BITS(c, 64); */
/* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
- uint32_t t4 = c & M; c >>= 26; c += u4 * R1;
+ t4 = c & M; c >>= 26; c += u4 * R1;
VERIFY_BITS(t4, 26);
VERIFY_BITS(c, 39);
/* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
@@ -885,12 +905,12 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
+ (uint64_t)(a[7]*2) * a[8];
VERIFY_BITS(d, 62);
/* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
- uint64_t u5 = d & M; d >>= 26; c += u5 * R0;
+ u5 = d & M; d >>= 26; c += u5 * R0;
VERIFY_BITS(u5, 26);
VERIFY_BITS(d, 36);
/* VERIFY_BITS(c, 64); */
/* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
- uint32_t t5 = c & M; c >>= 26; c += u5 * R1;
+ t5 = c & M; c >>= 26; c += u5 * R1;
VERIFY_BITS(t5, 26);
VERIFY_BITS(c, 39);
/* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
@@ -906,12 +926,12 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
+ (uint64_t)a[8] * a[8];
VERIFY_BITS(d, 61);
/* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
- uint64_t u6 = d & M; d >>= 26; c += u6 * R0;
+ u6 = d & M; d >>= 26; c += u6 * R0;
VERIFY_BITS(u6, 26);
VERIFY_BITS(d, 35);
/* VERIFY_BITS(c, 64); */
/* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
- uint32_t t6 = c & M; c >>= 26; c += u6 * R1;
+ t6 = c & M; c >>= 26; c += u6 * R1;
VERIFY_BITS(t6, 26);
VERIFY_BITS(c, 39);
/* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
@@ -927,13 +947,13 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
d += (uint64_t)(a[8]*2) * a[9];
VERIFY_BITS(d, 58);
/* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
- uint64_t u7 = d & M; d >>= 26; c += u7 * R0;
+ u7 = d & M; d >>= 26; c += u7 * R0;
VERIFY_BITS(u7, 26);
VERIFY_BITS(d, 32);
/* VERIFY_BITS(c, 64); */
VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL);
/* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
- uint32_t t7 = c & M; c >>= 26; c += u7 * R1;
+ t7 = c & M; c >>= 26; c += u7 * R1;
VERIFY_BITS(t7, 26);
VERIFY_BITS(c, 38);
/* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
@@ -950,7 +970,7 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
d += (uint64_t)a[9] * a[9];
VERIFY_BITS(d, 57);
/* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- uint64_t u8 = d & M; d >>= 26; c += u8 * R0;
+ u8 = d & M; d >>= 26; c += u8 * R0;
VERIFY_BITS(u8, 26);
VERIFY_BITS(d, 31);
/* VERIFY_BITS(c, 64); */
@@ -1043,8 +1063,10 @@ static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
#endif
}
-static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag) {
- uint32_t mask0 = flag + ~((uint32_t)0), mask1 = ~mask0;
+static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage_t *r, const secp256k1_fe_storage_t *a, int flag) {
+ uint32_t mask0, mask1;
+ mask0 = flag + ~((uint32_t)0);
+ mask1 = ~mask0;
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1);
r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
@@ -1053,13 +1075,36 @@ static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int fl
r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1);
r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1);
r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1);
- r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1);
- r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1);
+}
+
+static void secp256k1_fe_to_storage(secp256k1_fe_storage_t *r, const secp256k1_fe_t *a) {
#ifdef VERIFY
- if (flag) {
- r->magnitude = a->magnitude;
- r->normalized = a->normalized;
- }
+ VERIFY_CHECK(a->normalized);
+#endif
+ r->n[0] = a->n[0] | a->n[1] << 26;
+ r->n[1] = a->n[1] >> 6 | a->n[2] << 20;
+ r->n[2] = a->n[2] >> 12 | a->n[3] << 14;
+ r->n[3] = a->n[3] >> 18 | a->n[4] << 8;
+ r->n[4] = a->n[4] >> 24 | a->n[5] << 2 | a->n[6] << 28;
+ r->n[5] = a->n[6] >> 4 | a->n[7] << 22;
+ r->n[6] = a->n[7] >> 10 | a->n[8] << 16;
+ r->n[7] = a->n[8] >> 16 | a->n[9] << 10;
+}
+
+static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe_t *r, const secp256k1_fe_storage_t *a) {
+ r->n[0] = a->n[0] & 0x3FFFFFFUL;
+ r->n[1] = a->n[0] >> 26 | ((a->n[1] << 6) & 0x3FFFFFFUL);
+ r->n[2] = a->n[1] >> 20 | ((a->n[2] << 12) & 0x3FFFFFFUL);
+ r->n[3] = a->n[2] >> 14 | ((a->n[3] << 18) & 0x3FFFFFFUL);
+ r->n[4] = a->n[3] >> 8 | ((a->n[4] << 24) & 0x3FFFFFFUL);
+ r->n[5] = (a->n[4] >> 2) & 0x3FFFFFFUL;
+ r->n[6] = a->n[4] >> 28 | ((a->n[5] << 4) & 0x3FFFFFFUL);
+ r->n[7] = a->n[5] >> 22 | ((a->n[6] << 10) & 0x3FFFFFFUL);
+ r->n[8] = a->n[6] >> 16 | ((a->n[7] << 16) & 0x3FFFFFFUL);
+ r->n[9] = a->n[7] >> 10;
+#ifdef VERIFY
+ r->magnitude = 1;
+ r->normalized = 1;
#endif
}
diff --git a/src/secp256k1/src/field_5x52.h b/src/secp256k1/src/field_5x52.h
index aeb0a6a1e8..4513d36f49 100644
--- a/src/secp256k1/src/field_5x52.h
+++ b/src/secp256k1/src/field_5x52.h
@@ -18,4 +18,30 @@ typedef struct {
#endif
} secp256k1_fe_t;
+/* Unpacks a constant into a overlapping multi-limbed FE element. */
+#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \
+ (d0) | ((uint64_t)(d1) & 0xFFFFFUL) << 32, \
+ ((d1) >> 20) | ((uint64_t)(d2)) << 12 | ((uint64_t)(d3) & 0xFFUL) << 44, \
+ ((d3) >> 8) | ((uint64_t)(d4) & 0xFFFFFFFUL) << 24, \
+ ((d4) >> 28) | ((uint64_t)(d5)) << 4 | ((uint64_t)(d6) & 0xFFFFUL) << 36, \
+ ((d6) >> 16) | ((uint64_t)(d7)) << 16 \
+}
+
+#ifdef VERIFY
+#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1}
+#else
+#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))}
+#endif
+
+typedef struct {
+ uint64_t n[4];
+} secp256k1_fe_storage_t;
+
+#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \
+ (d0) | ((uint64_t)(d1)) << 32, \
+ (d2) | ((uint64_t)(d3)) << 32, \
+ (d4) | ((uint64_t)(d5)) << 32, \
+ (d6) | ((uint64_t)(d7)) << 32 \
+}}
+
#endif
diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h
index 4db9e6f5ff..2f9c8704a8 100644
--- a/src/secp256k1/src/field_5x52_impl.h
+++ b/src/secp256k1/src/field_5x52_impl.h
@@ -30,13 +30,11 @@
* output.
*/
-static void secp256k1_fe_inner_start(void) {}
-static void secp256k1_fe_inner_stop(void) {}
-
#ifdef VERIFY
static void secp256k1_fe_verify(const secp256k1_fe_t *a) {
const uint64_t *d = a->n;
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
+ /* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m);
r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m);
r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m);
@@ -62,8 +60,8 @@ static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
- uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
uint64_t m;
+ uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x1000003D1ULL;
@@ -129,8 +127,8 @@ static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
- uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
uint64_t m;
+ uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x1000003D1ULL;
@@ -172,12 +170,12 @@ static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
- /* Reduce t4 at the start so there will be at most a single carry from the first pass */
- uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
-
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
uint64_t z0, z1;
+ /* Reduce t4 at the start so there will be at most a single carry from the first pass */
+ uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
+
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x1000003D1ULL;
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL;
@@ -193,22 +191,31 @@ static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
}
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe_t *r) {
- uint64_t t0 = r->n[0], t4 = r->n[4];
+ uint64_t t0, t1, t2, t3, t4;
+ uint64_t z0, z1;
+ uint64_t x;
+
+ t0 = r->n[0];
+ t4 = r->n[4];
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
- uint64_t x = t4 >> 48;
+ x = t4 >> 48;
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x1000003D1ULL;
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
- uint64_t z0 = t0 & 0xFFFFFFFFFFFFFULL, z1 = z0 ^ 0x1000003D0ULL;
+ z0 = t0 & 0xFFFFFFFFFFFFFULL;
+ z1 = z0 ^ 0x1000003D0ULL;
/* Fast return path should catch the majority of cases */
if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL))
return 0;
- uint64_t t1 = r->n[1], t2 = r->n[2], t3 = r->n[3];
+ t1 = r->n[1];
+ t2 = r->n[2];
+ t3 = r->n[3];
+
t4 &= 0x0FFFFFFFFFFFFULL;
t1 += (t0 >> 52); t0 = z0;
@@ -234,11 +241,11 @@ SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
}
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
+ const uint64_t *t = a->n;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
- const uint64_t *t = a->n;
return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0;
}
@@ -251,23 +258,25 @@ SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
}
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe_t *a) {
+ int i;
#ifdef VERIFY
a->magnitude = 0;
a->normalized = 1;
#endif
- for (int i=0; i<5; i++) {
+ for (i=0; i<5; i++) {
a->n[i] = 0;
}
}
static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+ int i;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
VERIFY_CHECK(b->normalized);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
#endif
- for (int i = 4; i >= 0; i--) {
+ for (i = 4; i >= 0; i--) {
if (a->n[i] > b->n[i]) return 1;
if (a->n[i] < b->n[i]) return -1;
}
@@ -275,9 +284,11 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b
}
static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
+ int i;
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
- for (int i=0; i<32; i++) {
- for (int j=0; j<2; j++) {
+ for (i=0; i<32; i++) {
+ int j;
+ for (j=0; j<2; j++) {
int limb = (8*i+4*j)/52;
int shift = (8*i+4*j)%52;
r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift;
@@ -296,13 +307,15 @@ static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) {
+ int i;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
- for (int i=0; i<32; i++) {
+ for (i=0; i<32; i++) {
+ int j;
int c = 0;
- for (int j=0; j<2; j++) {
+ for (j=0; j<2; j++) {
int limb = (8*i+4*j)/52;
int shift = (8*i+4*j)%52;
c |= ((a->n[limb] >> shift) & 0xF) << (4 * j);
@@ -386,18 +399,35 @@ static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
#endif
}
-static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag) {
- uint64_t mask0 = flag + ~((uint64_t)0), mask1 = ~mask0;
+static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage_t *r, const secp256k1_fe_storage_t *a, int flag) {
+ uint64_t mask0, mask1;
+ mask0 = flag + ~((uint64_t)0);
+ mask1 = ~mask0;
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1);
r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
- r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
+}
+
+static void secp256k1_fe_to_storage(secp256k1_fe_storage_t *r, const secp256k1_fe_t *a) {
#ifdef VERIFY
- if (flag) {
- r->magnitude = a->magnitude;
- r->normalized = a->normalized;
- }
+ VERIFY_CHECK(a->normalized);
+#endif
+ r->n[0] = a->n[0] | a->n[1] << 52;
+ r->n[1] = a->n[1] >> 12 | a->n[2] << 40;
+ r->n[2] = a->n[2] >> 24 | a->n[3] << 28;
+ r->n[3] = a->n[3] >> 36 | a->n[4] << 16;
+}
+
+static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe_t *r, const secp256k1_fe_storage_t *a) {
+ r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL;
+ r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL);
+ r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL);
+ r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL);
+ r->n[4] = a->n[3] >> 16;
+#ifdef VERIFY
+ r->magnitude = 1;
+ r->normalized = 1;
#endif
}
diff --git a/src/secp256k1/src/field_5x52_int128_impl.h b/src/secp256k1/src/field_5x52_int128_impl.h
index ec631833cf..9280bb5ea2 100644
--- a/src/secp256k1/src/field_5x52_int128_impl.h
+++ b/src/secp256k1/src/field_5x52_int128_impl.h
@@ -16,6 +16,11 @@
#endif
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
+ uint128_t c, d;
+ uint64_t t3, t4, tx, u0;
+ uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
+ const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
+
VERIFY_BITS(a[0], 56);
VERIFY_BITS(a[1], 56);
VERIFY_BITS(a[2], 56);
@@ -28,63 +33,58 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
VERIFY_BITS(b[4], 52);
VERIFY_CHECK(r != b);
- const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
/* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n.
* px is a shorthand for sum(a[i]*b[x-i], i=0..x).
* Note that [x 0 0 0 0 0] = [x*R].
*/
- uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
-
- __int128 c, d;
-
- d = (__int128)a0 * b[3]
- + (__int128)a1 * b[2]
- + (__int128)a2 * b[1]
- + (__int128)a3 * b[0];
+ d = (uint128_t)a0 * b[3]
+ + (uint128_t)a1 * b[2]
+ + (uint128_t)a2 * b[1]
+ + (uint128_t)a3 * b[0];
VERIFY_BITS(d, 114);
/* [d 0 0 0] = [p3 0 0 0] */
- c = (__int128)a4 * b[4];
+ c = (uint128_t)a4 * b[4];
VERIFY_BITS(c, 112);
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
d += (c & M) * R; c >>= 52;
VERIFY_BITS(d, 115);
VERIFY_BITS(c, 60);
/* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- uint64_t t3 = d & M; d >>= 52;
+ t3 = d & M; d >>= 52;
VERIFY_BITS(t3, 52);
VERIFY_BITS(d, 63);
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- d += (__int128)a0 * b[4]
- + (__int128)a1 * b[3]
- + (__int128)a2 * b[2]
- + (__int128)a3 * b[1]
- + (__int128)a4 * b[0];
+ d += (uint128_t)a0 * b[4]
+ + (uint128_t)a1 * b[3]
+ + (uint128_t)a2 * b[2]
+ + (uint128_t)a3 * b[1]
+ + (uint128_t)a4 * b[0];
VERIFY_BITS(d, 115);
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
d += c * R;
VERIFY_BITS(d, 116);
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- uint64_t t4 = d & M; d >>= 52;
+ t4 = d & M; d >>= 52;
VERIFY_BITS(t4, 52);
VERIFY_BITS(d, 64);
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- uint64_t tx = (t4 >> 48); t4 &= (M >> 4);
+ tx = (t4 >> 48); t4 &= (M >> 4);
VERIFY_BITS(tx, 4);
VERIFY_BITS(t4, 48);
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- c = (__int128)a0 * b[0];
+ c = (uint128_t)a0 * b[0];
VERIFY_BITS(c, 112);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
- d += (__int128)a1 * b[4]
- + (__int128)a2 * b[3]
- + (__int128)a3 * b[2]
- + (__int128)a4 * b[1];
+ d += (uint128_t)a1 * b[4]
+ + (uint128_t)a2 * b[3]
+ + (uint128_t)a3 * b[2]
+ + (uint128_t)a4 * b[1];
VERIFY_BITS(d, 115);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- uint64_t u0 = d & M; d >>= 52;
+ u0 = d & M; d >>= 52;
VERIFY_BITS(u0, 52);
VERIFY_BITS(d, 63);
/* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
@@ -92,7 +92,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
u0 = (u0 << 4) | tx;
VERIFY_BITS(u0, 56);
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- c += (__int128)u0 * (R >> 4);
+ c += (uint128_t)u0 * (R >> 4);
VERIFY_BITS(c, 115);
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
r[0] = c & M; c >>= 52;
@@ -100,13 +100,13 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
VERIFY_BITS(c, 61);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
- c += (__int128)a0 * b[1]
- + (__int128)a1 * b[0];
+ c += (uint128_t)a0 * b[1]
+ + (uint128_t)a1 * b[0];
VERIFY_BITS(c, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
- d += (__int128)a2 * b[4]
- + (__int128)a3 * b[3]
- + (__int128)a4 * b[2];
+ d += (uint128_t)a2 * b[4]
+ + (uint128_t)a3 * b[3]
+ + (uint128_t)a4 * b[2];
VERIFY_BITS(d, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
c += (d & M) * R; d >>= 52;
@@ -118,13 +118,13 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
VERIFY_BITS(c, 63);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (__int128)a0 * b[2]
- + (__int128)a1 * b[1]
- + (__int128)a2 * b[0];
+ c += (uint128_t)a0 * b[2]
+ + (uint128_t)a1 * b[1]
+ + (uint128_t)a2 * b[0];
VERIFY_BITS(c, 114);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
- d += (__int128)a3 * b[4]
- + (__int128)a4 * b[3];
+ d += (uint128_t)a3 * b[4]
+ + (uint128_t)a4 * b[3];
VERIFY_BITS(d, 114);
/* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
c += (d & M) * R; d >>= 52;
@@ -153,64 +153,64 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
}
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
+ uint128_t c, d;
+ uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
+ int64_t t3, t4, tx, u0;
+ const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
+
VERIFY_BITS(a[0], 56);
VERIFY_BITS(a[1], 56);
VERIFY_BITS(a[2], 56);
VERIFY_BITS(a[3], 56);
VERIFY_BITS(a[4], 52);
- const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
/** [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n.
* px is a shorthand for sum(a[i]*a[x-i], i=0..x).
* Note that [x 0 0 0 0 0] = [x*R].
*/
- __int128 c, d;
-
- uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
-
- d = (__int128)(a0*2) * a3
- + (__int128)(a1*2) * a2;
+ d = (uint128_t)(a0*2) * a3
+ + (uint128_t)(a1*2) * a2;
VERIFY_BITS(d, 114);
/* [d 0 0 0] = [p3 0 0 0] */
- c = (__int128)a4 * a4;
+ c = (uint128_t)a4 * a4;
VERIFY_BITS(c, 112);
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
d += (c & M) * R; c >>= 52;
VERIFY_BITS(d, 115);
VERIFY_BITS(c, 60);
/* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- uint64_t t3 = d & M; d >>= 52;
+ t3 = d & M; d >>= 52;
VERIFY_BITS(t3, 52);
VERIFY_BITS(d, 63);
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
a4 *= 2;
- d += (__int128)a0 * a4
- + (__int128)(a1*2) * a3
- + (__int128)a2 * a2;
+ d += (uint128_t)a0 * a4
+ + (uint128_t)(a1*2) * a3
+ + (uint128_t)a2 * a2;
VERIFY_BITS(d, 115);
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
d += c * R;
VERIFY_BITS(d, 116);
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- uint64_t t4 = d & M; d >>= 52;
+ t4 = d & M; d >>= 52;
VERIFY_BITS(t4, 52);
VERIFY_BITS(d, 64);
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- uint64_t tx = (t4 >> 48); t4 &= (M >> 4);
+ tx = (t4 >> 48); t4 &= (M >> 4);
VERIFY_BITS(tx, 4);
VERIFY_BITS(t4, 48);
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- c = (__int128)a0 * a0;
+ c = (uint128_t)a0 * a0;
VERIFY_BITS(c, 112);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
- d += (__int128)a1 * a4
- + (__int128)(a2*2) * a3;
+ d += (uint128_t)a1 * a4
+ + (uint128_t)(a2*2) * a3;
VERIFY_BITS(d, 114);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- uint64_t u0 = d & M; d >>= 52;
+ u0 = d & M; d >>= 52;
VERIFY_BITS(u0, 52);
VERIFY_BITS(d, 62);
/* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
@@ -218,7 +218,7 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t
u0 = (u0 << 4) | tx;
VERIFY_BITS(u0, 56);
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- c += (__int128)u0 * (R >> 4);
+ c += (uint128_t)u0 * (R >> 4);
VERIFY_BITS(c, 113);
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
r[0] = c & M; c >>= 52;
@@ -227,11 +227,11 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
a0 *= 2;
- c += (__int128)a0 * a1;
+ c += (uint128_t)a0 * a1;
VERIFY_BITS(c, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
- d += (__int128)a2 * a4
- + (__int128)a3 * a3;
+ d += (uint128_t)a2 * a4
+ + (uint128_t)a3 * a3;
VERIFY_BITS(d, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
c += (d & M) * R; d >>= 52;
@@ -243,11 +243,11 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t
VERIFY_BITS(c, 63);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (__int128)a0 * a2
- + (__int128)a1 * a1;
+ c += (uint128_t)a0 * a2
+ + (uint128_t)a1 * a1;
VERIFY_BITS(c, 114);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
- d += (__int128)a3 * a4;
+ d += (uint128_t)a3 * a4;
VERIFY_BITS(d, 114);
/* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
c += (d & M) * R; d >>= 52;
diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h
index 4e2c24aa15..047914cf28 100644
--- a/src/secp256k1/src/field_impl.h
+++ b/src/secp256k1/src/field_impl.h
@@ -21,49 +21,6 @@
#error "Please select field implementation"
#endif
-static void secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a) {
- if (*rlen < 65) {
- *rlen = 65;
- return;
- }
- *rlen = 65;
- unsigned char tmp[32];
- secp256k1_fe_t b = *a;
- secp256k1_fe_normalize(&b);
- secp256k1_fe_get_b32(tmp, &b);
- for (int i=0; i<32; i++) {
- static const char *c = "0123456789ABCDEF";
- r[2*i] = c[(tmp[i] >> 4) & 0xF];
- r[2*i+1] = c[(tmp[i]) & 0xF];
- }
- r[64] = 0x00;
-}
-
-static int secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
- unsigned char tmp[32] = {};
- static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0,
- 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0};
- for (int i=0; i<32; i++) {
- if (alen > i*2)
- tmp[32 - alen/2 + i] = (cvt[(unsigned char)a[2*i]] << 4) + cvt[(unsigned char)a[2*i+1]];
- }
- return secp256k1_fe_set_b32(r, tmp);
-}
-
SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
secp256k1_fe_t na;
secp256k1_fe_negate(&na, a, 1);
@@ -72,62 +29,62 @@ SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe_t *a, cons
}
static int secp256k1_fe_sqrt_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+ secp256k1_fe_t x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
+ int j;
/** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
* { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
* 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
*/
- secp256k1_fe_t x2;
secp256k1_fe_sqr(&x2, a);
secp256k1_fe_mul(&x2, &x2, a);
- secp256k1_fe_t x3;
secp256k1_fe_sqr(&x3, &x2);
secp256k1_fe_mul(&x3, &x3, a);
- secp256k1_fe_t x6 = x3;
- for (int j=0; j<3; j++) secp256k1_fe_sqr(&x6, &x6);
+ x6 = x3;
+ for (j=0; j<3; j++) secp256k1_fe_sqr(&x6, &x6);
secp256k1_fe_mul(&x6, &x6, &x3);
- secp256k1_fe_t x9 = x6;
- for (int j=0; j<3; j++) secp256k1_fe_sqr(&x9, &x9);
+ x9 = x6;
+ for (j=0; j<3; j++) secp256k1_fe_sqr(&x9, &x9);
secp256k1_fe_mul(&x9, &x9, &x3);
- secp256k1_fe_t x11 = x9;
- for (int j=0; j<2; j++) secp256k1_fe_sqr(&x11, &x11);
+ x11 = x9;
+ for (j=0; j<2; j++) secp256k1_fe_sqr(&x11, &x11);
secp256k1_fe_mul(&x11, &x11, &x2);
- secp256k1_fe_t x22 = x11;
- for (int j=0; j<11; j++) secp256k1_fe_sqr(&x22, &x22);
+ x22 = x11;
+ for (j=0; j<11; j++) secp256k1_fe_sqr(&x22, &x22);
secp256k1_fe_mul(&x22, &x22, &x11);
- secp256k1_fe_t x44 = x22;
- for (int j=0; j<22; j++) secp256k1_fe_sqr(&x44, &x44);
+ x44 = x22;
+ for (j=0; j<22; j++) secp256k1_fe_sqr(&x44, &x44);
secp256k1_fe_mul(&x44, &x44, &x22);
- secp256k1_fe_t x88 = x44;
- for (int j=0; j<44; j++) secp256k1_fe_sqr(&x88, &x88);
+ x88 = x44;
+ for (j=0; j<44; j++) secp256k1_fe_sqr(&x88, &x88);
secp256k1_fe_mul(&x88, &x88, &x44);
- secp256k1_fe_t x176 = x88;
- for (int j=0; j<88; j++) secp256k1_fe_sqr(&x176, &x176);
+ x176 = x88;
+ for (j=0; j<88; j++) secp256k1_fe_sqr(&x176, &x176);
secp256k1_fe_mul(&x176, &x176, &x88);
- secp256k1_fe_t x220 = x176;
- for (int j=0; j<44; j++) secp256k1_fe_sqr(&x220, &x220);
+ x220 = x176;
+ for (j=0; j<44; j++) secp256k1_fe_sqr(&x220, &x220);
secp256k1_fe_mul(&x220, &x220, &x44);
- secp256k1_fe_t x223 = x220;
- for (int j=0; j<3; j++) secp256k1_fe_sqr(&x223, &x223);
+ x223 = x220;
+ for (j=0; j<3; j++) secp256k1_fe_sqr(&x223, &x223);
secp256k1_fe_mul(&x223, &x223, &x3);
/* The final result is then assembled using a sliding window over the blocks. */
- secp256k1_fe_t t1 = x223;
- for (int j=0; j<23; j++) secp256k1_fe_sqr(&t1, &t1);
+ t1 = x223;
+ for (j=0; j<23; j++) secp256k1_fe_sqr(&t1, &t1);
secp256k1_fe_mul(&t1, &t1, &x22);
- for (int j=0; j<6; j++) secp256k1_fe_sqr(&t1, &t1);
+ for (j=0; j<6; j++) secp256k1_fe_sqr(&t1, &t1);
secp256k1_fe_mul(&t1, &t1, &x2);
secp256k1_fe_sqr(&t1, &t1);
secp256k1_fe_sqr(r, &t1);
@@ -139,66 +96,66 @@ static int secp256k1_fe_sqrt_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
}
static void secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+ secp256k1_fe_t x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
+ int j;
/** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in
* { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
* [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
*/
- secp256k1_fe_t x2;
secp256k1_fe_sqr(&x2, a);
secp256k1_fe_mul(&x2, &x2, a);
- secp256k1_fe_t x3;
secp256k1_fe_sqr(&x3, &x2);
secp256k1_fe_mul(&x3, &x3, a);
- secp256k1_fe_t x6 = x3;
- for (int j=0; j<3; j++) secp256k1_fe_sqr(&x6, &x6);
+ x6 = x3;
+ for (j=0; j<3; j++) secp256k1_fe_sqr(&x6, &x6);
secp256k1_fe_mul(&x6, &x6, &x3);
- secp256k1_fe_t x9 = x6;
- for (int j=0; j<3; j++) secp256k1_fe_sqr(&x9, &x9);
+ x9 = x6;
+ for (j=0; j<3; j++) secp256k1_fe_sqr(&x9, &x9);
secp256k1_fe_mul(&x9, &x9, &x3);
- secp256k1_fe_t x11 = x9;
- for (int j=0; j<2; j++) secp256k1_fe_sqr(&x11, &x11);
+ x11 = x9;
+ for (j=0; j<2; j++) secp256k1_fe_sqr(&x11, &x11);
secp256k1_fe_mul(&x11, &x11, &x2);
- secp256k1_fe_t x22 = x11;
- for (int j=0; j<11; j++) secp256k1_fe_sqr(&x22, &x22);
+ x22 = x11;
+ for (j=0; j<11; j++) secp256k1_fe_sqr(&x22, &x22);
secp256k1_fe_mul(&x22, &x22, &x11);
- secp256k1_fe_t x44 = x22;
- for (int j=0; j<22; j++) secp256k1_fe_sqr(&x44, &x44);
+ x44 = x22;
+ for (j=0; j<22; j++) secp256k1_fe_sqr(&x44, &x44);
secp256k1_fe_mul(&x44, &x44, &x22);
- secp256k1_fe_t x88 = x44;
- for (int j=0; j<44; j++) secp256k1_fe_sqr(&x88, &x88);
+ x88 = x44;
+ for (j=0; j<44; j++) secp256k1_fe_sqr(&x88, &x88);
secp256k1_fe_mul(&x88, &x88, &x44);
- secp256k1_fe_t x176 = x88;
- for (int j=0; j<88; j++) secp256k1_fe_sqr(&x176, &x176);
+ x176 = x88;
+ for (j=0; j<88; j++) secp256k1_fe_sqr(&x176, &x176);
secp256k1_fe_mul(&x176, &x176, &x88);
- secp256k1_fe_t x220 = x176;
- for (int j=0; j<44; j++) secp256k1_fe_sqr(&x220, &x220);
+ x220 = x176;
+ for (j=0; j<44; j++) secp256k1_fe_sqr(&x220, &x220);
secp256k1_fe_mul(&x220, &x220, &x44);
- secp256k1_fe_t x223 = x220;
- for (int j=0; j<3; j++) secp256k1_fe_sqr(&x223, &x223);
+ x223 = x220;
+ for (j=0; j<3; j++) secp256k1_fe_sqr(&x223, &x223);
secp256k1_fe_mul(&x223, &x223, &x3);
/* The final result is then assembled using a sliding window over the blocks. */
- secp256k1_fe_t t1 = x223;
- for (int j=0; j<23; j++) secp256k1_fe_sqr(&t1, &t1);
+ t1 = x223;
+ for (j=0; j<23; j++) secp256k1_fe_sqr(&t1, &t1);
secp256k1_fe_mul(&t1, &t1, &x22);
- for (int j=0; j<5; j++) secp256k1_fe_sqr(&t1, &t1);
+ for (j=0; j<5; j++) secp256k1_fe_sqr(&t1, &t1);
secp256k1_fe_mul(&t1, &t1, a);
- for (int j=0; j<3; j++) secp256k1_fe_sqr(&t1, &t1);
+ for (j=0; j<3; j++) secp256k1_fe_sqr(&t1, &t1);
secp256k1_fe_mul(&t1, &t1, &x2);
- for (int j=0; j<2; j++) secp256k1_fe_sqr(&t1, &t1);
+ for (j=0; j<2; j++) secp256k1_fe_sqr(&t1, &t1);
secp256k1_fe_mul(r, a, &t1);
}
@@ -206,13 +163,21 @@ static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
#if defined(USE_FIELD_INV_BUILTIN)
secp256k1_fe_inv(r, a);
#elif defined(USE_FIELD_INV_NUM)
+ secp256k1_num_t n, m;
+ /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
+ static const unsigned char prime[32] = {
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
+ };
unsigned char b[32];
secp256k1_fe_t c = *a;
secp256k1_fe_normalize_var(&c);
secp256k1_fe_get_b32(b, &c);
- secp256k1_num_t n;
secp256k1_num_set_bin(&n, b, 32);
- secp256k1_num_mod_inverse(&n, &n, &secp256k1_fe_consts->p);
+ secp256k1_num_set_bin(&m, prime, 32);
+ secp256k1_num_mod_inverse(&n, &n, &m);
secp256k1_num_get_bin(b, 32, &n);
VERIFY_CHECK(secp256k1_fe_set_b32(r, b));
#else
@@ -220,7 +185,9 @@ static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
#endif
}
-static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t r[len], const secp256k1_fe_t a[len]) {
+static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+ secp256k1_fe_t u;
+ size_t i;
if (len < 1)
return;
@@ -228,12 +195,12 @@ static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t r[len], const se
r[0] = a[0];
- size_t i = 0;
+ i = 0;
while (++i < len) {
secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]);
}
- secp256k1_fe_t u; secp256k1_fe_inv_var(&u, &r[--i]);
+ secp256k1_fe_inv_var(&u, &r[--i]);
while (i > 0) {
int j = i--;
@@ -244,32 +211,4 @@ static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t r[len], const se
r[0] = u;
}
-static void secp256k1_fe_start(void) {
-#ifndef USE_NUM_NONE
- static const unsigned char secp256k1_fe_consts_p[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
- };
-#endif
- if (secp256k1_fe_consts == NULL) {
- secp256k1_fe_inner_start();
- secp256k1_fe_consts_t *ret = (secp256k1_fe_consts_t*)checked_malloc(sizeof(secp256k1_fe_consts_t));
-#ifndef USE_NUM_NONE
- secp256k1_num_set_bin(&ret->p, secp256k1_fe_consts_p, sizeof(secp256k1_fe_consts_p));
-#endif
- secp256k1_fe_consts = ret;
- }
-}
-
-static void secp256k1_fe_stop(void) {
- if (secp256k1_fe_consts != NULL) {
- secp256k1_fe_consts_t *c = (secp256k1_fe_consts_t*)secp256k1_fe_consts;
- free((void*)c);
- secp256k1_fe_consts = NULL;
- secp256k1_fe_inner_stop();
- }
-}
-
#endif
diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h
index 6dea6bb5ac..d1e5834909 100644
--- a/src/secp256k1/src/group.h
+++ b/src/secp256k1/src/group.h
@@ -17,6 +17,9 @@ typedef struct {
int infinity; /* whether this represents the point at infinity */
} secp256k1_ge_t;
+#define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0}
+#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1}
+
/** A group element of the secp256k1 curve, in jacobian coordinates. */
typedef struct {
secp256k1_fe_t x; /* actual X: x/z^2 */
@@ -25,23 +28,15 @@ typedef struct {
int infinity; /* whether this represents the point at infinity */
} secp256k1_gej_t;
-/** Global constants related to the group */
-typedef struct {
- secp256k1_ge_t g; /* the generator point */
-
-#ifdef USE_ENDOMORPHISM
- /* constants related to secp256k1's efficiently computable endomorphism */
- secp256k1_fe_t beta;
-#endif
-} secp256k1_ge_consts_t;
-
-static const secp256k1_ge_consts_t *secp256k1_ge_consts = NULL;
+#define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0}
+#define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1}
-/** Initialize the group module. */
-static void secp256k1_ge_start(void);
+typedef struct {
+ secp256k1_fe_storage_t x;
+ secp256k1_fe_storage_t y;
+} secp256k1_ge_storage_t;
-/** De-initialize the group module. */
-static void secp256k1_ge_stop(void);
+#define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))}
/** Set a group element equal to the point at infinity */
static void secp256k1_ge_set_infinity(secp256k1_ge_t *r);
@@ -61,14 +56,11 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge_t *a);
static void secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a);
-/** Get a hex representation of a point. *rlen will be overwritten with the real length. */
-static void secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a);
-
/** Set a group element equal to another which is given in jacobian coordinates */
static void secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a);
/** Set a batch of group elements equal to the inputs given in jacobian coordinates */
-static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t r[len], const secp256k1_gej_t a[len]);
+static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t *r, const secp256k1_gej_t *a);
/** Set a group element (jacobian) equal to the point at infinity. */
@@ -103,9 +95,6 @@ static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c
guarantee, and b is allowed to be infinity. */
static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b);
-/** Get a hex representation of a point. *rlen will be overwritten with the real length. */
-static void secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a);
-
#ifdef USE_ENDOMORPHISM
/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */
static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a);
@@ -117,4 +106,13 @@ static void secp256k1_gej_clear(secp256k1_gej_t *r);
/** Clear a secp256k1_ge_t to prevent leaking sensitive information. */
static void secp256k1_ge_clear(secp256k1_ge_t *r);
+/** Convert a group element to the storage type. */
+static void secp256k1_ge_to_storage(secp256k1_ge_storage_t *r, const secp256k1_ge_t*);
+
+/** Convert a group element back from the storage type. */
+static void secp256k1_ge_from_storage(secp256k1_ge_t *r, const secp256k1_ge_storage_t*);
+
+/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
+static void secp256k1_ge_storage_cmov(secp256k1_ge_storage_t *r, const secp256k1_ge_storage_t *a, int flag);
+
#endif
diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h
index fef06df289..8d8c359c5a 100644
--- a/src/secp256k1/src/group_impl.h
+++ b/src/secp256k1/src/group_impl.h
@@ -13,6 +13,16 @@
#include "field.h"
#include "group.h"
+/** Generator for secp256k1, value 'g' defined in
+ * "Standards for Efficient Cryptography" (SEC2) 2.7.1.
+ */
+static const secp256k1_ge_t secp256k1_ge_const_g = SECP256K1_GE_CONST(
+ 0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,
+ 0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,
+ 0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,
+ 0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL
+);
+
static void secp256k1_ge_set_infinity(secp256k1_ge_t *r) {
r->infinity = 1;
}
@@ -33,32 +43,12 @@ static void secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a) {
secp256k1_fe_negate(&r->y, &r->y, 1);
}
-static void secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a) {
- char cx[65]; int lx=65;
- char cy[65]; int ly=65;
- secp256k1_fe_get_hex(cx, &lx, &a->x);
- secp256k1_fe_get_hex(cy, &ly, &a->y);
- lx = strlen(cx);
- ly = strlen(cy);
- int len = lx + ly + 3 + 1;
- if (*rlen < len) {
- *rlen = len;
- return;
- }
- *rlen = len;
- r[0] = '(';
- memcpy(r+1, cx, lx);
- r[1+lx] = ',';
- memcpy(r+2+lx, cy, ly);
- r[2+lx+ly] = ')';
- r[3+lx+ly] = 0;
-}
-
static void secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a) {
+ secp256k1_fe_t z2, z3;
r->infinity = a->infinity;
secp256k1_fe_inv(&a->z, &a->z);
- secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z);
- secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &a->z, &z2);
+ secp256k1_fe_sqr(&z2, &a->z);
+ secp256k1_fe_mul(&z3, &a->z, &z2);
secp256k1_fe_mul(&a->x, &a->x, &z2);
secp256k1_fe_mul(&a->y, &a->y, &z3);
secp256k1_fe_set_int(&a->z, 1);
@@ -67,13 +57,14 @@ static void secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a) {
}
static void secp256k1_ge_set_gej_var(secp256k1_ge_t *r, secp256k1_gej_t *a) {
+ secp256k1_fe_t z2, z3;
r->infinity = a->infinity;
if (a->infinity) {
return;
}
secp256k1_fe_inv_var(&a->z, &a->z);
- secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z);
- secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &a->z, &z2);
+ secp256k1_fe_sqr(&z2, &a->z);
+ secp256k1_fe_mul(&z3, &a->z, &z2);
secp256k1_fe_mul(&a->x, &a->x, &z2);
secp256k1_fe_mul(&a->y, &a->y, &z3);
secp256k1_fe_set_int(&a->z, 1);
@@ -81,26 +72,30 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge_t *r, secp256k1_gej_t *a) {
r->y = a->y;
}
-static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t r[len], const secp256k1_gej_t a[len]) {
+static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t *r, const secp256k1_gej_t *a) {
+ secp256k1_fe_t *az;
+ secp256k1_fe_t *azi;
+ size_t i;
size_t count = 0;
- secp256k1_fe_t *az = checked_malloc(sizeof(secp256k1_fe_t) * len);
- for (size_t i=0; i<len; i++) {
+ az = checked_malloc(sizeof(secp256k1_fe_t) * len);
+ for (i = 0; i < len; i++) {
if (!a[i].infinity) {
az[count++] = a[i].z;
}
}
- secp256k1_fe_t *azi = checked_malloc(sizeof(secp256k1_fe_t) * count);
+ azi = checked_malloc(sizeof(secp256k1_fe_t) * count);
secp256k1_fe_inv_all_var(count, azi, az);
free(az);
count = 0;
- for (size_t i=0; i<len; i++) {
+ for (i = 0; i < len; i++) {
r[i].infinity = a[i].infinity;
if (!a[i].infinity) {
+ secp256k1_fe_t zi2, zi3;
secp256k1_fe_t *zi = &azi[count++];
- secp256k1_fe_t zi2; secp256k1_fe_sqr(&zi2, zi);
- secp256k1_fe_t zi3; secp256k1_fe_mul(&zi3, &zi2, zi);
+ secp256k1_fe_sqr(&zi2, zi);
+ secp256k1_fe_mul(&zi3, &zi2, zi);
secp256k1_fe_mul(&r[i].x, &a[i].x, &zi2);
secp256k1_fe_mul(&r[i].y, &a[i].y, &zi3);
}
@@ -136,11 +131,12 @@ static void secp256k1_ge_clear(secp256k1_ge_t *r) {
}
static int secp256k1_ge_set_xo_var(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd) {
+ secp256k1_fe_t x2, x3, c;
r->x = *x;
- secp256k1_fe_t x2; secp256k1_fe_sqr(&x2, x);
- secp256k1_fe_t x3; secp256k1_fe_mul(&x3, x, &x2);
+ secp256k1_fe_sqr(&x2, x);
+ secp256k1_fe_mul(&x3, x, &x2);
r->infinity = 0;
- secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7);
+ secp256k1_fe_set_int(&c, 7);
secp256k1_fe_add(&c, &x3);
if (!secp256k1_fe_sqrt_var(&r->y, &c))
return 0;
@@ -158,9 +154,10 @@ static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a) {
}
static int secp256k1_gej_eq_x_var(const secp256k1_fe_t *x, const secp256k1_gej_t *a) {
+ secp256k1_fe_t r, r2;
VERIFY_CHECK(!a->infinity);
- secp256k1_fe_t r; secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
- secp256k1_fe_t r2 = a->x; secp256k1_fe_normalize_weak(&r2);
+ secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
+ r2 = a->x; secp256k1_fe_normalize_weak(&r2);
return secp256k1_fe_equal_var(&r, &r2);
}
@@ -178,6 +175,7 @@ static int secp256k1_gej_is_infinity(const secp256k1_gej_t *a) {
}
static int secp256k1_gej_is_valid_var(const secp256k1_gej_t *a) {
+ secp256k1_fe_t y2, x3, z2, z6;
if (a->infinity)
return 0;
/** y^2 = x^3 + 7
@@ -185,10 +183,10 @@ static int secp256k1_gej_is_valid_var(const secp256k1_gej_t *a) {
* Y^2 / Z^6 = X^3 / Z^6 + 7
* Y^2 = X^3 + 7*Z^6
*/
- secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &a->y);
- secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
- secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z);
- secp256k1_fe_t z6; secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2);
+ secp256k1_fe_sqr(&y2, &a->y);
+ secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
+ secp256k1_fe_sqr(&z2, &a->z);
+ secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2);
secp256k1_fe_mul_int(&z6, 7);
secp256k1_fe_add(&x3, &z6);
secp256k1_fe_normalize_weak(&x3);
@@ -196,27 +194,30 @@ static int secp256k1_gej_is_valid_var(const secp256k1_gej_t *a) {
}
static int secp256k1_ge_is_valid_var(const secp256k1_ge_t *a) {
+ secp256k1_fe_t y2, x3, c;
if (a->infinity)
return 0;
/* y^2 = x^3 + 7 */
- secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &a->y);
- secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
- secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7);
+ secp256k1_fe_sqr(&y2, &a->y);
+ secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
+ secp256k1_fe_set_int(&c, 7);
secp256k1_fe_add(&x3, &c);
secp256k1_fe_normalize_weak(&x3);
return secp256k1_fe_equal_var(&y2, &x3);
}
static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *a) {
- // For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity,
- // Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have
- // y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p.
+ /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate */
+ secp256k1_fe_t t1,t2,t3,t4;
+ /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity,
+ * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have
+ * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p.
+ */
r->infinity = a->infinity;
if (r->infinity) {
return;
}
- secp256k1_fe_t t1,t2,t3,t4;
secp256k1_fe_mul(&r->z, &a->z, &a->y);
secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */
secp256k1_fe_sqr(&t1, &a->x);
@@ -240,6 +241,8 @@ static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *
}
static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b) {
+ /* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */
+ secp256k1_fe_t z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t;
if (a->infinity) {
*r = *b;
return;
@@ -249,14 +252,14 @@ static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a,
return;
}
r->infinity = 0;
- secp256k1_fe_t z22; secp256k1_fe_sqr(&z22, &b->z);
- secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &a->z);
- secp256k1_fe_t u1; secp256k1_fe_mul(&u1, &a->x, &z22);
- secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12);
- secp256k1_fe_t s1; secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z);
- secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
- secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
- secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
+ secp256k1_fe_sqr(&z22, &b->z);
+ secp256k1_fe_sqr(&z12, &a->z);
+ secp256k1_fe_mul(&u1, &a->x, &z22);
+ secp256k1_fe_mul(&u2, &b->x, &z12);
+ secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z);
+ secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
+ secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
+ secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
if (secp256k1_fe_normalizes_to_zero_var(&h)) {
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
secp256k1_gej_double_var(r, a);
@@ -265,11 +268,11 @@ static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a,
}
return;
}
- secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i);
- secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h);
- secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2);
+ secp256k1_fe_sqr(&i2, &i);
+ secp256k1_fe_sqr(&h2, &h);
+ secp256k1_fe_mul(&h3, &h, &h2);
secp256k1_fe_mul(&r->z, &a->z, &b->z); secp256k1_fe_mul(&r->z, &r->z, &h);
- secp256k1_fe_t t; secp256k1_fe_mul(&t, &u1, &h2);
+ secp256k1_fe_mul(&t, &u1, &h2);
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2);
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i);
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
@@ -277,6 +280,8 @@ static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a,
}
static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) {
+ /* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */
+ secp256k1_fe_t z12, u1, u2, s1, s2, h, i, i2, h2, h3, t;
if (a->infinity) {
r->infinity = b->infinity;
r->x = b->x;
@@ -289,13 +294,13 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *
return;
}
r->infinity = 0;
- secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &a->z);
- secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize_weak(&u1);
- secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12);
- secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize_weak(&s1);
- secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
- secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
- secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
+ secp256k1_fe_sqr(&z12, &a->z);
+ u1 = a->x; secp256k1_fe_normalize_weak(&u1);
+ secp256k1_fe_mul(&u2, &b->x, &z12);
+ s1 = a->y; secp256k1_fe_normalize_weak(&s1);
+ secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
+ secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
+ secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
if (secp256k1_fe_normalizes_to_zero_var(&h)) {
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
secp256k1_gej_double_var(r, a);
@@ -304,11 +309,11 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *
}
return;
}
- secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i);
- secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h);
- secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2);
+ secp256k1_fe_sqr(&i2, &i);
+ secp256k1_fe_sqr(&h2, &h);
+ secp256k1_fe_mul(&h3, &h, &h2);
r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h);
- secp256k1_fe_t t; secp256k1_fe_mul(&t, &u1, &h2);
+ secp256k1_fe_mul(&t, &u1, &h2);
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2);
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i);
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
@@ -316,6 +321,9 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *
}
static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) {
+ /* Operations: 7 mul, 5 sqr, 5 normalize, 19 mul_int/add/negate */
+ secp256k1_fe_t zz, u1, u2, s1, s2, z, t, m, n, q, rr;
+ int infinity;
VERIFY_CHECK(!b->infinity);
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
@@ -341,24 +349,24 @@ static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c
* (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.)
*/
- secp256k1_fe_t zz; secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */
- secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */
- secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */
- secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */
- secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z2^2 (1) */
- secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */
- secp256k1_fe_t z = a->z; /* z = Z = Z1*Z2 (8) */
- secp256k1_fe_t t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */
- secp256k1_fe_t m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */
- secp256k1_fe_t n; secp256k1_fe_sqr(&n, &m); /* n = M^2 (1) */
- secp256k1_fe_t q; secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*M^2 (1) */
- secp256k1_fe_sqr(&n, &n); /* n = M^4 (1) */
- secp256k1_fe_t rr; secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */
+ secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */
+ u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */
+ secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */
+ s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */
+ secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z2^2 (1) */
+ secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */
+ z = a->z; /* z = Z = Z1*Z2 (8) */
+ t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */
+ m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */
+ secp256k1_fe_sqr(&n, &m); /* n = M^2 (1) */
+ secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*M^2 (1) */
+ secp256k1_fe_sqr(&n, &n); /* n = M^4 (1) */
+ secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */
secp256k1_fe_mul(&t, &u1, &u2); secp256k1_fe_negate(&t, &t, 1); /* t = -U1*U2 (2) */
secp256k1_fe_add(&rr, &t); /* rr = R = T^2-U1*U2 (3) */
secp256k1_fe_sqr(&t, &rr); /* t = R^2 (1) */
secp256k1_fe_mul(&r->z, &m, &z); /* r->z = M*Z (1) */
- int infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity);
+ infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity);
secp256k1_fe_mul_int(&r->z, 2 * (1 - a->infinity)); /* r->z = Z3 = 2*M*Z (2) */
r->x = t; /* r->x = R^2 (1) */
secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */
@@ -386,63 +394,37 @@ static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c
r->infinity = infinity;
}
+static void secp256k1_ge_to_storage(secp256k1_ge_storage_t *r, const secp256k1_ge_t *a) {
+ secp256k1_fe_t x, y;
+ VERIFY_CHECK(!a->infinity);
+ x = a->x;
+ secp256k1_fe_normalize(&x);
+ y = a->y;
+ secp256k1_fe_normalize(&y);
+ secp256k1_fe_to_storage(&r->x, &x);
+ secp256k1_fe_to_storage(&r->y, &y);
+}
+static void secp256k1_ge_from_storage(secp256k1_ge_t *r, const secp256k1_ge_storage_t *a) {
+ secp256k1_fe_from_storage(&r->x, &a->x);
+ secp256k1_fe_from_storage(&r->y, &a->y);
+ r->infinity = 0;
+}
-static void secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a) {
- secp256k1_gej_t c = *a;
- secp256k1_ge_t t; secp256k1_ge_set_gej(&t, &c);
- secp256k1_ge_get_hex(r, rlen, &t);
+static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage_t *r, const secp256k1_ge_storage_t *a, int flag) {
+ secp256k1_fe_storage_cmov(&r->x, &a->x, flag);
+ secp256k1_fe_storage_cmov(&r->y, &a->y, flag);
}
#ifdef USE_ENDOMORPHISM
static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a) {
- const secp256k1_fe_t *beta = &secp256k1_ge_consts->beta;
+ static const secp256k1_fe_t beta = SECP256K1_FE_CONST(
+ 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
+ 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul
+ );
*r = *a;
- secp256k1_fe_mul(&r->x, &r->x, beta);
+ secp256k1_fe_mul(&r->x, &r->x, &beta);
}
#endif
-static void secp256k1_ge_start(void) {
- static const unsigned char secp256k1_ge_consts_g_x[] = {
- 0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,
- 0x55,0xA0,0x62,0x95,0xCE,0x87,0x0B,0x07,
- 0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,
- 0x59,0xF2,0x81,0x5B,0x16,0xF8,0x17,0x98
- };
- static const unsigned char secp256k1_ge_consts_g_y[] = {
- 0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,
- 0x5D,0xA4,0xFB,0xFC,0x0E,0x11,0x08,0xA8,
- 0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,
- 0x9C,0x47,0xD0,0x8F,0xFB,0x10,0xD4,0xB8
- };
-#ifdef USE_ENDOMORPHISM
- /* properties of secp256k1's efficiently computable endomorphism */
- static const unsigned char secp256k1_ge_consts_beta[] = {
- 0x7a,0xe9,0x6a,0x2b,0x65,0x7c,0x07,0x10,
- 0x6e,0x64,0x47,0x9e,0xac,0x34,0x34,0xe9,
- 0x9c,0xf0,0x49,0x75,0x12,0xf5,0x89,0x95,
- 0xc1,0x39,0x6c,0x28,0x71,0x95,0x01,0xee
- };
-#endif
- if (secp256k1_ge_consts == NULL) {
- secp256k1_ge_consts_t *ret = (secp256k1_ge_consts_t*)checked_malloc(sizeof(secp256k1_ge_consts_t));
-#ifdef USE_ENDOMORPHISM
- VERIFY_CHECK(secp256k1_fe_set_b32(&ret->beta, secp256k1_ge_consts_beta));
-#endif
- secp256k1_fe_t g_x, g_y;
- VERIFY_CHECK(secp256k1_fe_set_b32(&g_x, secp256k1_ge_consts_g_x));
- VERIFY_CHECK(secp256k1_fe_set_b32(&g_y, secp256k1_ge_consts_g_y));
- secp256k1_ge_set_xy(&ret->g, &g_x, &g_y);
- secp256k1_ge_consts = ret;
- }
-}
-
-static void secp256k1_ge_stop(void) {
- if (secp256k1_ge_consts != NULL) {
- secp256k1_ge_consts_t *c = (secp256k1_ge_consts_t*)secp256k1_ge_consts;
- free((void*)c);
- secp256k1_ge_consts = NULL;
- }
-}
-
#endif
diff --git a/src/secp256k1/src/hash.h b/src/secp256k1/src/hash.h
index d1e65b968a..843423d7f7 100644
--- a/src/secp256k1/src/hash.h
+++ b/src/secp256k1/src/hash.h
@@ -12,7 +12,7 @@
typedef struct {
uint32_t s[32];
- unsigned char buf[64];
+ uint32_t buf[16]; /* In big endian */
size_t bytes;
} secp256k1_sha256_t;
@@ -34,7 +34,7 @@ typedef struct {
int retry;
} secp256k1_rfc6979_hmac_sha256_t;
-static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen, const unsigned char *msg, size_t msglen);
+static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen, const unsigned char *msg, size_t msglen, const unsigned char *rnd, size_t rndlen);
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen);
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng);
diff --git a/src/secp256k1/src/hash_impl.h b/src/secp256k1/src/hash_impl.h
index f35c5f7a82..60fdbf7718 100644
--- a/src/secp256k1/src/hash_impl.h
+++ b/src/secp256k1/src/hash_impl.h
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <stdint.h>
+#include <string.h>
#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
@@ -26,8 +27,11 @@
(h) = t1 + t2; \
} while(0)
-#define ReadBE32(p) (((uint32_t)((p)[0])) << 24 | ((uint32_t)((p)[1])) << 16 | ((uint32_t)((p)[2])) << 8 | ((uint32_t)((p)[3])))
-#define WriteBE32(p, v) do { (p)[0] = (v) >> 24; (p)[1] = (v) >> 16; (p)[2] = (v) >> 8; (p)[3] = (v); } while(0)
+#ifdef WORDS_BIGENDIAN
+#define BE32(x) (x)
+#else
+#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24))
+#endif
static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) {
hash->s[0] = 0x6a09e667ul;
@@ -41,27 +45,27 @@ static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) {
hash->bytes = 0;
}
-/** Perform one SHA-256 transformation, processing a 64-byte chunk. */
-static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* chunk) {
+/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */
+static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) {
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];
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
- Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0));
- Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4));
- Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8));
- Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12));
- Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16));
- Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20));
- Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24));
- Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28));
- Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32));
- Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36));
- Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40));
- Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44));
- Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48));
- Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52));
- Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56));
- Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60));
+ Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = BE32(chunk[0]));
+ Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = BE32(chunk[1]));
+ Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = BE32(chunk[2]));
+ Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = BE32(chunk[3]));
+ Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = BE32(chunk[4]));
+ Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = BE32(chunk[5]));
+ Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = BE32(chunk[6]));
+ Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = BE32(chunk[7]));
+ Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = BE32(chunk[8]));
+ Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = BE32(chunk[9]));
+ Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = BE32(chunk[10]));
+ Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = BE32(chunk[11]));
+ Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = BE32(chunk[12]));
+ Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = BE32(chunk[13]));
+ Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = BE32(chunk[14]));
+ Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = BE32(chunk[15]));
Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
@@ -125,55 +129,40 @@ static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* chunk)
}
static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) {
- const unsigned char* end = data + len;
- size_t bufsize = hash->bytes % 64;
- if (bufsize && bufsize + len >= 64) {
- // Fill the buffer, and process it.
- memcpy(hash->buf + bufsize, data, 64 - bufsize);
- hash->bytes += 64 - bufsize;
+ size_t bufsize = hash->bytes & 0x3F;
+ hash->bytes += len;
+ while (bufsize + len >= 64) {
+ /* Fill the buffer, and process it. */
+ memcpy(((unsigned char*)hash->buf) + bufsize, data, 64 - bufsize);
data += 64 - bufsize;
+ len -= 64 - bufsize;
secp256k1_sha256_transform(hash->s, hash->buf);
bufsize = 0;
}
- while (end >= data + 64) {
- // Process full chunks directly from the source.
- secp256k1_sha256_transform(hash->s, data);
- hash->bytes += 64;
- data += 64;
- }
- if (end > data) {
- // Fill the buffer with what remains.
- memcpy(hash->buf + bufsize, data, end - data);
- hash->bytes += end - data;
+ if (len) {
+ /* Fill the buffer with what remains. */
+ memcpy(((unsigned char*)hash->buf) + bufsize, data, len);
}
}
static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) {
static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- unsigned char sizedesc[8];
- WriteBE32(sizedesc, hash->bytes >> 29);
- WriteBE32(sizedesc + 4, hash->bytes << 3);
+ uint32_t sizedesc[2];
+ uint32_t out[8];
+ int i = 0;
+ sizedesc[0] = BE32(hash->bytes >> 29);
+ sizedesc[1] = BE32(hash->bytes << 3);
secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64));
- secp256k1_sha256_write(hash, sizedesc, 8);
- WriteBE32(out32, hash->s[0]);
- hash->s[0] = 0;
- WriteBE32(out32 + 4, hash->s[1]);
- hash->s[1] = 0;
- WriteBE32(out32 + 8, hash->s[2]);
- hash->s[2] = 0;
- WriteBE32(out32 + 12, hash->s[3]);
- hash->s[3] = 0;
- WriteBE32(out32 + 16, hash->s[4]);
- hash->s[4] = 0;
- WriteBE32(out32 + 20, hash->s[5]);
- hash->s[5] = 0;
- WriteBE32(out32 + 24, hash->s[6]);
- hash->s[6] = 0;
- WriteBE32(out32 + 28, hash->s[7]);
- hash->s[7] = 0;
+ secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8);
+ for (i = 0; i < 8; i++) {
+ out[i] = BE32(hash->s[i]);
+ hash->s[i] = 0;
+ }
+ memcpy(out32, (const unsigned char*)out, 32);
}
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) {
+ int n;
unsigned char rkey[64];
if (keylen <= 64) {
memcpy(rkey, key, keylen);
@@ -187,12 +176,12 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, cons
}
secp256k1_sha256_initialize(&hash->outer);
- for (int n = 0; n < 64; n++)
+ for (n = 0; n < 64; n++)
rkey[n] ^= 0x5c;
secp256k1_sha256_write(&hash->outer, rkey, 64);
secp256k1_sha256_initialize(&hash->inner);
- for (int n = 0; n < 64; n++)
+ for (n = 0; n < 64; n++)
rkey[n] ^= 0x5c ^ 0x36;
secp256k1_sha256_write(&hash->inner, rkey, 64);
memset(rkey, 0, 64);
@@ -211,19 +200,22 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsign
}
-static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen, const unsigned char *msg, size_t msglen) {
+static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen, const unsigned char *msg, size_t msglen, const unsigned char *rnd, size_t rndlen) {
+ secp256k1_hmac_sha256_t hmac;
static const unsigned char zero[1] = {0x00};
static const unsigned char one[1] = {0x01};
memset(rng->v, 0x01, 32);
memset(rng->k, 0x00, 32);
- secp256k1_hmac_sha256_t hmac;
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_write(&hmac, zero, 1);
secp256k1_hmac_sha256_write(&hmac, key, keylen);
secp256k1_hmac_sha256_write(&hmac, msg, msglen);
+ if (rnd && rndlen) {
+ secp256k1_hmac_sha256_write(&hmac, rnd, rndlen);
+ }
secp256k1_hmac_sha256_finalize(&hmac, rng->k);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
@@ -234,6 +226,9 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2
secp256k1_hmac_sha256_write(&hmac, one, 1);
secp256k1_hmac_sha256_write(&hmac, key, keylen);
secp256k1_hmac_sha256_write(&hmac, msg, msglen);
+ if (rnd && rndlen) {
+ secp256k1_hmac_sha256_write(&hmac, rnd, rndlen);
+ }
secp256k1_hmac_sha256_finalize(&hmac, rng->k);
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
@@ -256,10 +251,10 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256
while (outlen > 0) {
secp256k1_hmac_sha256_t hmac;
+ int now = outlen;
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_finalize(&hmac, rng->v);
- int now = outlen;
if (now > 32) {
now = 32;
}
diff --git a/src/secp256k1/src/num_gmp_impl.h b/src/secp256k1/src/num_gmp_impl.h
index 19d474e59f..3e4b92d329 100644
--- a/src/secp256k1/src/num_gmp_impl.h
+++ b/src/secp256k1/src/num_gmp_impl.h
@@ -29,10 +29,10 @@ static void secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) {
unsigned char tmp[65];
int len = 0;
+ int shift = 0;
if (a->limbs>1 || a->data[0] != 0) {
len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs);
}
- int shift = 0;
while (shift < len && tmp[shift] == 0) shift++;
VERIFY_CHECK(len-shift <= (int)rlen);
memset(r, 0, rlen - len + shift);
@@ -43,9 +43,10 @@ static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const sec
}
static void secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) {
+ int len;
VERIFY_CHECK(alen > 0);
VERIFY_CHECK(alen <= 64);
- int len = mpn_set_str(r->data, a, alen, 256);
+ len = mpn_set_str(r->data, a, alen, 256);
if (len == 0) {
r->data[0] = 0;
len = 1;
@@ -91,6 +92,12 @@ static void secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) {
}
static void secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) {
+ int i;
+ mp_limb_t g[NUM_LIMBS+1];
+ mp_limb_t u[NUM_LIMBS+1];
+ mp_limb_t v[NUM_LIMBS+1];
+ mp_size_t sn;
+ mp_size_t gn;
secp256k1_num_sanity(a);
secp256k1_num_sanity(m);
@@ -106,15 +113,12 @@ static void secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t
*/
VERIFY_CHECK(m->limbs <= NUM_LIMBS);
VERIFY_CHECK(m->data[m->limbs-1] != 0);
- mp_limb_t g[NUM_LIMBS+1];
- mp_limb_t u[NUM_LIMBS+1];
- mp_limb_t v[NUM_LIMBS+1];
- for (int i=0; i < m->limbs; i++) {
+ for (i = 0; i < m->limbs; i++) {
u[i] = (i < a->limbs) ? a->data[i] : 0;
v[i] = m->data[i];
}
- mp_size_t sn = NUM_LIMBS+1;
- mp_size_t gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs);
+ sn = NUM_LIMBS+1;
+ gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs);
VERIFY_CHECK(gn == 1);
VERIFY_CHECK(g[0] == 1);
r->neg = a->neg ^ m->neg;
@@ -183,10 +187,10 @@ static void secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, cons
}
static void secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+ mp_limb_t tmp[2*NUM_LIMBS+1];
secp256k1_num_sanity(a);
secp256k1_num_sanity(b);
- mp_limb_t tmp[2*NUM_LIMBS+1];
VERIFY_CHECK(a->limbs + b->limbs <= 2*NUM_LIMBS+1);
if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) {
r->limbs = 1;
@@ -207,13 +211,14 @@ static void secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, cons
}
static void secp256k1_num_shift(secp256k1_num_t *r, int bits) {
+ int i;
if (bits % GMP_NUMB_BITS) {
- // Shift within limbs.
+ /* Shift within limbs. */
mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS);
}
if (bits >= GMP_NUMB_BITS) {
- // Shift full limbs.
- for (int i = 0; i < r->limbs; i++) {
+ /* Shift full limbs. */
+ for (i = 0; i < r->limbs; i++) {
int index = i + (bits / GMP_NUMB_BITS);
if (index < r->limbs && index < 2*NUM_LIMBS) {
r->data[i] = r->data[index];
diff --git a/src/secp256k1/src/scalar.h b/src/secp256k1/src/scalar.h
index 2f5ba0d447..f5d09f8d47 100644
--- a/src/secp256k1/src/scalar.h
+++ b/src/secp256k1/src/scalar.h
@@ -21,9 +21,6 @@
#error "Please select scalar implementation"
#endif
-static void secp256k1_scalar_start(void);
-static void secp256k1_scalar_stop(void);
-
/** Clear a scalar to prevent the leak of sensitive data. */
static void secp256k1_scalar_clear(secp256k1_scalar_t *r);
@@ -83,9 +80,9 @@ static void secp256k1_scalar_order_get_num(secp256k1_num_t *r);
/** Compare two scalars. */
static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
-static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
-
#ifdef USE_ENDOMORPHISM
+/** Find r1 and r2 such that r1+r2*2^128 = a. */
+static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */
static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
#endif
diff --git a/src/secp256k1/src/scalar_4x64.h b/src/secp256k1/src/scalar_4x64.h
index 5a751c6862..82899aa7b0 100644
--- a/src/secp256k1/src/scalar_4x64.h
+++ b/src/secp256k1/src/scalar_4x64.h
@@ -14,4 +14,6 @@ typedef struct {
uint64_t d[4];
} secp256k1_scalar_t;
+#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}}
+
#endif
diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h
index d144775220..ff365292f8 100644
--- a/src/secp256k1/src/scalar_4x64_impl.h
+++ b/src/secp256k1/src/scalar_4x64_impl.h
@@ -7,8 +7,6 @@
#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_
#define _SECP256K1_SCALAR_REPR_IMPL_H_
-typedef unsigned __int128 uint128_t;
-
/* Limbs of the secp256k1 order. */
#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL)
#define SECP256K1_N_1 ((uint64_t)0xBAAEDCE6AF48A03BULL)
@@ -69,8 +67,9 @@ SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scal
}
SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar_t *r, unsigned int overflow) {
+ uint128_t t;
VERIFY_CHECK(overflow <= 1);
- uint128_t t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0;
+ t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0;
r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
t += (uint128_t)r->d[1] + overflow * SECP256K1_N_C_1;
r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
@@ -82,6 +81,7 @@ SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar_t *r, unsig
}
static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+ int overflow;
uint128_t t = (uint128_t)a->d[0] + b->d[0];
r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
t += (uint128_t)a->d[1] + b->d[1];
@@ -90,15 +90,16 @@ static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t
r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
t += (uint128_t)a->d[3] + b->d[3];
r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- int overflow = t + secp256k1_scalar_check_overflow(r);
+ overflow = t + secp256k1_scalar_check_overflow(r);
VERIFY_CHECK(overflow == 0 || overflow == 1);
secp256k1_scalar_reduce(r, overflow);
return overflow;
}
static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) {
+ uint128_t t;
VERIFY_CHECK(bit < 256);
- uint128_t t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
+ t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F));
r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
@@ -113,11 +114,12 @@ static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) {
}
static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *b32, int *overflow) {
+ int over;
r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56;
r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56;
r->d[2] = (uint64_t)b32[15] | (uint64_t)b32[14] << 8 | (uint64_t)b32[13] << 16 | (uint64_t)b32[12] << 24 | (uint64_t)b32[11] << 32 | (uint64_t)b32[10] << 40 | (uint64_t)b32[9] << 48 | (uint64_t)b32[8] << 56;
r->d[3] = (uint64_t)b32[7] | (uint64_t)b32[6] << 8 | (uint64_t)b32[5] << 16 | (uint64_t)b32[4] << 24 | (uint64_t)b32[3] << 32 | (uint64_t)b32[2] << 40 | (uint64_t)b32[1] << 48 | (uint64_t)b32[0] << 56;
- int over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r));
+ over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r));
if (overflow) {
*overflow = over;
}
@@ -195,16 +197,16 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */
#define muladd2(a,b) { \
- uint64_t tl, th; \
+ uint64_t tl, th, th2, tl2; \
{ \
uint128_t t = (uint128_t)a * b; \
th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
tl = t; \
} \
- uint64_t th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \
+ th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \
c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
VERIFY_CHECK((th2 >= th) || (c2 != 0)); \
- uint64_t tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \
+ tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \
th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \
c0 += tl2; /* overflow is handled on the next line */ \
th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \
@@ -217,8 +219,9 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */
#define sumadd(a) { \
+ unsigned int over; \
c0 += (a); /* overflow is handled on the next line */ \
- unsigned int over = (c0 < (a)) ? 1 : 0; \
+ over = (c0 < (a)) ? 1 : 0; \
c1 += over; /* overflow is handled on the next line */ \
c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \
}
@@ -248,63 +251,301 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
}
static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint64_t *l) {
- uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7];
+#ifdef USE_ASM_X86_64
+ /* Reduce 512 bits into 385. */
+ uint64_t m0, m1, m2, m3, m4, m5, m6;
+ uint64_t p0, p1, p2, p3, p4;
+ uint64_t c;
+
+ __asm__ __volatile__(
+ /* Preload. */
+ "movq 32(%%rsi), %%r11\n"
+ "movq 40(%%rsi), %%r12\n"
+ "movq 48(%%rsi), %%r13\n"
+ "movq 56(%%rsi), %%r14\n"
+ /* Initialize r8,r9,r10 */
+ "movq 0(%%rsi), %%r8\n"
+ "movq $0, %%r9\n"
+ "movq $0, %%r10\n"
+ /* (r8,r9) += n0 * c0 */
+ "movq %8, %%rax\n"
+ "mulq %%r11\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ /* extract m0 */
+ "movq %%r8, %q0\n"
+ "movq $0, %%r8\n"
+ /* (r9,r10) += l1 */
+ "addq 8(%%rsi), %%r9\n"
+ "adcq $0, %%r10\n"
+ /* (r9,r10,r8) += n1 * c0 */
+ "movq %8, %%rax\n"
+ "mulq %%r12\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* (r9,r10,r8) += n0 * c1 */
+ "movq %9, %%rax\n"
+ "mulq %%r11\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* extract m1 */
+ "movq %%r9, %q1\n"
+ "movq $0, %%r9\n"
+ /* (r10,r8,r9) += l2 */
+ "addq 16(%%rsi), %%r10\n"
+ "adcq $0, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r10,r8,r9) += n2 * c0 */
+ "movq %8, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r10,r8,r9) += n1 * c1 */
+ "movq %9, %%rax\n"
+ "mulq %%r12\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r10,r8,r9) += n0 */
+ "addq %%r11, %%r10\n"
+ "adcq $0, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* extract m2 */
+ "movq %%r10, %q2\n"
+ "movq $0, %%r10\n"
+ /* (r8,r9,r10) += l3 */
+ "addq 24(%%rsi), %%r8\n"
+ "adcq $0, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* (r8,r9,r10) += n3 * c0 */
+ "movq %8, %%rax\n"
+ "mulq %%r14\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* (r8,r9,r10) += n2 * c1 */
+ "movq %9, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* (r8,r9,r10) += n1 */
+ "addq %%r12, %%r8\n"
+ "adcq $0, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* extract m3 */
+ "movq %%r8, %q3\n"
+ "movq $0, %%r8\n"
+ /* (r9,r10,r8) += n3 * c1 */
+ "movq %9, %%rax\n"
+ "mulq %%r14\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* (r9,r10,r8) += n2 */
+ "addq %%r13, %%r9\n"
+ "adcq $0, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* extract m4 */
+ "movq %%r9, %q4\n"
+ /* (r10,r8) += n3 */
+ "addq %%r14, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* extract m5 */
+ "movq %%r10, %q5\n"
+ /* extract m6 */
+ "movq %%r8, %q6\n"
+ : "=g"(m0), "=g"(m1), "=g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6)
+ : "S"(l), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1)
+ : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc");
- /* 160 bit accumulator. */
- uint64_t c0, c1;
- uint32_t c2;
+ /* Reduce 385 bits into 258. */
+ __asm__ __volatile__(
+ /* Preload */
+ "movq %q9, %%r11\n"
+ "movq %q10, %%r12\n"
+ "movq %q11, %%r13\n"
+ /* Initialize (r8,r9,r10) */
+ "movq %q5, %%r8\n"
+ "movq $0, %%r9\n"
+ "movq $0, %%r10\n"
+ /* (r8,r9) += m4 * c0 */
+ "movq %12, %%rax\n"
+ "mulq %%r11\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ /* extract p0 */
+ "movq %%r8, %q0\n"
+ "movq $0, %%r8\n"
+ /* (r9,r10) += m1 */
+ "addq %q6, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* (r9,r10,r8) += m5 * c0 */
+ "movq %12, %%rax\n"
+ "mulq %%r12\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* (r9,r10,r8) += m4 * c1 */
+ "movq %13, %%rax\n"
+ "mulq %%r11\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* extract p1 */
+ "movq %%r9, %q1\n"
+ "movq $0, %%r9\n"
+ /* (r10,r8,r9) += m2 */
+ "addq %q7, %%r10\n"
+ "adcq $0, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r10,r8,r9) += m6 * c0 */
+ "movq %12, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r10,r8,r9) += m5 * c1 */
+ "movq %13, %%rax\n"
+ "mulq %%r12\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r10,r8,r9) += m4 */
+ "addq %%r11, %%r10\n"
+ "adcq $0, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* extract p2 */
+ "movq %%r10, %q2\n"
+ /* (r8,r9) += m3 */
+ "addq %q8, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r8,r9) += m6 * c1 */
+ "movq %13, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ /* (r8,r9) += m5 */
+ "addq %%r12, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* extract p3 */
+ "movq %%r8, %q3\n"
+ /* (r9) += m6 */
+ "addq %%r13, %%r9\n"
+ /* extract p4 */
+ "movq %%r9, %q4\n"
+ : "=&g"(p0), "=&g"(p1), "=&g"(p2), "=g"(p3), "=g"(p4)
+ : "g"(m0), "g"(m1), "g"(m2), "g"(m3), "g"(m4), "g"(m5), "g"(m6), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1)
+ : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "cc");
+
+ /* Reduce 258 bits into 256. */
+ __asm__ __volatile__(
+ /* Preload */
+ "movq %q5, %%r10\n"
+ /* (rax,rdx) = p4 * c0 */
+ "movq %7, %%rax\n"
+ "mulq %%r10\n"
+ /* (rax,rdx) += p0 */
+ "addq %q1, %%rax\n"
+ "adcq $0, %%rdx\n"
+ /* extract r0 */
+ "movq %%rax, 0(%q6)\n"
+ /* Move to (r8,r9) */
+ "movq %%rdx, %%r8\n"
+ "movq $0, %%r9\n"
+ /* (r8,r9) += p1 */
+ "addq %q2, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r8,r9) += p4 * c1 */
+ "movq %8, %%rax\n"
+ "mulq %%r10\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ /* Extract r1 */
+ "movq %%r8, 8(%q6)\n"
+ "movq $0, %%r8\n"
+ /* (r9,r8) += p4 */
+ "addq %%r10, %%r9\n"
+ "adcq $0, %%r8\n"
+ /* (r9,r8) += p2 */
+ "addq %q3, %%r9\n"
+ "adcq $0, %%r8\n"
+ /* Extract r2 */
+ "movq %%r9, 16(%q6)\n"
+ "movq $0, %%r9\n"
+ /* (r8,r9) += p3 */
+ "addq %q4, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* Extract r3 */
+ "movq %%r8, 24(%q6)\n"
+ /* Extract c */
+ "movq %%r9, %q0\n"
+ : "=g"(c)
+ : "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1)
+ : "rax", "rdx", "r8", "r9", "r10", "cc", "memory");
+#else
+ uint128_t c;
+ uint64_t c0, c1, c2;
+ uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7];
+ uint64_t m0, m1, m2, m3, m4, m5;
+ uint32_t m6;
+ uint64_t p0, p1, p2, p3;
+ uint32_t p4;
/* Reduce 512 bits into 385. */
/* m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C. */
c0 = l[0]; c1 = 0; c2 = 0;
muladd_fast(n0, SECP256K1_N_C_0);
- uint64_t m0; extract_fast(m0);
+ extract_fast(m0);
sumadd_fast(l[1]);
muladd(n1, SECP256K1_N_C_0);
muladd(n0, SECP256K1_N_C_1);
- uint64_t m1; extract(m1);
+ extract(m1);
sumadd(l[2]);
muladd(n2, SECP256K1_N_C_0);
muladd(n1, SECP256K1_N_C_1);
sumadd(n0);
- uint64_t m2; extract(m2);
+ extract(m2);
sumadd(l[3]);
muladd(n3, SECP256K1_N_C_0);
muladd(n2, SECP256K1_N_C_1);
sumadd(n1);
- uint64_t m3; extract(m3);
+ extract(m3);
muladd(n3, SECP256K1_N_C_1);
sumadd(n2);
- uint64_t m4; extract(m4);
+ extract(m4);
sumadd_fast(n3);
- uint64_t m5; extract_fast(m5);
+ extract_fast(m5);
VERIFY_CHECK(c0 <= 1);
- uint32_t m6 = c0;
+ m6 = c0;
/* Reduce 385 bits into 258. */
/* p[0..4] = m[0..3] + m[4..6] * SECP256K1_N_C. */
c0 = m0; c1 = 0; c2 = 0;
muladd_fast(m4, SECP256K1_N_C_0);
- uint64_t p0; extract_fast(p0);
+ extract_fast(p0);
sumadd_fast(m1);
muladd(m5, SECP256K1_N_C_0);
muladd(m4, SECP256K1_N_C_1);
- uint64_t p1; extract(p1);
+ extract(p1);
sumadd(m2);
muladd(m6, SECP256K1_N_C_0);
muladd(m5, SECP256K1_N_C_1);
sumadd(m4);
- uint64_t p2; extract(p2);
+ extract(p2);
sumadd_fast(m3);
muladd_fast(m6, SECP256K1_N_C_1);
sumadd_fast(m5);
- uint64_t p3; extract_fast(p3);
- uint32_t p4 = c0 + m6;
+ extract_fast(p3);
+ p4 = c0 + m6;
VERIFY_CHECK(p4 <= 2);
/* Reduce 258 bits into 256. */
/* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */
- uint128_t c = p0 + (uint128_t)SECP256K1_N_C_0 * p4;
+ c = p0 + (uint128_t)SECP256K1_N_C_0 * p4;
r->d[0] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
c += p1 + (uint128_t)SECP256K1_N_C_1 * p4;
r->d[1] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
@@ -312,12 +553,146 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint64_t *l
r->d[2] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
c += p3;
r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
+#endif
/* Final reduction of r. */
secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r));
}
static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+#ifdef USE_ASM_X86_64
+ const uint64_t *pb = b->d;
+ __asm__ __volatile__(
+ /* Preload */
+ "movq 0(%%rdi), %%r15\n"
+ "movq 8(%%rdi), %%rbx\n"
+ "movq 16(%%rdi), %%rcx\n"
+ "movq 0(%%rdx), %%r11\n"
+ "movq 8(%%rdx), %%r12\n"
+ "movq 16(%%rdx), %%r13\n"
+ "movq 24(%%rdx), %%r14\n"
+ /* (rax,rdx) = a0 * b0 */
+ "movq %%r15, %%rax\n"
+ "mulq %%r11\n"
+ /* Extract l0 */
+ "movq %%rax, 0(%%rsi)\n"
+ /* (r8,r9,r10) = (rdx) */
+ "movq %%rdx, %%r8\n"
+ "xorq %%r9, %%r9\n"
+ "xorq %%r10, %%r10\n"
+ /* (r8,r9,r10) += a0 * b1 */
+ "movq %%r15, %%rax\n"
+ "mulq %%r12\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* (r8,r9,r10) += a1 * b0 */
+ "movq %%rbx, %%rax\n"
+ "mulq %%r11\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* Extract l1 */
+ "movq %%r8, 8(%%rsi)\n"
+ "xorq %%r8, %%r8\n"
+ /* (r9,r10,r8) += a0 * b2 */
+ "movq %%r15, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* (r9,r10,r8) += a1 * b1 */
+ "movq %%rbx, %%rax\n"
+ "mulq %%r12\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* (r9,r10,r8) += a2 * b0 */
+ "movq %%rcx, %%rax\n"
+ "mulq %%r11\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* Extract l2 */
+ "movq %%r9, 16(%%rsi)\n"
+ "xorq %%r9, %%r9\n"
+ /* (r10,r8,r9) += a0 * b3 */
+ "movq %%r15, %%rax\n"
+ "mulq %%r14\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* Preload a3 */
+ "movq 24(%%rdi), %%r15\n"
+ /* (r10,r8,r9) += a1 * b2 */
+ "movq %%rbx, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r10,r8,r9) += a2 * b1 */
+ "movq %%rcx, %%rax\n"
+ "mulq %%r12\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r10,r8,r9) += a3 * b0 */
+ "movq %%r15, %%rax\n"
+ "mulq %%r11\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* Extract l3 */
+ "movq %%r10, 24(%%rsi)\n"
+ "xorq %%r10, %%r10\n"
+ /* (r8,r9,r10) += a1 * b3 */
+ "movq %%rbx, %%rax\n"
+ "mulq %%r14\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* (r8,r9,r10) += a2 * b2 */
+ "movq %%rcx, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* (r8,r9,r10) += a3 * b1 */
+ "movq %%r15, %%rax\n"
+ "mulq %%r12\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* Extract l4 */
+ "movq %%r8, 32(%%rsi)\n"
+ "xorq %%r8, %%r8\n"
+ /* (r9,r10,r8) += a2 * b3 */
+ "movq %%rcx, %%rax\n"
+ "mulq %%r14\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* (r9,r10,r8) += a3 * b2 */
+ "movq %%r15, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* Extract l5 */
+ "movq %%r9, 40(%%rsi)\n"
+ /* (r10,r8) += a3 * b3 */
+ "movq %%r15, %%rax\n"
+ "mulq %%r14\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ /* Extract l6 */
+ "movq %%r10, 48(%%rsi)\n"
+ /* Extract l7 */
+ "movq %%r8, 56(%%rsi)\n"
+ : "+d"(pb)
+ : "S"(l), "D"(a->d)
+ : "rax", "rbx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc", "memory");
+#else
/* 160 bit accumulator. */
uint64_t c0 = 0, c1 = 0;
uint32_t c2 = 0;
@@ -348,9 +723,119 @@ static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar_t *a,
extract_fast(l[6]);
VERIFY_CHECK(c1 <= 0);
l[7] = c0;
+#endif
}
static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar_t *a) {
+#ifdef USE_ASM_X86_64
+ __asm__ __volatile__(
+ /* Preload */
+ "movq 0(%%rdi), %%r11\n"
+ "movq 8(%%rdi), %%r12\n"
+ "movq 16(%%rdi), %%r13\n"
+ "movq 24(%%rdi), %%r14\n"
+ /* (rax,rdx) = a0 * a0 */
+ "movq %%r11, %%rax\n"
+ "mulq %%r11\n"
+ /* Extract l0 */
+ "movq %%rax, 0(%%rsi)\n"
+ /* (r8,r9,r10) = (rdx,0) */
+ "movq %%rdx, %%r8\n"
+ "xorq %%r9, %%r9\n"
+ "xorq %%r10, %%r10\n"
+ /* (r8,r9,r10) += 2 * a0 * a1 */
+ "movq %%r11, %%rax\n"
+ "mulq %%r12\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* Extract l1 */
+ "movq %%r8, 8(%%rsi)\n"
+ "xorq %%r8, %%r8\n"
+ /* (r9,r10,r8) += 2 * a0 * a2 */
+ "movq %%r11, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* (r9,r10,r8) += a1 * a1 */
+ "movq %%r12, %%rax\n"
+ "mulq %%r12\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* Extract l2 */
+ "movq %%r9, 16(%%rsi)\n"
+ "xorq %%r9, %%r9\n"
+ /* (r10,r8,r9) += 2 * a0 * a3 */
+ "movq %%r11, %%rax\n"
+ "mulq %%r14\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* (r10,r8,r9) += 2 * a1 * a2 */
+ "movq %%r12, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ "adcq $0, %%r9\n"
+ /* Extract l3 */
+ "movq %%r10, 24(%%rsi)\n"
+ "xorq %%r10, %%r10\n"
+ /* (r8,r9,r10) += 2 * a1 * a3 */
+ "movq %%r12, %%rax\n"
+ "mulq %%r14\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* (r8,r9,r10) += a2 * a2 */
+ "movq %%r13, %%rax\n"
+ "mulq %%r13\n"
+ "addq %%rax, %%r8\n"
+ "adcq %%rdx, %%r9\n"
+ "adcq $0, %%r10\n"
+ /* Extract l4 */
+ "movq %%r8, 32(%%rsi)\n"
+ "xorq %%r8, %%r8\n"
+ /* (r9,r10,r8) += 2 * a2 * a3 */
+ "movq %%r13, %%rax\n"
+ "mulq %%r14\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ "addq %%rax, %%r9\n"
+ "adcq %%rdx, %%r10\n"
+ "adcq $0, %%r8\n"
+ /* Extract l5 */
+ "movq %%r9, 40(%%rsi)\n"
+ /* (r10,r8) += a3 * a3 */
+ "movq %%r14, %%rax\n"
+ "mulq %%r14\n"
+ "addq %%rax, %%r10\n"
+ "adcq %%rdx, %%r8\n"
+ /* Extract l6 */
+ "movq %%r10, 48(%%rsi)\n"
+ /* Extract l7 */
+ "movq %%r8, 56(%%rsi)\n"
+ :
+ : "S"(l), "D"(a->d)
+ : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc", "memory");
+#else
/* 160 bit accumulator. */
uint64_t c0 = 0, c1 = 0;
uint32_t c2 = 0;
@@ -375,6 +860,7 @@ static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar_t *a)
extract_fast(l[6]);
VERIFY_CHECK(c1 == 0);
l[7] = c0;
+#endif
}
#undef sumadd
@@ -413,12 +899,15 @@ SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, con
}
SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b, unsigned int shift) {
- VERIFY_CHECK(shift >= 256);
uint64_t l[8];
+ unsigned int shiftlimbs;
+ unsigned int shiftlow;
+ unsigned int shifthigh;
+ VERIFY_CHECK(shift >= 256);
secp256k1_scalar_mul_512(l, a, b);
- unsigned int shiftlimbs = shift >> 6;
- unsigned int shiftlow = shift & 0x3F;
- unsigned int shifthigh = 64 - shiftlow;
+ shiftlimbs = shift >> 6;
+ shiftlow = shift & 0x3F;
+ shifthigh = 64 - shiftlow;
r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0;
r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0;
r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0;
diff --git a/src/secp256k1/src/scalar_8x32.h b/src/secp256k1/src/scalar_8x32.h
index f70328cfc9..f17017e24e 100644
--- a/src/secp256k1/src/scalar_8x32.h
+++ b/src/secp256k1/src/scalar_8x32.h
@@ -14,4 +14,6 @@ typedef struct {
uint32_t d[8];
} secp256k1_scalar_t;
+#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}}
+
#endif
diff --git a/src/secp256k1/src/scalar_8x32_impl.h b/src/secp256k1/src/scalar_8x32_impl.h
index 915cbcddbe..22b31d4112 100644
--- a/src/secp256k1/src/scalar_8x32_impl.h
+++ b/src/secp256k1/src/scalar_8x32_impl.h
@@ -91,8 +91,9 @@ SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scal
}
SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar_t *r, uint32_t overflow) {
+ uint64_t t;
VERIFY_CHECK(overflow <= 1);
- uint64_t t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0;
+ t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0;
r->d[0] = t & 0xFFFFFFFFUL; t >>= 32;
t += (uint64_t)r->d[1] + overflow * SECP256K1_N_C_1;
r->d[1] = t & 0xFFFFFFFFUL; t >>= 32;
@@ -112,6 +113,7 @@ SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar_t *r, uint3
}
static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+ int overflow;
uint64_t t = (uint64_t)a->d[0] + b->d[0];
r->d[0] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)a->d[1] + b->d[1];
@@ -128,15 +130,16 @@ static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t
r->d[6] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)a->d[7] + b->d[7];
r->d[7] = t & 0xFFFFFFFFULL; t >>= 32;
- int overflow = t + secp256k1_scalar_check_overflow(r);
+ overflow = t + secp256k1_scalar_check_overflow(r);
VERIFY_CHECK(overflow == 0 || overflow == 1);
secp256k1_scalar_reduce(r, overflow);
return overflow;
}
static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) {
+ uint64_t t;
VERIFY_CHECK(bit < 256);
- uint64_t t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F));
+ t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F));
r->d[0] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F));
r->d[1] = t & 0xFFFFFFFFULL; t >>= 32;
@@ -159,6 +162,7 @@ static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) {
}
static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *b32, int *overflow) {
+ int over;
r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24;
r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24;
r->d[2] = (uint32_t)b32[23] | (uint32_t)b32[22] << 8 | (uint32_t)b32[21] << 16 | (uint32_t)b32[20] << 24;
@@ -167,7 +171,7 @@ static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char
r->d[5] = (uint32_t)b32[11] | (uint32_t)b32[10] << 8 | (uint32_t)b32[9] << 16 | (uint32_t)b32[8] << 24;
r->d[6] = (uint32_t)b32[7] | (uint32_t)b32[6] << 8 | (uint32_t)b32[5] << 16 | (uint32_t)b32[4] << 24;
r->d[7] = (uint32_t)b32[3] | (uint32_t)b32[2] << 8 | (uint32_t)b32[1] << 16 | (uint32_t)b32[0] << 24;
- int over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r));
+ over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r));
if (overflow) {
*overflow = over;
}
@@ -263,16 +267,16 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */
#define muladd2(a,b) { \
- uint32_t tl, th; \
+ uint32_t tl, th, th2, tl2; \
{ \
uint64_t t = (uint64_t)a * b; \
th = t >> 32; /* at most 0xFFFFFFFE */ \
tl = t; \
} \
- uint32_t th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \
+ th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \
c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
VERIFY_CHECK((th2 >= th) || (c2 != 0)); \
- uint32_t tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \
+ tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \
th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \
c0 += tl2; /* overflow is handled on the next line */ \
th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \
@@ -285,8 +289,9 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */
#define sumadd(a) { \
+ unsigned int over; \
c0 += (a); /* overflow is handled on the next line */ \
- unsigned int over = (c0 < (a)) ? 1 : 0; \
+ over = (c0 < (a)) ? 1 : 0; \
c1 += over; /* overflow is handled on the next line */ \
c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \
}
@@ -316,7 +321,10 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
}
static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint32_t *l) {
+ uint64_t c;
uint32_t n0 = l[8], n1 = l[9], n2 = l[10], n3 = l[11], n4 = l[12], n5 = l[13], n6 = l[14], n7 = l[15];
+ uint32_t m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12;
+ uint32_t p0, p1, p2, p3, p4, p5, p6, p7, p8;
/* 96 bit accumulator. */
uint32_t c0, c1, c2;
@@ -325,115 +333,115 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint32_t *l
/* m[0..12] = l[0..7] + n[0..7] * SECP256K1_N_C. */
c0 = l[0]; c1 = 0; c2 = 0;
muladd_fast(n0, SECP256K1_N_C_0);
- uint32_t m0; extract_fast(m0);
+ extract_fast(m0);
sumadd_fast(l[1]);
muladd(n1, SECP256K1_N_C_0);
muladd(n0, SECP256K1_N_C_1);
- uint32_t m1; extract(m1);
+ extract(m1);
sumadd(l[2]);
muladd(n2, SECP256K1_N_C_0);
muladd(n1, SECP256K1_N_C_1);
muladd(n0, SECP256K1_N_C_2);
- uint32_t m2; extract(m2);
+ extract(m2);
sumadd(l[3]);
muladd(n3, SECP256K1_N_C_0);
muladd(n2, SECP256K1_N_C_1);
muladd(n1, SECP256K1_N_C_2);
muladd(n0, SECP256K1_N_C_3);
- uint32_t m3; extract(m3);
+ extract(m3);
sumadd(l[4]);
muladd(n4, SECP256K1_N_C_0);
muladd(n3, SECP256K1_N_C_1);
muladd(n2, SECP256K1_N_C_2);
muladd(n1, SECP256K1_N_C_3);
sumadd(n0);
- uint32_t m4; extract(m4);
+ extract(m4);
sumadd(l[5]);
muladd(n5, SECP256K1_N_C_0);
muladd(n4, SECP256K1_N_C_1);
muladd(n3, SECP256K1_N_C_2);
muladd(n2, SECP256K1_N_C_3);
sumadd(n1);
- uint32_t m5; extract(m5);
+ extract(m5);
sumadd(l[6]);
muladd(n6, SECP256K1_N_C_0);
muladd(n5, SECP256K1_N_C_1);
muladd(n4, SECP256K1_N_C_2);
muladd(n3, SECP256K1_N_C_3);
sumadd(n2);
- uint32_t m6; extract(m6);
+ extract(m6);
sumadd(l[7]);
muladd(n7, SECP256K1_N_C_0);
muladd(n6, SECP256K1_N_C_1);
muladd(n5, SECP256K1_N_C_2);
muladd(n4, SECP256K1_N_C_3);
sumadd(n3);
- uint32_t m7; extract(m7);
+ extract(m7);
muladd(n7, SECP256K1_N_C_1);
muladd(n6, SECP256K1_N_C_2);
muladd(n5, SECP256K1_N_C_3);
sumadd(n4);
- uint32_t m8; extract(m8);
+ extract(m8);
muladd(n7, SECP256K1_N_C_2);
muladd(n6, SECP256K1_N_C_3);
sumadd(n5);
- uint32_t m9; extract(m9);
+ extract(m9);
muladd(n7, SECP256K1_N_C_3);
sumadd(n6);
- uint32_t m10; extract(m10);
+ extract(m10);
sumadd_fast(n7);
- uint32_t m11; extract_fast(m11);
+ extract_fast(m11);
VERIFY_CHECK(c0 <= 1);
- uint32_t m12 = c0;
+ m12 = c0;
/* Reduce 385 bits into 258. */
/* p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C. */
c0 = m0; c1 = 0; c2 = 0;
muladd_fast(m8, SECP256K1_N_C_0);
- uint32_t p0; extract_fast(p0);
+ extract_fast(p0);
sumadd_fast(m1);
muladd(m9, SECP256K1_N_C_0);
muladd(m8, SECP256K1_N_C_1);
- uint32_t p1; extract(p1);
+ extract(p1);
sumadd(m2);
muladd(m10, SECP256K1_N_C_0);
muladd(m9, SECP256K1_N_C_1);
muladd(m8, SECP256K1_N_C_2);
- uint32_t p2; extract(p2);
+ extract(p2);
sumadd(m3);
muladd(m11, SECP256K1_N_C_0);
muladd(m10, SECP256K1_N_C_1);
muladd(m9, SECP256K1_N_C_2);
muladd(m8, SECP256K1_N_C_3);
- uint32_t p3; extract(p3);
+ extract(p3);
sumadd(m4);
muladd(m12, SECP256K1_N_C_0);
muladd(m11, SECP256K1_N_C_1);
muladd(m10, SECP256K1_N_C_2);
muladd(m9, SECP256K1_N_C_3);
sumadd(m8);
- uint32_t p4; extract(p4);
+ extract(p4);
sumadd(m5);
muladd(m12, SECP256K1_N_C_1);
muladd(m11, SECP256K1_N_C_2);
muladd(m10, SECP256K1_N_C_3);
sumadd(m9);
- uint32_t p5; extract(p5);
+ extract(p5);
sumadd(m6);
muladd(m12, SECP256K1_N_C_2);
muladd(m11, SECP256K1_N_C_3);
sumadd(m10);
- uint32_t p6; extract(p6);
+ extract(p6);
sumadd_fast(m7);
muladd_fast(m12, SECP256K1_N_C_3);
sumadd_fast(m11);
- uint32_t p7; extract_fast(p7);
- uint32_t p8 = c0 + m12;
+ extract_fast(p7);
+ p8 = c0 + m12;
VERIFY_CHECK(p8 <= 2);
/* Reduce 258 bits into 256. */
/* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */
- uint64_t c = p0 + (uint64_t)SECP256K1_N_C_0 * p8;
+ c = p0 + (uint64_t)SECP256K1_N_C_0 * p8;
r->d[0] = c & 0xFFFFFFFFUL; c >>= 32;
c += p1 + (uint64_t)SECP256K1_N_C_1 * p8;
r->d[1] = c & 0xFFFFFFFFUL; c >>= 32;
@@ -454,7 +462,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint32_t *l
secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r));
}
-static void secp256k1_scalar_mul_512(uint32_t l[16], const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+static void secp256k1_scalar_mul_512(uint32_t *l, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
/* 96 bit accumulator. */
uint32_t c0 = 0, c1 = 0, c2 = 0;
@@ -542,7 +550,7 @@ static void secp256k1_scalar_mul_512(uint32_t l[16], const secp256k1_scalar_t *a
l[15] = c0;
}
-static void secp256k1_scalar_sqr_512(uint32_t l[16], const secp256k1_scalar_t *a) {
+static void secp256k1_scalar_sqr_512(uint32_t *l, const secp256k1_scalar_t *a) {
/* 96 bit accumulator. */
uint32_t c0 = 0, c1 = 0, c2 = 0;
@@ -622,6 +630,7 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t
secp256k1_scalar_reduce_512(r, l);
}
+#ifdef USE_ENDOMORPHISM
static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) {
r1->d[0] = a->d[0];
r1->d[1] = a->d[1];
@@ -640,18 +649,22 @@ static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_
r2->d[6] = 0;
r2->d[7] = 0;
}
+#endif
SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0;
}
SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b, unsigned int shift) {
- VERIFY_CHECK(shift >= 256);
uint32_t l[16];
+ unsigned int shiftlimbs;
+ unsigned int shiftlow;
+ unsigned int shifthigh;
+ VERIFY_CHECK(shift >= 256);
secp256k1_scalar_mul_512(l, a, b);
- unsigned int shiftlimbs = shift >> 5;
- unsigned int shiftlow = shift & 0x1F;
- unsigned int shifthigh = 32 - shiftlow;
+ shiftlimbs = shift >> 5;
+ shiftlow = shift & 0x1F;
+ shifthigh = 32 - shiftlow;
r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 480 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0;
r->d[1] = shift < 480 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0;
r->d[2] = shift < 448 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 416 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0;
diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h
index 4408cce2d8..3acbe264ae 100644
--- a/src/secp256k1/src/scalar_impl.h
+++ b/src/secp256k1/src/scalar_impl.h
@@ -24,121 +24,6 @@
#error "Please select scalar implementation"
#endif
-typedef struct {
-#ifndef USE_NUM_NONE
- secp256k1_num_t order;
-#endif
-#ifdef USE_ENDOMORPHISM
- secp256k1_scalar_t minus_lambda, minus_b1, minus_b2, g1, g2;
-#endif
-} secp256k1_scalar_consts_t;
-
-static const secp256k1_scalar_consts_t *secp256k1_scalar_consts = NULL;
-
-static void secp256k1_scalar_start(void) {
- if (secp256k1_scalar_consts != NULL)
- return;
-
- /* Allocate. */
- secp256k1_scalar_consts_t *ret = (secp256k1_scalar_consts_t*)checked_malloc(sizeof(secp256k1_scalar_consts_t));
-
-#ifndef USE_NUM_NONE
- static const unsigned char secp256k1_scalar_consts_order[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
- 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
- 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41
- };
- secp256k1_num_set_bin(&ret->order, secp256k1_scalar_consts_order, sizeof(secp256k1_scalar_consts_order));
-#endif
-#ifdef USE_ENDOMORPHISM
- /**
- * Lambda is a scalar which has the property for secp256k1 that point multiplication by
- * it is efficiently computable (see secp256k1_gej_mul_lambda). */
- static const unsigned char secp256k1_scalar_consts_lambda[32] = {
- 0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,
- 0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,
- 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,
- 0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72
- };
- /**
- * "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm
- * (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1
- * and k2 have a small size.
- * It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are:
- *
- * - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
- * - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3}
- * - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8}
- * - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
- *
- * The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives
- * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and
- * compute k1 as k - k2 * lambda, avoiding the need for constants a1 and a2.
- *
- * g1, g2 are precomputed constants used to replace division with a rounded multiplication
- * when decomposing the scalar for an endomorphism-based point multiplication.
- *
- * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve
- * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5.
- *
- * The derivation is described in the paper "Efficient Software Implementation of Public-Key
- * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez),
- * Section 4.3 (here we use a somewhat higher-precision estimate):
- * d = a1*b2 - b1*a2
- * g1 = round((2^272)*b2/d)
- * g2 = round((2^272)*b1/d)
- *
- * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found
- * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda').
- */
- static const unsigned char secp256k1_scalar_consts_minus_b1[32] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,
- 0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3
- };
- static const unsigned char secp256k1_scalar_consts_b2[32] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,
- 0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15
- };
- static const unsigned char secp256k1_scalar_consts_g1[32] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x86,
- 0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,
- 0x90,0xe4,0x92,0x84,0xeb,0x15,0x3d,0xab
- };
- static const unsigned char secp256k1_scalar_consts_g2[32] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x43,
- 0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,
- 0x7f,0xa9,0x0a,0xbf,0xe4,0xc4,0x22,0x12
- };
-
- secp256k1_scalar_set_b32(&ret->minus_lambda, secp256k1_scalar_consts_lambda, NULL);
- secp256k1_scalar_negate(&ret->minus_lambda, &ret->minus_lambda);
- secp256k1_scalar_set_b32(&ret->minus_b1, secp256k1_scalar_consts_minus_b1, NULL);
- secp256k1_scalar_set_b32(&ret->minus_b2, secp256k1_scalar_consts_b2, NULL);
- secp256k1_scalar_negate(&ret->minus_b2, &ret->minus_b2);
- secp256k1_scalar_set_b32(&ret->g1, secp256k1_scalar_consts_g1, NULL);
- secp256k1_scalar_set_b32(&ret->g2, secp256k1_scalar_consts_g2, NULL);
-#endif
-
- /* Set the global pointer. */
- secp256k1_scalar_consts = ret;
-}
-
-static void secp256k1_scalar_stop(void) {
- if (secp256k1_scalar_consts == NULL)
- return;
-
- secp256k1_scalar_consts_t *c = (secp256k1_scalar_consts_t*)secp256k1_scalar_consts;
- secp256k1_scalar_consts = NULL;
- free(c);
-}
-
#ifndef USE_NUM_NONE
static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a) {
unsigned char c[32];
@@ -146,12 +31,21 @@ static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_
secp256k1_num_set_bin(r, c, 32);
}
+/** secp256k1 curve order, see secp256k1_ecdsa_const_order_as_fe in ecdsa_impl.h */
static void secp256k1_scalar_order_get_num(secp256k1_num_t *r) {
- *r = secp256k1_scalar_consts->order;
+ static const unsigned char order[32] = {
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+ 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
+ 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41
+ };
+ secp256k1_num_set_bin(r, order, 32);
}
#endif
static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *x) {
+ secp256k1_scalar_t *t;
+ int i;
/* First compute x ^ (2^N - 1) for some values of N. */
secp256k1_scalar_t x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127;
@@ -175,129 +69,129 @@ static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scal
secp256k1_scalar_mul(&x8, &x8, x);
secp256k1_scalar_sqr(&x15, &x8);
- for (int i=0; i<6; i++)
+ for (i = 0; i < 6; i++)
secp256k1_scalar_sqr(&x15, &x15);
secp256k1_scalar_mul(&x15, &x15, &x7);
secp256k1_scalar_sqr(&x30, &x15);
- for (int i=0; i<14; i++)
+ for (i = 0; i < 14; i++)
secp256k1_scalar_sqr(&x30, &x30);
secp256k1_scalar_mul(&x30, &x30, &x15);
secp256k1_scalar_sqr(&x60, &x30);
- for (int i=0; i<29; i++)
+ for (i = 0; i < 29; i++)
secp256k1_scalar_sqr(&x60, &x60);
secp256k1_scalar_mul(&x60, &x60, &x30);
secp256k1_scalar_sqr(&x120, &x60);
- for (int i=0; i<59; i++)
+ for (i = 0; i < 59; i++)
secp256k1_scalar_sqr(&x120, &x120);
secp256k1_scalar_mul(&x120, &x120, &x60);
secp256k1_scalar_sqr(&x127, &x120);
- for (int i=0; i<6; i++)
+ for (i = 0; i < 6; i++)
secp256k1_scalar_sqr(&x127, &x127);
secp256k1_scalar_mul(&x127, &x127, &x7);
/* Then accumulate the final result (t starts at x127). */
- secp256k1_scalar_t *t = &x127;
- for (int i=0; i<2; i++) /* 0 */
+ t = &x127;
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<4; i++) /* 0 */
+ for (i = 0; i < 4; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); /* 111 */
- for (int i=0; i<2; i++) /* 0 */
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<2; i++) /* 0 */
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<2; i++) /* 0 */
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<4; i++) /* 0 */
+ for (i = 0; i < 4; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); /* 111 */
- for (int i=0; i<3; i++) /* 0 */
+ for (i = 0; i < 3; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); /* 11 */
- for (int i=0; i<4; i++) /* 0 */
+ for (i = 0; i < 4; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); /* 111 */
- for (int i=0; i<5; i++) /* 00 */
+ for (i = 0; i < 5; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); /* 111 */
- for (int i=0; i<4; i++) /* 00 */
+ for (i = 0; i < 4; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); /* 11 */
- for (int i=0; i<2; i++) /* 0 */
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<2; i++) /* 0 */
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<5; i++) /* 0 */
+ for (i = 0; i < 5; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x4); /* 1111 */
- for (int i=0; i<2; i++) /* 0 */
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<3; i++) /* 00 */
+ for (i = 0; i < 3; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<4; i++) /* 000 */
+ for (i = 0; i < 4; i++) /* 000 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<2; i++) /* 0 */
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<10; i++) /* 0000000 */
+ for (i = 0; i < 10; i++) /* 0000000 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); /* 111 */
- for (int i=0; i<4; i++) /* 0 */
+ for (i = 0; i < 4; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); /* 111 */
- for (int i=0; i<9; i++) /* 0 */
+ for (i = 0; i < 9; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x8); /* 11111111 */
- for (int i=0; i<2; i++) /* 0 */
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<3; i++) /* 00 */
+ for (i = 0; i < 3; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<3; i++) /* 00 */
+ for (i = 0; i < 3; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<5; i++) /* 0 */
+ for (i = 0; i < 5; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x4); /* 1111 */
- for (int i=0; i<2; i++) /* 0 */
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<5; i++) /* 000 */
+ for (i = 0; i < 5; i++) /* 000 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); /* 11 */
- for (int i=0; i<4; i++) /* 00 */
+ for (i = 0; i < 4; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); /* 11 */
- for (int i=0; i<2; i++) /* 0 */
+ for (i = 0; i < 2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<8; i++) /* 000000 */
+ for (i = 0; i < 8; i++) /* 000000 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); /* 11 */
- for (int i=0; i<3; i++) /* 0 */
+ for (i = 0; i < 3; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); /* 11 */
- for (int i=0; i<3; i++) /* 00 */
+ for (i = 0; i < 3; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<6; i++) /* 00000 */
+ for (i = 0; i < 6; i++) /* 00000 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); /* 1 */
- for (int i=0; i<8; i++) /* 00 */
+ for (i = 0; i < 8; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(r, t, &x6); /* 111111 */
}
@@ -307,10 +201,11 @@ static void secp256k1_scalar_inverse_var(secp256k1_scalar_t *r, const secp256k1_
secp256k1_scalar_inverse(r, x);
#elif defined(USE_SCALAR_INV_NUM)
unsigned char b[32];
+ secp256k1_num_t n, m;
secp256k1_scalar_get_b32(b, x);
- secp256k1_num_t n;
secp256k1_num_set_bin(&n, b, 32);
- secp256k1_num_mod_inverse(&n, &n, &secp256k1_scalar_consts->order);
+ secp256k1_scalar_order_get_num(&m);
+ secp256k1_num_mod_inverse(&n, &n, &m);
secp256k1_num_get_bin(b, 32, &n);
secp256k1_scalar_set_b32(r, b, NULL);
#else
@@ -319,16 +214,74 @@ static void secp256k1_scalar_inverse_var(secp256k1_scalar_t *r, const secp256k1_
}
#ifdef USE_ENDOMORPHISM
+/**
+ * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where
+ * lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,
+ * 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72}
+ *
+ * "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm
+ * (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1
+ * and k2 have a small size.
+ * It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are:
+ *
+ * - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
+ * - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3}
+ * - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8}
+ * - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
+ *
+ * The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives
+ * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and
+ * compute k1 as k - k2 * lambda, avoiding the need for constants a1 and a2.
+ *
+ * g1, g2 are precomputed constants used to replace division with a rounded multiplication
+ * when decomposing the scalar for an endomorphism-based point multiplication.
+ *
+ * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve
+ * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5.
+ *
+ * The derivation is described in the paper "Efficient Software Implementation of Public-Key
+ * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez),
+ * Section 4.3 (here we use a somewhat higher-precision estimate):
+ * d = a1*b2 - b1*a2
+ * g1 = round((2^272)*b2/d)
+ * g2 = round((2^272)*b1/d)
+ *
+ * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found
+ * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda').
+ *
+ * The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order).
+ */
+
static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) {
+ secp256k1_scalar_t c1, c2;
+ static const secp256k1_scalar_t minus_lambda = SECP256K1_SCALAR_CONST(
+ 0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL,
+ 0xA880B9FCUL, 0x8EC739C2UL, 0xE0CFC810UL, 0xB51283CFUL
+ );
+ static const secp256k1_scalar_t minus_b1 = SECP256K1_SCALAR_CONST(
+ 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+ 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL
+ );
+ static const secp256k1_scalar_t minus_b2 = SECP256K1_SCALAR_CONST(
+ 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL,
+ 0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL
+ );
+ static const secp256k1_scalar_t g1 = SECP256K1_SCALAR_CONST(
+ 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00003086UL,
+ 0xD221A7D4UL, 0x6BCDE86CUL, 0x90E49284UL, 0xEB153DABUL
+ );
+ static const secp256k1_scalar_t g2 = SECP256K1_SCALAR_CONST(
+ 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0000E443UL,
+ 0x7ED6010EUL, 0x88286F54UL, 0x7FA90ABFUL, 0xE4C42212UL
+ );
VERIFY_CHECK(r1 != a);
VERIFY_CHECK(r2 != a);
- secp256k1_scalar_t c1, c2;
- secp256k1_scalar_mul_shift_var(&c1, a, &secp256k1_scalar_consts->g1, 272);
- secp256k1_scalar_mul_shift_var(&c2, a, &secp256k1_scalar_consts->g2, 272);
- secp256k1_scalar_mul(&c1, &c1, &secp256k1_scalar_consts->minus_b1);
- secp256k1_scalar_mul(&c2, &c2, &secp256k1_scalar_consts->minus_b2);
+ secp256k1_scalar_mul_shift_var(&c1, a, &g1, 272);
+ secp256k1_scalar_mul_shift_var(&c2, a, &g2, 272);
+ secp256k1_scalar_mul(&c1, &c1, &minus_b1);
+ secp256k1_scalar_mul(&c2, &c2, &minus_b2);
secp256k1_scalar_add(r2, &c1, &c2);
- secp256k1_scalar_mul(r1, r2, &secp256k1_scalar_consts->minus_lambda);
+ secp256k1_scalar_mul(r1, r2, &minus_lambda);
secp256k1_scalar_add(r1, r1, a);
}
#endif
diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c
index 58bcd8d009..8c4eca4b62 100644
--- a/src/secp256k1/src/secp256k1.c
+++ b/src/secp256k1/src/secp256k1.c
@@ -20,10 +20,6 @@
#include "hash_impl.h"
void secp256k1_start(unsigned int flags) {
- secp256k1_fe_start();
- secp256k1_ge_start();
- secp256k1_scalar_start();
- secp256k1_ecdsa_start();
if (flags & SECP256K1_START_SIGN) {
secp256k1_ecmult_gen_start();
}
@@ -35,46 +31,43 @@ void secp256k1_start(unsigned int flags) {
void secp256k1_stop(void) {
secp256k1_ecmult_stop();
secp256k1_ecmult_gen_stop();
- secp256k1_ecdsa_stop();
- secp256k1_scalar_stop();
- secp256k1_ge_stop();
- secp256k1_fe_stop();
}
int secp256k1_ecdsa_verify(const unsigned char *msg32, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) {
+ secp256k1_ge_t q;
+ secp256k1_ecdsa_sig_t s;
+ secp256k1_scalar_t m;
+ int ret = -3;
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(sig != NULL);
DEBUG_CHECK(pubkey != NULL);
- int ret = -3;
- secp256k1_scalar_t m;
- secp256k1_ecdsa_sig_t s;
- secp256k1_ge_t q;
secp256k1_scalar_set_b32(&m, msg32, NULL);
- if (!secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) {
+ if (secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) {
+ if (secp256k1_ecdsa_sig_parse(&s, sig, siglen)) {
+ if (secp256k1_ecdsa_sig_verify(&s, &q, &m)) {
+ /* success is 1, all other values are fail */
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ } else {
+ ret = -2;
+ }
+ } else {
ret = -1;
- goto end;
- }
- if (!secp256k1_ecdsa_sig_parse(&s, sig, siglen)) {
- ret = -2;
- goto end;
}
- if (!secp256k1_ecdsa_sig_verify(&s, &q, &m)) {
- ret = 0;
- goto end;
- }
- ret = 1;
-end:
+
return ret;
}
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) {
- (void)data;
secp256k1_rfc6979_hmac_sha256_t rng;
- secp256k1_rfc6979_hmac_sha256_initialize(&rng, key32, 32, msg32, 32);
- for (unsigned int i = 0; i <= counter; i++) {
+ unsigned int i;
+ secp256k1_rfc6979_hmac_sha256_initialize(&rng, key32, 32, msg32, 32, data, data != NULL ? 32 : 0);
+ for (i = 0; i <= counter; i++) {
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
}
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
@@ -85,6 +78,11 @@ const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979 = nonce_functi
const secp256k1_nonce_function_t secp256k1_nonce_function_default = nonce_function_rfc6979;
int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, int *signaturelen, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) {
+ secp256k1_ecdsa_sig_t sig;
+ secp256k1_scalar_t sec, non, msg;
+ int ret = 0;
+ int overflow = 0;
+ unsigned int count = 0;
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(signature != NULL);
@@ -94,38 +92,44 @@ int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, i
noncefp = secp256k1_nonce_function_default;
}
- secp256k1_scalar_t sec, non, msg;
- secp256k1_scalar_set_b32(&sec, seckey, NULL);
- secp256k1_scalar_set_b32(&msg, msg32, NULL);
- int overflow = 0;
- int ret = 0;
- unsigned int count = 0;
- secp256k1_ecdsa_sig_t sig;
- while (1) {
- unsigned char nonce32[32];
- ret = noncefp(nonce32, msg32, seckey, count, noncedata);
- if (!ret) {
- break;
- }
- secp256k1_scalar_set_b32(&non, nonce32, &overflow);
- memset(nonce32, 0, 32);
- if (!secp256k1_scalar_is_zero(&non) && !overflow) {
- if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL)) {
+ secp256k1_scalar_set_b32(&sec, seckey, &overflow);
+ /* Fail if the secret key is invalid. */
+ if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
+ secp256k1_scalar_set_b32(&msg, msg32, NULL);
+ while (1) {
+ unsigned char nonce32[32];
+ ret = noncefp(nonce32, msg32, seckey, count, noncedata);
+ if (!ret) {
break;
}
+ secp256k1_scalar_set_b32(&non, nonce32, &overflow);
+ memset(nonce32, 0, 32);
+ if (!secp256k1_scalar_is_zero(&non) && !overflow) {
+ if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL)) {
+ break;
+ }
+ }
+ count++;
+ }
+ if (ret) {
+ ret = secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig);
}
- count++;
+ secp256k1_scalar_clear(&msg);
+ secp256k1_scalar_clear(&non);
+ secp256k1_scalar_clear(&sec);
}
- if (ret) {
- ret = secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig);
+ if (!ret) {
+ *signaturelen = 0;
}
- secp256k1_scalar_clear(&msg);
- secp256k1_scalar_clear(&non);
- secp256k1_scalar_clear(&sec);
return ret;
}
int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata, int *recid) {
+ secp256k1_ecdsa_sig_t sig;
+ secp256k1_scalar_t sec, non, msg;
+ int ret = 0;
+ int overflow = 0;
+ unsigned int count = 0;
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(sig64 != NULL);
@@ -134,39 +138,45 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig6
noncefp = secp256k1_nonce_function_default;
}
- secp256k1_scalar_t sec, non, msg;
- secp256k1_scalar_set_b32(&sec, seckey, NULL);
- secp256k1_scalar_set_b32(&msg, msg32, NULL);
- int overflow = 0;
- int ret = 0;
- unsigned int count = 0;
- secp256k1_ecdsa_sig_t sig;
- while (1) {
- unsigned char nonce32[32];
- ret = noncefp(nonce32, msg32, seckey, count, noncedata);
- if (!ret) {
- break;
- }
- secp256k1_scalar_set_b32(&non, nonce32, &overflow);
- memset(nonce32, 0, 32);
- if (!secp256k1_scalar_is_zero(&non) && !overflow) {
- if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid)) {
+ secp256k1_scalar_set_b32(&sec, seckey, &overflow);
+ /* Fail if the secret key is invalid. */
+ if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
+ secp256k1_scalar_set_b32(&msg, msg32, NULL);
+ while (1) {
+ unsigned char nonce32[32];
+ ret = noncefp(nonce32, msg32, seckey, count, noncedata);
+ if (!ret) {
break;
}
+ secp256k1_scalar_set_b32(&non, nonce32, &overflow);
+ memset(nonce32, 0, 32);
+ if (!secp256k1_scalar_is_zero(&non) && !overflow) {
+ if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid)) {
+ break;
+ }
+ }
+ count++;
+ }
+ if (ret) {
+ secp256k1_scalar_get_b32(sig64, &sig.r);
+ secp256k1_scalar_get_b32(sig64 + 32, &sig.s);
}
- count++;
+ secp256k1_scalar_clear(&msg);
+ secp256k1_scalar_clear(&non);
+ secp256k1_scalar_clear(&sec);
}
- if (ret) {
- secp256k1_scalar_get_b32(sig64, &sig.r);
- secp256k1_scalar_get_b32(sig64 + 32, &sig.s);
+ if (!ret) {
+ memset(sig64, 0, 64);
}
- secp256k1_scalar_clear(&msg);
- secp256k1_scalar_clear(&non);
- secp256k1_scalar_clear(&sec);
return ret;
}
int secp256k1_ecdsa_recover_compact(const unsigned char *msg32, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) {
+ secp256k1_ge_t q;
+ secp256k1_ecdsa_sig_t sig;
+ secp256k1_scalar_t m;
+ int ret = 0;
+ int overflow = 0;
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(sig64 != NULL);
@@ -174,82 +184,87 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg32, const unsigned c
DEBUG_CHECK(pubkeylen != NULL);
DEBUG_CHECK(recid >= 0 && recid <= 3);
- int ret = 0;
- secp256k1_scalar_t m;
- secp256k1_ecdsa_sig_t sig;
- int overflow = 0;
secp256k1_scalar_set_b32(&sig.r, sig64, &overflow);
- if (overflow) {
- return 0;
- }
- secp256k1_scalar_set_b32(&sig.s, sig64 + 32, &overflow);
- if (overflow) {
- return 0;
- }
- secp256k1_scalar_set_b32(&m, msg32, NULL);
+ if (!overflow) {
+ secp256k1_scalar_set_b32(&sig.s, sig64 + 32, &overflow);
+ if (!overflow) {
+ secp256k1_scalar_set_b32(&m, msg32, NULL);
- secp256k1_ge_t q;
- if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) {
- ret = secp256k1_eckey_pubkey_serialize(&q, pubkey, pubkeylen, compressed);
+ if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) {
+ ret = secp256k1_eckey_pubkey_serialize(&q, pubkey, pubkeylen, compressed);
+ }
+ }
}
return ret;
}
int secp256k1_ec_seckey_verify(const unsigned char *seckey) {
- DEBUG_CHECK(seckey != NULL);
-
secp256k1_scalar_t sec;
+ int ret;
int overflow;
+ DEBUG_CHECK(seckey != NULL);
+
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
- int ret = !secp256k1_scalar_is_zero(&sec) && !overflow;
+ ret = !secp256k1_scalar_is_zero(&sec) && !overflow;
secp256k1_scalar_clear(&sec);
return ret;
}
int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) {
+ secp256k1_ge_t q;
DEBUG_CHECK(pubkey != NULL);
- secp256k1_ge_t q;
return secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen);
}
int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) {
+ secp256k1_gej_t pj;
+ secp256k1_ge_t p;
+ secp256k1_scalar_t sec;
+ int overflow;
+ int ret = 0;
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(pubkeylen != NULL);
DEBUG_CHECK(seckey != NULL);
- secp256k1_scalar_t sec;
- secp256k1_scalar_set_b32(&sec, seckey, NULL);
- secp256k1_gej_t pj;
- secp256k1_ecmult_gen(&pj, &sec);
- secp256k1_scalar_clear(&sec);
- secp256k1_ge_t p;
- secp256k1_ge_set_gej(&p, &pj);
- return secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, compressed);
+ secp256k1_scalar_set_b32(&sec, seckey, &overflow);
+ if (!overflow) {
+ secp256k1_ecmult_gen(&pj, &sec);
+ secp256k1_scalar_clear(&sec);
+ secp256k1_ge_set_gej(&p, &pj);
+ ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, compressed);
+ }
+ if (!ret) {
+ *pubkeylen = 0;
+ }
+ return ret;
}
int secp256k1_ec_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) {
+ secp256k1_ge_t p;
+ int ret = 0;
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(pubkeylen != NULL);
- secp256k1_ge_t p;
- if (!secp256k1_eckey_pubkey_parse(&p, pubkey, *pubkeylen))
- return 0;
- return secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, 0);
+ if (secp256k1_eckey_pubkey_parse(&p, pubkey, *pubkeylen)) {
+ ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, 0);
+ }
+ return ret;
}
int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) {
+ secp256k1_scalar_t term;
+ secp256k1_scalar_t sec;
+ int ret = 0;
+ int overflow = 0;
DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(tweak != NULL);
- secp256k1_scalar_t term;
- int overflow = 0;
secp256k1_scalar_set_b32(&term, tweak, &overflow);
- secp256k1_scalar_t sec;
secp256k1_scalar_set_b32(&sec, seckey, NULL);
- int ret = secp256k1_eckey_privkey_tweak_add(&sec, &term) && !overflow;
+ ret = secp256k1_eckey_privkey_tweak_add(&sec, &term) && !overflow;
if (ret) {
secp256k1_scalar_get_b32(seckey, &sec);
}
@@ -260,40 +275,41 @@ int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *t
}
int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
+ secp256k1_ge_t p;
+ secp256k1_scalar_t term;
+ int ret = 0;
+ int overflow = 0;
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL);
- secp256k1_scalar_t term;
- int overflow = 0;
secp256k1_scalar_set_b32(&term, tweak, &overflow);
- if (overflow) {
- return 0;
- }
- secp256k1_ge_t p;
- int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
- if (ret) {
- ret = secp256k1_eckey_pubkey_tweak_add(&p, &term);
- }
- if (ret) {
- int oldlen = pubkeylen;
- ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33);
- VERIFY_CHECK(pubkeylen == oldlen);
+ if (!overflow) {
+ ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
+ if (ret) {
+ ret = secp256k1_eckey_pubkey_tweak_add(&p, &term);
+ }
+ if (ret) {
+ int oldlen = pubkeylen;
+ ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33);
+ VERIFY_CHECK(pubkeylen == oldlen);
+ }
}
return ret;
}
int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) {
+ secp256k1_scalar_t factor;
+ secp256k1_scalar_t sec;
+ int ret = 0;
+ int overflow = 0;
DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(tweak != NULL);
- secp256k1_scalar_t factor;
- int overflow = 0;
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
- secp256k1_scalar_t sec;
secp256k1_scalar_set_b32(&sec, seckey, NULL);
- int ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor) && !overflow;
+ ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor) && !overflow;
if (ret) {
secp256k1_scalar_get_b32(seckey, &sec);
}
@@ -304,50 +320,53 @@ int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *t
}
int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
+ secp256k1_ge_t p;
+ secp256k1_scalar_t factor;
+ int ret = 0;
+ int overflow = 0;
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL);
- secp256k1_scalar_t factor;
- int overflow = 0;
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
- if (overflow) {
- return 0;
- }
- secp256k1_ge_t p;
- int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
- if (ret) {
- ret = secp256k1_eckey_pubkey_tweak_mul(&p, &factor);
- }
- if (ret) {
- int oldlen = pubkeylen;
- ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33);
- VERIFY_CHECK(pubkeylen == oldlen);
+ if (!overflow) {
+ ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
+ if (ret) {
+ ret = secp256k1_eckey_pubkey_tweak_mul(&p, &factor);
+ }
+ if (ret) {
+ int oldlen = pubkeylen;
+ ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33);
+ VERIFY_CHECK(pubkeylen == oldlen);
+ }
}
return ret;
}
int secp256k1_ec_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) {
+ secp256k1_scalar_t key;
+ int ret = 0;
DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(privkey != NULL);
DEBUG_CHECK(privkeylen != NULL);
- secp256k1_scalar_t key;
secp256k1_scalar_set_b32(&key, seckey, NULL);
- int ret = secp256k1_eckey_privkey_serialize(privkey, privkeylen, &key, compressed);
+ ret = secp256k1_eckey_privkey_serialize(privkey, privkeylen, &key, compressed);
secp256k1_scalar_clear(&key);
return ret;
}
int secp256k1_ec_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) {
+ secp256k1_scalar_t key;
+ int ret = 0;
DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(privkey != NULL);
- secp256k1_scalar_t key;
- int ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen);
- if (ret)
+ ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen);
+ if (ret) {
secp256k1_scalar_get_b32(seckey, &key);
+ }
secp256k1_scalar_clear(&key);
return ret;
}
diff --git a/src/secp256k1/src/testrand.h b/src/secp256k1/src/testrand.h
index 018b65cd53..041bb92c47 100644
--- a/src/secp256k1/src/testrand.h
+++ b/src/secp256k1/src/testrand.h
@@ -11,8 +11,10 @@
#include "libsecp256k1-config.h"
#endif
-/** Seed the pseudorandom number generator. */
-SECP256K1_INLINE static void secp256k1_rand_seed(uint64_t v);
+/* A non-cryptographic RNG used only for test infrastructure. */
+
+/** Seed the pseudorandom number generator for testing. */
+SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16);
/** Generate a pseudorandom 32-bit number. */
static uint32_t secp256k1_rand32(void);
diff --git a/src/secp256k1/src/testrand_impl.h b/src/secp256k1/src/testrand_impl.h
index 677c4b9a0e..21c69f1c51 100644
--- a/src/secp256k1/src/testrand_impl.h
+++ b/src/secp256k1/src/testrand_impl.h
@@ -11,44 +11,44 @@
#include <string.h>
#include "testrand.h"
+#include "hash.h"
-static uint32_t secp256k1_Rz = 11, secp256k1_Rw = 11;
+static secp256k1_rfc6979_hmac_sha256_t secp256k1_test_rng;
+static uint32_t secp256k1_test_rng_precomputed[8];
+static int secp256k1_test_rng_precomputed_used = 8;
-SECP256K1_INLINE static void secp256k1_rand_seed(uint64_t v) {
- secp256k1_Rz = v >> 32;
- secp256k1_Rw = v;
-
- if (secp256k1_Rz == 0 || secp256k1_Rz == 0x9068ffffU) {
- secp256k1_Rz = 111;
- }
- if (secp256k1_Rw == 0 || secp256k1_Rw == 0x464fffffU) {
- secp256k1_Rw = 111;
- }
+SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16) {
+ secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, (const unsigned char*)"TestRNG", 7, seed16, 16, NULL, 0);
}
SECP256K1_INLINE static uint32_t secp256k1_rand32(void) {
- secp256k1_Rz = 36969 * (secp256k1_Rz & 0xFFFF) + (secp256k1_Rz >> 16);
- secp256k1_Rw = 18000 * (secp256k1_Rw & 0xFFFF) + (secp256k1_Rw >> 16);
- return (secp256k1_Rw << 16) + (secp256k1_Rw >> 16) + secp256k1_Rz;
+ if (secp256k1_test_rng_precomputed_used == 8) {
+ secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, (unsigned char*)(&secp256k1_test_rng_precomputed[0]), sizeof(secp256k1_test_rng_precomputed));
+ secp256k1_test_rng_precomputed_used = 0;
+ }
+ return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++];
}
static void secp256k1_rand256(unsigned char *b32) {
- for (int i=0; i<8; i++) {
- uint32_t r = secp256k1_rand32();
- b32[i*4 + 0] = (r >> 0) & 0xFF;
- b32[i*4 + 1] = (r >> 8) & 0xFF;
- b32[i*4 + 2] = (r >> 16) & 0xFF;
- b32[i*4 + 3] = (r >> 24) & 0xFF;
- }
+ secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32);
}
static void secp256k1_rand256_test(unsigned char *b32) {
int bits=0;
+ uint64_t ent = 0;
+ int entleft = 0;
memset(b32, 0, 32);
while (bits < 256) {
- uint32_t ent = secp256k1_rand32();
- int now = 1 + ((ent % 64)*((ent >> 6) % 32)+16)/31;
- uint32_t val = 1 & (ent >> 11);
+ int now;
+ uint32_t val;
+ if (entleft < 12) {
+ ent |= ((uint64_t)secp256k1_rand32()) << entleft;
+ entleft += 32;
+ }
+ now = 1 + ((ent % 64)*((ent >> 6) % 32)+16)/31;
+ val = 1 & (ent >> 11);
+ ent >>= 12;
+ entleft -= 12;
while (now > 0 && bits < 256) {
b32[bits / 8] |= val << (bits % 8);
now--;
diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c
index cff32f1d06..f7f1acac64 100644
--- a/src/secp256k1/src/tests.c
+++ b/src/secp256k1/src/tests.c
@@ -36,12 +36,12 @@ void random_field_element_test(secp256k1_fe_t *fe) {
}
void random_field_element_magnitude(secp256k1_fe_t *fe) {
+ secp256k1_fe_t zero;
int n = secp256k1_rand32() % 9;
secp256k1_fe_normalize(fe);
if (n == 0) {
return;
}
- secp256k1_fe_t zero;
secp256k1_fe_clear(&zero);
secp256k1_fe_negate(&zero, &zero, 0);
secp256k1_fe_mul_int(&zero, n - 1);
@@ -61,14 +61,15 @@ void random_group_element_test(secp256k1_ge_t *ge) {
}
void random_group_element_jacobian_test(secp256k1_gej_t *gej, const secp256k1_ge_t *ge) {
+ secp256k1_fe_t z2, z3;
do {
random_field_element_test(&gej->z);
if (!secp256k1_fe_is_zero(&gej->z)) {
break;
}
} while(1);
- secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &gej->z);
- secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &z2, &gej->z);
+ secp256k1_fe_sqr(&z2, &gej->z);
+ secp256k1_fe_mul(&z3, &z2, &gej->z);
secp256k1_fe_mul(&gej->x, &ge->x, &z2);
secp256k1_fe_mul(&gej->y, &ge->y, &z3);
gej->infinity = ge->infinity;
@@ -77,8 +78,8 @@ void random_group_element_jacobian_test(secp256k1_gej_t *gej, const secp256k1_ge
void random_scalar_order_test(secp256k1_scalar_t *num) {
do {
unsigned char b32[32];
- secp256k1_rand256_test(b32);
int overflow = 0;
+ secp256k1_rand256_test(b32);
secp256k1_scalar_set_b32(num, b32, &overflow);
if (overflow || secp256k1_scalar_is_zero(num))
continue;
@@ -89,8 +90,8 @@ void random_scalar_order_test(secp256k1_scalar_t *num) {
void random_scalar_order(secp256k1_scalar_t *num) {
do {
unsigned char b32[32];
- secp256k1_rand256(b32);
int overflow = 0;
+ secp256k1_rand256(b32);
secp256k1_scalar_set_b32(num, b32, &overflow);
if (overflow || secp256k1_scalar_is_zero(num))
continue;
@@ -117,16 +118,17 @@ void run_sha256_tests(void) {
{0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42},
{0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8}
};
- for (int i = 0; i < 8; i++) {
+ int i;
+ for (i = 0; i < 8; i++) {
+ unsigned char out[32];
secp256k1_sha256_t hasher;
secp256k1_sha256_initialize(&hasher);
secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
- unsigned char out[32];
secp256k1_sha256_finalize(&hasher, out);
CHECK(memcmp(out, outputs[i], 32) == 0);
if (strlen(inputs[i]) > 0) {
- secp256k1_sha256_initialize(&hasher);
int split = secp256k1_rand32() % strlen(inputs[i]);
+ secp256k1_sha256_initialize(&hasher);
secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split);
secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split);
secp256k1_sha256_finalize(&hasher, out);
@@ -160,16 +162,17 @@ void run_hmac_sha256_tests(void) {
{0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54},
{0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2}
};
- for (int i = 0; i < 6; i++) {
+ int i;
+ for (i = 0; i < 6; i++) {
secp256k1_hmac_sha256_t hasher;
+ unsigned char out[32];
secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]));
secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
- unsigned char out[32];
secp256k1_hmac_sha256_finalize(&hasher, out);
CHECK(memcmp(out, outputs[i], 32) == 0);
if (strlen(inputs[i]) > 0) {
- secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]));
int split = secp256k1_rand32() % strlen(inputs[i]);
+ secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]));
secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split);
secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split);
secp256k1_hmac_sha256_finalize(&hasher, out);
@@ -197,16 +200,25 @@ void run_rfc6979_hmac_sha256_tests(void) {
secp256k1_rfc6979_hmac_sha256_t rng;
unsigned char out[32];
+ unsigned char zero[1] = {0};
+ int i;
- secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 32, msg1, 32);
- for (int i = 0; i < 3; i++) {
+ secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 32, msg1, 32, NULL, 1);
+ for (i = 0; i < 3; i++) {
secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32);
CHECK(memcmp(out, out1[i], 32) == 0);
}
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
- secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 32, msg2, 32);
- for (int i = 0; i < 3; i++) {
+ secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 32, msg1, 32, zero, 1);
+ for (i = 0; i < 3; i++) {
+ secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32);
+ CHECK(memcmp(out, out1[i], 32) != 0);
+ }
+ secp256k1_rfc6979_hmac_sha256_finalize(&rng);
+
+ secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 32, msg2, 32, zero, 0);
+ for (i = 0; i < 3; i++) {
secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32);
CHECK(memcmp(out, out2[i], 32) == 0);
}
@@ -254,9 +266,10 @@ void test_num_negate(void) {
}
void test_num_add_sub(void) {
- int r = secp256k1_rand32();
secp256k1_num_t n1;
secp256k1_num_t n2;
+ secp256k1_num_t n1p2, n2p1, n1m2, n2m1;
+ int r = secp256k1_rand32();
random_num_order_test(&n1); /* n1 = R1 */
if (r & 1) {
random_num_negate(&n1);
@@ -265,7 +278,6 @@ void test_num_add_sub(void) {
if (r & 2) {
random_num_negate(&n2);
}
- secp256k1_num_t n1p2, n2p1, n1m2, n2m1;
secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */
secp256k1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */
secp256k1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */
@@ -283,7 +295,8 @@ void test_num_add_sub(void) {
}
void run_num_smalltests(void) {
- for (int i=0; i<100*count; i++) {
+ int i;
+ for (i = 0; i < 100*count; i++) {
test_num_negate();
test_num_add_sub();
}
@@ -293,41 +306,45 @@ void run_num_smalltests(void) {
/***** SCALAR TESTS *****/
void scalar_test(void) {
+ secp256k1_scalar_t s;
+ secp256k1_scalar_t s1;
+ secp256k1_scalar_t s2;
+#ifndef USE_NUM_NONE
+ secp256k1_num_t snum, s1num, s2num;
+ secp256k1_num_t order, half_order;
+#endif
unsigned char c[32];
/* Set 's' to a random scalar, with value 'snum'. */
- secp256k1_scalar_t s;
random_scalar_order_test(&s);
/* Set 's1' to a random scalar, with value 's1num'. */
- secp256k1_scalar_t s1;
random_scalar_order_test(&s1);
/* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */
- secp256k1_scalar_t s2;
random_scalar_order_test(&s2);
secp256k1_scalar_get_b32(c, &s2);
#ifndef USE_NUM_NONE
- secp256k1_num_t snum, s1num, s2num;
secp256k1_scalar_get_num(&snum, &s);
secp256k1_scalar_get_num(&s1num, &s1);
secp256k1_scalar_get_num(&s2num, &s2);
- secp256k1_num_t order;
secp256k1_scalar_order_get_num(&order);
- secp256k1_num_t half_order = order;
+ half_order = order;
secp256k1_num_shift(&half_order, 1);
#endif
{
+ int i;
/* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */
secp256k1_scalar_t n;
secp256k1_scalar_set_int(&n, 0);
- for (int i = 0; i < 256; i += 4) {
+ for (i = 0; i < 256; i += 4) {
secp256k1_scalar_t t;
+ int j;
secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4));
- for (int j = 0; j < 4; j++) {
+ for (j = 0; j < 4; j++) {
secp256k1_scalar_add(&n, &n, &n);
}
secp256k1_scalar_add(&n, &n, &t);
@@ -338,16 +355,17 @@ void scalar_test(void) {
{
/* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */
secp256k1_scalar_t n;
- secp256k1_scalar_set_int(&n, 0);
int i = 0;
+ secp256k1_scalar_set_int(&n, 0);
while (i < 256) {
+ secp256k1_scalar_t t;
+ int j;
int now = (secp256k1_rand32() % 15) + 1;
if (now + i > 256) {
now = 256 - i;
}
- secp256k1_scalar_t t;
secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now));
- for (int j = 0; j < now; j++) {
+ for (j = 0; j < now; j++) {
secp256k1_scalar_add(&n, &n, &n);
}
secp256k1_scalar_add(&n, &n, &t);
@@ -360,23 +378,23 @@ void scalar_test(void) {
{
/* Test that adding the scalars together is equal to adding their numbers together modulo the order. */
secp256k1_num_t rnum;
+ secp256k1_num_t r2num;
+ secp256k1_scalar_t r;
secp256k1_num_add(&rnum, &snum, &s2num);
secp256k1_num_mod(&rnum, &order);
- secp256k1_scalar_t r;
secp256k1_scalar_add(&r, &s, &s2);
- secp256k1_num_t r2num;
secp256k1_scalar_get_num(&r2num, &r);
CHECK(secp256k1_num_eq(&rnum, &r2num));
}
{
/* Test that multipying the scalars is equal to multiplying their numbers modulo the order. */
+ secp256k1_scalar_t r;
+ secp256k1_num_t r2num;
secp256k1_num_t rnum;
secp256k1_num_mul(&rnum, &snum, &s2num);
secp256k1_num_mod(&rnum, &order);
- secp256k1_scalar_t r;
secp256k1_scalar_mul(&r, &s, &s2);
- secp256k1_num_t r2num;
secp256k1_scalar_get_num(&r2num, &r);
CHECK(secp256k1_num_eq(&rnum, &r2num));
/* The result can only be zero if at least one of the factors was zero. */
@@ -387,20 +405,20 @@ void scalar_test(void) {
}
{
+ secp256k1_scalar_t neg;
+ secp256k1_num_t negnum;
+ secp256k1_num_t negnum2;
/* Check that comparison with zero matches comparison with zero on the number. */
CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s));
/* Check that comparison with the half order is equal to testing for high scalar. */
CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &half_order) > 0));
- secp256k1_scalar_t neg;
secp256k1_scalar_negate(&neg, &s);
- secp256k1_num_t negnum;
secp256k1_num_sub(&negnum, &order, &snum);
secp256k1_num_mod(&negnum, &order);
/* Check that comparison with the half order is equal to testing for high scalar after negation. */
CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &half_order) > 0));
/* Negating should change the high property, unless the value was already zero. */
CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s));
- secp256k1_num_t negnum2;
secp256k1_scalar_get_num(&negnum2, &neg);
/* Negating a scalar should be equal to (order - n) mod order on the number. */
CHECK(secp256k1_num_eq(&negnum, &negnum2));
@@ -415,17 +433,17 @@ void scalar_test(void) {
{
/* Test secp256k1_scalar_mul_shift_var. */
secp256k1_scalar_t r;
+ secp256k1_num_t one;
+ secp256k1_num_t rnum;
+ secp256k1_num_t rnum2;
+ unsigned char cone[1] = {0x01};
unsigned int shift = 256 + (secp256k1_rand32() % 257);
secp256k1_scalar_mul_shift_var(&r, &s1, &s2, shift);
- secp256k1_num_t rnum;
secp256k1_num_mul(&rnum, &s1num, &s2num);
secp256k1_num_shift(&rnum, shift - 1);
- secp256k1_num_t one;
- unsigned char cone[1] = {0x01};
secp256k1_num_set_bin(&one, cone, 1);
secp256k1_num_add(&rnum, &rnum, &one);
secp256k1_num_shift(&rnum, 1);
- secp256k1_num_t rnum2;
secp256k1_scalar_get_num(&rnum2, &r);
CHECK(secp256k1_num_eq(&rnum, &rnum2));
}
@@ -435,11 +453,13 @@ void scalar_test(void) {
/* Test that scalar inverses are equal to the inverse of their number modulo the order. */
if (!secp256k1_scalar_is_zero(&s)) {
secp256k1_scalar_t inv;
- secp256k1_scalar_inverse(&inv, &s);
#ifndef USE_NUM_NONE
secp256k1_num_t invnum;
- secp256k1_num_mod_inverse(&invnum, &snum, &order);
secp256k1_num_t invnum2;
+#endif
+ secp256k1_scalar_inverse(&inv, &s);
+#ifndef USE_NUM_NONE
+ secp256k1_num_mod_inverse(&invnum, &snum, &order);
secp256k1_scalar_get_num(&invnum2, &inv);
CHECK(secp256k1_num_eq(&invnum, &invnum2));
#endif
@@ -461,15 +481,18 @@ void scalar_test(void) {
}
{
+ secp256k1_scalar_t r1, r2;
+ secp256k1_scalar_t b;
+ int i;
/* Test add_bit. */
int bit = secp256k1_rand32() % 256;
- secp256k1_scalar_t b;
secp256k1_scalar_set_int(&b, 1);
CHECK(secp256k1_scalar_is_one(&b));
- for (int i = 0; i < bit; i++) {
+ for (i = 0; i < bit; i++) {
secp256k1_scalar_add(&b, &b, &b);
}
- secp256k1_scalar_t r1 = s1, r2 = s1;
+ r1 = s1;
+ r2 = s1;
if (!secp256k1_scalar_add(&r1, &r1, &b)) {
/* No overflow happened. */
secp256k1_scalar_add_bit(&r2, bit);
@@ -551,7 +574,8 @@ void scalar_test(void) {
}
void run_scalar_tests(void) {
- for (int i = 0; i < 128 * count; i++) {
+ int i;
+ for (i = 0; i < 128 * count; i++) {
scalar_test();
}
@@ -571,11 +595,11 @@ void run_scalar_tests(void) {
{
/* A scalar with value of the curve order should be 0. */
secp256k1_num_t order;
- secp256k1_scalar_order_get_num(&order);
- unsigned char bin[32];
- secp256k1_num_get_bin(bin, 32, &order);
secp256k1_scalar_t zero;
+ unsigned char bin[32];
int overflow = 0;
+ secp256k1_scalar_order_get_num(&order);
+ secp256k1_num_get_bin(bin, 32, &order);
secp256k1_scalar_set_b32(&zero, bin, &overflow);
CHECK(overflow == 1);
CHECK(secp256k1_scalar_is_zero(&zero));
@@ -608,39 +632,67 @@ void random_fe_non_zero(secp256k1_fe_t *nz) {
}
void random_fe_non_square(secp256k1_fe_t *ns) {
- random_fe_non_zero(ns);
secp256k1_fe_t r;
+ random_fe_non_zero(ns);
if (secp256k1_fe_sqrt_var(&r, ns)) {
secp256k1_fe_negate(ns, ns, 1);
}
}
int check_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
- secp256k1_fe_t an = *a; secp256k1_fe_normalize_weak(&an);
- secp256k1_fe_t bn = *b; secp256k1_fe_normalize_var(&bn);
+ secp256k1_fe_t an = *a;
+ secp256k1_fe_t bn = *b;
+ secp256k1_fe_normalize_weak(&an);
+ secp256k1_fe_normalize_var(&bn);
return secp256k1_fe_equal_var(&an, &bn);
}
int check_fe_inverse(const secp256k1_fe_t *a, const secp256k1_fe_t *ai) {
- secp256k1_fe_t x; secp256k1_fe_mul(&x, a, ai);
- secp256k1_fe_t one; secp256k1_fe_set_int(&one, 1);
+ secp256k1_fe_t x;
+ secp256k1_fe_t one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
+ secp256k1_fe_mul(&x, a, ai);
return check_fe_equal(&x, &one);
}
-void run_field_misc(void) {
- const unsigned char f32_5[32] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+void run_field_convert(void) {
+ static const unsigned char b32[32] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
+ 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40
};
+ static const secp256k1_fe_storage_t fes = SECP256K1_FE_STORAGE_CONST(
+ 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL,
+ 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL
+ );
+ static const secp256k1_fe_t fe = SECP256K1_FE_CONST(
+ 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL,
+ 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL
+ );
+ secp256k1_fe_t fe2;
+ unsigned char b322[32];
+ secp256k1_fe_storage_t fes2;
+ /* Check conversions to fe. */
+ CHECK(secp256k1_fe_set_b32(&fe2, b32));
+ CHECK(secp256k1_fe_equal_var(&fe, &fe2));
+ secp256k1_fe_from_storage(&fe2, &fes);
+ CHECK(secp256k1_fe_equal_var(&fe, &fe2));
+ /* Check conversion from fe. */
+ secp256k1_fe_get_b32(b322, &fe);
+ CHECK(memcmp(b322, b32, 32) == 0);
+ secp256k1_fe_to_storage(&fes2, &fe);
+ CHECK(memcmp(&fes2, &fes, sizeof(fes)) == 0);
+}
+
+void run_field_misc(void) {
secp256k1_fe_t x;
secp256k1_fe_t y;
secp256k1_fe_t z;
secp256k1_fe_t q;
- secp256k1_fe_t fe5;
- CHECK(secp256k1_fe_set_b32(&fe5, f32_5));
- for (int i=0; i<5*count; i++) {
+ secp256k1_fe_t fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5);
+ int i;
+ for (i = 0; i < 5*count; i++) {
+ secp256k1_fe_storage_t xs, ys, zs;
random_fe(&x);
random_fe_non_zero(&y);
/* Test the fe equality and comparison operations. */
@@ -649,12 +701,17 @@ void run_field_misc(void) {
z = x;
secp256k1_fe_add(&z,&y);
secp256k1_fe_normalize(&z);
- /* Test the conditional move. */
- secp256k1_fe_cmov(&z, &x, 0);
- CHECK(secp256k1_fe_equal_var(&x, &z) == 0);
- CHECK(secp256k1_fe_cmp_var(&x, &z) != 0);
- secp256k1_fe_cmov(&y, &x, 1);
- CHECK(secp256k1_fe_equal_var(&x, &y));
+ /* Test storage conversion and conditional moves. */
+ secp256k1_fe_to_storage(&xs, &x);
+ secp256k1_fe_to_storage(&ys, &y);
+ secp256k1_fe_to_storage(&zs, &z);
+ secp256k1_fe_storage_cmov(&zs, &xs, 0);
+ CHECK(memcmp(&xs, &zs, sizeof(xs)) != 0);
+ secp256k1_fe_storage_cmov(&ys, &xs, 1);
+ CHECK(memcmp(&xs, &ys, sizeof(xs)) == 0);
+ secp256k1_fe_from_storage(&x, &xs);
+ secp256k1_fe_from_storage(&y, &ys);
+ secp256k1_fe_from_storage(&z, &zs);
/* Test that mul_int, mul, and add agree. */
secp256k1_fe_add(&y, &x);
secp256k1_fe_add(&y, &x);
@@ -678,7 +735,8 @@ void run_field_misc(void) {
void run_field_inv(void) {
secp256k1_fe_t x, xi, xii;
- for (int i=0; i<10*count; i++) {
+ int i;
+ for (i = 0; i < 10*count; i++) {
random_fe_non_zero(&x);
secp256k1_fe_inv(&xi, &x);
CHECK(check_fe_inverse(&x, &xi));
@@ -689,7 +747,8 @@ void run_field_inv(void) {
void run_field_inv_var(void) {
secp256k1_fe_t x, xi, xii;
- for (int i=0; i<10*count; i++) {
+ int i;
+ for (i = 0; i < 10*count; i++) {
random_fe_non_zero(&x);
secp256k1_fe_inv_var(&xi, &x);
CHECK(check_fe_inverse(&x, &xi));
@@ -700,17 +759,19 @@ void run_field_inv_var(void) {
void run_field_inv_all_var(void) {
secp256k1_fe_t x[16], xi[16], xii[16];
+ int i;
/* Check it's safe to call for 0 elements */
secp256k1_fe_inv_all_var(0, xi, x);
- for (int i=0; i<count; i++) {
+ for (i = 0; i < count; i++) {
+ size_t j;
size_t len = (secp256k1_rand32() & 15) + 1;
- for (size_t j=0; j<len; j++)
+ for (j = 0; j < len; j++)
random_fe_non_zero(&x[j]);
secp256k1_fe_inv_all_var(len, xi, x);
- for (size_t j=0; j<len; j++)
+ for (j = 0; j < len; j++)
CHECK(check_fe_inverse(&x[j], &xi[j]));
secp256k1_fe_inv_all_var(len, xii, xi);
- for (size_t j=0; j<len; j++)
+ for (j = 0; j < len; j++)
CHECK(check_fe_equal(&x[j], &xii[j]));
}
}
@@ -719,10 +780,11 @@ void run_sqr(void) {
secp256k1_fe_t x, s;
{
+ int i;
secp256k1_fe_set_int(&x, 1);
secp256k1_fe_negate(&x, &x, 1);
- for (int i=1; i<=512; ++i) {
+ for (i = 1; i <= 512; ++i) {
secp256k1_fe_mul_int(&x, 2);
secp256k1_fe_normalize(&x);
secp256k1_fe_sqr(&s, &x);
@@ -746,6 +808,7 @@ void test_sqrt(const secp256k1_fe_t *a, const secp256k1_fe_t *k) {
void run_sqrt(void) {
secp256k1_fe_t ns, x, s, t;
+ int i;
/* Check sqrt(0) is 0 */
secp256k1_fe_set_int(&x, 0);
@@ -753,7 +816,7 @@ void run_sqrt(void) {
test_sqrt(&s, &x);
/* Check sqrt of small squares (and their negatives) */
- for (int i=1; i<=100; i++) {
+ for (i = 1; i <= 100; i++) {
secp256k1_fe_set_int(&x, i);
secp256k1_fe_sqr(&s, &x);
test_sqrt(&s, &x);
@@ -762,9 +825,10 @@ void run_sqrt(void) {
}
/* Consistency checks for large random values */
- for (int i=0; i<10; i++) {
+ for (i = 0; i < 10; i++) {
+ int j;
random_fe_non_square(&ns);
- for (int j=0; j<count; j++) {
+ for (j = 0; j < count; j++) {
random_fe(&x);
secp256k1_fe_sqr(&s, &x);
test_sqrt(&s, &x);
@@ -787,13 +851,13 @@ void ge_equals_ge(const secp256k1_ge_t *a, const secp256k1_ge_t *b) {
}
void ge_equals_gej(const secp256k1_ge_t *a, const secp256k1_gej_t *b) {
+ secp256k1_fe_t z2s;
+ secp256k1_fe_t u1, u2, s1, s2;
CHECK(a->infinity == b->infinity);
if (a->infinity)
return;
/* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */
- secp256k1_fe_t z2s;
secp256k1_fe_sqr(&z2s, &b->z);
- secp256k1_fe_t u1, u2, s1, s2;
secp256k1_fe_mul(&u1, &a->x, &z2s);
u2 = b->x; secp256k1_fe_normalize_weak(&u2);
secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z);
@@ -803,6 +867,7 @@ void ge_equals_gej(const secp256k1_ge_t *a, const secp256k1_gej_t *b) {
}
void test_ge(void) {
+ int i, i1;
int runs = 4;
/* Points: (infinity, p1, p1, -p1, -p1, p2, p2, -p2, -p2, p3, p3, -p3, -p3, p4, p4, -p4, -p4).
* The second in each pair of identical points uses a random Z coordinate in the Jacobian form.
@@ -814,7 +879,8 @@ void test_ge(void) {
secp256k1_gej_set_infinity(&gej[0]);
secp256k1_ge_clear(&ge[0]);
secp256k1_ge_set_gej_var(&ge[0], &gej[0]);
- for (int i = 0; i < runs; i++) {
+ for (i = 0; i < runs; i++) {
+ int j;
secp256k1_ge_t g;
random_group_element_test(&g);
ge[1 + 4 * i] = g;
@@ -825,7 +891,7 @@ void test_ge(void) {
random_group_element_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]);
secp256k1_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]);
random_group_element_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]);
- for (int j = 0; j < 4; j++) {
+ for (j = 0; j < 4; j++) {
random_field_element_magnitude(&ge[1 + j + 4 * i].x);
random_field_element_magnitude(&ge[1 + j + 4 * i].y);
random_field_element_magnitude(&gej[1 + j + 4 * i].x);
@@ -834,8 +900,9 @@ void test_ge(void) {
}
}
- for (int i1 = 0; i1 < 1 + 4 * runs; i1++) {
- for (int i2 = 0; i2 < 1 + 4 * runs; i2++) {
+ for (i1 = 0; i1 < 1 + 4 * runs; i1++) {
+ int i2;
+ for (i2 = 0; i2 < 1 + 4 * runs; i2++) {
/* Compute reference result using gej + gej (var). */
secp256k1_gej_t refj, resj;
secp256k1_ge_t ref;
@@ -883,11 +950,12 @@ void test_ge(void) {
/* Test adding all points together in random order equals infinity. */
{
+ secp256k1_gej_t sum = SECP256K1_GEJ_CONST_INFINITY;
secp256k1_gej_t *gej_shuffled = malloc((4 * runs + 1) * sizeof(secp256k1_gej_t));
- for (int i = 0; i < 4 * runs + 1; i++) {
+ for (i = 0; i < 4 * runs + 1; i++) {
gej_shuffled[i] = gej[i];
}
- for (int i = 0; i < 4 * runs + 1; i++) {
+ for (i = 0; i < 4 * runs + 1; i++) {
int swap = i + secp256k1_rand32() % (4 * runs + 1 - i);
if (swap != i) {
secp256k1_gej_t t = gej_shuffled[i];
@@ -895,9 +963,7 @@ void test_ge(void) {
gej_shuffled[swap] = t;
}
}
- secp256k1_gej_t sum;
- secp256k1_gej_set_infinity(&sum);
- for (int i = 0; i < 4 * runs + 1; i++) {
+ for (i = 0; i < 4 * runs + 1; i++) {
secp256k1_gej_add_var(&sum, &sum, &gej_shuffled[i]);
}
CHECK(secp256k1_gej_is_infinity(&sum));
@@ -908,7 +974,7 @@ void test_ge(void) {
{
secp256k1_ge_t *ge_set_all = malloc((4 * runs + 1) * sizeof(secp256k1_ge_t));
secp256k1_ge_set_all_gej_var(4 * runs + 1, ge_set_all, gej);
- for (int i = 0; i < 4 * runs + 1; i++) {
+ for (i = 0; i < 4 * runs + 1; i++) {
ge_equals_gej(&ge_set_all[i], &gej[i]);
}
free(ge_set_all);
@@ -919,7 +985,8 @@ void test_ge(void) {
}
void run_ge(void) {
- for (int i = 0; i < count * 32; i++) {
+ int i;
+ for (i = 0; i < count * 32; i++) {
test_ge();
}
}
@@ -928,41 +995,35 @@ void run_ge(void) {
void run_ecmult_chain(void) {
/* random starting point A (on the curve) */
- secp256k1_fe_t ax; VERIFY_CHECK(secp256k1_fe_set_hex(&ax, "8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004", 64));
- secp256k1_fe_t ay; VERIFY_CHECK(secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64));
- secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay);
+ secp256k1_gej_t a = SECP256K1_GEJ_CONST(
+ 0x8b30bbe9, 0xae2a9906, 0x96b22f67, 0x0709dff3,
+ 0x727fd8bc, 0x04d3362c, 0x6c7bf458, 0xe2846004,
+ 0xa357ae91, 0x5c4a6528, 0x1309edf2, 0x0504740f,
+ 0x0eb33439, 0x90216b4f, 0x81063cb6, 0x5f2f7e0f
+ );
/* two random initial factors xn and gn */
- static const unsigned char xni[32] = {
- 0x84, 0xcc, 0x54, 0x52, 0xf7, 0xfd, 0xe1, 0xed,
- 0xb4, 0xd3, 0x8a, 0x8c, 0xe9, 0xb1, 0xb8, 0x4c,
- 0xce, 0xf3, 0x1f, 0x14, 0x6e, 0x56, 0x9b, 0xe9,
- 0x70, 0x5d, 0x35, 0x7a, 0x42, 0x98, 0x54, 0x07
- };
- secp256k1_scalar_t xn;
- secp256k1_scalar_set_b32(&xn, xni, NULL);
- static const unsigned char gni[32] = {
- 0xa1, 0xe5, 0x8d, 0x22, 0x55, 0x3d, 0xcd, 0x42,
- 0xb2, 0x39, 0x80, 0x62, 0x5d, 0x4c, 0x57, 0xa9,
- 0x6e, 0x93, 0x23, 0xd4, 0x2b, 0x31, 0x52, 0xe5,
- 0xca, 0x2c, 0x39, 0x90, 0xed, 0xc7, 0xc9, 0xde
- };
- secp256k1_scalar_t gn;
- secp256k1_scalar_set_b32(&gn, gni, NULL);
+ secp256k1_scalar_t xn = SECP256K1_SCALAR_CONST(
+ 0x84cc5452, 0xf7fde1ed, 0xb4d38a8c, 0xe9b1b84c,
+ 0xcef31f14, 0x6e569be9, 0x705d357a, 0x42985407
+ );
+ secp256k1_scalar_t gn = SECP256K1_SCALAR_CONST(
+ 0xa1e58d22, 0x553dcd42, 0xb2398062, 0x5d4c57a9,
+ 0x6e9323d4, 0x2b3152e5, 0xca2c3990, 0xedc7c9de
+ );
/* two small multipliers to be applied to xn and gn in every iteration: */
- static const unsigned char xfi[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x13,0x37};
- secp256k1_scalar_t xf;
- secp256k1_scalar_set_b32(&xf, xfi, NULL);
- static const unsigned char gfi[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x71,0x13};
- secp256k1_scalar_t gf;
- secp256k1_scalar_set_b32(&gf, gfi, NULL);
+ static const secp256k1_scalar_t xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337);
+ static const secp256k1_scalar_t gf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x7113);
/* accumulators with the resulting coefficients to A and G */
- secp256k1_scalar_t ae;
- secp256k1_scalar_set_int(&ae, 1);
- secp256k1_scalar_t ge;
- secp256k1_scalar_set_int(&ge, 0);
- /* the point being computed */
+ secp256k1_scalar_t ae = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1);
+ secp256k1_scalar_t ge = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
+ /* actual points */
secp256k1_gej_t x = a;
- for (int i=0; i<200*count; i++) {
+ secp256k1_gej_t x2;
+ int i;
+
+ /* the point being computed */
+ x = a;
+ for (i = 0; i < 200*count; i++) {
/* in each iteration, compute X = xn*X + gn*G; */
secp256k1_ecmult(&x, &x, &xn, &gn);
/* also compute ae and ge: the actual accumulated factors for A and G */
@@ -976,78 +1037,84 @@ void run_ecmult_chain(void) {
/* verify */
if (i == 19999) {
- char res[132]; int resl = 132;
- secp256k1_gej_get_hex(res, &resl, &x);
- CHECK(strcmp(res, "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)") == 0);
+ /* expected result after 19999 iterations */
+ secp256k1_gej_t rp = SECP256K1_GEJ_CONST(
+ 0xD6E96687, 0xF9B10D09, 0x2A6F3543, 0x9D86CEBE,
+ 0xA4535D0D, 0x409F5358, 0x6440BD74, 0xB933E830,
+ 0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D,
+ 0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88
+ );
+
+ secp256k1_gej_neg(&rp, &rp);
+ secp256k1_gej_add_var(&rp, &rp, &x);
+ CHECK(secp256k1_gej_is_infinity(&rp));
}
}
/* redo the computation, but directly with the resulting ae and ge coefficients: */
- secp256k1_gej_t x2; secp256k1_ecmult(&x2, &a, &ae, &ge);
- char res[132]; int resl = 132;
- char res2[132]; int resl2 = 132;
- secp256k1_gej_get_hex(res, &resl, &x);
- secp256k1_gej_get_hex(res2, &resl2, &x2);
- CHECK(strcmp(res, res2) == 0);
- CHECK(strlen(res) == 131);
+ secp256k1_ecmult(&x2, &a, &ae, &ge);
+ secp256k1_gej_neg(&x2, &x2);
+ secp256k1_gej_add_var(&x2, &x2, &x);
+ CHECK(secp256k1_gej_is_infinity(&x2));
}
void test_point_times_order(const secp256k1_gej_t *point) {
- unsigned char pub[65];
/* X * (point + G) + (order-X) * (pointer + G) = 0 */
secp256k1_scalar_t x;
- random_scalar_order_test(&x);
secp256k1_scalar_t nx;
- secp256k1_scalar_negate(&nx, &x);
secp256k1_gej_t res1, res2;
+ secp256k1_ge_t res3;
+ unsigned char pub[65];
+ int psize = 65;
+ random_scalar_order_test(&x);
+ secp256k1_scalar_negate(&nx, &x);
secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */
secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
secp256k1_gej_add_var(&res1, &res1, &res2);
CHECK(secp256k1_gej_is_infinity(&res1));
CHECK(secp256k1_gej_is_valid_var(&res1) == 0);
- secp256k1_ge_t res3;
secp256k1_ge_set_gej(&res3, &res1);
CHECK(secp256k1_ge_is_infinity(&res3));
CHECK(secp256k1_ge_is_valid_var(&res3) == 0);
- int psize = 65;
CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0);
psize = 65;
CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0);
}
void run_point_times_order(void) {
- secp256k1_fe_t x; VERIFY_CHECK(secp256k1_fe_set_hex(&x, "02", 2));
- for (int i=0; i<500; i++) {
+ int i;
+ secp256k1_fe_t x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2);
+ static const secp256k1_fe_t xr = SECP256K1_FE_CONST(
+ 0x7603CB59, 0xB0EF6C63, 0xFE608479, 0x2A0C378C,
+ 0xDB3233A8, 0x0F8A9A09, 0xA877DEAD, 0x31B38C45
+ );
+ for (i = 0; i < 500; i++) {
secp256k1_ge_t p;
if (secp256k1_ge_set_xo_var(&p, &x, 1)) {
- CHECK(secp256k1_ge_is_valid_var(&p));
secp256k1_gej_t j;
+ CHECK(secp256k1_ge_is_valid_var(&p));
secp256k1_gej_set_ge(&j, &p);
CHECK(secp256k1_gej_is_valid_var(&j));
test_point_times_order(&j);
}
secp256k1_fe_sqr(&x, &x);
}
- char c[65];
- int cl = 1;
- c[1] = 123;
- secp256k1_fe_get_hex(c, &cl, &x); /* Check that fe_get_hex handles a too short input. */
- CHECK(c[1] == 123);
- cl = 65;
- secp256k1_fe_get_hex(c, &cl, &x);
- CHECK(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0);
+ secp256k1_fe_normalize_var(&x);
+ CHECK(secp256k1_fe_equal_var(&x, &xr));
}
void test_wnaf(const secp256k1_scalar_t *number, int w) {
secp256k1_scalar_t x, two, t;
+ int wnaf[256];
+ int zeroes = -1;
+ int i;
+ int bits;
secp256k1_scalar_set_int(&x, 0);
secp256k1_scalar_set_int(&two, 2);
- int wnaf[256];
- int bits = secp256k1_ecmult_wnaf(wnaf, number, w);
+ bits = secp256k1_ecmult_wnaf(wnaf, number, w);
CHECK(bits <= 256);
- int zeroes = -1;
- for (int i=bits-1; i>=0; i--) {
- secp256k1_scalar_mul(&x, &x, &two);
+ for (i = bits-1; i >= 0; i--) {
int v = wnaf[i];
+ secp256k1_scalar_mul(&x, &x, &two);
if (v) {
CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */
zeroes=0;
@@ -1070,8 +1137,9 @@ void test_wnaf(const secp256k1_scalar_t *number, int w) {
}
void run_wnaf(void) {
+ int i;
secp256k1_scalar_t n;
- for (int i=0; i<count; i++) {
+ for (i = 0; i < count; i++) {
random_scalar_order(&n);
if (i % 1)
secp256k1_scalar_negate(&n, &n);
@@ -1087,26 +1155,29 @@ void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *key, cons
}
void test_ecdsa_sign_verify(void) {
+ secp256k1_gej_t pubj;
+ secp256k1_ge_t pub;
+ secp256k1_scalar_t one;
+ secp256k1_scalar_t msg, key;
+ secp256k1_ecdsa_sig_t sig;
int recid;
int getrec;
- secp256k1_scalar_t msg, key;
random_scalar_order_test(&msg);
random_scalar_order_test(&key);
- secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key);
- secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj);
- secp256k1_ecdsa_sig_t sig;
+ secp256k1_ecmult_gen(&pubj, &key);
+ secp256k1_ge_set_gej(&pub, &pubj);
getrec = secp256k1_rand32()&1;
random_sign(&sig, &key, &msg, getrec?&recid:NULL);
if (getrec) CHECK(recid >= 0 && recid < 4);
CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
- secp256k1_scalar_t one;
secp256k1_scalar_set_int(&one, 1);
secp256k1_scalar_add(&msg, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
}
void run_ecdsa_sign_verify(void) {
- for (int i=0; i<10*count; i++) {
+ int i;
+ for (i = 0; i < 10*count; i++) {
test_ecdsa_sign_verify();
}
}
@@ -1149,9 +1220,32 @@ static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char
return nonce_function_rfc6979(nonce32, msg32, key32, counter - 5, data);
}
+int is_empty_compact_signature(const unsigned char *sig64) {
+ static const unsigned char res[64] = {0};
+ return memcmp(sig64, res, 64) == 0;
+}
+
void test_ecdsa_end_to_end(void) {
+ unsigned char extra[32] = {0x00};
unsigned char privkey[32];
unsigned char message[32];
+ unsigned char privkey2[32];
+ unsigned char csignature[64];
+ unsigned char signature[72];
+ unsigned char signature2[72];
+ unsigned char signature3[72];
+ unsigned char signature4[72];
+ unsigned char pubkey[65];
+ unsigned char recpubkey[65];
+ unsigned char seckey[300];
+ int signaturelen = 72;
+ int signaturelen2 = 72;
+ int signaturelen3 = 72;
+ int signaturelen4 = 72;
+ int recid = 0;
+ int recpubkeylen = 0;
+ int pubkeylen = 65;
+ int seckeylen = 300;
/* Generate a random key and message. */
{
@@ -1164,7 +1258,6 @@ void test_ecdsa_end_to_end(void) {
/* Construct and verify corresponding public key. */
CHECK(secp256k1_ec_seckey_verify(privkey) == 1);
- unsigned char pubkey[65]; int pubkeylen = 65;
CHECK(secp256k1_ec_pubkey_create(pubkey, &pubkeylen, privkey, (secp256k1_rand32() & 3) != 0) == 1);
if (secp256k1_rand32() & 1) {
CHECK(secp256k1_ec_pubkey_decompress(pubkey, &pubkeylen));
@@ -1172,52 +1265,73 @@ void test_ecdsa_end_to_end(void) {
CHECK(secp256k1_ec_pubkey_verify(pubkey, pubkeylen));
/* Verify private key import and export. */
- unsigned char seckey[300]; int seckeylen = 300;
CHECK(secp256k1_ec_privkey_export(privkey, seckey, &seckeylen, secp256k1_rand32() % 2) == 1);
- unsigned char privkey2[32];
CHECK(secp256k1_ec_privkey_import(privkey2, seckey, seckeylen) == 1);
CHECK(memcmp(privkey, privkey2, 32) == 0);
/* Optionally tweak the keys using addition. */
if (secp256k1_rand32() % 3 == 0) {
+ int ret1;
+ int ret2;
unsigned char rnd[32];
+ unsigned char pubkey2[65];
+ int pubkeylen2 = 65;
secp256k1_rand256_test(rnd);
- int ret1 = secp256k1_ec_privkey_tweak_add(privkey, rnd);
- int ret2 = secp256k1_ec_pubkey_tweak_add(pubkey, pubkeylen, rnd);
+ ret1 = secp256k1_ec_privkey_tweak_add(privkey, rnd);
+ ret2 = secp256k1_ec_pubkey_tweak_add(pubkey, pubkeylen, rnd);
CHECK(ret1 == ret2);
if (ret1 == 0) return;
- unsigned char pubkey2[65]; int pubkeylen2 = 65;
CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1);
CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0);
}
/* Optionally tweak the keys using multiplication. */
if (secp256k1_rand32() % 3 == 0) {
+ int ret1;
+ int ret2;
unsigned char rnd[32];
+ unsigned char pubkey2[65];
+ int pubkeylen2 = 65;
secp256k1_rand256_test(rnd);
- int ret1 = secp256k1_ec_privkey_tweak_mul(privkey, rnd);
- int ret2 = secp256k1_ec_pubkey_tweak_mul(pubkey, pubkeylen, rnd);
+ ret1 = secp256k1_ec_privkey_tweak_mul(privkey, rnd);
+ ret2 = secp256k1_ec_pubkey_tweak_mul(pubkey, pubkeylen, rnd);
CHECK(ret1 == ret2);
if (ret1 == 0) return;
- unsigned char pubkey2[65]; int pubkeylen2 = 65;
CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1);
CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0);
}
/* Sign. */
- unsigned char signature[72]; int signaturelen = 72;
CHECK(secp256k1_ecdsa_sign(message, signature, &signaturelen, privkey, NULL, NULL) == 1);
+ CHECK(signaturelen > 0);
+ CHECK(secp256k1_ecdsa_sign(message, signature2, &signaturelen2, privkey, NULL, extra) == 1);
+ CHECK(signaturelen2 > 0);
+ extra[31] = 1;
+ CHECK(secp256k1_ecdsa_sign(message, signature3, &signaturelen3, privkey, NULL, extra) == 1);
+ CHECK(signaturelen3 > 0);
+ extra[31] = 0;
+ extra[0] = 1;
+ CHECK(secp256k1_ecdsa_sign(message, signature4, &signaturelen4, privkey, NULL, extra) == 1);
+ CHECK(signaturelen3 > 0);
+ CHECK((signaturelen != signaturelen2) || (memcmp(signature, signature2, signaturelen) != 0));
+ CHECK((signaturelen != signaturelen3) || (memcmp(signature, signature3, signaturelen) != 0));
+ CHECK((signaturelen3 != signaturelen2) || (memcmp(signature3, signature2, signaturelen3) != 0));
+ CHECK((signaturelen4 != signaturelen3) || (memcmp(signature4, signature3, signaturelen4) != 0));
+ CHECK((signaturelen4 != signaturelen2) || (memcmp(signature4, signature2, signaturelen4) != 0));
+ CHECK((signaturelen4 != signaturelen) || (memcmp(signature4, signature, signaturelen4) != 0));
/* Verify. */
CHECK(secp256k1_ecdsa_verify(message, signature, signaturelen, pubkey, pubkeylen) == 1);
+ CHECK(secp256k1_ecdsa_verify(message, signature2, signaturelen2, pubkey, pubkeylen) == 1);
+ CHECK(secp256k1_ecdsa_verify(message, signature3, signaturelen3, pubkey, pubkeylen) == 1);
+ CHECK(secp256k1_ecdsa_verify(message, signature4, signaturelen4, pubkey, pubkeylen) == 1);
/* Destroy signature and verify again. */
signature[signaturelen - 1 - secp256k1_rand32() % 20] += 1 + (secp256k1_rand32() % 255);
CHECK(secp256k1_ecdsa_verify(message, signature, signaturelen, pubkey, pubkeylen) != 1);
/* Compact sign. */
- unsigned char csignature[64]; int recid = 0;
CHECK(secp256k1_ecdsa_sign_compact(message, csignature, privkey, NULL, NULL, &recid) == 1);
+ CHECK(!is_empty_compact_signature(csignature));
/* Recover. */
- unsigned char recpubkey[65]; int recpubkeylen = 0;
CHECK(secp256k1_ecdsa_recover_compact(message, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1);
CHECK(recpubkeylen == pubkeylen);
CHECK(memcmp(pubkey, recpubkey, pubkeylen) == 0);
@@ -1230,6 +1344,8 @@ void test_ecdsa_end_to_end(void) {
}
void test_random_pubkeys(void) {
+ secp256k1_ge_t elem;
+ secp256k1_ge_t elem2;
unsigned char in[65];
/* Generate some randomly sized pubkeys. */
uint32_t r = secp256k1_rand32();
@@ -1247,8 +1363,6 @@ void test_random_pubkeys(void) {
r>>=11;
if (len > 1) secp256k1_rand256(&in[1]);
if (len > 33) secp256k1_rand256(&in[33]);
- secp256k1_ge_t elem;
- secp256k1_ge_t elem2;
if (secp256k1_eckey_pubkey_parse(&elem, in, len)) {
unsigned char out[65];
unsigned char firstb;
@@ -1282,13 +1396,15 @@ void test_random_pubkeys(void) {
}
void run_random_pubkeys(void) {
- for (int i=0; i<10*count; i++) {
+ int i;
+ for (i = 0; i < 10*count; i++) {
test_random_pubkeys();
}
}
void run_ecdsa_end_to_end(void) {
- for (int i=0; i<64*count; i++) {
+ int i;
+ for (i = 0; i < 64*count; i++) {
test_ecdsa_end_to_end();
}
}
@@ -1314,12 +1430,8 @@ void test_ecdsa_edge_cases(void) {
0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57
};
unsigned char pubkey[65];
+ int t;
int pubkeylen = 65;
- CHECK(!secp256k1_ecdsa_recover_compact(msg32, sig64, pubkey, &pubkeylen, 0, 0));
- CHECK(secp256k1_ecdsa_recover_compact(msg32, sig64, pubkey, &pubkeylen, 0, 1));
- CHECK(!secp256k1_ecdsa_recover_compact(msg32, sig64, pubkey, &pubkeylen, 0, 2));
- CHECK(!secp256k1_ecdsa_recover_compact(msg32, sig64, pubkey, &pubkeylen, 0, 3));
-
/* signature (r,s) = (4,4), which can be recovered with all 4 recids. */
const unsigned char sigb64[64] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1333,7 +1445,16 @@ void test_ecdsa_edge_cases(void) {
};
unsigned char pubkeyb[33];
int pubkeyblen = 33;
- for (int recid = 0; recid < 4; recid++) {
+ int recid;
+
+ CHECK(!secp256k1_ecdsa_recover_compact(msg32, sig64, pubkey, &pubkeylen, 0, 0));
+ CHECK(secp256k1_ecdsa_recover_compact(msg32, sig64, pubkey, &pubkeylen, 0, 1));
+ CHECK(!secp256k1_ecdsa_recover_compact(msg32, sig64, pubkey, &pubkeylen, 0, 2));
+ CHECK(!secp256k1_ecdsa_recover_compact(msg32, sig64, pubkey, &pubkeylen, 0, 3));
+
+ for (recid = 0; recid < 4; recid++) {
+ int i;
+ int recid2;
/* (4,4) encoded in DER. */
unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04};
unsigned char sigcder_zr[7] = {0x30, 0x05, 0x02, 0x00, 0x02, 0x01, 0x01};
@@ -1376,7 +1497,7 @@ void test_ecdsa_edge_cases(void) {
};
CHECK(secp256k1_ecdsa_recover_compact(msg32, sigb64, pubkeyb, &pubkeyblen, 1, recid));
CHECK(secp256k1_ecdsa_verify(msg32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 1);
- for (int recid2 = 0; recid2 < 4; recid2++) {
+ for (recid2 = 0; recid2 < 4; recid2++) {
unsigned char pubkey2b[33];
int pubkey2blen = 33;
CHECK(secp256k1_ecdsa_recover_compact(msg32, sigb64, pubkey2b, &pubkey2blen, 1, recid2));
@@ -1402,10 +1523,11 @@ void test_ecdsa_edge_cases(void) {
sigbder[7]--;
CHECK(secp256k1_ecdsa_verify(msg32, sigbder, 6, pubkeyb, pubkeyblen) == -2);
CHECK(secp256k1_ecdsa_verify(msg32, sigbder, sizeof(sigbder)-1, pubkeyb, pubkeyblen) == -2);
- for(int i = 0; i<8; i++) {
+ for(i = 0; i < 8; i++) {
+ int c;
unsigned char orig = sigbder[i];
/*Try every single-byte change.*/
- for (int c=0; c<256; c++) {
+ for (c = 0; c < 256; c++) {
if (c == orig ) continue;
sigbder[i] = c;
CHECK(secp256k1_ecdsa_verify(msg32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) ==
@@ -1417,16 +1539,17 @@ void test_ecdsa_edge_cases(void) {
/* Test the case where ECDSA recomputes a point that is infinity. */
{
+ secp256k1_gej_t keyj;
+ secp256k1_ge_t key;
+ secp256k1_scalar_t msg;
secp256k1_ecdsa_sig_t sig;
secp256k1_scalar_set_int(&sig.s, 1);
secp256k1_scalar_negate(&sig.s, &sig.s);
secp256k1_scalar_inverse(&sig.s, &sig.s);
secp256k1_scalar_set_int(&sig.r, 1);
- secp256k1_gej_t keyj;
secp256k1_ecmult_gen(&keyj, &sig.r);
- secp256k1_ge_t key;
secp256k1_ge_set_gej(&key, &keyj);
- secp256k1_scalar_t msg = sig.s;
+ msg = sig.s;
CHECK(secp256k1_ecdsa_sig_verify(&sig, &key, &msg) == 0);
}
@@ -1489,69 +1612,97 @@ void test_ecdsa_edge_cases(void) {
unsigned char sig[72];
int siglen = 72;
CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce) == 0);
+ CHECK(siglen == 0);
CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce2) == 0);
+ CHECK(siglen == 0);
msg[31] = 0xaa;
siglen = 72;
CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce) == 1);
+ CHECK(siglen > 0);
CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce2) == 1);
+ CHECK(siglen > 0);
siglen = 10;
CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce) != 1);
+ CHECK(siglen == 0);
}
/* Nonce function corner cases. */
- {
+ for (t = 0; t < 2; t++) {
+ static const unsigned char zero[32] = {0x00};
+ int i;
unsigned char key[32];
unsigned char msg[32];
unsigned char sig[72];
- memset(key, 0, 32);
+ unsigned char sig2[72];
+ secp256k1_ecdsa_sig_t s[512];
+ int siglen = 72;
+ int siglen2 = 72;
+ int recid2;
+ const unsigned char *extra;
+ extra = t == 0 ? NULL : zero;
memset(msg, 0, 32);
- key[31] = 1;
msg[31] = 1;
- int siglen = 72;
- int recid;
+ /* High key results in signature failure. */
+ memset(key, 0xFF, 32);
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, extra) == 0);
+ CHECK(siglen == 0);
+ /* Zero key results in signature failure. */
+ memset(key, 0, 32);
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, extra) == 0);
+ CHECK(siglen == 0);
/* Nonce function failure results in signature failure. */
- CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce_function_test_fail, NULL) == 0);
- CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, nonce_function_test_fail, NULL, &recid) == 0);
+ key[31] = 1;
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce_function_test_fail, extra) == 0);
+ CHECK(siglen == 0);
+ CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, nonce_function_test_fail, extra, &recid) == 0);
+ CHECK(is_empty_compact_signature(sig));
/* The retry loop successfully makes its way to the first good value. */
- unsigned char sig2[72];
- int siglen2 = 72;
siglen = 72;
- CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce_function_test_retry, NULL) == 1);
- CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, nonce_function_rfc6979, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce_function_test_retry, extra) == 1);
+ CHECK(siglen > 0);
+ CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, nonce_function_rfc6979, extra) == 1);
+ CHECK(siglen > 0);
CHECK((siglen == siglen2) && (memcmp(sig, sig2, siglen) == 0));
- int recid2;
- CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, nonce_function_test_retry, NULL, &recid) == 1);
- CHECK(secp256k1_ecdsa_sign_compact(msg, sig2, key, nonce_function_rfc6979, NULL, &recid2) == 1);
+ CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, nonce_function_test_retry, extra, &recid) == 1);
+ CHECK(!is_empty_compact_signature(sig));
+ CHECK(secp256k1_ecdsa_sign_compact(msg, sig2, key, nonce_function_rfc6979, extra, &recid2) == 1);
+ CHECK(!is_empty_compact_signature(sig2));
CHECK((recid == recid2) && (memcmp(sig, sig2, 64) == 0));
/* The default nonce function is determinstic. */
siglen = 72;
siglen2 = 72;
- CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, NULL) == 1);
- CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, extra) == 1);
+ CHECK(siglen > 0);
+ CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, extra) == 1);
+ CHECK(siglen2 > 0);
CHECK((siglen == siglen2) && (memcmp(sig, sig2, siglen) == 0));
- CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, NULL, NULL, &recid) == 1);
- CHECK(secp256k1_ecdsa_sign_compact(msg, sig2, key, NULL, NULL, &recid2) == 1);
+ CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, NULL, extra, &recid) == 1);
+ CHECK(!is_empty_compact_signature(sig));
+ CHECK(secp256k1_ecdsa_sign_compact(msg, sig2, key, NULL, extra, &recid2) == 1);
+ CHECK(!is_empty_compact_signature(sig));
CHECK((recid == recid2) && (memcmp(sig, sig2, 64) == 0));
/* The default nonce function changes output with different messages. */
- secp256k1_ecdsa_sig_t s[512];
- for(int i=0; i<256; i++) {
+ for(i = 0; i < 256; i++) {
+ int j;
siglen2 = 72;
msg[0] = i;
- CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, extra) == 1);
+ CHECK(!is_empty_compact_signature(sig));
CHECK(secp256k1_ecdsa_sig_parse(&s[i], sig2, siglen2));
- for (int j=0; j<i; j++) {
+ for (j = 0; j < i; j++) {
CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r));
}
}
msg[0] = 0;
msg[31] = 2;
/* The default nonce function changes output with different keys. */
- for(int i=256; i<512; i++) {
+ for(i = 256; i < 512; i++) {
+ int j;
siglen2 = 72;
key[0] = i - 256;
- CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, extra) == 1);
CHECK(secp256k1_ecdsa_sig_parse(&s[i], sig2, siglen2));
- for (int j=0; j<i; j++) {
+ for (j = 0; j < i; j++) {
CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r));
}
}
@@ -1581,8 +1732,8 @@ void run_ecdsa_edge_cases(void) {
EC_KEY *get_openssl_key(const secp256k1_scalar_t *key) {
unsigned char privkey[300];
int privkeylen;
- int compr = secp256k1_rand32() & 1;
const unsigned char* pbegin = privkey;
+ int compr = secp256k1_rand32() & 1;
EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
CHECK(secp256k1_eckey_privkey_serialize(privkey, &privkeylen, key, compr));
CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen));
@@ -1591,31 +1742,32 @@ EC_KEY *get_openssl_key(const secp256k1_scalar_t *key) {
}
void test_ecdsa_openssl(void) {
+ secp256k1_gej_t qj;
+ secp256k1_ge_t q;
+ secp256k1_ecdsa_sig_t sig;
+ secp256k1_scalar_t one;
+ secp256k1_scalar_t msg2;
secp256k1_scalar_t key, msg;
+ EC_KEY *ec_key;
+ unsigned int sigsize = 80;
+ int secp_sigsize = 80;
unsigned char message[32];
+ unsigned char signature[80];
secp256k1_rand256_test(message);
secp256k1_scalar_set_b32(&msg, message, NULL);
random_scalar_order_test(&key);
- secp256k1_gej_t qj;
secp256k1_ecmult_gen(&qj, &key);
- secp256k1_ge_t q;
secp256k1_ge_set_gej(&q, &qj);
- EC_KEY *ec_key = get_openssl_key(&key);
+ ec_key = get_openssl_key(&key);
CHECK(ec_key);
- unsigned char signature[80];
- unsigned int sigsize = 80;
CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
- secp256k1_ecdsa_sig_t sig;
CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize));
CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg));
- secp256k1_scalar_t one;
secp256k1_scalar_set_int(&one, 1);
- secp256k1_scalar_t msg2;
secp256k1_scalar_add(&msg2, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg2));
random_sign(&sig, &key, &msg, NULL);
- int secp_sigsize = 80;
CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sig));
CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1);
@@ -1623,33 +1775,54 @@ void test_ecdsa_openssl(void) {
}
void run_ecdsa_openssl(void) {
- for (int i=0; i<10*count; i++) {
+ int i;
+ for (i = 0; i < 10*count; i++) {
test_ecdsa_openssl();
}
}
#endif
int main(int argc, char **argv) {
+ unsigned char seed16[16] = {0};
+ unsigned char run32[32] = {0};
/* find iteration count */
if (argc > 1) {
count = strtol(argv[1], NULL, 0);
}
/* find random seed */
- uint64_t seed;
if (argc > 2) {
- seed = strtoull(argv[2], NULL, 0);
+ int pos = 0;
+ const char* ch = argv[2];
+ while (pos < 16 && ch[0] != 0 && ch[1] != 0) {
+ unsigned short sh;
+ if (sscanf(ch, "%2hx", &sh)) {
+ seed16[pos] = sh;
+ } else {
+ break;
+ }
+ ch += 2;
+ pos++;
+ }
} else {
FILE *frand = fopen("/dev/urandom", "r");
- if (!frand || !fread(&seed, sizeof(seed), 1, frand)) {
- seed = time(NULL) * 1337;
+ if (!frand || !fread(&seed16, sizeof(seed16), 1, frand)) {
+ uint64_t t = time(NULL) * (uint64_t)1337;
+ seed16[0] ^= t;
+ seed16[1] ^= t >> 8;
+ seed16[2] ^= t >> 16;
+ seed16[3] ^= t >> 24;
+ seed16[4] ^= t >> 32;
+ seed16[5] ^= t >> 40;
+ seed16[6] ^= t >> 48;
+ seed16[7] ^= t >> 56;
}
fclose(frand);
}
- secp256k1_rand_seed(seed);
+ secp256k1_rand_seed(seed16);
printf("test count = %i\n", count);
- printf("random seed = %llu\n", (unsigned long long)seed);
+ printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]);
/* initialize */
secp256k1_start(SECP256K1_START_SIGN | SECP256K1_START_VERIFY);
@@ -1657,12 +1830,6 @@ int main(int argc, char **argv) {
/* initializing a second time shouldn't cause any harm or memory leaks. */
secp256k1_start(SECP256K1_START_SIGN | SECP256K1_START_VERIFY);
- /* Likewise, re-running the internal init functions should be harmless. */
- secp256k1_fe_start();
- secp256k1_ge_start();
- secp256k1_scalar_start();
- secp256k1_ecdsa_start();
-
run_sha256_tests();
run_hmac_sha256_tests();
run_rfc6979_hmac_sha256_tests();
@@ -1680,6 +1847,7 @@ int main(int argc, char **argv) {
run_field_inv_var();
run_field_inv_all_var();
run_field_misc();
+ run_field_convert();
run_sqr();
run_sqrt();
@@ -1700,18 +1868,13 @@ int main(int argc, char **argv) {
run_ecdsa_openssl();
#endif
- printf("random run = %llu\n", (unsigned long long)secp256k1_rand32() + ((unsigned long long)secp256k1_rand32() << 32));
+ secp256k1_rand256(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]);
/* shutdown */
secp256k1_stop();
/* shutting down twice shouldn't cause any double frees. */
secp256k1_stop();
-
- /* Same for the internal shutdown functions. */
- secp256k1_fe_stop();
- secp256k1_ge_stop();
- secp256k1_scalar_stop();
- secp256k1_ecdsa_stop();
return 0;
}
diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h
index c3a8f3a42b..ae98639f7c 100644
--- a/src/secp256k1/src/util.h
+++ b/src/secp256k1/src/util.h
@@ -27,7 +27,7 @@
} while(0)
#endif
-#ifndef HAVE_BUILTIN_EXPECT
+#ifdef HAVE_BUILTIN_EXPECT
#define EXPECT(x,c) __builtin_expect((x),(c))
#else
#define EXPECT(x,c) (x)
@@ -61,7 +61,7 @@
#define VERIFY_CHECK(cond) do { (void)(cond); } while(0)
#endif
-static inline void *checked_malloc(size_t size) {
+static SECP256K1_INLINE void *checked_malloc(size_t size) {
void *ret = malloc(size);
CHECK(ret != NULL);
return ret;
@@ -84,4 +84,21 @@ static inline void *checked_malloc(size_t size) {
# endif
#endif
+#if defined(_WIN32)
+# define I64FORMAT "I64d"
+# define I64uFORMAT "I64u"
+#else
+# define I64FORMAT "lld"
+# define I64uFORMAT "llu"
+#endif
+
+#if defined(HAVE___INT128)
+# if defined(__GNUC__)
+# define SECP256K1_GNUC_EXT __extension__
+# else
+# define SECP256K1_GNUC_EXT
+# endif
+SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
+#endif
+
#endif
diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp
index 5e1f5f0294..6b6df5199a 100644
--- a/src/test/alert_tests.cpp
+++ b/src/test/alert_tests.cpp
@@ -10,6 +10,7 @@
#include "clientversion.h"
#include "data/alertTests.raw.h"
+#include "chainparams.h"
#include "serialize.h"
#include "streams.h"
#include "util.h"
@@ -119,10 +120,11 @@ BOOST_FIXTURE_TEST_SUITE(Alert_tests, ReadAlerts)
BOOST_AUTO_TEST_CASE(AlertApplies)
{
SetMockTime(11);
+ const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
BOOST_FOREACH(const CAlert& alert, alerts)
{
- BOOST_CHECK(alert.CheckSignature());
+ BOOST_CHECK(alert.CheckSignature(alertKey));
}
BOOST_CHECK(alerts.size() >= 3);
@@ -159,6 +161,7 @@ BOOST_AUTO_TEST_CASE(AlertApplies)
BOOST_AUTO_TEST_CASE(AlertNotify)
{
SetMockTime(11);
+ const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
boost::filesystem::path temp = GetTempPath() / "alertnotify.txt";
boost::filesystem::remove(temp);
@@ -166,7 +169,7 @@ BOOST_AUTO_TEST_CASE(AlertNotify)
mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string();
BOOST_FOREACH(CAlert alert, alerts)
- alert.ProcessAlert(false);
+ alert.ProcessAlert(alertKey, false);
std::vector<std::string> r = read_lines(temp);
BOOST_CHECK_EQUAL(r.size(), 4u);
diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json
index 3c52547a64..271bc70f73 100644
--- a/src/test/data/script_invalid.json
+++ b/src/test/data/script_invalid.json
@@ -522,13 +522,13 @@
["Automatically generated test cases"],
[
- "0x47 0x3044022053205076a7bb12d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801",
+ "0x47 0x304402200a5c6163f07b8c3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
"0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"",
"P2PK, bad sig"
],
[
- "0x47 0x30440220151ea78fa148b59f399b23731b634645ebc142f299ee9838d46fb78cf7e0bc0102200d62327dcd54ac6bcfb1516b035b1bf8eaea438c52c62d3450d1f3a8f030e0de01 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
+ "0x47 0x3044022034bb0494b50b8ef130e2185bb220265b9284ef5b4b8a8da4d8415df489c83b5102206259a26d9cc0a125ac26af6153b17c02956855ebe1467412f066e402f5f05d1201 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
"DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG",
"",
"P2PKH, bad pubkey"
@@ -540,19 +540,19 @@
"P2PK anyonecanpay marked with normal hashtype"
],
[
- "0x47 0x304402202166fcd5e607de452d3c6f15e059505cf21654346592f9650ba906b9e8be88fa022005d976d28eb8de477102feba28807b3ad361e7fa24796d259c9d61452f7c318c01 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
"HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
"P2SH",
"P2SH(P2PK), bad redeemscript"
],
[
- "0x47 0x3044022064cc90ca89ad721384b231653b945579359a24b928ef8539b331172628c9cc6102203e238869ab5dac3fc293db53c12e7dd3079e86cfde9024b689efc7227e4d671001 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
+ "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
"HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
"P2SH",
"P2SH(P2PKH), bad sig"
],
[
- "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0",
+ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"",
"3-of-3, 2 sigs"
@@ -564,13 +564,13 @@
"P2SH(2-of-3), 1 sig"
],
[
- "0x47 0x30440220001d6702bfa4f49c3a2542af9b1c2844a2eaac55f86f310f42d26a5dd17d6a8002202cdadbe608c00b50dd951c6ba0877d5b07a970f3e265c18697bc413a0a86f69901",
+ "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"DERSIG",
"P2PK with too much R padding"
],
[
- "0x48 0x304502207d2b258e959605e2ea50b46fea1325b7391ffb0c14a5b58ef8ad3851da3644380221007e75136df5f2e38216c4338b31c97e8307102edb97d611e06914e1f8fba68ead01",
+ "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"DERSIG",
"P2PK with too much S padding"
@@ -582,19 +582,19 @@
"P2PK with too little R padding"
],
[
- "0x47 0x30440220003040725f724b0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
+ "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"DERSIG",
"P2PK NOT with bad sig with too much R padding"
],
[
- "0x47 0x30440220003040725f724a0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
+ "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"",
"P2PK NOT with too much R padding but no DERSIG"
],
[
- "0x47 0x30440220003040725f724a0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
+ "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"DERSIG",
"P2PK NOT with too much R padding"
@@ -648,19 +648,19 @@
"BIP66 example 6, with DERSIG"
],
[
- "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x304402200b3d0b0375bb15c14620afa4aa10ae90a0d6a046ce217bc20fe0bc1ced68c1b802204b550acab90ae6d3478057c9ad24f9df743815b799b6449dd7e7f6d3bc6e274c01",
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
"DERSIG",
"BIP66 example 7, with DERSIG"
],
[
- "0 0x47 0x30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"",
"BIP66 example 8, without DERSIG"
],
[
- "0 0x47 0x30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"DERSIG",
"BIP66 example 8, with DERSIG"
@@ -678,7 +678,7 @@
"BIP66 example 9, with DERSIG"
],
[
- "0 0 0x47 0x30440220afa76a8f60622f813b05711f051c6c3407e32d1b1b70b0576c1f01b54e4c05c702200d58e9df044fd1845cabfbeef6e624ba0401daf7d7e084736f9ff601c3783bf501",
+ "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"DERSIG",
"BIP66 example 10, with DERSIG"
@@ -708,37 +708,37 @@
"P2PK with high S"
],
[
- "0x47 0x30440220745d63eb70d45652128b450aa5ca7d9b513439963f261cb1c40a60f0785e7ee402204877785b38945ca9dbec78e1c1d4dd12148cc25c868bd27480023b49ae0f310501",
+ "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"STRICTENC",
"P2PK with hybrid pubkey"
],
[
- "0x47 0x30440220606f6f9f6cebc94ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201",
+ "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"",
"P2PK NOT with hybrid pubkey but no STRICTENC"
],
[
- "0x47 0x30440220606f6f9f6cebc94ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201",
+ "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"STRICTENC",
"P2PK NOT with hybrid pubkey"
],
[
- "0x47 0x30440220606f6f9f6cebc84ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201",
+ "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"STRICTENC",
"P2PK NOT with invalid hybrid pubkey"
],
[
- "0 0x47 0x304402203cdcf66792fe97e3955655ede5dad004950e58b369831ffa7743132c507b272c022031fbcfb4a72b3e00217abf2f5557585f1f9891f12827d2f0a2ae2978e7f9f11001",
+ "0 0x47 0x3044022079c7824d6c868e0e1a273484e28c2654a27d043c8a27f49f52cb72efed0759090220452bbbf7089574fa082095a4fc1b3a16bafcf97a3a34d745fafc922cce66b27201",
"1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG",
"STRICTENC",
"1-of-2 with the first 1 hybrid pubkey"
],
[
- "0x47 0x304402201c215cb13e4954e60ce4f6de74941904c771f998de7b1d9627e82a1949fde517022031c2197455f3dbecbb78321201308d7b039424e38d480772d7cd4eb465a083f405",
+ "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"STRICTENC",
"P2PK with undefined hashtype"
@@ -750,7 +750,7 @@
"P2PK NOT with invalid sig and undefined hashtype"
],
[
- "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"NULLDUMMY",
"3-of-3 with nonzero dummy"
@@ -762,7 +762,7 @@
"3-of-3 NOT with invalid sig with nonzero dummy"
],
[
- "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 DUP",
+ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"SIGPUSHONLY",
"2-of-2 with two identical keys and sigs pushed using OP_DUP"
@@ -780,7 +780,7 @@
"P2SH(P2PK) with non-push scriptSig"
],
[
- "11 0x47 0x3044022053205076a7bb13d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801",
+ "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
"0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"CLEANSTACK,P2SH",
"P2PK with unnecessary input"
diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json
index 34e2c8d61a..064dde8464 100644
--- a/src/test/data/script_valid.json
+++ b/src/test/data/script_valid.json
@@ -700,7 +700,7 @@
["Automatically generated test cases"],
[
- "0x47 0x3044022053205076a7bb13d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801",
+ "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
"0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"",
"P2PK"
@@ -718,37 +718,37 @@
"P2PK anyonecanpay"
],
[
- "0x47 0x304402202166fcd5e607de452d3c6f15e059505cf21654346592f9650ba906b9e8be88fa022005d976d28eb8de477102feba28807b3ad361e7fa24796d259c9d61452f7c318c01 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
"HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
"P2SH",
"P2SH(P2PK)"
],
[
- "0x47 0x3044022064cc90ca89ad721384b231653b945579359a24b928ef8539b331172628c9cc6102203e238869ab5dac3fc293db53c12e7dd3079e86cfde9024b689efc7227e4d671001 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
+ "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
"HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
"",
"P2SH(P2PKH), bad sig but no VERIFY_P2SH"
],
[
- "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"",
"3-of-3"
],
[
- "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x304402204511cf05e85c2be07c6c176c5338a08ed3cb34212667f39613340881169986c002207cc48b27aa3691a20706a5773ec9923cadd20fedffd00c24457d85f83f0b51fe01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
+ "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x30440220563e5b3b1fc11662a84bc5ea2a32cc3819703254060ba30d639a1aaf2d5068ad0220601c1f47ddc76d93284dd9ed68f7c9974c4a0ea7cbe8a247d6bc3878567a5fca01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
"HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
"P2SH",
"P2SH(2-of-3)"
],
[
- "0x47 0x30440220001d6702bfa4f49c3a2542af9b1c2844a2eaac55f86f310f42d26a5dd17d6a8002202cdadbe608c00b50dd951c6ba0877d5b07a970f3e265c18697bc413a0a86f69901",
+ "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"",
"P2PK with too much R padding but no DERSIG"
],
[
- "0x48 0x304502207d2b258e959605e2ea50b46fea1325b7391ffb0c14a5b58ef8ad3851da3644380221007e75136df5f2e38216c4338b31c97e8307102edb97d611e06914e1f8fba68ead01",
+ "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"",
"P2PK with too much S padding but no DERSIG"
@@ -760,7 +760,7 @@
"P2PK with too little R padding but no DERSIG"
],
[
- "0x47 0x30440220003040725f724b0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
+ "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"",
"P2PK NOT with bad sig with too much R padding but no DERSIG"
@@ -790,25 +790,25 @@
"BIP66 example 6, without DERSIG"
],
[
- "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x304402200b3d0b0375bb15c14620afa4aa10ae90a0d6a046ce217bc20fe0bc1ced68c1b802204b550acab90ae6d3478057c9ad24f9df743815b799b6449dd7e7f6d3bc6e274c01",
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
"",
"BIP66 example 7, without DERSIG"
],
[
- "0 0 0x47 0x30440220afa76a8f60622f813b05711f051c6c3407e32d1b1b70b0576c1f01b54e4c05c702200d58e9df044fd1845cabfbeef6e624ba0401daf7d7e084736f9ff601c3783bf501",
+ "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"",
"BIP66 example 10, without DERSIG"
],
[
- "0 0x47 0x30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601 0",
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"",
"BIP66 example 12, without DERSIG"
],
[
- "0 0x47 0x30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601 0",
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"DERSIG",
"BIP66 example 12, with DERSIG"
@@ -826,31 +826,31 @@
"P2PK with high S but no LOW_S"
],
[
- "0x47 0x30440220745d63eb70d45652128b450aa5ca7d9b513439963f261cb1c40a60f0785e7ee402204877785b38945ca9dbec78e1c1d4dd12148cc25c868bd27480023b49ae0f310501",
+ "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"",
"P2PK with hybrid pubkey but no STRICTENC"
],
[
- "0x47 0x30440220606f6f9f6cebc84ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201",
+ "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"",
"P2PK NOT with invalid hybrid pubkey but no STRICTENC"
],
[
- "0 0x47 0x304402203a5ee39032637c431af0a3ac42e32e0627390bd44f6f98c9c04e6d714635ad0202207b42fcd889c3ae8a1b515608f38535f1f9be815176ee8d1b65a27c767cf37aed01",
+ "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401",
"1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"",
"1-of-2 with the second 1 hybrid pubkey and no STRICTENC"
],
[
- "0 0x47 0x304402203a5ee39032637c431af0a3ac42e32e0627390bd44f6f98c9c04e6d714635ad0202207b42fcd889c3ae8a1b515608f38535f1f9be815176ee8d1b65a27c767cf37aed01",
+ "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401",
"1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"STRICTENC",
"1-of-2 with the second 1 hybrid pubkey"
],
[
- "0x47 0x304402201c215cb13e4954e60ce4f6de74941904c771f998de7b1d9627e82a1949fde517022031c2197455f3dbecbb78321201308d7b039424e38d480772d7cd4eb465a083f405",
+ "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"",
"P2PK with undefined hashtype but no STRICTENC"
@@ -862,7 +862,7 @@
"P2PK NOT with invalid sig and undefined hashtype but no STRICTENC"
],
[
- "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"",
"3-of-3 with nonzero dummy but no NULLDUMMY"
@@ -874,19 +874,19 @@
"3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY"
],
[
- "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 DUP",
+ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"",
"2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY"
],
[
- "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01",
+ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"SIGPUSHONLY",
"2-of-2 with two identical keys and sigs pushed"
],
[
- "11 0x47 0x3044022053205076a7bb13d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801",
+ "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
"0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"P2SH",
"P2PK with unnecessary input but no CLEANSTACK"
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
new file mode 100644
index 0000000000..0996e13c48
--- /dev/null
+++ b/src/test/mempool_tests.cpp
@@ -0,0 +1,104 @@
+// Copyright (c) 2011-2014 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 "main.h"
+#include "txmempool.h"
+#include "util.h"
+
+#include "test/test_bitcoin.h"
+
+#include <boost/test/unit_test.hpp>
+#include <list>
+
+BOOST_FIXTURE_TEST_SUITE(mempool_tests, TestingSetup)
+
+BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
+{
+ // Test CTxMemPool::remove functionality
+
+ // Parent transaction with three children,
+ // and three grand-children:
+ CMutableTransaction txParent;
+ txParent.vin.resize(1);
+ txParent.vin[0].scriptSig = CScript() << OP_11;
+ txParent.vout.resize(3);
+ for (int i = 0; i < 3; i++)
+ {
+ txParent.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ txParent.vout[i].nValue = 33000LL;
+ }
+ CMutableTransaction txChild[3];
+ for (int i = 0; i < 3; i++)
+ {
+ txChild[i].vin.resize(1);
+ txChild[i].vin[0].scriptSig = CScript() << OP_11;
+ txChild[i].vin[0].prevout.hash = txParent.GetHash();
+ txChild[i].vin[0].prevout.n = i;
+ txChild[i].vout.resize(1);
+ txChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ txChild[i].vout[0].nValue = 11000LL;
+ }
+ CMutableTransaction txGrandChild[3];
+ for (int i = 0; i < 3; i++)
+ {
+ txGrandChild[i].vin.resize(1);
+ txGrandChild[i].vin[0].scriptSig = CScript() << OP_11;
+ txGrandChild[i].vin[0].prevout.hash = txChild[i].GetHash();
+ txGrandChild[i].vin[0].prevout.n = 0;
+ txGrandChild[i].vout.resize(1);
+ txGrandChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ txGrandChild[i].vout[0].nValue = 11000LL;
+ }
+
+
+ CTxMemPool testPool(CFeeRate(0));
+ std::list<CTransaction> removed;
+
+ // Nothing in pool, remove should do nothing:
+ testPool.remove(txParent, removed, true);
+ BOOST_CHECK_EQUAL(removed.size(), 0);
+
+ // Just the parent:
+ testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1));
+ testPool.remove(txParent, removed, true);
+ BOOST_CHECK_EQUAL(removed.size(), 1);
+ removed.clear();
+
+ // Parent, children, grandchildren:
+ testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1));
+ for (int i = 0; i < 3; i++)
+ {
+ testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1));
+ testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1));
+ }
+ // Remove Child[0], GrandChild[0] should be removed:
+ testPool.remove(txChild[0], removed, true);
+ BOOST_CHECK_EQUAL(removed.size(), 2);
+ removed.clear();
+ // ... make sure grandchild and child are gone:
+ testPool.remove(txGrandChild[0], removed, true);
+ BOOST_CHECK_EQUAL(removed.size(), 0);
+ testPool.remove(txChild[0], removed, true);
+ BOOST_CHECK_EQUAL(removed.size(), 0);
+ // Remove parent, all children/grandchildren should go:
+ testPool.remove(txParent, removed, true);
+ BOOST_CHECK_EQUAL(removed.size(), 5);
+ BOOST_CHECK_EQUAL(testPool.size(), 0);
+ removed.clear();
+
+ // Add children and grandchildren, but NOT the parent (simulate the parent being in a block)
+ for (int i = 0; i < 3; i++)
+ {
+ testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1));
+ testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1));
+ }
+ // Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be
+ // put into the mempool (maybe because it is non-standard):
+ testPool.remove(txParent, removed, true);
+ BOOST_CHECK_EQUAL(removed.size(), 6);
+ BOOST_CHECK_EQUAL(testPool.size(), 0);
+ removed.clear();
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 0d50660327..85ea3f77b5 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -444,6 +444,18 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem
LOCK(cs);
std::deque<uint256> txToRemove;
txToRemove.push_back(origTx.GetHash());
+ if (fRecursive && !mapTx.count(origTx.GetHash())) {
+ // If recursively removing but origTx isn't in the mempool
+ // be sure to remove any children that are in the pool. This can
+ // happen during chain re-orgs if origTx isn't re-accepted into
+ // the mempool for any reason.
+ for (unsigned int i = 0; i < origTx.vout.size(); i++) {
+ std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(origTx.GetHash(), i));
+ if (it == mapNextTx.end())
+ continue;
+ txToRemove.push_back(it->second.ptx->GetHash());
+ }
+ }
while (!txToRemove.empty())
{
uint256 hash = txToRemove.front();
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index a10123002e..2566b2712b 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1096,6 +1096,9 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
void CWallet::ReacceptWalletTransactions()
{
+ // If transcations aren't broadcasted, don't let them into local mempool either
+ if (!fBroadcastTransactions)
+ return;
LOCK2(cs_main, cs_wallet);
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
{
@@ -1116,6 +1119,7 @@ void CWallet::ReacceptWalletTransactions()
bool CWalletTx::RelayWalletTransaction()
{
+ assert(pwallet->GetBroadcastTransactions());
if (!IsCoinBase())
{
if (GetDepthInMainChain() == 0) {
@@ -1354,7 +1358,7 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime)
{
// Do this infrequently and randomly to avoid giving away
// that these are our transactions.
- if (GetTime() < nNextResend)
+ if (GetTime() < nNextResend || !fBroadcastTransactions)
return;
bool fFirst = (nNextResend == 0);
nNextResend = GetTime() + GetRand(30 * 60);
@@ -1979,14 +1983,17 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
// Track how many getdata requests our transaction gets
mapRequestCount[wtxNew.GetHash()] = 0;
- // Broadcast
- if (!wtxNew.AcceptToMemoryPool(false))
+ if (fBroadcastTransactions)
{
- // This must not fail. The transaction has already been signed and recorded.
- LogPrintf("CommitTransaction(): Error: Transaction not valid");
- return false;
+ // Broadcast
+ if (!wtxNew.AcceptToMemoryPool(false))
+ {
+ // This must not fail. The transaction has already been signed and recorded.
+ LogPrintf("CommitTransaction(): Error: Transaction not valid");
+ return false;
+ }
+ wtxNew.RelayWalletTransaction();
}
- wtxNew.RelayWalletTransaction();
}
return true;
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 6ae1c87b1d..4dbb0e2e57 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -455,6 +455,7 @@ private:
int64_t nNextResend;
int64_t nLastResend;
+ bool fBroadcastTransactions;
/**
* Used to keep track of spent outpoints, and
@@ -518,6 +519,7 @@ public:
nNextResend = 0;
nLastResend = 0;
nTimeFirstKey = 0;
+ fBroadcastTransactions = false;
}
std::map<uint256, CWalletTx> mapWallet;
@@ -723,6 +725,11 @@ public:
/** Watch-only address added */
boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;
+
+ /** Inquire whether this wallet broadcasts transactions. */
+ bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
+ /** Set whether this wallet broadcasts transactions. */
+ void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
};
/** A key allocated from the key pool. */