clang 7 to 11 (and maybe earlier versions) warn about recid being
potentially unitiliazed in "CHECK(recid >= 0 [...]", which was mitigated
in commit 3d2cf6c5bd35b0d72716b47bdd7e3892388aafc4 by initializing recid
to make clang happy but VG_UNDEF'ing the variable after initializiation
in order to ensure valgrind's memcheck analysis will still be sound and
complain if recid is not actually written to when creating a signature.
However, it turns out that at least for binaries produced by clang 11
(but not clang 7), valgrind complains about a branch on unitialized data
in the recid variable in that line before *and* after the aforementioned
commit. While the complaint after the commit could be spurious (clang
knows that recid is initialized, so it's fine to access it even though
the access is stupid), the complaint before the commit indicates a real
problem: it might be the case that clang is performing a wrong
optimization that leads to a situation where recid is really not
guaranteed to be initialized when it's accessed. As a result, clang
warns about this and generates code that just accesses the variable.
I'm not going to bother with this further because this is fixed in
clang 12 and the problem is just in our test code, not in the tested
code.
This commit rewrites the code in a way that groups the signing together
with the CHECK such that it's very easy to figure out for clang that
recid will be initialized properly. This seems to circument the issue.
unsigned char foo[4] = "abcd" is not valid C++ because the string
literal "abcd" does not fit into foo due to the terminating NUL
character. This is valid in C, it will just omit the NUL character.
Fixes#962.
5f6ceafcfa46a69e901bed87e2c5f323b03b1e8c schnorrsig: allow setting MSGLEN != 32 in benchmark (Jonas Nick)
fdd06b7967196a3b34f73a5b19632637b4bde90a schnorrsig: add tests for sign_custom and varlen msg verification (Jonas Nick)
d8d806aaf386c7ead9431649f899ff82b0185aae schnorrsig: add extra parameter struct for sign_custom (Jonas Nick)
a0c3fc177f7f435e593962504182c3861c47d1be schnorrsig: allow signing and verification of variable length msgs (Jonas Nick)
5a8e4991ad443cc0cc613d80380a2db802a4cbce Add secp256k1_tagged_sha256 as defined in BIP-340 (Jonas Nick)
b6c0b72fb06e3c31121f1ef4403d2a229a31ec1c schnorrsig: remove noncefp args from sign; add sign_custom function (Jonas Nick)
442cee5bafbd7419acadf203ca11569e371f1f85 schnorrsig: add algolen argument to nonce_function_hardened (Jonas Nick)
df3bfa12c3b728241d3e61d13f8c976719a3de41 schnorrsig: clarify result of calling nonce_function_bip340 without data (Jonas Nick)
99e8614812bf23798a48c53649957e26e5b12f4a README: mention schnorrsig module (Jonas Nick)
Pull request description:
This is a work in progress because I wanted to put this up for discussion before writing tests. It addresses the TODOs that didn't make it in the schnorrsig PR and changes the APIs of `schnorrsig_sign`, `schnorrsig_verify` and `hardened_nonce_function`.
- Ideally, the new `aux_rand32` argument for `sign` would be const, but didn't find a solution I was happy with.
- Support for variable length message signing and verification supports the [suggested BIP amendment](https://github.com/sipa/bips/issues/207#issuecomment-673681901) for such messages.
- ~~`sign_custom` with its opaque config object allows adding more arguments later without having to change the API again. Perhaps there are other sensible customization options, but I'm thinking of [sign-to-contract/covert-channel](https://github.com/bitcoin-core/secp256k1/pull/590) in particular. It would require adding the fields `unsigned char *s2c_data32` and `secp256k1_s2c_opening *s2c_opening` to the config struct. The former is the data to commit to and the latter is written to by `sign_custom`.~~ (EDIT: see below)
ACKs for top commit:
ariard:
utACK 5f6ceaf
LLFourn:
utACK 5f6ceafcfa46a69e901bed87e2c5f323b03b1e8c
Tree-SHA512: cf1716dddf4f29bcacf542ed22622a817d0ec9c20d0592333cb7e6105902c77d819952e776b9407fae1333cbd03d63fded492d3a5df7769dcc5b450d91bb4761
If `secp256k1_ecdsa_sign` fails, the signature which is then loaded by
`secp256k1_ecdsa_signature_load` is garbage. Exit early with an error
when this occurs.
Function `test_inverse_scalar` contains:
(var ? secp256k1_scalar_inverse_var : secp256k1_scalar_inverse_var)(&l, x); /* l = 1/x */
The two sides of the condition are the same function. This seems to be
an error, as there also exists a non-var function, named
`secp256k1_scalar_inverse`.
Make `test_inverse_scalar` use this other function when `var` is false.
This issue was found using clang's static analyzer, which reported a
"Logic error: Identical expressions in conditional expression" (with
checker `alpha.core.IdenticalExpr`).
Varlen message support for the default sign function comes from recommending
tagged_sha256. sign_custom on the other hand gets the ability to directly sign
message of any length. This also implies signing and verification support for
the empty message (NULL) with msglen 0.
Tests for variable lengths follow in a later commit.
This makes the default sign function easier to use while allowing more granular
control through sign_custom.
Tests for sign_custom follow in a later commit.
9570f674cc729cafcba65f4cce03552d9a6108f4 Avoid passing out-of-bound pointers to 0-size memcpy (Pieter Wuille)
Pull request description:
Doing so could be considered UB in a pedantic interpretation of the standard. Avoid it.
Closes#876.
ACKs for top commit:
practicalswift:
cr ACK 9570f674cc729cafcba65f4cce03552d9a6108f4: patch looks correct
real-or-random:
ACK 9570f674cc729cafcba65f4cce03552d9a6108f4
Tree-SHA512: f991462d72e39f14e609021b8427c2e6756009bc8cd21efca2da46ec9410250725a4fed662df20fcdcfd10a4dc59038f13e8c166362b2eadde4366586b9ca72b
14c9739a1fb485bb56dbe3447132a37bcbef4e22 tests: Improve secp256k1_ge_set_all_gej_var for some infinity inputs (Tim Ruffing)
4a19668c37bc77d0165f4a1c0e626e321e9c4a09 tests: Test secp256k1_ge_set_all_gej_var for all infinity inputs (Tim Ruffing)
45b6468d7e3ed9849ed474c71e9a9479de1a77db Have secp256k1_ge_set_all_gej_var initialize all fields. Previous behaviour would not initialize r->y values in the case where infinity is passed in. Furthermore, the previous behaviour wouldn't initialize anything in the case where all inputs were infinity. (Russell O'Connor)
31c0f6de413e521731ad0e63424431b3dd49cec8 Have secp256k1_gej_double_var initialize all fields. Previous behaviour would not initialize r->x and r->y values in the case where infinity is passed in. (Russell O'Connor)
dd6c3de322740a3054cf6a1994a38dc8f201b473 Have secp256k1_ge_set_gej_var initialize all fields. Previous behaviour would not initialize r->x and r->y values in the case where infinity is passed in. (Russell O'Connor)
Pull request description:
Previous behaviour would not initialize `r->x` and `r->y` values in the case where infinity is passed in.
ACKs for top commit:
gmaxwell:
ACK 14c9739a1fb485bb56dbe3447132a37bcbef4e22
sipa:
utACK 14c9739a1fb485bb56dbe3447132a37bcbef4e22
real-or-random:
ACK 14c9739a1fb485bb56dbe3447132a37bcbef4e22
Tree-SHA512: 2e779b767f02e348af4bbc62aa9871c3d1d29e61a6c643c879c49f2de27556a3588850acd2f7c7483790677597d01064025e14befdbf29e783f57996fe4430f9
Previous behaviour would not initialize r->y values in the case where infinity is passed in.
Furthermore, the previous behaviour wouldn't initialize anything in the case where all inputs were infinity.
This makes a difference with mingw builds on Wine, where the subsequent
fread() may abort early in the default text mode.
The Microsoft C docs say:
"In text mode, CTRL+Z is interpreted as an EOF character on input."
be0609fd54af95a15b76cea150e6907d581318dd Add unit tests for edge cases with delta=1/2 variant of divsteps (Pieter Wuille)
cd393ce2283e0e7234ea39a15c4931715f4dde1e Optimization: only do 59 hddivsteps per iteration instead of 62 (Pieter Wuille)
277b224b6aba942efbac4a6aae1054035a68d8dd Use modified divsteps with initial delta=1/2 for constant-time (Pieter Wuille)
376ca366db0469f39b93af0af762090986ea75f2 Fix typo in explanation (Pieter Wuille)
Pull request description:
This updates the divsteps-based modular inverse code to use the modified version which starts with delta=1/2. For variable time, the delta=1 variant is still used as it appears to be faster.
See https://github.com/sipa/safegcd-bounds/tree/master/coq and https://medium.com/blockstream/a-formal-proof-of-safegcd-bounds-695e1735a348 for a proof of correctness of this variant.
TODO:
* [x] Update unit tests to include edge cases specific to this variant
I'm still running the Coq proof verification for the 590 bound in non-native mode. It's unclear how long this will take.
ACKs for top commit:
gmaxwell:
ACK be0609fd54af95a15b76cea150e6907d581318dd
sanket1729:
crACK be0609fd54af95a15b76cea150e6907d581318dd
real-or-random:
ACK be0609fd54af95a15b76cea150e6907d581318dd careful code review and some testing
Tree-SHA512: 2f8f400ba3ac8dbd08622d564c3b3e5ff30768bd0eb559f2c4279c6c813e17cdde71b1c16f05742c5657b5238b4d592b48306f9f47d7dbdb57907e58dd99b47a
Before this commit, gen_context.c both included libsecp256k1-config.h
and basic-config.h: The former only to obtain ECMULT_GEN_PREC_BITS
and the latter to obtain a basic working configuration to be able to
use the library.
This was inelegant and confusing: It meant that basic-config.h needs
to #undef all the macros defined in libsecp256k1-config.h. Moreover,
it meant that basic-config.h cannot define ECMULT_GEN_PREC_BITS,
essentially making this file specific for use in gen_context.c.
After this commit, gen_context.c include only libsecp256k1-config.h.
basic-config.h is not necessary anymore for the modules used in
gen_context.c because 79f1f7a made the preprocessor detect all the
relevant config options.
On the way, we remove an unused #define in basic-config.h.
Instead of using eta=-delta, use zeta=-(delta+1/2) to represent
delta. This variant only needs at most 590 iterations for 256-bit
inputs rather than 724 (by convex hull bounds analysis).